Пример #1
0
class DBViewWindow(QWidget, Ui_DB_View_Form):
    def __init__(self, database_name):
        super().__init__()
        # uic.loadUi('db_view.ui', self)
        self.setupUi(self)
        # self.db_name = database_name
        # # Подключение БД к таблице отображения
        # # Подключение через QSqlRelationalTableModel
        # self.db = QSqlDatabase.addDatabase('QSQLITE')
        # self.db.setDatabaseName(self.db_name)
        # self.db.open()
        self.model = QSqlRelationalTableModel(self)
        self.model.setTable('goods')
        self.model.setRelation(
            5, QSqlRelation('statuses', 'id_status', 'status_name'))
        self.model.setRelation(
            6, QSqlRelation('goods_types', 'id_goods_type', 'goods_type_name'))
        self.model.setRelation(
            7,
            QSqlRelation('goods_subtypes', 'id_goods_subtype',
                         'goods_subtype_name'))
        self.model.setRelation(
            8, QSqlRelation('location', 'id_location', 'location_name'))
        self.model.setRelation(
            9, QSqlRelation('responsibles', 'id_responsible', 'FIO'))
        self.refresh()
        self.tableView.doubleClicked.connect(self.table_clicked)
        # self.tableView.clicked.connect()
        self.refreshBtn.clicked.connect(self.refresh)
        self.save_all_btn.clicked.connect(self.submitall)

    def table_clicked(self):
        row = self.tableView.currentIndex().row()
        if row != -1:
            self.tableView.selectRow(row)
        index = self.tableView.currentIndex()
        self.edit_form = EditForm(index, self.model)
        self.edit_form.show()

    # Предположительно на выходе будет закрываться БД
    def __exit__(self, exc_type, exc_val, exc_tb):
        self.db.close()
        super().__exit__()

    def refresh(self):
        self.model.select()
        self.tableView.setModel(self.model)
        self.tableView.setItemDelegate(QSqlRelationalDelegate(self.tableView))

    def submitall(self):
        if not self.model.submitAll():
            print(self.model.lastError())
        else:
            self.refresh()
Пример #2
0
class TableModel():

    def __init__(self, db):
        self.model = QSqlRelationalTableModel(db=db)

        self.model.setTable('balance')
        self.model.setEditStrategy(QSqlRelationalTableModel.OnFieldChange)
        self.model.setRelation(1, QSqlRelation('items', 'id', 'name'))
        self.model.setRelation(2, QSqlRelation('categories', 'id', 'name'))
        self.model.setRelation(4, QSqlRelation('currencies', 'id', 'name'))
        self.model.setRelation(5, QSqlRelation('users', 'id', 'full_name'))
        self.model.setRelation(6, QSqlRelation('places', 'id', 'name'))
        self.model.setRelation(8, QSqlRelation('measures', 'id', 'short'))

        self.model.setHeaderData(0, Qt.Horizontal, QtGui.qApp.tr("ID"))
        self.model.setHeaderData(1, Qt.Horizontal, QtGui.qApp.tr("Item"))
        self.model.setHeaderData(2, Qt.Horizontal, QtGui.qApp.tr("Category"))
        self.model.setHeaderData(3, Qt.Horizontal, QtGui.qApp.tr("Cost"))
        self.model.setHeaderData(4, Qt.Horizontal, QtGui.qApp.tr("Currency"))
        self.model.setHeaderData(5, Qt.Horizontal, QtGui.qApp.tr("By whom"))
        self.model.setHeaderData(6, Qt.Horizontal, QtGui.qApp.tr("Where"))
        self.model.setHeaderData(7, Qt.Horizontal, QtGui.qApp.tr("Qty/Amount"))
        self.model.setHeaderData(8, Qt.Horizontal, QtGui.qApp.tr("Units"))
        self.model.setHeaderData(9, Qt.Horizontal, QtGui.qApp.tr("is spending"))
        self.model.setHeaderData(10, Qt.Horizontal, QtGui.qApp.tr("Note"))
        self.model.setHeaderData(11, Qt.Horizontal, QtGui.qApp.tr("Date and "
                                                                  "Time"))
        self.model.removeColumn(12)
        self.model.removeColumn(13)

        if not self.model.select():
            _log("Table model selection error[%s]: %s" % (
                self.model.lastError().type(), self.model.lastError().text()
            ))

    def get_model(self):
        return self.model
