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()
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.completerRubro = QCompleter() self.completerMarca = QCompleter() self.completerProveedor = QCompleter() 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) #windowMarca.connect(windowMarca, Qt.SIGNAL('destroyed()'), self.onQuitMarca) self.winPrincipal.txtFilterProductos_p.returnPressed.connect( self.search) #self.cargarTabla() self.winPrincipal.tvProductos_p.setMouseTracking(True) self.winPrincipal.tvProductos_p.setSelectionBehavior( QAbstractItemView.SelectRows) self.setCompleterMarca() self.setCompleterRubro() self.setCompleterProveedor() self.winPrincipal.txtFilterProductos_p.setFocus(True) def finish(self): self.winPrincipal.btnAgregar_p.disconnect() self.winPrincipal.btnGuardar_p.disconnect() self.winPrincipal.btnModificar_p.disconnect() self.winPrincipal.btnBorrar_p.disconnect() self.winPrincipal.btnRubro_p.disconnect() self.winPrincipal.btnMarca_p.disconnect() self.winPrincipal.tvProductos_p.disconnect() def search(self): if self.winPrincipal.txtFilterProductos_p.hasFocus() is True: self.cargarTabla() 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") elif self.winPrincipal.rbMasculino_p.isChecked() is True: self.producto.setGenero("M") else: self.producto.setGenero("I") 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): parameter = self.winPrincipal.txtFilterProductos_p.text() typeParameter = '' if self.winPrincipal.cbFilterProducto_p.currentText() == 'Nombre': typeParameter = 'p.nombre' elif self.winPrincipal.cbFilterProducto_p.currentText() == 'Marca': typeParameter = 'm.descripcion' else: typeParameter = 'r.descripcion' parameterState = 1 if self.winPrincipal.cbInactivo_p.isChecked() is True: parameterState = 0 parameterStock = 1 if self.winPrincipal.cbSinStock_p.isChecked() is True: parameterStock = 0 listaProductos = self.conexionProducto.selectProducto( typeParameter, parameter, parameterState, parameterStock) 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) else: self.winPrincipal.tvProductos_p.setModel(None) 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('') self.completerProveedor.setCurrentRow(0) self.completerRubro.setCurrentRow(0) self.completerMarca.setCurrentRow(0) self.winPrincipal.txtFilterProductos_p.setText('') self.winPrincipal.tvProductos_p.setModel(None) self.winPrincipal.txtFilterProductos_p.setFocus(True) 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) elif self.producto.getGenero() == 'M': self.winPrincipal.rbMasculino_p.setChecked(True) else: self.winPrincipal.rbIndiferente_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() == '': mensaje = "Falta ingresar un Proveedor" elif self.completerMarca.currentCompletion() == '': mensaje = "Falta seleccionar la marca" elif self.completerRubro.currentCompletion() == '': mensaje = 'Falta seleccionar el rubro' """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.dynamicPropertyNames() self.completerRubro.setCaseSensitivity(QtCore.Qt.CaseInsensitive) self.winPrincipal.txtRubro_p.setCompleter(self.completerRubro) def setCompleterProveedor(self): listProveedores = self.conexionProducto.listProveedor() self.completerProveedor = QCompleter(listProveedores) self.completerProveedor.setCaseSensitivity(QtCore.Qt.CaseInsensitive) self.winPrincipal.txtProveedor_p.setCompleter(self.completerProveedor)
class TextStatusEditComplete(TextStatusEdit): """ Adds Completion functions to the base class This class extends 'TextStatusEdit' by: 1. providing a QCompleter to validate lines for the 'fixupText' and 'lineChanged' signals 2. providing a popup for suggested completions as the user is typing 3. auto-completing the line when the user selects a suggestion. The task of auto completion and providing suggestions is provided directly by this class. The task validating and cleaning up text is provided by the PluginFinder. """ def __init__(self, parent: QWidget = None): super().__init__(parent) self._dataModel = None self._monitorDbChanges = False self._enableAutoCompletion = False self._completedAndSelected = False self._completer = QCompleter(self) self._completer.setWidget(self) self._completer.setWrapAround(False) self._completer.setCompletionMode(QCompleter.PopupCompletion) self._completer.setCaseSensitivity(Qt.CaseInsensitive) self._completer.setFilterMode(Qt.MatchStartsWith) self._completer.setModelSorting( QCompleter.CaseInsensitivelySortedModel) self._completer.activated.connect(self.replaceLine) self._pluginFinder = PluginFinder(self._completer, self) self.fixupText.connect(self._pluginFinder.fixupText) self.lineChanged.connect(self._pluginFinder.setRowForLine) QShortcut(Qt.CTRL + Qt.Key_E, self, self.toggleAutoCompletion) QShortcut(Qt.CTRL + Qt.Key_T, self, self.suggestCompletions) # --- Methods related to the completer's underlying data model def setModel(self, model: QAbstractItemModel): self._completer.setModel(model) def _updateModelSignals(self): """ We do not need to check for column changes due to the way our PluginModel is structured. """ if self._dataModel is not None: self._dataModel.rowsMoved.disconnect(self.resetData) self._dataModel.rowsInserted.disconnect(self.resetData) self._dataModel.rowsRemoved.disconnect(self.resetData) self._dataModel.modelReset.disconnect(self.resetData) self._dataModel.dataChanged.disconnect(self.resetData) self._dataModel.layoutChanged.disconnect(self.resetData) if self._monitorDbChanges: self._dataModel = self._completer.model() if self._dataModel is not None: self._dataModel.rowsMoved.connect(self.resetData) self._dataModel.rowsInserted.connect(self.resetData) self._dataModel.rowsRemoved.connect(self.resetData) self._dataModel.modelReset.connect(self.resetData) self._dataModel.dataChanged.connect(self.resetData) self._dataModel.layoutChanged.connect(self.resetData) else: self._dataModel = None def monitorDbChanges(self, enable: bool): """ Enable invalidating line status when the data model changes. Depending on the underlying data model, it may be unnecessary to monitor these changes, or, a higher level class can monitor specific signals more efficiently. So, this is not enabled by default. """ if self._monitorDbChanges == enable: return self._monitorDbChanges = enable if enable: self._dataModel = self._completer.model() self._completer.completionModel().sourceModelChanged.connect( self._updateModelSignals) else: self._completer.completionModel().sourceModelChanged.disconnect( self._updateModelSignals) self._updateModelSignals() # ---- Methods related to line completion def completer(self): return self._completer def enableAutoCompletion(self, enable: bool): self._enableAutoCompletion = enable def toggleAutoCompletion(self): self.enableAutoCompletion(not self._enableAutoCompletion) def _textUnderCursor(self): tc = self.textCursor() if tc.positionInBlock() == 0 and len(tc.block().text()) > 1: tc.movePosition(QTextCursor.NextCharacter) tc.movePosition(QTextCursor.StartOfLine, QTextCursor.KeepAnchor) return tc.selectedText().lstrip() def suggestCompletions(self): if self.isLineInvalid(self.textCursor().blockNumber()): self._suggestCompletionsForText(self._textUnderCursor()) def _suggestCompletionsForText(self, prefix: str): if not prefix: return if prefix != self._completer.completionPrefix(): self._completer.setCompletionPrefix(prefix) self._completer.popup().setCurrentIndex( self._completer.completionModel().index(0, 0)) if self._completer.completionCount() == 1: self._insertSuggestion(self._completer.currentCompletion()) else: rect = self.cursorRect() rect.moveRight(self.statusAreaWidth()) rect.setWidth( self._completer.popup().sizeHintForColumn( self._completer.completionColumn()) + self._completer.popup().verticalScrollBar().sizeHint().width()) self._completer.complete(rect) def _insertSuggestion(self, text: str): """ Only one suggestion matched, prefill line """ cursor = self.textCursor() # handle when cursor is in middle of line if not cursor.atBlockEnd(): cursor.beginEditBlock() cursor.select(QTextCursor.LineUnderCursor) cursor.removeSelectedText() cursor.insertText(text) cursor.movePosition(QTextCursor.StartOfLine) cursor.movePosition(QTextCursor.EndOfLine, QTextCursor.KeepAnchor) self._completedAndSelected = True self.setTextCursor(cursor) cursor.endEditBlock() return # handle when cursor at end of line cursor.beginEditBlock() numCharsToComplete = len(text) - len( self._completer.completionPrefix()) insertionPosition = cursor.position() cursor.movePosition(QTextCursor.EndOfLine, QTextCursor.KeepAnchor) cursor.removeSelectedText() cursor.insertText(text[-numCharsToComplete:]) cursor.setPosition(insertionPosition) cursor.movePosition(QTextCursor.EndOfLine, QTextCursor.KeepAnchor) self._completedAndSelected = True self.setTextCursor(cursor) cursor.endEditBlock() def keyPressEvent(self, event: QKeyEvent): if self._completedAndSelected and self.handledCompletedAndSelected( event): return self._completedAndSelected = False if self._completer.popup().isVisible(): ignoredKeys = [ Qt.Key_Up, Qt.Key_Down, Qt.Key_Enter, Qt.Key_Return, Qt.Key_Tab, Qt.Key_Escape, ] if event.key() in ignoredKeys: event.ignore() return self._completer.popup().hide() super().keyPressEvent(event) if not self._enableAutoCompletion: return ctrlOrShift = (event.modifiers() & Qt.ShiftModifier == Qt.ShiftModifier or event.modifiers() & Qt.ControlModifier == Qt.ControlModifier) if ctrlOrShift and not event.text(): return if self.textCursor().atBlockEnd(): self.suggestCompletions() def mousePressEvent(self, event: QMouseEvent): if self._completedAndSelected: self._completedAndSelected = False self.document().undo() super().mousePressEvent(event) def handledCompletedAndSelected(self, event: QKeyEvent): """ The line is prefilled when only one completion matches. The user can accept the suggestion by pressing 'Enter'. The user can reject the suggestion by pressing 'Esc' or by continuing to type. """ self._completedAndSelected = False cursor = self.textCursor() acceptKeys = [Qt.Key_Enter, Qt.Key_Return, Qt.Key_Tab] if event.key() in acceptKeys: self.replaceLine(self._completer.currentCompletion()) elif event.key() == Qt.Key_Escape: self.document().undo() else: self.document().undo() return False self.setTextCursor(cursor) event.accept() return True def replaceLine(self, text: str): cursor = self.textCursor() cursor.beginEditBlock() cursor.select(QTextCursor.LineUnderCursor) cursor.removeSelectedText() cursor.insertText(text) cursor.movePosition(QTextCursor.EndOfLine) self.setTextCursor(cursor) cursor.endEditBlock() # ---- Methods related to Context Menu def createStandardContextMenu(self, pos: QPoint): menu = super().createStandardContextMenu(pos) menu.addSeparator() autoCompletionAction = menu.addAction( QIcon(), self.tr("Enable Auto Complete"), self.toggleAutoCompletion, QKeySequence(Qt.CTRL + Qt.Key_E), ) autoCompletionAction.setCheckable(True) autoCompletionAction.setChecked(self._enableAutoCompletion) completionAction = menu.addAction( QIcon(), self.tr("Suggest Completions"), self.suggestCompletions, QKeySequence(Qt.CTRL + Qt.Key_T), ) completionAction.setEnabled( self.isLineInvalid(self.textCursor().blockNumber())) return menu
class FilteringComboBox(Widget): """Combination of QCombobox and QLineEdit with autocompletionself. Line edit and completer model is taken from QSqlTable mod Parameters: table (str): db table name containing data for combobox column (str): column name containing data for combobox color (str): 'rgb(r, g, b)' used for primary color font_size (int): default text font size in pt _model (QSqlTableModel): data model _col (int): display data model source coulumn _proxy (QSortFilterProxyModel): completer data model. _proxy.sourceModel() == _model _le (QLineEdit): QCombobox LineEdit Methods: createEditor(): (Widget): returns user input widgets value(): (str): returns user input text value setValue(value(str)): sets editor widget display value style(): (str): Returns CSS stylesheet string for input widget updateModel(): updates input widget model Args: table (str): db table name containing data for combobox column (str): column name containing data for combobox """ def __init__(self, parent, placeholderText, table, column, color='rgb(0,145,234)', image=''): self.table = table self.column = column self.color = color super().__init__(parent, placeholderText, image) self.updateModel() def createEditor(self): # setup data model self._model = QSqlTableModel() self._model.setTable(self.table) self._col = self._model.fieldIndex(self.column) # setup filter model for sorting and filtering self._proxy = QSortFilterProxyModel() self._proxy.setFilterCaseSensitivity(Qt.CaseInsensitive) self._proxy.setSourceModel(self._model) self._proxy.setFilterKeyColumn(self._col) # setup completer self._completer = QCompleter() self._completer.setModel(self._proxy) self._completer.setCompletionColumn(self._col) self._completer.setCompletionMode(QCompleter.UnfilteredPopupCompletion) # setup combobox editor = QComboBox() editor.setModel(self._proxy) editor.setModelColumn(self._col) editor.setEditable(True) editor.setFocusPolicy(Qt.StrongFocus) editor.setInsertPolicy(QComboBox.NoInsert) editor.setCompleter(self._completer) # setup connections editor.currentTextChanged[str].connect(self.onActivated) # setup editor appearence style = self.style() editor.setStyleSheet(style) editor.lineEdit().setStyleSheet(style) font = editor.font() self._completer.popup().setFont(font) return editor @pyqtSlot(str) def onActivated(self, text): print('combo_box filter text', text) if not text: # placeholder text displayed and label is not visible self._editor.setCurrentIndex(-1) if self.toggle: self._label.showLabel(False) else: # selected text is displayed and label is visible # self._editor.showPopup() # self._editor.lineEdit().setFocus() print('current copmpletion string', self._completer.currentCompletion()) self._proxy.setFilterFixedString(text) if self.toggle: self._label.showLabel(True) def style(self): """Returns stylesheet for editors Returns: style (str) """ style = """ QLineEdit {{ border: none; padding-bottom: 2px; border-bottom: 1px solid rgba(0,0,0,0.42); background-color: white; color: rgba(0,0,0,0.42); font-size: {font_size}pt;}} QLineEdit:editable {{ padding-bottom: 2px; border-bottom: 1px rgba(0,0,0,0.42); color: rgba(0,0,0,0.42);}} QLineEdit:disabled {{ border: none; padding-bottom: 2px; border-bottom: 1px rgba(0,0,0,0.42); color: rgba(0,0,0,0.38);}} QLineEdit:hover {{ padding-bottom: 2px; border-bottom: 2px solid rgba(0,0,0,0.6); color: rgba(0,0,0,0.54); }} QLineEdit:focus {{ padding-bottom: 2px; border-bottom: 2px solid {color}; color: rgba(0,0,0,0.87);}} QLineEdit:pressed {{ border-bottom: 2px {color}; font: bold; color: rgba(0,0,0,0.87)}} QComboBox {{ border: none; padding-bottom: 2px; font-size: {font_size}pt; }} QComboBox::down-arrow {{ image: url('dropdown.png'); background-color: white; border: 0px white; padding: 0px; margin: 0px; height:14px; width:14px;}} QComboBox::drop-down{{ subcontrol-position: center right; border: 0px; margin: 0px; }} QComboBox QAbstractItemView {{ font: {font_size};}} """.format(color=self.color, font_size=self._editor_font_size, dropdown=DROPDOWN_PNG) return style def updateModel(self): model = self._editor.model().sourceModel() col = self._editor.modelColumn() model.select() model.sort(col, Qt.AscendingOrder) def value(self): return self._editor.currentText() def setValue(self, value): self._editor.setCurrentText(value)
class ImageManager(QMainWindow, Ui_Manager): _signal_update_image_id = pyqtSignal(QModelIndex, int) def __init__(self, parent=None): super(ImageManager, self).__init__(parent) self.setupUi(self) self.__db_helper = DBHelper(self.db_error_handler) # 数据库操作 # 下拉列表设置 self.__type_model = MyBaseListModel() self.comboBox_type.setModel(self.__type_model) self.__type_model.add_items(self.__db_helper.get_model_data_list('type')) self.comboBox_type.setCurrentIndex(0) self.__level_model = MyBaseListModel() self.comboBox_level.setModel(self.__level_model) levels = self.__db_helper.get_model_data_list('level') for i in range(len(levels)): level = levels[i] if level.id == 10: levels.remove(level) levels.insert(4, level) self.__level_model.add_items(levels) self.comboBox_level.setCurrentIndex(0) # 图片信息 self.__image_model = ImageFileListModel(self) self.__image_model.delete_repeat = self.checkBox_delete_repeat.isChecked() self.__config = ConfigHelper(self) threading.Thread(target=self._load_default_images, daemon=True).start() self.lineEdit_sql_where.setText(self.__config.get_config_key('history', 'sqlWhere')) self.lineEdit_export_dir.setText(self.__config.get_config_key('history', 'lastExportDir')) self.listView.setModel(self.__image_model) # 关联事件 self.listView.selectionModel().currentChanged.connect(self.__on_list_view_current_row_change) self.listView.set_key_press_delegate(self.key_press_delegate) self.listView.set_action_show_file_directory_delegate(self.open_file_directory) self.pushButton_classify.clicked.connect(self.__classify) self.pushButton_search.clicked.connect(self.__search) self.pushButton_clean.clicked.connect(self.__clean_not_exist_images) self.checkBox_delete_repeat.clicked.connect(self._on_check_box_delete_repeat_click) self.actionOpen.triggered.connect(self.__open_files) self.lineEdit_sql_where.returnPressed.connect(self.__search) self.pushButton_export_dir.clicked.connect(self.__choose_export_dir) self.pushButton_export.clicked.connect(self.__choose_export) self.lineEdit_desc.returnPressed.connect(self.__classify) self.lineEdit_tag.returnPressed.connect(self.__classify) self.lineEdit_role.returnPressed.connect(self.__classify) self.lineEdit_works.returnPressed.connect(self.__classify) self.lineEdit_series.returnPressed.connect(self.__classify) self.lineEdit_source.returnPressed.connect(self.__classify) self.lineEdit_uploader.returnPressed.connect(self.__classify) self.lineEdit_author.returnPressed.connect(self.__classify) self._signal_update_image_id.connect(self._update_image_id) # 设置 tab 切换顺序 self.setTabOrder(self.lineEdit_desc, self.lineEdit_tag) self.setTabOrder(self.lineEdit_tag, self.lineEdit_path) self.setTabOrder(self.lineEdit_path, self.comboBox_type) self.setTabOrder(self.comboBox_type, self.comboBox_level) self.setTabOrder(self.comboBox_level, self.lineEdit_role) self.setTabOrder(self.lineEdit_role, self.lineEdit_works) self.setTabOrder(self.lineEdit_works, self.lineEdit_series) self.setTabOrder(self.lineEdit_series, self.lineEdit_source) self.setTabOrder(self.lineEdit_source, self.lineEdit_uploader) self.setTabOrder(self.lineEdit_uploader, self.lineEdit_author) self.setTabOrder(self.lineEdit_author, self.pushButton_classify) self.setTabOrder(self.pushButton_classify, self.pushButton_search) # 自动补全 self.__completer_list = [] self.__completer_filename = 'works.txt' if not os.path.exists(self.__completer_filename): f = open(self.__completer_filename, 'w', encoding='utf-8') f.close() with open(self.__completer_filename, 'r+', encoding='utf-8') as f: self.__completer_list = list(map(lambda x: x.replace("\n", "").replace("\r", ""), f.readlines())) self.completer = QCompleter(self.__completer_list) self.completer.setCompletionMode(QCompleter.InlineCompletion) self.completer.setFilterMode(Qt.MatchContains) self.lineEdit_works.setCompleter(self.completer) self.lineEdit_works.editingFinished.connect(self.__add_complete) # Image.MAX_IMAGE_PIXELS = 1882320000 self.listView.setFocus() # 预加载图片 threading.Thread(target=self.__preload, daemon=True).start() def __add_complete(self): """ 添加自动补全作品 :return: """ cur_completion = self.completer.currentCompletion() if cur_completion == "": self.__completer_list.append(self.lineEdit_works.text()) self.completer = QCompleter(self.__completer_list) self.completer.setCompletionMode(QCompleter.InlineCompletion) self.completer.setFilterMode(Qt.MatchContains) self.lineEdit_works.setCompleter(self.completer) print(self.__completer_list) def _load_default_images(self): last_dir = self.__config.get_config_key('history', 'lastDir') if os.path.isdir(last_dir) and os.path.exists(last_dir): self.__image_model.add_path(last_dir) if self.__image_model.rowCount() > 0: self.listView.setCurrentIndex(self.__image_model.index(0, 0)) def __open_files(self): """ 打开图片文件 :return: """ path_list = \ QtWidgets.QFileDialog.getOpenFileNames(self, "选择文件", filter='图片(*.jpg *.png *.gif *.jpeg *.bmp)')[0] # 生成List使用的Model for path in path_list: tp_lists = path.split('/') item_data = ImageFile( name="%s/%s" % (tp_lists[-2], tp_lists[-1]), full_path=path ) self.__image_model.addItem(item_data) def __choose_export_dir(self): """ 选择保存文件夹 :return: """ dir_path = QtWidgets.QFileDialog.getExistingDirectory(self, "选择保存的文件夹", "E:/图片") self.lineEdit_export_dir.setText(dir_path) def __show_image(self, index): """ 显示指定索引文件名对应的图片 :param index: 文件索引 :return: """ path = self.__image_model.get_item(index).full_path start_time = time.time() status = f"[{index + 1}/{self.__image_model.rowCount()}] {path}" try: # 填充缩放 pixmap, is_preload = self.__get_image(path) cur_time = time.time() status += f"\t是否预加载:{is_preload}\t图片读取:${round((cur_time - start_time) * 1000, 2)}ms" start_time = time.time() # 加载图片 item = QtWidgets.QGraphicsPixmapItem(pixmap) scene = QtWidgets.QGraphicsScene() scene.addItem(item) self.graphicsView.setScene(scene) cur_time = time.time() status += f"\t图片加载:${round((cur_time - start_time) * 1000, 2)}ms" except Exception as e: print(e) QMessageBox.information(self, "提示", str(e), QMessageBox.Ok) self.__analysis_file_info(path) self.statusbar.showMessage(status) def __on_list_view_current_row_change(self, current: QModelIndex, previous: QModelIndex): """ 图片列表当前行变化事件 :param current: 当前行索引 :param previous: :return: """ self.__show_image(current.row()) def __analysis_file_info(self, path): info = self.__db_helper.search_by_file_path(path) if not info: # 分析图片信息 self.lineEdit_path.setText(path) info = ImageHelper.analyze_image_info(path) self.lineEdit_size.setText(f"{info.size} MB") self.dateTimeEdit_file_create.setDateTime(info.create_time) self.lineEdit_desc.setText(info.desc) self.lineEdit_tag.setText(info.tags) if info.source: self.lineEdit_source.setText(info.source) if info.uploader: self.lineEdit_uploader.setText(info.uploader) if info.author: self.lineEdit_author.setText(info.author) return # 显示已有记录 self.lineEdit_desc.setText(info.desc) self.lineEdit_tag.setText(info.tags) self.lineEdit_path.setText(info.path) self.lineEdit_works.setText(info.works) self.lineEdit_source.setText(info.source) self.lineEdit_role.setText(info.role) self.lineEdit_author.setText(info.author) self.lineEdit_series.setText(info.series) self.lineEdit_uploader.setText(info.uploader) self.lineEdit_size.setText(f"{info.size} MB") self.comboBox_type.setCurrentIndex(self.__type_model.get_index(info.type_id)) self.comboBox_level.setCurrentIndex(self.__level_model.get_index(info.level_id)) self.dateTimeEdit_file_create.setDateTime(info.file_create_time) self.dateTimeEdit_create.setDateTime(info.create_time) self.dateTimeEdit_update.setDateTime(info.update_time) def __classify(self): """ 分类图片 :return: """ select_rows = self.listView.selectionModel().selectedRows() select_rows = [x for x in select_rows] th = threading.Thread(target=self.__insert_or_update_db, args=(select_rows,), daemon=True) th.start() end_index = select_rows[-1] self.__select_index(self.__image_model.index(end_index.row() + 1, end_index.column())) def __insert_or_update_db(self, select_rows): index = self.comboBox_type.currentIndex() type_id = self.__type_model.get_item(index).id index = self.comboBox_level.currentIndex() level_id = self.__level_model.get_item(index).id desc = self.lineEdit_desc.text() author = self.lineEdit_author.text() tags = self.lineEdit_tag.text() works = self.lineEdit_works.text() role = self.lineEdit_role.text() source = self.lineEdit_source.text() series = self.lineEdit_series.text() uploader = self.lineEdit_uploader.text() for i in range(len(select_rows)): item = self.__image_model.get_item(select_rows[i].row()) path = item.full_path image = MyImage(id=item.id, desc=desc, author=author, type_id=type_id, level_id=level_id, tags=tags, works=works, role=role, source=source, width=self.lineEdit_width.text(), height=self.lineEdit_height.text(), size=FileHelper.get_file_size_in_mb(path), filename=item.name, path=path, md5=FileHelper.get_md5(path), file_create_time=FileHelper.get_create_time_str(path), series=series, uploader=uploader) if image.id == 0: self.__db_helper.insert_image(image) image_id = self.__db_helper.get_id_by_path(path) self._signal_update_image_id.emit(select_rows[i], image_id) self.dateTimeEdit_create.setDateTime(datetime.datetime.now()) self.dateTimeEdit_update.setDateTime(datetime.datetime.now()) # message = f"{item.name} 创建完成!" else: # 批量更新时,保持原来的描述、作者、等级、标签、作品 old_image = self.__image_model.get_database_item(image.id) if old_image and len(select_rows) > 1: image.desc = old_image.desc image.author = old_image.author image.level_id = old_image.level_id image.tags = old_image.tags image.works = old_image.works self.__db_helper.update_image(image) self.dateTimeEdit_update.setDateTime(datetime.datetime.now()) message = f"{item.name} 更新完成!" self.statusbar.showMessage(f"[{i + 1}/{len(select_rows)}] {message}") # end_index = select_rows[-1] def _update_image_id(self, index: QModelIndex, image_id: int): self.__image_model.set_image_id(index,image_id) def __select_index(self, index: QModelIndex): if 0 < index.row() < self.__image_model.rowCount(): self.listView.setCurrentIndex(index) self.listView.setFocus() else: self.listView.clearFocus() self.listView.setFocus() def __del_select_rows(self): """ 删除选中行 :return: """ select_rows = self.listView.selectionModel().selectedRows() if len(select_rows) == 0: return first_index = select_rows[0] for i in range(len(select_rows)): index = select_rows[i] item = self.__image_model.get_item(index.row() - i) if item.id != 0: self.__db_helper.delete(item.id) os.remove(item.full_path) self.__image_model.delete_item(index.row() - i) self.statusbar.showMessage(f"[{i + 1}/{len(select_rows)}] {item.name} 删除成功!") if len(select_rows) > 1: self.listView.clearSelection() # 如果删除到了最后一行,则刷新上一个 if first_index.row() >= self.__image_model.rowCount(): if first_index.row() == 0: return else: self.listView.setCurrentIndex(self.listView.model().index(first_index.row() - 1, first_index.column())) else: if len(select_rows) > 1: self.listView.setCurrentIndex(first_index) else: self.__show_image(first_index.row()) def __search(self): sql_where = self.lineEdit_sql_where.text() if not sql_where: sql_where = "" if len(self.lineEdit_desc.text()): sql_where += f" `desc` like '%{self.lineEdit_desc.text()}%'" if len(self.lineEdit_role.text()): sql_where += f" `role` like '%{self.lineEdit_role.text()}%'" if len(self.lineEdit_works.text()): sql_where += f" `works` like '%{self.lineEdit_works.text()}%'" if len(self.lineEdit_series.text()): sql_where += f" `series` like '%{self.lineEdit_series.text()}%'" if len(self.lineEdit_source.text()): sql_where += f" `source` like '%{self.lineEdit_source.text()}%'" if len(self.lineEdit_uploader.text()): sql_where += f" `uploader` like '%{self.lineEdit_uploader.text()}%'" if len(self.lineEdit_author.text()): sql_where += f" `author` like '%{self.lineEdit_author.text()}%'" image_sql_list, image_file_list = self.__db_helper.search_by_where(sql_where) if len(image_sql_list) > 0: self.__image_model.set_images(image_sql_list, image_file_list) self.listView.setFocus() self.listView.scrollToTop() def __choose_export(self): dir_path = self.lineEdit_export_dir.text() if not os.path.exists(dir_path): os.makedirs(dir_path) if not os.path.isdir(dir_path): return for i in range(self.__image_model.rowCount()): image = self.__image_model.get_item(i) if image.id: image_sql = self.__image_model.get_database_item(image.id) if not os.path.exists(image_sql.path): continue try: FileHelper.copyfile_without_override(image_sql.path, dir_path) except Exception as e: print(e) else: FileHelper.copyfile_without_override(image.full_path, dir_path) self.statusbar.showMessage(f"[{i + 1}/{self.__image_model.rowCount()}] {image.name} 复制成功!") def _on_check_box_delete_repeat_click(self): print(f'是否删除重复:{self.checkBox_delete_repeat.isChecked()}') self.__image_model.delete_repeat = self.checkBox_delete_repeat.isChecked() # region 重写 Qt 控件方法 def keyPressEvent(self, event: QtGui.QKeyEvent) -> None: # 键盘快捷键事件 if event.key() == Qt.Key_R and QApplication.keyboardModifiers() == Qt.ControlModifier: self.__classify() self.listView.setFocus() if event.key() == Qt.Key_E and QApplication.keyboardModifiers() == Qt.ControlModifier: self.comboBox_level.setFocus() if event.key() == Qt.Key_W and QApplication.keyboardModifiers() == Qt.ControlModifier: self.lineEdit_works.setText("") # if event.key() == Qt.Key_Delete: # self.__del_select_rows() def key_press_delegate(self, event: QtGui.QKeyEvent): level_index = None if event.key() == Qt.Key_1: level_index = 1 if event.key() == Qt.Key_2: level_index = 2 if event.key() == Qt.Key_3: level_index = 3 if event.key() == Qt.Key_4: level_index = 4 if event.key() == Qt.Key_5: level_index = 5 if event.key() == Qt.Key_6: level_index = 6 if event.key() == Qt.Key_7: level_index = 7 if event.key() == Qt.Key_8: level_index = 8 if event.key() == Qt.Key_9: level_index = 9 if level_index and self.__level_model.rowCount() >= level_index: self.comboBox_level.setCurrentIndex(level_index - 1) return True if event.key() == Qt.Key_R: self.__classify() return True if event.key() == Qt.Key_E: self.lineEdit_role.setFocus() return True if event.key() == Qt.Key_C: self.lineEdit_works.setText("") return True if event.key() == Qt.Key_D: self.__del_select_rows() return True if event.key() == Qt.Key_W: current_index = self.listView.currentIndex() if current_index.row() > 0: self.listView.setCurrentIndex(self.__image_model.index(current_index.row() - 1, current_index.column())) return True if event.key() == Qt.Key_S: current_index = self.listView.currentIndex() if current_index.row() < self.__image_model.rowCount() - 1: self.listView.setCurrentIndex(self.__image_model.index(current_index.row() + 1, current_index.column())) return True return False def dragEnterEvent(self, e: QtGui.QDragEnterEvent) -> None: # 设置允许接收 e.accept() def dropEvent(self, e: QtGui.QDropEvent) -> None: # 接收文件夹和文件以刷新图片列表 urls = e.mimeData().urls() th = threading.Thread(target=self.__load_list_data, args=(urls,), daemon=True) th.start() def __load_list_data(self, urls): self.__image_model.clear() for url in urls: self.__image_model.add_path(url.toLocalFile()) if self.__image_model.rowCount() > 0: self.listView.setCurrentIndex(self.__image_model.index(0, 0)) if not os.path.isdir(urls[0].toLocalFile()): return self.__config.add_config_key('history', 'lastDir', urls[0].toLocalFile()) def closeEvent(self, event: QtGui.QCloseEvent) -> None: self.__config.add_config_key('history', 'lastExportDir', self.lineEdit_export_dir.text()) self.__config.add_config_key('history', 'sqlWhere', self.lineEdit_sql_where.text()) # 关闭时保存自动填充作品列表的配置文件 with open(self.__completer_filename, 'w+', encoding='utf-8') as f: f.writelines(list(map(lambda x: x + "\n", self.__completer_list))) # endregion # region 预加载图片 __preload_count = 5 __preload_image_queue = queue.Queue(__preload_count) __preload_image_size = queue.Queue(__preload_count) __preload_lock = threading.Lock() def __preload(self): while True: if self.__preload_image_queue.qsize() == 5: time.sleep(1) continue index = self.listView.currentIndex().row() preload_index = index + self.__preload_image_queue.qsize() + 1 image_file = self.__image_model.get_item(preload_index) if not image_file: time.sleep(1) continue full_path = image_file.full_path try: pixmap, width, height = ImageHelper.get_image_from_file(full_path, self.graphicsView.width(), self.graphicsView.height()) self.__preload_image_queue.put(PreloadImage(full_path, pixmap)) self.__preload_image_size.put((width, height)) print(f"预加载成功:{full_path}") except Exception as e: print(e) print(f"预加载失败:{full_path}") time.sleep(1) def __get_image(self, path): # 优先从队列中获取 while self.__preload_image_queue.qsize() > 0: image = self.__preload_image_queue.get() size = self.__preload_image_size.get() if isinstance(image, PreloadImage) and image.full_path == path: print("从预载中读取") self.lineEdit_width.setText(str(size[0])) self.lineEdit_height.setText(str(size[1])) return image.pixmap, True print("从文件中读取") image, width, height = ImageHelper.get_image_from_file(path, self.graphicsView.width(), self.graphicsView.height()) self.lineEdit_width.setText(str(width)) self.lineEdit_height.setText(str(height)) return image, False # endregion def __clean_not_exist_images(self): """ 清理不存在的图片 :return: """ th = threading.Thread( target=ImageHelper.refresh_recode_info, args=(self.db_error_handler,self.show_status_message,), daemon=True ) th.start() def show_status_message(self, message): self.statusbar.showMessage(message) def open_file_directory(self): """ 打开文件所在目录并选中文件 :return: """ select_rows = self.listView.selectionModel().selectedRows() if not len(select_rows): return file_path = self.__image_model.get_item(select_rows[0].row()).full_path FileHelper.open_file_directory(file_path) def db_error_handler(self, error_str): QMessageBox.information(self, "提示", error_str, QMessageBox.Ok)
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.completerRubro = QCompleter() self.completerMarca = QCompleter() self.completerProveedor = QCompleter() 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) #windowMarca.connect(windowMarca, Qt.SIGNAL('destroyed()'), self.onQuitMarca) self.winPrincipal.txtFilterProductos_p.returnPressed.connect(self.search) #self.cargarTabla() self.winPrincipal.tvProductos_p.setMouseTracking(True) self.winPrincipal.tvProductos_p.setSelectionBehavior(QAbstractItemView.SelectRows) self.setCompleterMarca() self.setCompleterRubro() self.setCompleterProveedor() self.winPrincipal.txtFilterProductos_p.setFocus(True) def finish(self): self.winPrincipal.btnAgregar_p.disconnect() self.winPrincipal.btnGuardar_p.disconnect() self.winPrincipal.btnModificar_p.disconnect() self.winPrincipal.btnBorrar_p.disconnect() self.winPrincipal.btnRubro_p.disconnect() self.winPrincipal.btnMarca_p.disconnect() self.winPrincipal.tvProductos_p.disconnect() def search(self): if self.winPrincipal.txtFilterProductos_p.hasFocus() is True: self.cargarTabla() 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") elif self.winPrincipal.rbMasculino_p.isChecked() is True: self.producto.setGenero("M") else: self.producto.setGenero("I") 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): parameter = self.winPrincipal.txtFilterProductos_p.text() typeParameter = '' if self.winPrincipal.cbFilterProducto_p.currentText() == 'Nombre': typeParameter = 'p.nombre' elif self.winPrincipal.cbFilterProducto_p.currentText() == 'Marca': typeParameter = 'm.descripcion' else: typeParameter = 'r.descripcion' parameterState = 1 if self.winPrincipal.cbInactivo_p.isChecked() is True: parameterState = 0 parameterStock = 1 if self.winPrincipal.cbSinStock_p.isChecked() is True: parameterStock = 0 listaProductos = self.conexionProducto.selectProducto(typeParameter, parameter, parameterState, parameterStock) 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) else: self.winPrincipal.tvProductos_p.setModel(None) 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('') self.completerProveedor.setCurrentRow(0) self.completerRubro.setCurrentRow(0) self.completerMarca.setCurrentRow(0) self.winPrincipal.txtFilterProductos_p.setText('') self.winPrincipal.tvProductos_p.setModel(None) self.winPrincipal.txtFilterProductos_p.setFocus(True) 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) elif self.producto.getGenero() == 'M': self.winPrincipal.rbMasculino_p.setChecked(True) else: self.winPrincipal.rbIndiferente_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() =='': mensaje= "Falta ingresar un Proveedor" elif self.completerMarca.currentCompletion() == '': mensaje = "Falta seleccionar la marca" elif self.completerRubro.currentCompletion() == '': mensaje = 'Falta seleccionar el rubro' """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.dynamicPropertyNames() self.completerRubro.setCaseSensitivity(QtCore.Qt.CaseInsensitive) self.winPrincipal.txtRubro_p.setCompleter(self.completerRubro) def setCompleterProveedor(self): listProveedores = self.conexionProducto.listProveedor() self.completerProveedor = QCompleter(listProveedores) self.completerProveedor.setCaseSensitivity(QtCore.Qt.CaseInsensitive) self.winPrincipal.txtProveedor_p.setCompleter(self.completerProveedor)