class APISSystemTableEditor(QDialog, FORM_CLASS): def __init__(self, dbm, parent=None): """Constructor.""" self.dbm = dbm super(APISSystemTableEditor, self).__init__(parent) self.table = None self.model = None self.insertQuery = None self.updateQuery = None self.deleteQuery = None self.inputDialog = None self.setupUi(self) self.uiEditBtn.setEnabled(False) self.uiRemoveBtn.setEnabled(False) self.rejected.connect(self.onClose) self.setupTable() def setupTable(self): self.uiSystemTableV.setSelectionBehavior(QAbstractItemView.SelectRows) self.uiSystemTableV.setEditTriggers(QAbstractItemView.NoEditTriggers) self.uiSystemTableV.resizeColumnsToContents() self.uiSystemTableV.resizeRowsToContents() self.uiSystemTableV.horizontalHeader().setSectionResizeMode( QHeaderView.Stretch) def onSelectionChanged(self): if self.uiSystemTableV.selectionModel().hasSelection(): self.uiEditBtn.setEnabled(True) self.uiRemoveBtn.setEnabled(True) else: self.uiEditBtn.setEnabled(False) self.uiRemoveBtn.setEnabled(False) def loadTable(self, table): # check if table in db if not DbHasTable(self.dbm.db, table): return False self.table = table self.dbm.createTriggerForSystemTable(table) # TODO: if returns FALSE then deactivate editing Capabilites + Wanring self.uiSysTableLbl.setText(self.table) self.model = QSqlRelationalTableModel(self, self.dbm.db) self.model.setTable(table) self.model.select() #rc = self.model.rowCount() while (self.model.canFetchMore()): self.model.fetchMore() #rc = self.model.rowCount() self.uiSystemTableV.setModel(self.model) self.uiSystemTableV.selectionModel().selectionChanged.connect( self.onSelectionChanged) self.onSelectionChanged() # dummyRecord holds field structure! dummyRecord = self.model.record() editors = [] for fIdx in range(dummyRecord.count()): field = dummyRecord.field(fIdx) if field.name() != "ogc_fid": editors.append({ 'name': field.name(), 'type': field.type(), 'lineEdit': QLineEdit(), 'default': None }) # init input dialog self.inputDialog = APISInputDialog(editors, dummyRecord, parent=self) self.uiAddBtn.clicked.connect(self.addRecord) self.uiEditBtn.clicked.connect( self.editRecord ) # in EditMode: load current Value; try to update (but with trigger: only possible to update if not in use!!!) self.uiRemoveBtn.clicked.connect(self.removeRecord) return True def addRecord(self): if self.inputDialog.exec_(): rec = self.inputDialog.getRecord() if not rec.isEmpty(): res = self.model.insertRowIntoTable(rec) if res: self.model.select() self.dbm.dbRequiresUpdate = True else: QMessageBox.warning( self, "DB Fehler", "Der folgende Fehler ist aufgetreten: {}".format( self.model.lastError().text())) else: pass self.inputDialog.resetEditors() def editRecord(self): recIdx = self.uiSystemTableV.selectionModel().currentIndex().row() # Get current Record for index currRec = self.model.record(recIdx) # Set current Record in Dialog self.inputDialog.setEditors(currRec) if self.inputDialog.exec_(): data = self.inputDialog.getData() # QMessageBox.information(None, "edited record", f"{data}") for key in data: currRec.setValue(key, data[key]) if not currRec.isEmpty(): res = self.model.updateRowInTable(recIdx, currRec) if res: self.model.select() self.dbm.dbRequiresUpdate = True else: QMessageBox.warning( self, "DB Fehler", "Der folgende Fehler ist aufgetreten: {}".format( self.model.lastError().text())) self.inputDialog.resetEditors() def removeRecord(self): #Check if one really wants to remove the entry! # Abfrage wirklich löschen header = u"Eintrag löschen" question = u"Möchten Sie den Eintrag wirklich aus der Datenbank löschen?" result = QMessageBox.question(self, header, question, QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes) if result == QMessageBox.Yes: recIdx = self.uiSystemTableV.selectionModel().currentIndex().row() # QMessageBox.information(self, "Information", f"Current Idx {recIdx}") res = self.model.removeRow(recIdx) if res: self.model.select() self.dbm.dbRequiresUpdate = True else: QMessageBox.warning( self, "DB Fehler", "Der folgende Fehler ist aufgetreten: {}".format( self.model.lastError().text())) def onClose(self): ''' Run some actions when the user closes the dialog ''' self.uiAddBtn.clicked.disconnect(self.addRecord) self.uiEditBtn.clicked.disconnect(self.editRecord) self.uiRemoveBtn.clicked.disconnect(self.removeRecord) self.inputDialog.deleteLater()
class StampTableWidget(StampTableView): addStampSignal = pyqtSignal(str) # deleteStampSignal = pyqtSignal() surveyModeSignal = pyqtSignal(bool) def __init__(self): super().__init__() self.hasSelection = False # todo self.surveyDatetime = None # init table model self.stampTableModel = QSqlRelationalTableModel() self.stampTableModel.setTable(R.tableName) self.stampTableModel.setEditStrategy(QSqlTableModel.OnFieldChange) self.stampTableModel.setFilter("survey_datetime = None") self.stampTableModel.select() self.stampTableView.setModel(self.stampTableModel) self.stampTableSelectionModel = self.stampTableView.selectionModel() self.stampTableSelectionModel.selectionChanged.connect( self.onStampSelectionChange) # connect buttons self.addStampButton.clicked.connect( lambda ignore, key="-": self.addStampSignal.emit(key)) self.deleteStampButton.clicked.connect(self.deleteButtonAction) self.hotkeyButton.clicked.connect(self.enableHotkeys) # self.recordButton.clicked.connect(self.surveyMode) # hotkeys self.hotkeys = self.initHotkeys() # copy selection to clipboard self.installEventFilter(self) def eventFilter(self, source, event): if (event.type() == QEvent.KeyPress and event.matches(QKeySequence.Copy)): self.copySelection() return True return super().eventFilter(source, event) def copySelection(self): selection = self.stampTableView.selectedIndexes() if selection: rows = sorted(index.row() for index in selection) columns = sorted(index.column() for index in selection) rowcount = rows[-1] - rows[0] + 1 colcount = columns[-1] - columns[0] + 1 table = [[''] * colcount for _ in range(rowcount)] for index in selection: row = index.row() - rows[0] column = index.column() - columns[0] table[row][column] = index.data() stream = io.StringIO() csv.writer(stream).writerows(table) QApplication.clipboard().setText(stream.getvalue()) def initHotkeys(self): keyList = [] shortcut = QShortcut( QKeySequence(Qt.Key_Space, QKeySequence.NativeText), self) keyList.append(shortcut) shortcut.activated.connect( lambda key="-": self.addStampSignal.emit(key)) for i in range(0, 10): print(i) shortcut = QShortcut(QKeySequence(str(i), QKeySequence.NativeText), self) keyList.append(shortcut) shortcut.activated.connect( lambda key=str(i): self.addStampSignal.emit(key)) return keyList def enableHotkeys(self, isClicked): for shortcut in self.hotkeys: shortcut.setEnabled(isClicked) def onDeselection(self): self.enableHotkeys(False) self.hotkeyButton.setChecked(False) # TODO delete def testHotKey(self, key): print("test") print(key) # TODO maybe repaint def loadSurveyStamps(self, keys): print("LSS") self.surveyDatetime = keys[0] filter = self.createFilter(keys) self.stampTableModel.setFilter(filter) self.stampTableModel.select() print("survey_datetime = " + self.surveyDatetime) QApplication.processEvents() self.repaint() def createFilter(self, keys): filter = "survey_datetime = \"" + self.surveyDatetime + "\"" for i in range(1, len(keys)): filter = filter + " OR survey_datetime = \"" + keys[i] + "\"" print(filter) return filter @pyqtSlot() def deleteButtonAction(self): for row in self.stampTableSelectionModel.selectedRows(): self.stampTableModel.removeRow(row.row()) self.stampTableSelectionModel.clearSelection() self.stampTableModel.select() QApplication.processEvents() def clearSurveyStamps(self): self.surveyDatetime = None # self.stampTableModel.setFilter("") # TODO will this work? self.stampTableModel.setFilter("survey_datetime = None") print("survey_datetime = None") def addStamp(self, stamp, key="-"): stampRecord = StampRecord(miliseconds=stamp, surveyDatetime=self.surveyDatetime, label=key, note="") sqlRecord = stampRecord.getQSQLRecord(self.stampTableModel.record()) self.stampTableModel.insertRecord(0, sqlRecord) # self.surveyWidget.sortByKey() # self.surveyWidget.select(0) QApplication.processEvents() # allow for selection highlight def addRecord(self, stampRecord): sqlRecord = stampRecord.getQSQLRecord(self.stampTableModel.record()) print(self.stampTableModel.insertRowIntoTable(sqlRecord)) # self.repaint() # TODO # self.surveyModeSignal.emit(modeOn) # @pyqtSlot(bool) # def enableSurvey(self, canSurvey): # print(canSurvey) # self.recordButton.setEnabled(canSurvey) @pyqtSlot() def testButtonAction(self): print("Test") @pyqtSlot(bool) def surveyMode(self, modeOn): self.addStampButton.setEnabled(modeOn) self.hotkeyButton.setEnabled(modeOn) self.enableHotkeys(self.hotkeyButton.isChecked()) @pyqtSlot(QItemSelection) def onStampSelectionChange(self, selection): self.hasSelection = selection.count() > 0 self.deleteStampButton.setEnabled(self.hasSelection) @pyqtSlot(bool) def enableStamps(self, modeOn): self.addStampButton.setEnabled(modeOn) self.hotkeyButton.setEnabled(modeOn) if not modeOn and self.hotkeyButton.isChecked(): self.hotkeyButton.setChecked(False) self.enableHotkeys(False)
class APISAdvancedInputDialog(QDialog): def __init__(self, dbm, tableName, showEntriesCombo, modelColumnName=None, excludeEntries=None, parent=None): super(APISAdvancedInputDialog, self).__init__(parent) self.dbm = dbm self.tableName = tableName self.modelColumnName = modelColumnName self.showEntriesCombo = showEntriesCombo self.excludeEntries = excludeEntries self.valueToBeAdded = None self.editors = None self.record = None self.tableExists = False if self.prepairEditorsAndRecord(): self.setupForm() else: pass # something went wrong preping def prepairEditorsAndRecord(self): if not DbHasTable(self.dbm.db, self.tableName): return False self.tableExists = True self.model = QSqlRelationalTableModel(self, self.dbm.db) self.model.setTable(self.tableName) self.model.select() while (self.model.canFetchMore()): self.model.fetchMore() self.record = self.model.record() self.editors = [] for fIdx in range(self.record.count()): field = self.record.field(fIdx) if field.name() != "ogc_fid": self.editors.append({ 'name': field.name(), 'type': field.type(), 'lineEdit': QLineEdit() }) return True def setupForm(self): layout = QFormLayout() if self.showEntriesCombo: self.uiAvailableEntriesCombo = QComboBox() # populate (but exlude if exclude has elements) if self.excludeEntries and len(self.excludeEntries) > 0: self.model.setFilter("{0} NOT IN ({1})".format( self.modelColumnName, ",".join("'{0}'".format(i) for i in self.excludeEntries))) # QMessageBox.information(self, "info", "{0} NOT IN ({1})".format(self.modelColumnName, ",".join("'{0}'".format(i) for i in self.excludeEntries))) # self.model.select() self.model.removeColumn(0) self.setupComboBox(self.uiAvailableEntriesCombo, self.model.fieldIndex(self.modelColumnName)) layout.addRow(self.uiAvailableEntriesCombo) self.uiAddBtn = QPushButton("Hinzufügen") if self.uiAvailableEntriesCombo.count() < 1: self.uiAddBtn.setEnabled(False) self.uiAddBtn.clicked.connect(self.addInputToSelection) layout.addRow(self.uiAddBtn) for editor in self.editors: # QMessageBox.information(self, "info", "{}".format((editor["name"]))) if editor["name"] != "ogc_fid": label = QLabel(editor["name"]) # QMessageBox.information(None, "info", "{}".format(editor["type"])) if editor["type"] == QVariant.Int: intVal = QIntValidator() intVal.setBottom(0) editor['lineEdit'].setValidator(intVal) layout.addRow(label, editor['lineEdit']) editor['lineEdit'].textEdited.connect(self.onTextEdited) self.uiSubmitBtn = QPushButton("Speichern") self.uiSubmitBtn.setEnabled(False) self.uiSubmitBtn.clicked.connect(self.saveInputAsQSqlRecord) layout.addRow(self.uiSubmitBtn) self.setLayout(layout) self.setWindowTitle("APIS Input Dialog") self.adjustSize() def onTextEdited(self, text): for editor in self.editors: if len(editor['lineEdit'].text().replace(" ", "")) == 0: self.uiSubmitBtn.setEnabled(False) return self.uiSubmitBtn.setEnabled(True) def addInputToSelection(self): self.setValueToBeAdded(self.uiAvailableEntriesCombo.currentText()) self.accept() def setValueToBeAdded(self, value): self.valueToBeAdded = value def getValueToBeAdded(self): return self.valueToBeAdded def saveInputAsQSqlRecord(self): for editor in self.editors: self.record.setValue(editor["name"], editor['lineEdit'].text()) if not self.record.isEmpty(): result = self.model.insertRowIntoTable(self.record) if result: self.setValueToBeAdded( self.record.field(self.modelColumnName).value()) self.accept() else: QMessageBox.warning( self, "DB Fehler", "Der folgende Feheler ist aufgetreten: {}".format( self.model.lastError().text())) self.reject() else: self.reject() def setupComboBox(self, editor, modelColumn): tv = QTableView() editor.setView(tv) tv.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded) tv.setSelectionMode(QAbstractItemView.SingleSelection) tv.setSelectionBehavior(QAbstractItemView.SelectRows) tv.setAutoScroll(False) editor.setModel(self.model) editor.setModelColumn(modelColumn) editor.setInsertPolicy(QComboBox.NoInsert) tv.resizeColumnsToContents() tv.resizeRowsToContents() tv.verticalHeader().setVisible(False) tv.horizontalHeader().setVisible(True) #tv.setMinimumWidth(tv.horizontalHeader().length()) tv.horizontalHeader().setStretchLastSection(True) #tv.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeToContents) tv.resizeColumnsToContents() scroll = 0 if editor.count() <= editor.maxVisibleItems( ) else QApplication.style().pixelMetric(QStyle.PM_ScrollBarExtent) tv.setMinimumWidth(tv.horizontalHeader().length() + scroll)