Пример #3
0
class QmyMainWindow(QMainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)  #调用父类构造函数,创建窗体
        self.ui = Ui_MainWindow()  #创建UI对象
        self.ui.setupUi(self)  #构造UI界面

        self.setCentralWidget(self.ui.tableView)

        #   tableView显示属性设置
        self.ui.tableView.setSelectionBehavior(QAbstractItemView.SelectItems)
        self.ui.tableView.setSelectionMode(QAbstractItemView.SingleSelection)
        self.ui.tableView.setAlternatingRowColors(True)

        self.ui.tableView.verticalHeader().setDefaultSectionSize(22)
        self.ui.tableView.horizontalHeader().setDefaultSectionSize(100)

##  ==============自定义功能函数============

    def __getFieldNames(self):  ##获取所有字段名称
        emptyRec = self.tabModel.record()  #获取空记录,只有字段名
        self.fldNum = {}  #字段名与序号的字典
        for i in range(emptyRec.count()):
            fieldName = emptyRec.fieldName(i)
            self.fldNum.setdefault(fieldName)
            self.fldNum[fieldName] = i
        print(self.fldNum)

    def __openTable(self):  ##打开数据表
        self.tabModel = QSqlRelationalTableModel(self, self.DB)  #数据表

        self.tabModel.setTable("studInfo")  #设置数据表
        self.tabModel.setEditStrategy(QSqlTableModel.OnManualSubmit
                                      )  #数据保存方式,OnManualSubmit , OnRowChange
        self.tabModel.setSort(self.tabModel.fieldIndex("studID"),
                              Qt.AscendingOrder)  #排序

        if (self.tabModel.select() == False):  #查询数据失败
            QMessageBox.critical(
                self, "错误信息",
                "打开数据表错误,错误信息\n" + self.tabModel.lastError().text())
            return

        self.__getFieldNames()  #获取字段名和序号

        ##字段显示名
        self.tabModel.setHeaderData(self.fldNum["studID"], Qt.Horizontal, "学号")
        self.tabModel.setHeaderData(self.fldNum["name"], Qt.Horizontal, "姓名")
        self.tabModel.setHeaderData(self.fldNum["gender"], Qt.Horizontal, "性别")
        self.tabModel.setHeaderData(self.fldNum["departID"], Qt.Horizontal,
                                    "学院")
        self.tabModel.setHeaderData(self.fldNum["majorID"], Qt.Horizontal,
                                    "专业")

        ##    设置代码字段的查询关系数据表
        self.tabModel.setRelation(self.fldNum["departID"],
                                  QSqlRelation("departments", "departID",
                                               "department"))  #学院
        self.tabModel.setRelation(self.fldNum["majorID"],
                                  QSqlRelation("majors", "majorID",
                                               "major"))  #专业

        self.selModel = QItemSelectionModel(self.tabModel)  #关联选择模型

        ##selModel当前项变化时触发currentChanged信号
        self.selModel.currentChanged.connect(self.do_currentChanged)
        ##选择行变化时
        ##      self.selModel.currentRowChanged.connect(self.do_currentRowChanged)

        self.ui.tableView.setModel(self.tabModel)  #设置数据模型
        self.ui.tableView.setSelectionModel(self.selModel)  #设置选择模型

        delgate = QSqlRelationalDelegate(self.ui.tableView)
        self.ui.tableView.setItemDelegate(delgate)  #为关系型字段设置缺省代理组件

        self.tabModel.select()  #必须重新查询数据
        ##更新actions和界面组件的使能状态
        self.ui.actOpenDB.setEnabled(False)

        self.ui.actRecAppend.setEnabled(True)
        self.ui.actRecInsert.setEnabled(True)
        self.ui.actRecDelete.setEnabled(True)
        self.ui.actFields.setEnabled(True)

