def _make_expression_completer(owner, data_type): model = QStringListModel() comp = QCompleter(owner) comp.setCaseSensitivity(Qt.CaseSensitive) if isinstance(data_type, str): data_type = uavcan.TYPENAMES[data_type] # TODO: implement proper completion, requires Python lexer # TODO: IPython/Jupyter solves the same task splendidly, might make sense to take a closer look at their code def make_suggestions(t): """Builds a flat list of fields in a given data type""" if t.category == t.CATEGORY_COMPOUND: out = [] for a in t.fields + t.constants: if (a.type.category != a.type.CATEGORY_COMPOUND) and \ (a.type.category != a.type.CATEGORY_VOID) and \ (a.type.category != a.type.CATEGORY_ARRAY or a.type.value_type.category == a.type.value_type.CATEGORY_PRIMITIVE): out.append(a.name) out += [(a.name + x) for x in make_suggestions(a.type)] return [('.' + x) for x in out] elif t.category == t.CATEGORY_ARRAY: base = '[0]' if t.value_type.category == t.CATEGORY_COMPOUND: return [(base + x) for x in make_suggestions(t.value_type)] else: return [base] return [] suggestions = [(EXPRESSION_VARIABLE_FOR_MESSAGE + x) for x in make_suggestions(data_type)] model.setStringList(suggestions) comp.setModel(model) return comp
class MainWindow(QMainWindow): def __init__(self, parent=None): super(MainWindow, self).__init__(parent) self.createMenu() self.completingTextEdit = TextEdit() self.completer = QCompleter(self) self.completer.setModel(self.modelFromFile(':/resources/wordlist.txt')) self.completer.setModelSorting(QCompleter.CaseInsensitivelySortedModel) self.completer.setCaseSensitivity(Qt.CaseInsensitive) self.completer.setWrapAround(False) self.completingTextEdit.setCompleter(self.completer) self.setCentralWidget(self.completingTextEdit) self.resize(500, 300) self.setWindowTitle("Completer") def createMenu(self): exitAction = QAction("Exit", self) aboutAct = QAction("About", self) aboutQtAct = QAction("About Qt", self) exitAction.triggered.connect(QApplication.instance().quit) aboutAct.triggered.connect(self.about) aboutQtAct.triggered.connect(QApplication.instance().aboutQt) fileMenu = self.menuBar().addMenu("File") fileMenu.addAction(exitAction) helpMenu = self.menuBar().addMenu("About") helpMenu.addAction(aboutAct) helpMenu.addAction(aboutQtAct) def modelFromFile(self, fileName): f = QFile(fileName) if not f.open(QFile.ReadOnly): return QStringListModel(self.completer) QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) words = [] while not f.atEnd(): line = f.readLine().trimmed() if line.length() != 0: try: line = str(line, encoding='ascii') except TypeError: line = str(line) words.append(line) QApplication.restoreOverrideCursor() return QStringListModel(words, self.completer) def about(self): QMessageBox.about(self, "About", "This example demonstrates the different features of the " "QCompleter class.")
class Completer(QGraphicsProxyWidget, object): ''' Class for handling text autocompletion in the SDL scene ''' def __init__(self, parent): ''' Create an autocompletion list popup ''' widget = QListWidget() super(Completer, self).__init__(parent) self.setWidget(widget) self.string_list = QStringListModel() self._completer = QCompleter() self.parent = parent self._completer.setCaseSensitivity(Qt.CaseInsensitive) # For some reason the default minimum size is (61,61) # Set it to 0 so that the size of the box is not taken # into account when it is hidden. self.setMinimumSize(0, 0) self.prepareGeometryChange() self.resize(0, 0) self.hide() def set_completer_list(self): ''' Set list of items for the autocompleter popup ''' compl = [item.replace('-', '_') for item in self.parent.parentItem().completion_list] self.string_list.setStringList(compl) self._completer.setModel(self.string_list) def set_completion_prefix(self, completion_prefix): ''' Set the current completion prefix (user-entered text) and set the corresponding list of words in the popup widget ''' self._completer.setCompletionPrefix(completion_prefix) self.widget().clear() count = self._completer.completionCount() for i in xrange(count): self._completer.setCurrentRow(i) self.widget().addItem(self._completer.currentCompletion()) self.prepareGeometryChange() if count: self.resize(self.widget().sizeHintForColumn(0) + 40, 70) else: self.resize(0, 0) return count # pylint: disable=C0103 def keyPressEvent(self, e): super(Completer, self).keyPressEvent(e) if e.key() == Qt.Key_Escape: self.parentItem().setFocus() # Consume the event so that it is not repeated at EditableText level e.accept() # pylint: disable=C0103 def focusOutEvent(self, event): ''' When the user leaves the popup, return focus to parent ''' super(Completer, self).focusOutEvent(event) self.hide() self.resize(0, 0) self.parentItem().setFocus()
def return_tag_completer_TextEdit(parent=None): ns = gallerydb.TagDB.get_all_ns() for t in gallerydb.TagDB.get_all_tags(): ns.append(t) TextEditCompleter = CompleterTextEdit() comp = QCompleter(ns, parent) comp.setCaseSensitivity(Qt.CaseInsensitive) TextEditCompleter.setCompleter(comp) return TextEditCompleter
def __init__(self, parent, completion_model=None): super(SearchBarComboBox, self).__init__(parent) self.setFont(get_monospace_font()) self.setToolTip('Enter the search pattern here') completer = QCompleter(self) completer.setCaseSensitivity(Qt.CaseSensitive) if completion_model is not None: completer.setModel(completion_model) else: completer.setModel(self.model()) self.setCompleter(completer)
def __init__(self,expdat): super(DBAnnotateSave, self).__init__() print("DBAnnotateSave") uic.loadUi(os.path.join(hs.heatsequerdir,'ui/manualdata.py'), self) self.bplus.clicked.connect(self.plus) self.bminus.clicked.connect(self.minus) self.bontoinput.returnPressed.connect(self.plus) self.bstudyinfo.clicked.connect(self.studyinfo) self.bisa.toggled.connect(self.radiotoggle) self.bdiffpres.toggled.connect(self.radiotoggle) self.bisatype.currentIndexChanged.connect(self.isatypechanged) self.bhistory.clicked.connect(self.history) self.cexp=expdat self.lnumbact.setText(str(len(expdat.selectedseqs))) completer = QCompleter() self.bontoinput.setCompleter(completer) scdb=hs.scdb self.scdb=scdb self.dataid=hs.supercooldb.finddataid(scdb,datamd5=self.cexp.datamd5,mapmd5=self.cexp.mapmd5) model = QStringListModel() completer.setModel(model) # completer.setCompletionMode(QCompleter.InlineCompletion) completer.maxVisibleItems=10 completer.setCaseSensitivity(Qt.CaseInsensitive) # make the completer selection also erase the text edit completer.activated.connect(self.cleartext,type=Qt.QueuedConnection) # in qt5 should work with middle complete as well... # completer.setFilterMode(Qt.MatchContains) if not hs.scdb.ontologyfromid: hs.scdb=hs.supercooldb.loaddbonto(hs.scdb) self.ontology=hs.scdb.ontology self.ontologyfromid=hs.scdb.ontologyfromid nlist=list(self.ontology.keys()) # nlist=sorted(nlist) nlist=sorted(nlist, key=lambda s: s.lower()) print("sorted ontology") model.setStringList(nlist) self.setWindowTitle(self.cexp.studyname) try: tt=hs.lastdatamd5 except: hs.lastdatamd5='' if self.cexp.datamd5==hs.lastdatamd5: self.fillfromcuration(hs.lastcurations[-1],onlyall=True) self.prefillinfo() self.bontoinput.setFocus()
def createEditor(self, manager, property, parent): type = manager.propertyType(property) if (type == VariantPropertyManager.filePathTypeId()): editor = FileEdit(parent) editor.setFilePath(manager.value(property)) editor.setFilter(manager.attributeValue(property, "filter")) self.mCreatedEditors[property].append(editor) self.mEditorToProperty[editor] = property editor.filePathChanged.connect(self.slotSetValue) editor.destroyed.connect(self.slotEditorDestroyed) return editor editor = super().createEditor(manager, property, parent) if (type == QVariant.String): # Add support for "suggestions" attribute that adds a QCompleter to the QLineEdit suggestions = manager.attributeValue(property, "suggestions") if suggestions and len(suggestions)>0: lineEdit = editor if lineEdit: completer = QCompleter(suggestions, lineEdit) completer.setCaseSensitivity(Qt.CaseInsensitive) lineEdit.setCompleter(completer) return editor
def __init__(self): super(GeneralPreferences, self).__init__() grid = QGridLayout(self) grid.setSpacing(20) grid.setColumnStretch(1, 10) # directory auto completer completer = QCompleter(self) dirs = QDirModel(self) dirs.setFilter(QDir.AllDirs | QDir.NoDotAndDotDot) completer.setModel(dirs) completer.setCaseSensitivity(Qt.CaseInsensitive) completer.setCompletionMode(QCompleter.PopupCompletion) label = QLabel( "<b>Ingresá el directorio donde descargar los videos...</b>") label.setTextFormat(Qt.RichText) grid.addWidget(label, 0, 0, 1, 2) grid.addWidget(QLabel("Descargar en:"), 1, 0, 2, 1) prv = config.get('downloaddir', '') self.downloaddir_entry = QLineEdit(prv) self.downloaddir_entry.setCompleter(completer) self.downloaddir_entry.setPlaceholderText('Ingresá un directorio') grid.addWidget(self.downloaddir_entry, 1, 1, 2, 2) self.downloaddir_buttn = QPushButton("Elegir un directorio") self.downloaddir_buttn.clicked.connect(self._choose_dir) grid.addWidget(self.downloaddir_buttn, 2, 1, 3, 2) self.autoreload_checkbox = QCheckBox( "Recargar automáticamente la lista de episodios al iniciar") self.autoreload_checkbox.setToolTip( "Cada vez que arranca el programa refrescar la lista de episodios." ) prv = config.get('autorefresh', False) self.autoreload_checkbox.setChecked(prv) grid.addWidget(self.autoreload_checkbox, 3, 0, 4, 2) self.shownotifs_checkbox = QCheckBox( "Mostrar una notificación cuando termina cada descarga") self.shownotifs_checkbox.setToolTip( "Hacer que el escritorio muestre una notificación cada vez que una descarga " "se complete.") prv = config.get('notification', True) self.shownotifs_checkbox.setChecked(prv) grid.addWidget(self.shownotifs_checkbox, 4, 0, 5, 2) self.cleanfnames_checkbox = QCheckBox( "Limpiar nombres para que se pueda guardar en cualquier lado") self.cleanfnames_checkbox.setToolTip( "Convertir caracteres extraños en títulos para que el archivo se pueda grabar en " "cualquier disco o pendrive.") prv = config.get('clean-filenames', False) self.cleanfnames_checkbox.setChecked(prv) grid.addWidget(self.cleanfnames_checkbox, 5, 0, 6, 2) lq = QLabel( "<b>Ingrese la Calidad de Video Preferida para las Descargas:</b>") lq.setTextFormat(Qt.RichText) grid.addWidget(lq, 8, 0, 7, 2) lqd = QLabel("* En caso de no existir se eligirá la más conveniente.") lqd.setTextFormat(Qt.RichText) grid.addWidget(lqd, 9, 0, 8, 2) self.select_quality = QComboBox() self.select_quality.setGeometry(QRect()) self.select_quality.setObjectName("Calidad de Video Preferida") self.select_quality.addItem("1080p") # HD self.select_quality.addItem("720p") # ALTA self.select_quality.addItem("480p") # MEDIA self.select_quality.addItem("360p") # BAJA self.select_quality.addItem("240p") # MALA self.select_quality.activated[str].connect(self.selected) prv = config.get('quality', '720p') self.select_quality.setCurrentText(prv) grid.addWidget(self.select_quality, 10, 0, 9, 2)
class PestaniaProducto(): def __init__(self, winPrincipal): self.winPrincipal = winPrincipal self.producto = Producto() self.proveedor = Proveedor() self.marca = Marca() self.rubro = Rubro() self.estado = "" self.conexionProducto = conexionProducto() self.configInit() def configInit(self): #Configurando botones self.winPrincipal.btnAgregar_p.clicked.connect(self.onClickAgregar_p) self.winPrincipal.btnGuardar_p.clicked.connect(self.onClickGuardar_p) self.winPrincipal.btnBorrar_p.clicked.connect(self.onClickBorrar_p) self.winPrincipal.btnModificar_p.clicked.connect(self.onClickModificar_p) self.winPrincipal.btnRubro_p.clicked.connect(windowRubro) self.winPrincipal.btnMarca_p.clicked.connect(windowMarca) self.cargarTabla() self.winPrincipal.tvProductos_p.setMouseTracking(True) self.winPrincipal.tvProductos_p.setSelectionBehavior(QAbstractItemView.SelectRows) self.setCompleterMarca() self.setCompleterRubro() self.setCompleterProveedor() def onClickAgregar_p(self): self.estado = 'AGREGAR' self.validarBotones(button='AGREGAR') def onClickGuardar_p(self): validar = self.validar() if validar != "": print(validar) alert = QDialog() QMessageBox.information(alert,"ERROR", validar) else: self.producto.setDescripcion(str(self.winPrincipal.txtDescripcion_p.toPlainText())) self.producto.setCantidad(int(self.winPrincipal.sbCantidad_p.value())) self.producto.setCantidadMinima(int(self.winPrincipal.sbCantidadMin_p.value())) if self.winPrincipal.cbEstado_p.currentText() == "ACTIVO": self.producto.setEstado(1) else: self.producto.setEstado(0) if self.winPrincipal.rbFemenino_p.isChecked() is True: self.producto.setGenero("F") else: self.producto.setGenero("M") self.producto.setNombre(str(self.winPrincipal.txtNombre_p.text())) self.producto.setPrecioCompra(float(self.winPrincipal.txtPrecioCompra_p.text())) self.producto.setPrecioVenta(float(self.winPrincipal.txtPrecioVenta_p.text())) self.rubro.setRubro(str(self.completerRubro.currentCompletion())) self.producto.setRubro(self.rubro) self.proveedor.setDescripcion(str(self.completerProveedor.currentCompletion())) self.producto.setProveedor(self.proveedor) self.marca.setMarca(str(self.completerMarca.currentCompletion())) self.producto.setMarca(self.marca) if self.estado == 'AGREGAR': self.insertarProducto() elif self.estado == 'MODIFICAR': self.modificarProducto() self.validarBotones('GUARDAR') def onClickModificar_p(self): self.estado = 'MODIFICAR' self.validarBotones(button='MODIFICAR') def onClickBorrar_p(self): if self.winPrincipal.btnGuardar_p.isEnabled() != True: self.conexionProducto.borrarProducto(self.producto) self.cargarTabla() self.validarBotones(button='BORRAR') def cargarTabla(self): listaProductos = self.conexionProducto.selectProducto() if len(listaProductos) > 0: header = ['idPro','Nombre', 'Descripcion', 'PC', 'PV', 'G', 'Estado', 'Cant', 'Cantidad Min', 'idMar', 'Marca', 'idRubro', 'Rubro', 'idProv', 'Proveedor'] self.tablaModel = MyTableModel(self.winPrincipal.tvProductos_p, listaProductos, header) self.winPrincipal.tvProductos_p.setModel(self.tablaModel) self.winPrincipal.tvProductos_p.selectionModel().currentChanged.connect(self.changeSelectedTable) self.winPrincipal.tvProductos_p.setColumnHidden(0, True) self.winPrincipal.tvProductos_p.setColumnWidth(1, 200) self.winPrincipal.tvProductos_p.setColumnWidth(2, 320) self.winPrincipal.tvProductos_p.setColumnWidth(3, 60) self.winPrincipal.tvProductos_p.setColumnWidth(4, 60) self.winPrincipal.tvProductos_p.setColumnWidth(5, 60) self.winPrincipal.tvProductos_p.setColumnHidden(6, True) self.winPrincipal.tvProductos_p.setColumnWidth(7, 40) self.winPrincipal.tvProductos_p.setColumnHidden(8, True) self.winPrincipal.tvProductos_p.setColumnHidden(9, True) self.winPrincipal.tvProductos_p.setColumnWidth(10, 130) self.winPrincipal.tvProductos_p.setColumnHidden(11, True) self.winPrincipal.tvProductos_p.setColumnWidth(12, 130) self.winPrincipal.tvProductos_p.setColumnHidden(13, True) self.winPrincipal.tvProductos_p.setColumnWidth(14, 130) def changeSelectedTable(self, selected, deselected): productoList = selected.model().mylist productoSelected = productoList[selected.row()] self.producto = Producto() self.rubro = Rubro() self.proveedor = Proveedor() self.marca = Marca() self.producto.setIdProducto(productoSelected[0]) self.producto.setNombre(productoSelected[1]) self.producto.setDescripcion(productoSelected[2]) self.producto.setPrecioCompra(productoSelected[3]) self.producto.setPrecioVenta(productoSelected[4]) self.producto.setGenero(productoSelected[5]) self.producto.setEstado(productoSelected[6]) self.producto.setCantidad(productoSelected[7]) self.producto.setCantidadMinima(productoSelected[8]) self.marca.setIdMarca(productoSelected[9]) self.marca.setMarca(productoSelected[10]) self.producto.setMarca(self.marca) self.rubro.setIdRubro(productoSelected[11]) self.rubro.setRubro(productoSelected[12]) self.producto.setRubro(self.rubro) self.proveedor.setIdProveedor(productoSelected[13]) self.proveedor.setDescripcion(productoSelected[14]) self.producto.setProveedor(self.proveedor) self.winPrincipal.tvProductos_p.setRowHeight(deselected.row(),33) self.winPrincipal.tvProductos_p.setRowHeight(selected.row(),45) self.setCampos() self.winPrincipal.btnModificar_p.setEnabled(True) self.winPrincipal.btnBorrar_p.setEnabled(True) def validarBotones(self, button): if button == 'AGREGAR' : self.winPrincipal.wDatosProducto.setEnabled(True) self.winPrincipal.btnBorrar_p.setEnabled(True) self.winPrincipal.btnBorrar_p.setText('CANCELAR') self.winPrincipal.btnGuardar_p.setEnabled(True) self.winPrincipal.btnModificar_p.setEnabled(False) self.winPrincipal.btnAgregar_p.setEnabled(False) self.winPrincipal.tvProductos_p.setEnabled(False) self.limpiarCampos() elif button=='GUARDAR': self.winPrincipal.btnModificar_p.setEnabled(False) self.winPrincipal.btnAgregar_p.setEnabled(True) self.winPrincipal.btnGuardar_p.setEnabled(False) self.winPrincipal.btnBorrar_p.setText('BORRAR') self.winPrincipal.btnBorrar_p.setEnabled(False) self.winPrincipal.tvProductos_p.setEnabled(True) self.winPrincipal.wDatosProducto.setEnabled(False) self.limpiarCampos() elif button == 'MODIFICAR': self.winPrincipal.btnModificar_p.setEnabled(False) self.winPrincipal.btnAgregar_p.setEnabled(False) self.winPrincipal.btnGuardar_p.setEnabled(True) self.winPrincipal.btnBorrar_p.setText('CANCELAR') self.winPrincipal.btnBorrar_p.setEnabled(True) self.winPrincipal.tvProductos_p.setEnabled(False) self.winPrincipal.wDatosProducto.setEnabled(True) elif button=='BORRAR': self.winPrincipal.btnModificar_p.setEnabled(False) self.winPrincipal.btnAgregar_p.setEnabled(True) self.winPrincipal.btnGuardar_p.setEnabled(False) self.winPrincipal.btnBorrar_p.setText('BORRAR') self.winPrincipal.btnBorrar_p.setEnabled(False) self.winPrincipal.tvProductos_p.setEnabled(True) self.winPrincipal.wDatosProducto.setEnabled(False) self.limpiarCampos() def insertarProducto(self): self.conexionProducto.insertarProducto(producto=self.producto) self.cargarTabla() def modificarProducto(self): self.conexionProducto.modificarProducto(self.producto) self.cargarTabla() def limpiarCampos(self): self.winPrincipal.txtNombre_p.setText('') self.winPrincipal.txtPrecioCompra_p.setText('') self.winPrincipal.txtPrecioVenta_p.setText('') self.winPrincipal.sbCantidad_p.setValue(0) self.winPrincipal.sbCantidadMin_p.setValue(0) self.winPrincipal.txtProveedor_p.setText('') self.winPrincipal.txtDescripcion_p.setText('') self.winPrincipal.txtRubro_p.setText('') self.winPrincipal.txtMarca_p.setText('') def setCampos(self): self.winPrincipal.txtNombre_p.setText(self.producto.getNombre()) self.winPrincipal.txtDescripcion_p.setText(str(self.producto.getDescripcion())) self.winPrincipal.txtPrecioCompra_p.setText(str(self.producto.getPrecioCompra())) self.winPrincipal.txtPrecioVenta_p.setText(str(self.producto.getPrecioVenta())) self.winPrincipal.txtProveedor_p.setText(str(self.producto.getProveedor().getDescripcion())) self.winPrincipal.sbCantidad_p.setValue(int(self.producto.getCantidad())) self.winPrincipal.sbCantidadMin_p.setValue(int(self.producto.getCantidadMinima())) self.winPrincipal.txtRubro_p.setText(str(self.producto.getRubro().getRubro())) self.winPrincipal.txtMarca_p.setText(str(self.producto.getMarca().getMarca())) if self.producto.getEstado() == 1: self.winPrincipal.cbEstado_p.setCurrentIndex(0) else: self.winPrincipal.cbEstado_p.setCurrentIndex(1) if self.producto.getGenero() == 'F': self.winPrincipal.rbFemenino_p.setChecked(True) else: self.winPrincipal.rbMasculino_p.setChecked(True) def validar(self): mensaje='' if self.winPrincipal.txtNombre_p.text() == '': mensaje= "Falta ingresar Nombre" elif self.winPrincipal.txtPrecioCompra_p.text() =='': mensaje= "Falta ingresar Precio de Compra" elif self.winPrincipal.txtPrecioVenta_p.text() =='': mensaje= "Falta ingresar Precio de Venta" elif self.completerProveedor.currentCompletion() =='' or self.completerProveedor.currentRow() == 0: mensaje= "Falta ingresar un Proveedor" elif self.completerMarca.currentCompletion() == '' or self.completerMarca.currentRow() == 0: mensaje = "Falta seleccionar la marca" elif self.completerRubro.currentCompletion() == '' or self.completerRubro.currentRow() == 0: mensaje = 'Falta seleccionar el rubro' return mensaje def setCompleterMarca(self): listMarcas = self.conexionProducto.listMarcas() self.completerMarca = QCompleter(listMarcas) self.completerMarca.setCaseSensitivity(QtCore.Qt.CaseInsensitive) self.winPrincipal.txtMarca_p.setCompleter(self.completerMarca) def setCompleterRubro(self): listRubros = self.conexionProducto.listRubro() self.completerRubro = QCompleter(listRubros) self.completerRubro.setCaseSensitivity(QtCore.Qt.CaseInsensitive) self.winPrincipal.txtRubro_p.setCompleter(self.completerRubro) def setCompleterProveedor(self): listProveedores = self.conexionProducto.listProveedor() self.completerProveedor = QCompleter(listProveedores) pass self.completerProveedor.setCaseSensitivity(QtCore.Qt.CaseInsensitive) self.winPrincipal.txtProveedor_p.setCompleter(self.completerProveedor)
def createTabs(self): """Create tabs in main window.""" try: # Initialize tab screen self.tabs = QTabWidget() self.tab1 = QWidget() self.tab2 = QWidget() # self.tabs.resize(300,200) # Add tabs self.tabs.addTab(self.tab1, _("Match Grabber for AlphaTL && RSL")) self.tabs.addTab(self.tab2, _("Custom Match")) # Create first tab self.tab1.layout = QVBoxLayout() self.le_url = MatchComboBox(self) self.le_url.returnPressed.connect(self.refresh_click) minWidth = self.scoreWidth + 2 * self.raceWidth + \ 2 * self.mimumLineEditWidth + 4 * 6 self.le_url.setMinimumWidth(minWidth) self.pb_openBrowser = QPushButton(_("Open in Browser")) self.pb_openBrowser.clicked.connect(self.openBrowser_click) width = (self.scoreWidth + 2 * self.raceWidth + 2 * self.mimumLineEditWidth + 4 * 6) / 2 - 2 self.pb_openBrowser.setMinimumWidth(width) container = QHBoxLayout() label = QLabel() label.setFixedWidth(self.labelWidth) container.addWidget(label, 0) label = QLabel(_("Match-URL:")) label.setMinimumWidth(80) container.addWidget(label, 0) container.addWidget(self.le_url, 1) button = QPushButton() pixmap = QIcon(scctool.settings.getResFile('alpha.png')) button.setIcon(pixmap) button.clicked.connect( lambda: self.controller.openURL("https://alpha.tl/")) container.addWidget(button, 0) button = QPushButton() pixmap = QIcon(scctool.settings.getResFile('rsl.png')) button.setIcon(pixmap) button.clicked.connect( lambda: self.controller.openURL("https://rfcs.ru/en/")) container.addWidget(button, 0) self.tab1.layout = QFormLayout() self.tab1.layout.addRow(container) container = QHBoxLayout() # self.pb_download = QPushButton("Download Images from URL") # container.addWidget(self.pb_download) label = QLabel() label.setFixedWidth(self.labelWidth) container.addWidget(label, 0) label = QLabel() label.setMinimumWidth(80) container.addWidget(label, 0) self.pb_refresh = QPushButton(_("Load Data from URL")) self.pb_refresh.clicked.connect(self.refresh_click) container.addWidget(self.pb_openBrowser, 3) container.addWidget(self.pb_refresh, 3) self.tab1.layout.addRow(container) self.tab1.setLayout(self.tab1.layout) # Create second tab self.tab2.layout = QVBoxLayout() container = QHBoxLayout() label = QLabel() label.setMinimumWidth(self.labelWidth) container.addWidget(label, 0) label = QLabel(_("Match Format:")) label.setMinimumWidth(80) container.addWidget(label, 0) container.addWidget(QLabel(_("Best of")), 0) self.cb_bestof = QComboBox() for idx in range(0, scctool.settings.max_no_sets): self.cb_bestof.addItem(str(idx + 1)) self.cb_bestof.setCurrentIndex(3) string = _('"Best of 6/4": First, a Bo5/3 is played and the' ' ace map gets extended to a Bo3 if needed;' ' Best of 2: Bo3 with only two maps played.') self.cb_bestof.setToolTip(string) self.cb_bestof.setMaximumWidth(45) self.cb_bestof.currentIndexChanged.connect(self.changeBestOf) container.addWidget(self.cb_bestof, 0) container.addWidget(QLabel(_(" but at least")), 0) self.cb_minSets = QComboBox() self.cb_minSets.setToolTip( _('Minimum number of maps played (even if the match' ' is decided already)')) self.cb_minSets.setMaximumWidth(45) container.addWidget(self.cb_minSets, 0) container.addWidget(QLabel(" " + _("maps") + " "), 0) self.cb_minSets.currentIndexChanged.connect( lambda idx: self.highlightApplyCustom()) self.cb_allkill = QCheckBox(_("All-Kill Format")) self.cb_allkill.setChecked(False) self.cb_allkill.setToolTip( _('Winner stays and is automatically' ' placed into the next set')) self.cb_allkill.stateChanged.connect(self.allkill_change) container.addWidget(self.cb_allkill, 0) self.cb_solo = QCheckBox(_("1vs1")) self.cb_solo.setChecked(False) self.cb_solo.setToolTip(_('Select for solo (non-team matches)')) container.addWidget(self.cb_solo, 0) self.cb_solo.stateChanged.connect( lambda idx: self.highlightApplyCustom()) label = QLabel("") container.addWidget(label, 1) self.applycustom_is_highlighted = False self.pb_applycustom = QToolButton() action = QAction(_("Apply Format")) action.triggered.connect(self.applycustom_click) self.pb_applycustom.setDefaultAction(action) self.custom_menu = QMenu(self.pb_applycustom) for format, icon in \ self.controller.matchControl.getCustomFormats(): if icon: action = self.custom_menu.addAction( QIcon(scctool.settings.getResFile(icon)), format) else: action = self.custom_menu.addAction(format) action.triggered.connect( lambda x, format=format: self.applyCustomFormat(format)) self.pb_applycustom.setMenu(self.custom_menu) self.pb_applycustom.setPopupMode(QToolButton.MenuButtonPopup) self.pb_applycustom.setFixedWidth(150) container.addWidget(self.pb_applycustom, 0) self.defaultButtonPalette = self.pb_applycustom.palette() self.tab2.layout.addLayout(container) container = QHBoxLayout() label = QLabel() label.setMinimumWidth(self.labelWidth) container.addWidget(label, 0) label = QLabel(_("Match-URL:")) label.setMinimumWidth(80) container.addWidget(label, 0) self.le_url_custom = MonitoredLineEdit() self.le_url_custom.setAlignment(Qt.AlignCenter) self.le_url_custom.setToolTip( _('Optionally specify the Match-URL,' ' e.g., for Nightbot commands')) self.le_url_custom.setPlaceholderText( _("Specify the Match-URL of your Custom Match")) completer = QCompleter(["http://"], self.le_url_custom) completer.setCaseSensitivity(Qt.CaseInsensitive) completer.setCompletionMode(QCompleter.UnfilteredPopupCompletion) completer.setWrapAround(True) self.le_url_custom.setCompleter(completer) self.le_url_custom.setMinimumWidth(360) self.le_url_custom.textModified.connect(self.highlightApplyCustom) container.addWidget(self.le_url_custom, 11) label = QLabel("") container.addWidget(label, 1) self.pb_resetdata = QPushButton(_("Reset Match Data")) self.pb_resetdata.setFixedWidth(150) self.pb_resetdata.clicked.connect(self.resetdata_click) container.addWidget(self.pb_resetdata, 0) self.tab2.layout.addLayout(container) self.tab2.setLayout(self.tab2.layout) except Exception as e: module_logger.exception("message")
class TabController(QWidget): # Adding signal catCreated = pyqtSignal(Tag) catClicked = pyqtSignal(Tag) catUpdated = pyqtSignal(Tag) childClicked = pyqtSignal(str) def __init__(self, parent, docker, window, editSpace_theme='light'): super(QWidget, self).__init__(parent) self.layout = QVBoxLayout(self) self.editSpace = None # Used for displaying source code self.graphview = None # Used for the graphical display self.aiml = None # THIS SHOULD BE THE ONLY MODEL IN THE SYSTEM self.docker = docker self.window = window self.up_to_date = True self.editSpace_theme = editSpace_theme # Initialize tab screen self.tabs = QTabWidget() self.tab1 = QWidget() self.tab2 = QWidget() self.tabs.resize(300, 200) # Add tabs self.tabs.addTab(self.tab1, "Text Display") self.tabs.addTab(self.tab2, "Graph Display") # Create tabs self.add_editspace(self.tab1) self.add_graphview(self.tab2) # Add tabs to widget self.layout.addWidget(self.tabs) self.setLayout(self.layout) # Make Connection self.docker.catCreated.connect(self.categoryCreated) self.window.catCreated.connect(self.categoryCreated) self.docker.catUpdated.connect( self.categoryUpdated ) # connecting signal from EditorWindow to update Node self.editSpace.textChanged.connect(self.editsMade) def editsMade(self): self.tabs.setStyleSheet('QTabBar::tab {background-color: red;}') self.up_to_date = False if DEBUG: print("Text has been changed!!") def add_editspace(self, tab): tab.layout = QVBoxLayout(self) # Setting main editing area where Files will be displayed and can be edited self.editSpace = QCodeEditor(self, theme_color=self.editSpace_theme) # list for Completer model words = [ "<aiml></aiml>", "<topic></topic>", "<category></category>", "<pattern></pattern>", "<template></template>", "<condition></condition>", "<li></li>", "<random></random>", "<set></set>", "<think></think>", "<that></that>", "<oob></oob>", "<robot></robot>", "<options></options>", "<option></option>", "<image></image>", "<video></video>", "<filename></filename>", "<get name=\"\" />", "<srai/>", "<star/>" ] # Setting completer self.completer = QCompleter(self.editSpace) self.completer.setCompletionMode(QCompleter.UnfilteredPopupCompletion) # self.completer.setCompletionMode(QCompleter.PopupCompletion) print( f"modelFromFile returning: {QStringListModel(words, self.completer).stringList()}" ) # self.completer.setModel(self.modelFromFile('GUI/style/keywords.txt')) self.completer.setModel(QStringListModel(words, self.completer)) self.completer.setModelSorting(QCompleter.CaseInsensitivelySortedModel) self.completer.setCaseSensitivity(Qt.CaseInsensitive) self.completer.setWrapAround(False) self.editSpace.setCompleter(self.completer) self.tab1.layout.addWidget(self.editSpace) tab.setLayout(tab.layout) def modelFromFile(self, fileName): if getattr(sys, 'frozen', False): path = os.path.dirname(sys.executable) path = path[:-4] + fileName else: path = os.path.abspath(os.path.dirname( os.path.abspath(__file__))) + fileName if DEBUG: print(f"path: {path}") with open(path, "r") as f: words = f.read().splitlines() QApplication.restoreOverrideCursor() if DEBUG: print( f"modelFromFile returning: {QStringListModel(words, self.completer).stringList()}" ) return QStringListModel(words, self.completer) def add_graphview(self, tab): tab.layout = QGridLayout(self) # Setting of backdrop for view categories as nodes. self.graphview = EditorWidget(self) # Building legend and zoom buttons self.add_legend() # Adding widgets to layout self.tab2.layout.addWidget(self.legendLabel, 0, 0) self.tab2.layout.addWidget(self.zoom_out, 0, 1) self.tab2.layout.addWidget(self.zoom_in, 0, 2) self.tab2.layout.addWidget(self.graphview, 1, 0, 1, 3) # Making button connections self.zoom_out.clicked.connect(self.zoom_out_clicked) self.zoom_in.clicked.connect(self.zoom_in_clicked) # Setting layout tab.setLayout(tab.layout) def add_legend(self): # Creating buttons to zoom in and out of the graph scene self.zoom_out = QPushButton("-") self.zoom_out.resize(50, 50) self.zoom_in = QPushButton("+") self.zoom_in.resize(50, 50) # Creating legend to clarify what fields in nodes mean self.legendLabel = QLabel() self.legendLabel.setFont(QFont("Sanserif", 10)) self.legendLabel.setText( "1st textbox represents the Pattern Tag\n" "2nd textbox represents the That Tag\n" "3rd textbox represents the Template Tag\n" "Yellow node is node currently selected, Red nodes are children, Turquoise nodes are parents." ) self.legendLabel.setStyleSheet( "QLabel {background-color: black; color: white; border: 1px solid " "#01DFD7; border-radius: 5px;}") def zoom_in_clicked(self): if DEBUG: print("Zoom In Clicked") zoomFactor = self.graphview.view.zoomInFactor zoomFactor += (self.graphview.view.zoomStep * 0.25) self.graphview.view.scale(zoomFactor, zoomFactor) def zoom_out_clicked(self): if DEBUG: print("Zoom Out Clicked") zoomFactor = self.graphview.view.zoomInFactor zoomFactor -= (self.graphview.view.zoomStep * 0.5) self.graphview.view.scale(zoomFactor, zoomFactor) def create_category_code_editor(self, cat): try: if self.aiml is not None: if DEBUG: print(f"Current aiml Model:\n{self.aiml}") if DEBUG: print("Ok to add category") self.aiml.append(cat) if DEBUG: print("appended category to AIML object") self.catCreated.emit(self.aiml) return cat else: if DEBUG: print("CodeEditor is equal to None") self.aiml = AIML() # self.clear() self.aiml.append(cat) if DEBUG: print("appended category to AIML object") self.catCreated.emit(self.aiml) return cat except Exception as ex: handleError(ex) print( "Exception caught in TabController - create_category_code_editor()" ) print(ex) def create_category_graph_view(self, cat): try: if cat.type == "topic": # Iterate through topic and place categories for category in cat.tags: thatToCheck = self.graphview.getLastSentence(category) if DEBUG: print("got last sentence of category") title = "Category: " + category.cat_id aNode = Node(self.graphview.scene, title, category) if DEBUG: print("created node") aNode.content.wdg_label.displayVisuals(category) if DEBUG: print("displayed contents on node") if thatToCheck is not None: for that in thatToCheck: self.graphview.findChildNodes(aNode, that) # FIXME: Nodes only get placed if there are <that> tags otherwise get stacked in default place. self.graphview.findParentNodes(aNode) self.graphview.placeNodes(self.graphview.scene.nodes) for node in self.graphview.scene.nodes: node.updateConnectedEdges() aNode.content.catClicked.connect( self.graphview.categoryClicked ) # connecting signals coming from Content Widget # NOTE: When addChildClicked has been implemented then this can be uncommented # if DEBUG: print("trying to connect addChild button") # aNode.content.childClicked.connect(self.graphview.addChildClicked) # connecting signals coming from Content Widget elif cat.type == "comment": print("Comment found, don't display comments on graphview.") else: thatToCheck = self.graphview.getLastSentence(cat) if DEBUG: print("got last sentence of category") title = "Category: " + cat.cat_id aNode = Node(self.graphview.scene, title, cat) if DEBUG: print("created node") aNode.content.wdg_label.displayVisuals(cat) if DEBUG: print("displayed contents on node") if thatToCheck is not None: for that in thatToCheck: self.graphview.findChildNodes(aNode, that) self.graphview.findParentNodes(aNode) self.graphview.placeNodes(self.graphview.scene.nodes) for node in self.graphview.scene.nodes: node.updateConnectedEdges() aNode.content.catClicked.connect( self.graphview.categoryClicked ) # connecting signals coming from Content Widget except Exception as ex: print( "Exception caught in TabController - create_category_graph_view()" ) print(ex) handleError(ex) # slot function for a category being created and displaying on editSpace @pyqtSlot(Tag) def categoryCreated(self, cat): try: if DEBUG: print("In TabController Slot - categoryCreated()") cat = self.create_category_code_editor(cat) self.create_category_graph_view(cat) except Exception as ex: print("Exception caught in TabController - categoryCreated()") print(ex) handleError(ex) # Slot function for updating categories. @pyqtSlot(Tag) def categoryUpdated(self, cat): if DEBUG: print("slot in TabController - categoryUpdated()") try: updatedCat = self.aiml.update(cat) # NOTE: This should be a safer alternative rather than updating # then requiring user to manually compile. But this still # runs into the same issue as compiling manually after # moving and updating nodes. # self.editSpace.setPlainText(str(self.aiml)) # self.window.onCompile() if DEBUG: print(f'Updated aiml object:\n{self.aiml}') self.graphview.updateNode(cat) # Updating graphview display if DEBUG: print("EditorWidget successfully updated") if DEBUG: print(f"aiml object to set (TabController):\n{self.aiml}") self.catUpdated.emit( self.aiml ) # Sending the updated aiml object to the CodeEditor. except Exception as ex: print("Exception caught in TabController - categoryUpdated()") print(ex) handleError(ex)
class MainWindow(QMainWindow): def __init__(self, parent=None): super(MainWindow, self).__init__() self.setGeometry(300, 300, 400, 300) fid = open('example.db', 'w') fid.close() db = QSqlDatabase.addDatabase("QSQLITE") db.setDatabaseName('example.db') db.open() query = QSqlQuery(db) query.exec_('CREATE TABLE "airports" ("city" TEXT, "code" TEXT)') airports = [('Aberdeen, SD', 'ABR'), ('Abilene, TX', 'ABI'), ('Adak Island, AK', 'ADK'), ('Akiachak, AK', 'KKI'), ('Akiak, AK', 'AKI'), ('Akron/Canton, OH', 'CAK'), ('Akuton, AK', 'KQA'), ('Alakanuk, AK', 'AUK'), ('Alamogordo, NM', 'ALM'), ('Alamosa, CO', 'ALS'), ('Albany, NY', 'ALB'), ('Albuquerque, NM', 'ABQ')] for item in airports: sql = 'INSERT INTO airports(city, code) VALUES(?, ?)' query.prepare(sql) query.addBindValue(item[0]) query.addBindValue(item[1]) query.exec_() query.exec_('SELECT * FROM airports') model = QSqlQueryModel() model.setQuery(query) self.cb = QComboBox(parent=self) self.cb.setModel(model) self.cb.setModelColumn(1) self.cb.setView(QTableView(self.cb)) self.cb.setGeometry(50, 50, 250, 50) self.cb.currentIndexChanged.connect(self.indexer) self.label = QLabel(parent=self) self.label.setGeometry(20, 200, 250, 50) self.cb.view().setMinimumWidth(500) self.cb.setEditable(True) self.completer = QCompleter() self.completer.setCaseSensitivity(False) self.cb.setCompleter(self.completer) self.completer.setModel(model) self.completer.setCompletionColumn(1) self.completer.setPopup(QTableView()) self.completer.popup().setMinimumWidth(500) self.completer.popup().setMinimumHeight(500) self.completer.activated.connect(self.activatedHandler) #@pyqtSlot(QObject) def activatedHandler(self, arg): pass def indexer(self, idx): self.label.setText('%d' % idx)
def __init__(self, parent): super(ProjectExecution, self).__init__() self._parent = parent grid = QGridLayout(self) grid.addWidget(QLabel(translations.TR_PROJECT_MAIN_FILE), 0, 0) # Main file self.path = QLineEdit() choose_main_file_action = QAction(self) choose_main_file_action.setIcon( self.style().standardIcon(self.style().SP_FileIcon)) choose_main_file_action.setToolTip( translations.TR_PROJECT_SELECT_MAIN_FILE) self.path.addAction( choose_main_file_action, QLineEdit.TrailingPosition) clear_main_file_action = self.path.addAction( self.style().standardIcon(self.style().SP_LineEditClearButton), QLineEdit.TrailingPosition) clear_main_file_action.triggered.connect(self.path.clear) self.path.setPlaceholderText( os.path.join(os.path.expanduser("~"), 'path', 'to', 'main.py')) self.path.setText(self._parent.project.main_file) grid.addWidget(self.path, 0, 1) # this should be changed, and ALL pythonPath names to # python_custom_interpreter or something like that. this is NOT the # PYTHONPATH self.line_interpreter = QLineEdit() choose_interpreter = self.line_interpreter.addAction( self.style().standardIcon(self.style().SP_DirIcon), QLineEdit.TrailingPosition) self.line_interpreter.setText(self._parent.project.python_exec) completer = QCompleter(utils.get_python()) completer.setCaseSensitivity(Qt.CaseInsensitive) completer.setFilterMode(Qt.MatchContains) self.line_interpreter.setCompleter(completer) self.line_interpreter.setPlaceholderText("python") grid.addWidget(QLabel( translations.TR_PROJECT_PYTHON_INTERPRETER), 1, 0) grid.addWidget(self.line_interpreter, 1, 1) # PYTHONPATH grid.addWidget(QLabel(translations.TR_PROJECT_PYTHON_PATH), 2, 0) self.txt_python_path = QPlainTextEdit() # TODO : better widget self.txt_python_path.setPlainText(self._parent.project.python_path) self.txt_python_path.setToolTip(translations.TR_PROJECT_PATH_PER_LINE) grid.addWidget(self.txt_python_path, 2, 1) # Additional builtins/globals for pyflakes grid.addWidget(QLabel(translations.TR_PROJECT_BUILTINS), 3, 0) self.additional_builtins = QLineEdit() self.additional_builtins.setText( ' '.join(self._parent.project.additional_builtins)) self.additional_builtins.setToolTip( translations.TR_PROJECT_BUILTINS_TOOLTIP) grid.addWidget(self.additional_builtins, 3, 1) # Pre script self._line_pre_exec = QLineEdit() choose_pre_exec = QAction(self) choose_pre_exec.setToolTip( "Choose Script to execute before run project") choose_pre_exec.setIcon( self.style().standardIcon(self.style().SP_FileIcon)) self._line_pre_exec.addAction( choose_pre_exec, QLineEdit.TrailingPosition) clear_pre_action = self._line_pre_exec.addAction( self.style().standardIcon(self.style().SP_LineEditClearButton), QLineEdit.TrailingPosition) clear_pre_action.triggered.connect(self._line_pre_exec.clear) self._line_pre_exec.setReadOnly(True) self._line_pre_exec.setText(self._parent.project.pre_exec_script) self._line_pre_exec.setPlaceholderText( os.path.join(os.path.expanduser("~"), 'path', 'to', 'script.sh')) grid.addWidget(QLabel(translations.TR_PROJECT_PRE_EXEC), 4, 0) grid.addWidget(self._line_pre_exec, 4, 1) # Post script self._line_post_exec = QLineEdit() choose_post_exec = QAction(self) choose_post_exec.setToolTip( "Choose script to execute after run project") choose_post_exec.setIcon( self.style().standardIcon(self.style().SP_FileIcon)) self._line_post_exec.addAction( choose_post_exec, QLineEdit.TrailingPosition) clear_post_action = self._line_post_exec.addAction( self.style().standardIcon(self.style().SP_LineEditClearButton), QLineEdit.TrailingPosition) clear_post_action.triggered.connect(self._line_post_exec.clear) self._line_post_exec.setReadOnly(True) self._line_post_exec.setText(self._parent.project.post_exec_script) self._line_post_exec.setPlaceholderText( os.path.join(os.path.expanduser("~"), 'path', 'to', 'script.sh')) grid.addWidget(QLabel(translations.TR_PROJECT_POST_EXEC), 5, 0) grid.addWidget(self._line_post_exec, 5, 1) # grid.addItem(QSpacerItem(5, 10, QSizePolicy.Expanding, # QSizePolicy.Expanding), 6, 0) # Properties grid.addWidget(QLabel(translations.TR_PROJECT_PROPERTIES), 7, 0) self._line_params = QLineEdit() self._line_params.setToolTip(translations.TR_PROJECT_PARAMS_TOOLTIP) self._line_params.setText(self._parent.project.program_params) self._line_params.setPlaceholderText('verbose, debug, force') grid.addWidget(QLabel(translations.TR_PROJECT_PARAMS), 8, 0) grid.addWidget(self._line_params, 8, 1) # Widgets for virtualenv properties self.txtVenvPath = QLineEdit() # ui_tools.LineEditButton( # self.txtVenvPath, self.txtVenvPath.clear, # self.style().standardPixmap(self.style().SP_TrashIcon)) self.txtVenvPath.setText(self._parent.project.venv) self._dir_completer = QCompleter() self._dir_completer.setModel(QDirModel(self._dir_completer)) self.txtVenvPath.setCompleter(self._dir_completer) self.txtVenvPath.setPlaceholderText( os.path.join(os.path.expanduser("~"), 'path', 'to', 'virtualenv')) # self.btnVenvPath = QPushButton(QIcon(":img/open"), '') grid.addWidget(QLabel(translations.TR_PROJECT_VIRTUALENV), 9, 0) grid.addWidget(self.txtVenvPath, 9, 1) # grid.addWidget(self.btnVenvPath, 9, 2) choose_main_file_action.triggered.connect(self.select_file) choose_interpreter.triggered.connect(self._load_python_path) choose_pre_exec.triggered.connect(self.select_pre_exec_script) choose_post_exec.triggered.connect(self.select_post_exec_script)
def __init__(self, device, *args, **kwargs): super().__init__() self.setAllowedAreas(Qt.BottomDockWidgetArea) self.setWindowTitle("Console [{}]".format(device.p["FriendlyName1"])) self.device = device self.settings = QSettings("{}/TDM/tdm.cfg".format(QDir.homePath()), QSettings.IniFormat) console_font_size = self.settings.value("console_font_size", 9, int) console_font.setPointSize(console_font_size) console_word_wrap = self.settings.value("console_word_wrap", True, bool) w = QWidget() vl = VLayout() self.console = QPlainTextEdit() self.console.setTabChangesFocus(True) self.console.setWordWrapMode(console_word_wrap) self.console.setReadOnly(True) self.console.setFont(console_font) self.console_hl = JSONHighLighter(self.console.document()) hl_command_mqttlog = HLayout(0) self.command = QLineEdit() self.command.setFont(console_font) self.command.setPlaceholderText( "Type the command and press ENTER to send.") self.command.returnPressed.connect(self.command_enter) self.command.textChanged.connect(self.command_changed) self.command.installEventFilter(self) command_cpl = QCompleter(sorted(commands)) command_cpl.setCaseSensitivity(Qt.CaseInsensitive) command_cpl.setCompletionMode(QCompleter.UnfilteredPopupCompletion) self.command.setCompleter(command_cpl) # command_cpl.popup().installEventFilter(self) command_cpl.activated.connect(self.command.clear, Qt.QueuedConnection) pbSave = QPushButton(QIcon("GUI/icons/save.png"), "") pbSave.setFlat(True) pbSave.setToolTip("Save console") pbSave.clicked.connect(self.save_console) pbClear = QPushButton(QIcon("GUI/icons/clear.png"), "") pbClear.setFlat(True) pbClear.setToolTip("Clear console") pbClear.clicked.connect(self.clear_console) self.cbMQTTLog = QComboBox() self.cbMQTTLog.addItems([ "Disabled", "Error", "Error/Info (default)", "Error/Info/Debug", "Error/Info/More debug", "All" ]) mqttlog = self.device.p.get("MqttLog", -1) if mqttlog != -1: self.cbMQTTLog.setCurrentIndex(int(mqttlog)) else: self.cbMQTTLog.setEnabled(False) self.cbMQTTLog.currentIndexChanged.connect(self.change_mqttlog) hl_command_mqttlog.addWidgets([ self.command, pbSave, pbClear, QLabel("MQTT Log level"), self.cbMQTTLog ]) vl.addWidget(self.console) vl.addLayout(hl_command_mqttlog) w.setLayout(vl) self.setWidget(w)
def completer(self, lst, edit): comp = QCompleter(lst) comp.setCaseSensitivity(Qt.CaseInsensitive) edit.setCompleter(comp)
def run_iface_config_window(icon): win = QDialog() win.setWindowTitle('CAN Interface Configuration') win.setWindowIcon(icon) win.setWindowFlags(Qt.CustomizeWindowHint | Qt.WindowTitleHint | Qt.WindowCloseButtonHint) win.setAttribute(Qt.WA_DeleteOnClose) # This is required to stop background timers! combo = QComboBox(win) combo.setEditable(True) combo.setInsertPolicy(QComboBox.NoInsert) combo.setSizeAdjustPolicy(QComboBox.AdjustToContents) combo.setFont(get_monospace_font()) combo_completer = QCompleter() combo_completer.setCaseSensitivity(Qt.CaseSensitive) combo_completer.setModel(combo.model()) combo.setCompleter(combo_completer) bitrate = QSpinBox(win) bitrate.setMaximum(1000000) bitrate.setMinimum(10000) bitrate.setValue(1000000) baudrate = QComboBox(win) baudrate.setEditable(True) baudrate.setInsertPolicy(QComboBox.NoInsert) baudrate.setSizeAdjustPolicy(QComboBox.AdjustToContents) baudrate.setFont(get_monospace_font()) baudrate_completer = QCompleter(win) baudrate_completer.setModel(baudrate.model()) baudrate.setCompleter(baudrate_completer) baudrate.setValidator(QIntValidator(min(STANDARD_BAUD_RATES), max(STANDARD_BAUD_RATES))) baudrate.insertItems(0, map(str, STANDARD_BAUD_RATES)) baudrate.setCurrentText(str(DEFAULT_BAUD_RATE)) ok = QPushButton('OK', win) def update_slcan_options_visibility(): if RUNNING_ON_LINUX: slcan_active = '/' in combo.currentText() else: slcan_active = True slcan_group.setEnabled(slcan_active) combo.currentTextChanged.connect(update_slcan_options_visibility) ifaces = None def update_iface_list(): nonlocal ifaces ifaces = iface_lister.get_list() known_keys = set() remove_indices = [] was_empty = combo.count() == 0 # Marking known and scheduling for removal for idx in count(): tx = combo.itemText(idx) if not tx: break known_keys.add(tx) if tx not in ifaces: logger.debug('Removing iface %r', tx) remove_indices.append(idx) # Removing - starting from the last item in order to retain indexes for idx in remove_indices[::-1]: combo.removeItem(idx) # Adding new items - starting from the last item in order to retain the final order for key in list(ifaces.keys())[::-1]: if key not in known_keys: logger.debug('Adding iface %r', key) combo.insertItem(0, key) # Updating selection if was_empty: combo.setCurrentIndex(0) result = None kwargs = {} def on_ok(): nonlocal result, kwargs try: baud_rate_value = int(baudrate.currentText()) except ValueError: show_error('Invalid parameters', 'Could not parse baud rate', 'Please specify correct baud rate', parent=win) return if not (min(STANDARD_BAUD_RATES) <= baud_rate_value <= max(STANDARD_BAUD_RATES)): show_error('Invalid parameters', 'Baud rate is out of range', 'Baud rate value should be within [%s, %s]' % (min(STANDARD_BAUD_RATES), max(STANDARD_BAUD_RATES)), parent=win) return kwargs['baudrate'] = baud_rate_value kwargs['bitrate'] = int(bitrate.value()) result_key = str(combo.currentText()).strip() if not result_key: show_error('Invalid parameters', 'Interface name cannot be empty', 'Please select a valid interface', parent=win) return try: result = ifaces[result_key] except KeyError: result = result_key win.close() ok.clicked.connect(on_ok) layout = QVBoxLayout(win) layout.addWidget(QLabel('Select CAN interface')) layout.addWidget(combo) slcan_group = QGroupBox('SLCAN adapter settings', win) slcan_layout = QVBoxLayout(slcan_group) slcan_layout.addWidget(QLabel('CAN bus bit rate:')) slcan_layout.addWidget(bitrate) slcan_layout.addWidget(QLabel('Adapter baud rate (not applicable to USB-CAN adapters):')) slcan_layout.addWidget(baudrate) slcan_group.setLayout(slcan_layout) layout.addWidget(slcan_group) layout.addWidget(ok) layout.setSizeConstraint(layout.SetFixedSize) win.setLayout(layout) with BackgroundIfaceListUpdater() as iface_lister: update_slcan_options_visibility() update_iface_list() timer = QTimer(win) timer.setSingleShot(False) timer.timeout.connect(update_iface_list) timer.start(int(BackgroundIfaceListUpdater.UPDATE_INTERVAL / 2 * 1000)) win.exec() return result, kwargs
def setupUi(self, MainWindow): MainWindow.setObjectName("MainWindow") MainWindow.resize(967, 922) self.centralwidget = QtWidgets.QWidget(MainWindow) self.centralwidget.setObjectName("centralwidget") self.label_LN = QtWidgets.QLabel(self.centralwidget) self.label_LN.setGeometry(QtCore.QRect(20, 70, 81, 21)) self.label_LN.setObjectName("label_LN") self.line_LN = QtWidgets.QLineEdit(self.centralwidget) self.line_LN.setGeometry(QtCore.QRect(150, 70, 171, 25)) self.line_LN.setObjectName("line_LN") self.line_FN = QtWidgets.QLineEdit(self.centralwidget) self.line_FN.setGeometry(QtCore.QRect(440, 70, 171, 25)) self.line_FN.setObjectName("line_FN") self.label_FN = QtWidgets.QLabel(self.centralwidget) self.label_FN.setGeometry(QtCore.QRect(350, 70, 81, 21)) self.label_FN.setObjectName("label_FN") self.label_3 = QtWidgets.QLabel(self.centralwidget) self.label_3.setGeometry(QtCore.QRect(350, 170, 81, 21)) self.label_3.setObjectName("label_3") self.label_4 = QtWidgets.QLabel(self.centralwidget) self.label_4.setGeometry(QtCore.QRect(20, 20, 161, 41)) self.label_4.setStyleSheet("font: 57 14pt \"Ubuntu\";") self.label_4.setObjectName("label_4") self.label_DB = QtWidgets.QLabel(self.centralwidget) self.label_DB.setGeometry(QtCore.QRect(20, 120, 101, 21)) self.label_DB.setObjectName("label_DB") self.date_of_birth = QtWidgets.QDateEdit(self.centralwidget) self.date_of_birth.setDisplayFormat("dd/MM/yyyy") self.date_of_birth.setGeometry(QtCore.QRect(150, 115, 171, 31)) self.date_of_birth.setObjectName("date_of_birth") self.label_BP = QtWidgets.QLabel(self.centralwidget) self.label_BP.setGeometry(QtCore.QRect(350, 120, 81, 21)) self.label_BP.setObjectName("label_BP") self.dateEdit_2 = QtWidgets.QDateEdit(self.centralwidget) self.dateEdit_2.setDisplayFormat("dd/MM/yyyy") self.dateEdit_2.setGeometry(QtCore.QRect(150, 165, 171, 31)) self.dateEdit_2.setObjectName("dateEdit_2") self.label_7 = QtWidgets.QLabel(self.centralwidget) self.label_7.setGeometry(QtCore.QRect(20, 170, 131, 21)) self.label_7.setObjectName("label_7") self.label_icd = QtWidgets.QLabel(self.centralwidget) self.label_icd.setGeometry(QtCore.QRect(20, 220, 81, 21)) self.label_icd.setObjectName("label_icd") self.label_histology = QtWidgets.QLabel(self.centralwidget) self.label_histology.setGeometry(QtCore.QRect(20, 270, 81, 21)) self.label_histology.setObjectName("label_histology") self.label_T_stage = QtWidgets.QLabel(self.centralwidget) self.label_T_stage.setGeometry(QtCore.QRect(20, 320, 81, 21)) self.label_T_stage.setObjectName("label_T_stage") self.T_stage = QtWidgets.QComboBox(self.centralwidget) self.T_stage.setGeometry(QtCore.QRect(90, 320, 81, 25)) self.T_stage.setObjectName("T_stage") self.T_stage.addItem("") self.T_stage.addItem("") self.T_stage.addItem("") self.T_stage.addItem("") self.T_stage.addItem("") self.T_stage.addItem("") self.T_stage.addItem("") self.N_stage = QtWidgets.QComboBox(self.centralwidget) self.N_stage.setGeometry(QtCore.QRect(270, 320, 81, 25)) self.N_stage.setObjectName("N_stage") self.N_stage.addItem("") self.N_stage.addItem("") self.N_stage.addItem("") self.N_stage.addItem("") self.N_stage.addItem("") self.label_N_Stage = QtWidgets.QLabel(self.centralwidget) self.label_N_Stage.setGeometry(QtCore.QRect(200, 320, 81, 21)) self.label_N_Stage.setObjectName("label_N_Stage") self.M_stage = QtWidgets.QComboBox(self.centralwidget) self.M_stage.setGeometry(QtCore.QRect(450, 320, 81, 25)) self.M_stage.setObjectName("M_stage") self.M_stage.addItem("") self.M_stage.addItem("") self.M_stage.addItem("") self.label_Overall_Stage = QtWidgets.QLabel(self.centralwidget) self.label_Overall_Stage.setGeometry(QtCore.QRect(560, 320, 101, 21)) self.label_Overall_Stage.setObjectName("label_Overall_Stage") self.Overall_Stage = QtWidgets.QComboBox(self.centralwidget) self.Overall_Stage.setGeometry(QtCore.QRect(670, 320, 81, 25)) self.Overall_Stage.setObjectName("Overall_Stage") self.Overall_Stage.addItem("") self.Overall_Stage.addItem("") self.Overall_Stage.addItem("") self.Overall_Stage.addItem("") self.Overall_Stage.addItem("") self.Overall_Stage.addItem("") self.Overall_Stage.addItem("") self.Overall_Stage.addItem("") self.Overall_Stage.addItem("") self.Overall_Stage.addItem("") self.Overall_Stage.addItem("") self.Overall_Stage.addItem("") self.Overall_Stage.addItem("") self.Overall_Stage.addItem("") self.Overall_Stage.addItem("") self.Overall_Stage.addItem("") self.label_M_Stage = QtWidgets.QLabel(self.centralwidget) self.label_M_Stage.setGeometry(QtCore.QRect(380, 320, 81, 21)) self.label_M_Stage.setObjectName("label_M_Stage") self.Tx_intent = QtWidgets.QComboBox(self.centralwidget) self.Tx_intent.setGeometry(QtCore.QRect(150, 370, 171, 25)) self.Tx_intent.setObjectName("Tx_intent") self.Tx_intent.addItem("") self.Tx_intent.addItem("") self.Tx_intent.addItem("") self.Tx_intent.addItem("") self.Tx_intent.addItem("") self.Tx_intent.addItem("") self.label_Tx_intent = QtWidgets.QLabel(self.centralwidget) self.label_Tx_intent.setGeometry(QtCore.QRect(20, 370, 81, 21)) self.label_Tx_intent.setObjectName("label_Tx_intent") self.label_Surgery = QtWidgets.QLabel(self.centralwidget) self.label_Surgery.setGeometry(QtCore.QRect(20, 420, 81, 21)) self.label_Surgery.setObjectName("label_Surgery") self.Surgery = QtWidgets.QComboBox(self.centralwidget) self.Surgery.setGeometry(QtCore.QRect(150, 420, 171, 25)) self.Surgery.setObjectName("Surgery") self.Surgery.addItem("") self.Surgery.addItem("") self.Surgery.addItem("") self.Surgery.addItem("") self.Surgery.addItem("") self.Surgery.addItem("") self.Surgery.addItem("") self.Surgery.addItem("") self.Surgery.addItem("") self.Surgery.addItem("") self.Surgery.addItem("") self.Surgery.addItem("") self.Surgery.addItem("") self.label_Rad = QtWidgets.QLabel(self.centralwidget) self.label_Rad.setGeometry(QtCore.QRect(350, 420, 81, 21)) self.label_Rad.setObjectName("label_Rad") self.label_Immuno = QtWidgets.QLabel(self.centralwidget) self.label_Immuno.setGeometry(QtCore.QRect(350, 470, 81, 21)) self.label_Immuno.setObjectName("label_Immuno") self.label_Chemo = QtWidgets.QLabel(self.centralwidget) self.label_Chemo.setGeometry(QtCore.QRect(20, 470, 81, 21)) self.label_Chemo.setObjectName("label_Chemo") self.label_Hormone = QtWidgets.QLabel(self.centralwidget) self.label_Hormone.setGeometry(QtCore.QRect(350, 520, 81, 21)) self.label_Hormone.setObjectName("label_Hormone") self.label_Branchy = QtWidgets.QLabel(self.centralwidget) self.label_Branchy.setGeometry(QtCore.QRect(20, 520, 81, 21)) self.label_Branchy.setObjectName("label_Branchy") self.label_DT_Last_existence = QtWidgets.QLabel(self.centralwidget) self.label_DT_Last_existence.setGeometry(QtCore.QRect( 20, 570, 171, 21)) self.label_DT_Last_existence.setObjectName("label_DT_Last_existence") self.Dt_Last_Existence = QtWidgets.QDateEdit(self.centralwidget) self.Dt_Last_Existence.setDisplayFormat("dd/MM/yyyy") self.Dt_Last_Existence.setGeometry(QtCore.QRect(200, 565, 171, 31)) self.Dt_Last_Existence.setObjectName("Dt_Last_Existence") self.gender = QtWidgets.QComboBox(self.centralwidget) self.gender.setGeometry(QtCore.QRect(440, 170, 171, 25)) self.gender.setObjectName("gender") self.gender.addItem("") self.gender.addItem("") self.gender.addItem("") self.gender.addItem("") self.label_Cancer_death = QtWidgets.QLabel(self.centralwidget) self.label_Cancer_death.setGeometry(QtCore.QRect(350, 620, 111, 21)) self.label_Cancer_death.setObjectName("label_Cancer_death") self.label_Death = QtWidgets.QLabel(self.centralwidget) self.label_Death.setGeometry(QtCore.QRect(20, 620, 81, 21)) self.label_Death.setObjectName("label_Death") self.label_Regional_control = QtWidgets.QLabel(self.centralwidget) self.label_Regional_control.setGeometry(QtCore.QRect(20, 720, 121, 21)) self.label_Regional_control.setObjectName("label_Regional_control") self.label_Distant_Control = QtWidgets.QLabel(self.centralwidget) self.label_Distant_Control.setGeometry(QtCore.QRect(20, 770, 121, 21)) self.label_Distant_Control.setObjectName("label_Distant_Control") self.label_Local_control = QtWidgets.QLabel(self.centralwidget) self.label_Local_control.setGeometry(QtCore.QRect(20, 670, 101, 21)) self.label_Local_control.setObjectName("label_Local_control") self.Save_button = QtWidgets.QPushButton(self.centralwidget) self.Save_button.setGeometry(QtCore.QRect(20, 820, 89, 25)) self.Save_button.setStyleSheet("background-color: rgb(138, 43, 226);\n" "font: 57 11pt \"Ubuntu\";\n" "color: rgb(238, 238, 236);") self.Save_button.setObjectName("Save_button") self.Death = QtWidgets.QComboBox(self.centralwidget) self.Death.setGeometry(QtCore.QRect(150, 620, 171, 25)) self.Death.setObjectName("Death") self.Death.addItem("") self.Death.addItem("") self.Death.addItem("") self.Cancer_death = QtWidgets.QComboBox(self.centralwidget) self.Cancer_death.setGeometry(QtCore.QRect(530, 620, 171, 25)) self.Cancer_death.setObjectName("Cancer_death") self.Cancer_death.addItem("") self.Cancer_death.addItem("") self.Cancer_death.addItem("") self.Local_control = QtWidgets.QComboBox(self.centralwidget) self.Local_control.setGeometry(QtCore.QRect(150, 670, 171, 25)) self.Local_control.setObjectName("Local_control") self.Local_control.addItem("") self.Local_control.addItem("") self.Local_control.addItem("") self.Regional_Control = QtWidgets.QComboBox(self.centralwidget) self.Regional_Control.setGeometry(QtCore.QRect(150, 720, 171, 25)) self.Regional_Control.setObjectName("Regional_Control") self.Regional_Control.addItem("") self.Regional_Control.addItem("") self.Regional_Control.addItem("") self.Distant_Control = QtWidgets.QComboBox(self.centralwidget) self.Distant_Control.setGeometry(QtCore.QRect(150, 770, 171, 25)) self.Distant_Control.setObjectName("Distant_Control") self.Distant_Control.addItem("") self.Distant_Control.addItem("") self.Distant_Control.addItem("") self.Chemo = QtWidgets.QComboBox(self.centralwidget) self.Chemo.setGeometry(QtCore.QRect(150, 470, 171, 25)) self.Chemo.setObjectName("Chemo") self.Chemo.addItem("") self.Chemo.addItem("") self.Chemo.addItem("") self.Chemo.addItem("") self.Chemo.addItem("") self.Chemo.addItem("") self.Chemo.addItem("") self.Chemo.addItem("") self.Chemo.addItem("") self.Chemo.addItem("") self.Chemo.addItem("") self.Chemo.addItem("") self.Chemo.addItem("") self.Branchy = QtWidgets.QComboBox(self.centralwidget) self.Branchy.setGeometry(QtCore.QRect(150, 520, 171, 25)) self.Branchy.setObjectName("Branchy") self.Branchy.addItem("") self.Branchy.addItem("") self.Branchy.addItem("") self.Branchy.addItem("") self.Branchy.addItem("") self.Branchy.addItem("") self.Branchy.addItem("") self.Branchy.addItem("") self.Branchy.addItem("") self.Branchy.addItem("") self.Branchy.addItem("") self.Branchy.addItem("") self.Branchy.addItem("") self.Rad = QtWidgets.QComboBox(self.centralwidget) self.Rad.setGeometry(QtCore.QRect(440, 420, 171, 25)) self.Rad.setObjectName("Rad") self.Rad.addItem("") self.Rad.addItem("") self.Rad.addItem("") self.Rad.addItem("") self.Rad.addItem("") self.Rad.addItem("") self.Rad.addItem("") self.Rad.addItem("") self.Rad.addItem("") self.Rad.addItem("") self.Rad.addItem("") self.Rad.addItem("") self.Rad.addItem("") self.Immuno = QtWidgets.QComboBox(self.centralwidget) self.Immuno.setGeometry(QtCore.QRect(440, 470, 171, 25)) self.Immuno.setObjectName("Immuno") self.Immuno.addItem("") self.Immuno.addItem("") self.Immuno.addItem("") self.Immuno.addItem("") self.Immuno.addItem("") self.Immuno.addItem("") self.Immuno.addItem("") self.Immuno.addItem("") self.Immuno.addItem("") self.Immuno.addItem("") self.Immuno.addItem("") self.Immuno.addItem("") self.Immuno.addItem("") self.Hormone = QtWidgets.QComboBox(self.centralwidget) self.Hormone.setGeometry(QtCore.QRect(440, 520, 171, 25)) self.Hormone.setObjectName("Hormone") self.Hormone.addItem("") self.Hormone.addItem("") self.Hormone.addItem("") self.Hormone.addItem("") self.Hormone.addItem("") self.Hormone.addItem("") self.Hormone.addItem("") self.Hormone.addItem("") self.Hormone.addItem("") self.Hormone.addItem("") self.Hormone.addItem("") self.Hormone.addItem("") self.Hormone.addItem("") self.label_Dt_Local_failure = QtWidgets.QLabel(self.centralwidget) self.label_Dt_Local_failure.setGeometry(QtCore.QRect( 350, 675, 151, 21)) self.label_Dt_Local_failure.setObjectName("label_Dt_Local_failure") self.Dt_local_failure = QtWidgets.QDateEdit(self.centralwidget) self.Dt_local_failure.setDisplayFormat("dd/MM/yyyy") self.Dt_local_failure.setGeometry(QtCore.QRect(530, 670, 171, 31)) self.Dt_local_failure.setObjectName("Dt_local_failure") self.Dt_local_failure.setDisabled(True) self.label_Dt_Regional_Failure = QtWidgets.QLabel(self.centralwidget) self.label_Dt_Regional_Failure.setGeometry( QtCore.QRect(350, 725, 171, 21)) self.label_Dt_Regional_Failure.setObjectName( "label_Dt_Regional_Failure") self.Dt_REgional_failure = QtWidgets.QDateEdit(self.centralwidget) self.Dt_REgional_failure.setDisplayFormat("dd/MM/yyyy") self.Dt_REgional_failure.setGeometry(QtCore.QRect(530, 720, 171, 31)) self.Dt_REgional_failure.setObjectName("Dt_REgional_failure") self.Dt_REgional_failure.setDisabled(True) self.Dt_Distant_Failure = QtWidgets.QDateEdit(self.centralwidget) self.Dt_Distant_Failure.setDisplayFormat("dd/MM/yyyy") self.Dt_Distant_Failure.setGeometry(QtCore.QRect(530, 765, 171, 31)) self.Dt_Distant_Failure.setObjectName("Dt_Distant_Failure") self.Dt_Distant_Failure.setDisabled(True) #self.Dt_Distant_Failure.setReadOnly(True) self.label_Dt_Distant_Failure = QtWidgets.QLabel(self.centralwidget) self.label_Dt_Distant_Failure.setGeometry( QtCore.QRect(350, 770, 171, 21)) self.label_Dt_Distant_Failure.setObjectName("label_Dt_Distant_Failure") self.line_BP = QtWidgets.QLineEdit(self.centralwidget) self.line_BP.setGeometry(QtCore.QRect(440, 120, 171, 25)) self.line_BP.setObjectName("line_BP") completer = QCompleter(data, self.line_BP) completer.setCaseSensitivity(QtCore.Qt.CaseInsensitive) self.line_BP.setCompleter(completer) self.line_icd = QtWidgets.QLineEdit(self.centralwidget) self.line_icd.setGeometry(QtCore.QRect(150, 220, 601, 25)) self.line_icd.setObjectName("line_icd") completer_5 = QCompleter(new_icd, self.line_icd) completer_5.setCaseSensitivity(QtCore.Qt.CaseInsensitive) completer_5.setFilterMode(QtCore.Qt.MatchContains) self.line_icd.setCompleter(completer_5) self.line_histology = QtWidgets.QLineEdit(self.centralwidget) self.line_histology.setGeometry(QtCore.QRect(150, 270, 601, 25)) self.line_histology.setObjectName("line_histology") completer_4 = QCompleter(new_hist, self.line_histology) completer_4.setCaseSensitivity(QtCore.Qt.CaseInsensitive) completer_4.setFilterMode(QtCore.Qt.MatchContains) self.line_histology.setCompleter(completer_4) MainWindow.setCentralWidget(self.centralwidget) self.menubar = QtWidgets.QMenuBar(MainWindow) self.menubar.setGeometry(QtCore.QRect(0, 0, 967, 22)) self.menubar.setObjectName("menubar") MainWindow.setMenuBar(self.menubar) self.statusbar = QtWidgets.QStatusBar(MainWindow) self.statusbar.setObjectName("statusbar") MainWindow.setStatusBar(self.statusbar) self.retranslateUi(MainWindow) QtCore.QMetaObject.connectSlotsByName(MainWindow)
def __init__(self, device, *args, **kwargs): super().__init__() self.setAllowedAreas(Qt.BottomDockWidgetArea) self.setWindowTitle("Console [{}]".format(device.p["FriendlyName1"])) self.device = device w = QWidget() vl = VLayout() self.console = QPlainTextEdit() self.console.setTabChangesFocus(True) fnt_mono = QFont("asd") fnt_mono.setStyleHint(QFont.TypeWriter) self.console.setFont(fnt_mono) self.console.setReadOnly(True) self.console_hl = JSONHighLighter(self.console.document()) hl_command_mqttlog = HLayout(0) self.command = QLineEdit() self.command.setFont(fnt_mono) self.command.setPlaceholderText( "Type the command and press ENTER to send.") self.command.returnPressed.connect(self.command_enter) self.command.textChanged.connect(self.command_changed) self.command.installEventFilter(self) command_cpl = QCompleter(sorted(commands)) command_cpl.setCaseSensitivity(Qt.CaseInsensitive) command_cpl.setCompletionMode(QCompleter.UnfilteredPopupCompletion) self.command.setCompleter(command_cpl) # command_cpl.popup().installEventFilter(self) command_cpl.activated.connect(self.command.clear, Qt.QueuedConnection) self.cbMQTTLog = QComboBox() self.cbMQTTLog.addItems([ "Disabled", "Error", "Error/Info (default)", "Error/Info/Debug", "Error/Info/More debug", "All" ]) mqttlog = self.device.p.get("MqttLog", -1) if mqttlog != -1: self.cbMQTTLog.setCurrentIndex(int(mqttlog)) else: self.cbMQTTLog.setEnabled(False) self.cbMQTTLog.currentIndexChanged.connect(self.change_mqttlog) hl_command_mqttlog.addWidgets( [self.command, QLabel("MQTT Log level"), self.cbMQTTLog]) vl.addWidget(self.console) vl.addLayout(hl_command_mqttlog) w.setLayout(vl) self.setWidget(w)
def __init__(self, parent: typing.Optional[QWidget], on_connection_request: ConnectionRequestCallback, on_disconnection_request: DisconnectionRequestCallback): super(DeviceManagementWidget, self).__init__(parent) self.setAttribute( Qt.WA_DeleteOnClose) # This is required to stop background timers! self._port_discoverer = PortDiscoverer() self._port_mapping: typing.Dict[str:str] = {} self._port_combo = QComboBox(self) self._port_combo.setEditable(True) self._port_combo.setInsertPolicy(QComboBox.NoInsert) self._port_combo.setSizeAdjustPolicy(QComboBox.AdjustToContents) self._port_combo.setFont(get_monospace_font()) self._port_combo.lineEdit().returnPressed.connect( self._on_confirmation) self._connect_button = make_button(self, 'Connect', 'disconnected', on_clicked=self._on_confirmation) self._connect_button.setEnabled( False) # Empty by default, therefore disabled self._port_combo.currentTextChanged.connect( lambda: self._connect_button.setEnabled( bool(self._port_combo.currentText().strip()))) self._status_text = QLabel(self) self._status_text.setText(_STATUS_WHEN_NOT_CONNECTED) self._status_text.setWordWrap(True) self._device_info_widget = LittleBobbyTablesWidget(self) combo_completer = QCompleter() combo_completer.setCaseSensitivity(Qt.CaseInsensitive) combo_completer.setModel(self._port_combo.model()) self._port_combo.setCompleter(combo_completer) self._update_timer = QTimer(self) self._update_timer.timeout.connect(self._update_ports) self._update_timer.start(2000) self._connection_progress_bar = QProgressBar(self) self._connection_progress_bar.setMinimum(0) self._connection_progress_bar.setMaximum(100) self._connection_established = False self._last_task: typing.Optional[asyncio.Task] = None self._connection_request_callback: ConnectionRequestCallback = on_connection_request self._disconnection_request_callback: DisconnectionRequestCallback = on_disconnection_request # Layout self._overlay = QStackedLayout(self) self._init_overlay_widgets() self.setLayout(self._overlay) # Initialization self._update_ports()
class DBAlbumsQT5Mini(QMainWindow): """Init mini Gui constants.""" PATH_PROG = path.dirname(path.abspath(__file__)) RESS_ICOS = path.join(PATH_PROG, 'IMG', 'ICO') chdir(PATH_PROG) VERS_PROG = '1.01' TITL_PROG = "♫ DBAlbums mini v{v} (2017)".format(v=VERS_PROG) FILE__INI = 'DBAlbums.json' Json_params = JsonParams(FILE__INI) group_dbalbums = Json_params.getMember('dbalbums') WINS_ICO = path.join(PATH_PROG, 'IMG', group_dbalbums['wins_icone']) PICM_NCO = path.join(PATH_PROG, 'IMG', group_dbalbums['pict_blank']) THEM_COL = group_dbalbums['name_theme'] ENVT_DEF = group_dbalbums['envt_deflt'] def __init__(self, parent=None): super(DBAlbumsQT5Mini, self).__init__(parent) self.setWindowIcon(QIcon(self.WINS_ICO)) self.setWindowTitle(self.TITL_PROG + ' : [' + self.ENVT_DEF + ']') self.h_main = 400 self.resize(1248, self.h_main) centerWidget(self) self.menua = QMenu() self.action_OPF = self.menua.addAction( self.style().standardIcon(QStyle.SP_DialogOpenButton), "Open Folder...", self.getFolder) self.textsearch = QLineEdit() self.textsearch.setFixedSize(170, 22) self.statusBar().addPermanentWidget(self.textsearch) self.textsearch.textChanged.connect(self.onFiltersChanged) self.btn_style = QPushButton() self.btn_style.setIcon(self.style().standardIcon( QStyle.SP_DialogResetButton)) self.btn_style.setStyleSheet("border: none;") self.btn_style.clicked.connect( lambda: [self.curthe.nextTheme(), self.applyTheme()]) self.statusBar().addPermanentWidget(self.btn_style) boolconnect, self.dbbase, self.modsql, self.rootDk, self.lstcat = connectDatabase( self.ENVT_DEF) autoList = DBFuncBase().sqlToArray( getrequest('autocompletion', self.modsql)) self.com_autcom = QCompleter(autoList, self.textsearch) self.com_autcom.setCaseSensitivity(Qt.CaseInsensitive) self.textsearch.setCompleter(self.com_autcom) self.mytable = QTableView(self) self.mytable.setAlternatingRowColors(True) self.mytable.setSortingEnabled(True) self.mytable.setSelectionBehavior(QTableView.SelectRows) self.mytable.setSelectionMode(QAbstractItemView.SingleSelection) self.mytable.doubleClicked.connect(self.onSelect) self.mytable.setContextMenuPolicy(Qt.CustomContextMenu) self.mytable.customContextMenuRequested.connect(self.popUpTreeAlbums) self.curthe = ThemeColors(self.THEM_COL) self.applyTheme() req = getrequest('albumslist', self.modsql) self.model = ModelTableAlbumsABS(self, req) self.model.SortFilterProxy.layoutChanged.connect(self.listChanged) self.model.SortFilterProxy.sort(-1) self.mytable.setModel(self.model.SortFilterProxy) # width columns for ind in range(len(self.model.A_C_WIDTH)): self.mytable.setColumnWidth(ind, self.model.A_C_WIDTH[ind]) # height rows self.mytable.verticalHeader().setDefaultSectionSize( self.model.C_HEIGHT) self.displayTitle() self.setCentralWidget(self.mytable) def onFiltersChanged(self): self.model.SortFilterProxy.updateFilters(self.textsearch.text()) self.displayTitle() def onSelect(self): indexes = self.mytable.selectedIndexes() indexes = self.model.SortFilterProxy.mapToSource(indexes[0]) self.currow = indexes.row() albumname = self.model.getData(self.currow, 'NAME') idcd = self.model.getData(self.currow, 'ID_CD') coveral = DBFuncBase().sqlToPixmap(idcd, self.PICM_NCO) CoverViewGui(coveral, albumname, self.h_main, self.h_main) def popUpTreeAlbums(self, position): self.menua.exec_(self.mytable.viewport().mapToGlobal(position)) def getFolder(self): """Open album folder.""" indexes = self.mytable.selectedIndexes() indexes = self.model.SortFilterProxy.mapToSource(indexes[0]) self.currow = indexes.row() albumpath = self.model.getData(self.currow, 'PATHNAME') openFolder(albumpath) def listChanged(self): pass def displayTitle(self): if int(((self.model.SortFilterProxy.cpt_len / 60 / 60) / 24) * 10) / 10 < 1: # seoncd -> Hours txt_len = str( int(((self.model.SortFilterProxy.cpt_len / 60 / 60)) * 10) / 10) + ' Hours' else: # seoncd -> Days txt_len = str( int(((self.model.SortFilterProxy.cpt_len / 60 / 60) / 24) * 10) / 10) + ' Days' if int(self.model.SortFilterProxy.cpt_siz / 1024) == 0: txt_siz = str(self.model.SortFilterProxy.cpt_siz) + ' Mo' else: txt_siz = str(int( self.model.SortFilterProxy.cpt_siz / 1024)) + ' Go' txt_sch = (self.textsearch.text() if len(self.textsearch.text()) > 0 else 'all') message = "Search Result \"{sch}\" : {alb} | {trk} | {cds} | {siz} | {dur}" message = message.format( alb=displayCounters(self.model.SortFilterProxy.rowCount(), 'Album'), cds=displayCounters(self.model.SortFilterProxy.cpt_cds, 'CD'), trk=displayCounters(self.model.SortFilterProxy.cpt_trk, 'Track'), siz=txt_siz, dur=txt_len, sch=txt_sch) self.statusBar().showMessage(message) # setsetWindowTitle(message) def applyTheme(self): """Apply color Theme to main Gui.""" # main mainstyle = 'QMainWindow{{background-color: {col1};border: 1px solid black;}}' \ 'QLineEdit{{background-color: {col2};}}' \ 'QStatusBar{{background-color: {col1};border: 1px solid black;}}' \ 'QScrollBar:vertical{{width: 14px;}}' \ 'QScrollBar:horizontal{{height: 14px;}}' \ 'QTableView{{alternate-background-color: {col3};background-color: {col4};}}' \ 'QTableView::item:selected{{ background-color:{col5}; color:white;}}' mainstyle = mainstyle.format(col1=self.curthe.listcolors[0], col2=self.curthe.listcolors[1], col3=self.curthe.listcolors[2], col4=self.curthe.listcolors[3], col5=self.curthe.listcolors[4]) self.setStyleSheet(mainstyle) # treeview gridstyle = 'QHeaderView::section{{background-color: {col2};border-radius:1px;margin: 1px;padding: 2px;}}' gridstyle = gridstyle.format(col2=self.curthe.listcolors[1]) self.mytable.setStyleSheet(gridstyle)
class AddCrossRefDialog(QDialog): def __init__(self, project_structure: dict, is_cursor_in_sentence: bool, parent): super().__init__(parent=parent) self.ui = Ui_AddCrossRefDialog() self.ui.setupUi(self) self.setPalette(parent.palette()) # Set attributes self.tag = "" self.project_structure = project_structure self.identifier_list = self.get_identifier_list() self.IdentifierCompleter = QCompleter(self.identifier_list, self) self.IdentifierCompleter.setCaseSensitivity(Qt.CaseInsensitive) self.ui.IdentiferLineEdit.setCompleter(self.IdentifierCompleter) # Prepare ui common.load_project_structure(self.project_structure, self.ui.StructureTreeWidget, ["footnotes", "citations"]) self.ui.StructureTreeWidget.setHeaderLabels(("Text", "Identifier")) if is_cursor_in_sentence: self.ui.LCCleverRefRadioButton.setChecked(True) else: self.ui.TCCleverRefRadioButton.setChecked(True) def get_identifier_list(self) -> list: """Returns a list of all identifiers in project structure""" #del self.project_structure["filepath"] identifiers = list() for item1 in self.project_structure.items(): for item2 in item1[1].items(): identifiers.append(item2[0]) return identifiers def accept(self) -> None: """Forms a tag based on the ui contents before closing the form""" identifier = self.ui.IdentiferLineEdit.text() # Check if identifier exists if identifier not in self.identifier_list: QMessageBox.warning( self, "Identifier invalid", "Identifier you specified has not been found. Please specify an identifier defined " + "in the current namespace (files to be rendered if current file is to be rendered or " + "only the current file if it is not.") return # Determine reference type identifier_categories = copy.deepcopy(defaults.identifier_categories) identifier_categories.remove("footnotes") identifier_categories.remove("citations") identifier_category = "" for category in identifier_categories: if identifier in self.project_structure[category]: identifier_category = category break # Form tag tag = "@" prefix = defaults.identifier_prefixes[identifier_category] if not identifier.startswith(prefix + ":"): tag += prefix + ":" tag += identifier # Handle clever references clever_ref_symbol = "" if self.ui.LCCleverRefRadioButton.isChecked(): clever_ref_symbol = "+" elif self.ui.TCCleverRefRadioButton.isChecked(): clever_ref_symbol = "*" elif self.ui.NoCleverRefRadioButton.isChecked(): clever_ref_symbol = "!" tag = clever_ref_symbol + tag self.tag = tag super().accept() @pyqtSlot(QTreeWidgetItem, int) def on_StructureTreeWidget_itemClicked(self, item, column_number) -> None: """Fills IdentifierLineEdit with identifier, which was clicked on in the StructureTreeWidget""" self.ui.IdentiferLineEdit.setText(item.text(1))
def init_toolbar(self): self.toolbar = QToolBar() self.toolbar.setFixedHeight(25) self.toolbar.setWindowTitle("Show") # text for the contextmenu #self.toolbar.setStyleSheet("QToolBar {border:0px}") # make it user defined? self.toolbar.setMovable(False) self.toolbar.setFloatable(False) #self.toolbar.setIconSize(QSize(20,20)) self.toolbar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) self.toolbar.setIconSize(QSize(20,20)) spacer_start = QWidget() # aligns the first actions properly spacer_start.setFixedSize(QSize(10, 1)) self.toolbar.addWidget(spacer_start) self.favourite_btn = misc.ToolbarButton(self.toolbar, 'Favorites') self.toolbar.addWidget(self.favourite_btn) self.favourite_btn.clicked.connect(self.favourite_display) #need lambda to pass extra args self.library_btn = misc.ToolbarButton(self.toolbar, 'Library') self.toolbar.addWidget(self.library_btn) self.library_btn.clicked.connect(self.catalog_display) #need lambda to pass extra args self.library_btn.selected = True self.toolbar.addSeparator() gallery_menu = QMenu() gallery_action = QToolButton() gallery_action.setText('Gallery ') gallery_action.setPopupMode(QToolButton.InstantPopup) gallery_action.setToolTip('Contains various gallery related features') gallery_action.setMenu(gallery_menu) add_gallery_icon = QIcon(app_constants.PLUS_PATH) gallery_action_add = QAction(add_gallery_icon, "Add single gallery...", self) gallery_action_add.triggered.connect(self.manga_list_view.SERIES_DIALOG.emit) gallery_action_add.setToolTip('Add a single gallery thoroughly') gallery_menu.addAction(gallery_action_add) add_more_action = QAction(add_gallery_icon, "Add galleries...", self) add_more_action.setStatusTip('Add galleries from different folders') add_more_action.triggered.connect(lambda: self.populate(True)) gallery_menu.addAction(add_more_action) populate_action = QAction(add_gallery_icon, "Populate from directory/archive...", self) populate_action.setStatusTip('Populates the DB with galleries from a single folder or archive') populate_action.triggered.connect(self.populate) gallery_menu.addAction(populate_action) gallery_menu.addSeparator() metadata_action = QAction('Get metadata for all galleries', self) metadata_action.triggered.connect(self.get_metadata) gallery_menu.addAction(metadata_action) scan_galleries_action = QAction('Scan for new galleries', self) scan_galleries_action.triggered.connect(self.scan_for_new_galleries) scan_galleries_action.setStatusTip('Scan monitored folders for new galleries') gallery_menu.addAction(scan_galleries_action) gallery_action_random = gallery_menu.addAction("Open random gallery") gallery_action_random.triggered.connect(self.manga_list_view.open_random_gallery) self.toolbar.addWidget(gallery_action) misc_action = QToolButton() misc_action.setText('Tools ') misc_action_menu = QMenu() misc_action.setMenu(misc_action_menu) misc_action.setPopupMode(QToolButton.InstantPopup) misc_action.setToolTip("Contains misc. features") gallery_downloader = QAction("Gallery Downloader", misc_action_menu) gallery_downloader.triggered.connect(self.download_window.show) misc_action_menu.addAction(gallery_downloader) duplicate_check_simple = QAction("Simple Duplicate Finder", misc_action_menu) duplicate_check_simple.triggered.connect(lambda: self.manga_list_view.duplicate_check()) misc_action_menu.addAction(duplicate_check_simple) self.toolbar.addWidget(misc_action) spacer_middle = QWidget() # aligns buttons to the right spacer_middle.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.toolbar.addWidget(spacer_middle) sort_action = QToolButton() sort_action.setIcon(QIcon(app_constants.SORT_PATH)) sort_action.setMenu(misc.SortMenu(self.toolbar, self.manga_list_view)) sort_action.setPopupMode(QToolButton.InstantPopup) self.toolbar.addWidget(sort_action) self.grid_toggle_g_icon = QIcon(app_constants.GRID_PATH) self.grid_toggle_l_icon = QIcon(app_constants.LIST_PATH) self.grid_toggle = QToolButton() if self.display.currentIndex() == self.m_l_view_index: self.grid_toggle.setIcon(self.grid_toggle_l_icon) else: self.grid_toggle.setIcon(self.grid_toggle_g_icon) self.grid_toggle.setObjectName('gridtoggle') self.grid_toggle.clicked.connect(self.toggle_view) self.toolbar.addWidget(self.grid_toggle) spacer_mid2 = QWidget() spacer_mid2.setFixedSize(QSize(5, 1)) self.toolbar.addWidget(spacer_mid2) def set_search_case(b): app_constants.GALLERY_SEARCH_CASE = b settings.set(b, 'Application', 'gallery search case') settings.save() def set_search_strict(b): app_constants.GALLERY_SEARCH_STRICT = b settings.set(b, 'Application', 'gallery search strict') settings.save() self.search_bar = misc.LineEdit() search_options = self.search_bar.addAction(QIcon(app_constants.SEARCH_OPTIONS_PATH), QLineEdit.TrailingPosition) search_options_menu = QMenu(self) search_options.triggered.connect(lambda: search_options_menu.popup(QCursor.pos())) search_options.setMenu(search_options_menu) case_search_option = search_options_menu.addAction('Case Sensitive') case_search_option.setCheckable(True) case_search_option.setChecked(app_constants.GALLERY_SEARCH_CASE) case_search_option.toggled.connect(set_search_case) strict_search_option = search_options_menu.addAction('Match whole terms') strict_search_option.setCheckable(True) strict_search_option.setChecked(app_constants.GALLERY_SEARCH_STRICT) strict_search_option.toggled.connect(set_search_strict) self.search_bar.setObjectName('search_bar') self.search_timer = QTimer(self) self.search_timer.setSingleShot(True) self.search_timer.timeout.connect(lambda: self.search(self.search_bar.text())) self._search_cursor_pos = [0, 0] def set_cursor_pos(old, new): self._search_cursor_pos[0] = old self._search_cursor_pos[1] = new self.search_bar.cursorPositionChanged.connect(set_cursor_pos) if app_constants.SEARCH_AUTOCOMPLETE: completer = QCompleter(self) completer_view = misc.CompleterPopupView() completer.setPopup(completer_view) completer_view._setup() completer.setModel(self.manga_list_view.gallery_model) completer.setCaseSensitivity(Qt.CaseInsensitive) completer.setCompletionMode(QCompleter.PopupCompletion) completer.setCompletionRole(Qt.DisplayRole) completer.setCompletionColumn(app_constants.TITLE) completer.setFilterMode(Qt.MatchContains) self.search_bar.setCompleter(completer) self.search_bar.returnPressed.connect(lambda: self.search(self.search_bar.text())) if not app_constants.SEARCH_ON_ENTER: self.search_bar.textEdited.connect(lambda: self.search_timer.start(800)) self.search_bar.setPlaceholderText("Search title, artist, namespace & tags") self.search_bar.setMinimumWidth(150) self.search_bar.setMaximumWidth(500) self.search_bar.setFixedHeight(19) self.manga_list_view.sort_model.HISTORY_SEARCH_TERM.connect(lambda a: self.search_bar.setText(a)) self.toolbar.addWidget(self.search_bar) def search_history(_, back=True): # clicked signal passes a bool sort_model = self.manga_list_view.sort_model nav = sort_model.PREV if back else sort_model.NEXT history_term = sort_model.navigate_history(nav) if back: self.search_forward.setVisible(True) back = QShortcut(QKeySequence(QKeySequence.Back), self, lambda: search_history(None)) forward = QShortcut(QKeySequence(QKeySequence.Forward), self, lambda: search_history(None, False)) search_backbutton = QToolButton(self.toolbar) search_backbutton.setText(u'\u25C0') search_backbutton.setFixedWidth(15) search_backbutton.clicked.connect(search_history) self.search_backward = self.toolbar.addWidget(search_backbutton) self.search_backward.setVisible(False) search_forwardbutton = QToolButton(self.toolbar) search_forwardbutton.setText(u'\u25B6') search_forwardbutton.setFixedWidth(15) search_forwardbutton.clicked.connect(lambda: search_history(None, False)) self.search_forward = self.toolbar.addWidget(search_forwardbutton) self.search_forward.setVisible(False) spacer_end = QWidget() # aligns settings action properly spacer_end.setFixedSize(QSize(10, 1)) self.toolbar.addWidget(spacer_end) settings_act = QToolButton(self.toolbar) settings_act.setIcon(QIcon(app_constants.SETTINGS_PATH)) settings_act.clicked.connect(self.settings) self.toolbar.addWidget(settings_act) spacer_end2 = QWidget() # aligns About action properly spacer_end2.setFixedSize(QSize(5, 1)) self.toolbar.addWidget(spacer_end2) self.addToolBar(self.toolbar)
def __init__(self, parent, node, active_data_type_detector): super(SubscriberWindow, self).__init__(parent) self.setWindowTitle(self.WINDOW_NAME_PREFIX) self.setAttribute(Qt.WA_DeleteOnClose) # This is required to stop background timers! self._node = node self._active_data_type_detector = active_data_type_detector self._active_data_type_detector.message_types_updated.connect(self._update_data_type_list) self._message_queue = queue.Queue() self._subscriber_handle = None self._update_timer = QTimer(self) self._update_timer.setSingleShot(False) self._update_timer.timeout.connect(self._do_redraw) self._update_timer.start(100) self._log_viewer = QPlainTextEdit(self) self._log_viewer.setReadOnly(True) self._log_viewer.setLineWrapMode(QPlainTextEdit.NoWrap) self._log_viewer.setFont(get_monospace_font()) self._log_viewer.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn) try: self._log_viewer.setPlaceholderText('Received messages will be printed here in YAML format') except AttributeError: # Old PyQt pass self._num_rows_spinbox = QSpinBox(self) self._num_rows_spinbox.setToolTip('Number of rows to display; large number will impair performance') self._num_rows_spinbox.valueChanged.connect( lambda: self._log_viewer.setMaximumBlockCount(self._num_rows_spinbox.value())) self._num_rows_spinbox.setMinimum(1) self._num_rows_spinbox.setMaximum(1000000) self._num_rows_spinbox.setValue(100) self._num_errors = 0 self._num_messages_total = 0 self._num_messages_past_filter = 0 self._msgs_per_sec_estimator = RateEstimator() self._num_messages_total_label = QuantityDisplay(self, 'Total', 'msgs') self._num_messages_past_filter_label = QuantityDisplay(self, 'Accepted', 'msgs') self._msgs_per_sec_label = QuantityDisplay(self, 'Accepting', 'msg/sec') self._type_selector = CommitableComboBoxWithHistory(self) self._type_selector.setToolTip('Name of the message type to subscribe to') self._type_selector.setInsertPolicy(QComboBox.NoInsert) completer = QCompleter(self._type_selector) completer.setCaseSensitivity(Qt.CaseSensitive) completer.setModel(self._type_selector.model()) self._type_selector.setCompleter(completer) self._type_selector.on_commit = self._do_start self._type_selector.setFont(get_monospace_font()) self._type_selector.setSizeAdjustPolicy(QComboBox.AdjustToContents) self._type_selector.setFocus(Qt.OtherFocusReason) self._active_filter = None self._filter_bar = FilterBar(self) self._filter_bar.on_filter = self._install_filter self._start_stop_button = make_icon_button('video-camera', 'Begin subscription', self, checkable=True, on_clicked=self._toggle_start_stop) self._pause_button = make_icon_button('pause', 'Pause updates, non-displayed messages will be queued in memory', self, checkable=True) self._clear_button = make_icon_button('trash-o', 'Clear output and reset stat counters', self, on_clicked=self._do_clear) self._show_all_message_types = make_icon_button('puzzle-piece', 'Show all known message types, not only those that are ' 'currently being exchanged over the bus', self, checkable=True, on_clicked=self._update_data_type_list) layout = QVBoxLayout(self) controls_layout = QHBoxLayout(self) controls_layout.addWidget(self._start_stop_button) controls_layout.addWidget(self._pause_button) controls_layout.addWidget(self._clear_button) controls_layout.addWidget(self._filter_bar.add_filter_button) controls_layout.addWidget(self._show_all_message_types) controls_layout.addWidget(self._type_selector, 1) controls_layout.addWidget(self._num_rows_spinbox) layout.addLayout(controls_layout) layout.addWidget(self._filter_bar) layout.addWidget(self._log_viewer, 1) stats_layout = QHBoxLayout(self) stats_layout.addWidget(self._num_messages_total_label) stats_layout.addWidget(self._num_messages_past_filter_label) stats_layout.addWidget(self._msgs_per_sec_label) layout.addLayout(stats_layout) self.setLayout(layout) # Initial updates self._update_data_type_list()
def init_toolbar(self): self.toolbar = QToolBar() self.toolbar.setFixedHeight(25) self.toolbar.setWindowTitle("Show") # text for the contextmenu # self.toolbar.setStyleSheet("QToolBar {border:0px}") # make it user defined? self.toolbar.setMovable(False) self.toolbar.setFloatable(False) # self.toolbar.setIconSize(QSize(20,20)) self.toolbar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) spacer_start = QWidget() # aligns the first actions properly spacer_start.setFixedSize(QSize(10, 1)) self.toolbar.addWidget(spacer_start) favourite_view_icon = QIcon(gui_constants.STAR_BTN_PATH) favourite_view_action = QAction(favourite_view_icon, "Favorites", self) favourite_view_action.setToolTip("Show only favourite galleries") favourite_view_action.triggered.connect(self.favourite_display) # need lambda to pass extra args self.toolbar.addAction(favourite_view_action) catalog_view_icon = QIcon(gui_constants.HOME_BTN_PATH) catalog_view_action = QAction(catalog_view_icon, "Library", self) catalog_view_action.setToolTip("Show all your galleries") # catalog_view_action.setText("Catalog") catalog_view_action.triggered.connect(self.catalog_display) # need lambda to pass extra args self.toolbar.addAction(catalog_view_action) self.toolbar.addSeparator() gallery_menu = QMenu() gallery_action = QToolButton() gallery_action.setText("Gallery ") gallery_action.setPopupMode(QToolButton.InstantPopup) gallery_action.setToolTip("Contains various gallery related features") gallery_action.setMenu(gallery_menu) add_gallery_icon = QIcon(gui_constants.PLUS_PATH) gallery_action_add = QAction(add_gallery_icon, "Add gallery", self) gallery_action_add.triggered.connect(self.manga_list_view.SERIES_DIALOG.emit) gallery_action_add.setToolTip("Add a single gallery thoroughly") gallery_menu.addAction(gallery_action_add) add_more_action = QAction(add_gallery_icon, "Add galleries...", self) add_more_action.setStatusTip("Add galleries from different folders") add_more_action.triggered.connect(lambda: self.populate(True)) gallery_menu.addAction(add_more_action) populate_action = QAction(add_gallery_icon, "Populate from folder...", self) populate_action.setStatusTip("Populates the DB with galleries from a single folder") populate_action.triggered.connect(self.populate) gallery_menu.addAction(populate_action) gallery_menu.addSeparator() metadata_action = QAction("Get metadata for all galleries", self) metadata_action.triggered.connect(self.get_metadata) gallery_menu.addAction(metadata_action) self.toolbar.addWidget(gallery_action) self.toolbar.addSeparator() misc_action = QToolButton() misc_action.setText("Misc ") misc_action_menu = QMenu() misc_action.setMenu(misc_action_menu) misc_action.setPopupMode(QToolButton.InstantPopup) misc_action.setToolTip("Contains misc. features") misc_action_random = QAction("Open random gallery", misc_action_menu) misc_action_random.triggered.connect(self.manga_list_view.open_random_gallery) misc_action_menu.addAction(misc_action_random) duplicate_check_simple = QAction("Simple duplicate finder", misc_action_menu) duplicate_check_simple.triggered.connect(lambda: self.manga_list_view.duplicate_check()) misc_action_menu.addAction(duplicate_check_simple) self.toolbar.addWidget(misc_action) spacer_middle = QWidget() # aligns buttons to the right spacer_middle.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.toolbar.addWidget(spacer_middle) self.grid_toggle_g_icon = QIcon(gui_constants.GRID_PATH) self.grid_toggle_l_icon = QIcon(gui_constants.LIST_PATH) self.grid_toggle = QToolButton() if self.display.currentIndex() == self.m_l_view_index: self.grid_toggle.setIcon(self.grid_toggle_l_icon) else: self.grid_toggle.setIcon(self.grid_toggle_g_icon) self.grid_toggle.setObjectName("gridtoggle") self.grid_toggle.clicked.connect(self.toggle_view) self.toolbar.addWidget(self.grid_toggle) self.search_bar = misc.LineEdit() if gui_constants.SEARCH_AUTOCOMPLETE: completer = QCompleter(self) completer.setModel(self.manga_list_view.gallery_model) completer.setCaseSensitivity(Qt.CaseInsensitive) completer.setCompletionMode(QCompleter.PopupCompletion) completer.setCompletionRole(Qt.DisplayRole) completer.setCompletionColumn(gui_constants.TITLE) completer.setFilterMode(Qt.MatchContains) self.search_bar.setCompleter(completer) if gui_constants.SEARCH_ON_ENTER: self.search_bar.returnPressed.connect(lambda: self.search(self.search_bar.text())) else: self.search_bar.textChanged[str].connect(self.search) self.search_bar.setPlaceholderText("Search title, artist, namespace & tags") self.search_bar.setMinimumWidth(150) self.search_bar.setMaximumWidth(500) self.toolbar.addWidget(self.search_bar) self.toolbar.addSeparator() settings_icon = QIcon(gui_constants.SETTINGS_PATH) settings_action = QAction("Set&tings", self) settings_action.triggered.connect(self.settings) self.toolbar.addAction(settings_action) spacer_end = QWidget() # aligns About action properly spacer_end.setFixedSize(QSize(10, 1)) self.toolbar.addWidget(spacer_end) self.addToolBar(self.toolbar)
class ZoomToPostcode: """QGIS Plugin Implementation.""" METADATA_URL = "http://qgis.locationcentre.co.uk/ZoomToPostcode_medata.xml" POSTCODE_URL = "http://qgis.locationcentre.co.uk/UK_Postcodes.zip" def __init__(self, iface): """Constructor. :param iface: An interface instance that will be passed to this class which provides the hook by which you can manipulate the QGIS application at run time. :type iface: QgsInterface """ # Save reference to the QGIS interface self.iface = iface self.canvas = iface.mapCanvas() # initialize plugin directory self.plugin_dir = path.dirname(__file__) # initialize locale locale = QSettings().value('locale/userLocale')[0:2] locale_path = path.join( self.plugin_dir, 'i18n', 'ZoomToPostcode_{}.qm'.format(locale)) if path.exists(locale_path): self.translator = QTranslator() self.translator.load(locale_path) if qVersion() > '4.3.3': QCoreApplication.installTranslator(self.translator) # Create the dialog (after translation) and keep reference self.dlg = ZoomToPostcodeDialog() # Create licence dlg self.licence_dlg = LicenceDialog() # Create various class references self.marker = None self.completer = None self.previous_searches = [] # Declare instance attributes self.actions = [] self.menu = self.tr(u'&Zoom To Postcode') self.toolbar = self.iface.addToolBar(u'ZoomToPostcode') self.toolbar.setObjectName(u'ZoomToPostcode') # noinspection PyMethodMayBeStatic def tr(self, message): """Get the translation for a string using Qt translation API. We implement this ourselves since we do not inherit QObject. :param message: String for translation. :type message: str, QString :returns: Translated version of message. :rtype: QString """ # noinspection PyTypeChecker,PyArgumentList,PyCallByClass return QCoreApplication.translate('ZoomToPostcode', message) def add_action( self, icon_path, text, callback, enabled_flag=True, add_to_menu=True, add_to_toolbar=True, status_tip=None, whats_this=None, parent=None): """Add a toolbar icon to the toolbar.""" icon = QIcon(icon_path) action = QAction(icon, text, parent) action.triggered.connect(callback) action.setEnabled(enabled_flag) if status_tip is not None: action.setStatusTip(status_tip) if whats_this is not None: action.setWhatsThis(whats_this) if add_to_toolbar: self.toolbar.addAction(action) if add_to_menu: self.iface.addPluginToMenu( self.menu, action) self.actions.append(action) return action def initGui(self): """Create the menu entries and toolbar icons inside the QGIS GUI.""" icon_path = ':/plugins/zoom_to_postcode/icon.png' self.add_action( icon_path, text=self.tr(u'Zoom to postcode'), callback=self.run, parent=self.iface.mainWindow()) # Configure toolbar widget self.toolbar = self.iface.addToolBar("Zoom To Postcode Toolbar") self.toolbar.setObjectName("Zoom To Postcode Toolbar") self.toolbar_search = QLineEdit() self.toolbar_search.setMaximumWidth(100) self.toolbar_search.setAlignment(Qt.AlignLeft) self.toolbar_search.setPlaceholderText("Enter postcode...") self.toolbar.addWidget(self.toolbar_search) self.toolbar_search.returnPressed.connect(self.check_pkl) self.search_btn = QAction(QIcon(":/plugins/zoomtopostcode/zoomicon.png"), "Search", self.iface.mainWindow()) self.search_btn.triggered.connect(self.check_pkl) self.toolbar.addActions([self.search_btn]) # Create action that will start plugin configuration self.action = QAction(QIcon(":/plugins/zoomtopostcode/zoomicon.png"), u"Zoom to Postcode", self.iface.mainWindow()) self.action.triggered.connect(self.toolbar.show) self.licence = QAction(u"OS Licence", self.iface.mainWindow()) self.licence.triggered.connect(self.licence_dlg.show) # Add toolbar button and menu item self.iface.addPluginToMenu(u"&Zoom to Postcode", self.action) self.iface.addPluginToMenu(u"&Zoom to Postcode", self.licence) def unload(self): """Removes the plugin menu item and icon from QGIS GUI.""" for action in self.actions: self.iface.removePluginMenu( self.tr(u'&Zoom To Postcode'), action) self.iface.removeToolBarIcon(action) # remove the toolbar del self.toolbar def run(self): """Show the toolbar dialog.""" self.dlg.show() def search_completer(self): self.completer = QCompleter(self.previous_searches, self.iface.mainWindow()) self.completer.setCompletionMode(QCompleter.PopupCompletion) self.completer.setCaseSensitivity(Qt.CaseInsensitive) def check_crs(self): """Check if a transformation needs to take place. :return: None """ srs = self.canvas.mapSettings().destinationCrs() current_crs = srs.authid() return current_crs def transform(self, cor): """Transforms point from british nation grid to map crs. :param cor: Coords :return: Point """ srs = self.canvas.mapSettings().destinationCrs() crs_src = QgsCoordinateReferenceSystem(27700) crs_dest = QgsCoordinateReferenceSystem(srs) xform = QgsCoordinateTransform(crs_src, crs_dest, QgsProject.instance()) x, y = cor t_point = xform.transform(float(x), float(y)) return t_point def check_pkl(self): """Check the Pickle postcode dir exists. :return: None """ checkpkl = path.isdir(path.join(self.plugin_dir, 'UK_Postcodes')) if checkpkl: xml_path = path.join(self.plugin_dir, r'UK_Postcodes/metadata.xml') check_xml = path.isfile(xml_path) if check_xml: check_currency = self.check_pcode_date(xml_path) if check_currency: self.postcode_dict() else: self.update_pcode_option() else: self.update_pcode_option() else: msg = "Postcode files must be downloaded to use this plugin, do you wish to continue?" goahead = QMessageBox.question(self.iface.mainWindow(), "Download Message", msg, QMessageBox.Yes, QMessageBox.No) if goahead == QMessageBox.Yes: self.download_pkl() else: pass def check_pcode_date(self, xml_path): """Parses metadata xml to check currency of pcodes. :param xml_path: Full path to xml file. :return: True for up-to-date postcodes, False requires download to update """ try: http = urllib3.PoolManager() r = http.request('GET', self.METADATA_URL, retries=3) xml_as_string = ET.fromstring(r.data.decode('utf-8')) tree_web = ET.ElementTree(xml_as_string) root_web = tree_web.getroot() current_version = "" for child in root_web: if child.tag == "pcode_date": current_version = child.text tree_plugin = ET.parse(xml_path) root_plugin = tree_plugin.getroot() last_update = "" for child in root_plugin: if child.tag == "pcode_date": last_update = child.text last_up_datetime = datetime.strptime(last_update, '%Y-%m-%d') curr_ver_datetime = datetime.strptime(current_version, '%Y-%m-%d') if last_up_datetime.date() >= curr_ver_datetime.date(): return True else: return False except urllib3.exceptions.MaxRetryError: QMessageBox.information(self.iface.mainWindow(), "HTTP Error", "Unable to download file") def update_pcode_option(self): """Provide option to update postcodes. :return: None """ msg = "Updated postcode files are available, do you wish to download?" goahead = QMessageBox.question(self.iface.mainWindow(), "Download Message", msg, QMessageBox.Yes, QMessageBox.No) if goahead == QMessageBox.Yes: self.download_pkl() if goahead == QMessageBox.No: self.postcode_dict() def download_pkl(self): """Download the Pickle postcode file to the plugin dir. :return: None """ pcode_path = path.join(path.dirname(__file__), 'UK_Postcodes') if not path.exists(pcode_path): makedirs(pcode_path) try: http = urllib3.PoolManager() response = http.request('GET', self.POSTCODE_URL, preload_content=False, retries=3) content_length = response.headers['Content-Length'] total_size = int(content_length) downloaded = 0 CHUNK = 256 * 10240 dlbar = QProgressBar() dlbar.setMinimum(0) dlbar.setMaximum(total_size) zip_temp = tempfile.NamedTemporaryFile(mode='w+b', suffix='.zip', delete=False) zip_temp_n = zip_temp.name zip_temp.seek(0) with open(zip_temp_n, 'wb') as fp: while True: dlbar.show() chunk = response.read(CHUNK) downloaded += len(chunk) dlbar.setValue(downloaded) if not chunk: break fp.write(chunk) response.release_conn() pcode_zip = ZipFile(zip_temp) pcode_zip.extractall(pcode_path) zip_temp.close() self.check_pkl() except urllib3.exceptions.MaxRetryError: QMessageBox.information(self.iface.mainWindow(), "HTTP Error", "Unable to download file") def postcode_dict(self): """Create dictionary of postcodes from correct Pickle file. :return: None """ try: input_pcode = self.toolbar_search.text().replace(' ', '') if input_pcode[1].isdigit(): find_pkl = str(r"UK_Postcodes/" + input_pcode[:1] + ".pkl") else: find_pkl = str(r"UK_Postcodes/" + input_pcode[:2] + ".pkl") pklfile = open(path.join(path.dirname(__file__), find_pkl), 'rb') pcode_dict = pickle.load(pklfile) pklfile.close() if input_pcode.upper() not in self.previous_searches: self.previous_searches.append(input_pcode.upper()) self.search_completer() self.toolbar_search.setCompleter(self.completer) self.zoomto(pcode_dict) except (KeyError, IOError): QMessageBox.information(self.iface.mainWindow(), "Invalid postcode", "The postcode you entered was not found") except IndexError: pass def zoomto(self, pcode_dict): """Find the coordinates for postcode in the dictionary. :param pcode_dict: :return: None """ current_crs = self.check_crs() input_pc = self.toolbar_search.text() input_pc_fmt = str(input_pc).replace(' ', '').upper() coords = pcode_dict[input_pc_fmt] x, y = coords if current_crs != "EPSG:27700": cor = (x, y) point = self.transform(cor) self.update_canvas(point) else: point = (x, y) self.update_canvas(point) def update_canvas(self, point): """Update the canvas and add vertex marker. :param point: :return: None """ x, y = point scale = 120 rect = QgsRectangle(float(x) - scale, float(y) - scale, float(x) + scale, float(y) + scale) self.canvas.setExtent(rect) self.marker = QgsVertexMarker(self.canvas) self.marker.setIconSize(15) self.marker.setPenWidth(2) self.marker.setCenter(QgsPointXY(int(x), int(y))) self.canvas.refresh() self.canvas.extentsChanged.connect(self.remove_marker) def remove_marker(self): """Remove vertex marker. :return: None """ self.marker.hide() self.canvas.scene().removeItem(self.marker) self.canvas.extentsChanged.disconnect(self.remove_marker)
class EditerIdeeViewChild(Ui_DialogEditerIdee): role_etat = Qt.UserRole + 5 def __init__(self): self.dialog = None self.idee: Idee = None self.completer_text_delegue: QCompleter = None def setup_ui_with_idee(self, dialog_editer_idee, idee: Idee): """ Caharge la fenetre :param dialog_editer_idee: la boite de dialogue :param idee: l'idée devant être modifiée :return: """ Ui_DialogEditerIdee.setupUi(self, dialog_editer_idee) # Evenements self.buttonEditerEtapes.clicked.connect(self.__open_etape) self.buttonValider.clicked.connect(self.__editer_action) self.textDelegue.textEdited.connect(self.__autocomplete_delegue) # AutoComplete Deleguation self.completer_text_delegue = QCompleter(self.textDelegue) self.completer_text_delegue.setCaseSensitivity( QtCore.Qt.CaseInsensitive) self.completer_text_delegue.setCompletionMode( QCompleter.PopupCompletion) self.completer_text_delegue.setWrapAround(False) self.textDelegue.setCompleter(self.completer_text_delegue) # populate QComboBox model = QStandardItemModel(self.comboEtat) model.clear() for etat in Etat: item = QStandardItem(etat.name) item.setData(etat, self.role_etat) model.appendRow(item) self.comboEtat.setModel(model) self.comboEtat.show() # mise en mémoire des infos récuéré self.dialog = dialog_editer_idee self.idee = ControllerView.get_idee_fm_db(idee) # affichage self.__afficher_idee() def __afficher_idee(self): """ Rempli les élements à partir de l'idée demandée :return: """ self.__select_etat_combobox(Etat(self.idee.etat)) self.labelDate.setText( self.idee.dateCreation.strftime('%d/%m/%Y %H:%M:%S')) self.textIdee.setPlainText(self.idee.texte) self.textCommentaire.setPlainText(self.idee.commentaire) if self.idee.delegue and self.idee.delegue.nom: self.textDelegue.setText(self.idee.delegue.nom) def __open_etape(self): """ Ouvre la dialgoue des étapes :return: """ dialog_etapes = QtWidgets.QDialog(self.dialog) ui = GererActionViewChild() ui.setup_ui_with_idee(dialog_etapes, self.idee) dialog_etapes.exec_() def __autocomplete_delegue(self): """ Autocomplete sur le champ Délègue :return: """ result = controllerDelegue.rechercher_personne_delegue( self.textDelegue.text()) self.completer_text_delegue.setModel(QStringListModel(result)) if self.textDelegue.text(): self.__select_etat_combobox(Etat.DELEGUER) def __editer_action(self): """ Modifie une idée en controlant les champs :return: """ if not self.textIdee.toPlainText(): error = QMessageBox() error.setIcon(QMessageBox.Warning) error.setText("Le champ idée doit être rempli") error.setWindowTitle("Erreur") error.setStandardButtons(QMessageBox.Ok) error.exec_() return if (self.textDelegue.text() and self.comboEtat.currentText() != Etat.DELEGUER.name) or \ (not self.textDelegue.text() and self.comboEtat.currentText() == Etat.DELEGUER.name): error = QMessageBox() error.setIcon(QMessageBox.Warning) error.setText( "Si la tâche est déléguée, son état doit être à l'état délégué" ) error.setWindowTitle("Erreur") error.setStandardButtons(QMessageBox.Ok) error.exec_() return ControllerView.modifier_idee( self.idee.id, self.textIdee.toPlainText(), self.textDelegue.text(), self.textCommentaire.toPlainText(), self.comboEtat.currentData(self.role_etat)) self.dialog.close() def __select_etat_combobox(self, etat: Etat): """ Chnage l'état sélectionné par la comboBox :param etat: l'état à sélectionner :return: """ index = self.comboEtat.findText(etat.name, QtCore.Qt.MatchFixedString) if index >= 0: self.comboEtat.setCurrentIndex(index)
def completer(): dados = Item.tabela["nome"].copy() dados = dados.sort_values() completer = QCompleter(dados.str.title().unique()) completer.setCaseSensitivity(Qt.CaseInsensitive) gui.ui.lineProcurar.setCompleter(completer)
class IDClient(QWidget): my_shutdown_signal = pyqtSignal(int) def __init__(self): super().__init__() def getToWork(self, mess): global messenger messenger = mess # Save the local temp directory for image files and the class list. self.workingDirectory = directoryPath # List of papers we have to ID. self.paperList = [] # Fire up the interface. self.ui = Ui_IdentifyWindow() self.ui.setupUi(self) # Paste username into the GUI (TODO: but why?) self.ui.userLabel.setText(mess.whoami()) # Exam model for the table of papers - associate to table in GUI. self.exM = ExamModel() self.ui.tableView.setModel(self.exM) # A view window for the papers so user can zoom in as needed. # Paste into appropriate location in gui. self.testImg = ExamViewWindow() self.ui.gridLayout_7.addWidget(self.testImg, 0, 0) # Get the classlist from server for name/ID completion. try: self.getClassList() except PlomSeriousException as err: self.throwSeriousError(err) return # Init the name/ID completers and a validator for ID self.setCompleters() # Get the predicted list from server for ID guesses. try: self.getPredictions() except PlomSeriousException as err: self.throwSeriousError(err) return # Connect buttons and key-presses to functions. self.ui.idEdit.returnPressed.connect(self.enterID) self.ui.closeButton.clicked.connect(self.shutDown) self.ui.nextButton.clicked.connect(self.skipOnClick) self.ui.predButton.clicked.connect(self.acceptPrediction) self.ui.blankButton.clicked.connect(self.blankPaper) self.ui.viewButton.clicked.connect(self.viewWholePaper) # Make sure no button is clicked by a return-press self.ui.nextButton.setAutoDefault(False) self.ui.closeButton.setAutoDefault(False) # Make sure window is maximised and request a paper from server. self.showMaximized() # Get list of papers already ID'd and add to table. try: self.getAlreadyIDList() except PlomSeriousException as err: self.throwSeriousError(err) return # Connect the view **after** list updated. # Connect the table's model sel-changed to appropriate function. self.ui.tableView.selectionModel().selectionChanged.connect( self.selChanged) self.requestNext() # make sure exam view window's view is reset.... self.testImg.forceRedrawOrSomeBullshit() # Create variable to store ID/Name conf window position # Initially set to top-left corner of window self.msgGeometry = None def throwSeriousError(self, err): ErrorMessage( 'A serious error has been thrown:\n"{}".\nCannot recover from this, so shutting down identifier.' .format(err)).exec_() self.shutDownError() raise (err) def throwBenign(self, err): ErrorMessage( 'A benign exception has been thrown:\n"{}".'.format(err)).exec_() def skipOnClick(self): """Skip the current, moving to the next or loading a new one""" index = self.ui.tableView.selectedIndexes() if len(index) == 0: return r = index[0].row() # which row is selected if r == self.exM.rowCount() - 1: # the last row is selected. if self.requestNext(): return self.moveToNextUnID() def getClassList(self): """Get the classlist from the server. Returns nothing but modifies the state of self, adding two dicts to the class data: `student_id_to_name_map` Maps unique ID (str) to name (str). `student_name_to_idlist` Names are not unique so we map each name to a list of IDs. """ # a list of pairs [sid, sname] self.student_id_and_name_list = messenger.IDrequestClasslist() # use 'snid' to mean "student_id_and_name" as one string. self.snid_to_student_id = dict() self.snid_to_student_name = dict() # also need id to snid for predictionlist wrangling. self.student_id_to_snid = dict() name_list = [] for sid, sname in self.student_id_and_name_list: snid = "{}: {}".format(sid, sname) self.snid_to_student_id[snid] = sid self.snid_to_student_name[snid] = sname self.student_id_to_snid[sid] = snid if sname in name_list: log.warning('Just FYI: multiple students with name "%s"', censorName(sname)) def getPredictions(self): """Send request for prediction list (iRPL) to server. The server then sends back the CSV of the predictions testnumber -> studentID. """ # Send request for prediction list to server csvfile = messenger.IDrequestPredictions() # create dictionary from the prediction list self.predictedTestToNumbers = defaultdict(int) reader = csv.DictReader(csvfile, skipinitialspace=True) for row in reader: self.predictedTestToNumbers[int(row["test"])] = str(row["id"]) # Also tweak font size fnt = self.font() fnt.setPointSize(fnt.pointSize() * 2) self.ui.pNameLabel.setFont(fnt) # also tweak size of "accept prediction" button font self.ui.predButton.setFont(fnt) # make the SID larger still. fnt.setPointSize(fnt.pointSize() * 1.5) self.ui.pSIDLabel.setFont(fnt) # And if no predictions then hide that box if len(self.predictedTestToNumbers) == 0: self.ui.predictionBox.hide() return True def setCompleters(self): """Set up the studentname + studentnumber line-edit completers. Means that user can enter the first few numbers (or letters) and be prompted with little pop-up with list of possible completions. """ # Build stringlistmodels - one for combined student_name_and_id = snid self.snidlist = QStringListModel() # Feed in the numbers and names. self.snidlist.setStringList(list(self.snid_to_student_id.keys())) # Build the snid-completer = substring matching and case insensitive self.snidcompleter = QCompleter() self.snidcompleter.setModel(self.snidlist) self.snidcompleter.setCaseSensitivity(Qt.CaseInsensitive) self.snidcompleter.setFilterMode(Qt.MatchContains) # Link the ID-completer to the ID-lineedit in the gui. self.ui.idEdit.setCompleter(self.snidcompleter) # Make sure lineedit has little "Clear this" button. self.ui.idEdit.setClearButtonEnabled(True) def shutDownError(self): self.my_shutdown_signal.emit(1) self.close() def shutDown(self): """Send the server a DNF (did not finish) message so it knows to take anything that this user has out-for-id-ing and return it to the todo pile. Then send a user-closing message so that the authorisation token is removed. Then finally close. TODO: messenger needs to drop token here? """ self.DNF() try: messenger.closeUser() except PlomSeriousException as err: self.throwSeriousError(err) self.my_shutdown_signal.emit(1) self.close() def DNF(self): """Send the server a "did not finished" message for each paper in the list that has not been ID'd. The server will put these back onto the todo-pile. """ # Go through each entry in the table - it not ID'd then send a DNF # to the server. rc = self.exM.rowCount() for r in range(rc): if self.exM.data(self.exM.index(r, 1)) != "identified": # Tell user DNF, user, auth-token, and paper's code. try: messenger.IDdidNotFinishTask( self.exM.data(self.exM.index(r, 0))) except PlomSeriousException as err: self.throwSeriousError(err) def getAlreadyIDList(self): # Ask server for list of previously ID'd papers idList = messenger.IDrequestDoneTasks() for x in idList: self.addPaperToList( Paper(x[0], fnames=[], stat="identified", id=x[1], name=x[2]), update=False, ) def selChanged(self, selnew, selold): # When the selection changes, update the ID and name line-edit boxes # with the data from the table - if it exists. # Update the displayed image with that of the newly selected test. self.ui.idEdit.setText(self.exM.data(selnew.indexes()[2])) self.updateImage(selnew.indexes()[0].row()) self.ui.idEdit.setFocus() def checkFiles(self, r): # grab the selected tgv test = self.exM.paperList[r].test # check if we have a copy if len(self.exM.paperList[r].originalFiles) > 0: return # else try to grab it from server try: imageList = messenger.IDrequestImage(test) except PlomSeriousException as e: self.throwSeriousError(e) return except PlomBenignException as e: self.throwBenign(e) # self.exM.removePaper(r) return # Image names = "i<testnumber>.<imagenumber>.<ext>" inames = [] for i in range(len(imageList)): tmp = os.path.join(self.workingDirectory, "i{}.{}.image".format(test, i)) inames.append(tmp) with open(tmp, "wb+") as fh: fh.write(imageList[i]) self.exM.paperList[r].originalFiles = inames def updateImage(self, r=0): # Here the system should check if imagefile exist and grab if needed. self.checkFiles(r) # Update the test-image pixmap with the image in the indicated file. self.testImg.updateImage(self.exM.paperList[r].originalFiles) # update the prediction if present tn = int(self.exM.paperList[r].test) if tn in self.predictedTestToNumbers: psid = self.predictedTestToNumbers[tn] # predicted student ID psnid = self.student_id_to_snid[psid] # predicted SNID pname = self.snid_to_student_name[psnid] # predicted student name if pname == "": self.ui.predictionBox.hide() else: self.ui.predictionBox.show() self.ui.pSIDLabel.setText(psid) self.ui.pNameLabel.setText(pname) else: self.ui.pSIDLabel.setText("") self.ui.pNameLabel.setText("") # now update the snid entry line-edit. # if test is already identified then populate the idlinedit accordingly if self.exM.paperList[r].status == "identified": snid = "{}: {}".format(self.exM.paperList[r].sid, self.exM.paperList[r].sname) self.ui.idEdit.setText(snid) else: # leave it blank. self.ui.idEdit.clear() self.ui.idEdit.setFocus() def addPaperToList(self, paper, update=True): # Add paper to the exam-table-model - get back the corresponding row. r = self.exM.addPaper(paper) # select that row and display the image if update: # One more unid'd paper self.ui.tableView.selectRow(r) self.updateImage(r) def updateProgress(self): # update progressbars try: v, m = messenger.IDprogressCount() except PlomSeriousException as err: self.throwSeriousError(err) if m == 0: v, m = (0, 1) # avoid (0, 0) indeterminate animation self.ui.idProgressBar.setFormat("No papers to identify") ErrorMessage("No papers to identify.").exec_() else: self.ui.idProgressBar.resetFormat() self.ui.idProgressBar.setMaximum(m) self.ui.idProgressBar.setValue(v) def requestNext(self): """Ask the server for an unID'd paper. Get file, add to the list of papers and update the image. """ self.updateProgress() attempts = 0 while True: # TODO - remove this little sanity check else replace with a pop-up warning thingy. if attempts >= 5: return False else: attempts += 1 # ask server for ID of next task try: test = messenger.IDaskNextTask() if not test: # no tasks left ErrorMessage("No more tasks left on server.").exec_() return False except PlomSeriousException as err: self.throwSeriousError(err) return False try: imageList = messenger.IDclaimThisTask(test) break except PlomTakenException as err: log.info( "will keep trying as task already taken: {}".format(err)) continue # Image names = "i<testnumber>.<imagenumber>.<ext>" inames = [] for i in range(len(imageList)): tmp = os.path.join(self.workingDirectory, "i{}.{}.image".format(test, i)) inames.append(tmp) with open(tmp, "wb+") as fh: fh.write(imageList[i]) # Add the paper [code, filename, etc] to the list self.addPaperToList(Paper(test, inames)) # Clean up table - and set focus on the ID-lineedit so user can # just start typing in the next ID-number. self.ui.tableView.resizeColumnsToContents() self.ui.idEdit.setFocus() return True def acceptPrediction(self): # first check currently selected paper is unidentified - else do nothing index = self.ui.tableView.selectedIndexes() status = self.exM.data(index[1]) if status != "unidentified": msg = SimpleMessage("Do you want to change the ID?") # Put message popup on top-corner of idenfier window if msg.exec_() == QMessageBox.No: return code = self.exM.data(index[0]) sname = self.ui.pNameLabel.text() sid = self.ui.pSIDLabel.text() if not self.identifyStudent(index, sid, sname): return if index[0].row() == self.exM.rowCount() - 1: # at bottom of table. self.requestNext() # updates progressbars. else: # else move to the next unidentified paper. self.moveToNextUnID() # doesn't self.updateProgress() return def identifyStudent(self, index, sid, sname, blank=False, no_id=False): """Push identification of a paper to the server and misc UI table. User ID's the student of the current paper. Some care around whether or not the paper was ID'd previously. Not called directly - instead is called by "enterID" or "acceptPrediction" when user hits return on the line-edit. Args: index: an index into the UI table of the currently highlighted row. sname (str): The student name or special placeholder. - note that this should always be non-trivial string. sid (str/None): The student ID or None. - note that this is either 'None' (but only if blank or no_id is true), or should have passed the 'is_valid_id' test. blank (bool): the paper was blank: `sid` must be None and `sname` must be `"Blank paper"`. no_id (bool): paper is not blank but student did not fill-in the ID page(s). `sid` must be None and `sname` must be `"No ID given"`. Returns: True/False/None: True on success, False/None on failure. """ # do some sanity checks on inputs. assert isinstance(sname, str), "Student must be a string" assert len(sname) > 0, "Student name cannot be empty" # check that sid is none only when blank or no_id is true if sid is None: assert ( blank or no_id ), "Student ID is only None-type when blank paper or no ID given." # similarly blank only when sid=None and sname = "Blank paper" if blank: assert (sid is None) and ( sname == "Blank paper" ), "Blank should only be true when sid=None and sname = 'Blank paper'" # similarly no_id only when sid=None and sname = "No ID given" if no_id: assert (sid is None) and ( sname == "No ID given" ), "No_id should only be true when sid=None and sname = 'No ID given'" # Pass the info to the exam model to put data into the table. self.exM.identifyStudent(index, sid, sname) code = self.exM.data(index[0]) # Return paper to server with the code, ID, name. try: # TODO - do we need this return value msg = messenger.IDreturnIDdTask(code, sid, sname) except PlomBenignException as err: self.throwBenign(err) # If an error, revert the student and clear things. self.exM.revertStudent(index) return False except PlomSeriousException as err: self.throwSeriousError(err) return # successful ID # Issue #25: Use timer to avoid macOS conflict between completer and # clearing the line-edit. Very annoying but this fixes it. QTimer.singleShot(0, self.ui.idEdit.clear) # Update progressbars self.updateProgress() return True def moveToNextUnID(self): # Move to the next test in table which is not ID'd. rt = self.exM.rowCount() if rt == 0: return rstart = self.ui.tableView.selectedIndexes()[0].row() r = (rstart + 1) % rt # Be careful to not get stuck in loop if all are ID'd. while self.exM.data(self.exM.index(r, 1)) == "identified" and r != rstart: r = (r + 1) % rt self.ui.tableView.selectRow(r) def enterID(self): """Triggered when user hits return in the ID-lineedit.. that is when they have entered a full student ID. """ # check that the student name / id line-edit has some text. if len(self.ui.idEdit.text()) == 0: ErrorMessage( 'Please use the "blank page" button if student has not given their name or ID.' ).exec_() return # if no papers then simply return. if self.exM.rowCount() == 0: return # Grab table-index and code of current test. index = self.ui.tableView.selectedIndexes() code = self.exM.data(index[0]) # No code then return. if code is None: return # Get the status of the test status = self.exM.data(index[1]) alreadyIDd = False # If the paper is already ID'd ask the user if they want to # change it - set the alreadyIDd flag to true. if status == "identified": msg = SimpleMessage("Do you want to change the ID?") # Put message popup on top-corner of idenfier window if msg.exec_() == QMessageBox.No: return else: alreadyIDd = True # Check if the entered SNID (student name and id) is in the list from the classlist. if self.ui.idEdit.text() in self.snid_to_student_id: # Ask user to confirm ID/Name msg = SimpleMessage('Student "{}". Save and move to next?'.format( self.ui.idEdit.text())) # Put message popup in its last location if self.msgGeometry is not None: msg.setGeometry(self.msgGeometry) # If user says "no" then just return from function. if msg.exec_() == QMessageBox.No: self.msgGeometry = msg.geometry() return self.msgGeometry = msg.geometry() snid = self.ui.idEdit.text() sid = self.snid_to_student_id[snid] sname = self.snid_to_student_name[snid] else: # Number is not in class list - ask user if they really want to # enter that number. msg = SimpleMessage( 'Student "{}" not found in classlist. Do you want to input the ID and name manually?' .format(self.ui.idEdit.text())) # Put message popup on top-corner of idenfier window msg.move(self.pos()) # If no then return from function. if msg.exec_() == QMessageBox.No: self.msgPosition = msg.pos() return self.msgPosition = msg.pos() # Otherwise get an id and name from the user (and the okay) snidbox = SNIDBox(self.ui.idEdit.text()) if snidbox.exec_() != QDialog.Accepted: return sid = snidbox.sid.strip() sname = snidbox.sname.strip() # note sid, sname will not be None-types. if not isValidStudentNumber( sid): # this should not happen as snidbox checks. return if not sname: # this should not happen as snidbox checks. return # check if SID is actually in classlist. if sid in self.student_id_to_snid: ErrorMessage('ID "{}" is in class list as "{}"'.format( sid, self.student_id_to_snid[sid])).exec_() return snid = "{}: {}".format(sid, sname) # update our lists self.snid_to_student_id[snid] = sid self.snid_to_student_name[snid] = sname self.student_id_to_snid[sid] = sid # finally update the line-edit. TODO: remove? used to be for identifyStudent call below but not needed anymore? self.ui.idEdit.setText(snid) # Run identify student command (which talks to server) if self.identifyStudent(index, sid, sname): if alreadyIDd: self.moveToNextUnID() return if index[0].row( ) == self.exM.rowCount() - 1: # last row is highlighted if self.requestNext(): return self.moveToNextUnID() def viewWholePaper(self): index = self.ui.tableView.selectedIndexes() if len(index) == 0: return testNumber = self.exM.data(index[0]) try: pageNames, imagesAsBytes = messenger.MrequestWholePaper(testNumber) except PlomBenignException as err: self.throwBenign(err) viewFiles = [] for iab in imagesAsBytes: tfn = tempfile.NamedTemporaryFile(delete=False).name viewFiles.append(tfn) with open(tfn, "wb") as fh: fh.write(iab) WholeTestView(viewFiles).exec_() def blankPaper(self): # first check currently selected paper is unidentified - else do nothing index = self.ui.tableView.selectedIndexes() if len(index) == 0: return status = self.exM.data(index[1]) # if status != "unidentified": # return code = self.exM.data(index[0]) rv = BlankIDBox(self, code).exec_() # return values 0=cancel, 1=blank paper, 2=no id given. if rv == 0: return elif rv == 1: # return with sname ='blank paper', and sid = None self.identifyStudent(index, None, "Blank paper", blank=True) else: # return with sname ='no id given', and sid = None self.identifyStudent(index, None, "No ID given", no_id=True) if index[0].row() == self.exM.rowCount() - 1: # at bottom of table. self.requestNext() # updates progressbars. else: # else move to the next unidentified paper. self.moveToNextUnID() # doesn't self.updateProgress() return
class Spdom(WizardWidget): drag_label = "Spatial Domain <spdom>" acceptable_tags = ['spdom', 'bounding'] ui_class = UI_spdom.Ui_fgdc_spdom def __init__(self, root_widget=None): self.east = 180 self.west = -180 self.north = 90 self.south = -90 self.valid = True super(self.__class__, self).__init__() self.schema = 'bdp' self.root_widget = root_widget self.after_load = False self.in_xml_load = False self.has_rect = True self.completer = QCompleter() self.ui.fgdc_descgeog.setCompleter(self.completer) self.model = QStringListModel() self.completer.setModel(self.model) self.completer.setCaseSensitivity(0) fname = utils.get_resource_path("spatial/BNDCoords.csv") self.bnds_df = pd.read_csv(fname) self.model.setStringList(self.bnds_df['Name']) self.completer.popup().clicked.connect(self.on_completer_activated) self.completer.popup().selectionModel().selectionChanged.connect( self.on_completer_activated) # self.completer.popup().activated.connect(self.on_completer_activated) def build_ui(self): """ Build and modify this widget's GUI Returns ------- None """ self.ui = self.ui_class() self.ui.setupUi(self) if platform.system() == 'Darwin': map_fname = utils.get_resource_path('leaflet/map_mac.html') else: map_fname = utils.get_resource_path('leaflet/map.html') try: self.view = QWebView() self.view.page().mainFrame().addToJavaScriptWindowObject( "Spdom", self) self.view.setUrl(QUrl.fromLocalFile(map_fname)) self.frame = self.view.page().mainFrame() self.view.load( QUrl.fromLocalFile(QtCore.QDir.current().filePath(map_fname))) except AttributeError: self.view = QWebView() self.view.load( QUrl.fromLocalFile(QtCore.QDir.current().filePath(map_fname))) channel = QWebChannel(self.view.page()) jstr = """ var spdom; new QWebChannel(qt.webChannelTransport, function (channel) { spdom = channel.objects.spdom; });""" self.view.page().setWebChannel(channel) self.evaluate_js(jstr) channel.registerObject("spdom", self) self.ui.verticalLayout_3.addWidget(self.view) # setup drag-drop functionality for this widget and all it's children. self.setup_dragdrop(self) self.add_rect() self.raise_() def connect_events(self): self.ui.fgdc_eastbc.editingFinished.connect(self.coord_updated) self.ui.fgdc_westbc.editingFinished.connect(self.coord_updated) self.ui.fgdc_northbc.editingFinished.connect(self.coord_updated) self.ui.fgdc_southbc.editingFinished.connect(self.coord_updated) def on_completer_activated(self, model_index): try: cur_descgeog = model_index.data() except AttributeError: try: cur_descgeog = model_index.indexes()[0].data() except: return try: if self.bnds_df['Name'].str.contains(cur_descgeog).any(): self.ui.fgdc_eastbc.setText( str( float(self.bnds_df[self.bnds_df['Name'] == cur_descgeog]['east']))) self.ui.fgdc_westbc.setText( str( float(self.bnds_df[self.bnds_df['Name'] == cur_descgeog]['west']))) self.ui.fgdc_northbc.setText( str( float(self.bnds_df[self.bnds_df['Name'] == cur_descgeog]['north']))) self.ui.fgdc_southbc.setText( str( float(self.bnds_df[self.bnds_df['Name'] == cur_descgeog]['south']))) self.add_rect() self.update_map() except: pass # this is a convenience function. # If anything at all happens pass silently def complete_name(self): self.view.page().runJavaScript('addRect();', js_callback) def coord_updated(self): good_coords = self.all_good_coords() try: cur_name = self.sender().objectName() if 'fgdc' not in cur_name: return cur_value = self.sender().text() except AttributeError: cur_name = '' cur_value = '' try: cur_value = float(cur_value) except ValueError: pass msg = '' if type(cur_value) != float and cur_value != '': msg = 'number entered must be numeric only' elif cur_value == '': msg = '' elif cur_name in ['fgdc_westbc', 'fgdc_eastbc'] \ and -180 >= cur_value >= 180: msg = 'East or West coordinate must be within -180 and 180' elif cur_name in ['fgdc_southbc', 'fgdc_northbc'] \ and -90 >= cur_value >= 90: msg = 'North and South coordinates must be within -90 and 90' elif cur_name == 'fgdc_southbc': try: north = float(self.ui.fgdc_northbc.text()) if north <= cur_value: msg = 'North coordinate must be greater than South coordinate' except ValueError: pass elif cur_name == 'fgdc_northbc': try: south = float(self.ui.fgdc_southbc.text()) if south >= cur_value: msg = 'North coordinate must be greater than South coordinate' except ValueError: pass if msg: QMessageBox.warning(self, "Problem bounding coordinates", msg) if good_coords: self.add_rect() else: self.remove_rect() return self.update_map() def update_map(self): jstr = """east = {eastbc}; west = {westbc}; south = {southbc}; north = {northbc}; updateMap(); fitMap(); """.format( **{ 'eastbc': self.ui.fgdc_eastbc.text(), 'westbc': self.ui.fgdc_westbc.text(), 'northbc': self.ui.fgdc_northbc.text(), 'southbc': self.ui.fgdc_southbc.text(), }) self.evaluate_js(jstr) def add_rect(self): jstr = """addRect();""" self.evaluate_js(jstr) def remove_rect(self): if self.has_rect: self.has_rect = False jstr = """removeRect()""" self.evaluate_js(jstr) def evaluate_js(self, jstr): """ :param jstr: :return: """ try: self.frame.evaluateJavaScript(jstr) except: self.view.page().runJavaScript(jstr, js_callback) @pyqtSlot(float, float) def on_ne_move(self, lat, lng): if self.in_xml_load: n, e = lat, lng s = float(self.ui.fgdc_southbc.text()) w = float(self.ui.fgdc_westbc.text()) bounds = spatial_utils.format_bounding((w, e, n, s)) self.ui.fgdc_eastbc.setText(bounds[1]) self.ui.fgdc_northbc.setText(bounds[2]) @pyqtSlot(float, float) def on_nw_move(self, lat, lng): if self.in_xml_load: n, w = lat, lng s = float(self.ui.fgdc_southbc.text()) e = float(self.ui.fgdc_eastbc.text()) bounds = spatial_utils.format_bounding((w, e, n, s)) self.ui.fgdc_westbc.setText(bounds[0]) self.ui.fgdc_northbc.setText(bounds[2]) @pyqtSlot(float, float) def on_se_move(self, lat, lng): if self.in_xml_load: s, e = lat, lng n = float(self.ui.fgdc_northbc.text()) w = float(self.ui.fgdc_westbc.text()) bounds = spatial_utils.format_bounding((w, e, n, s)) self.ui.fgdc_eastbc.setText(bounds[1]) self.ui.fgdc_southbc.setText(bounds[3]) @pyqtSlot(float, float) def on_sw_move(self, lat, lng): if self.in_xml_load: s, w = lat, lng n = float(self.ui.fgdc_northbc.text()) e = float(self.ui.fgdc_eastbc.text()) bounds = spatial_utils.format_bounding((w, e, n, s)) self.ui.fgdc_westbc.setText(bounds[0]) self.ui.fgdc_southbc.setText(bounds[3]) def switch_schema(self, schema): self.schema = schema if schema == 'bdp': self.ui.fgdc_descgeog.show() self.ui.descgeog_label.show() self.ui.descgeog_star.show() else: self.ui.fgdc_descgeog.hide() self.ui.descgeog_label.hide() self.ui.descgeog_star.hide() def all_good_coords(self): try: if -180 > float(self.ui.fgdc_westbc.text()) > 180: return False if -180 > float(self.ui.fgdc_eastbc.text()) > 180: return False if -90 > float(self.ui.fgdc_southbc.text()) > 90: return False if -90 > float(self.ui.fgdc_northbc.text()) > 90: return False if float(self.ui.fgdc_northbc.text()) <= float( self.ui.fgdc_southbc.text()): return False return True except: return False def clear_widget(self): super(self.__class__, self).clear_widget() # self.view.page().mainFrame().addToJavaScriptWindowObject("Spdom", self) # map_fname = utils.get_resource_path('leaflet/map.html') # self.view.setUrl(QUrl.fromLocalFile(map_fname)) def showEvent(self, e): if not self.after_load: self.add_rect() self.update_map() jstr = "sw_marker.openPopup();" self.evaluate_js(jstr) self.after_load = True def to_xml(self): spdom = xml_node('spdom') if self.schema == 'bdp': descgeog = xml_node('descgeog', text=self.ui.fgdc_descgeog.text(), parent_node=spdom) bounding = xml_node('bounding', parent_node=spdom) westbc = xml_node('westbc', text=self.ui.fgdc_westbc.text(), parent_node=bounding) eastbc = xml_node('eastbc', text=self.ui.fgdc_eastbc.text(), parent_node=bounding) northbc = xml_node('northbc', text=self.ui.fgdc_northbc.text(), parent_node=bounding) southbc = xml_node('southbc', text=self.ui.fgdc_southbc.text(), parent_node=bounding) if self.original_xml is not None: boundalt = xml_utils.search_xpath(self.original_xml, 'bounding/boundalt') if boundalt is not None: spdom.append(deepcopy(boundalt)) dsgpoly_list = xml_utils.search_xpath(self.original_xml, 'dsgpoly', only_first=False) for dsgpoly in dsgpoly_list: spdom.append(deepcopy(dsgpoly)) return spdom def from_xml(self, spdom): self.in_xml_load = False self.original_xml = spdom self.clear_widget() utils.populate_widget(self, spdom) contents = xml_utils.node_to_dict(spdom, add_fgdc=False) if 'bounding' in contents: contents = contents['bounding'] try: if self.all_good_coords(): self.add_rect() self.update_map() else: self.remove_rect() except KeyError: self.remove_rect() self.in_xml_load = True
def __init__(self, cols: dict, parent=None, address_space: dict=None): super(AnalyzerView, self).__init__(parent) self.cols = cols self.address_space = address_space self.dataformat = {} self.entry = QLineEdit(self) self.entry.setClearButtonEnabled(True) self.entry.setPlaceholderText('Base Address or Register Name') completer = QCompleter() completer.setCaseSensitivity(Qt.CaseInsensitive) completer.setFilterMode(Qt.MatchContains) self.entry.setCompleter(completer) self.entry.setMinimumWidth(500) self.entry.setMinimumHeight(35) self.close_btn = QPushButton('X', self,) self.close_btn.setMaximumWidth(40) hbox1 = QHBoxLayout() hbox1.addWidget(self.entry) hbox1.addStretch(1) # hbox1.addWidget() ctrl_box = QHBoxLayout() self.show_detail = QCheckBox('Show Detail', self) self.show_reserved = QCheckBox('Show Reserved', self) self.add_col = QPushButton('Add Column', self,) self.add_col.setDisabled(True) ctrl_box.addWidget(self.show_detail) # ctrl_box.addWidget(detail_label) ctrl_box.addWidget(self.show_reserved) ctrl_box.addWidget(self.add_col) ctrl_box.addStretch(1) ctrl_box.addWidget(self.close_btn) self.string_model = QStringListModel() completer.setModel(self.string_model) self.string_model.setStringList(self.address_space.keys()) self.model = QStandardItemModel() self.table = TableView(self) self.table.setWordWrap(True) self.table.setModel(self.model) self.table.setHorizontalHeader(MetaHeaderView(Qt.Horizontal, parent=self.table)) vbox = QVBoxLayout() vbox.addLayout(hbox1) # vbox.addWidget(self.entry) vbox.addLayout(ctrl_box) vbox.addWidget(self.table) self.setLayout(vbox) # self.table.horizontalHeader().setHidden(True) self.table.verticalHeader().setHidden(True) self.table.setShowGrid(False) self.table.setSizeAdjustPolicy( QAbstractScrollArea.AdjustToContents ) # self.table.setMinimumHeight(600) self.reserved_row = [] self.add_col.clicked.connect(self.add_column) self.close_btn.clicked.connect(self.close) self.show_detail.stateChanged.connect(self.detail) self.show_reserved.stateChanged.connect(self.hide_reserved) self.entry.textChanged.connect(self.create_rows) # self.table.dataChangedSignal.connect(self.test) self.default_col = list(self.cols.keys()).index('Default') self.create_cols() self.detail()
class MainWindow(base_1, form_1): def __init__(self): print("__init__") lists.create() favorites.create() widget_list = [] favorites_list = [] self.lock = passs.update("false", "true") check1 = lists.viewall() check2 = favorites.viewall() password = (passs.viewall())[0][1] for i in check1: a = [] for j in i: if (isinstance(j, str)): a.append(j) widget_list.append(a) for i in check2: a = [] for j in i: if (isinstance(j, str)): a.append(j) favorites_list.append(a) for i in widget_list: if (i[4] not in tag_list): tag_list.append(i[4]) super(base_1, self).__init__() self.setupUi(self) self.account = QWidget() self.accountLayout = QVBoxLayout() for i in reversed(range(self.accountLayout.count())): self.accountLayout.itemAt(i).widget().setParent(None) self.widgets = [] for info in widget_list: item = AccountWidget(info[0], info[1], info[2], info[3], info[4], info[5]) self.accountLayout.addWidget(item) self.widgets.append(item) self.account.setLayout(self.accountLayout) self.scroll = QScrollArea() self.scroll.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn) self.scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.scroll.setWidgetResizable(True) self.scroll.setWidget(self.account) self.scroll2 = QScrollArea() self.scroll2.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn) self.scroll2.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.scroll2.setWidgetResizable(True) self.scroll3 = QScrollArea() self.scroll3.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn) self.scroll3.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.scroll3.setWidgetResizable(True) self.searchbar = self.SearchLine self.searchbar.textChanged.connect(self.update) container = self.SearchReturn containerLayout = QVBoxLayout() containerLayout.addWidget(self.scroll) container.setLayout(containerLayout) site_names = [] for i in widget_list: site_names.append(i[0]) self.completer = QCompleter(site_names) self.completer.setCaseSensitivity(Qt.CaseInsensitive) self.searchbar.setCompleter(self.completer) self.AddButton.clicked.connect(self.AddButtonClicked) self.favorites = QWidget() self.favoritesLayout = QVBoxLayout() for i in reversed(range(self.favoritesLayout.count())): self.favoritesLayout.itemAt(i).widget().setParent(None) self.favorites_widget = [] for info in favorites_list: item = FavoritesWidget(info[0], info[1], info[2], info[3], info[4], info[5]) self.favoritesLayout.addWidget(item) self.favorites_widget.append(item) self.favorites.setLayout(self.favoritesLayout) self.scroll2.setWidget(self.favorites) container2 = self.Favorites container2Layout = QVBoxLayout() container2Layout.addWidget(self.scroll2) container2.setLayout(container2Layout) self.HelpButton.clicked.connect(self.HelpButtonClicked) self.tray_icon = QSystemTrayIcon(self) self.tray_icon.setIcon(self.style().standardIcon( QStyle.SP_ComputerIcon)) self.tray_icon.activated.connect(self.showing) ''' Define and add steps to work with the system tray icon show - show window hide - hide window exit - exit from application ''' show_action = QAction("창 보이기", self) quit_action = QAction("프로그램 종료", self) hide_action = QAction("창 숨기기", self) show_action.triggered.connect(self.show) hide_action.triggered.connect(self.hide) quit_action.triggered.connect(self.quiting) tray_menu = QMenu() tray_menu.addAction(show_action) tray_menu.addAction(hide_action) tray_menu.addAction(quit_action) self.tray_icon.setContextMenu(tray_menu) self.tray_icon.show() self.resetButton.clicked.connect(self.reset) self.tags = QWidget() self.tagsLayout = QVBoxLayout() for i in reversed(range(self.tagsLayout.count())): self.tagsLayout.itemAt(i).widget().setParent(None) self.tags_widget = [] for info in tag_list: item = Tag(info) self.tagsLayout.addWidget(item) self.tags_widget.append(item) self.tags.setLayout(self.tagsLayout) self.scroll3.setWidget(self.tags) container3 = self.TagWidget container3Layout = QVBoxLayout() container3Layout.addWidget(self.scroll3) container3.setLayout(container3Layout) self.lockButton.clicked.connect(self.LockButtonClicked) self.changePassword.clicked.connect(self.ChangeButtonClicked) self.setFixedSize(1000, 650) def ChangeButtonClicked(self): self.change = ChangeUi() check = self.change.showModal() def LockButtonClicked(self): self.lock = (passs.viewall())[1][1] print(self.lock) if self.lock == "true": self.test = VerifyUi() check = self.test.showModal() if check: self.lockButton.setText("잠금 설정") self.StatusLabel.setText("잠금 해제 상태입니다.") passs.update("true", "false") else: reply = QMessageBox.question(self, '확인', '잠금을 적용합니다.', QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if (reply == QMessageBox.Yes): self.lockButton.setText("잠금 해제") self.StatusLabel.setText("잠금 상태입니다.") QMessageBox.about(self, "확인", "잠금이 적용되었습니다.") passs.update("false", "true") def ChangePassword(self): ori = "000000" new = "000000" passs.update(ori, new) print(passs.viewall()) def clearLayout(self, layout): while layout.count(): child = layout.takeAt(0) if child.widget(): child.widget().deleteLater() def reset(self): self.clearLayout(self.accountLayout) self.clearLayout(self.favoritesLayout) self.clearLayout(self.tagsLayout) print("reset") lists.create() favorites.create() widget_list = [] favorites_list = [] tag_list = [] check1 = lists.viewall() check2 = favorites.viewall() for i in check1: a = [] for j in i: if (isinstance(j, str)): a.append(j) widget_list.append(a) for i in check2: a = [] for j in i: if (isinstance(j, str)): a.append(j) favorites_list.append(a) for i in widget_list: if (i[4] not in tag_list): tag_list.append(i[4]) self.widgets = [] for info in widget_list: item = AccountWidget(info[0], info[1], info[2], info[3], info[4], info[5]) self.accountLayout.addWidget(item) self.widgets.append(item) self.scroll = QScrollArea() self.scroll.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn) self.scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.scroll.setWidgetResizable(True) self.scroll2 = QScrollArea() self.scroll2.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn) self.scroll2.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.scroll2.setWidgetResizable(True) self.scroll3 = QScrollArea() self.scroll3.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn) self.scroll3.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.scroll3.setWidgetResizable(True) self.searchbar = self.SearchLine self.searchbar.textChanged.connect(self.update) site_names = [] for i in widget_list: site_names.append(i[0]) self.completer = QCompleter(site_names) self.completer.setCaseSensitivity(Qt.CaseInsensitive) self.searchbar.setCompleter(self.completer) self.favorites_widget = [] for info in favorites_list: item = FavoritesWidget(info[0], info[1], info[2], info[3], info[4], info[5]) self.favoritesLayout.addWidget(item) self.favorites_widget.append(item) for info in tag_list: item = Tag(info) self.tagsLayout.addWidget(item) self.tags_widget.append(item) def quiting(self): self.tray_icon.hide() self.close() qApp.quit() def printing(self): self.HelpButtonClicked(self) def HelpButtonClicked(self): self.help = HelpUi() self.help.setWindowModality(Qt.ApplicationModal) self.help.show() def showing(self, reason): if (reason == QSystemTrayIcon.DoubleClick): self.show() def update(self, text): #self.__init__() for widget in self.widgets: if text.lower() in widget.name.lower() or text.lower( ) in widget.link.lower(): widget.show() else: widget.hide() def AddButtonClicked(self): self.AddDialog = SaveUi() check = self.AddDialog.showModal() if check: item = AccountWidget(self.AddDialog.SaveName.text(), self.AddDialog.SiteLink.text(), self.AddDialog.ID.text(), self.AddDialog.Password.text(), self.AddDialog.Tag.text(), self.AddDialog.Memo.text()) self.accountLayout.addWidget(item, -2) self.widgets.append(item) widget_list.append([ self.AddDialog.SaveName.text(), self.AddDialog.SiteLink.text(), self.AddDialog.ID.text(), self.AddDialog.Password.text(), self.AddDialog.Tag.text(), self.AddDialog.Memo.text() ]) site_names.append(widget_list[-1][0]) self.completer = QCompleter(site_names) self.searchbar.setCompleter(self.completer) self.account.setLayout(self.accountLayout) lists.add(self.AddDialog.SaveName.text(), self.AddDialog.SiteLink.text(), self.AddDialog.ID.text(), self.AddDialog.Password.text(), self.AddDialog.Tag.text(), self.AddDialog.Memo.text()) check2 = self.AddDialog.FavoriteCheck.isChecked() if check2: print("check2") item = FavoritesWidget(self.AddDialog.SaveName.text(), self.AddDialog.SiteLink.text(), self.AddDialog.ID.text(), self.AddDialog.Password.text(), self.AddDialog.Tag.text(), self.AddDialog.Memo.text()) self.favoritesLayout.addWidget(item, -2) favorites_list.append([ self.AddDialog.SaveName.text(), self.AddDialog.SiteLink.text(), self.AddDialog.ID.text(), self.AddDialog.Password.text(), self.AddDialog.Tag.text(), self.AddDialog.Memo.text() ]) self.favorites.setLayout(self.favoritesLayout) favorites.add(self.AddDialog.SaveName.text(), self.AddDialog.SiteLink.text(), self.AddDialog.ID.text(), self.AddDialog.Password.text(), self.AddDialog.Tag.text(), self.AddDialog.Memo.text())
class Comercial(object): """ Funcoes das Telas de Venda e Compra """ def validaCampos(self): # Setando Validadot Int nos campos validaInt = QIntValidator(0, 9999) self.tx_IdBuscaItem.setValidator(validaInt) self.tx_Id.setValidator(validaInt) # Setando Validador float nos campos validarValor = QDoubleValidator(0.00, 999.99, 2) validarValor.setNotation(QDoubleValidator.StandardNotation) validarValor.setDecimals(2) self.tx_Desconto.setValidator(validarValor) self.tx_Frete.setValidator(validarValor) self.tx_QntdItem.setValidator(validarValor) # Setando Datas Padrão def setDatas(self): self.dt_Emissao.setDate(QDate.currentDate()) self.dt_Prazo.setDate(QDate.currentDate().addDays(2)) self.dt_Entrega.setDate(QDate.currentDate()) self.dt_Vencimento.setDate(QDate.currentDate()) # Setando Icone dos Botoes def setIcones(self): # Icone Botoes self.IconeBotaoMenu(self.bt_Salvar, self.resourcepath('Images/salvar.png')) self.IconeBotaoMenu(self.bt_Voltar, self.resourcepath('Images/cancelar.png')) self.IconeBotaoMenu(self.bt_Entregar, self.resourcepath('Images/ico_entrega.png')) self.IconeBotaoMenu(self.bt_Imprimir, self.resourcepath('Images/gtk-print.png')) self.IconeBotaoMenu(self.bt_GerarParcela, self.resourcepath('Images/ico_conta.png')) self.IconeBotaoForm(self.bt_IncluirItem, self.resourcepath('Images/addPedido.svg')) # Definindo Tamanho das tabelas def tamanhoTabelas(self): # Tamanho das Colunas Tabela Itens self.tb_Itens.blockSignals(True) self.tb_Itens.setColumnHidden(0, True) self.tb_Itens.setColumnHidden(7, True) self.tb_Itens.resizeRowsToContents() self.tb_Itens.setColumnWidth(1, 165) self.tb_Itens.setColumnWidth(2, 150) self.tb_Itens.setColumnWidth(3, 75) self.tb_Itens.setColumnWidth(4, 75) self.tb_Itens.setColumnWidth(5, 75) self.tb_Itens.setColumnWidth(6, 45) # Tamanho tabela parcelas self.tb_Parcelas.blockSignals(True) self.tb_Parcelas.setColumnHidden(0, True) self.tb_Parcelas.setColumnWidth(1, 90) self.tb_Parcelas.setColumnWidth(2, 60) self.tb_Parcelas.setColumnWidth(3, 80) self.tb_Parcelas.setColumnWidth(4, 90) def acaoCalculo(self): # calculando com desconto self.tx_Desconto.returnPressed.connect(self.TotalFinal) self.tx_Desconto.returnPressed.connect(self.tx_Frete.setFocus) self.tx_Desconto.returnPressed.connect(self.tx_Frete.selectAll) # calculando com frete self.tx_Frete.returnPressed.connect(self.TotalFinal) self.tx_Frete.returnPressed.connect(self.tx_valorRecebido.setFocus) self.tx_Frete.returnPressed.connect(self.tx_valorRecebido.selectAll) def ValidaFormAdd(self): if not self.tx_Id.text(): self.tx_Id.setFocus() elif not self.tx_BuscaItem.text(): self.tx_BuscaItem.setFocus() elif not self.tx_BuscaItem.text(): self.tx_BuscaItem.setFocus() elif not self.tx_QntdItem.text(): self.tx_QntdItem.setFocus() elif not self.tx_NomeFantasia.text(): self.tx_NomeFantasia.setFocus() else: self.AddItemTabela() # Adiciona Item a tabela def AddItemTabela(self): row = self.tb_Itens.rowCount() self.tb_Itens.insertRow(row) self.conteudoTabela(self.tb_Itens, row, 0, self.tx_IdBuscaItem.text()) self.conteudoTabelaLeft(self.tb_Itens, row, 1, self.tx_BuscaItem.text()) self.conteudoTabelaLeft(self.tb_Itens, row, 2, self.tx_ObsItem.text()) self.conteudoTabela(self.tb_Itens, row, 3, self.tx_QntdItem.text().replace(',', '.')) self.conteudoTabela(self.tb_Itens, row, 4, self.tx_ValorUnitarioItem.text()) self.conteudoTabela(self.tb_Itens, row, 5, self.tx_ValorTotalItem.text()) self.botaoRemoveItem(self.tb_Itens, row, 6, partial(self.RemoveLInha, row), "#005099") self.conteudoTabela( self.tb_Itens, row, 7, str(QDateTime.toMSecsSinceEpoch(QDateTime.currentDateTime()))) self.TotalFinal() self.LimpaCampoAddProduto() self.bt_GerarParcela.setEnabled(True) # Calcular total de Venda e Compra def TotalFinal(self): total = 0 if not int(self.tb_Itens.rowCount()) == 0 and self.tb_Itens.item( 0, 5).text(): for row in range(self.tb_Itens.rowCount()): total = float(self.tb_Itens.item(row, 5).text()) + total self.lb_SubTotal.setText(format(total, ".2f")) self.tx_TotalFinal.setText(format(total, ".2f")) self.lb_ValorPendente.setText(format(total, ".2f")) if self.tx_Desconto.text(): desconto = self.tx_Desconto.text().replace(',', '.') TotalFinal = float(total) - float(desconto) self.tx_TotalFinal.setText(format(TotalFinal, ".2f")) self.tx_Desconto.setText(format(float(desconto), ".2f")) self.lb_ValorPendente.setText(format(TotalFinal, ".2f")) if self.tx_Frete.text(): frete = self.tx_Frete.text().replace(',', '.') TotalFinal = float(total) - float( self.tx_Desconto.text()) + float(frete) self.tx_Frete.setText(format(float(frete), ".2f")) self.tx_TotalFinal.setText(format(TotalFinal, ".2f")) self.lb_ValorPendente.setText(format(TotalFinal, ".2f")) if self.tx_valorRecebido.text(): recebido = self.tx_valorRecebido.text().replace(",", ".") TotalFinal = float(self.tx_TotalFinal.text()) - \ float(recebido) self.tx_valorRecebido.setText(format(float(recebido), ".2f")) self.lb_ValorPendente.setText(format(TotalFinal, ".2f")) pass # Limpando campos após adicionar produdo def LimpaCampoAddProduto(self): for filho in self.fr_addProduto.findChildren(QLineEdit): filho.clear() self.bt_IncluirItem.setDisabled(True) self.tx_IdBuscaItem.setFocus() # Gerando parcelas Venda e Compra def gerarParcela(self, acao): numParcela = int(self.cb_QtdeParcela.currentData()) valorTotal = self.tx_TotalFinal.text() valor_parcela = float(valorTotal) / numParcela while self.tb_Parcelas.rowCount() > 0: self.tb_Parcelas.removeRow(0) pass for i in range(numParcela): self.tb_Parcelas.insertRow(i) self.dt_tabela(self.tb_Parcelas, i, 1, QDate.addMonths(self.dt_Vencimento.date(), i), 2) self.conteudoTabela(self.tb_Parcelas, i, 2, format(valor_parcela, ".2f")) self.botaoReceberParcela(self.tb_Parcelas, i, 4, partial(self.Receber, i), acao, 1) self.tx_tabelaReceber(self.tb_Parcelas, i, 3, 2, '') pass # Validar valor Recebido def validarRecebimento(self): valorRecebido = float(self.tx_ValorPago.text().replace(',', '.')) valorPendente = float(self.lb_ValorPendente.text().replace(',', '.')) if valorRecebido > valorPendente: self.tx_ValorPago.setText(format(valorPendente, '.2f')) # Setando auto complete def setAutocomplete(self): # Setando Auto complete self.completer = QCompleter(self) self.completer.setCaseSensitivity(Qt.CaseInsensitive) self.completer.setCompletionMode(QCompleter.PopupCompletion) self.model = QStringListModel(self) self.completer.setModel(self.model) self.tx_BuscaItem.setCompleter(self.completer) self.tx_NomeFantasia.setCompleter(self.completer) # AutoComplete Produtos def autocompleteProduto(self): busca = CrudProduto() busca.produto = self.tx_BuscaItem.text() busca.autoCompleteProduto() lista = [] if busca.produto: self.model.setStringList(busca.produto) # Busca Produto por nome def BuscaProdutoNome(self): busca = CrudProduto() busca.produto = self.tx_BuscaItem.text() busca.buscaProdutoNome() self.tx_IdBuscaItem.setText(str(busca.id)) self.BuscaProdutoId()
def init_UI(self,dynamic_row=10): self.ui=Ui_MainWindow() self.ui.setupUi(self) #self.table_name='characters' self.ui.menuwidget.activated[str].connect(self.onChanged) self.cursor = self.data.cursor() sql="SELECT COLUMN_NAME FROM information_schema.COLUMNS WHERE TABLE_NAME='"+str(self.table_name)+"'" self.column = self.cursor.execute(sql).fetchall() if self.searchflag==True: if(self.table_name=='Characters'): self.all_data=self.cursor.execute("select characters.*,images.photo from characters left join images on characters.id=images.id").fetchall() else: self.all_data=self.cursor.execute("select "+str(self.table_name)+".* from "+str(self.table_name)).fetchall() self.column=[elem[0] for elem in self.column] self.columnadditem=self.column.copy() if(self.table_name=='Characters'): self.column.append('photo') #self.columnadditem.append('photo') self.columnadditem.remove('id') print(self.columnadditem) #self.dynamic_row=2#len(data) self.ui.pushButton.clicked.connect(self.all) self.slider=QRangeSlider(self) self.slider.setGeometry(QtCore.QRect(1450, 350, 300, 40)) self.slider.setRange(0,300) self.slider.setMax(300) self.massslider=QRangeSlider(self) self.massslider.setGeometry(QtCore.QRect(1450, 450, 300, 40)) self.massslider.setRange(0,200) self.massslider.setMax(200) print(self.slider.endValueChanged) self.ui.search.clicked.connect(self.search) #Реализация подсказок # wordList=["select"," characters.*,","images.photo"," from ","characters ","left"," join"," images ","on ","characters.id=images.id"] wordList=self.loadDictionary() completer = QCompleter(wordList, self) completer.setCaseSensitivity(PyQt5.QtCore.Qt.CaseInsensitive) self.ui.searchline.setCompleter(completer) #Таблица для добавления данных в БД # self.ui.additemwidget.setColumnCount(len(self.columnadditem)) # self.ui.additemwidget.setHorizontalHeaderLabels(self.columnadditem) # self.ui.additemwidget.setRowCount(1) # self.ui.additembutton.clicked.connect(self.additemdatabase) #Основная таблица self.ui.tableWidget.setColumnCount(len(self.column)) self.ui.tableWidget.setRowCount(dynamic_row) self.ui.tableWidget.setHorizontalHeaderLabels(self.column) #self.ui.pushButton.clicked.connect(self.all) self.ui.tableWidget.setSortingEnabled(True) row = 0 self.btn=[] self.ui.tableWidget.resizeColumnsToContents() #print(self.column) for tup in self.all_data:#Заполнение таблицы данными из БД col = 0 for item in tup: if col==12: self.btn.append(Qt.QPushButton("Открыть картинку")) self.ui.tableWidget.setCellWidget(row, col, self.btn[row]) col += 1 #self.button=self.btn[row] self.btn[row].clicked.connect(partial(self.open_image,row))#Открытие картинки в новом окне #print(row) #print(re.search(r"\\", str(item))) else: self.cellinfo = QTableWidgetItem(str(item)) self.ui.tableWidget.setItem(row, col, self.cellinfo) col += 1 row += 1 #self.cellinfo.setFlags(self.cellinfo.flags() & ~QtCore.Qt.ItemIsEditable) self.searchflag=True self.ui.colorRed.stateChanged.connect(self.checkred) self.ui.colorBlue.stateChanged.connect(self.checkblue) self.ui.colorGreen.stateChanged.connect(self.checkgreen) self.ui.colorWhite.stateChanged.connect(self.checkwhite) self.ui.colorLight.stateChanged.connect(self.checklight) self.ui.colorYellow.stateChanged.connect(self.checkyellow) self.ui.colorBrown.stateChanged.connect(self.checkbrown) self.ui.colorDark.stateChanged.connect(self.checkdark) self.ui.colorOrange.stateChanged.connect(self.checkorange) self.ui.colorFair.stateChanged.connect(self.checkfair) self.ui.genderMale.stateChanged.connect(self.checkmale) self.ui.genderFemale.stateChanged.connect(self.checkfemale) # self.ui.userbutton.clicked.connect(self.openUsers) # self.ui.deletebutton.clicked.connect(self.delbutton) header = self.ui.tableWidget.horizontalHeader() #header.setSectionResizeMode(11, QtWidgets.QHeaderView.Stretch) self.ui.tableWidget.resizeColumnsToContents() self.ui.updatetable.clicked.connect(self.updatetable)
class MainWidget(QWidget, PM, Ui_MainWidget): # Signal Emits updatingStatus = pyqtSignal() repositoriesUpdated = pyqtSignal() selectionStatusChanged = pyqtSignal([str]) finished = pyqtSignal() cleanUp = pyqtSignal() def __init__(self, parent=None): super(MainWidget, self).__init__(parent) self.setupUi(self) self.parent = parent self._selectedGroups = [] self._preexceptions = [] self._postexceptions = [] self.state = StateManager(self) self.currentState = None self.completer = None self._updatesCheckedOnce = False # Search Thread self._searchThread = PThread(self, self.startSearch, self.searchFinished) self.statusUpdater = StatusUpdater() self.basket = BasketDialog(self.state, self.parent) self._postexceptions.append(lambda: self.basket.setActionEnabled(True)) self.searchButton.setIcon(QIcon.fromTheme('edit-find')) self.initializeUpdateTypeList() model = PackageModel(self) proxy = PackageProxy(self) proxy.setSourceModel(model) self.packageList.setModel(proxy) self.packageList.setItemDelegate(PackageDelegate(self, self.parent)) self.packageList.setColumnWidth(0, 32) self.packageList.dataChanged[QModelIndex, QModelIndex].connect(self.statusChanged) self.packageList.updateRequested.connect(self.initialize) self.updateSettings() self.setActionButton() self.operation = OperationManager(self.state) self.progressDialog = ProgressDialog(self.state, self.parent) self._preexceptions.append(self.progressDialog._hide) self.progressDialog.registerFunction( FINISHED, lambda: self.parent.statusBar().setVisible( not self.progressDialog.isVisible())) self.progressDialog.registerFunction( OUT, lambda: self.parent.statusBar().show()) self.summaryDialog = SummaryDialog() self.connectOperationSignals() self.pdsMessageBox = PMessageBox(self.content) def connectMainSignals(self): self.actionButton.clicked.connect(self.showBasket) self.checkUpdatesButton.clicked.connect(self.state.updateRepoAction) self.searchButton.clicked.connect(self.searchActivated) self.searchLine.textChanged[str].connect(self.searchLineChanged) self.searchLine.returnPressed.connect(self.searchActivated) self.searchLine.textChanged[str].connect(self.slotSearchLineClear) self.typeCombo.activated[int].connect(self.typeFilter) self.stateTab.currentChanged[int].connect(self.switchState) self.groupList.groupChanged.connect(self.groupFilter) self.groupList.groupChanged.connect( lambda: self.searchButton.setEnabled(False)) self.packageList.select_all.clicked[bool].connect(self.toggleSelectAll) self.packageList.itemDelegate().packageSelected[bool].connect( self.toggleSelect) self.statusUpdater.selectedInfoChanged[int, str, int, str].connect( self.emitStatusBarInfo) self.statusUpdater.selectedInfoChanged[str].connect( lambda message: self.selectionStatusChanged[str].emit(message)) self.statusUpdater.finished.connect(self.statusUpdated) def initialize(self): waitCursor() self.searchLine.clear() self._started = False self._last_packages = None self.state.reset() self.initializePackageList() self.initializeGroupList() self.initializeStatusUpdater() self.statusChanged() self._selectedGroups = [] self.packageList.select_all.setChecked(False) self.initializeBasket() self.searchLine.setFocus(True) if self.currentState == self.state.UPGRADE: if self.groupList.count() == 0: QTimer.singleShot(0, \ lambda: self.pdsMessageBox.showMessage(_translate("Package Manager","All packages are up to date"), icon = "info")) if self.groupList.count() > 0: if self.state.inUpgrade(): self.pdsMessageBox.hideMessage(force=True) restoreCursor() def initializeStatusUpdater(self): self.statusUpdater.calculate_deps = not self.state.state == self.state.ALL self.statusUpdater.setModel(self.packageList.model().sourceModel()) def initializeBasket(self): waitCursor() self.basket.setModel(self.packageList.model().sourceModel()) restoreCursor() def initializePackageList(self): self.packageList.model().reset() self.packageList.setPackages(self.state.packages()) if self.completer: self.completer.deleteLater() del self.completer self.completer = QCompleter(self.state.allPackages(), self) self.completer.setCaseSensitivity(Qt.CaseInsensitive) self.searchLine.setCompleter(self.completer) def selectComponent(self, component): if not self.state.iface.operationInProgress(): if self.basket.isVisible(): self.basket._hide() self.stateTab.setCurrentIndex(1) self.switchState(self.state.INSTALL) if component in self.groupList._list: self.groupList.setCurrentItem(self.groupList._list[component]) self.groupFilter() def updateSettings(self): # pmconfig ikinci kez okunmuyor self.packageList.showComponents = PMConfig().showComponents() self.packageList.showIsA = PMConfig().showIsA() self.packageList.setFocus() self.initialize() def searchLineChanged(self, text): self.searchButton.setEnabled(bool(text)) if text == 'true': self.searchActivated() def statusUpdated(self): if self.statusUpdater.needsUpdate: self.statusUpdater.needsUpdate = False self.statusChanged() def statusChanged(self): self.setActionEnabled() if self.statusUpdater.isRunning(): self.statusUpdater.needsUpdate = True else: self.updatingStatus.emit() self.statusUpdater.start() def initializeGroupList(self): self.groupList.clear() self.groupList._list = {} self.groupList.setAlternatingRowColors(True) self.groupList.setIconSize(QSize(32, 32)) self.groupList.setState(self.state) self.groupList.addGroups(self.state.groups()) if self.state.state == self.state.UPGRADE: self.typeCombo.show() else: self.typeCombo.hide() self.state._typeFilter = 'normal' self.groupFilter() def packageFilter(self, text): self.packageList.model().setFilterRole(Qt.DisplayRole) self.packageList.model().setFilterRegExp( QRegExp(unicode(text), Qt.CaseInsensitive, QRegExp.FixedString)) def typeFilter(self, index): if self.state.state == self.state.UPGRADE: filter = self.typeCombo.itemData(index) if not self.state._typeFilter == filter: self.state._typeFilter = filter self.initializeGroupList() def slotSearchLineClear(self): if self.searchLine.text() != 'true': return self.groupFilter() def groupFilter(self): waitCursor() self.packageList.resetMoreInfoRow() packages = self.state.groupPackages(self.groupList.currentGroup()) self.packageList.model().setFilterRole(GroupRole) self.packageList.model().setFilterPackages(packages) self.packageList.scrollToTop() self.packageList.select_all.setChecked( self.groupList.currentGroup() in self._selectedGroups) restoreCursor() def searchActivated(self): if self.currentState == self.state.UPGRADE: if self.groupList.count() == 0 and not self.searchUsed: return if not self.searchLine.text() == '': self.pdsMessageBox.showMessage(_translate("Package Manager", "Searching..."), busy=True) self.groupList.lastSelected = None self._searchThread.start() self.searchUsed = True else: self.state.cached_packages = None self.state.packages() self.searchUsed = False self.searchFinished() def searchFinished(self): if self.state.cached_packages == []: self.pdsMessageBox.showMessage( _translate("Package Manager", "No results found."), "dialog-information") else: self.pdsMessageBox.hideMessage() self.initializeGroupList() self.initializePackageList() def startSearch(self): searchText = str(self.searchLine.text()).split() sourceModel = self.packageList.model().sourceModel() self.state.cached_packages = sourceModel.search(searchText) self.finished.emit() return self.state.cached_packages def setActionButton(self): self.actionButton.setEnabled(False) if self.state.state == self.state.ALL: menu = QMenu(self.actionButton) self.__install_action = menu.addAction( self.state.getActionIcon(self.state.INSTALL), self.state.getActionName(self.state.INSTALL), self.showBasket) self.__remove_action = menu.addAction( self.state.getActionIcon(self.state.REMOVE), self.state.getActionName(self.state.REMOVE), self.showBasket) self.actionButton.setMenu(menu) else: self.actionButton.setMenu(None) self.actionButton.setIcon(self.state.getActionIcon()) self.actionButton.setText(self.state.getActionName()) def actionStarted(self, operation): self.pdsMessageBox.hideMessage() self.progressDialog.reset() if not operation in [ "System.Manager.updateRepository", "System.Manager.updateAllRepositories" ]: totalPackages = self.packageList.packageCount() self.operation.setTotalPackages(totalPackages) self.progressDialog.updateStatus(0, totalPackages, self.state.toBe()) if self.isVisible(): if operation in [ "System.Manager.updateRepository", "System.Manager.updateAllRepositories" ]: self.progressDialog.repoOperationView() if self.basket.isVisible(): self.basket._hide() QTimer.singleShot(0, self.progressDialog._show) else: self.progressDialog._show() if not self._started: self.progressDialog.disableCancel() else: self.progressDialog.enableCancel() def actionFinished(self, operation): if operation in ("System.Manager.installPackage", "System.Manager.removePackage", "System.Manager.updatePackage"): self.notifyFinished() if operation == "System.Manager.installPackage" and self._started: KIconLoader.updateAvailableIcons() self.summaryDialog.setDesktopFiles(self.operation.desktopFiles) self.summaryDialog.showSummary() if operation in ("System.Manager.updateRepository", "System.Manager.updateAllRepositories"): self.repositoriesUpdated.emit() self.searchLine.clear() self.state.reset() self.progressDialog._hide() if not self.currentState == self.state.UPGRADE: self.switchState(self.currentState) self.initialize() def actionCancelled(self): self.progressDialog._hide() self.progressDialog.reset() self.switchState(self.currentState) self.groupFilter() def setActionEnabled(self): enabled = self.packageList.isSelected() self.actionButton.setEnabled(enabled) self.basket.setActionEnabled(enabled) def switchState(self, state): self.pdsMessageBox.hideMessage() self._states[state][1].setChecked(True) self.state.setState(state) self.currentState = state self._selectedGroups = [] if not state == self.state.HISTORY: self.setActionButton() self.state.cached_packages = None if state == self.state.UPGRADE or (state == self.state.INSTALL and self.groupList.count() == 1): if not self._updatesCheckedOnce: self._updatesCheckedOnce = self.state.updateRepoAction( silence=True) self.checkUpdatesButton.setHidden(not state == self.state.UPGRADE) self.initialize() def emitStatusBarInfo(self, packages, packagesSize, extraPackages, extraPackagesSize): self.selectionStatusChanged[str].emit( self.state.statusText(packages, packagesSize, extraPackages, extraPackagesSize)) # paket seçimine geçici çözüm if packages > 0: self.actionButton.setEnabled(True) else: self.actionButton.setEnabled(False) def setSelectAll(self, packages=None): if packages: self.packageList.reverseSelection(packages) def setReverseAll(self, packages=None): if packages: self.packageList.selectAll(packages) def toggleSelectAll(self, toggled): self._last_packages = self.packageList.model().getFilteredPackages() if toggled: if self.groupList.currentGroup() not in self._selectedGroups: self._selectedGroups.append(self.groupList.currentGroup()) self.setReverseAll(self._last_packages) else: if self.groupList.currentGroup() in self._selectedGroups: self._selectedGroups.remove(self.groupList.currentGroup()) self.setSelectAll(self._last_packages) self.packageList.setFocus() self.statusChanged() def toggleSelect(self, toggled): #self._last_packages = self.packageList.model().getFilteredPackages() if toggled: if self.groupList.currentGroup() not in self._selectedGroups: self._selectedGroups.append(self.groupList.currentGroup()) #else: #if self.groupList.currentGroup() in self._selectedGroups: # self._selectedGroups.remove(self.groupList.currentGroup()) #self.setSelectAll(self._last_packages) self.packageList.setFocus() self.statusChanged() def showBasket(self): if self.basket.isVisible(): return waitCursor() self.statusUpdater.wait() if self.currentState == self.state.ALL: action = { self.__remove_action: self.state.REMOVE, self.__install_action: self.state.INSTALL }.get(self.sender(), self.state.INSTALL) if action: if action == self.state.REMOVE: installed_packages = self.state.iface.getInstalledPackages( ) filtered_packages = filter( lambda x: x not in installed_packages, self.basket.model.selectedPackages()) if filtered_packages == self.basket.model.selectedPackages( ): restoreCursor() QMessageBox( _translate("Package Manager", "Select packages"), _translate( "Package Manager", "You must select at least one installed package" ), QMessageBox.Information, QMessageBox.Ok, 0, 0).exec_() return self.packageList.model().sourceModel().selectPackages( filtered_packages, state=False) self.state.state = action self.basket._show() restoreCursor() def initializeUpdateTypeList(self): self.typeCombo.clear() self.typeCombo.addItem(QIcon.fromTheme('system-software-update'), _translate("Package Manager", 'All Updates'), 'normal') self.typeCombo.addItem( QIcon.fromTheme('security-medium'), _translate("Package Manager", 'Security Updates'), 'security') self.typeCombo.addItem( QIcon.fromTheme('security-low'), _translate("Package Manager", 'Critical Updates'), 'critical')
class MainWidget(QWidget, PM, Ui_MainWidget): # Signal Emits updatingStatus = pyqtSignal() repositoriesUpdated = pyqtSignal() selectionStatusChanged = pyqtSignal([str]) finished = pyqtSignal() cleanUp = pyqtSignal() def __init__(self, parent = None): super(MainWidget, self).__init__(parent) self.setupUi(self) self.parent = parent self._selectedGroups = [] self._preexceptions = [] self._postexceptions = [] self.state = StateManager(self) self.currentState = None self.completer = None self._updatesCheckedOnce = False # Search Thread self._searchThread = PThread(self, self.startSearch, self.searchFinished) self.statusUpdater = StatusUpdater() self.basket = BasketDialog(self.state, self.parent) self._postexceptions.append(lambda: self.basket.setActionEnabled(True)) self.searchButton.setIcon(KIcon(("edit-find", "find"))) self.initializeUpdateTypeList() model = PackageModel(self) proxy = PackageProxy(self) proxy.setSourceModel(model) self.packageList.setModel(proxy) self.packageList.setItemDelegate(PackageDelegate(self, self.parent)) self.packageList.setColumnWidth(0, 32) self.packageList.dataChanged[QModelIndex,QModelIndex].connect(self.statusChanged) self.packageList.updateRequested.connect(self.initialize) self.updateSettings() self.setActionButton() self.operation = OperationManager(self.state) self.progressDialog = ProgressDialog(self.state, self.parent) self._preexceptions.append(self.progressDialog._hide) self.progressDialog.registerFunction(FINISHED, lambda: self.parent.statusBar().setVisible(not self.progressDialog.isVisible())) self.progressDialog.registerFunction(OUT, lambda: self.parent.statusBar().show()) self.summaryDialog = SummaryDialog() self.connectOperationSignals() self.pdsMessageBox = PMessageBox(self.content) def connectMainSignals(self): self.actionButton.clicked.connect(self.showBasket) self.checkUpdatesButton.clicked.connect(self.state.updateRepoAction) self.searchButton.clicked.connect(self.searchActivated) self.searchLine.textEdited[str].connect(self.searchLineChanged) self.searchLine.returnPressed.connect(self.searchActivated) self.searchLine.textChanged[str].connect(self.slotSearchLineClear) self.typeCombo.activated[int].connect(self.typeFilter) self.stateTab.currentChanged[int].connect(self.switchState) self.groupList.groupChanged.connect(self.groupFilter) self.groupList.groupChanged.connect(lambda:self.searchButton.setEnabled(False)) self.packageList.select_all.clicked[bool].connect(self.toggleSelectAll) self.packageList.itemDelegate().packageSelected[bool].connect(self.toggleSelect) self.statusUpdater.selectedInfoChanged[int,str,int,str].connect(self.emitStatusBarInfo) self.statusUpdater.selectedInfoChanged[str].connect(lambda message: self.selectionStatusChanged[str].emit(message)) self.statusUpdater.finished.connect(self.statusUpdated) def initialize(self): waitCursor() self.searchLine.clear() self._started = False self._last_packages = None self.state.reset() self.initializePackageList() self.initializeGroupList() self.initializeStatusUpdater() self.statusChanged() self._selectedGroups = [] self.packageList.select_all.setChecked(False) self.initializeBasket() self.searchLine.setFocus(True) if self.currentState == self.state.UPGRADE: if self.groupList.count() == 0: QTimer.singleShot(0, \ lambda: self.pdsMessageBox.showMessage(_translate("Packaga Manager","All packages are up to date"), icon = "info")) if self.groupList.count() > 0: if self.state.inUpgrade(): self.pdsMessageBox.hideMessage(force = True) restoreCursor() def initializeStatusUpdater(self): self.statusUpdater.calculate_deps = not self.state.state == self.state.ALL self.statusUpdater.setModel(self.packageList.model().sourceModel()) def initializeBasket(self): waitCursor() self.basket.setModel(self.packageList.model().sourceModel()) restoreCursor() def initializePackageList(self): self.packageList.model().reset() self.packageList.setPackages(self.state.packages()) if self.completer: self.completer.deleteLater() del self.completer self.completer = QCompleter(self.state.allPackages(), self) self.completer.setCaseSensitivity(Qt.CaseInsensitive) self.searchLine.setCompleter(self.completer) def selectComponent(self, component): if not self.state.iface.operationInProgress(): if self.basket.isVisible(): self.basket._hide() self.stateTab.setCurrentIndex(1) self.switchState(self.state.INSTALL) if component in self.groupList._list: self.groupList.setCurrentItem(self.groupList._list[component]) self.groupFilter() def updateSettings(self): # pmconfig ikinci kez okunmuyor self.packageList.showComponents = PMConfig().showComponents() self.packageList.showIsA = PMConfig().showIsA() self.packageList.setFocus() self.initialize() def searchLineChanged(self, text): self.searchButton.setEnabled(bool(text)) if text == '': self.searchActivated() def statusUpdated(self): if self.statusUpdater.needsUpdate: self.statusUpdater.needsUpdate = False self.statusChanged() def statusChanged(self): self.setActionEnabled() if self.statusUpdater.isRunning(): self.statusUpdater.needsUpdate = True else: self.updatingStatus.emit() self.statusUpdater.start() def initializeGroupList(self): self.groupList.clear() self.groupList._list = {} self.groupList.setAlternatingRowColors(True) self.groupList.setIconSize(QSize(32, 32)) self.groupList.setState(self.state) self.groupList.addGroups(self.state.groups()) if self.state.state == self.state.UPGRADE: self.typeCombo.show() else: self.typeCombo.hide() self.state._typeFilter = 'normal' self.groupFilter() def packageFilter(self, text): self.packageList.model().setFilterRole(Qt.DisplayRole) self.packageList.model().setFilterRegExp(QRegExp(unicode(text), Qt.CaseInsensitive, QRegExp.FixedString)) def typeFilter(self, index): if self.state.state == self.state.UPGRADE: filter = self.typeCombo.itemData(index) if not self.state._typeFilter == filter: self.state._typeFilter = filter self.initializeGroupList() def slotSearchLineClear(self): if self.searchLine.text()!="": return self.groupFilter() def groupFilter(self): waitCursor() self.packageList.resetMoreInfoRow() packages = self.state.groupPackages(self.groupList.currentGroup()) self.packageList.model().setFilterRole(GroupRole) self.packageList.model().setFilterPackages(packages) self.packageList.scrollToTop() self.packageList.select_all.setChecked(self.groupList.currentGroup() in self._selectedGroups) restoreCursor() def searchActivated(self): if self.currentState == self.state.UPGRADE: if self.groupList.count() == 0 and not self.searchUsed: return if not self.searchLine.text() == '': self.pdsMessageBox.showMessage(_translate("Packaga Manager","Searching..."), busy = True) self.groupList.lastSelected = None self._searchThread.start() self.searchUsed = True else: self.state.cached_packages = None self.state.packages() self.searchUsed = False self.searchFinished() def searchFinished(self): if self.state.cached_packages == []: self.pdsMessageBox.showMessage(_translate("Packaga Manager","No results found."), "dialog-information") else: self.pdsMessageBox.hideMessage() self.initializeGroupList() self.initializePackageList() def startSearch(self): searchText = str(self.searchLine.text()).split() sourceModel = self.packageList.model().sourceModel() self.state.cached_packages = sourceModel.search(searchText) self.finished.emit() return self.state.cached_packages def setActionButton(self): self.actionButton.setEnabled(False) if self.state.state == self.state.ALL: menu = QMenu(self.actionButton) self.__install_action = menu.addAction(self.state.getActionIcon(self.state.INSTALL), self.state.getActionName(self.state.INSTALL), self.showBasket) self.__remove_action = menu.addAction(self.state.getActionIcon(self.state.REMOVE), self.state.getActionName(self.state.REMOVE), self.showBasket) self.actionButton.setMenu(menu) else: self.actionButton.setMenu(None) self.actionButton.setIcon(self.state.getActionIcon()) self.actionButton.setText(self.state.getActionName()) def actionStarted(self, operation): self.pdsMessageBox.hideMessage() self.progressDialog.reset() if not operation in ["System.Manager.updateRepository", "System.Manager.updateAllRepositories"]: totalPackages = self.packageList.packageCount() self.operation.setTotalPackages(totalPackages) self.progressDialog.updateStatus(0, totalPackages, self.state.toBe()) if self.isVisible(): if operation in ["System.Manager.updateRepository", "System.Manager.updateAllRepositories"]: self.progressDialog.repoOperationView() if self.basket.isVisible(): self.basket._hide() QTimer.singleShot(0, self.progressDialog._show) else: self.progressDialog._show() if not self._started: self.progressDialog.disableCancel() else: self.progressDialog.enableCancel() def actionFinished(self, operation): if operation in ("System.Manager.installPackage", "System.Manager.removePackage", "System.Manager.updatePackage"): self.notifyFinished() if operation == "System.Manager.installPackage" and self._started: KIconLoader.updateAvailableIcons() self.summaryDialog.setDesktopFiles(self.operation.desktopFiles) self.summaryDialog.showSummary() if operation in ("System.Manager.updateRepository", "System.Manager.updateAllRepositories"): self.repositoriesUpdated.emit() self.searchLine.clear() self.state.reset() self.progressDialog._hide() if not self.currentState == self.state.UPGRADE: self.switchState(self.currentState) self.initialize() def actionCancelled(self): self.progressDialog._hide() self.progressDialog.reset() self.switchState(self.currentState) self.groupFilter() def setActionEnabled(self): enabled = self.packageList.isSelected() self.actionButton.setEnabled(enabled) self.basket.setActionEnabled(enabled) def switchState(self, state): self.pdsMessageBox.hideMessage() self._states[state][1].setChecked(True) self.state.setState(state) self.currentState = state self._selectedGroups = [] if not state == self.state.HISTORY: self.setActionButton() self.state.cached_packages = None if state == self.state.UPGRADE or (state == self.state.INSTALL and self.groupList.count() == 1): if not self._updatesCheckedOnce: self._updatesCheckedOnce = self.state.updateRepoAction(silence = True) self.checkUpdatesButton.setHidden(not state == self.state.UPGRADE) self.initialize() def emitStatusBarInfo(self, packages, packagesSize, extraPackages, extraPackagesSize): self.selectionStatusChanged[str].emit(self.state.statusText(packages, packagesSize, extraPackages, extraPackagesSize)) # paket seçimine geçici çözüm if packages > 0: self.actionButton.setEnabled(True) else: self.actionButton.setEnabled(False) def setSelectAll(self, packages=None): if packages: self.packageList.reverseSelection(packages) def setReverseAll(self, packages=None): if packages: self.packageList.selectAll(packages) def toggleSelectAll(self, toggled): self._last_packages = self.packageList.model().getFilteredPackages() if toggled: if self.groupList.currentGroup() not in self._selectedGroups: self._selectedGroups.append(self.groupList.currentGroup()) self.setReverseAll(self._last_packages) else: if self.groupList.currentGroup() in self._selectedGroups: self._selectedGroups.remove(self.groupList.currentGroup()) self.setSelectAll(self._last_packages) self.packageList.setFocus() self.statusChanged() def toggleSelect(self, toggled): #self._last_packages = self.packageList.model().getFilteredPackages() if toggled: if self.groupList.currentGroup() not in self._selectedGroups: self._selectedGroups.append(self.groupList.currentGroup()) #else: #if self.groupList.currentGroup() in self._selectedGroups: # self._selectedGroups.remove(self.groupList.currentGroup()) #self.setSelectAll(self._last_packages) self.packageList.setFocus() self.statusChanged() def showBasket(self): if self.basket.isVisible(): return waitCursor() self.statusUpdater.wait() if self.currentState == self.state.ALL: action = {self.__remove_action:self.state.REMOVE, self.__install_action:self.state.INSTALL}.get(self.sender(), self.state.INSTALL) if action: if action == self.state.REMOVE: installed_packages = self.state.iface.getInstalledPackages() filtered_packages = filter(lambda x: x not in installed_packages, self.basket.model.selectedPackages()) if filtered_packages == self.basket.model.selectedPackages(): restoreCursor() QMessageBox(_translate("Packaga Manager","Select packages"), _translate("Packaga Manager","You must select at least one installed package"), QMessageBox.Information, QMessageBox.Ok, 0, 0).exec_() return self.packageList.model().sourceModel().selectPackages(filtered_packages, state = False) self.state.state = action self.basket._show() restoreCursor() def initializeUpdateTypeList(self): self.typeCombo.clear() UPDATE_TYPES = [['normal', _translate("Packaga Manager",'All Updates'), ('system-software-update', 'ledgreen')], ['security', _translate("Packaga Manager",'Security Updates'), ('security-medium', 'ledyellow')], ['critical', _translate("Packaga Manager",'Critical Updates'), ('security-low', 'ledred')]] for type in UPDATE_TYPES: self.typeCombo.addItem(KIcon(type[2]), type[1], QVariant(type[0]))
def run_iface_config_window(icon): win = QDialog() win.setWindowTitle('CAN Interface Configuration') win.setWindowIcon(icon) win.setWindowFlags(Qt.CustomizeWindowHint | Qt.WindowTitleHint | Qt.WindowCloseButtonHint) combo = QComboBox(win) combo.setEditable(True) combo.setInsertPolicy(QComboBox.NoInsert) combo.setSizeAdjustPolicy(QComboBox.AdjustToContents) combo.setFont(get_monospace_font()) combo_completer = QCompleter() combo_completer.setCaseSensitivity(Qt.CaseSensitive) combo_completer.setModel(combo.model()) combo.setCompleter(combo_completer) bitrate = QSpinBox() bitrate.setMaximum(1000000) bitrate.setMinimum(10000) bitrate.setValue(1000000) extra_args = QLineEdit() extra_args.setFont(get_monospace_font()) ok = QPushButton('OK', win) ifaces = None def update_iface_list(): nonlocal ifaces ifaces = iface_lister.get_list() known_keys = set() remove_indices = [] was_empty = combo.count() == 0 # Marking known and scheduling for removal for idx in count(): tx = combo.itemText(idx) if not tx: break known_keys.add(tx) if tx not in ifaces: logger.debug('Removing iface %r', tx) remove_indices.append(idx) # Removing - starting from the last item in order to retain indexes for idx in remove_indices[::-1]: combo.removeItem(idx) # Adding new items - starting from the last item in order to retain the final order for key in list(ifaces.keys())[::-1]: if key not in known_keys: logger.debug('Adding iface %r', key) combo.insertItem(0, key) # Updating selection if was_empty: combo.setCurrentIndex(0) result = None kwargs = {} def on_ok(): nonlocal result, kwargs a = str(extra_args.text()) if a: try: kwargs = dict(eval(a)) except Exception as ex: show_error('Invalid parameters', 'Could not parse optional arguments', ex, parent=win) return kwargs['bitrate'] = int(bitrate.value()) result_key = str(combo.currentText()).strip() if not result_key: show_error('Invalid parameters', 'Interface name cannot be empty', 'Please select a valid interface', parent=win) return try: result = ifaces[result_key] except KeyError: result = result_key win.close() ok.clicked.connect(on_ok) layout = QVBoxLayout() layout.addWidget(QLabel('Select CAN interface or serial port for SLCAN:')) layout.addWidget(combo) layout.addWidget(QLabel('Interface bitrate (SLCAN only):')) layout.addWidget(bitrate) layout.addWidget(QLabel('Optional arguments (refer to PyUAVCAN for info):')) layout.addWidget(extra_args) layout.addWidget(ok) layout.setSizeConstraint(layout.SetFixedSize) win.setLayout(layout) with BackgroundIfaceListUpdater() as iface_lister: update_iface_list() timer = QTimer(win) timer.setSingleShot(False) timer.timeout.connect(update_iface_list) timer.start(int(BackgroundIfaceListUpdater.UPDATE_INTERVAL / 2 * 1000)) win.exec() return result, kwargs
class CLIWidget(QWidget): def __init__(self, parent, cli_iface): super(CLIWidget, self).__init__(parent) self._cli_iface = cli_iface self._command_line = CommitableComboBoxWithHistory(self) self._command_line.setToolTip('Enter the command here') self._command_line.setSizeAdjustPolicy(QComboBox.AdjustToContents) self._command_line.setFont(get_monospace_font()) self._command_line.on_commit = self._do_execute self._command_line_completer = QCompleter() self._command_line_completer.setCaseSensitivity(Qt.CaseSensitive) self._command_line_completer.setModel(self._command_line.model()) self._command_line.setCompleter(self._command_line_completer) self._execute_button = make_icon_button('flash', 'Execute command', self, on_clicked=self._do_execute) self._response_box = QPlainTextEdit(self) self._response_box.setToolTip('Command output will be printed here') self._response_box.setReadOnly(True) self._response_box.setLineWrapMode(QPlainTextEdit.NoWrap) self._response_box.setFont(get_monospace_font()) self._response_box.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded) try: self._log_viewer.setPlaceholderText('Command output will be printed here') except AttributeError: # Old PyQt pass layout = QVBoxLayout(self) controls_layout = QHBoxLayout(self) controls_layout.addWidget(self._command_line, 1) controls_layout.addWidget(self._execute_button) layout.addLayout(controls_layout) layout.addWidget(self._response_box, 1) self.setLayout(layout) def _do_execute(self): self._response_box.clear() command = self._command_line.currentText() if not command.strip(): return self._command_line.add_current_text_to_history() def callback(lines): self.setEnabled(True) if lines is None: self.window().show_message('Command response timed out') self._response_box.setPlainText('<RESPONSE TIMED OUT>') else: self.window().show_message('Command response received') self._response_box.setPlainText(lines) self.setEnabled(False) self._cli_iface.execute_raw_command(command, callback)
def __init__(self, parent, active_data_types): super(NewValueExtractorWindow, self).__init__(parent) self.setAttribute(Qt.WA_DeleteOnClose) # This is required to stop background timers! self.setWindowTitle('New Plot') self.setModal(True) self._active_data_types = active_data_types self.on_done = print # Message type selection box self._type_selector = CommitableComboBoxWithHistory(self) self._type_selector.setToolTip('Name of the message type to plot') self._type_selector.setInsertPolicy(QComboBox.NoInsert) type_completer = QCompleter(self._type_selector) type_completer.setCaseSensitivity(Qt.CaseSensitive) type_completer.setModel(self._type_selector.model()) self._type_selector.setCompleter(type_completer) self._type_selector.setFont(get_monospace_font()) self._type_selector.setSizeAdjustPolicy(QComboBox.AdjustToContents) self._type_selector.setFocus(Qt.OtherFocusReason) self._type_selector.currentTextChanged.connect(self._on_type_changed) self._show_all_types_button = make_icon_button('puzzle-piece', 'Show all known message types, not only those that are ' 'currently being exchanged over the bus', self, checkable=True, on_clicked=self._update_data_type_list) # Existence is torment. self._extraction_expression_box = QLineEdit(self) self._extraction_expression_box.setFont(get_monospace_font()) self._extraction_expression_box.setToolTip('Example: msg.cmd[0] / 16384') # Node ID filter self._node_id_filter_checkbox = QCheckBox('Accept messages only from specific node', self) self._node_id_filter_checkbox.stateChanged.connect( lambda: self._node_id_filter_spinbox.setEnabled(self._node_id_filter_checkbox.isChecked())) self._node_id_filter_spinbox = QSpinBox(self) self._node_id_filter_spinbox.setMinimum(1) self._node_id_filter_spinbox.setMaximum(127) self._node_id_filter_spinbox.setValue(1) self._node_id_filter_spinbox.setEnabled(False) # Expression filter self._filter_expression_box = QLineEdit(self) self._filter_expression_box.setFont(get_monospace_font()) self._filter_expression_box.setToolTip('Example: msg.esc_index == 3') # Visualization options self._selected_color = self.default_color_rotator.get() self._select_color_button = make_icon_button('paint-brush', 'Select line color', self, on_clicked=self._select_color) self._select_color_button.setFlat(True) _set_color(self._select_color_button, QPalette.Button, self._selected_color) # Buttons self._ok_button = make_icon_button('check', 'Create new extractor with these settings', self, text='OK', on_clicked=self._on_ok) # Layout layout = QVBoxLayout(self) msg_type_box = QGroupBox('Message type', self) msg_type_box_layout = QHBoxLayout(self) msg_type_box_layout.addWidget(self._show_all_types_button) msg_type_box_layout.addWidget(self._type_selector, 1) msg_type_box.setLayout(msg_type_box_layout) layout.addWidget(msg_type_box) expr_box = QGroupBox('Expression to plot', self) expr_box_layout = QVBoxLayout(self) expr_box_layout.addWidget(QLabel('Message is stored in the variable "msg"', self)) expr_box_layout.addWidget(self._extraction_expression_box) expr_box.setLayout(expr_box_layout) layout.addWidget(expr_box) nid_filter_box = QGroupBox('Node ID filter', self) nid_filter_box_layout = QHBoxLayout(self) nid_filter_box_layout.addWidget(self._node_id_filter_checkbox) nid_filter_box_layout.addWidget(self._node_id_filter_spinbox, 1) nid_filter_box.setLayout(nid_filter_box_layout) layout.addWidget(nid_filter_box) field_filter_box = QGroupBox('Field filter', self) field_filter_box_layout = QVBoxLayout(self) field_filter_box_layout.addWidget(QLabel('Message is stored in the variable "msg"', self)) field_filter_box_layout.addWidget(self._filter_expression_box) field_filter_box.setLayout(field_filter_box_layout) layout.addWidget(field_filter_box) vis_box = QGroupBox('Visualization', self) vis_box_layout = QHBoxLayout(self) vis_box_layout.addWidget(QLabel('Plot line color', self)) vis_box_layout.addWidget(self._select_color_button) vis_box.setLayout(vis_box_layout) layout.addWidget(vis_box) layout.addWidget(self._ok_button) self.setLayout(layout) self.setFixedHeight(layout.sizeHint().height()) # Initialization self._update_data_type_list() self._on_type_changed()
def create_send_layout(self) -> QVBoxLayout: """ Re-render the layout and it's child widgets of this view. """ # A 4-column grid layout. All the stretch is in the last column. # The exchange rate plugin adds a fiat widget in column 2 self._send_grid = grid = QGridLayout() grid.setSpacing(8) # This ensures all columns are stretched over the full width of the last tab. grid.setColumnStretch(4, 1) self.amount_e = BTCAmountEdit(self) self._payto_e = PayToEdit(self) # From fields row. # This is enabled by "spending" coins in the coins tab. self._from_label = QLabel(_('From'), self) self._from_label.setContentsMargins(0, 5, 0, 0) self._from_label.setAlignment(Qt.AlignTop) grid.addWidget(self._from_label, 1, 0) self._from_list = MyTreeWidget(self, self._main_window.reference(), self.from_list_menu, ['Address / Outpoint', 'Amount']) self._from_list.setMaximumHeight(80) grid.addWidget(self._from_list, 1, 1, 1, -1) self.set_pay_from([]) msg = ( _('Recipient of the funds.') + '\n\n' + _('You may enter a Bitcoin SV address, a label from your list of ' 'contacts (a list of completions will be proposed), or an alias ' '(email-like address that forwards to a Bitcoin SV address)')) payto_label = HelpLabel(_('Pay to'), msg, self) payto_label.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Preferred) grid.addWidget(payto_label, 2, 0) grid.addWidget(self._payto_e, 2, 1, 1, -1) msg = ( _('Amount to be sent.') + '\n\n' + _('The amount will be displayed in red if you do not have ' 'enough funds in your wallet.') + ' ' + _('Note that if you have frozen some of your coins, the available ' 'funds will be lower than your total balance.') + '\n\n' + _('Keyboard shortcut: type "!" to send all your coins.')) amount_label = HelpLabel(_('Amount'), msg, self) grid.addWidget(amount_label, 3, 0) grid.addWidget(self.amount_e, 3, 1) self._fiat_send_e = AmountEdit( app_state.fx.get_currency if app_state.fx else '', self) self.set_fiat_ccy_enabled( bool(app_state.fx and app_state.fx.is_enabled())) grid.addWidget(self._fiat_send_e, 3, 2) self.amount_e.frozen.connect( lambda: self._fiat_send_e.setFrozen(self.amount_e.isReadOnly())) self._max_button = EnterButton(_("Max"), self._spend_max, self) self._max_button.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Preferred) grid.addWidget(self._max_button, 3, 3) completer = QCompleter() completer.setCaseSensitivity(False) self._payto_e.set_completer(completer) completer.setModel(self._completions) msg = (_( 'Description of the transaction (not mandatory).' ) + '\n\n' + _( 'The description is not sent to the recipient of the funds. ' 'It is stored in your wallet file, and displayed in the \'History\' tab.' )) description_label = HelpLabel(_('Description'), msg, self) grid.addWidget(description_label, 4, 0) self._message_e = MyLineEdit(self) grid.addWidget(self._message_e, 4, 1, 1, -1) self._main_window.connect_fields(self.amount_e, self._fiat_send_e) self._coinsplitting_checkbox = QCheckBox( _('Add extra data to ensure the coins used ' 'by the transaction are only used on the Bitcoin SV blockchain (coin-splitting).' ), self) self._coinsplitting_checkbox.setChecked( not self._account.involves_hardware_wallet()) self._coinsplitting_checkbox.setVisible(self._show_splitting_option()) # Hardware wallets can only sign a small set of fixed types of scripts (not this kind). self._coinsplitting_checkbox.setEnabled( not self._account.involves_hardware_wallet()) def coinsplitting_checkbox_cb(state: int) -> None: if state != Qt.Checked: dialogs.show_named('sv-only-disabled') self._coinsplitting_checkbox.stateChanged.connect( coinsplitting_checkbox_cb) grid.addWidget(self._coinsplitting_checkbox, 5, 1, 1, -1) self._help_button = HelpDialogButton(self, "misc", "send-tab", _("Help")) self._preview_button = EnterButton(_("Preview"), self._do_preview, self) self._preview_button.setToolTip( _('Display the details of your transactions before signing it.')) self._send_button = EnterButton(_("Send"), self._do_send, self) if self._main_window.network is None: self._send_button.setEnabled(False) self._send_button.setToolTip( _('You are using ElectrumSV in offline mode; restart ' 'ElectrumSV if you want to get connected')) self._send_button.setVisible(not self._account.is_watching_only()) self._clear_button = EnterButton(_("Clear"), self.clear, self) buttons = QHBoxLayout() buttons.addStretch(1) buttons.addWidget(self._help_button) buttons.addWidget(self._clear_button) buttons.addWidget(self._preview_button) buttons.addWidget(self._send_button) buttons.addStretch(1) grid.addLayout(buttons, 7, 0, 1, -1) self.amount_e.shortcut.connect(self._spend_max) self._payto_e.textChanged.connect(self.update_fee) self.amount_e.textEdited.connect(self.update_fee) def reset_max(t) -> None: # Invoices set the amounts, which invokes this despite them being frozen. if self._payment_request is not None: return self._is_max = False self._max_button.setEnabled(not bool(t)) self.amount_e.textEdited.connect(reset_max) self.amount_e.textChanged.connect(self._on_entry_changed) self._fiat_send_e.textEdited.connect(reset_max) self._invoice_list_toolbar_layout = TableTopButtonLayout() self._invoice_list_toolbar_layout.refresh_signal.connect( self._main_window.refresh_wallet_display) self._invoice_list_toolbar_layout.filter_signal.connect( self._filter_invoice_list) self._invoice_list = InvoiceList(self, self._main_window.reference()) vbox0 = QVBoxLayout() vbox0.addLayout(grid) hbox = QHBoxLayout() hbox.addLayout(vbox0) invoice_layout = QVBoxLayout() invoice_layout.setSpacing(0) invoice_layout.setContentsMargins(6, 0, 6, 6) invoice_layout.addLayout(self._invoice_list_toolbar_layout) invoice_layout.addWidget(self._invoice_list) invoice_box = QGroupBox() invoice_box.setTitle(_('Invoices')) invoice_box.setAlignment(Qt.AlignCenter) invoice_box.setContentsMargins(0, 0, 0, 0) invoice_box.setLayout(invoice_layout) vbox = QVBoxLayout(self) vbox.addLayout(hbox) vbox.addSpacing(20) vbox.addWidget(invoice_box) vbox.setStretchFactor(self._invoice_list, 1000) return vbox
class MainWindow(QMainWindow): def __init__(self, parent=None): super(MainWindow, self).__init__(parent) self.createMenu() self.completingTextEdit = TextEdit() self.completer = QCompleter(self) self.completer.setModel(self.modelFromFile(':/resources/wordlist.txt')) self.completer.setModelSorting(QCompleter.CaseInsensitivelySortedModel) self.completer.setCaseSensitivity(Qt.CaseInsensitive) self.completer.setWrapAround(False) self.completingTextEdit.setCompleter(self.completer) self.setCentralWidget(self.completingTextEdit) self.resize(500, 300) self.setWindowTitle("Completer") def createMenu(self): exitAction = QAction("Exit", self) aboutAct = QAction("About", self) aboutQtAct = QAction("About Qt", self) exitAction.triggered.connect(QApplication.instance().quit) aboutAct.triggered.connect(self.about) aboutQtAct.triggered.connect(QApplication.instance().aboutQt) fileMenu = self.menuBar().addMenu("File") fileMenu.addAction(exitAction) helpMenu = self.menuBar().addMenu("About") helpMenu.addAction(aboutAct) helpMenu.addAction(aboutQtAct) def modelFromFile(self, fileName): f = QFile(fileName) if not f.open(QFile.ReadOnly): return QStringListModel(self.completer) QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) words = [] while not f.atEnd(): line = f.readLine().trimmed() if line.length() != 0: try: line = str(line, encoding='ascii') except TypeError: line = str(line) words.append(line) QApplication.restoreOverrideCursor() return QStringListModel(words, self.completer) def about(self): QMessageBox.about( self, "About", "This example demonstrates the different features of the " "QCompleter class.")
class CalculateMaterial(QVBoxLayout): def __init__(self, material_type=1): super().__init__() self.del_btn = QPushButton("Удалить") self.line = QLineEdit() self.line.setMinimumWidth(100) self.combo_box = QComboBox() self.combo_box.setCurrentText('') self.combo_box.setMaximumWidth(200) self.layout = QHBoxLayout() self.type = material_type self.materials = MATERIALS[material_type - 1] self.completer = QCompleter(self.materials) self.combo_box.setEditable(True) self.create_layout() def create_layout(self): self.combo_box.addItems(self.materials) self.combo_box.setCompleter(self.completer) self.completer.setFilterMode(Qt.MatchContains) self.completer.setCaseSensitivity(Qt.CaseInsensitive) self.combo_box.setCurrentText("") self.line.textChanged.connect(lambda: FinalTable.set_row( win.get_final_table(), CalculationBox.get_full_cost(win.get_calc_box(self.type)), self. type)) self.line.textChanged.connect( lambda: FinalTable.set_sum_row(win.get_final_table())) self.line.textChanged.connect( lambda: FinalTable.set_final_price_row(win.get_final_table())) self.line.textChanged.connect(lambda: input_check(self.line)) self.combo_box.currentTextChanged.connect(lambda: FinalTable.set_row( win.get_final_table(), CalculationBox.get_full_cost(win.get_calc_box(self.type)), self. type)) self.combo_box.currentTextChanged.connect( lambda: FinalTable.set_sum_row(win.get_final_table())) self.combo_box.currentTextChanged.connect( lambda: FinalTable.set_final_price_row(win.get_final_table())) self.line.setPlaceholderText("Количество в м. кв. / шт.") # self.layout.addWidget(QLabel("Количество \n в м. кв. / шт.")) self.layout.addWidget(self.line, 1) self.layout.addWidget(self.combo_box, 1) self.del_btn.setFixedSize(80, 20) self.del_btn.clicked.connect(lambda: clear_layout(self.layout)) self.del_btn.clicked.connect(lambda: FinalTable.set_row( win.get_final_table(), (CalculationBox.get_full_cost( win.get_calc_box(self.type)) - calculate([self])), self.type)) self.del_btn.clicked.connect( lambda: FinalTable.set_sum_row(win.get_final_table())) self.del_btn.clicked.connect( lambda: FinalTable.set_final_price_row(win.get_final_table())) self.layout.addWidget(self.del_btn, 0) self.addLayout(self.layout) def get_size(self): try: return self.line.text() except RuntimeError: return 0 def get_material(self): try: return self.combo_box.currentText() except RuntimeError: return 0 def get_materials_dict(self): try: return dict.copy(self.materials) except RuntimeError: return 0 def self_clear(self): clear_layout(self.layout)
def run_iface_config_window(icon): ifaces = list_ifaces() win = QDialog() win.setWindowTitle('CAN Interface Configuration') win.setWindowIcon(icon) win.setWindowFlags(Qt.CustomizeWindowHint | Qt.WindowTitleHint | Qt.WindowCloseButtonHint) combo = QComboBox(win) combo.setEditable(True) combo.setInsertPolicy(QComboBox.NoInsert) combo.setSizeAdjustPolicy(QComboBox.AdjustToContents) combo.addItems(ifaces.keys()) combo_completer = QCompleter() combo_completer.setCaseSensitivity(Qt.CaseSensitive) combo_completer.setModel(combo.model()) combo.setCompleter(combo_completer) bitrate = QSpinBox() bitrate.setMaximum(1000000) bitrate.setMinimum(10000) bitrate.setValue(1000000) extra_args = QLineEdit() extra_args.setFont(get_monospace_font()) ok = QPushButton('OK', win) result = None kwargs = {} def on_ok(): nonlocal result, kwargs a = str(extra_args.text()) if a: try: kwargs = dict(eval(a)) except Exception as ex: show_error('Invalid parameters', 'Could not parse optional arguments', ex, parent=win) return kwargs['bitrate'] = int(bitrate.value()) result_key = str(combo.currentText()).strip() try: result = ifaces[result_key] except KeyError: result = result_key win.close() ok.clicked.connect(on_ok) layout = QVBoxLayout() layout.addWidget(QLabel('Select CAN interface or serial port for SLCAN:')) layout.addWidget(combo) layout.addWidget(QLabel('Interface bitrate (SLCAN only):')) layout.addWidget(bitrate) layout.addWidget(QLabel('Optional arguments (refer to Pyuavcan for info):')) layout.addWidget(extra_args) layout.addWidget(ok) layout.setSizeConstraint(layout.SetFixedSize) win.setLayout(layout) win.exec() return result, kwargs
def set_functionalities(self): #adding completers completer = QCompleter(product_names) completer.setCaseSensitivity(False) for i in range(15): el_productnames[i].setCompleter(completer) #Listner on product name el_productnames[0].editingFinished.connect(lambda:fillDataProduct(1)) el_productnames[1].editingFinished.connect(lambda:fillDataProduct(2)) el_productnames[2].editingFinished.connect(lambda:fillDataProduct(3)) el_productnames[3].editingFinished.connect(lambda:fillDataProduct(4)) el_productnames[4].editingFinished.connect(lambda:fillDataProduct(5)) el_productnames[5].editingFinished.connect(lambda:fillDataProduct(6)) el_productnames[6].editingFinished.connect(lambda:fillDataProduct(7)) el_productnames[7].editingFinished.connect(lambda:fillDataProduct(8)) el_productnames[8].editingFinished.connect(lambda:fillDataProduct(9)) el_productnames[9].editingFinished.connect(lambda:fillDataProduct(10)) el_productnames[10].editingFinished.connect(lambda:fillDataProduct(11)) el_productnames[11].editingFinished.connect(lambda:fillDataProduct(12)) el_productnames[12].editingFinished.connect(lambda:fillDataProduct(13)) el_productnames[13].editingFinished.connect(lambda:fillDataProduct(14)) el_productnames[14].editingFinished.connect(lambda:fillDataProduct(15)) #Listner on rate products_inputs[0][4].editingFinished.connect(lambda:fillValues(1)) products_inputs[1][4].editingFinished.connect(lambda:fillValues(2)) products_inputs[2][4].editingFinished.connect(lambda:fillValues(3)) products_inputs[3][4].editingFinished.connect(lambda:fillValues(4)) products_inputs[4][4].editingFinished.connect(lambda:fillValues(5)) products_inputs[5][4].editingFinished.connect(lambda:fillValues(6)) products_inputs[6][4].editingFinished.connect(lambda:fillValues(7)) products_inputs[7][4].editingFinished.connect(lambda:fillValues(8)) products_inputs[8][4].editingFinished.connect(lambda:fillValues(9)) products_inputs[9][4].editingFinished.connect(lambda:fillValues(10)) products_inputs[10][4].editingFinished.connect(lambda:fillValues(11)) products_inputs[11][4].editingFinished.connect(lambda:fillValues(12)) products_inputs[12][4].editingFinished.connect(lambda:fillValues(13)) products_inputs[13][4].editingFinished.connect(lambda:fillValues(14)) products_inputs[14][4].editingFinished.connect(lambda:fillValues(15)) #Listner on qty products_inputs[0][3].editingFinished.connect(lambda:fillValues(1)) products_inputs[1][3].editingFinished.connect(lambda:fillValues(2)) products_inputs[2][3].editingFinished.connect(lambda:fillValues(3)) products_inputs[3][3].editingFinished.connect(lambda:fillValues(4)) products_inputs[4][3].editingFinished.connect(lambda:fillValues(5)) products_inputs[5][3].editingFinished.connect(lambda:fillValues(6)) products_inputs[6][3].editingFinished.connect(lambda:fillValues(7)) products_inputs[7][3].editingFinished.connect(lambda:fillValues(8)) products_inputs[8][3].editingFinished.connect(lambda:fillValues(9)) products_inputs[9][3].editingFinished.connect(lambda:fillValues(10)) products_inputs[10][3].editingFinished.connect(lambda:fillValues(11)) products_inputs[11][3].editingFinished.connect(lambda:fillValues(12)) products_inputs[12][3].editingFinished.connect(lambda:fillValues(13)) products_inputs[13][3].editingFinished.connect(lambda:fillValues(14)) products_inputs[14][3].editingFinished.connect(lambda:fillValues(15)) #Listner on CSGT products_inputs[0][6].editingFinished.connect(lambda:fillValues(1)) products_inputs[1][6].editingFinished.connect(lambda:fillValues(2)) products_inputs[2][6].editingFinished.connect(lambda:fillValues(3)) products_inputs[3][6].editingFinished.connect(lambda:fillValues(4)) products_inputs[4][6].editingFinished.connect(lambda:fillValues(5)) products_inputs[5][6].editingFinished.connect(lambda:fillValues(6)) products_inputs[6][6].editingFinished.connect(lambda:fillValues(7)) products_inputs[7][6].editingFinished.connect(lambda:fillValues(8)) products_inputs[8][6].editingFinished.connect(lambda:fillValues(9)) products_inputs[9][6].editingFinished.connect(lambda:fillValues(10)) products_inputs[10][6].editingFinished.connect(lambda:fillValues(11)) products_inputs[11][6].editingFinished.connect(lambda:fillValues(12)) products_inputs[12][6].editingFinished.connect(lambda:fillValues(13)) products_inputs[13][6].editingFinished.connect(lambda:fillValues(14)) products_inputs[14][6].editingFinished.connect(lambda:fillValues(15)) #Listner on SGST products_inputs[0][8].editingFinished.connect(lambda:fillValues(1)) products_inputs[1][8].editingFinished.connect(lambda:fillValues(2)) products_inputs[2][8].editingFinished.connect(lambda:fillValues(3)) products_inputs[3][8].editingFinished.connect(lambda:fillValues(4)) products_inputs[4][8].editingFinished.connect(lambda:fillValues(5)) products_inputs[5][8].editingFinished.connect(lambda:fillValues(6)) products_inputs[6][8].editingFinished.connect(lambda:fillValues(7)) products_inputs[7][8].editingFinished.connect(lambda:fillValues(8)) products_inputs[8][8].editingFinished.connect(lambda:fillValues(9)) products_inputs[9][8].editingFinished.connect(lambda:fillValues(10)) products_inputs[10][8].editingFinished.connect(lambda:fillValues(11)) products_inputs[11][8].editingFinished.connect(lambda:fillValues(12)) products_inputs[12][8].editingFinished.connect(lambda:fillValues(13)) products_inputs[13][8].editingFinished.connect(lambda:fillValues(14)) products_inputs[14][8].editingFinished.connect(lambda:fillValues(15)) vendor_inputs[0].editingFinished.connect(fillVendor) completer = QCompleter(vendors_names) completer.setCaseSensitivity(False) self.vendor_name.setCompleter(completer) #Listener on Buttons self.edit_find.clicked.connect(findClicked) self.new_bill.clicked.connect(newClicked) self.edit_save.clicked.connect(editSaveCliked) self.save_bill.clicked.connect(saveBillClicked) self.print_bill.clicked.connect(printBill) self.refresh.clicked.connect(refreshData) self.comboBox.currentIndexChanged.connect(changeCompany)
class LineEditWithHistory(QLineEdit): elementSelected = pyqtSignal(str) nowTime = 0 oldTime = 0 def __init__(self, parent, title='历史记录', configPath='', qssFilePath="./Resources/stylesheet/style.qss"): super(LineEditWithHistory, self).__init__(parent) self.qssFilePath = qssFilePath if "" == configPath: self.configPath = "./config/{parentName}/LineEditWithHistory.ini".format( parentName=type(parent).__name__) else: if 0 <= os.path.basename(configPath).find("."): self.configPath = configPath else: self.configPath = "{basePath}/LineEditWithHistory.ini".format( basePath=configPath) self.title = title self.sectionName = '{title}'.format(title=self.title) self.HistoryListChanged = False self.commandHasSent = False # 用于存放历史记录的List self.inputList = [] self.__loadHistory() self.__widgetInit() def Exit(self): self.__saveHistory() def __widgetInit(self): # LineEdit设置QCompleter,用于显示历史记录 self.completer = QCompleter(self) self.listModel = QStringListModel(self.inputList, self) self.completer.setCaseSensitivity(Qt.CaseInsensitive) self.completer.setModel(self.listModel) self.completer.activated.connect(self.Slot_completer_activated, type=Qt.QueuedConnection) try: with open(self.qssFilePath, "r") as fh: self.completer.popup().setStyleSheet(fh.read()) except Exception as e: logger.info('读取QSS文件失败' + str(e)) self.setCompleter(self.completer) # 输入完成按下回车后去重添加到历史记录中 self.returnPressed.connect(self.Slot_updateHistoryModule) def __loadHistory(self): historyList = self.inputList historyOp = Public.Public_ConfigOp(self.configPath) rt = historyOp.ReadAllBySection(self.sectionName) if True is rt[0]: for item in rt[1]: if (item[1] not in historyList) and ("" != item[1]): historyList.append(item[1]) else: logger.info(rt[1]) def __saveHistory(self): ipOp = Public.Public_ConfigOp(self.configPath) if True is self.HistoryListChanged: ipOp.RemoveSection(self.sectionName) ipOp.SaveAll() for index, item in enumerate(self.inputList): ipOp.SaveConfig(self.sectionName, str(index), item) def updateHistory(self): content = self.text() if content != "": if content not in self.inputList: self.inputList.append(content) self.listModel.setStringList(self.inputList) self.completer.setCompletionMode(QCompleter.PopupCompletion) self.HistoryListChanged = True self.__sendElement() def Slot_updateHistoryModule(self): self.updateHistory() # 按下回车或单击后恢复显示模式 https://doc.qt.io/qt-5/qcompleter.html#activated def Slot_completer_activated(self, text): self.completer.setCompletionMode(QCompleter.PopupCompletion) self.__sendElement() def __sendElement(self): self.elementSelected.emit(self.text()) def deleteEle(self, ele): if ele in self.inputList: self.inputList.remove(ele) self.listModel.setStringList(self.inputList) self.completer.setCompletionMode(QCompleter.PopupCompletion) self.HistoryListChanged = True def event(self, event): # 按下Tab键时弹出所有记录 if event.type() == QEvent.KeyPress: if event.key() == Qt.Key_Tab: # 设置不过滤显示 https://doc.qt.io/qt-5/qcompleter.html#completionMode-prop if self.completer.completionCount() > 0: self.completer.setCompletionMode( QCompleter.UnfilteredPopupCompletion) self.listModel.setStringList(self.inputList) self.completer.complete() self.completer.popup().show() return True elif event.key() == Qt.Key_Delete: self.deleteEle(self.text()) return super().event(event)
def createWindow(self, mainWindow, placeholder, team): """Create readme sub window.""" super().__init__(None) self.mainWindow = mainWindow self.controller = mainWindow.controller self.team = team self.liquipediaGrabber = LiquipediaGrabber() self.setWindowIcon(QIcon( scctool.settings.getResFile("liquipedia.png"))) self.setWindowModality(Qt.ApplicationModal) mainLayout = QGridLayout() self.qle_search = QLineEdit(placeholder) self.qle_search.setAlignment(Qt.AlignCenter) self.qle_search.returnPressed.connect(self.search) completer = QCompleter( scctool.settings.config.getMyTeams() + self.controller.historyManager.getTeamList(), self.qle_search) completer.setCaseSensitivity(Qt.CaseInsensitive) completer.setCompletionMode(QCompleter.UnfilteredPopupCompletion) completer.setWrapAround(True) self.qle_search.setCompleter(completer) mainLayout.addWidget(self.qle_search, 0, 0, 1, 2) self.searchButton = QPushButton(_("Search")) self.searchButton.clicked.connect(self.search) mainLayout.addWidget(self.searchButton, 0, 2) self.box = QGroupBox(_("Results")) layout = QHBoxLayout() self.result_list = QListWidget() self.result_list.setViewMode(QListWidget.IconMode) self.result_list.itemDoubleClicked.connect(self.doubleClicked) self.result_list.setContextMenuPolicy(Qt.CustomContextMenu) self.result_list.customContextMenuRequested.connect( self.listItemRightClicked) self.result_list.setIconSize(QSize(75, 75)) # list.setWrapping(False) # list.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.result_list.setAcceptDrops(False) self.result_list.setDragEnabled(False) layout.addWidget(self.result_list) self.box.setLayout(layout) mainLayout.addWidget(self.box, 1, 0, 1, 3) self.selectButton = QPushButton(" " + _("Use Selected Logo") + " ") self.selectButton.clicked.connect(self.applyLogo) self.closeButton = QPushButton(_("Cancel")) self.closeButton.clicked.connect(self.close) mainLayout.addItem( QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Minimum), 2, 0) mainLayout.addWidget(self.closeButton, 2, 1) mainLayout.addWidget(self.selectButton, 2, 2) self.setLayout(mainLayout) self.setWindowTitle(_("Liquipedia Image Search")) self.resize( QSize(int(mainWindow.size().width() * 0.9), self.sizeHint().height())) relativeChange = QPoint(int(mainWindow.size().width() / 2), int(mainWindow.size().height() / 3))\ - QPoint(int(self.size().width() / 2), int(self.size().height() / 3)) self.move(mainWindow.pos() + relativeChange)
class MainWindow(QMainWindow): """Main window class.""" def __init__(self, parent=None): """Init class.""" super(MainWindow, self).__init__() QNetworkProxyFactory.setUseSystemConfiguration(True) self.statusBar().showMessage(__doc__ + get_nuitka_version()) self.setWindowTitle(__doc__.strip().capitalize()) self.setMinimumSize(480, 400) self.setMaximumSize(1024, 800) self.resize(self.minimumSize()) self.setWindowIcon(QIcon.fromTheme("python")) self.center() QShortcut("Ctrl+q", self, activated=lambda: self.close()) self.menuBar().addMenu("&File").addAction("Exit", lambda: self.close()) windowMenu = self.menuBar().addMenu("&Window") windowMenu.addAction("Minimize", lambda: self.showMinimized()) windowMenu.addAction("Maximize", lambda: self.showMaximized()) windowMenu.addAction("Restore", lambda: self.showNormal()) windowMenu.addAction("FullScreen", lambda: self.showFullScreen()) windowMenu.addAction("Center", lambda: self.center()) windowMenu.addAction("Top-Left", lambda: self.move(0, 0)) windowMenu.addAction("To Mouse", lambda: self.move_to_mouse_position()) windowMenu.addSeparator() windowMenu.addAction( "Increase size", lambda: self.resize(self.size().width() * 1.4, self.size().height() * 1.4)) windowMenu.addAction("Decrease size", lambda: self.resize( self.size().width() // 1.4, self.size().height() // 1.4)) windowMenu.addAction("Minimum size", lambda: self.resize(self.minimumSize())) windowMenu.addAction("Maximum size", lambda: self.resize(self.maximumSize())) windowMenu.addAction("Horizontal Wide", lambda: self.resize( self.maximumSize().width(), self.minimumSize().height())) windowMenu.addAction("Vertical Tall", lambda: self.resize( self.minimumSize().width(), self.maximumSize().height())) windowMenu.addSeparator() windowMenu.addAction("Disable Resize", lambda: self.setFixedSize(self.size())) windowMenu.addAction("Set Interface Font...", lambda: self.setFont(QFontDialog.getFont()[0])) windowMenu.addAction( "Load .qss Skin", lambda: self.setStyleSheet(self.skin())) helpMenu = self.menuBar().addMenu("&Help") helpMenu.addAction("About Qt 5", lambda: QMessageBox.aboutQt(self)) helpMenu.addAction("About Python 3", lambda: open_new_tab('https://www.python.org')) helpMenu.addAction("About " + __doc__, lambda: QMessageBox.about(self, __doc__, HELP)) helpMenu.addSeparator() helpMenu.addAction( "Keyboard Shortcut", lambda: QMessageBox.information(self, __doc__, "<b>Quit = CTRL+Q")) if sys.platform.startswith('linux'): helpMenu.addAction("View Source Code", lambda: call('xdg-open ' + __file__, shell=True)) helpMenu.addAction("View GitHub Repo", lambda: open_new_tab(__url__)) helpMenu.addAction("Check Updates", lambda: Downloader(self)) # process self.process = QProcess() self.process.readyReadStandardOutput.connect(self._read_output) self.process.readyReadStandardError.connect(self._read_errors) self.process.finished.connect(self._process_finished) self.process.error.connect(self._process_failed) # widgets self.group0, self.group1 = QGroupBox("Options"), QGroupBox("Paths") self.group4, self.group5 = QGroupBox("Details"), QGroupBox("Miscs") g0grid, g1vlay = QGridLayout(self.group0), QGridLayout(self.group1) g5vlay, g4vlay = QVBoxLayout(self.group5), QVBoxLayout(self.group4) # group 0 the options self.module = QCheckBox("Create compiled extension module") self.standalone = QCheckBox("Standalone executable binary output") self.nofreeze = QCheckBox("No freeze all modules of standard library") self.python_debug = QCheckBox("Use Python Debug") self.warning = QCheckBox("Warnings for implicit exceptions at compile") self.recurse_std = QCheckBox("Recursive compile the standard library") self.recurse_not = QCheckBox("Force No recursive compiling") self.execute = QCheckBox("Execute the created binary after compiling") self.pythonpath = QCheckBox("Keep pythonpath when executing") self.enhaced = QCheckBox("Enhaced compile, Not CPython compatible") self.nolineno = QCheckBox("No Statements line numbers on compile") self.rmbuilddir = QCheckBox("Remove build directory after compile.") self.nuitka_debug = QCheckBox("Use Nuitka Debug") self.keep_debug = QCheckBox("Keep debug info on compile for GDB") self.traced = QCheckBox("Traced execution output") self.plusplus = QCheckBox("Compile C++ Only on generated source files") self.experimental = QCheckBox("Experimental features") self.force_clang = QCheckBox("Force use of CLang") self.force_mingw = QCheckBox("Force use of MinGW on MS Windows") self.force_lto = QCheckBox("Use link time optimizations LTO") self.show_scons = QCheckBox("Show Scons executed commands") self.show_progress = QCheckBox("Show progress info and statistics") self.show_summary = QCheckBox("Show final summary of included modules") self.disable_console = QCheckBox("Disable the Console on MS Windows") for i, widget in enumerate(( self.module, self.standalone, self.nofreeze, self.python_debug, self.warning, self.recurse_std, self.recurse_not, self.execute, self.pythonpath, self.enhaced, self.nolineno, self.rmbuilddir, self.nuitka_debug, self.keep_debug, self.traced, self.plusplus, self.experimental, self.force_clang, self.force_mingw, self.force_lto, self.show_scons, self.show_progress, self.show_summary, self.disable_console)): widget.setToolTip(widget.text()) g0grid.addWidget(widget, i if i < i + 1 else i - (i - 1), i % 2) # group 1 paths self.target = QLineEdit() self.outdir = QLineEdit(os.path.expanduser("~")) self.t_icon = QLineEdit() self.target.setToolTip("Python App file you want to Compile to Binary") self.outdir.setToolTip("Folder to write Compiled Output Binary files") self.t_icon.setToolTip("Icon image file to embed for your Python App") self.target.setPlaceholderText("/full/path/to/target/python_app.py") self.outdir.setPlaceholderText("/full/path/to/output/folder/") self.t_icon.setPlaceholderText("/full/path/to/python_app/icon.png") self.completer, self.dirs = QCompleter(self), QDirModel(self) self.completer.setModel(self.dirs) self.completer.setCaseSensitivity(Qt.CaseInsensitive) self.completer.setCompletionMode(QCompleter.PopupCompletion) self.completer.popup().setStyleSheet("border: 1px solid gray") self.completer.popup().setVerticalScrollBarPolicy( Qt.ScrollBarAlwaysOff) self.outdir.setCompleter(self.completer) self.t_icon.setCompleter(self.completer) self.target.setCompleter(self.completer) self.clear_1 = QPushButton(QIcon.fromTheme("edit-clear"), "", self, clicked=lambda: self.target.clear()) self.clear_2 = QPushButton(QIcon.fromTheme("edit-clear"), "", self, clicked=lambda: self.t_icon.clear()) self.clear_3 = QPushButton(QIcon.fromTheme("edit-clear"), "", self, clicked=lambda: self.outdir.clear()) self.open_1 = QPushButton( QIcon.fromTheme("folder-open"), "", self, clicked=lambda: self.target.setText(str(QFileDialog.getOpenFileName( self, __doc__, os.path.expanduser("~"), """Python (*.py);; Python for Windows (*.pyw);;All (*.*)""")[0]))) self.open_2 = QPushButton( QIcon.fromTheme("folder-open"), "", self, clicked=lambda: self.t_icon.setText(str(QFileDialog.getOpenFileName( self, __doc__, os.path.expanduser("~"), "PNG (*.png);;JPG (*.jpg);;ICO (*.ico);;All (*.*)")[0]))) self.open_3 = QPushButton( QIcon.fromTheme("folder-open"), "", self, clicked=lambda: self.outdir.setText(str(QFileDialog.getExistingDirectory( self, __doc__, os.path.expanduser("~"))))) self.l_icon = QLabel("Target Icon") g1vlay.addWidget(QLabel("<b>Target Python"), 0, 0) g1vlay.addWidget(self.target, 0, 1) g1vlay.addWidget(self.clear_1, 0, 2) g1vlay.addWidget(self.open_1, 0, 3) g1vlay.addWidget(self.l_icon, 1, 0) g1vlay.addWidget(self.t_icon, 1, 1) g1vlay.addWidget(self.clear_2, 1, 2) g1vlay.addWidget(self.open_2, 1, 3) g1vlay.addWidget(QLabel("<b>Output Folder"), 2, 0) g1vlay.addWidget(self.outdir, 2, 1) g1vlay.addWidget(self.clear_3, 2, 2) g1vlay.addWidget(self.open_3, 2, 3) # group 4 the dome view mode self.jobs = QSpinBox() self.jobs.setRange(1, cpu_count()) self.jobs.setValue(cpu_count()) self.jobs.setToolTip("Backend Worker Jobs Processes") self.python_version = QComboBox() self.python_version.addItems(["2.7", "3.2", "3.3", "3.4"]) self.python_version.setToolTip("Python version to use with Nuitka") self.display_tree = QPushButton("Display Tree") self.display_tree.clicked.connect( lambda: call(NUITKA + " --display-tree {}".format( self.target.text()), shell=True)) self.dump_tree = QPushButton( "View Docs", clicked=lambda: open_new_tab("http://nuitka.net/doc/user-manual.html")) self.open_log = QPushButton("View Logs") _log = os.path.join(gettempdir(), "nuitka-gui.log") _open = "xdg-open " if sys.platform.startswith("lin") else "open " self.open_log.clicked.connect(lambda: call(_open + _log, shell=True)) self.open_folder = QPushButton("Open Build Folder") self.open_folder.clicked.connect(lambda: call( _open + str(self.outdir.text()).strip(), shell=True)) # self.display_tree.clicked.connect(self._display_tree) g4vlay.addWidget(QLabel("<b>Worker Jobs")) g4vlay.addWidget(self.jobs) g4vlay.addWidget(QLabel("<b>Python Version")) g4vlay.addWidget(self.python_version) g4vlay.addWidget(QLabel("<b>Actions")) g4vlay.addWidget(self.display_tree) g4vlay.addWidget(self.dump_tree) g4vlay.addWidget(self.open_log) g4vlay.addWidget(self.open_folder) # group 5 miscelaneous stuff self.debug, self.scr = QCheckBox("Use Debug"), QCheckBox("Make Script") self.chrt, self.ionice = QCheckBox("Slow CPU"), QCheckBox("Slow HDD") self.minimi = QCheckBox("Auto Minimize") self.chrt.setToolTip("Use Low CPU speed priority (Linux only)") self.ionice.setToolTip("Use Low HDD speed priority (Linux only)") self.scr.setToolTip("Generate a Bash Script to Compile with Nuitka") self.debug.setToolTip("Use Debug Verbose mode") self.minimi.setToolTip("Automatically Minimize when compiling starts") self.scr.setChecked(True) self.chrt.setChecked(True) self.ionice.setChecked(True) self.minimi.setChecked(True) g5vlay.addWidget(self.debug) g5vlay.addWidget(self.scr) g5vlay.addWidget(self.chrt) g5vlay.addWidget(self.ionice) g5vlay.addWidget(self.minimi) # option to show or hide some widgets on the gui self.guimode = QComboBox() self.guimode.addItems(('Full UX / UI', 'Simple UX / UI')) self.guimode.setCurrentIndex(1) self._set_guimode() self.guimode.setStyleSheet("""QComboBox{background:transparent; margin-left:25px;color:gray;text-decoration:underline;border:0}""") self.guimode.currentIndexChanged.connect(self._set_guimode) # buttons from bottom to close or proceed self.bt = QDialogButtonBox(self) self.bt.setStandardButtons( QDialogButtonBox.Ok | QDialogButtonBox.Close) self.bt.rejected.connect(self.close) self.bt.accepted.connect(self.run) if not sys.platform.startswith('lin'): self.scr.setChecked(False) self.chrt.setChecked(False) self.ionice.setChecked(False) self.scr.hide() self.chrt.hide() self.ionice.hide() if not sys.platform.startswith('win'): self.l_icon.hide() self.t_icon.hide() self.clear_2.hide() self.open_2.hide() if sys.platform.startswith('win'): self.display_tree.hide() # container for all groups of widgets container = QWidget() container_layout = QGridLayout(container) # Y, X container_layout.addWidget(self.guimode, 0, 1) container_layout.addWidget(self.group0, 1, 1) container_layout.addWidget(self.group1, 2, 1) container_layout.addWidget(self.group4, 1, 2) container_layout.addWidget(self.group5, 2, 2) container_layout.addWidget(self.bt, 3, 1) self.setCentralWidget(container) def check_paths(self): """Check that the paths are valid.""" if not os.path.isfile(self.target.text()): log.error("Target File not found or not valid.") QMessageBox.warning(self, __doc__.title(), "Target File not found or not valid.") return False if not str(self.target.text()).endswith((".py", ".pyw")): log.error("Target File not valid.") QMessageBox.warning(self, __doc__.title(), "Target File not valid.") return False if not os.path.isdir(self.outdir.text()): log.error("Target Folder not found or not valid.") QMessageBox.warning(self, __doc__.title(), "Target Folder not found or not valid.") return False if self.t_icon.text() and not os.path.isfile(self.t_icon.text()): log.warning("Target Icon File not found or not valid.") QMessageBox.warning(self, __doc__.title(), "Target Icon File not found or not valid.") return True else: return True def generate_build_command(self): """Generate a build command.""" return re.sub(r"\s+", " ", " ".join(( 'chrt --verbose --idle 0' if self.chrt.isChecked() else '', 'ionice --ignore --class 3' if self.ionice.isChecked() else '', NUITKA, '--debug --verbose' if self.debug.isChecked() else '', '--show-progress' if self.show_progress.isChecked() else '', '--show-scons --show-modules' if self.show_scons.isChecked() else '', '--unstriped' if self.keep_debug.isChecked() else '', '--trace-execution' if self.traced.isChecked() else '', '--remove-output' if self.rmbuilddir.isChecked() else '', '--code-gen-no-statement-lines' if self.nolineno.isChecked() else '', '--execute' if self.execute.isChecked() else '', '--recurse-none' if self.recurse_not.isChecked() else '--recurse-all', '--recurse-stdlib' if self.recurse_std.isChecked() else '', '--clang' if self.force_clang.isChecked() else '', '--lto' if self.force_lto.isChecked() else '', '--c++-only' if self.plusplus.isChecked() else '', '--windows-disable-console' if self.disable_console.isChecked() else '', '--experimental' if self.experimental.isChecked() else '', '--python-debug' if self.python_debug.isChecked() else '', '--module' if self.module.isChecked() else '--standalone', '--nofreeze-stdlib' if self.nofreeze.isChecked() else '', '--mingw' if self.force_mingw.isChecked() else '', '--warn-implicit-exceptions' if self.warning.isChecked() else '', '--execute-with-pythonpath' if self.pythonpath.isChecked() else '', '--enhanced' if self.enhaced.isChecked() else '', '--icon="{}"'.format(self.t_icon.text()) if self.t_icon.text() else '', '--python-version={}'.format(self.python_version.currentText()), '--jobs={}'.format(self.jobs.value()), '--output-dir="{}"'.format(self.outdir.text()), '"{}"'.format(self.target.text())))) def run(self): """Run the main method and run Nuitka.""" self.statusBar().showMessage('Working...') log.debug("Working...") if not self.check_paths(): return command_to_run_nuitka = self.generate_build_command() log.debug(command_to_run_nuitka) self.process.start(command_to_run_nuitka) if not self.process.waitForStarted(): log.error(self._read_errors()) return # ERROR if self.scr.isChecked() and sys.platform.startswith("lin"): script_file = str(self.target.text()).replace(".py", "-nuitka-compile.sh") log.debug("Writing Script {}".format(script_file)) with open(script_file, "w", encoding="utf-8") as script: script.write("#!/usr/bin/env bash\n" + command_to_run_nuitka) os.chmod(script_file, 0o755) self.statusBar().showMessage(__doc__.title()) def _process_finished(self): """Finished sucessfuly.""" log.debug("Finished.") self.showNormal() def _read_output(self): """Read and return output.""" return str(self.process.readAllStandardOutput()).strip() def _read_errors(self): """Read and return errors.""" log.debug(self.process.readAllStandardError()) return str(self.process.readAllStandardError()).strip() def _process_failed(self): """Read and return errors.""" self.showNormal() self.statusBar().showMessage(" ERROR: Failed ! ") log.warning(str(self.process.readAllStandardError()).strip().lower()) return str(self.process.readAllStandardError()).strip().lower() def _set_guimode(self): """Switch between simple and full UX.""" for widget in (self.group0, self.group4, self.group5, self.statusBar(), self.menuBar()): widget.hide() if self.guimode.currentIndex() else widget.show() self.resize(self.minimumSize() if self.guimode.currentIndex() else self.maximumSize()) self.center() def skin(self, filename=None): """Open QSS from filename,if no QSS return None,if no filename ask.""" if not filename: filename = str(QFileDialog.getOpenFileName( self, __doc__ + "-Open QSS Skin file", os.path.expanduser("~"), "CSS Cascading Style Sheet for Qt 5 (*.qss);;All (*.*)")[0]) if filename and os.path.isfile(filename): log.debug(filename) with open(filename, 'r') as file_to_read: text = file_to_read.read().strip() if text: log.debug(text) return text def center(self): """Center the Window on the Current Screen,with Multi-Monitor support. >>> MainWindow().center() True """ window_geometry = self.frameGeometry() mousepointer_position = QApplication.desktop().cursor().pos() screen = QApplication.desktop().screenNumber(mousepointer_position) centerPoint = QApplication.desktop().screenGeometry(screen).center() window_geometry.moveCenter(centerPoint) return bool(not self.move(window_geometry.topLeft())) def move_to_mouse_position(self): """Center the Window on the Current Mouse position. >>> MainWindow().move_to_mouse_position() True """ window_geometry = self.frameGeometry() window_geometry.moveCenter(QApplication.desktop().cursor().pos()) return bool(not self.move(window_geometry.topLeft())) def closeEvent(self, event): """Ask to Quit.""" the_conditional_is_true = QMessageBox.question( self, __doc__.title(), 'Quit ?.', QMessageBox.Yes | QMessageBox.No, QMessageBox.No) == QMessageBox.Yes event.accept() if the_conditional_is_true else event.ignore()
def __init__(self, window: 'ElectrumWindow'): QWidget.__init__(self, window) Logger.__init__(self) self.window = window self.wallet = window.wallet self.fx = window.fx self.config = window.config self.network = window.network self.format_amount_and_units = window.format_amount_and_units self.format_amount = window.format_amount self.base_unit = window.base_unit self.payto_URI = None self.payment_request = None # type: Optional[paymentrequest.PaymentRequest] self.pending_invoice = None # A 4-column grid layout. All the stretch is in the last column. # The exchange rate plugin adds a fiat widget in column 2 self.send_grid = grid = QGridLayout() grid.setSpacing(8) grid.setColumnStretch(3, 1) from .paytoedit import PayToEdit self.amount_e = BTCAmountEdit(self.window.get_decimal_point) self.payto_e = PayToEdit(self) msg = (_("Recipient of the funds.") + "\n\n" + _( "You may enter a Bitcoin address, a label from your list of contacts " "(a list of completions will be proposed), " "or an alias (email-like address that forwards to a Bitcoin address)" ) + ". " + _("Lightning invoices are also supported.") + "\n\n" + _( "You can also pay to many outputs in a single transaction, " "specifying one output per line." ) + "\n" + _("Format: address, amount") + "\n" + _( "To set the amount to 'max', use the '!' special character." ) + "\n" + _( "Integers weights can also be used in conjunction with '!', " "e.g. set one amount to '2!' and another to '3!' to split your coins 40-60." )) payto_label = HelpLabel(_('Pay to'), msg) grid.addWidget(payto_label, 1, 0) grid.addWidget(self.payto_e, 1, 1, 1, -1) completer = QCompleter() completer.setCaseSensitivity(False) self.payto_e.set_completer(completer) completer.setModel(self.window.completions) msg = _('Description of the transaction (not mandatory).') + '\n\n' \ + _( 'The description is not sent to the recipient of the funds. It is stored in your wallet file, and displayed in the \'History\' tab.') description_label = HelpLabel(_('Description'), msg) grid.addWidget(description_label, 2, 0) self.message_e = SizedFreezableLineEdit(width=700) grid.addWidget(self.message_e, 2, 1, 1, -1) msg = (_('The amount to be received by the recipient.') + ' ' + _( 'Fees are paid by the sender.' ) + '\n\n' + _( 'The amount will be displayed in red if you do not have enough funds in your wallet.' ) + ' ' + _( 'Note that if you have frozen some of your addresses, the available funds will be lower than your total balance.' ) + '\n\n' + _('Keyboard shortcut: type "!" to send all your coins.')) amount_label = HelpLabel(_('Amount'), msg) grid.addWidget(amount_label, 3, 0) grid.addWidget(self.amount_e, 3, 1) self.fiat_send_e = AmountEdit(self.fx.get_currency if self.fx else '') if not self.fx or not self.fx.is_enabled(): self.fiat_send_e.setVisible(False) grid.addWidget(self.fiat_send_e, 3, 2) self.amount_e.frozen.connect( lambda: self.fiat_send_e.setFrozen(self.amount_e.isReadOnly())) self.window.connect_fields(self.amount_e, self.fiat_send_e) self.max_button = EnterButton(_("Max"), self.spend_max) self.max_button.setFixedWidth(100) self.max_button.setCheckable(True) grid.addWidget(self.max_button, 3, 3) self.save_button = EnterButton(_("Save"), self.do_save_invoice) self.send_button = EnterButton( _("Pay") + "...", self.do_pay_or_get_invoice) self.clear_button = EnterButton(_("Clear"), self.do_clear) buttons = QHBoxLayout() buttons.addStretch(1) buttons.addWidget(self.clear_button) buttons.addWidget(self.save_button) buttons.addWidget(self.send_button) grid.addLayout(buttons, 6, 1, 1, 4) self.amount_e.shortcut.connect(self.spend_max) def reset_max(text): self.max_button.setChecked(False) enable = not bool(text) and not self.amount_e.isReadOnly() # self.max_button.setEnabled(enable) self.amount_e.textEdited.connect(reset_max) self.fiat_send_e.textEdited.connect(reset_max) self.set_onchain(False) self.invoices_label = QLabel(_('Send queue')) from .invoice_list import InvoiceList self.invoice_list = InvoiceList(self) vbox0 = QVBoxLayout() vbox0.addLayout(grid) hbox = QHBoxLayout() hbox.addLayout(vbox0) hbox.addStretch(1) vbox = QVBoxLayout(self) vbox.addLayout(hbox) vbox.addStretch(1) vbox.addWidget(self.invoices_label) vbox.addWidget(self.invoice_list) vbox.setStretchFactor(self.invoice_list, 1000) self.searchable_list = self.invoice_list self.invoice_list.update( ) # after parented and put into a layout, can update without flickering run_hook('create_send_tab', grid) self.payment_request_ok_signal.connect(self.payment_request_ok) self.payment_request_error_signal.connect(self.payment_request_error) self.lnurl6_round1_signal.connect(self.on_lnurl6_round1) self.lnurl6_round2_signal.connect(self.on_lnurl6_round2) self.clear_send_tab_signal.connect(self.do_clear) self.show_error_signal.connect(self.show_error)
class TextEditTechnique(QTextEdit): def __init__(self, text_file, input_trigger=None, active=True): super(TextEditTechnique, self).__init__() self._completer = None self.isActive = active word_list = self.get_suggestion_words(text_file) self.input_trigger = input_trigger # connects the text textChanged event self.textChanged.connect(self.handle_input) self.char_length = 1 self.set_completer(word_list) self.technique_used = False self.no_suggestion_input = "~!@#$%^&*()_+{}|:\"<>?,./;'[]\\-= " # gets words for suggestion def get_suggestion_words(self, text_file): words = [] file = open(text_file) for line in file: for word in line.split(' '): word = word.strip().lower().replace('.', '').replace( ',', '').replace(':', '').replace('?', '') if word and word not in words: words.append(word) file.close() return words # initializes the completer def set_completer(self, words): if self._completer is not None: self._completer.activated.disconnect() self._completer = QCompleter(words, self) self._completer.setCaseSensitivity(Qt.CaseInsensitive) self._completer.setWrapAround(False) self._completer.setWidget(self) self._completer.setCompletionMode(QCompleter.PopupCompletion) self._completer.activated.connect(self.insert_sel_suggestion) # insert the selected suggestion and moves the text cursor def insert_sel_suggestion(self, suggestion): if self._completer.widget() is not self: return text_cursor = self.textCursor() extra = len(suggestion) - len(self._completer.completionPrefix()) text_cursor.movePosition(QTextCursor.Left) text_cursor.movePosition(QTextCursor.EndOfWord) text_cursor.insertText(suggestion[-extra:]) self.setTextCursor(text_cursor) # returns the current typed word def text_under_cursor(self): text_cursor = self.textCursor() text_cursor.select(QTextCursor.WordUnderCursor) return text_cursor.selectedText() # sets the widget def focusInEvent(self, e): if self._completer is not None and self.isActive: self._completer.setWidget(self) super(TextEditTechnique, self).focusInEvent(e) def keyPressEvent(self, e): # behaves like a normal input field! if not self.isActive or self._completer is None: super(TextEditTechnique, self).keyPressEvent(e) return # ignore events funktion keys on Textedit if popup is visible --> popup behaves default if self._completer.popup().isVisible(): if e.key() in (Qt.Key_Enter, Qt.Key_Return, Qt.Key_Escape, Qt.Key_Tab, Qt.Key_Backtab): e.ignore() self.technique_used = True return # writes text in the editfield super(TextEditTechnique, self).keyPressEvent(e) ctrl_or_shift = e.modifiers() & (Qt.ControlModifier | Qt.ShiftModifier) if self._completer is None or (ctrl_or_shift and len(e.text()) == 0): return has_modifier = (e.modifiers() != Qt.NoModifier) and not ctrl_or_shift completion_prefix = self.text_under_cursor() # hide the popup for no chars, modifiers, shift and no text if (has_modifier or len(e.text()) == 0 or len(completion_prefix) < self.char_length or e.text()[-1] in self.no_suggestion_input): self._completer.popup().hide() return # shows the popup with the suggested words if completion_prefix != self._completer.completionPrefix(): self._completer.setCompletionPrefix(completion_prefix) self._completer.popup().setCurrentIndex( self._completer.completionModel().index(0, 0)) cursor = self.cursorRect() cursor.setWidth( self._completer.popup().sizeHintForColumn(0) + self._completer.popup().verticalScrollBar().sizeHint().width()) self._completer.complete(cursor) # event called if textedit input has changed def handle_input(self): timestamp = time.time() self.input_trigger.emit(self.toPlainText(), timestamp) # clears the text input def clear_input(self): self.setHtml('') # deactivates the completer def deactivate_completer(self): self.isActive = False # activates the completer def activate_completer(self): self.isActive = True
def _on_user_find_success(self, job): users = job.ret completer = QCompleter(users) completer.setCaseSensitivity(Qt.CaseInsensitive) self.line_edit_share.setCompleter(completer) self.line_edit_share.completer().complete()