def _(values: List[str], value: str, key: KeyType, signal: Callable) \ -> QComboBox: combo = QComboBox() combo.addItems(values) combo.setCurrentText(value) combo.currentTextChanged.connect(lambda text: signal.emit(key, text)) return combo
def _(value: str, values: List[str], parent: QGroupBox, key: KeyType, signal: Callable) -> QComboBox: combo = QComboBox() combo.addItems(values) combo.setCurrentText(value) parent.layout().addWidget(combo) combo.currentTextChanged.connect(lambda text: signal.emit(key, text)) return combo
class UserPrefUI(QWidget): def __init__(self, prefs, parent): super(UserPrefUI, self).__init__() self.title = 'User Preferences' self.setLayout(QVBoxLayout(self)) self.parent = parent self.prefs = prefs # Init logger self.logger = Logger('userPrefsUI', 'UI : User Preferences') # Set up container container = QWidget() container.setLayout(QVBoxLayout()) # Set up scroll area scrollArea = QScrollArea() scrollArea.setWidget(container) scrollArea.setWidgetResizable(True) self.layout().addWidget(scrollArea) # Permanent controls self._saveButton = QPushButton('Save', self) self._saveButton.clicked.connect(self.__save) self._startMaximized = QCheckBox('Start Maximized', self) self._allowDuplicatePins = QCheckBox('Allow Duplicate Output Pins', self) self._enableOBA = QCheckBox('OnBoard Air', self) self._enableLighting = QCheckBox('Lighting', self) self._enableTracControl = QCheckBox('Traction Control', self) self._enableCamViewer = QCheckBox('Camera Viewer', self) self._enableGyro = QCheckBox('Inclinometer', self) self._panelLabel = QLabel( '<html><center>Enable Modules:<br>\ <em>Restart TacOS for changes to take effect.</em></center></html>', self) self._i2cBus = QComboBox(self) self._i2cBus.addItems(Config.busList) self._i2cBusLabel = QLabel('I2C Bus', self) self._i2cAddress = QLineEdit('I2C Address', self) self._i2cLabel = QLabel( '<html><center>I2C Parameters:<br>\ <em>Restart TacOS for changes to take effect.</em></center></html>', self) self._i2cDebug = QCheckBox('I2C Debug Mode', self) self._i2cDebugLabel = QLabel( '<html><center>I2C Debug Mode:<br>\ <em>Disables all I2C comms.<br>\ Restart TacOS for changes to take effect.</em></center></html>', self) self._debugLogging = QCheckBox('Enable Debug Logs', self) self._restartButton = QPushButton('Restart TacOS', self) self._restartButton.clicked.connect(self.__restart) # Set initial values for control in [ 'startMaximized', 'allowDuplicatePins', 'enableOBA', 'enableLighting', 'enableTracControl', 'enableCamViewer', 'enableGyro', 'i2cDebug', 'debugLogging' ]: if control in prefs.keys(): exec('self._%s.setChecked(prefs["%s"])' % (control, control)) else: if control in [ 'enableOBA', 'enableLighting', 'enableTracControl', 'enableCamViewer', 'enableGyro' ]: exec('self._%s.setChecked(True)' % control) else: exec('self._%s.setChecked(False)' % control) if 'i2cAddress' in prefs.keys(): self._i2cAddress.setText(prefs['i2cAddress']) else: self._i2cAddress.setText('0x20') if 'i2cBus' in prefs.keys(): self._i2cBus.setCurrentText(str(prefs['i2cBus'])) else: self._i2cBus.setCurrentIndex(0) layoutList = [[ '_startMaximized', '_allowDuplicatePins', '_debugLogging' ], ['_panelLabel'], ['_enableOBA', '_enableLighting', '_enableTracControl'], ['_enableCamViewer', '_enableGyro'], ['_i2cLabel'], ['_i2cBusLabel', '_i2cBus', '_i2cAddress'], ['_i2cDebugLabel'], ['_i2cDebug'], ['_saveButton', '_restartButton']] for i in layoutList: panel = QWidget() panel.setLayout(QHBoxLayout(panel)) panel.layout().setSpacing(20) panel.layout().setAlignment(Qt.AlignCenter) for c in i: panel.layout().addWidget(eval('self.%s' % c)) container.layout().addWidget(panel) def refresh(self): self.__init__(self.window().prefs, self.parent) def __save(self): self.parent.prefs = self.__getPrefs() self.parent.savePrefs() def __restart(self): os.system("sudo sh /home/pi/TacOS/launcher.sh") sys.exit() def __getPrefs(self): _updates = { 'startMaximized': self._startMaximized.isChecked(), 'allowDuplicatePins': self._allowDuplicatePins.isChecked(), 'enableOBA': self._enableOBA.isChecked(), 'enableLighting': self._enableLighting.isChecked(), 'enableTracControl': self._enableTracControl.isChecked(), 'enableCamViewer': self._enableCamViewer.isChecked(), 'enableGyro': self._enableGyro.isChecked(), 'i2cBus': self._i2cBus.currentText(), 'i2cAddress': hex(int(self._i2cAddress.text(), 16)), 'i2cDebug': self._i2cDebug.isChecked(), 'debugLogging': self._debugLogging.isChecked() } for _key in _updates.keys(): self.prefs[_key] = _updates[_key] return self.prefs
class FileLoader(QWidget): activated = pyqtSignal() file_loaded = pyqtSignal() def __init__(self): super().__init__() self.recent_paths = [] self.file_combo = QComboBox() self.file_combo.setMinimumWidth(80) self.file_combo.activated.connect(self._activate) self.browse_btn = QPushButton("...") icon = self.style().standardIcon(QStyle.SP_DirOpenIcon) self.browse_btn.setIcon(icon) self.browse_btn.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Fixed) self.browse_btn.clicked.connect(self.browse) self.load_btn = QPushButton("") icon = self.style().standardIcon(QStyle.SP_BrowserReload) self.load_btn.setIcon(icon) self.load_btn.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Fixed) self.load_btn.setAutoDefault(True) self.load_btn.clicked.connect(self.file_loaded) def browse(self): start_file = self.last_path() or os.path.expanduser("~/") formats = ["Text files (*.txt)", "All files (*)"] file_name, _ = QFileDialog.getOpenFileName(None, "Open...", start_file, ";;".join(formats), formats[0]) if not file_name: return self.add_path(file_name) self._activate() def _activate(self): self.activated.emit() self.file_loaded.emit() def set_current_file(self, path: str): if path: self.add_path(path) self.file_combo.setCurrentText(path) else: self.file_combo.setCurrentText("(none)") def get_current_file(self) -> Optional[RecentPath]: index = self.file_combo.currentIndex() if index >= len(self.recent_paths) or index < 0: return None path = self.recent_paths[index] return path if isinstance(path, RecentPath) else None def add_path(self, filename: str): recent = RecentPath.create(filename, []) if recent in self.recent_paths: self.recent_paths.remove(recent) self.recent_paths.insert(0, recent) self.set_file_list() def set_file_list(self): self.file_combo.clear() for i, recent in enumerate(self.recent_paths): self.file_combo.addItem(recent.basename) self.file_combo.model().item(i).setToolTip(recent.abspath) if not os.path.exists(recent.abspath): self.file_combo.setItemData(i, QBrush(Qt.red), Qt.TextColorRole) self.file_combo.addItem(_DEFAULT_NONE) def last_path(self) -> Optional[str]: return self.recent_paths[0].abspath if self.recent_paths else None
def _(combo: QComboBox, value: str): combo.setCurrentText(value)
class OWSql(OWBaseSql): name = "SQL Table" id = "orange.widgets.data.sql" description = "Load dataset from SQL." icon = "icons/SQLTable.svg" priority = 30 category = "Data" keywords = ["load"] class Outputs: data = Output("Data", Table, doc="Attribute-valued dataset read from the input file.") settings_version = 2 buttons_area_orientation = None selected_backend = Setting(None) table = Setting(None) sql = Setting("") guess_values = Setting(True) download = Setting(False) materialize = Setting(False) materialize_table_name = Setting("") class Information(OWBaseSql.Information): data_sampled = Msg("Data description was generated from a sample.") class Warning(OWBaseSql.Warning): missing_extension = Msg("Database is missing extensions: {}") class Error(OWBaseSql.Error): no_backends = Msg("Please install a backend to use this widget.") def __init__(self): # Lint self.backends = None self.backendcombo = None self.tables = None self.tablecombo = None self.sqltext = None self.custom_sql = None self.downloadcb = None super().__init__() def _setup_gui(self): super()._setup_gui() self._add_backend_controls() self._add_tables_controls() def _add_backend_controls(self): box = self.serverbox self.backends = BackendModel(Backend.available_backends()) self.backendcombo = QComboBox(box) if self.backends: self.backendcombo.setModel(self.backends) names = [backend.display_name for backend in self.backends] if self.selected_backend and self.selected_backend in names: self.backendcombo.setCurrentText(self.selected_backend) else: self.Error.no_backends() box.setEnabled(False) self.backendcombo.currentTextChanged.connect(self.__backend_changed) box.layout().insertWidget(0, self.backendcombo) def __backend_changed(self): backend = self.get_backend() self.selected_backend = backend.display_name if backend else None def _add_tables_controls(self): vbox = gui.vBox(self.controlArea, "Tables") box = gui.vBox(vbox) self.tables = TableModel() self.tablecombo = QComboBox( minimumContentsLength=35, sizeAdjustPolicy=QComboBox.AdjustToMinimumContentsLengthWithIcon) self.tablecombo.setModel(self.tables) self.tablecombo.setToolTip('table') self.tablecombo.activated[int].connect(self.select_table) box.layout().addWidget(self.tablecombo) self.custom_sql = gui.vBox(box) self.custom_sql.setVisible(False) self.sqltext = QTextEdit(self.custom_sql) self.sqltext.setPlainText(self.sql) self.custom_sql.layout().addWidget(self.sqltext) mt = gui.hBox(self.custom_sql) cb = gui.checkBox(mt, self, 'materialize', 'Materialize to table ') cb.setToolTip('Save results of the query in a table') le = gui.lineEdit(mt, self, 'materialize_table_name') le.setToolTip('Save results of the query in a table') gui.button(self.custom_sql, self, 'Execute', callback=self.open_table) box.layout().addWidget(self.custom_sql) gui.checkBox(box, self, "guess_values", "Auto-discover categorical variables", callback=self.open_table) self.downloadcb = gui.checkBox(box, self, "download", "Download data to local memory", callback=self.open_table) def highlight_error(self, text=""): err = ['', 'QLineEdit {border: 2px solid red;}'] self.servertext.setStyleSheet(err['server' in text or 'host' in text]) self.usernametext.setStyleSheet(err['role' in text]) self.databasetext.setStyleSheet(err['database' in text]) def get_backend(self): if self.backendcombo.currentIndex() < 0: return None return self.backends[self.backendcombo.currentIndex()] def on_connection_success(self): if getattr(self.backend, 'missing_extension', False): self.Warning.missing_extension(", ".join( self.backend.missing_extension)) self.download = True self.downloadcb.setEnabled(False) if not is_postgres(self.backend): self.download = True self.downloadcb.setEnabled(False) super().on_connection_success() self.refresh_tables() self.select_table() def on_connection_error(self, err): super().on_connection_error(err) self.highlight_error(str(err).split("\n")[0]) def clear(self): super().clear() self.Warning.missing_extension.clear() self.downloadcb.setEnabled(True) self.highlight_error() self.tablecombo.clear() self.tablecombo.repaint() def refresh_tables(self): self.tables.clear() if self.backend is None: self.data_desc_table = None return self.tables.append("Select a table") self.tables.append("Custom SQL") self.tables.extend(self.backend.list_tables(self.schema)) index = self.tablecombo.findText(str(self.table)) self.tablecombo.setCurrentIndex(index if index != -1 else 0) self.tablecombo.repaint() # Called on tablecombo selection change: def select_table(self): curIdx = self.tablecombo.currentIndex() if self.tablecombo.itemText(curIdx) != "Custom SQL": self.custom_sql.setVisible(False) return self.open_table() else: self.custom_sql.setVisible(True) self.data_desc_table = None self.database_desc["Table"] = "(None)" self.table = None if len(str(self.sql)) > 14: return self.open_table() return None def get_table(self): curIdx = self.tablecombo.currentIndex() if curIdx <= 0: if self.database_desc: self.database_desc["Table"] = "(None)" self.data_desc_table = None return None if self.tablecombo.itemText(curIdx) != "Custom SQL": self.table = self.tables[self.tablecombo.currentIndex()] self.database_desc["Table"] = self.table if "Query" in self.database_desc: del self.database_desc["Query"] what = self.table else: what = self.sql = self.sqltext.toPlainText() self.table = "Custom SQL" if self.materialize: if not self.materialize_table_name: self.Error.connection( "Specify a table name to materialize the query") return None try: with self.backend.execute_sql_query( "DROP TABLE IF EXISTS " + self.materialize_table_name): pass with self.backend.execute_sql_query( "CREATE TABLE " + self.materialize_table_name + " AS " + self.sql): pass with self.backend.execute_sql_query( "ANALYZE " + self.materialize_table_name): pass except BackendError as ex: self.Error.connection(str(ex)) return None try: table = SqlTable(dict(host=self.host, port=self.port, database=self.database, user=self.username, password=self.password), what, backend=type(self.backend), inspect_values=False) except BackendError as ex: self.Error.connection(str(ex)) return None self.Error.connection.clear() sample = False if table.approx_len() > LARGE_TABLE and self.guess_values: confirm = QMessageBox(self) confirm.setIcon(QMessageBox.Warning) confirm.setText("Attribute discovery might take " "a long time on large tables.\n" "Do you want to auto discover attributes?") confirm.addButton("Yes", QMessageBox.YesRole) no_button = confirm.addButton("No", QMessageBox.NoRole) if is_postgres(self.backend): sample_button = confirm.addButton("Yes, on a sample", QMessageBox.YesRole) confirm.exec() if confirm.clickedButton() == no_button: self.guess_values = False elif is_postgres(self.backend) and \ confirm.clickedButton() == sample_button: sample = True self.Information.clear() if self.guess_values: QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) if sample: s = table.sample_time(1) domain = s.get_domain(inspect_values=True) self.Information.data_sampled() else: domain = table.get_domain(inspect_values=True) QApplication.restoreOverrideCursor() table.domain = domain if self.download: if table.approx_len() > AUTO_DL_LIMIT: if is_postgres(self.backend): confirm = QMessageBox(self) confirm.setIcon(QMessageBox.Warning) confirm.setText("Data appears to be big. Do you really " "want to download it to local memory?") if table.approx_len() <= MAX_DL_LIMIT: confirm.addButton("Yes", QMessageBox.YesRole) no_button = confirm.addButton("No", QMessageBox.NoRole) sample_button = confirm.addButton("Yes, a sample", QMessageBox.YesRole) confirm.exec() if confirm.clickedButton() == no_button: return None elif confirm.clickedButton() == sample_button: table = table.sample_percentage( AUTO_DL_LIMIT / table.approx_len() * 100) else: if table.approx_len() > MAX_DL_LIMIT: QMessageBox.warning(self, 'Warning', "Data is too big to download.\n") return None else: confirm = QMessageBox.question( self, 'Question', "Data appears to be big. Do you really " "want to download it to local memory?", QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if confirm == QMessageBox.No: return None table.download_data(MAX_DL_LIMIT) table = Table(table) return table @classmethod def migrate_settings(cls, settings, version): if version < 2: # Until Orange version 3.4.4 username and password had been stored # in Settings. cm = cls._credential_manager(settings["host"], settings["port"]) cm.username = settings["username"] cm.password = settings["password"]
class NormalizeEditor(ScBaseEditor): DEFAULT_GROUP_BY = False DEFAULT_GROUP_VAR = None DEFAULT_METHOD = Normalize.CPM def __init__(self, parent=None, master=None, **kwargs): super().__init__(parent, **kwargs) self._group_var = self.DEFAULT_GROUP_VAR self._master = master self._master.input_data_changed.connect(self._set_model) self.setLayout(QVBoxLayout()) form = QFormLayout() cpm_b = QRadioButton("Counts per million", checked=True) med_b = QRadioButton("Median") self.group = QButtonGroup() self.group.buttonClicked.connect(self._on_button_clicked) for i, button in enumerate([cpm_b, med_b]): index = index_to_enum(Normalize.Method, i).value self.group.addButton(button, index - 1) form.addRow(button) self.group_by_check = QCheckBox("Cell Groups: ", enabled=self.DEFAULT_GROUP_BY) self.group_by_check.clicked.connect(self.edited) self.group_by_combo = QComboBox(enabled=self.DEFAULT_GROUP_BY) self.group_by_model = DomainModel(order=(DomainModel.METAS, DomainModel.CLASSES), valid_types=DiscreteVariable, alphabetical=True) self.group_by_combo.setModel(self.group_by_model) self.group_by_combo.currentIndexChanged.connect(self.changed) self.group_by_combo.activated.connect(self.edited) form.addRow(self.group_by_check, self.group_by_combo) self.layout().addLayout(form) self._set_model() def _set_model(self): data = self._master.data self.group_by_model.set_domain(data and data.domain) enable = bool(self.group_by_model) self.group_by_check.setChecked(False) self.group_by_check.setEnabled(enable) self.group_by_combo.setEnabled(enable) if self.group_by_model: self.group_by_combo.setCurrentIndex(0) if self._group_var and self._group_var in data.domain: index = self.group_by_model.indexOf(self._group_var) self.group_by_combo.setCurrentIndex(index) else: self.group_by_combo.setCurrentText(None) def _on_button_clicked(self): self.changed.emit() self.edited.emit() def setParameters(self, params): method = params.get("method", self.DEFAULT_METHOD) index = enum_to_index(Normalize.Method, method) self.group.buttons()[index].setChecked(True) self._group_var = params.get("group_var", self.DEFAULT_GROUP_VAR) group = bool(self._group_var and self.group_by_model) if group: index = self.group_by_model.indexOf(self._group_var) self.group_by_combo.setCurrentIndex(index) group_by = params.get("group_by", self.DEFAULT_GROUP_BY) self.group_by_check.setChecked(group_by and group) def parameters(self): index = self.group_by_combo.currentIndex() group_var = self.group_by_model[index] if index > -1 else None group_by = self.group_by_check.isChecked() method = index_to_enum(Normalize.Method, self.group.checkedId()) return {"group_var": group_var, "group_by": group_by, "method": method} @staticmethod def createinstance(params): group_var = params.get("group_var") group_by = params.get("group_by", NormalizeEditor.DEFAULT_GROUP_BY) method = params.get("method", NormalizeEditor.DEFAULT_METHOD) return NormalizeGroups(group_var, method) \ if group_by and group_var else NormalizeSamples(method) def __repr__(self): method = self.group.button(self.group.checkedId()).text() index = self.group_by_combo.currentIndex() group_var = self.group_by_model[index] if index > -1 else None group_by = self.group_by_check.isChecked() group_text = ", Grouped by: {}".format(group_var) if group_by else "" return "Method: {}".format(method) + group_text