##  ==========由connectSlotsByName() 自动连接的槽函数==================

    @pyqtSlot()
    def on_actOpenDB_triggered(self):
        dbFilename, flt = QFileDialog.getOpenFileName(
            self, "选择数据库文件", "", "SQL Lite数据库(*.db *.db3)")
        if (dbFilename == ''):
            return

        #打开数据库
        self.DB = QSqlDatabase.addDatabase("QSQLITE")  #添加 SQL LITE数据库驱动
        self.DB.setDatabaseName(dbFilename)  #设置数据库名称
        ##    DB.setHostName()
        ##    DB.setUserName()
        ##    DB.setPassword()
        if self.DB.open():  #打开数据库
            self.__openTable()  #打开数据表
        else:
            QMessageBox.warning(self, "错误", "打开数据库失败")

    @pyqtSlot()  ##保存修改
    def on_actSubmit_triggered(self):
        res = self.tabModel.submitAll()
        if (res == False):
            QMessageBox.information(
                self, "消息", "数据保存错误,错误信息\n" + self.tabModel.lastError().text())
        else:
            self.ui.actSubmit.setEnabled(False)
            self.ui.actRevert.setEnabled(False)

    @pyqtSlot()  ##取消修改
    def on_actRevert_triggered(self):
        self.tabModel.revertAll()
        self.ui.actSubmit.setEnabled(False)
        self.ui.actRevert.setEnabled(False)

    @pyqtSlot()  ##添加记录
    def on_actRecAppend_triggered(self):
        self.tabModel.insertRow(self.tabModel.rowCount(),
                                QModelIndex())  #在末尾添加一个记录
        curIndex = self.tabModel.index(self.tabModel.rowCount() - 1,
                                       1)  #创建最后一行的ModelIndex
        self.selModel.clearSelection()  #清空选择项
        self.selModel.setCurrentIndex(
            curIndex, QItemSelectionModel.Select)  #设置刚插入的行为当前选择行

    @pyqtSlot()  ##插入记录
    def on_actRecInsert_triggered(self):
        curIndex = self.ui.tableView.currentIndex()  #QModelIndex
        self.tabModel.insertRow(curIndex.row(), QModelIndex())
        self.selModel.clearSelection()  #清除已有选择
        self.selModel.setCurrentIndex(curIndex, QItemSelectionModel.Select)

    @pyqtSlot()  ##删除记录
    def on_actRecDelete_triggered(self):
        curIndex = self.selModel.currentIndex()  #获取当前选择单元格的模型索引
        self.tabModel.removeRow(curIndex.row())  #删除最后一行

    @pyqtSlot()  ##显示字段列表
    def on_actFields_triggered(self):
        emptyRec = self.tabModel.record()  #获取空记录,只有字段名
        str = ''
        for i in range(emptyRec.count()):
            str = str + emptyRec.fieldName(i) + '\n'
        QMessageBox.information(self, "所有字段名", str)

##  =============自定义槽函数===============================

    def do_currentChanged(self, current, previous):  ##更新actPost和actCancel 的状态
        self.ui.actSubmit.setEnabled(self.tabModel.isDirty())  #有未保存修改时可用
        self.ui.actRevert.setEnabled(self.tabModel.isDirty())
Пример #4
0
    def __init__(self, parent=None):
        super().__init__(parent)

        horizontalLayout = QHBoxLayout()
        self.dayView = QTableView()
        self.dayView.setFrameShape(QFrame.Box)
        self.dayView.horizontalHeader().setStretchLastSection(True)
        self.dayView.verticalHeader().setVisible(False)
        horizontalLayout.addWidget(self.dayView)

        verticalLayout = QVBoxLayout()
        self.calendarWidget = QCalendarWidget()
        self.calendarWidget.setMinimumSize(QSize(250, 200))
        self.calendarWidget.setMaximumSize(QSize(250, 200))
        self.calendarWidget.setMinimumDate(QDate(2017, 1, 1))
        self.calendarWidget.setMaximumDate(QDate(2030, 1, 1))
        self.calendarWidget.selectionChanged.connect(self.dataChange)
        self.calendarWidget.setSelectedDate(QDate.currentDate())

        verticalLayout.addWidget(self.calendarWidget)

        titleFV = QLabel('Food View')
        verticalLayout.addWidget(titleFV)

        self.filterLine = QLineEdit()
        self.filterLine.setMaximumSize(QSize(200, 25))

        self.filterLine.textChanged.connect(self.filterChange)

        buttonAdd = QPushButton(QIcon("images/add.png"), '', None)
        buttonAdd.setMaximumSize(QSize(20, 30))
        buttonAdd.clicked.connect(self.addFood)
        buttonDell = QPushButton(QIcon("images/del.png"), '', None)
        buttonDell.setMaximumSize(QSize(20, 30))
        buttonDell.clicked.connect(self.delFood)

        lineEditLayout = QHBoxLayout()
        lineEditLayout.addWidget(self.filterLine)
        lineEditLayout.addWidget(buttonAdd)
        lineEditLayout.addWidget(buttonDell)

        verticalLayout.addLayout(lineEditLayout)

        self.foodView = QTableView()
        self.foodView.setMinimumSize(QSize(0, 0))
        self.foodView.setMaximumSize(QSize(250, 1000))
        self.foodView.verticalHeader().setVisible(False)
        self.foodView.horizontalHeader().setStretchLastSection(True)

        verticalLayout.addWidget(self.foodView)
        horizontalLayout.addLayout(verticalLayout)

        self.setLayout(horizontalLayout)

        model_in = QSqlRelationalTableModel()
        model_in.setEditStrategy(QSqlTableModel.OnFieldChange)
        model_in.setTable("intake_food")

        id_food = model_in.fieldIndex("id_food")
        date = model_in.fieldIndex("food_date")
        mass = model_in.fieldIndex("mass")

        # Set model, hide ID column
        model_in.setRelation(id_food, QSqlRelation("food", "id", "name"))
        model_in.setHeaderData(id_food, Qt.Horizontal, "Food")
        model_in.setHeaderData(date, Qt.Horizontal, "Date")
        model_in.setHeaderData(mass, Qt.Horizontal, "Mass")

        if not model_in.select():
            self.showError(model_in.lastError())
            return

        self.proxyModel_in = QSortFilterProxyModel()
        self.proxyModel_in.setSourceModel(model_in)
        self.proxyModel_in.setFilterKeyColumn(2)

        self.dayView.setItemDelegate(FlipProxyDelegate())
        self.dayView.setModel(self.proxyModel_in)
        self.dayView.setColumnHidden(0, True)
        self.dayView.setColumnHidden(2, True)
        self.dayView.setSelectionMode(QAbstractItemView.SingleSelection)
        self.dayView.setContextMenuPolicy(Qt.CustomContextMenu)
        self.dayView.customContextMenuRequested.connect(self.ShowContextMenu)
        # filter day food by calendar widget
        self.dataChange()

        self.model_f = QSqlRelationalTableModel()
        self.model_f.setEditStrategy(QSqlTableModel.OnFieldChange)
        self.model_f.setTable("food")

        self.model_f.setHeaderData(1, Qt.Horizontal, "Food")
        self.model_f.setHeaderData(2, Qt.Horizontal, "Rate")

        if not self.model_f.select():
            self.showError(self.model_f.lastError())
            return

        self.proxyModel_f = QSortFilterProxyModel()
        self.proxyModel_f.setSourceModel(self.model_f)
        self.proxyModel_f.setFilterKeyColumn(1)

        self.foodView.setModel(self.proxyModel_f)
        self.foodView.setColumnHidden(0, True)
        self.foodView.setSelectionMode(QAbstractItemView.SingleSelection)
        self.foodView.setColumnWidth(1, 150)
        self.foodView.setColumnWidth(2, 90)
Пример #5
0
class MyWidget(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)

        horizontalLayout = QHBoxLayout()
        self.dayView = QTableView()
        self.dayView.setFrameShape(QFrame.Box)
        self.dayView.horizontalHeader().setStretchLastSection(True)
        self.dayView.verticalHeader().setVisible(False)
        horizontalLayout.addWidget(self.dayView)

        verticalLayout = QVBoxLayout()
        self.calendarWidget = QCalendarWidget()
        self.calendarWidget.setMinimumSize(QSize(250, 200))
        self.calendarWidget.setMaximumSize(QSize(250, 200))
        self.calendarWidget.setMinimumDate(QDate(2017, 1, 1))
        self.calendarWidget.setMaximumDate(QDate(2030, 1, 1))
        self.calendarWidget.selectionChanged.connect(self.dataChange)
        self.calendarWidget.setSelectedDate(QDate.currentDate())

        verticalLayout.addWidget(self.calendarWidget)

        titleFV = QLabel('Food View')
        verticalLayout.addWidget(titleFV)

        self.filterLine = QLineEdit()
        self.filterLine.setMaximumSize(QSize(200, 25))

        self.filterLine.textChanged.connect(self.filterChange)

        buttonAdd = QPushButton(QIcon("images/add.png"), '', None)
        buttonAdd.setMaximumSize(QSize(20, 30))
        buttonAdd.clicked.connect(self.addFood)
        buttonDell = QPushButton(QIcon("images/del.png"), '', None)
        buttonDell.setMaximumSize(QSize(20, 30))
        buttonDell.clicked.connect(self.delFood)

        lineEditLayout = QHBoxLayout()
        lineEditLayout.addWidget(self.filterLine)
        lineEditLayout.addWidget(buttonAdd)
        lineEditLayout.addWidget(buttonDell)

        verticalLayout.addLayout(lineEditLayout)

        self.foodView = QTableView()
        self.foodView.setMinimumSize(QSize(0, 0))
        self.foodView.setMaximumSize(QSize(250, 1000))
        self.foodView.verticalHeader().setVisible(False)
        self.foodView.horizontalHeader().setStretchLastSection(True)

        verticalLayout.addWidget(self.foodView)
        horizontalLayout.addLayout(verticalLayout)

        self.setLayout(horizontalLayout)

        model_in = QSqlRelationalTableModel()
        model_in.setEditStrategy(QSqlTableModel.OnFieldChange)
        model_in.setTable("intake_food")

        id_food = model_in.fieldIndex("id_food")
        date = model_in.fieldIndex("food_date")
        mass = model_in.fieldIndex("mass")

        # Set model, hide ID column
        model_in.setRelation(id_food, QSqlRelation("food", "id", "name"))
        model_in.setHeaderData(id_food, Qt.Horizontal, "Food")
        model_in.setHeaderData(date, Qt.Horizontal, "Date")
        model_in.setHeaderData(mass, Qt.Horizontal, "Mass")

        if not model_in.select():
            self.showError(model_in.lastError())
            return

        self.proxyModel_in = QSortFilterProxyModel()
        self.proxyModel_in.setSourceModel(model_in)
        self.proxyModel_in.setFilterKeyColumn(2)

        self.dayView.setItemDelegate(FlipProxyDelegate())
        self.dayView.setModel(self.proxyModel_in)
        self.dayView.setColumnHidden(0, True)
        self.dayView.setColumnHidden(2, True)
        self.dayView.setSelectionMode(QAbstractItemView.SingleSelection)
        self.dayView.setContextMenuPolicy(Qt.CustomContextMenu)
        self.dayView.customContextMenuRequested.connect(self.ShowContextMenu)
        # filter day food by calendar widget
        self.dataChange()

        self.model_f = QSqlRelationalTableModel()
        self.model_f.setEditStrategy(QSqlTableModel.OnFieldChange)
        self.model_f.setTable("food")

        self.model_f.setHeaderData(1, Qt.Horizontal, "Food")
        self.model_f.setHeaderData(2, Qt.Horizontal, "Rate")

        if not self.model_f.select():
            self.showError(self.model_f.lastError())
            return

        self.proxyModel_f = QSortFilterProxyModel()
        self.proxyModel_f.setSourceModel(self.model_f)
        self.proxyModel_f.setFilterKeyColumn(1)

        self.foodView.setModel(self.proxyModel_f)
        self.foodView.setColumnHidden(0, True)
        self.foodView.setSelectionMode(QAbstractItemView.SingleSelection)
        self.foodView.setColumnWidth(1, 150)
        self.foodView.setColumnWidth(2, 90)

    def showError(self, err):

        QMessageBox.critical(self, "Unable to initialize Database",
                             "Error initializing database: " + err.text())

    def filterChange(self):
        regExp = QRegExp(self.filterLine.text(), Qt.CaseInsensitive,
                         QRegExp.FixedString)
        self.proxyModel_f.setFilterRegExp(regExp)

    def dataChange(self):
        date = self.calendarWidget.selectedDate().toString('dd.MM.yyyy')
        regExp = QRegExp(date, Qt.CaseInsensitive, QRegExp.FixedString)
        self.proxyModel_in.setFilterRegExp(regExp)

    def addFood(self):
        self.model_f.insertRow(self.model_f.rowCount())

    def delFood(self):
        self.model_f.removeRow(self.foodView.currentIndex().row())
        self.model_f.select()

    def resizeEvent(self, event):
        self.dayView.setColumnWidth(1, self.dayView.width() * 0.7)
        self.dayView.setColumnWidth(3, self.dayView.width() * 0.2)

        QWidget.resizeEvent(self, event)

    def ShowContextMenu(self, pos):
        contextMenu = QMenu("Context menu", self)

        action1 = QAction("Add food eaten", self)
        contextMenu.addAction(action1)
        contextMenu.exec(self.mapToGlobal(pos))
Пример #6
0
class QmyMainWindow(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.setCentralWidget(self.ui.tableView)

        self.ui.tableView.setSelectionBehavior(QAbstractItemView.SelectItems)
        self.ui.tableView.setSelectionMode(QAbstractItemView.SingleSelection)
        self.ui.tableView.setAlternatingRowColors(True)

        self.ui.tableView.verticalHeader().setDefaultSectionSize(22)
        self.ui.tableView.horizontalHeader().setDefaultSectionSize(100)

    def __getFieldNames(self):
        emptyRec = self.tabModel.record()
        self.fldNum = {}
        for i in range(emptyRec.count()):
            fieldName = emptyRec.fieldName(i)
            self.fldNum.setdefault(fieldName)
            self.fldNum[fieldName] = i
        print(self.fldNum)

    def __openTable(self):
        self.tabModel = QSqlRelationalTableModel(self, self.DB)
        self.tabModel.setTable("studInfo")
        self.tabModel.setEditStrategy(QSqlTableModel.OnManualSubmit)
        self.tabModel.setSort(self.tabModel.fieldIndex("studID"),
                              Qt.AscendingOrder)

        if (self.tabModel.select() == False):
            QMessageBox.critical(
                self, "错误信息",
                "打开数据表错误,错误信息\n" + self.tabModel.lastError().text())
            return

        self.__getFieldNames()
        self.tabModel.setHeaderData(self.fldNum["studID"], Qt.Horizontal, "学号")
        self.tabModel.setHeaderData(self.fldNum["name"], Qt.Horizontal, "姓名")
        self.tabModel.setHeaderData(self.fldNum["gender"], Qt.Horizontal, "性别")
        self.tabModel.setHeaderData(self.fldNum["departID"], Qt.Horizontal,
                                    "学院")
        self.tabModel.setHeaderData(self.fldNum["majorID"], Qt.Horizontal,
                                    "专业")

        self.tabModel.setRelation(
            self.fldNum["departID"],
            QSqlRelation("departments", "departID", "department"))
        self.tabModel.setRelation(self.fldNum["majorID"],
                                  QSqlRelation("majors", "majorID", "major"))

        self.selModel = QItemSelectionModel(self.tabModel)
        self.selModel.currentChanged.connect(self.do_currentChanged)

        self.ui.tableView.setModel(self.tabModel)
        self.ui.tableView.setSelectionModel(self.selModel)

        delgate = QSqlRelationalDelegate(self.ui.tableView)
        self.ui.tableView.setItemDelegate(delgate)

        self.tabModel.select()

        self.ui.actOpenDB.setEnabled(False)
        self.ui.actRecAppend.setEnabled(True)
        self.ui.actRecInsert.setEnabled(True)
        self.ui.actRecDelete.setEnabled(True)
        self.ui.actFields.setEnabled(True)

    @pyqtSlot()
    def on_actOpenDB_triggered(self):
        dbFilename, flt = QFileDialog.getOpenFileName(
            self, "选择数据库文件", "", "SQL Lite数据库(*.db *.db3)")
        if (dbFilename == ''):
            return
        self.DB = QSqlDatabase.addDatabase("QSQLITE")
        self.DB.setDatabaseName(dbFilename)
        if self.DB.open():
            self.__openTable()
        else:
            QMessageBox.warning(self, "错误", "打开数据库失败了")

    @pyqtSlot()
    def on_actSubmit_triggered(self):
        res = self.tabModel.submitAll()
        if (res == False):
            QMessageBox.information(
                self, "消息", "数据保存错误,错误信息\n" + self.tabModel.lastError().text())
        else:
            self.ui.actSubmit.setEnabled(False)
            self.ui.actRevert.setEnabled(False)

    @pyqtSlot()
    def on_actRevert_triggered(self):
        self.tabModel.revertAll()
        self.ui.actSubmit.setEnabled(False)
        self.ui.actRevert.setEnabled(False)

    @pyqtSlot()
    def on_actRecInsert_triggered(self):
        curIndex = self.ui.tableView.currentIndex()
        self.tabModel.insertRow(curIndex.row(), QModelIndex())
        self.selModel.clearSelection()
        self.selModel.setCurrentIndex(curIndex, QItemSelectionModel.Select)

    @pyqtSlot()
    def on_actRecDelete_triggered(self):
        curIndex = self.selModel.currentIndex()
        self.tabModel.removeRow(curIndex.row())

    @pyqtSlot()
    def on_actFields_triggered(self):
        emptyRec = self.tabModel.record()
        str = ''
        for i in range(emptyRec.count()):
            str = str + emptyRec.fieldName(i) + '\n'
        QMessageBox.information(self, "所有字段名", str)

    def do_currentChanged(self, current, previous):
        self.ui.actSubmit.setEnabled(self.tabModel.isDirty())
        self.ui.actRevert.setEnabled(self.tabModel.isDirty())
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 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)