Beispiel #1
0
class MainWindow(QMainWindow):
    def __init__(self, labeltool, parent=None):
        try:
            QMainWindow.__init__(self, parent)
        except:
            print('QMainWindow:bad init')
        self.idletimer = QTimer()
        self.loader = None

        self.labeltool = labeltool
        self.setupGui()
        self.loadApplicationSettings()
        self.onAnnotationsLoaded()  # uncommenting crashes on Anaconda

    # Slots
    def onPluginLoaded(self, action):
        self.ui.menuPlugins.addAction(action)

    def onStatusMessage(self, message=''):
        self.statusBar().showMessage(message, 5000)

    def onModelDirtyChanged(self, dirty):
        postfix = "[+]" if dirty else ""
        if self.labeltool.getCurrentFilename() is not None:
            self.setWindowTitle("%s - %s %s" % \
                (APP_NAME, QFileInfo(self.labeltool.getCurrentFilename()).fileName(), postfix))
        else:
            self.setWindowTitle("%s - Unnamed %s" % (APP_NAME, postfix))

    def onMousePositionChanged(self, x, y):
        self.posinfo.setText("%d, %d" % (x, y))

    def startBackgroundLoading(self):
        self.stopBackgroundLoading(forced=True)
        self.loader = BackgroundLoader(self.labeltool.model(), self.statusBar(), self.sb_progress)
        self.idletimer.timeout.connect(self.loader.load)
        self.loader.finished.connect(self.stopBackgroundLoading)
        self.statusBar().addWidget(self.sb_progress)
        self.sb_progress.show()
        self.idletimer.start()

    def stopBackgroundLoading(self, forced=False):
        if not forced:
            self.statusBar().showMessage("Background loading finished", 5000)
        self.idletimer.stop()
        if self.loader is not None:
            self.idletimer.timeout.disconnect(self.loader.load)
            self.statusBar().removeWidget(self.sb_progress)
            self.loader = None

    def onAnnotationsLoaded(self):
        self.labeltool.model().dirtyChanged.connect(self.onModelDirtyChanged)
        self.onModelDirtyChanged(self.labeltool.model().dirty())
        self.treeview.setModel(self.labeltool.model())
        self.scene.setModel(self.labeltool.model())
        self.selectionmodel = QItemSelectionModel(self.labeltool.model())
        self.treeview.setSelectionModel(self.selectionmodel)
        self.treeview.selectionModel().currentChanged.connect(self.labeltool.setCurrentImage)
        self.property_editor.onModelChanged(self.labeltool.model())
        self.startBackgroundLoading()

    def onCurrentImageChanged(self):
        new_image = self.labeltool.currentImage()
        self.scene.setCurrentImage(new_image)
        self.onFitToWindowModeChanged()
        self.treeview.scrollTo(new_image.index())

        img = self.labeltool.getImage(new_image)

        if img is None:
            self.controls.setFilename("")
            self.selectionmodel.setCurrentIndex(new_image.index(), QItemSelectionModel.ClearAndSelect|QItemSelectionModel.Rows)
            return

        h = img.shape[0]
        w = img.shape[1]
        self.image_resolution.setText("%dx%d" % (w, h))

        # TODO: This info should be obtained from AnnotationModel or LabelTool
        if isinstance(new_image, FrameModelItem):
            self.controls.setFrameNumAndTimestamp(new_image.framenum(), new_image.timestamp())
        elif isinstance(new_image, ImageFileModelItem):
            self.controls.setFilename(os.path.basename(new_image['filename']))

        self.selectionmodel.setCurrentIndex(new_image.index(), QItemSelectionModel.ClearAndSelect|QItemSelectionModel.Rows)

    def onFitToWindowModeChanged(self):
        if self.options["Fit-to-window mode"].isChecked():
            self.view.fitInView()

    def onEnumerateCornersModeChanged(self):
        if self.options["Enumerate-corners mode"].isChecked():
            self.scene.enumerateCorners()
            self.onCurrentImageChanged()
        else:
            self.scene.removeCorners()
            self.onCurrentImageChanged()

    def onCopyAnnotationsModeChanged(self):
        if self.annotationMenu["Copy from previous"].isChecked():
            self.copyAnnotations.copy()
            self.annotationMenu["Copy from previous"].setChecked(False)

    def onInterpolateRangeModeChanged(self):
        if self.annotationMenu["Interpolate range"].isChecked():
            self.interpolateRange.interpolateRange()
            self.annotationMenu["Interpolate range"].setChecked(False)

    def onScaleChanged(self, scale):
        self.zoominfo.setText("%.2f%%" % (100 * scale, ))

    def initShortcuts(self, HOTKEYS):
        self.shortcuts = []

        for hotkey in HOTKEYS:
            assert len(hotkey) >= 2
            key = hotkey[0]
            fun = hotkey[1]
            desc = ""
            if len(hotkey) > 2:
                desc = hotkey[2]
            if type(fun) == str:
                fun = import_callable(fun)

            hk = QAction(desc, self)
            hk.setShortcut(QKeySequence(key))
            hk.setEnabled(True)
            if hasattr(fun, '__call__'):
                hk.triggered.connect(bind(fun, self.labeltool))
            else:
                hk.triggered.connect(compose_noargs([bind(f, self.labeltool) for f in fun]))
            self.ui.menuShortcuts.addAction(hk)
            self.shortcuts.append(hk)

    def initOptions(self):
        self.options = {}
        for o in ["Fit-to-window mode"]:
            action = QAction(o, self)
            action.setCheckable(True)
            self.ui.menuOptions.addAction(action)
            self.options[o] = action

        for o in ["Enumerate-corners mode"]:
            action = QAction(o, self)
            action.setCheckable(True)
            self.ui.menuOptions.addAction(action)
            self.options[o] = action

    def initAnnotationMenu(self):
        self.annotationMenu = {}
        for a in ["Copy from previous"]:
            action = QAction(a, self)
            action.setCheckable(True)
            self.ui.menuAnnotation.addAction(action)
            self.annotationMenu[a] = action

        for a in ["Interpolate range"]:
            action = QAction(a, self)
            action.setCheckable(True)
            self.ui.menuAnnotation.addAction(action)
            self.annotationMenu[a] = action



    ###
    ### GUI/Application setup
    ###___________________________________________________________________________________________
    def setupGui(self):
        self.ui = uic.loadUi(os.path.join(GUIDIR, "labeltool.ui"), self)

        # get inserters and items from labels
        # FIXME for handling the new-style config correctly
        inserters = dict([(label['attributes']['class'], label['inserter']) 
                          for label in config.LABELS
                          if 'class' in label.get('attributes', {}) and 'inserter' in label])
        items = dict([(label['attributes']['class'], label['item']) 
                      for label in config.LABELS
                      if 'class' in label.get('attributes', {}) and 'item' in label])

        # Property Editor
        self.property_editor = PropertyEditor(config.LABELS)
        self.ui.dockProperties.setWidget(self.property_editor)

        # Scene
        self.scene = AnnotationScene(self.labeltool, items=items, inserters=inserters)
        self.property_editor.insertionModeStarted.connect(self.scene.onInsertionModeStarted)
        self.property_editor.insertionModeEnded.connect(self.scene.onInsertionModeEnded)

        # SceneView
        self.view = GraphicsView(self)
        self.view.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)
        self.view.setScene(self.scene)

        self.central_widget = QWidget()
        self.central_layout = QVBoxLayout()
        self.controls = ControlButtonWidget()
        #give functions as lambdas, or else they will be called with a bool as parameter
        self.controls.back_button.clicked.connect(lambda lt: self.labeltool.gotoPrevious())
        self.controls.forward_button.clicked.connect(lambda lt: self.labeltool.gotoNext())

        self.central_layout.addWidget(self.controls)
        self.central_layout.addWidget(self.view)
        self.central_widget.setLayout(self.central_layout)
        self.setCentralWidget(self.central_widget)

        self.initShortcuts(config.HOTKEYS)
        self.initOptions()
        self.initAnnotationMenu()

        self.treeview = AnnotationTreeView()
        self.treeview.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Preferred)
        self.ui.dockAnnotations.setWidget(self.treeview)

        self.scene.selectionChanged.connect(self.scene.onSelectionChanged)
        self.treeview.selectedItemsChanged.connect(self.scene.onSelectionChangedInTreeView)

        self.posinfo = QLabel("-1, -1")
        self.posinfo.setFrameStyle(QFrame.StyledPanel)
        self.statusBar().addPermanentWidget(self.posinfo)
        self.scene.mousePositionChanged.connect(self.onMousePositionChanged)

        self.image_resolution = QLabel("[no image]")
        self.image_resolution.setFrameStyle(QFrame.StyledPanel)
        self.statusBar().addPermanentWidget(self.image_resolution)

        self.zoominfo = QLabel()
        self.zoominfo.setFrameStyle(QFrame.StyledPanel)
        self.statusBar().addPermanentWidget(self.zoominfo)
        self.view.scaleChanged.connect(self.onScaleChanged)
        self.onScaleChanged(self.view.getScale())

        self.sb_progress = QProgressBar()

        # View menu
        self.ui.menu_Views.addAction(self.ui.dockProperties.toggleViewAction())
        self.ui.menu_Views.addAction(self.ui.dockAnnotations.toggleViewAction())

        # Annotation menu
        self.copyAnnotations = CopyAnnotations(self.labeltool)
        self.interpolateRange = InterpolateRange(self.labeltool)

        # Show the UI.  It is important that this comes *after* the above 
        # adding of custom widgets, especially the central widget.  Otherwise the
        # dock widgets would be far to large.
        self.ui.show()

        ## connect action signals
        self.connectActions()

    def connectActions(self):
        ## File menu
        self.ui.actionNew.    triggered.connect(self.fileNew)
        self.ui.actionOpen.   triggered.connect(self.fileOpen)
        self.ui.actionSave.   triggered.connect(self.fileSave)
        self.ui.actionSave_As.triggered.connect(self.fileSaveAs)
        self.ui.actionExit.   triggered.connect(self.close)

        ## View menu
        self.ui.actionLocked.toggled.connect(self.onViewsLockedChanged)

        ## Help menu
        self.ui.action_About.triggered.connect(self.about)

        ## Navigation
        self.ui.action_Add_Image.triggered.connect(self.addMediaFile)
        self.ui.actionNext.      triggered.connect(self.labeltool.gotoNext)
        self.ui.actionPrevious.  triggered.connect(self.labeltool.gotoPrevious)
        self.ui.actionZoom_In.   triggered.connect(functools.partial(self.view.setScaleRelative, 1.2))
        self.ui.actionZoom_Out.  triggered.connect(functools.partial(self.view.setScaleRelative, 1/1.2))

        ## Connections to LabelTool
        self.labeltool.pluginLoaded.       connect(self.onPluginLoaded)
        self.labeltool.statusMessage.      connect(self.onStatusMessage)
        self.labeltool.annotationsLoaded.  connect(self.onAnnotationsLoaded)
        self.labeltool.currentImageChanged.connect(self.onCurrentImageChanged)

        ## options menu
        self.options["Fit-to-window mode"].changed.connect(self.onFitToWindowModeChanged)
        self.options["Enumerate-corners mode"].changed.connect(self.onEnumerateCornersModeChanged)

        ## annotation menu
        self.annotationMenu["Copy from previous"].changed.connect(self.onCopyAnnotationsModeChanged)
        self.annotationMenu["Interpolate range"].changed.connect(self.onInterpolateRangeModeChanged)

    def loadApplicationSettings(self):
        settings = QSettings()
        size   = settings.value("MainWindow/Size", QSize(800, 600))
        pos    = settings.value("MainWindow/Position", QPoint(10, 10))
        state  = settings.value("MainWindow/State")
        locked = settings.value("MainWindow/ViewsLocked", False)
        if isinstance(size,   QVariant): size  = size.toSize()
        if isinstance(pos,    QVariant): pos   = pos.toPoint()
        if isinstance(state,  QVariant): state = state.toByteArray()
        if isinstance(locked, QVariant): locked = locked.toBool()
        self.resize(size)
        self.move(pos)
        if state is not None:
                self.restoreState(state)
        self.ui.actionLocked.setChecked(bool(locked))

    def saveApplicationSettings(self):
        settings = QSettings()
        settings.setValue("MainWindow/Size",        self.size())
        settings.setValue("MainWindow/Position",    self.pos())
        settings.setValue("MainWindow/State",       self.saveState())
        settings.setValue("MainWindow/ViewsLocked", self.ui.actionLocked.isChecked())
        if self.labeltool.getCurrentFilename() is not None:
            filename = self.labeltool.getCurrentFilename()
        else:
            filename = None
        settings.setValue("LastFile", filename)

    def okToContinue(self):
        if self.labeltool.model().dirty():
            reply = QMessageBox.question(self,
                    "%s - Unsaved Changes" % (APP_NAME),
                    "Save unsaved changes?",
                    QMessageBox.Yes|QMessageBox.No|QMessageBox.Cancel)
            if reply == QMessageBox.Cancel:
                return False
            elif reply == QMessageBox.Yes:
                return self.fileSave()
        return True

    def fileNew(self):
        if self.okToContinue():
            self.labeltool.clearAnnotations()

    def fileOpen(self):
        if not self.okToContinue():
            return
        path = '.'
        filename = self.labeltool.getCurrentFilename()
        if (filename is not None) and (len(filename) > 0):
            path = QFileInfo(filename).path()

        format_str = ' '.join(self.labeltool.getAnnotationFilePatterns())
        fname = QFileDialog.getOpenFileName(self, 
                "%s - Load Annotations" % APP_NAME, path,
                "%s annotation files (%s)" % (APP_NAME, format_str))[0]
        if len(str(fname)) > 0:
            self.labeltool.loadAnnotations(fname)

    def fileSave(self):
        filename = self.labeltool.getCurrentFilename()
        if filename is None:
            return self.fileSaveAs()
        return self.labeltool.saveAnnotations(filename)

    def fileSaveAs(self):
        fname = '.'  # self.annotations.filename() or '.'
        format_str = ' '.join(self.labeltool.getAnnotationFilePatterns())
        fname = QFileDialog.getSaveFileName(self,
                "%s - Save Annotations" % APP_NAME, fname,
                "%s annotation files (%s)" % (APP_NAME, format_str))[0]

        if len(str(fname)) > 0:
            return self.labeltool.saveAnnotations(str(fname))
        return False

    def addMediaFile(self):
        path = '.'
        filename = self.labeltool.getCurrentFilename()
        if (filename is not None) and (len(filename) > 0):
            path = QFileInfo(filename).path()

        image_types = [ '*.jpg', '*.bmp', '*.png', '*.pgm', '*.ppm', '*.tiff', '*.tif', '*.gif' ]
        video_types = [ '*.mp4', '*.mpg', '*.mpeg', '*.avi', '*.mov', '*.vob' ]
        format_str = ' '.join(image_types + video_types)
        fnames = QFileDialog.getOpenFileNames(self, "%s - Add Media File" % APP_NAME, path, "Media files (%s)" % (format_str, ))[0]

        item = None
        numFiles = len(fnames)
        progress_bar = QProgressDialog('Importing files...', 'Cancel import', 0, numFiles, self)
        for fname,c in zip(fnames, range(numFiles)):
            if len(str(fname)) == 0:
                continue

            fname = str(fname)

            if os.path.isabs(fname):
                fname = os.path.relpath(fname, str(path))

            for pattern in image_types:
                if fnmatch.fnmatch(fname.lower(), pattern):
                    item = self.labeltool.addImageFile(fname)
            
            progress_bar.setValue(c)

        if item is None:
            return self.labeltool.addVideoFile(fname)

        progress_bar.close()
        
        return item

    def onViewsLockedChanged(self, checked):
        features = QDockWidget.AllDockWidgetFeatures
        if checked:
            features = QDockWidget.NoDockWidgetFeatures 

        self.ui.dockProperties.setFeatures(features)
        self.ui.dockAnnotations.setFeatures(features)


    ###
    ### global event handling
    ###______________________________________________________________________________
    def closeEvent(self, event):
        if self.okToContinue():
            self.saveApplicationSettings()
        else:
            event.ignore()

    def about(self):
        QMessageBox.about(self, "About %s" % APP_NAME,
             """<b>%s</b> version %s
             <p>This labeling application for computer vision research
             was developed at the CVHCI research group at KIT.
             <p>For more details, visit our homepage: <a href="%s">%s</a>"""
              % (APP_NAME, __version__, ORGANIZATION_DOMAIN, ORGANIZATION_DOMAIN))
Beispiel #2
0
class ManagerMainui(QMainWindow, Ui_MainWindow):
    def __init__(self):
        super(ManagerMainui, self).__init__()
        self.setupUi(self)
        self.opendb()
        self.show()
        self.lianjie()
        self.setCentralWidget(self.splitter)

        self.table_view.setSelectionBehavior(QAbstractItemView.SelectItems)
        self.table_view.setSelectionMode(
            QAbstractItemView.SingleSelection)  # 一次选择单行还是多行
        self.table_view.setAlternatingRowColors(True)  # 隔行自动改变颜色
        self.table_view.verticalHeader().setDefaultSectionSize(22)
        self.table_view.horizontalHeader().setDefaultSectionSize(60)

        # 为菜单添加动作

        self.filemenu.addAction(self.exit_Act)
        self.Updata_Menu.addAction(self.Updata_Act)

        # 当前页
        self.currentPage = 0
        # 总页数
        self.totalPage = 0
        # 总记录数
        self.totalRecord = 0
        # 每页数据数
        self.pageRecord = 10

    def opendb(self):
        db = QSqlDatabase.addDatabase('QSQLITE')
        db.setDatabaseName('F:/pycharm项目/图书管理系统NEW/AllDataBase/book.db')
        if db.open():
            self._biaocaozuo()
        else:
            QMessageBox.information(self, 'warning', '无法建立与数据库的连接')
            return False

    def _biaocaozuo(self):
        self.model = QtSql.QSqlTableModel()
        self.model.setTable('BookData')

        self.model.setEditStrategy(QSqlTableModel.OnManualSubmit)  # 设置保存策略

        self.table_view.setModel(self.model)
        self.model.select()
        self.model.setHeaderData(0, Qt.Horizontal, 'ISBN')
        self.model.setHeaderData(1, Qt.Horizontal, '书名')
        self.model.setHeaderData(2, Qt.Horizontal, '作者')
        self.model.setHeaderData(3, Qt.Horizontal, '出版社')
        self.model.setHeaderData(4, Qt.Horizontal, '出版日期')
        self.model.setHeaderData(5, Qt.Horizontal, '评分')
        self.model.setHeaderData(6, Qt.Horizontal, '照片')
        self.table_view.setColumnHidden(6, True)

        self.mapper = QDataWidgetMapper()
        self.mapper.setModel(self.model)
        self.mapper.setSubmitPolicy(QDataWidgetMapper.AutoSubmit)

        self.mapper.addMapping(self.lineEdit_ISBN, 0)
        self.mapper.addMapping(self.lineEdit_shuming, 1)
        self.mapper.addMapping(self.lineEdit_zuozhe, 2)
        self.mapper.addMapping(self.lineEdit_chubanshe, 3)
        self.mapper.addMapping(self.lineEdit_chubanriqi, 4)
        self.mapper.addMapping(self.lineEdit_pingfen, 5)
        self.mapper.toFirst()

        self.selModel = QItemSelectionModel(self.model)  # 选择模型
        self.table_view.setSelectionModel(self.selModel)
        self.selModel.currentChanged.connect(
            self.do_currentChanged)  # 当前项变化时触发
        self.selModel.currentRowChanged.connect(
            self.do_currentRowChanged)  # 选择行变化时

        # @pyqtSlot()  ##保存修改

    def on_p_baocun_triggered(self):
        result = QMessageBox.question(self, 'warning', '你要保存你的修改吗?',
                                      QMessageBox.Yes | QMessageBox.No,
                                      QMessageBox.No)
        if result == QMessageBox.Yes:
            res = self.model.submitAll()
            if (res == False):
                QMessageBox.information(
                    self, "消息",
                    "数据保存错误,错误信息\n" + self.model.lastError().text())
            else:
                QMessageBox.information(self, "message", "保存成功\n")
                self.p_baocun.setEnabled(False)
                self.p_quxiao.setEnabled(False)
        else:
            QMessageBox.information(self, 'message', 'Thanks')

    # @pyqtSlot()  ##取消修改

    def on_p_quxiao_triggered(self):
        # self.model.revertAll()
        result = QMessageBox.question(self, 'warning', '确认取消之前所有的的操作吗?',
                                      QMessageBox.Yes | QMessageBox.No,
                                      QMessageBox.No)
        if result == QMessageBox.Yes:
            self.model.revertAll()
            self.p_baocun.setEnabled(False)
            self.p_quxiao.setEnabled(False)
        else:
            self.p_baocun.setEnabled(True)
            self.p_quxiao.setEnabled(True)

    # @pyqtSlot()  ##添加记录
    def on_p_zengjia_triggered(self):
        #self.model.insertRows(self.model.rowCount(), 1)
        self.model.insertRow(self.model.rowCount(), QModelIndex())  # 在末尾添加一个记录

        curIndex = self.model.index(self.model.rowCount() - 1,
                                    1)  # 创建最后一行的ModelIndex
        self.selModel.clearSelection()  # 清空选择项
        self.selModel.setCurrentIndex(
            curIndex, QItemSelectionModel.Select)  # 设置刚插入的行为当前选择行

    # 删除记录

    def on_p_sanchu_triggered(self):
        # if self.p_baocun.isEnabled():
        result = QMessageBox.question(self, 'warning', '确认删除该记录吗?',
                                      QMessageBox.Yes | QMessageBox.No,
                                      QMessageBox.No)
        if result == QMessageBox.Yes:
            self.model.removeRow(self.table_view.currentIndex().row())
            self.p_baocun.setEnabled(True)
            self.p_quxiao.setEnabled(True)
        else:
            self.p_baocun.setEnabled(False)
            self.p_quxiao.setEnabled(False)

    # 插入记录

    def on_p_charu_triggered(self):
        curIndex = self.table_view.currentIndex()  # QModelIndex
        self.model.insertRow(curIndex.row(), QModelIndex())
        self.selModel.clearSelection()  # 清除已有选择
        self.selModel.setCurrentIndex(curIndex, QItemSelectionModel.Select)

    # 对当前行设置图片
    def on_p_photo_triggered(self):
        fileName, filt = QFileDialog.getOpenFileName(self, "选择图片文件", "",
                                                     "照片(*.jpg)")
        if (fileName == ''):
            return

        file = QFile(fileName)  # fileName为图片文件名
        file.open(QIODevice.ReadOnly)
        try:
            data = file.readAll()  # QByteArray
        finally:
            file.close()

        curRecNo = self.selModel.currentIndex().row()
        curRec = self.model.record(curRecNo)  # 获取当前记录QSqlRecord
        curRec.setValue("Photo", data)  # 设置字段数据
        self.model.setRecord(curRecNo, curRec)

        pic = QPixmap()
        pic.loadFromData(data)
        W = self.dbLabPhoto.width()
        self.dbLabPhoto.setPixmap(pic.scaledToWidth(W))  # 在界面上显示

    def closeEvent(self, event):
        """
        提示保存
        """
        if self.p_baocun.isEnabled():
            r = QMessageBox.warning(self, "注意", "你还没有保存,现在保存下?",
                                    QMessageBox.Yes | QMessageBox.No,
                                    QMessageBox.Yes)
            if r == QMessageBox.No:
                event.accept()
            else:
                event.ignore()

    def chaxun_ISBN(self):
        text1 = self.lineEdit_chaxun.text()
        self.model.setFilter(("ISBN='%s'" % (text1)))

    def chaxun_zuozhe(self):
        text2 = self.lineEdit_chaxun.text()
        self.model.setFilter(("author='%s'" % (text2)))

    def chaxun_shumin(self):
        text3 = self.lineEdit_chaxun.text()
        self.model.setFilter(("title='%s'" % (text3)))

    def chaxun_(self):
        """
        查找图书
        """
        searchtext = self.lineEdit_chaxun.text()
        if searchtext:
            if self.comboBox_chaxun.currentText() == "ISBN":
                self.chaxun_ISBN()
            elif self.comboBox_chaxun.currentText() == "书名":
                self.chaxun_shumin()
            elif self.comboBox_chaxun.currentText() == "作者":
                self.chaxun_zuozhe()
        else:
            QMessageBox.information(self, "提示", "请输入搜索关键词!")

    def on_p_quxiaoCX_triggered(self):
        self.lineEdit_chaxun.clear()
        self.model.setFilter("")

    def do_currentChanged(self, current, previous):  # 更新actPost和actCancel 的状态
        self.p_baocun.setEnabled(self.model.isDirty())  # 有未保存修改时可用
        self.p_quxiao.setEnabled(self.model.isDirty())

    def do_currentRowChanged(self, current, previous):  # 行切换时的状态控制
        self.mapper.setCurrentIndex(current.row())

        if (current.isValid() == False):
            self.dbLabPhoto.clear()  # 清除图片显示
            return

        self.mapper.setCurrentIndex(current.row())  # 更新数据映射的行号

        curRec = self.model.record(current.row())  # 获取当前记录,QSqlRecord类型
        if (curRec.isNull("Photo")):  # 图片字段内容为空
            self.dbLabPhoto.clear()
        else:
            # data=bytearray(curRec.value("Photo"))   #可以工作
            data = curRec.value("Photo")  # 也可以工作
            pic = QPixmap()
            pic.loadFromData(data)
            W = self.dbLabPhoto.size().width()
            self.dbLabPhoto.setPixmap(pic.scaledToWidth(W))

    def scrapy(self):
        """启动爬虫,在线更新功能"""

        # cmdline.execute(" scrapy ".split())
        self.hide()
        try:
            run = ScrapyRun()
        finally:
            pass

    def lianjie(self):
        self.p_zengjia.clicked.connect(self.on_p_zengjia_triggered)
        self.p_baocun.clicked.connect(self.on_p_baocun_triggered)
        self.p_quxiao.clicked.connect(self.on_p_quxiao_triggered)
        self.p_sanchu.clicked.connect(self.on_p_sanchu_triggered)
        self.p_charu.clicked.connect(self.on_p_charu_triggered)
        self.p_photo.clicked.connect(self.on_p_photo_triggered)
        self.p_chaxun.clicked.connect(self.chaxun_)
        self.p_quxiaoCX.clicked.connect(self.on_p_quxiaoCX_triggered)
        self.p_tuichu.clicked.connect(self.close)

        self.exit_Act.triggered.connect(self.close)
        self.Updata_Act.triggered.connect(self.scrapy)
Beispiel #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.splitter)

        #   tableView显示属性设置
        self.ui.tableView.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.ui.tableView.setSelectionMode(QAbstractItemView.SingleSelection)
        self.ui.tableView.setAlternatingRowColors(True)
        self.ui.tableView.verticalHeader().setDefaultSectionSize(22)
        self.ui.tableView.horizontalHeader().setDefaultSectionSize(60)
##      self.ui.tableView.resizeColumnsToContents()

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

    def __getFieldNames(self):  ##获取所有字段名称
        emptyRec = self.qryModel.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.qryModel = QSqlQueryModel(self)
        self.qryModel.setQuery(
            '''SELECT empNo, Name, Gender,  Birthday,  Province,
                             Department, Salary FROM employee ORDER BY empNo'''
        )

        if self.qryModel.lastError().isValid():
            QMessageBox.critical(
                self, "错误",
                "数据表查询错误,错误信息\n" + self.qryModel.lastError().text())
            return

        self.ui.statusBar.showMessage("记录条数:%d" % self.qryModel.rowCount())
        self.__getFieldNames()  #获取字段名和序号

        ##设置字段显示名,直接使用序号
        self.qryModel.setHeaderData(0, Qt.Horizontal, "工号")
        self.qryModel.setHeaderData(1, Qt.Horizontal, "姓名")
        self.qryModel.setHeaderData(2, Qt.Horizontal, "性别")
        self.qryModel.setHeaderData(3, Qt.Horizontal, "出生日期")
        self.qryModel.setHeaderData(4, Qt.Horizontal, "省份")
        self.qryModel.setHeaderData(5, Qt.Horizontal, "部门")
        self.qryModel.setHeaderData(6, Qt.Horizontal, "工资")

        ##      self.qryModel.setHeaderData(self.fldNum["empNo"],      Qt.Horizontal, "工号")
        ##      self.qryModel.setHeaderData(self.fldNum["Name"],       Qt.Horizontal, "姓名")
        ##      self.qryModel.setHeaderData(self.fldNum["Gender"],     Qt.Horizontal, "性别")
        ##      self.qryModel.setHeaderData(self.fldNum["Birthday"],   Qt.Horizontal, "出生日期")
        ##      self.qryModel.setHeaderData(self.fldNum["Province"],   Qt.Horizontal, "省份")
        ##      self.qryModel.setHeaderData(self.fldNum["Department"], Qt.Horizontal, "部门")
        ##      self.qryModel.setHeaderData(self.fldNum["Salary"],     Qt.Horizontal, "工资")

        ##创建界面组件与数据模型的字段之间的数据映射
        self.mapper = QDataWidgetMapper()
        self.mapper.setModel(self.qryModel)  #设置数据模型
        ##      self.mapper.setSubmitPolicy(QDataWidgetMapper.AutoSubmit)

        ##界面组件与qryModel的具体字段之间的联系
        ##      self.mapper.addMapping(self.ui.dbSpinEmpNo, self.fldNum["empNo"])
        ##      self.mapper.addMapping(self.ui.dbEditName,  self.fldNum["Name"])
        ##      self.mapper.addMapping(self.ui.dbComboSex,  self.fldNum["Gender"])
        ##      self.mapper.addMapping(self.ui.dbEditBirth, self.fldNum["Birthday"])
        ##      self.mapper.addMapping(self.ui.dbComboProvince,   self.fldNum["Province"] )
        ##      self.mapper.addMapping(self.ui.dbComboDep,  self.fldNum["Department"] )
        ##      self.mapper.addMapping(self.ui.dbSpinSalary,self.fldNum["Salary"] )

        self.mapper.addMapping(self.ui.dbSpinEmpNo, 0)
        self.mapper.addMapping(self.ui.dbEditName, 1)
        self.mapper.addMapping(self.ui.dbComboSex, 2)
        self.mapper.addMapping(self.ui.dbEditBirth, 3)
        self.mapper.addMapping(self.ui.dbComboProvince, 4)
        self.mapper.addMapping(self.ui.dbComboDep, 5)
        self.mapper.addMapping(self.ui.dbSpinSalary, 6)
        self.mapper.toFirst()  #移动到首记录

        self.selModel = QItemSelectionModel(self.qryModel)  #关联选择模型
        self.selModel.currentRowChanged.connect(
            self.do_currentRowChanged)  #选择行变化时

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

        self.ui.actOpenDB.setEnabled(False)

    def __refreshTableView(self):  ##刷新tableView显示
        index = self.mapper.currentIndex()
        curIndex = self.qryModel.index(index, 1)  #QModelIndex
        self.selModel.clearSelection()  #清空选择项
        self.selModel.setCurrentIndex(curIndex, QItemSelectionModel.Select)

##  ==========由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_actRecFirst_triggered(self):
        self.mapper.toFirst()
        self.__refreshTableView()

    @pyqtSlot()  ##前一记录
    def on_actRecPrevious_triggered(self):
        self.mapper.toPrevious()
        self.__refreshTableView()

    @pyqtSlot()  ##后一条记录
    def on_actRecNext_triggered(self):
        self.mapper.toNext()
        self.__refreshTableView()

    @pyqtSlot()  ##最后一条记录
    def on_actRecLast_triggered(self):
        self.mapper.toLast()
        self.__refreshTableView()

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

    def do_currentRowChanged(self, current, previous):  ##记录移动时触发
        if (current.isValid() == False):
            self.ui.dbLabPhoto.clear()  #清除图片显示
            return

        self.mapper.setCurrentIndex(current.row())  #更新数据映射的行号

        first = (current.row() == 0)  #是否首记录
        last = (current.row() == self.qryModel.rowCount() - 1)  #是否尾记录
        self.ui.actRecFirst.setEnabled(not first)  #更新使能状态
        self.ui.actRecPrevious.setEnabled(not first)
        self.ui.actRecNext.setEnabled(not last)
        self.ui.actRecLast.setEnabled(not last)

        curRec = self.qryModel.record(current.row())  #获取当前记录,QSqlRecord类型
        empNo = curRec.value("EmpNo")  #不需要加 toInt()函数

        query = QSqlQuery(self.DB)
        query.prepare(
            '''SELECT EmpNo, Memo, Photo FROM employee WHERE EmpNo = :ID''')
        query.bindValue(":ID", empNo)
        ##      if not query.exec_():  #注意,在PyQt5.11.2之前的版本里只能使用exec_()函数
        if not query.exec(
        ):  #注意,在PyQt5.11.2添加了遗漏的overload型exec()函数,在PyQt5.11.2里没问题了
            QMessageBox.critical(self, "错误",
                                 "执行SQL语句错误\n" + query.lastError().text())
            return
        else:
            query.first()

        picData = query.value("Photo")
        if (picData == None):  #图片字段内容为空
            self.ui.dbLabPhoto.clear()
        else:  #显示照片
            pic = QPixmap()
            pic.loadFromData(picData)
            W = self.ui.dbLabPhoto.size().width()
            self.ui.dbLabPhoto.setPixmap(pic.scaledToWidth(W))

        memoData = query.value("Memo")  #显示备注
        self.ui.dbEditMemo.setPlainText(memoData)
Beispiel #4
0
class QmyMainWindow(QMainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)  #调用父类构造函数,创建窗体
        self.ui = Ui_MainWindow()  #创建Ui对象
        self.ui.setupUi(self)  #构造UI

        self.__ColCount = 6  #列数
        self.itemModel = QStandardItemModel(
            10, self.__ColCount, self)  #创建QStandardItemModel类型的数据模型,指定行列值
        '''
		setSelectionBehavior()
		此属性保存视图使用的选择行为。
		此属性保存选择是根据单个项目,行还是列进行的

		#QItemSelectionModel()
		此属性保存视图在哪种选择模式下运行。
		#此属性控制用户是否可以选择一个或多个项目,并且在多个项目选择中控制选择是否必须是连续范围的项目
		'''
        self.selectionModel = QItemSelectionModel(self.itemModel)

        self.selectionModel.currentChanged.connect(
            self.do_curChanged)  #单元格选择发生变化时会发射此信号
        self.__lastColumnTitle = ""  #设置最后一列的标题,可以是空
        self.__lastColumnFlags = (Qt.ItemIsSelectable | Qt.ItemIsUserCheckable
                                  | Qt.ItemIsEnabled)
        #设置tableView属性
        self.ui.tableView.setModel(self.itemModel)  #数据模型
        self.ui.tableView.setSelectionModel(self.selectionModel)  #选择模型
        oneOrMore = QAbstractItemView.ExtendedSelection  #选择模式->多选模式
        self.ui.tableView.setSelectionMode(oneOrMore)  #多选模式
        itemOrRow = QAbstractItemView.SelectItems  #项选择模式->单元格选择
        self.ui.tableView.setSelectionBehavior(itemOrRow)  #单元格选择
        self.ui.tableView.verticalHeader().setDefaultSectionSize(22)
        self.ui.tableView.setAlternatingRowColors(True)  #交替行颜色
        self.ui.tableView.setEnabled(False)  #设置默认禁用tabelView
        self.ui.actFontBold.setCheckable(False)
        self.setCentralWidget(self.ui.splitter)  #设置中心组件
        # self.setCentralWidget(self.ui.tableView)
        self.__buildStatusBar()

        self.spinCeshen = QmyFloatSpinDelegate(0, 10000, 0, self)
        self.spinLength = QmyFloatSpinDelegate(0, 6000, 2, self)
        self.spinDegree = QmyFloatSpinDelegate(0, 360, 1, self)
        self.ui.tableView.setItemDelegateForColumn(0, self.spinCeshen)
        self.ui.tableView.setItemDelegateForColumn(1, self.spinLength)
        self.ui.tableView.setItemDelegateForColumn(3, self.spinLength)
        self.ui.tableView.setItemDelegateForColumn(2, self.spinDegree)

        qualities = ["优", "良", "合格", "不合格"]

        self.comboDelegate = QmyComboBoxDelegate(self)
        self.comboDelegate.setItems(qualities, False)
        self.ui.tableView.setItemDelegateForColumn(4, self.comboDelegate)

    ##==========自定义功能函数==========
    def __buildStatusBar(self):
        '''
		设置状态栏ui组件
		:return:
		'''
        self.LabCellPos = QLabel("当前单元格:", self)
        self.LabCellPos.setMinimumWidth(180)
        self.ui.statusBar.addWidget(self.LabCellPos)

        self.LabCellText = QLabel("单元格内容:", self)
        self.LabCellText.setMinimumWidth(150)
        self.ui.statusBar.addWidget(self.LabCellText)

        self.LabCurFile = QLabel("当前文件:", self)
        self.ui.statusBar.addWidget(self.LabCurFile)

    def __iniModelFromStringList(self, allLines):
        rowCnt = len(allLines)  #获取总行数
        self.itemModel.setRowCount(rowCnt - 1)  #除去表头的数据行数
        headerText = allLines[0].strip()  #表头去除换行符,文件呢的空格使用Tab代替
        headerList = headerText.split("\t")  #按照制表符转化为列表
        self.itemModel.setHorizontalHeaderLabels(headerList)  #设置表头标题
        # print(headerList)
        self.__lastColumnTitle = headerList[len(headerList) - 1]  #最后一列的标题
        lastColNo = self.__ColCount - 1  #最后一列的列号

        for i in range(rowCnt - 1):  #除去表头的数据行数
            # print(i)
            lineText = allLines[i + 1].strip()  #去除换行符,不包括表头
            strList = lineText.split("\t")  #按制表符生成列表
            for j in range(self.__ColCount - 1):  #不包括最后一列
                '''
				QStandardItem是一个数据结构,他可以存储一个cell的各种信息,比如文本、图标、是否可选、字体、别景色、前景色等等。
				并且QStandardItem可以有孩子和兄弟,他是为model提供数据存储的节点。
				QTableView:作为表格cell时,有一个作为根节点的QStandardItem,其他节点都是QStandardItem节点的孩子节点,并且都是兄弟节点(这里暂时不考虑多列的情况)。
				QTreeView:作为树节点cell时,有一个作为根节点的QStandardItem,其他节点都是他的孩子节点,但是其他节点也可以作为父节点存在(这里暂时不考虑多列的情况)。
				'''
                item = QStandardItem(strList[j])
                self.itemModel.setItem(i, j, item)
            #设置最后一行
            # print(self.__lastColumnTitle)
            item = QStandardItem(self.__lastColumnTitle)  #将最后一行的表头
            item.setFlags(self.__lastColumnFlags)
            item.setCheckable(True)
            # print(strList[lastColNo])
            if strList[lastColNo] == '0':  #对比文本内的数值进行设定,类型是字符串
                item.setCheckState(Qt.Unchecked)
            else:
                item.setCheckState(Qt.Checked)
            self.itemModel.setItem(i, lastColNo, item)

    def __setCellAlignment(self, align=Qt.AlignHCenter):
        if not self.selectionModel.hasSelection():
            return
        '''
		selectedIndexes()返回一个元素为QModelIndex类型的列表,包括所有被选中的单元格的模型索引
		'''
        selectdIndex = self.selectionModel.selectedIndexes()
        # print(selectdIndex)
        count = len(selectdIndex)
        for i in range(count):
            index = selectdIndex[i]
            '''
			itemFromIndex(index)返回的是模型索引为index的QStandardItem对象
			'''
            item = self.itemModel.itemFromIndex(index)
            item.setTextAlignment(align)

    ##==========事件处理函数===========

    ##==========由connectSlotsByName()自动关联的槽函数====
    @pyqtSlot()
    def on_actOpenFile_triggered(self):

        curPath = os.getcwd()  #获取当前路径
        # print(curPath)?
        #flt是文件过滤器
        filename, flt = QFileDialog.getOpenFileName(
            self, "打开一个文件", curPath, "井斜数据文件(*.txt);;所有文件(*.*)")
        if filename == "":
            return
        self.LabCurFile.setText(("当前文件: " + filename))  #设置状态栏文本
        self.ui.plainTextEdit.clear()
        aFile = open(filename, "r")
        allLines = aFile.readlines()
        aFile.close()
        for strLine in allLines:
            self.ui.plainTextEdit.appendPlainText(
                strLine.strip())  #按照行添加到plainTextEdit中
        self.__iniModelFromStringList(allLines)
        #设置激活状态
        self.ui.tableView.setEnabled(True)
        self.ui.actAppend.setEnabled(True)
        self.ui.actInsert.setEnabled(True)
        self.ui.actDel.setEnabled(True)
        self.ui.actSaveFile.setEnabled(True)
        self.ui.actModelData.setEnabled(True)
        self.ui.actFontBold.setCheckable(True)  #设置加粗可用

    @pyqtSlot()
    def on_actAppend_triggered(self):
        itemlist = []
        for i in range(self.__ColCount - 1):  #循环一行中的各个列,不包括最后一列
            item = QStandardItem("0")  #添加0到数据结构中
            itemlist.append(item)

        item = QStandardItem(self.__lastColumnTitle)  #将最后一行的表头添加入数据结构
        item.setCheckable(True)  #可选
        item.setFlags(self.__lastColumnFlags)
        itemlist.append(item)  #添加到itemlist内(添加到最后一个)

        self.itemModel.appendRow(itemlist)

        curIndex = self.itemModel.index(self.itemModel.rowCount() - 1,
                                        0)  #获取最后一行第一个单元格的模型索引
        self.selectionModel.clearSelection()  #清除选择
        self.selectionModel.setCurrentIndex(
            curIndex,
            QItemSelectionModel.Select)  #设置在添加后自动选择添加行的第一个单元格(可从状态栏确认)

    @pyqtSlot()
    def on_actInsert_triggered(self):
        '''
		插入行
		:return:
		'''
        itemlist = []
        for i in range(self.__ColCount - 1):
            item = QStandardItem("0")
            itemlist.append(item)

        item = QStandardItem(self.__lastColumnTitle)
        item.setFlags(self.__lastColumnFlags)
        item.setCheckable(False)  #是否可以修改选择
        item.setCheckState(Qt.Checked)  #是否选中
        itemlist.append(item)

        curIndex = self.selectionModel.currentIndex()  #选中项的模型索引,包括行列等其他信息
        self.itemModel.insertRow(curIndex.row(), itemlist)

        self.selectionModel.clearSelection()
        self.selectionModel.setCurrentIndex(curIndex,
                                            QItemSelectionModel.Select)

    @pyqtSlot()
    def on_actDel_triggered(self):
        '''
		删除行
		:return:
		'''
        curIndex = self.selectionModel.currentIndex()
        self.itemModel.removeRow(curIndex.row())

    @pyqtSlot()
    def on_actAlignLeft_triggered(self):
        self.__setCellAlignment(Qt.AlignLeft | Qt.AlignVCenter)

    @pyqtSlot()
    def on_actAlignCenter_triggered(self):
        self.__setCellAlignment(Qt.AlignHCenter | Qt.AlignVCenter)

    @pyqtSlot()
    def on_actAlignRight_triggered(self):
        self.__setCellAlignment(Qt.AlignRight | Qt.AlignVCenter)

    @pyqtSlot(bool)
    def on_actFontBold_triggered(self, checked):
        print("1,checked", checked)
        if not self.selectionModel.hasSelection():
            return
        selectIndex = self.selectionModel.selectedIndexes()
        for i in range(len(selectIndex)):
            index = selectIndex[i]
            item = self.itemModel.itemFromIndex(index)
            font = item.font()
            font.setBold(checked)
            item.setFont(font)

    @pyqtSlot()
    def on_actModelData_triggered(self):
        self.ui.plainTextEdit.clear()
        lineStr = ""
        for i in range(self.itemModel.columnCount() - 1):  #不包括最后一列的表头遍历
            item = self.itemModel.horizontalHeaderItem(i)  #返回行标题的一个数据项对象,i是列号
            lineStr = lineStr + item.text() + "\t"  #给每个项对象的文本添加Tab制表符
        item = self.itemModel.horizontalHeaderItem(self.__ColCount -
                                                   1)  #最后一列的表头
        lineStr = lineStr + item.text()
        self.ui.plainTextEdit.appendPlainText(lineStr)

        for i in range(self.itemModel.rowCount()):  #获取行总数,不包括表头行
            lineStr = ""
            for j in range(self.itemModel.columnCount() - 1):  #不包括最后一列的遍历
                item = self.itemModel.item(i, j)  #按照行列号获取工作区内项对象
                lineStr = lineStr + item.text() + "\t"  #项对象文本添加制表符
            item = self.itemModel.item(i, self.__ColCount - 1)  #按照行号获取最后一列的项对象
            if item.checkState() == Qt.Checked:  #匹配状态是否为选中
                lineStr = lineStr + "1"
            else:
                lineStr = lineStr + "0"
            self.ui.plainTextEdit.appendPlainText(lineStr)

    @pyqtSlot()
    def on_actSaveFile_triggered(self):
        '''
		保存文件
		:return:
		'''
        curPath = os.getcwd()
        filename, flt = QFileDialog.getSaveFileName(
            self, "保存文件", curPath, "井斜数据文件(*.txt);;所有文件(*.*)")
        if filename == "":
            return
        self.on_actModelData_triggered()
        aFile = open(filename, "w")
        aFile.write(self.ui.plainTextEdit.toPlainText())
        aFile.close()

    ##=========自定义槽函数============
    def do_curChanged(self, current, previous):
        '''
		设置状态栏组件显示内容
		:param current:
		:param previous:
		:return:
		'''
        if current != None:
            text = " 当前单元格: %d行,%d列" % (current.row() + 1,
                                        current.column() + 1)
            self.LabCellPos.setText(text)
            item = self.itemModel.itemFromIndex(current)
            self.LabCellText.setText("单元格内容:" + item.text())

            font = item.font()
            self.ui.actFontBold.setChecked(
                font.bold())  #设置按钮按下,当font.Bold的值大于50式font.blod()会为True
Beispiel #5
0
class QmyMainWindow(QMainWindow):

    cellIndexChanged = pyqtSignal(int, int)

    def __init__(self, parent=None):
        super().__init__(parent)  #调用父类构造函数,创建窗体
        self.ui = Ui_MainWindow()  #创建UI对象
        self.ui.setupUi(self)  #构造UI界面

        self.__dlgSetHeaders = None
        self.setCentralWidget(self.ui.tableView)

        ##构建状态栏
        self.LabCellPos = QLabel("当前单元格:", self)
        self.LabCellPos.setMinimumWidth(180)
        self.ui.statusBar.addWidget(self.LabCellPos)

        self.LabCellText = QLabel("单元格内容:", self)
        self.LabCellText.setMinimumWidth(200)
        self.ui.statusBar.addWidget(self.LabCellText)

        ##构建Item Model/View
        self.itemModel = QStandardItemModel(10, 5, self)  #数据模型,10行5列
        self.selectionModel = QItemSelectionModel(self.itemModel)  #Item选择模型
        self.selectionModel.currentChanged.connect(self.do_currentChanged)

        ##为tableView设置数据模型
        self.ui.tableView.setModel(self.itemModel)  #设置数据模型
        self.ui.tableView.setSelectionModel(self.selectionModel)  #设置选择模型
##      self.ui.tableView.setSelectionMode(QAbstractItemView.SingleSelection)    #单选
##      self.ui.tableView.setSelectionBehavior(QAbstractItemView.SelectItems)    #单元格选择

##      self.ui.tableView.setAlternatingRowColors(True)
##      self.ui.tableView.verticalHeader().setDefaultSectionSize(25)#缺省行高

    def __del__(self):
        ##      super().__del__(self)
        print("QmyMainWindow 对象被删除了")

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

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

    @pyqtSlot()  ##设置行数列数对话框
    def on_actTab_SetSize_triggered(self):
        dlgTableSize = QmyDialogSize()  #局部变量,构建时不能传递self
        dlgTableSize.setIniSize(self.itemModel.rowCount(),
                                self.itemModel.columnCount())
        ret = dlgTableSize.exec()  #模态方式运行对话框

        if (ret == QDialog.Accepted):
            rows, cols = dlgTableSize.getTableSize()
            self.itemModel.setRowCount(rows)
            self.itemModel.setColumnCount(cols)

    @pyqtSlot()  ##设置表头标题
    def on_actTab_SetHeader_triggered(self):
        if (self.__dlgSetHeaders == None):  #未创建对话框
            self.__dlgSetHeaders = QmyDialogHeaders(self)

        count = len(self.__dlgSetHeaders.headerList())
        if (count != self.itemModel.columnCount()):  #列数改变了
            strList = []
            for i in range(self.itemModel.columnCount()):
                text = str(
                    self.itemModel.headerData(i, Qt.Horizontal,
                                              Qt.DisplayRole))
                strList.append(text)  #现有表格标题
            self.__dlgSetHeaders.setHeaderList(strList)

        ret = self.__dlgSetHeaders.exec()  #以模态方式运行对话框
        if (ret == QDialog.Accepted):
            strList2 = self.__dlgSetHeaders.headerList()
            self.itemModel.setHorizontalHeaderLabels(strList2)

    @pyqtSlot()  ##"定位单元格"
    def on_actTab_Locate_triggered(self):
        dlgLocate = QmyDialogLocate(self)
        dlgLocate.setSpinRange(self.itemModel.rowCount(),
                               self.itemModel.columnCount())

        dlgLocate.changeActionEnable.connect(self.do_setActLocateEnable)
        dlgLocate.changeCellText.connect(self.do_setACellText)

        self.cellIndexChanged.connect(dlgLocate.do_setSpinValue)

        dlgLocate.setAttribute(Qt.WA_DeleteOnClose)  #对话框关闭时自动删除
        dlgLocate.show()

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

    def do_currentChanged(self, current, previous):
        if (current != None):  #当前模型索引有效
            self.LabCellPos.setText(
                "当前单元格:%d行,%d列" %
                (current.row(), current.column()))  #显示模型索引的行和列号
            item = self.itemModel.itemFromIndex(current)  #从模型索引获得Item
            self.LabCellText.setText("单元格内容:" + item.text())  #显示item的文字内容

            self.cellIndexChanged.emit(current.row(), current.column())

##    @pyqtSlot(bool)

    def do_setActLocateEnable(self, enable):
        self.ui.actTab_Locate.setEnabled(enable)

##    @pyqtSlot(int,int,str)

    def do_setACellText(self, row, column, text):
        index = self.itemModel.index(row, column)  #获取模型索引
        self.selectionModel.clearSelection()  #清除现有选择
        self.selectionModel.setCurrentIndex(
            index, QItemSelectionModel.Select)  #定位到单元格
        self.itemModel.setData(index, text, Qt.DisplayRole)  #设置单元格字符串
Beispiel #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())
Beispiel #7
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())
Beispiel #8
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.splitter)

        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(60)

    def __openTable(self):
        self.tabModel = QSqlTableModel(self, self.DB)
        self.tabModel.setTable("employee")
        self.tabModel.setEditStrategy(QSqlTableModel.OnManualSubmit)
        self.tabModel.setSort(self.tabModel.fieldIndex("empNo"), Qt.AscendingOrder)
        if(self.tabModel.select()==False):
            QMessageBox.critical(self, "错误信息", "打开数据表错误,错误信息\n"+self.tabModel.lastError().text())
            return
        self.__getFieldNames()

        self.tabModel.setHeaderData(self.fldNum["empNo"], Qt.Horizontal, "工号")
        self.tabModel.setHeaderData(self.fldNum["Name"], Qt.Horizontal, "姓名")
        self.tabModel.setHeaderData(self.fldNum["Gender"], Qt.Horizontal, "性别")
        self.tabModel.setHeaderData(self.fldNum["Birthday"], Qt.Horizontal, "出生日期")
        self.tabModel.setHeaderData(self.fldNum["Province"], Qt.Horizontal, "省份")
        self.tabModel.setHeaderData(self.fldNum["Department"], Qt.Horizontal, "部门")
        self.tabModel.setHeaderData(self.fldNum["Salary"], Qt.Horizontal, "工资")
        self.tabModel.setHeaderData(self.fldNum["Memo"], Qt.Horizontal, "备注")
        self.tabModel.setHeaderData(self.fldNum["Photo"], Qt.Horizontal, "照片")

        self.mapper = QDataWidgetMapper()
        self.mapper.setModel(self.tabModel)
        self.mapper.setSubmitPolicy(QDataWidgetMapper.AutoSubmit)
        self.mapper.addMapping(self.ui.dbSpinEmpNo, self.fldNum["empNo"])
        self.mapper.addMapping(self.ui.dbEditName, self.fldNum["Name"])
        self.mapper.addMapping(self.ui.dbComboSex, self.fldNum["Gender"])
        self.mapper.addMapping(self.ui.dbEditBirth, self.fldNum["Birthday"])
        self.mapper.addMapping(self.ui.dbComboProvince, self.fldNum["Province"])
        self.mapper.addMapping(self.ui.dbComboDep, self.fldNum["Department"])
        self.mapper.addMapping(self.ui.dbSpinSalary, self.fldNum["Salary"])
        self.mapper.addMapping(self.ui.dbEditMemo, self.fldNum["Memo"])
        self.mapper.toFirst()

        self.selModel = QItemSelectionModel(self.tabModel)
        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)

        self.ui.tableView.setColumnHidden(self.fldNum["Memo"], True)
        self.ui.tableView.setColumnHidden(self.fldNum["Photo"], True)


        strList = ("男", "女")
        self.__delegatesex = QmyComboBoxDelegate()
        self.__delegatesex.setItems(strList, False)
        self.ui.tableView.setItemDelegateForColumn(self.fldNum["Gender"], self.__delegatesex)

        strList = ("销售部", "技术部", "生产部", "行政部")
        self.__delegateDepart = QmyComboBoxDelegate()
        self.__delegateDepart.setItems(strList, True)
        self.ui.tableView.setItemDelegateForColumn(self.fldNum["Department"], self.__delegateDepart)

        self.ui.actOpenDB.setEnabled(False)
        self.ui.actOpenDB.setEnabled(False)

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

        self.ui.groupBoxSort.setEnabled(True)
        self.ui.groupBoxFilter.setEnabled(True)


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

    def do_currentChanged(self, current, previous):
        self.ui.actSubmit.setEnabled(self.tabModel.isDirty())
        self.ui.actRevert.setEnabled(self.tabModel.isDirty())

    def do_currentRowChanged(self, current, previous):
        self.ui.actRecDelete.setEnabled(current.isValid())
        self.ui.actPhoto.setEnabled(current.isValid())
        self.ui.actPhotoClear.setEnabled(current.isValid())

        if(current.isValid() == False):
            self.ui.dbLabPhoto.clear()
            return

        self.mapper.setCurrentIndex(current.row())
        curRec = self.tabModel.record(current.row())

        if(curRec.isNull("Photo")):
            self.ui.dbLabPhoto.clear()
        else:
            data = curRec.value("Photo")
            pic = QPixmap()
            pic.loadFromData(data)
            w = self.ui.dbLabPhoto.size().width()
            self.ui.dbLabPhoto.setPixmap(pic.scaledToWidth(w))

    @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_actRecAppend_triggered(self):
        self.tabModel.insertRow(self.tabModel.rowCount(), QModelIndex())
        curIndex = self.tabModel.index(self.tabModel.rowCount()-1, 1)
        self.selModel.clearSelection()
        self.selModel.setCurrentIndex(curIndex, QItemSelectionModel.Select)
        currow = curIndex.row()
        self.tabModel.setData(self.tabModel.index(currow, self.fldNum["empNo"]), 2000+self.tabModel.rowCount())
        self.tabModel.setData(self.tabModel.index(currow, self.fldNum["Gender"]), "男")

    @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_actPhotoClear_triggered(self):
        curRecNo = self.selModel.currentIndex().row()
        curRec = self.tabModel.record(curRecNo)
        curRec.setNull("Photo")
        self.tabModel.setRecord(curRecNo, curRec)
        self.ui.dbLabPhoto.clear()

    @pyqtSlot()
    def on_actPhoto_triggered(self):
        fileName, filt = QFileDialog.getOpenFileName(self, "选择图片文件", "", "照片(*.jpg")
        if(fileName==''):
            return
        file=QFile(fileName)
        file.open(QIODevice.ReadOnly)
        try:
            data = file.readAll()
        finally:
            file.close()

        curRecNo = self.selModel.currentIndex().row()
        curRec = self.tabModel.record(curRecNo)
        curRec.setValue("Photo", data)
        self.tabModel.setRecord(curRecNo, curRec)

        pic = QPixmap()
        pic.loadFromData(data)
        w = self.ui.dbLabPhoto.width()
        self.ui.dbLabPhoto.setPixmap(pic.scaledToWidth(w))

    @pyqtSlot()
    def on_actScan_triggered(self):
        if(self.tabModel.rowCount()==0):
            return
        for i in range(self.tabModel.rowCount()):
            aRec = self.tabModel.record(i)
            salary = aRec.value("Salary")
            salary = salary*1.1
            aRec.setValue("Salary", salary)
            self.tabModel.setRecord(i, aRec)

        if(self.tabModel.submitAll()):
            QMessageBox.information(self, "消息", "涨工资计算完毕了")

    @pyqtSlot()
    def on_comboFields_currentIndexChanged(self, index):
        if self.ui.radioBtnAscend.isChecked():
            self.tabModel.setSort(index, Qt.AscendingOrder)
        else:
            self.tabModel.setSort(index, Qt.DescendingOrder)
        self.tabModel.select()

    @pyqtSlot()
    def on_radioBtnAscend_clicked(self):
        self.tabModel.setSort(self.ui.comboFields.currentIndex(), Qt.AscendingOrder)
        self.tabModel.select()

    @pyqtSlot()
    def on_radioBtnDescend_clicked(self):
        self.tabModel.setSort(self.ui.comboFields.currentIndex(), Qt.DescendingOrder)
        self.tabModel.select()

    @pyqtSlot()
    def on_radioBtnMan_clicked(self):
        self.tabModel.setFilter("Gender='男'")

    @pyqtSlot()
    def on_radioBtnWoman_clicked(self):
        self.tabModel.setFilter("Gender='女'")

    @pyqtSlot()
    def on_radioBtnBoth_clicked(self):
        self.tabModel.setFilter("")
Beispiel #9
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.splitter)

        ##   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(60)

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

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

    def __openTable(self):  ##打开数据表
        self.tabModel = QSqlTableModel(self, self.DB)  #数据模型
        self.tabModel.setTable("employee")  #设置数据表
        self.tabModel.setEditStrategy(QSqlTableModel.OnManualSubmit
                                      )  #数据保存方式,OnManualSubmit , OnRowChange
        self.tabModel.setSort(self.tabModel.fieldIndex("empNo"),
                              Qt.AscendingOrder)  #排序
        if (self.tabModel.select() == False):  #查询数据失败
            QMessageBox.critical(
                self, "错误信息",
                "打开数据表错误,错误信息\n" + self.tabModel.lastError().text())
            return

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

        ##字段显示名
        self.tabModel.setHeaderData(self.fldNum["empNo"], Qt.Horizontal, "工号")
        self.tabModel.setHeaderData(self.fldNum["Name"], Qt.Horizontal, "姓名")
        self.tabModel.setHeaderData(self.fldNum["Gender"], Qt.Horizontal, "性别")
        self.tabModel.setHeaderData(self.fldNum["Birthday"], Qt.Horizontal,
                                    "出生日期")
        self.tabModel.setHeaderData(self.fldNum["Province"], Qt.Horizontal,
                                    "省份")
        self.tabModel.setHeaderData(self.fldNum["Department"], Qt.Horizontal,
                                    "部门")
        self.tabModel.setHeaderData(self.fldNum["Salary"], Qt.Horizontal, "工资")

        self.tabModel.setHeaderData(self.fldNum["Memo"], Qt.Horizontal,
                                    "备注")  #这两个字段不在tableView中显示
        self.tabModel.setHeaderData(self.fldNum["Photo"], Qt.Horizontal, "照片")

        ##      self.tabModel.setHeaderData(self.tabModel.fieldIndex("empNo"),  Qt.Horizontal, "工号")
        ##      self.tabModel.setHeaderData(self.tabModel.fieldIndex("Name"),   Qt.Horizontal, "姓名")
        ##      self.tabModel.setHeaderData(self.tabModel.fieldIndex("Gender"), Qt.Horizontal, "性别")
        ##      self.tabModel.setHeaderData(self.tabModel.fieldIndex("Birthday"),  Qt.Horizontal, "出生日期")
        ##      self.tabModel.setHeaderData(self.tabModel.fieldIndex("Province"),  Qt.Horizontal, "省份")
        ##      self.tabModel.setHeaderData(self.tabModel.fieldIndex("Department"),Qt.Horizontal, "部门")
        ##      self.tabModel.setHeaderData(self.tabModel.fieldIndex("Salary"), Qt.Horizontal, "工资")
        ##      self.tabModel.setHeaderData(self.tabModel.fieldIndex("Memo"),   Qt.Horizontal, "备注")   #这两个字段不在tableView中显示
        ##      self.tabModel.setHeaderData(self.tabModel.fieldIndex("Photo"),  Qt.Horizontal, "照片")

        ##创建界面组件与数据模型的字段之间的数据映射
        self.mapper = QDataWidgetMapper()
        self.mapper.setModel(self.tabModel)  #设置数据模型
        self.mapper.setSubmitPolicy(QDataWidgetMapper.AutoSubmit)

        ##界面组件与tabModel的具体字段之间的联系
        self.mapper.addMapping(self.ui.dbSpinEmpNo, self.fldNum["empNo"])
        self.mapper.addMapping(self.ui.dbEditName, self.fldNum["Name"])
        self.mapper.addMapping(self.ui.dbComboSex, self.fldNum["Gender"])
        self.mapper.addMapping(self.ui.dbEditBirth, self.fldNum["Birthday"])
        self.mapper.addMapping(self.ui.dbComboProvince,
                               self.fldNum["Province"])
        self.mapper.addMapping(self.ui.dbComboDep, self.fldNum["Department"])
        self.mapper.addMapping(self.ui.dbSpinSalary, self.fldNum["Salary"])
        self.mapper.addMapping(self.ui.dbEditMemo, self.fldNum["Memo"])
        self.mapper.toFirst()  #移动到首记录

        self.selModel = QItemSelectionModel(self.tabModel)  #选择模型
        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)  #设置选择模型

        self.ui.tableView.setColumnHidden(self.fldNum["Memo"], True)  #隐藏列
        self.ui.tableView.setColumnHidden(self.fldNum["Photo"], True)  #隐藏列

        ##tableView上为“性别”和“部门”两个字段设置自定义代理组件
        strList = ("男", "女")
        self.__delegateSex = QmyComboBoxDelegate()
        self.__delegateSex.setItems(strList, False)
        self.ui.tableView.setItemDelegateForColumn(
            self.fldNum["Gender"], self.__delegateSex)  #Combbox选择型

        strList = ("销售部", "技术部", "生产部", "行政部")
        self.__delegateDepart = QmyComboBoxDelegate()
        self.__delegateDepart.setItems(strList, True)
        self.ui.tableView.setItemDelegateForColumn(self.fldNum["Department"],
                                                   self.__delegateDepart)

        ##更新actions和界面组件的使能状态
        self.ui.actOpenDB.setEnabled(False)

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

        self.ui.groupBoxSort.setEnabled(True)
        self.ui.groupBoxFilter.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")  #添加 SQLITE数据库驱动
        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)  #设置刚插入的行为当前选择行

        currow = curIndex.row()  #获得当前行
        self.tabModel.setData(self.tabModel.index(currow,
                                                  self.fldNum["empNo"]),
                              2000 + self.tabModel.rowCount())  #自动生成编号
        self.tabModel.setData(
            self.tabModel.index(currow, self.fldNum["Gender"]), "男")

    @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_actPhotoClear_triggered(self):
        curRecNo = self.selModel.currentIndex().row()
        curRec = self.tabModel.record(curRecNo)  #获取当前记录,QSqlRecord
        curRec.setNull("Photo")  #设置为空值
        self.tabModel.setRecord(curRecNo, curRec)
        self.ui.dbLabPhoto.clear()  #清除界面上的图片显示

    @pyqtSlot()  ##设置照片
    def on_actPhoto_triggered(self):
        fileName, filt = QFileDialog.getOpenFileName(self, "选择图片文件", "",
                                                     "照片(*.jpg)")
        if (fileName == ''):
            return

        file = QFile(fileName)  #fileName为图片文件名
        file.open(QIODevice.ReadOnly)
        try:
            data = file.readAll()  #QByteArray
        finally:
            file.close()

        curRecNo = self.selModel.currentIndex().row()
        curRec = self.tabModel.record(curRecNo)  #获取当前记录QSqlRecord
        curRec.setValue("Photo", data)  #设置字段数据
        self.tabModel.setRecord(curRecNo, curRec)

        pic = QPixmap()
        pic.loadFromData(data)
        W = self.ui.dbLabPhoto.width()
        self.ui.dbLabPhoto.setPixmap(pic.scaledToWidth(W))  #在界面上显示

    @pyqtSlot()  ##涨工资,遍历数据表所有记录
    def on_actScan_triggered(self):
        if (self.tabModel.rowCount() == 0):
            return

        for i in range(self.tabModel.rowCount()):
            aRec = self.tabModel.record(i)  #获取当前记录
            ##         salary=aRec.value("Salary").toFloat()      #错误,无需再使用toFloat()函数
            salary = aRec.value("Salary")
            salary = salary * 1.1
            aRec.setValue("Salary", salary)
            self.tabModel.setRecord(i, aRec)

        if (self.tabModel.submitAll()):
            QMessageBox.information(self, "消息", "涨工资计算完毕")

    @pyqtSlot(int)  ##排序字段变化
    def on_comboFields_currentIndexChanged(self, index):
        if self.ui.radioBtnAscend.isChecked():
            self.tabModel.setSort(index, Qt.AscendingOrder)
        else:
            self.tabModel.setSort(index, Qt.DescendingOrder)
        self.tabModel.select()

    @pyqtSlot()  ##升序
    def on_radioBtnAscend_clicked(self):
        self.tabModel.setSort(self.ui.comboFields.currentIndex(),
                              Qt.AscendingOrder)
        self.tabModel.select()

    @pyqtSlot()  ##降序
    def on_radioBtnDescend_clicked(self):
        self.tabModel.setSort(self.ui.comboFields.currentIndex(),
                              Qt.DescendingOrder)
        self.tabModel.select()

    @pyqtSlot()  ##过滤,男
    def on_radioBtnMan_clicked(self):
        self.tabModel.setFilter("Gender='男'")

    ##      print(self.tabModel.filter())
    ##      self.tabModel.select()

    @pyqtSlot()  ##数据过滤,女
    def on_radioBtnWoman_clicked(self):
        self.tabModel.setFilter("Gender='女' ")

    ##      print(self.tabModel.filter())
    ##      self.tabModel.select()

    @pyqtSlot()  ##取消数据过滤
    def on_radioBtnBoth_clicked(self):
        self.tabModel.setFilter("")

    ##      print(self.tabModel.filter())
    ##      self.tabModel.select()

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

    def do_currentChanged(self, current, previous):  ##更新actPost和actCancel 的状态
        self.ui.actSubmit.setEnabled(self.tabModel.isDirty())  #有未保存修改时可用
        self.ui.actRevert.setEnabled(self.tabModel.isDirty())

    def do_currentRowChanged(self, current, previous):  #行切换时的状态控制
        self.ui.actRecDelete.setEnabled(current.isValid())
        self.ui.actPhoto.setEnabled(current.isValid())
        self.ui.actPhotoClear.setEnabled(current.isValid())

        if (current.isValid() == False):
            self.ui.dbLabPhoto.clear()  #清除图片显示
            return

        self.mapper.setCurrentIndex(current.row())  #更新数据映射的行号
        curRec = self.tabModel.record(current.row())  #获取当前记录,QSqlRecord类型

        if (curRec.isNull("Photo")):  #图片字段内容为空
            self.ui.dbLabPhoto.clear()
        else:
            ##         data=bytearray(curRec.value("Photo"))   #可以工作
            data = curRec.value("Photo")  # 也可以工作
            pic = QPixmap()
            pic.loadFromData(data)
            W = self.ui.dbLabPhoto.size().width()
            self.ui.dbLabPhoto.setPixmap(pic.scaledToWidth(W))
Beispiel #10
0
class QmyMainWindow(QMainWindow):
    def __init__(self, parent=None, dbFilename='None'):
        super().__init__(parent)  # Call the parent class. Create window.
        self.ui = Ui_MainWindow()  # Create UI object
        self.ui.setupUi(self)  # Create UI interface

        self.ui.tabWidget.setVisible(True)
        self.setCentralWidget(self.ui.tabWidget)

        # tableView setting
        self.ui.tableView.setSelectionBehavior(QAbstractItemView.SelectItems)
        self.ui.tableView.setSelectionMode(QAbstractItemView.SingleSelection)
        self.ui.tableView.setAlternatingRowColors(True)
        self.ui.tableView.verticalHeader().setDefaultSectionSize(44)
        self.ui.tableView.horizontalHeader().setDefaultSectionSize(70)
        self.ui.tableView.setSortingEnabled(True)

        # Initialize chart
        self.__iniPieChart()  # Initialize pie chart
        self.__iniStackedBar()  # Stacked bar

        mpl.rcParams['font.sans-serif'] = ['Calibri']
        mpl.rcParams['font.size'] = 8

        # Choose the SQLITE database drive
        self.DB = QSqlDatabase.addDatabase("QSQLITE")
        self.DB.setDatabaseName(dbFilename)  # Set the name of database
        if self.DB.open():  # Open database
            self.__openTable()  # Open tables
        else:
            QMessageBox.warning(self, "Warning",
                                "Failed to open the database.")

# ==============Self-defined Fuctions============

    def __getFieldNames(self):  # Get names of all fields.
        # Get empty records, only field name.
        emptyRec = self.tabModel.record()
        self.fldNum = {}  # Dictionary of field name and index.
        for i in range(emptyRec.count()):
            fieldName = emptyRec.fieldName(i)
            self.fldNum.setdefault(fieldName)
            self.fldNum[fieldName] = i

    def __openTable(self):  # Open the table of database
        self.tabModel = QSqlTableModel(self, self.DB)  # Data model
        # Set the table of database TODO: Can user insert their own tables from
        # the database?
        self.tabModel.setTable("battery")
        # Data storage,OnManualSubmit , OnRowChange
        self.tabModel.setEditStrategy(QSqlTableModel.OnManualSubmit)
        # self.tabModel.setSort(
        #     self.tabModel.fieldIndex("RANDOM"),
        #     Qt.DescendingOrder)  # Sorting
        if (self.tabModel.select() == False):  # Failed to query the data
            QMessageBox.critical(
                self, "Wrong",
                "Something wrong. Failed to open the database\n" +
                self.tabModel.lastError().text())
            return
        # self.tabModel.setFilter("NUM_RECORDS LIKE 'NONE'")
        self.__getFieldNames()  # Get the field name and index

        # Field name shown
        for i in self.fldNum:
            self.tabModel.setHeaderData(self.fldNum[i], Qt.Horizontal,
                                        i.capitalize())

# Create mappings between interface widget and the field name of data model
        self.mapper = QDataWidgetMapper()
        self.mapper.setModel(self.tabModel)  # Setting data model
        self.mapper.setSubmitPolicy(QDataWidgetMapper.AutoSubmit)

        # The relations between interface widget and field name of tabModel
        self.mapper.addMapping(self.ui.dbEditValue, self.fldNum["Value"])
        self.mapper.addMapping(self.ui.dbEditRunit, self.fldNum["Raw_unit"])
        self.mapper.addMapping(self.ui.dbComboProperty,
                               self.fldNum["Property"])
        self.mapper.addMapping(self.ui.dbEditUnit, self.fldNum["Unit"])
        self.mapper.addMapping(self.ui.dbEditName, self.fldNum["Name"])
        self.mapper.addMapping(self.ui.dbEditEname,
                               self.fldNum["Extracted_name"])
        self.mapper.addMapping(self.ui.dbEditRvalue, self.fldNum["Raw_value"])
        self.mapper.addMapping(self.ui.dbEditDOI_2, self.fldNum["DOI"])
        self.mapper.addMapping(self.ui.dbEditDOI_4, self.fldNum["Date"])
        self.mapper.addMapping(self.ui.dbEditDOI_3, self.fldNum["Title"])
        self.mapper.addMapping(self.ui.dbEditDOI, self.fldNum["Journal"])
        self.mapper.addMapping(self.ui.dbEditTag, self.fldNum["Tag"])
        self.mapper.addMapping(self.ui.dbEditInfo, self.fldNum["Info"])
        self.mapper.addMapping(self.ui.dbEditType, self.fldNum["Type"])
        self.mapper.addMapping(self.ui.dbEditWarning, self.fldNum["Warning"])
        self.mapper.addMapping(self.ui.dbEditSpecifier,
                               self.fldNum["Specifier"])
        self.mapper.toFirst()  # Move to the first record

        self.selModel = QItemSelectionModel(self.tabModel)  # Select model
        self.selModel.currentChanged.connect(
            self.do_currentChanged)  # Trigger when the current changed
        self.selModel.currentRowChanged.connect(
            self.do_currentRowChanged)  # Trigger when the current row changed

        self.ui.tableView.setModel(self.tabModel)  # Setting the data model
        self.ui.tableView.setSelectionModel(
            self.selModel)  # Setting the selection model

        #      self.ui.tableView.setColumnHidden(self.fldNum["TAG"],   True)  #Hide columns
        # self.ui.tableView.setColumnHidden(self.fldNum["INFO"],  True)  #Hide
        # columns
        self.ui.tableView.setColumnHidden(self.fldNum["Extracted_name"],
                                          True)  # Hide columns
        self.ui.tableView.setColumnHidden(self.fldNum["Unit"],
                                          True)  # Hide columns
        self.ui.tableView.setColumnHidden(self.fldNum["Num_records"],
                                          True)  # Hide columns
        # self.ui.tableView.setColumnHidden(
        #     self.fldNum["RAW_VALUE"], True)  # Hide columns

        # Update the conditions of actions of interface widget
        self.ui.actRecAppend.setEnabled(True)
        self.ui.actRecInsert.setEnabled(True)
        self.ui.actRecDelete.setEnabled(True)

        self.ui.btnDrawPieChart.setEnabled(True)  # Pie Chart
        self.ui.spinPieSize.setEnabled(True)
        self.ui.spinHoleSize.setEnabled(True)
        self.ui.chkBox_PieLegend.setEnabled(True)

        self.ui.generateButton_3.setEnabled(True)
        self.ui.searchButton_3.setEnabled(True)
        self.ui.clearButton_3.setEnabled(True)

        self.ui.frame_4.setEnabled(True)
        self.ui.frame_3.setEnabled(True)

        self.ui.searchInput.returnPressed.connect(self.ui.searchButton.click)
        self.ui.searchInput_3.returnPressed.connect(
            self.ui.searchButton_3.click)

    def __iniPieChart(self):  # Initialize pie chart
        chart = QChart()
        # chart.setTitle("Piechart")
        chart.setAnimationOptions(QChart.SeriesAnimations)
        chart.setTheme(QChart.ChartTheme(0))
        self.ui.chartViewPie.setChart(chart)  # Setting chart for chart view
        self.ui.chartViewPie.setRenderHint(QPainter.Antialiasing)
        self.ui.chartViewPie.setCursor(Qt.CrossCursor)  # Setting cross cursor

    def __iniStackedBar(self):  # Initialize stacked bar chart
        chart = QChart()
        # chart.setTitle("Number of property records for each chemical")
        chart.setAnimationOptions(QChart.SeriesAnimations)
        chart.setTheme(QChart.ChartTheme(0))
        self.ui.chartViewStackedBar.setChart(chart)  # Set chart
        self.ui.chartViewStackedBar.setRenderHint(QPainter.Antialiasing)
        self.ui.chartViewStackedBar.setCursor(Qt.CrossCursor)  # Set mouse

# ==========Table tab slot function==================

    @pyqtSlot()  # Save changes
    def on_actSubmit_triggered(self):
        res = self.tabModel.submitAll()
        if (res == False):
            QMessageBox.information(
                self, "Information",
                "Failed to store the changes. Wrong information. \n" +
                self.tabModel.lastError().text())
        else:
            self.ui.actSubmit.setEnabled(False)
            self.ui.actRevert.setEnabled(False)

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

    @pyqtSlot()  # Add records
    def on_actRecAppend_triggered(self):
        self.tabModel.insertRow(
            self.tabModel.rowCount(),
            QModelIndex())  # Add one record in the last row
        curIndex = self.tabModel.index(self.tabModel.rowCount() - 1,
                                       1)  # Create ModelIndex of the last row
        self.selModel.clearSelection()  # Clear selections
        # Choosing the current row when selection.
        self.selModel.setCurrentIndex(curIndex, QItemSelectionModel.Select)

        currow = curIndex.row()  # Get current row

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

    @pyqtSlot()  # Delete records
    def on_actRecDelete_triggered(self):
        # Get the current index of current model
        curIndex = self.selModel.currentIndex()
        self.tabModel.removeRow(curIndex.row(),
                                QModelIndex())  # Delete the current row
        self.tabModel.submit()

    @pyqtSlot()  # Help message box
    def on_actHelp_triggered(self):
        msg = QMessageBox()
        msg.about(
            self, "Help", '<div>'
            '<h3>Table:&nbsp;Query&nbsp;the&nbsp;database&nbsp;according&nbsp;to&nbsp;data&nbsp;types&nbsp;and&nbsp;name&nbsp;or&nbsp;DOI.</h3>'
            '<ul>'
            '<li>Search&nbsp;the&nbsp;exact&nbsp;compound&nbsp;name&nbsp;in&nbsp;"<em>Exact&nbsp;Match</em>". Search&nbsp;the&nbsp;element&nbsp;or&nbsp;part&nbsp;of&nbsp;compound&nbsp;name&nbsp;in&nbsp;"<em>Generic&nbsp;Match</em>".&nbsp;</li>'
            '<li>Click the "<em>Home</em>" or "<em>All</em>" button to view the full database</li>'
            '<li>Refer&nbsp;to&nbsp;"<em>Correctness</em>"&nbsp;column&nbsp;for&nbsp;database&nbsp;evaluation&nbsp;details.&nbsp;</li>'
            '<li>You can add your own database entries using the "<em>Insert</em>" tab; click "<em>Save</em>" to save the changes.</li>'
            '</ul>'
            '<h3>Figure:&nbsp;Statistical&nbsp;analysis&nbsp;of&nbsp;the&nbsp;database.</h3>'
            '<ul>'
            '<li><em>Pie&nbsp;chart</em>&nbsp;shows&nbsp;the&nbsp;proportion&nbsp;of&nbsp;data&nbsp;records.</li>'
            '<li><em>Stacked&nbsp;bar&nbsp;chart</em>&nbsp;shows&nbsp;the&nbsp;data&nbsp;types&nbsp;for&nbsp;each&nbsp;compound. First&nbsp;input&nbsp;the&nbsp;compound&nbsp;name,&nbsp;click&nbsp;"<em>Add</em>"&nbsp;and&nbsp;then&nbsp;"<em>Generate</em>"&nbsp;data&nbsp;for&nbsp;overview.&nbsp;</li>'
            '<li><em>Histogram&nbsp;</em>shows&nbsp;the&nbsp;distribution&nbsp;of&nbsp;each&nbsp;data&nbsp;type.</li>'
            '<li><em>Venn&nbsp;diagram</em>&nbsp;shows&nbsp;the&nbsp;correlation&nbsp;of&nbsp;each&nbsp;data&nbsp;type.</li>'
            '</ul>'
            '</div>')

    @pyqtSlot()  # Filtering
    def on_radioBtnVoltage_clicked(self):
        flag, sqlmerge = self.merged_or_not()
        print(sqlmerge)
        self.tabModel.setFilter("PROPERTY LIKE 'Voltage' AND %s" % sqlmerge)

    @pyqtSlot()  # Filtering
    def on_radioBtnCoulombic_clicked(self):
        flag, sqlmerge = self.merged_or_not()
        self.tabModel.setFilter("PROPERTY LIKE 'Coulombic Efficiency' AND %s" %
                                sqlmerge)

    @pyqtSlot()  # Filtering
    def on_radioBtnConductivity_clicked(self):
        flag, sqlmerge = self.merged_or_not()
        self.tabModel.setFilter("PROPERTY LIKE 'Conductivity' AND %s" %
                                sqlmerge)

    @pyqtSlot()  # Filetering
    def on_radioBtnCapacity_clicked(self):
        flag, sqlmerge = self.merged_or_not()
        self.tabModel.setFilter("PROPERTY LIKE 'Capacity' AND %s" % sqlmerge)

    @pyqtSlot()  # Filtering
    def on_radioBtnEnergy_clicked(self):
        flag, sqlmerge = self.merged_or_not()
        self.tabModel.setFilter("PROPERTY LIKE 'Energy' AND %s" % sqlmerge)

    @pyqtSlot()  # Cancel Filetering
    def on_radioBtnAll_clicked(self):
        flag, sqlmerge = self.merged_or_not()
        self.tabModel.setFilter("%s" % sqlmerge)

    # print(self.tabModel.filter())
    # self.tabModel.select()

    def get_elements(self):
        element_dic = {
            "Hydrogen": "H",
            "Helium": "He",
            "Lithium": "Li",
            "Beryllium": "Be",
            "Boron": "B",
            "Carbon": "C",
            "Nitrogen": "N",
            "Oxygen": "O",
            "Fluorine": "F",
            "Neon": "Ne",
            "Sodium": "Na",
            "Magnesium": "Mg",
            "Aluminum": "Al",
            "Silicon": "Si",
            "Phosphorus": "P",
            "Sulfur": "S",
            "Chlorine": "Cl",
            "Argon": "Ar",
            "Potassium": "K",
            "Calcium": "Ca",
            "Scandium": "Sc",
            "Titanium": "Ti",
            "Vanadium": "V",
            "Chromium": "Cr",
            "Manganese": "Mn",
            "Iron": "Fe",
            "Cobalt": "Co",
            "Nickel": "Ni",
            "Copper": "Cu",
            "Zinc": "Zn",
            "Gallium": "Ga",
            "Germanium": "Ge",
            "Arsenic": "As",
            "Selenium": "Se",
            "Bromine": "Br",
            "Krypton": "Kr",
            "Rubidium": "Rb",
            "Strontium": "Sr",
            "Yttrium": "Y",
            "Zirconium": "Zr",
            "Niobium": "Nb",
            "Molybdenum": "Mo",
            "Technetium": "Tc",
            "Ruthenium": "Ru",
            "Rhodium": "Rh",
            "Palladium": "Pd",
            "Silver": "Ag",
            "Cadmium": "Cd",
            "Indium": "In",
            "Tin": "Sn",
            "Antimony": "Sb",
            "Tellurium": "Te",
            "Iodine": "I",
            "Xenon": "Xe",
            "Cesium": "Cs",
            "Barium": "Ba",
            "Lanthanum": "La",
            "Cerium": "Ce",
            "Praseodymium": "Pr",
            "Neodymium": "Nd",
            "Promethium": "Pm",
            "Samarium": "Sm",
            "Europium": "Eu",
            "Gadolinium": "Gd",
            "Terbium": "Tb",
            "Dysprosium": "Dy",
            "Holmium": "Ho",
            "Erbium": "Er",
            "Thulium": "Tm",
            "Ytterbium": "Yb",
            "Lutetium": "Lu",
            "Hafnium": "Hf",
            "Tantalum": "Ta",
            "Tungsten": "W",
            "Rhenium": "Re",
            "Osmium": "Os",
            "Iridium": "Ir",
            "Platinum": "Pt",
            "Gold": "Au",
            "Mercury": "Hg",
            "Thallium": "Tl",
            "Lead": "Pb",
            "Bismuth": "Bi",
            "Polonium": "Po",
            "Astatine": "At",
            "Radon": "Rn",
            "Francium": "Fr",
            "Radium": "Ra",
            "Actinium": "Ac",
            "Thorium": "Th",
            "Protactinium": "Pa",
            "Uranium": "U",
            "Neptunium": "Np",
            "Plutonium": "Pu",
            "Americium": "Am",
            "Curium": "Cm",
            "Berkelium": "Bk",
            "Californium": "Cf",
            "Einsteinium": "Es",
            "Fermium": "Fm",
            "Mendelevium": "Md",
            "Nobelium": "No",
            "Lawrencium": "Lr",
            "Rutherfordium": "Rf",
            "Dubnium": "Db",
            "Seaborgium": "Sg",
            "Bohrium": "Bh",
            "Hassium": "Hs",
            "Meitnerium": "Mt",
            "Darmstadtium": "Ds",
            "Roentgenium": "Rg",
            "Copernicium": "Cn",
            "Nihonium": "Nh",
            "Flerovium": "Fl",
            "Moscovium": "Mc",
            "Livermorium": "Lv",
            "Tennessine": "Ts",
            "Oganesson": "Og"
        }
        return element_dic

    def merged_or_not(self):
        flag = self.ui.mergeBox.isChecked()
        if flag:
            sqlmerge = "NUM_RECORDS NOT LIKE 'NONE'"
        else:
            sqlmerge = "NUM_RECORDS LIKE 'NONE'"
        return flag, sqlmerge

    @pyqtSlot()
    def on_homeButton_clicked(self):
        self.tabModel.setFilter("NUM_RECORDS LIKE 'NONE'")
        self.ui.mergeBox.setChecked(False)

    @pyqtSlot()
    def on_mergeButton_clicked(self):
        self.tabModel.setFilter("NUM_RECORDS NOT LIKE 'NONE'")
        self.ui.mergeBox.setChecked(True)

    @pyqtSlot()
    def on_searchButton_clicked(self):
        searchtext = self.ui.searchInput.text()
        searchclass = self.ui.searchClass.currentText()
        matchtype = self.ui.matchType.currentText()
        flag, sqlmerge = self.merged_or_not()

        if searchclass == "DOI":
            if matchtype == "Exact Match":
                self.tabModel.setFilter("DOI LIKE '%s' AND %s" %
                                        (searchtext, sqlmerge))
            elif matchtype == "Generic Match":
                self.tabModel.setFilter("DOI LIKE '%%%s%%' AND %s" %
                                        (searchtext, sqlmerge))

            if self.tabModel.rowCount() == 0:
                self.tabModel.setFilter("")
                QMessageBox.warning(
                    self, "Warning",
                    "No such DOIs in the database. Please search new DOI.")

        elif searchclass == "Warning":
            if matchtype == "Exact Match":
                self.tabModel.setFilter("WARNING LIKE '%s' AND %s" %
                                        (searchtext, sqlmerge))
            elif matchtype == "Generic Match":
                self.tabModel.setFilter("WARNING LIKE '%%%s%%' AND %s" %
                                        (searchtext, sqlmerge))

            if self.tabModel.rowCount() == 0:
                self.tabModel.setFilter("")
                QMessageBox.warning(
                    self, "Warning",
                    "No such DOIs in the database. Please search new DOI.")

        elif searchclass == 'Name':
            try:
                searchtext = self.get_elements()[searchtext.capitalize()]
            except BaseException:
                pass
            if matchtype == "Exact Match":
                if self.ui.radioBtnAll.isChecked():
                    self.tabModel.setFilter("%s LIKE '%s' " %
                                            (searchclass, searchtext))
                elif self.ui.radioBtnVoltage.isChecked():
                    self.tabModel.setFilter(
                        "%s LIKE '%s' AND PROPERTY LIKE 'VOLTAGE' AND %s" %
                        (searchclass, searchtext, sqlmerge))
                elif self.ui.radioBtnCapacity.isChecked():
                    self.tabModel.setFilter(
                        "%s LIKE '%s' AND PROPERTY LIKE 'CAPACITY' AND %s" %
                        (searchclass, searchtext, sqlmerge))
                elif self.ui.radioBtnConductivity.isChecked():
                    self.tabModel.setFilter(
                        "%s LIKE '%s' AND PROPERTY LIKE 'CONDUCTIVITY' AND %s"
                        % (searchclass, searchtext, sqlmerge))
                elif self.ui.radioBtnCoulombic.isChecked():
                    self.tabModel.setFilter(
                        "%s LIKE '%s' AND PROPERTY LIKE 'COULOMBIC EFFICIENCY' AND %s "
                        % (searchclass, searchtext, sqlmerge))
                elif self.ui.radioBtnEnergy.isChecked():
                    self.tabModel.setFilter(
                        "%s LIKE '%s' AND PROPERTY LIKE 'ENERGY'AND %s " %
                        (searchclass, searchtext, sqlmerge))

            elif matchtype == "Generic Match":
                if self.ui.radioBtnAll.isChecked():
                    self.tabModel.setFilter(
                        "(EXTRACTED_NAME LIKE '%%''%s''%%' OR NAME LIKE '%s') AND %s"
                        % (searchtext, searchtext, sqlmerge))
                elif self.ui.radioBtnVoltage.isChecked():
                    self.tabModel.setFilter(
                        "EXTRACTED_NAME LIKE '%%''%s''%%' OR NAME LIKE '%s' AND %s"
                        % (searchtext, searchtext, sqlmerge))
                elif self.ui.radioBtnCapacity.isChecked():
                    self.tabModel.setFilter(
                        "EXTRACTED_NAME LIKE '%%''%s''%%' OR NAME LIKE '%s' AND %s"
                        % (searchtext, searchtext, sqlmerge))
                elif self.ui.radioBtnConductivity.isChecked():
                    self.tabModel.setFilter(
                        "EXTRACTED_NAME LIKE '%%''%s''%%' OR NAME LIKE '%s' AND %s"
                        % (searchtext, searchtext, sqlmerge))
                elif self.ui.radioBtnCoulombic.isChecked():
                    self.tabModel.setFilter(
                        "EXTRACTED_NAME LIKE '%%''%s''%%' OR NAME LIKE '%s' AND %s"
                        % (searchtext, searchtext, sqlmerge))
                elif self.ui.radioBtnEnergy.isChecked():
                    self.tabModel.setFilter(
                        "EXTRACTED_NAME LIKE '%%''%s''%%' OR NAME LIKE '%s' AND %s"
                        % (searchtext, searchtext, sqlmerge))

            if self.tabModel.rowCount() == 0:
                self.tabModel.setFilter("")
                QMessageBox.warning(
                    self, "Warning",
                    "No such compounds in the database. Please search new compounds."
                )

# ============Picture Tab 1, Pie Chart=====================

    @pyqtSlot()  # Draw the pie chart
    def on_btnDrawPieChart_clicked(self):
        self.draw_pieChart()

    @pyqtSlot(float)  # Set holeSize
    def on_spinHoleSize_valueChanged(self, arg1):
        seriesPie = self.ui.chartViewPie.chart().series()[0]
        seriesPie.setHoleSize(arg1)

    @pyqtSlot(float)  # Set pieSize
    def on_spinPieSize_valueChanged(self, arg1):
        seriesPie = self.ui.chartViewPie.chart().series()[0]
        seriesPie.setPieSize(arg1)

    @pyqtSlot(bool)  # Set legend checkbox
    def on_chkBox_PieLegend_clicked(self, checked):
        self.ui.chartViewPie.chart().legend().setVisible(checked)

    def pie_data(
            self):  # Return a list of property name and the number of property
        num_list = []
        pro_list = [
            "CAPACITY", "CONDUCTIVITY", "COULOMBIC EFFICIENCY", "ENERGY",
            "VOLTAGE"
        ]
        for i in range(len(pro_list)):
            query = QSqlQuery(
                db=self.DB,
                query=
                "SELECT COUNT(NAME) FROM BATTERY WHERE PROPERTY LIKE '%s' AND NUM_RECORDS LIKE 'NONE'"
                % pro_list[i])  # Query database
            while query.next():
                num_value = query.value(0)  # Returned value for each query

                item = self.ui.treeWidget_2.topLevelItem(i)  # The ith row
                # The 2nd column
                item.setText(1, str(num_value))
                item.setTextAlignment(1, Qt.AlignHCenter)

                num_list.append(num_value)
        return pro_list, num_list

    def draw_pieChart(self):  # Draw the pie chart
        chart = self.ui.chartViewPie.chart()

        chart.legend().setAlignment(Qt.AlignRight)  # AlignRight,AlignBottom
        chart.removeAllSeries()  # Delete all series

        seriesPie = QPieSeries()  # Pie chart series
        seriesPie.setHoleSize(self.ui.spinHoleSize.value())  # Hole size
        seriesPie.setPieSize(self.ui.spinPieSize.value())  # Pie size
        sec_count = 5  # Number of properties
        seriesPie.setLabelsVisible(True)  # Label

        pro, num = self.pie_data()
        for i in range(sec_count):
            seriesPie.append(pro[i], num[i])

        seriesPie.setLabelsVisible(True)  # Label

        # Pie hoverd when mouse selected
        seriesPie.hovered.connect(self.do_pieHovered)
        chart.addSeries(seriesPie)
        chart.setTitle("Proportion of data records for each property")
        font = QFont()
        font.setPointSize(12)
        font.setWeight(75)
        chart.setTitleFont(font)

        font = QFont()
        font.setPointSize(12)
        font.setBold(False)
        font.setWeight(35)
        legend = chart.legend()
        legend.setFont(font)

# =========Picture tab 2. StackedBar=========

    @pyqtSlot()  # Draw StackedBar
    def on_btnStackedBar_clicked(self):
        self.draw_stackedBar()

    @pyqtSlot()  # Draw horizontal StackedBar
    def on_btnStackedBarH_clicked(self):
        self.draw_stackedBar(False)

    # Search button in the Stacked bar chart tab. Add name to the first column
    # of the table.
    @pyqtSlot()
    def on_searchButton_3_clicked(self):
        searchtext = self.ui.searchInput_3.text()

        current_index = self.ui.stackedWidget.topLevelItemCount()
        item_0 = QtWidgets.QTreeWidgetItem(self.ui.stackedWidget)
        item_0.setText(0, searchtext)

    @pyqtSlot()  # Generate data using the input chemical names
    def on_generateButton_3_clicked(self):
        self.ui.zoominButton.setEnabled(True)
        self.ui.zoomoutButton.setEnabled(True)
        self.ui.originalButton.setEnabled(True)
        self.ui.btnStackedBar.setEnabled(True)  # Stacked bar chart
        self.ui.btnStackedBarH.setEnabled(True)

        current_index = self.ui.stackedWidget.topLevelItemCount()
        chemical_list = [
            self.ui.stackedWidget.topLevelItem(index).text(0)
            for index in range(current_index)
        ]  # Get a list of the inputed chemical name
        pro_list = [
            "CAPACITY", "CONDUCTIVITY", "COULOMBIC EFFICIENCY", "ENERGY",
            "VOLTAGE"
        ]
        for row, chemical in enumerate(chemical_list):
            for index, pro in enumerate(pro_list):
                query = QSqlQuery(
                    db=self.DB,
                    query=
                    "SELECT SUM(NUM_RECORDS) FROM BATTERY WHERE PROPERTY LIKE '%s' AND NAME LIKE '%s' "
                    % (pro, chemical))
                while query.next():
                    num_value = query.value(0)
                    print(num_value)
                    if num_value == "":
                        num_value = 0
                    item = self.ui.stackedWidget.topLevelItem(
                        row)  # The row'th row
                    item.setText(index + 1, str(num_value))
                    item.setTextAlignment(index + 1, Qt.AlignHCenter)

    @pyqtSlot()  # Clear button
    def on_clearButton_3_clicked(self):
        self.ui.stackedWidget.clear()

    @pyqtSlot()  # Zoom in
    def on_zoominButton_clicked(self):
        self.ui.chartViewStackedBar.chart().zoom(1.2)

    @pyqtSlot()  # Zoom out
    def on_zoomoutButton_clicked(self):
        self.ui.chartViewStackedBar.chart().zoom(0.8)

    @pyqtSlot()  # Reset original size
    def on_originalButton_clicked(self):
        self.ui.chartViewStackedBar.chart().zoomReset()

    def draw_stackedBar(self, isVertical=True):  # Stacked bar chart
        chart = self.ui.chartViewStackedBar.chart()
        chart.removeAllSeries()  # Remove all series
        chart.removeAxis(chart.axisX())  # remove axis
        chart.removeAxis(chart.axisY())
        if isVertical:  # Vertical
            chart.setTitle("Number of property records for each chemical ")
            chart.legend().setAlignment(Qt.AlignBottom)
        else:  # Horizontal
            chart.setTitle("Number of property records for each chemical")
            chart.legend().setAlignment(Qt.AlignRight)

        # Create data sets
        setCapacity = QBarSet("Capacity")
        setConductivity = QBarSet("Conductivity")
        setCoulombic = QBarSet("Coulombic")
        setEnergy = QBarSet("Energy")
        setVoltage = QBarSet("Voltage")

        chemical_Count = self.ui.stackedWidget.topLevelItemCount()
        nameList = []  # Chemical lists
        for i in range(chemical_Count):
            item = self.ui.stackedWidget.topLevelItem(i)
            # print(item.text(1))
            nameList.append(item.text(0))
            setCapacity.append(float(item.text(1)))
            setConductivity.append(float(item.text(2)))
            setCoulombic.append(float(item.text(3)))
            setEnergy.append(float(item.text(4)))
            setVoltage.append(float(item.text(5)))

        # Create series
        if isVertical:
            seriesBar = QStackedBarSeries()
        else:
            seriesBar = QHorizontalStackedBarSeries()

        seriesBar.append(setCapacity)
        seriesBar.append(setConductivity)
        seriesBar.append(setCoulombic)
        seriesBar.append(setEnergy)
        seriesBar.append(setVoltage)

        seriesBar.setLabelsVisible(True)  # Show labels for each bar
        seriesBar.setLabelsFormat("@value")
        seriesBar.setLabelsPosition(QAbstractBarSeries.LabelsCenter)

        seriesBar.setBarWidth(0.3)

        chart.addSeries(seriesBar)

        axisStud = QBarCategoryAxis()  # Category axis
        axisStud.append(nameList)
        axisStud.setRange(nameList[0], nameList[chemical_Count - 1])

        axisValue = QValueAxis()  # Value axis
        # axisValue.setRange(0, 300)
        axisValue.setTitleText("Number of records")
        # axisValue.setTickCount(6)
        axisValue.applyNiceNumbers()

        if isVertical:
            chart.setAxisX(axisStud, seriesBar)
            chart.setAxisY(axisValue, seriesBar)
        else:
            chart.setAxisY(axisStud, seriesBar)
            chart.setAxisX(axisValue, seriesBar)

        for marker in chart.legend().markers():  # QLegendMarker lists
            marker.clicked.connect(self.do_LegendMarkerClicked)

# =========Picture tab 3. Histogram=========

    @pyqtSlot(bool)  # Show toolbar
    def on_gBoxHist_toolbar_2_clicked(self, checked):
        self.ui.widgetHist_2.setToolbarVisible(checked)

    @pyqtSlot()  # Draw
    def on_histButton_clicked(self):
        self.__drawHist()

    def hist_data(self, pro):
        query = QSqlQuery(
            db=self.DB,
            query=
            "SELECT VALUE FROM BATTERY WHERE PROPERTY LIKE '%s' AND NUM_RECORDS LIKE 'NONE'"
            % pro)
        data = []
        while query.next():
            num_value = query.value(0)
            data.append(num_value)
        return data

    def __drawHist(self):  # Histogram
        pro = self.ui.propertycomboBox_2.currentText()
        data = self.hist_data(pro)
        self.ui.widgetHist_2.figure.clear()  # Clear figure

        ax = self.ui.widgetHist_2.figure.add_subplot(1, 1, 1)

        if pro == 'Capacity':
            M, bins, patches = ax.hist(
                [5000 if float(i) > 4999 else float(i) for i in data],
                bins='auto',
                color='darkgreen',
                alpha=0.5,
                rwidth=1)
            ax.set_xlim(0, 5001)
            # ax.set_ylim(0,15000)
            ax.tick_params(labelsize=12)
            ax.set_xticklabels(['0', '1000', '2000', '3000', '4000', '5000+'])
            ax.set_xlabel('Capacity (mAh/g)', fontsize=14)
            ax.set_ylabel('Frequency', fontsize=14)
            ax.set_title('Battery Capacity Distrbution', fontsize=14)
            ax.figure.canvas.draw()

        elif pro == "Voltage":
            count1 = []
            for i in data:
                count1.append(float(i))

            n, bins, patches = ax.hist(x=count1,
                                       bins='auto',
                                       range=(0, 8),
                                       color='r',
                                       alpha=0.5,
                                       rwidth=1)
            ax.set_xticklabels(['0', '1', '2', '3', '4', '5', '6', '7', '8+'])

            ax.set_xlim(0, 8)
            ax.tick_params(labelsize=12)
            ax.set_xlabel('Voltage (V)', fontsize=14)
            ax.set_ylabel('Frequency', fontsize=14)
            ax.set_title('Battery Voltage Distrbution', fontsize=14)
            ax.figure.canvas.draw()

        elif pro == "Energy":
            n, bins, patches = ax.hist(
                [3000 if float(i) > 2999 else float(i) for i in data],
                bins='auto',
                color='y',
                alpha=0.5,
                rwidth=1)
            ax.set_xticklabels(
                ['0', '500', '1000', '1500', '2000', '2500', '3000+'])
            ax.set_xlim(0, 3001)
            ax.tick_params(labelsize=12)
            ax.set_xlabel('Energy (Wh/kg)', fontsize=14)
            ax.set_ylabel('Frequency', fontsize=14)
            ax.set_title('Battery Energy Distrbution', fontsize=14)
            ax.figure.canvas.draw()

        elif pro == "Coulombic Efficiency":
            dataplot = [float(i) for i in data]
            n, bins, patches = ax.hist(x=dataplot,
                                       bins='auto',
                                       color='c',
                                       alpha=0.5,
                                       rwidth=1)
            ax.set_xlim(0, 100)
            ax.tick_params(labelsize=12)
            ax.set_xlabel('Coulombic Effciency (%)', fontsize=14)
            ax.set_ylabel('Frequency', fontsize=14)
            ax.set_title('Battery Coulombic Effciency Distrbution',
                         fontsize=14)
            ax.figure.canvas.draw()

        elif pro == "Conductivity":
            dataplot = [float(i) for i in data]
            n, bins, patches = ax.hist(x=dataplot,
                                       bins=np.logspace(
                                           np.log10(1e-15), np.log10(1)),
                                       color='k',
                                       alpha=0.5,
                                       rwidth=1)
            ax.set_xlim(1e-20, 10)
            ax.set_xscale('log')
            ax.tick_params(labelsize=12)
            ax.set_xlabel('log10 (Conductivity (S/cm))', fontsize=14)
            ax.set_ylabel('Frequency', fontsize=14)
            ax.set_title('Battery Conductivity Distrbution', fontsize=14)
            ax.figure.canvas.draw()

# =========Picture tab 4. Venn diagram=========

    @pyqtSlot()  # Draw
    def on_btnVenn_clicked(self):
        self.__drawVenn()

    @pyqtSlot(bool)  # Show toolbar
    def on_gBoxHist_toolbar_3_clicked(self, checked):
        self.ui.widgetVenn.setToolbarVisible(checked)

    def __drawVenn(self):
        self.ui.widgetVenn.figure.clear()  # Clear figure

        pro_list = [
            "Capacity", "Conductivity", "Coulombic Efficiency", "Energy",
            "Voltage"
        ]
        data_dic = {}
        color_dic = dict(zip(pro_list, ['C0', 'C2', 'C6', 'C8', 'C9']))

        for i in pro_list:
            query = QSqlQuery(
                db=self.DB,
                query=
                "SELECT COUNT(DISTINCT NAME) FROM BATTERY WHERE PROPERTY LIKE '%s' AND NUM_RECORDS LIKE 'NONE'"
                % i)
            while query.next():
                num_value = query.value(0)
                data_dic[i] = num_value

        for i, combo in enumerate(itertools.combinations(pro_list, 2)):

            query = QSqlQuery(
                db=self.DB,
                query=
                "SELECT COUNT() FROM (SELECT DISTINCT NAME AS PRO1 FROM BATTERY WHERE PROPERTY LIKE '%s'AND NUM_RECORDS LIKE 'NONE') INNER JOIN (SELECT DISTINCT NAME AS PRO2 FROM BATTERY WHERE PROPERTY LIKE '%s'AND NUM_RECORDS LIKE 'NONE') ON PRO1 = PRO2"
                % combo)
            while query.next():
                num = query.value(0)
            x3 = num
            x1 = data_dic[combo[0]] - x3
            x2 = data_dic[combo[1]] - x3

            hf = self.ui.widgetVenn.figure
            # hf.set_figheight(30)
            # hf.set_figwidth(30)
            # print(dir(hf))

            hf.set_size_inches((10, 10))
            ax1 = hf.add_subplot(5, 2, i + 1)
            v = venn2(subsets=(x1, x2, x3),
                      set_labels=(combo[0], combo[1]),
                      ax=ax1)

            v.get_patch_by_id('A').set_alpha(1)
            v.get_patch_by_id('A').set_color(color_dic[combo[0]])
            v.get_patch_by_id('B').set_color(color_dic[combo[1]])

            ax1.figure.canvas.draw()

# =============Self-defined slot function===============================

# Update the conditions of actPost and actCancel

    def do_currentChanged(self, current, previous):
        self.ui.actSubmit.setEnabled(
            self.tabModel.isDirty())  # Use when not saving changes
        self.ui.actRevert.setEnabled(self.tabModel.isDirty())

    def do_currentRowChanged(self, current,
                             previous):  # Control during row changes
        self.ui.actRecDelete.setEnabled(current.isValid())

        # Update current row index of mapping
        self.mapper.setCurrentIndex(current.row())
        # Get current record,QSqlRecord
        curRec = self.tabModel.record(current.row())

    def do_pieHovered(self, pieSlice,
                      state):  # Mouse move in and out in the pie chart
        pieSlice.setExploded(state)  # Pop-up animation
        if state:  # Show the tab of percentages
            self.__oldLabel = pieSlice.label()  # Save original labels
            pieSlice.setLabel(self.__oldLabel + ": %.1f%%" %
                              (pieSlice.percentage() * 100))
            font = QFont()
            font.setPointSize(10)
            font.setBold(False)
            font.setWeight(25)
            pieSlice.setLabelFont(font)
        else:  # show original labels
            pieSlice.setLabel(self.__oldLabel)
            font = QFont()
            font.setPointSize(10)
            font.setBold(False)
            font.setWeight(25)
            pieSlice.setLabelFont(font)

    def do_LegendMarkerClicked(self):  # Click legend marker
        marker = self.sender()  # QLegendMarker

        marker.series().setVisible(not marker.series().isVisible())
        marker.setVisible(True)
        alpha = 1.0
        if not marker.series().isVisible():
            alpha = 0.5

        brush = marker.labelBrush()  # QBrush
        color = brush.color()  # QColor
        color.setAlphaF(alpha)
        brush.setColor(color)
        marker.setLabelBrush(brush)

        brush = marker.brush()
        color = brush.color()
        color.setAlphaF(alpha)
        brush.setColor(color)
        marker.setBrush(brush)

        pen = marker.pen()  # QPen
        color = pen.color()
        color.setAlphaF(alpha)
        pen.setColor(color)
        marker.setPen(pen)
Beispiel #11
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.splitter)

        self.ui.tableView.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.ui.tableView.setSelectionMode(QAbstractItemView.SingleSelection)
        self.ui.tableView.setAlternatingRowColors(True)
        self.ui.tableView.verticalHeader().setDefaultSectionSize(22)
        self.ui.tableView.horizontalHeader().setDefaultSectionSize(60)

    @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, "错误", "打开数据库失败")

    def __openTable(self):
        self.qryModel = QSqlQueryModel(self)
        self.qryModel.setQuery(
            '''SELECT empNo, Name, Gender, Birthday, Province, Department, Salary FROM employee ORDER BY empNo'''
        )
        if self.qryModel.lastError().isValid():
            QMessageBox.critical(
                self, "错误",
                "数据表查询错误,错误信息\n" + self.qryModel.lastError().text())
            return
        self.ui.statusBar.showMessage("记录条数:%d" % self.qryModel.rowCount())
        self.__getFieldNames()

        self.qryModel.setHeaderData(0, Qt.Horizontal, "工号")
        self.qryModel.setHeaderData(1, Qt.Horizontal, "姓名")
        self.qryModel.setHeaderData(2, Qt.Horizontal, "性别")
        self.qryModel.setHeaderData(3, Qt.Horizontal, "出生日期")
        self.qryModel.setHeaderData(4, Qt.Horizontal, "省份")
        self.qryModel.setHeaderData(5, Qt.Horizontal, "部门")
        self.qryModel.setHeaderData(6, Qt.Horizontal, "工资")

        self.mapper = QDataWidgetMapper()
        self.mapper.setModel(self.qryModel)
        self.mapper.addMapping(self.ui.dbSpinEmpNo, 0)
        self.mapper.addMapping(self.ui.dbEditName, 1)
        self.mapper.addMapping(self.ui.dbComboSex, 2)
        self.mapper.addMapping(self.ui.dbEditBirth, 3)
        self.mapper.addMapping(self.ui.dbComboProvince, 4)
        self.mapper.addMapping(self.ui.dbComboDep, 5)
        self.mapper.addMapping(self.ui.dbSpinSalary, 6)
        self.mapper.toFirst()

        self.selModel = QItemSelectionModel(self.qryModel)
        self.selModel.currentRowChanged.connect(self.do_currentRowChanged)

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

        self.ui.actOpenDB.setEnabled(False)

    def __refreshTableView(self):
        index = self.mapper.currentIndex()
        curIndex = self.qryModel.index(index, 1)
        self.selModel.clearSelection()
        self.selModel.setCurrentIndex(curIndex, QItemSelectionModel.Select)

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

    @pyqtSlot()
    def on_actRecFirst_triggered(self):
        self.mapper.toFirst()
        self.__refreshTableView()

    @pyqtSlot()
    def on_actRecPrevious_triggered(self):
        self.mapper.toPrevious()
        self.__refreshTableView()

    @pyqtSlot()
    def on_actRecNext_triggered(self):
        self.mapper.toNext()
        self.__refreshTableView()

    @pyqtSlot()
    def on_actRecLast_triggered(self):
        self.mapper.toLast()
        self.__refreshTableView()

    def do_currentRowChanged(self, current, previous):
        if (current.isValid() == False):
            self.ui.dbLabPhoto.clear()
            return
        self.mapper.setCurrentIndex(current.row())
        first = (current.row() == 0)
        last = (current.row() == self.qryModel.rowCount() - 1)
        self.ui.actRecFirst.setEnabled(not first)
        self.ui.actRecPrevious.setEnabled(not first)
        self.ui.actRecNext.setEnabled(not last)
        self.ui.actRecLast.setEnabled(not last)

        curRec = self.qryModel.record(current.row())
        empNo = curRec.value("EmpNo")

        query = QSqlQuery(self.DB)
        query.prepare(
            '''SELECT EmpNo, Memo, Photo FROM employee WHERE EmpNo = :ID''')
        query.bindValue(":ID", empNo)
        if not query.exec():
            QMessageBox.critical(self, "错误",
                                 "执行SQL语句错误\n" + query.lastError().text())
            return
        else:
            query.first()

        picData = query.value("Photo")
        if (picData == None):
            self.ui.dbLabPhoto.clear()
        else:
            pic = QPixmap()
            pic.loadFromData(picData)
            W = self.ui.dbLabPhoto.size().width()
            self.ui.dbLabPhoto.setPixmap(pic.scaledToWidth(W))

        memoData = query.value("Memo")
        self.ui.dbEditMemo.setPlainText(memoData)
Beispiel #12
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.splitter)

        self.__ColCount = 6  #列数=6
        self.itemModel = QStandardItemModel(5, self.__ColCount,
                                            self)  # 数据模型,10行6列

        self.selectionModel = QItemSelectionModel(self.itemModel)  #Item选择模型
        self.selectionModel.currentChanged.connect(self.do_curChanged)

        self.__lastColumnTitle = "测井取样"
        self.__lastColumnFlags = (Qt.ItemIsSelectable
                                  | Qt.ItemIsUserCheckable | Qt.ItemIsEnabled)

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

        oneOrMore = QAbstractItemView.ExtendedSelection
        self.ui.tableView.setSelectionMode(oneOrMore)  #可多选

        itemOrRow = QAbstractItemView.SelectItems
        self.ui.tableView.setSelectionBehavior(itemOrRow)  #单元格选择

        self.ui.tableView.verticalHeader().setDefaultSectionSize(22)  #缺省行高
        self.ui.tableView.setAlternatingRowColors(True)  #交替行颜色

        self.ui.tableView.setEnabled(False)  #先禁用tableView
        self.__buildStatusBar()

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

    def __buildStatusBar(self):  ##构建状态栏
        self.LabCellPos = QLabel("当前单元格:", self)
        self.LabCellPos.setMinimumWidth(180)
        self.ui.statusBar.addWidget(self.LabCellPos)

        self.LabCellText = QLabel("单元格内容:", self)
        self.LabCellText.setMinimumWidth(150)
        self.ui.statusBar.addWidget(self.LabCellText)

        self.LabCurFile = QLabel("当前文件:", self)
        self.ui.statusBar.addPermanentWidget(self.LabCurFile)

    def __iniModelFromStringList(self, allLines):  ##从字符串列表构建模型
        rowCnt = len(allLines)  #文本行数,第1行是标题
        self.itemModel.setRowCount(rowCnt - 1)  #实际数据行数

        headerText = allLines[0].strip()  #第1行是表头,去掉末尾的换行符 "\n"
        headerList = headerText.split("\t")  #转换为字符串列表
        self.itemModel.setHorizontalHeaderLabels(headerList)  #设置表头标题

        self.__lastColumnTitle = headerList[len(headerList) -
                                            1]  # 最后一列表头的标题,即“测井取样”

        lastColNo = self.__ColCount - 1  #最后一列的列号
        for i in range(rowCnt - 1):
            lineText = allLines[i + 1].strip()  #一行的文字,\t分隔
            strList = lineText.split("\t")  #分割为字符串列表
            for j in range(self.__ColCount - 1):  #不含最后一列
                item = QStandardItem(strList[j])
                self.itemModel.setItem(i, j, item)  #设置模型的item

            item = QStandardItem(self.__lastColumnTitle)  #最后一列
            item.setFlags(self.__lastColumnFlags)
            item.setCheckable(True)
            if (strList[lastColNo] == "0"):
                item.setCheckState(Qt.Unchecked)
            else:
                item.setCheckState(Qt.Checked)

            self.itemModel.setItem(i, lastColNo, item)  #设置最后一列的item

    def __setCellAlignment(self, align=Qt.AlignHCenter):
        if (not self.selectionModel.hasSelection()):  #没有选择的项
            return
        selectedIndex = self.selectionModel.selectedIndexes()  #模型索引列表
        count = len(selectedIndex)
        for i in range(count):
            index = selectedIndex[i]  #获取其中的一个模型索引
            item = self.itemModel.itemFromIndex(index)  #获取一个单元格的项数据对象
            item.setTextAlignment(align)  #设置文字对齐方式

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

    @pyqtSlot()  ##“打开文件”
    def on_actOpen_triggered(self):
        ##        curPath=QDir.currentPath() #获取当前路径
        curPath = os.getcwd()  #获取当前路径

        filename, flt = QFileDialog.getOpenFileName(
            self, "打开一个文件", curPath, "井斜数据文件(*.txt);;所有文件(*.*)")
        if (filename == ""):
            return

        self.LabCurFile.setText("当前文件:" + filename)
        self.ui.plainTextEdit.clear()

        aFile = open(filename, 'r')
        allLines = aFile.readlines()  #读取所有行,list类型,每行末尾带有 \n
        aFile.close()

        for strLine in allLines:
            self.ui.plainTextEdit.appendPlainText(strLine.strip())

        self.__iniModelFromStringList(allLines)
        self.ui.tableView.setEnabled(True)  #tableView可用
        self.ui.actAppend.setEnabled(True)  #更新Actions的enable属性
        self.ui.actInsert.setEnabled(True)
        self.ui.actDelete.setEnabled(True)
        self.ui.actSave.setEnabled(True)
        self.ui.actModelData.setEnabled(True)

    @pyqtSlot()  ##保存文件
    def on_actSave_triggered(self):
        ##      curPath=QDir.currentPath() #获取当前路径
        curPath = os.getcwd()  #获取当前路径
        filename, flt = QFileDialog.getSaveFileName(
            self, "保存文件", curPath, "井斜数据文件(*.txt);;所有文件(*.*)")
        if (filename == ""):
            return

        self.on_actModelData_triggered()  #更新数据到plainTextEdit

        aFile = open(filename, 'w')  #以写方式打开
        aFile.write(self.ui.plainTextEdit.toPlainText())
        aFile.close()

    @pyqtSlot()  ##在最后添加一行
    def on_actAppend_triggered(self):
        itemlist = []  # QStandardItem 对象列表
        for i in range(self.__ColCount - 1):  #不包括最后一列
            item = QStandardItem("0")
            itemlist.append(item)

        item = QStandardItem(self.__lastColumnTitle)  #最后一列
        item.setCheckable(True)
        item.setFlags(self.__lastColumnFlags)
        itemlist.append(item)

        self.itemModel.appendRow(itemlist)  #添加一行
        curIndex = self.itemModel.index(self.itemModel.rowCount() - 1, 0)
        self.selectionModel.clearSelection()
        self.selectionModel.setCurrentIndex(curIndex,
                                            QItemSelectionModel.Select)

    @pyqtSlot()  ##插入一行
    def on_actInsert_triggered(self):
        itemlist = []  #  QStandardItem 对象列表
        for i in range(self.__ColCount - 1):  #不包括最后一列
            item = QStandardItem("0")
            itemlist.append(item)

        item = QStandardItem(self.__lastColumnTitle)  #最后一列
        item.setFlags(self.__lastColumnFlags)
        item.setCheckable(True)
        item.setCheckState(Qt.Checked)
        itemlist.append(item)

        curIndex = self.selectionModel.currentIndex()
        #获取当前选中项的模型索引
        self.itemModel.insertRow(curIndex.row(), itemlist)
        #在当前行的前面插入一行
        self.selectionModel.clearSelection()
        self.selectionModel.setCurrentIndex(curIndex,
                                            QItemSelectionModel.Select)

    @pyqtSlot()  ##删除当前行
    def on_actDelete_triggered(self):
        curIndex = self.selectionModel.currentIndex()  #获取当前选择单元格的模型索引
        self.itemModel.removeRow(curIndex.row())  #删除当前行

    @pyqtSlot()  ##左对齐
    def on_actAlignLeft_triggered(self):
        self.__setCellAlignment(Qt.AlignLeft | Qt.AlignVCenter)

    @pyqtSlot()  ##中间对齐
    def on_actAlignCenter_triggered(self):
        self.__setCellAlignment(Qt.AlignHCenter | Qt.AlignVCenter)

    @pyqtSlot()  ##右对齐
    def on_actAlignRight_triggered(self):
        self.__setCellAlignment(Qt.AlignRight | Qt.AlignVCenter)

    @pyqtSlot(bool)  ##字体Bold
    def on_actFontBold_triggered(self, checked):
        if (not self.selectionModel.hasSelection()):  #没有选择的项
            return
        selectedIndex = self.selectionModel.selectedIndexes()  #模型索引列表
        count = len(selectedIndex)
        for i in range(count):
            index = selectedIndex[i]  #获取其中的一个模型索引
            item = self.itemModel.itemFromIndex(index)  #获取一个单元格的项数据对象
            font = item.font()
            font.setBold(checked)
            item.setFont(font)

    @pyqtSlot()  ##模型数据显示到plainTextEdit里
    def on_actModelData_triggered(self):
        self.ui.plainTextEdit.clear()
        lineStr = ""
        for i in range(self.itemModel.columnCount() - 1):  #表头,不含最后一列
            item = self.itemModel.horizontalHeaderItem(i)
            lineStr = lineStr + item.text() + "\t"
        item = self.itemModel.horizontalHeaderItem(self.__ColCount - 1)  #最后一列
        lineStr = lineStr + item.text()  #表头文字字符串
        self.ui.plainTextEdit.appendPlainText(lineStr)

        for i in range(self.itemModel.rowCount()):
            lineStr = ""
            for j in range(self.itemModel.columnCount() - 1):  #不包括最后一列
                item = self.itemModel.item(i, j)
                lineStr = lineStr + item.text() + "\t"
            item = self.itemModel.item(i, self.__ColCount - 1)  #最后一列
            if (item.checkState() == Qt.Checked):
                lineStr = lineStr + "1"
            else:
                lineStr = lineStr + "0"
            self.ui.plainTextEdit.appendPlainText(lineStr)

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

    def do_curChanged(self, current, previous):
        if (current != None):  #当前模型索引有效
            text = "当前单元格:%d行,%d列" % (current.row(), current.column())
            self.LabCellPos.setText(text)
            item = self.itemModel.itemFromIndex(current)  #从模型索引获得Item
            self.LabCellText.setText("单元格内容:" + item.text())  #显示item的文字内容

            font = item.font()  #获取item的字体
            self.ui.actFontBold.setChecked(font.bold())  #更新actFontBold的check状态
class AccountsManager(ui.manageAccounts.Ui_Dialog, QDialog):
    """
    GUI that handles creation, editing and deletion of accounts.
    """
    def __init__(self, orm):
        super().__init__()
        self.setupUi(self)

        self.orm = orm

        self.accounts = ListModel()
        self.accountsView.setModel(self.accounts)

        self.selection = QItemSelectionModel(self.accounts)
        self.accountsView.setSelectionModel(self.selection)

        self.selection.currentRowChanged.connect(self.selection_changed)

        self.typeBox.addItems(ACCOUNT_TYPES)
        self.typeBox.currentTextChanged.connect(self.type_changed)

        self.closedBox.stateChanged.connect(self.closed_changed)
        self.exBudgetBox.stateChanged.connect(self.budget_changed)

        self.addAccountButton.clicked.connect(self.add_account)
        self.deleteAccountButton.clicked.connect(self.delete_account)

        for acc in self.orm.fetch_accounts():
            self.accounts.addItem(acc)

    def selection_changed(self, curr_index: QModelIndex, prev_index: QModelIndex):
        """
        Updates the information about currently selected account.
        """
        if not curr_index.isValid():
            return None

        # Make sure selection is visible in the view
        self.selection.setCurrentIndex(
            curr_index, QItemSelectionModel.SelectCurrent)

        acc = curr_index.data(role=Qt.UserRole)

        # Set the type of account
        self.typeBox.setCurrentText(acc.type)

        # Set the checkboxes
        self.closedBox.setChecked(acc.closed)
        self.exBudgetBox.setChecked(acc.exbudget)

    def type_changed(self, text: str):
        """
        Changes the type of the account in DB and GUI.
        """
        model_indexes = self.selection.selectedIndexes()
        if not model_indexes:
            return None

        model_index = model_indexes[0]
        acc = model_index.data(role=Qt.UserRole)

        # Catch only changes that differ for selected account
        if acc.type != text:
            self.orm.update_account_type(acc, text)
            acc.type = text

    def closed_changed(self, state: int):
        """
        Changes close status of the account in DB and GUI.
        """
        model_indexes = self.selection.selectedIndexes()
        if not model_indexes:
            return None

        model_index = model_indexes[0]
        acc = model_index.data(role=Qt.UserRole)

        # Catch only changes that differ for selected account
        # acc states in (0,1); Qt.CheckState in (0,1,2)
        # (0,1,2)//2 -> (0,0,1)
        state //= 2
        if acc.closed != state:
            self.orm.update_account_status(acc, state)
            acc.closed = state

    def budget_changed(self, state: int):
        """
        Changes the budget status of account in DB and GUI.
        """
        model_indexes = self.selection.selectedIndexes()
        if not model_indexes:
            return None

        model_index = model_indexes[0]
        acc = model_index.data(role=Qt.UserRole)

        # Catch only changes that differ for selected account
        # acc states in (0,1); Qt.CheckState in (0,1,2)
        # (0,1,2)//2 -> (0,0,1)
        state //= 2
        if acc.exbudget != state:
            self.orm.update_account_budget_status(acc, state)
            acc.exbudget = state

    def add_account(self):
        """
        Creates account with default attributes in DB and adds it to GUI.
        """
        name, ok = QInputDialog.getText(self, "Add new account",
                                        "Enter the name of the new account:")

        if ok and name:
            acc = self.orm.add_account(name)
            self.accounts.addItem(acc)

    def delete_account(self):
        """
        Tries to delete the account from DB, if successful deletes it from GUI.
        """
        model_indexes = self.selection.selectedIndexes()
        if not model_indexes:  # the list of accounts is empty
            return None

        model_index = model_indexes[0]
        acc = model_index.data(role=Qt.UserRole)

        msgBox = QMessageBox()
        msgBox.setText("Delete the {} account?".format(acc.name))
        msgBox.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel)
        msgBox.setDefaultButton(QMessageBox.Cancel)
        ret = msgBox.exec()

        if ret == QMessageBox.Ok:
            deletion = self.orm.delete_account(acc)
            if not deletion:
                show_warning("Can't delete account.")
            else:
                self.accounts.removeRow(model_index.row())
Beispiel #14
0
class QmyMainWindow(QMainWindow):
    cellIndexChange = pyqtSignal(int, int)

    def __init__(self, parent=None):
        super().__init__(parent)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        self.__dlgSetHeaders = None
        self.setCentralWidget(self.ui.qTableView)
        self.qLabel1 = QLabel("当前单元格:", self)
        self.qLabel1.setMinimumWidth(180)
        self.ui.qStatusBar.addWidget(self.qLabel1)

        self.qLabel2 = QLabel("单元格内容:", self)
        self.qLabel2.setMinimumWidth(200)
        self.ui.qStatusBar.addWidget(self.qLabel2)

        self.itemModel = QStandardItemModel(10, 5, self)
        self.selectionModel = QItemSelectionModel(self.itemModel)
        self.selectionModel.currentChanged.connect(
            self.do_currentChanged)  # 显示状态栏信息

        self.ui.qTableView.setModel(self.itemModel)
        self.ui.qTableView.setSelectionModel(self.selectionModel)

    @pyqtSlot()
    def on_qAction1_triggered(self):  # 设置行数列数
        dlgTableSize = QmyDialogSize(self.itemModel.rowCount(),
                                     self.itemModel.columnCount())
        ret = dlgTableSize.exec()
        if (ret == QDialog.Accepted):
            rows, cols = dlgTableSize.getTableSize()
            self.itemModel.setRowCount(rows)
            self.itemModel.setColumnCount(cols)

    @pyqtSlot()
    def on_qAction2_triggered(self):  # 设置表头标题
        if (self.__dlgSetHeaders == None):
            self.__dlgSetHeaders = QmyDialogHeaders(self)

        count = len(self.__dlgSetHeaders.headerList())
        if (count != self.itemModel.columnCount()
            ):  # 逻辑感人。首先表头标题不允许在表格内部直接改,因此如果发现标题与设置界面不一致,肯定是列数发生变化
            strList = []
            for i in range(self.itemModel.columnCount()):
                text = str(
                    self.itemModel.headerData(i, Qt.Horizontal,
                                              Qt.DisplayRole))
                strList.append(text)
            self.__dlgSetHeaders.setHeaderList(strList)
        ret = self.__dlgSetHeaders.exec()
        if (ret == QDialog.Accepted):
            strList2 = self.__dlgSetHeaders.headerList()
            self.itemModel.setHorizontalHeaderLabels(strList2)

    @pyqtSlot()
    def on_qAction3_triggered(self):  # 定位单元格
        dlgLocate = QmyDialogLocate(self)
        dlgLocate.setSpinRange(self.itemModel.rowCount(),
                               self.itemModel.columnCount())
        dlgLocate.changeActionEnable.connect(self.do_setActLocateEnable)
        dlgLocate.changeCellText.connect(self.do_setACellText)
        self.cellIndexChange.connect(dlgLocate.do_setSpinValue)
        dlgLocate.setAttribute(Qt.WA_DeleteOnClose)
        dlgLocate.show()

    def do_setActLocateEnable(self, enable):
        self.ui.qAction3.setEnabled(enable)

    def do_setACellText(self, row, column, text):
        index = self.itemModel.index(row, column)
        self.selectionModel.clearSelection()
        self.selectionModel.setCurrentIndex(index, QItemSelectionModel.Select)
        self.itemModel.setData(index, text, Qt.DisplayRole)

    def do_currentChanged(self, current, previous):
        if (current != None):
            self.qLabel1.setText("当前单元格:%d行,%d列" %
                                 (current.row(), current.column()))
            item = self.itemModel.itemFromIndex(current)
            self.qLabel2.setText("单元格内容:" + item.text())
            self.cellIndexChange.emit(current.row(), current.column())
Beispiel #15
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.splitter)
        self.__buildStatusBar()

        self.COL_COUNT = 6  #常数,列数=6
        self.itemModel = QStandardItemModel(5, self.COL_COUNT,
                                            self)  # 数据模型,10行6列

        ##      headerList=["测深(m)","垂深(m)","方位(°)","总位移(m)","固井质量","测井取样"]
        ##      self.itemModel.setHorizontalHeaderLabels(headerList) #设置表头文字

        self.selectionModel = QItemSelectionModel(self.itemModel)  #Item选择模型
        self.selectionModel.currentChanged.connect(self.do_currentChanged)
        self.__lastColumnFlags = (Qt.ItemIsSelectable | Qt.ItemIsUserCheckable
                                  | Qt.ItemIsEnabled)
        self.__lastColumnTitle = "测井取样"

        #为tableView设置数据模型
        self.ui.tableView.setModel(self.itemModel)  #设置数据模型
        self.ui.tableView.setSelectionModel(self.selectionModel)  #设置选择模型

        oneOrMore = QAbstractItemView.ExtendedSelection
        self.ui.tableView.setSelectionMode(oneOrMore)  #可多选

        itemOrRow = QAbstractItemView.SelectItems
        self.ui.tableView.setSelectionBehavior(itemOrRow)  #单元格选择

        self.ui.tableView.verticalHeader().setDefaultSectionSize(22)  #缺省行高
        self.ui.tableView.setEnabled(False)  #先禁用tableView
        ##      self.__resetTable(5)

        #创建自定义代理组件并设置
        self.spinCeShen = QmyFloatSpinDelegate(0, 10000, 0, self)  #用于 测深
        self.spinLength = QmyFloatSpinDelegate(0, 6000, 2, self)  #垂深,总位移
        self.spinDegree = QmyFloatSpinDelegate(0, 360, 1, self)  #用于 方位

        self.ui.tableView.setItemDelegateForColumn(0, self.spinCeShen)  #测深
        self.ui.tableView.setItemDelegateForColumn(1, self.spinLength)  #垂深
        self.ui.tableView.setItemDelegateForColumn(3, self.spinLength)  #总位移
        self.ui.tableView.setItemDelegateForColumn(2, self.spinDegree)  #方位角

        qualities = ["优", "良", "合格", "不合格"]
        self.comboDelegate = QmyComboBoxDelegate(self)
        self.comboDelegate.setItems(qualities, False)  #不可编辑
        self.ui.tableView.setItemDelegateForColumn(4,
                                                   self.comboDelegate)  #固井质量

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

    def __buildStatusBar(self):  ##构建状态栏
        self.LabCellPos = QLabel("当前单元格:", self)
        self.LabCellPos.setMinimumWidth(180)
        self.ui.statusBar.addWidget(self.LabCellPos)

        self.LabCellText = QLabel("单元格内容:", self)
        self.LabCellText.setMinimumWidth(150)
        self.ui.statusBar.addWidget(self.LabCellText)

        self.LabCurFile = QLabel("当前文件:", self)
        self.ui.statusBar.addPermanentWidget(self.LabCurFile)

##   def __resetTable(self,tableRowCount):  #复位数据表,必须为数值设置0,否则代理组件出错
##      self.itemModel.removeRows(0,self.itemModel.rowCount()) #删除所有行
##      self.itemModel.setRowCount(tableRowCount)     #设置新的行数
##
##      for i in range(tableRowCount):  #设置最后一列
##         for j in range(self.COL_COUNT-1):
##            index=self.itemModel.index(i,j) #获取模型索引
##            item=self.itemModel.itemFromIndex(index) #获取item
##            item.setData(0,Qt.DisplayRole) #数值必须初始化为0
##            item.setTextAlignment(Qt.AlignHCenter)
##
##         index=self.itemModel.index(i,self.COL_COUNT-1) #获取模型索引
##         item=self.itemModel.itemFromIndex(index) #获取item
##         item.setCheckable(True)
##         item.setData(self.__lastColumnTitle,Qt.DisplayRole)
##         item.setEditable(False) #不可编辑

    def __iniModelFromStringList(self, allLines):  ##从字符串列表构建模型
        rowCnt = len(allLines)  #文本行数,第1行是标题
        self.itemModel.setRowCount(rowCnt - 1)  #实际数据行数

        headerText = allLines[0].strip()  #第1行是表头,去掉末尾的换行符 "\n"
        headerList = headerText.split("\t")
        self.itemModel.setHorizontalHeaderLabels(headerList)

        self.__lastColumnTitle = headerList[len(headerList) -
                                            1]  # 最后一列表头的标题,即“测井取样”

        lastColNo = self.COL_COUNT - 1  #最后一列的列号
        for i in range(rowCnt - 1):
            lineText = allLines[i + 1].strip()  #一行的文字,\t分隔
            strList = lineText.split("\t")
            for j in range(self.COL_COUNT - 1):  #不含最后一列
                item = QStandardItem(strList[j])
                self.itemModel.setItem(i, j, item)

            item = QStandardItem(self.__lastColumnTitle)  #最后一列
            item.setFlags(self.__lastColumnFlags)
            item.setCheckable(True)
            if (strList[lastColNo] == "0"):
                item.setCheckState(Qt.Unchecked)
            else:
                item.setCheckState(Qt.Checked)

            self.itemModel.setItem(i, lastColNo, item)  #设置最后一列的item

    def __setCellAlignment(self, align=Qt.AlignHCenter):
        if (not self.selectionModel.hasSelection()):  #没有选择的项
            return
        selectedIndex = self.selectionModel.selectedIndexes()  #列表类型
        count = len(selectedIndex)
        for i in range(count):
            index = selectedIndex[i]  #获取其中的一个模型索引
            item = self.itemModel.itemFromIndex(index)  #获取一个单元格的项数据对象
            item.setTextAlignment(align)  #设置文字对齐方式

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

    @pyqtSlot()  ##“打开文件”
    def on_actOpen_triggered(self):
        curPath = os.getcwd()  #获取当前路径
        filename, flt = QFileDialog.getOpenFileName(
            self, "打开一个文件", curPath, "井斜数据文件(*.txt);;所有文件(*.*)")
        if (filename == ""):
            return

        self.LabCurFile.setText("当前文件:" + filename)
        self.ui.plainTextEdit.clear()

        aFile = open(filename, 'r')
        allLines = aFile.readlines()  #读取所有行,list类型,每行末尾带有 \n
        ##        for eachLine in aFile:  #每次读取一行
        ##            self.ui.plainTextEdit.appendPlainText(eachLine)
        aFile.close()

        for strLine in allLines:
            self.ui.plainTextEdit.appendPlainText(strLine.strip())

        self.__iniModelFromStringList(allLines)
        self.ui.actAppend.setEnabled(True)  #更新Actions的enable属性
        self.ui.actInsert.setEnabled(True)
        self.ui.actDelete.setEnabled(True)
        self.ui.actSave.setEnabled(True)
        self.ui.actModelData.setEnabled(True)

        self.ui.tableView.setEnabled(True)  #启用tableView

    @pyqtSlot()  ##保存文件
    def on_actSave_triggered(self):
        curPath = os.getcwd()  #获取当前路径
        filename, flt = QFileDialog.getSaveFileName(
            self, "保存文件", curPath, "井斜数据文件(*.txt);;所有文件(*.*)")
        if (filename == ""):
            return

        self.on_actModelData_triggered()  #更新数据到plainTextEdit

        aFile = open(filename, 'w')  #以写方式打开
        aFile.write(self.ui.plainTextEdit.toPlainText())
        aFile.close()

    @pyqtSlot()
    def on_actAppend_triggered(self):  #在最后添加一行
        itemlist = []  # 列表
        for i in range(self.COL_COUNT - 1):
            item = QStandardItem("0")
            itemlist.append(item)

        item = QStandardItem(self.__lastColumnTitle)  #最后一列
        item.setCheckable(True)
        item.setFlags(self.__lastColumnFlags)
        itemlist.append(item)

        self.itemModel.appendRow(itemlist)
        curIndex = self.itemModel.index(self.itemModel.rowCount() - 1, 0)
        self.selectionModel.clearSelection()
        self.selectionModel.setCurrentIndex(curIndex,
                                            QItemSelectionModel.Select)

    @pyqtSlot()  ##插入一行
    def on_actInsert_triggered(self):
        itemlist = []  # 列表
        for i in range(self.COL_COUNT - 1):
            item = QStandardItem("0")
            itemlist.append(item)

        item = QStandardItem(self.__lastColumnTitle)  #最后一列
        item.setFlags(self.__lastColumnFlags)
        item.setCheckable(True)
        item.setCheckState(Qt.Checked)
        itemlist.append(item)

        curIndex = self.selectionModel.currentIndex()
        #获取当前选中项的模型索引
        self.itemModel.insertRow(curIndex.row(), itemlist)
        #在当前行的前面插入一行
        self.selectionModel.clearSelection()
        self.selectionModel.setCurrentIndex(curIndex,
                                            QItemSelectionModel.Select)

    @pyqtSlot()  ##删除当前行
    def on_actDelete_triggered(self):
        curIndex = self.selectionModel.currentIndex()  #获取当前选择单元格的模型索引
        self.itemModel.removeRow(curIndex.row())  # //删除当前行

    @pyqtSlot()  ##左对齐
    def on_actAlignLeft_triggered(self):
        self.__setCellAlignment(Qt.AlignLeft | Qt.AlignVCenter)

    @pyqtSlot()  ##中间对齐
    def on_actAlignCenter_triggered(self):
        self.__setCellAlignment(Qt.AlignHCenter | Qt.AlignVCenter)

    @pyqtSlot()  ##右对齐
    def on_actAlignRight_triggered(self):
        self.__setCellAlignment(Qt.AlignRight | Qt.AlignVCenter)

    @pyqtSlot(bool)  ##字体Bold
    def on_actFontBold_triggered(self, checked):
        if (not self.selectionModel.hasSelection()):  #没有选择的项
            return

        selectedIndex = self.selectionModel.selectedIndexes()  #列表类型
        count = len(selectedIndex)
        for i in range(count):
            index = selectedIndex[i]  #获取其中的一个模型索引
            item = self.itemModel.itemFromIndex(index)  #获取一个单元格的项数据对象
            font = item.font()
            font.setBold(checked)
            item.setFont(font)

    @pyqtSlot()  ##模型数据显示到plainTextEdit里
    def on_actModelData_triggered(self):
        self.ui.plainTextEdit.clear()
        lineStr = ""
        for i in range(self.itemModel.columnCount() - 1):  #表头
            item = self.itemModel.horizontalHeaderItem(i)
            lineStr = lineStr + item.text() + "\t"
        item = self.itemModel.horizontalHeaderItem(self.COL_COUNT - 1)  #最后一列
        lineStr = lineStr + item.text()
        self.ui.plainTextEdit.appendPlainText(lineStr)

        for i in range(self.itemModel.rowCount()):
            lineStr = ""
            for j in range(self.itemModel.columnCount() - 1):  #不包括最后一列
                item = self.itemModel.item(i, j)
                lineStr = lineStr + item.text() + "\t"

            item = self.itemModel.item(i, self.COL_COUNT - 1)  #最后一列
            if (item.checkState() == Qt.Checked):
                lineStr = lineStr + "1"
            else:
                lineStr = lineStr + "0"
            self.ui.plainTextEdit.appendPlainText(lineStr)

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

    def do_currentChanged(self, current, previous):
        if (current != None):  #当前模型索引有效
            self.LabCellPos.setText(
                "当前单元格:%d行,%d列" %
                (current.row(), current.column()))  #显示模型索引的行和列号
            item = self.itemModel.itemFromIndex(current)  #从模型索引获得Item
            self.LabCellText.setText("单元格内容:" + item.text())  #显示item的文字内容

            font = item.font()  #获取item的字体
            self.ui.actFontBold.setChecked(font.bold())  #更新actFontBold的check状态
Beispiel #16
0
class LayerStackModel(QAbstractListModel):
    canMoveSelectedUp = pyqtSignal("bool")
    canMoveSelectedDown = pyqtSignal("bool")
    canDeleteSelected = pyqtSignal("bool")

    orderChanged = pyqtSignal()
    layerAdded = pyqtSignal(Layer, int)  # is now in row
    layerRemoved = pyqtSignal(Layer, int)  # was in row
    stackCleared = pyqtSignal()

    def __init__(self, parent=None):
        QAbstractListModel.__init__(self, parent)
        self._layerStack = []
        self.selectionModel = QItemSelectionModel(self)
        self.selectionModel.selectionChanged.connect(self.updateGUI)
        self.selectionModel.selectionChanged.connect(self._onSelectionChanged)
        self._movingRows = False
        QTimer.singleShot(0, self.updateGUI)

        def _handleRemovedLayer(layer):
            # Layerstacks *own* the layers they hold, and thus are
            #  responsible for cleaning them up when they are removed:
            layer.clean_up()

        self.layerRemoved.connect(_handleRemovedLayer)

    ####
    ## High level API to manipulate the layerstack
    ###

    def __len__(self):
        return self.rowCount()

    def __repr__(self):
        return "<LayerStackModel: layerStack='%r'>" % (self._layerStack, )

    def __getitem__(self, i):
        return self._layerStack[i]

    def __iter__(self):
        return self._layerStack.__iter__()

    def layerIndex(self, layer):
        #note that the 'index' function already has a different implementation
        #from Qt side
        return self._layerStack.index(layer)

    def findMatchingIndex(self, func):
        """Call the given function with each layer and return the index of the first layer for which f is True."""
        for index, layer in enumerate(self._layerStack):
            if func(layer):
                return index
        raise ValueError("No matching layer in stack.")

    def append(self, data):
        self.insert(0, data)

    def clear(self):
        if len(self) > 0:
            self.removeRows(0, len(self))
            self.stackCleared.emit()

    def insert(self, index, data):
        """
        Insert a layer into this layer stack, which *takes ownership* of the layer.
        """
        assert isinstance(
            data, Layer), "Only Layers can be added to a LayerStackModel"
        self.insertRow(index)
        self.setData(self.index(index), data)
        if self.selectedRow() >= 0:
            self.selectionModel.select(self.index(self.selectedRow()),
                                       QItemSelectionModel.Deselect)
        self.selectionModel.select(self.index(index),
                                   QItemSelectionModel.Select)

        data.changed.connect(
            functools.partial(self._onLayerChanged, self.index(index)))
        index = self._layerStack.index(data)
        self.layerAdded.emit(data, index)

        self.updateGUI()

    def selectRow(self, row):
        already_selected_rows = self.selectionModel.selectedRows()
        if len(already_selected_rows) == 1 and row == already_selected_rows[0]:
            # Nothing to do if this row is already selected
            return
        self.selectionModel.clear()
        self.selectionModel.setCurrentIndex(self.index(row),
                                            QItemSelectionModel.SelectCurrent)

    def deleteSelected(self):
        num_rows = len(self.selectionModel.selectedRows())
        assert num_rows == 1, "Can't delete selected row: {} layers are currently selected.".format(
            num_rows)
        row = self.selectionModel.selectedRows()[0]
        layer = self._layerStack[row.row()]
        assert not layer._cleaned_up, "This layer ({}) has already been cleaned up.  Shouldn't it already be removed from the layerstack?".format(
            layer.name)
        self.removeRow(row.row())
        if self.rowCount() > 0:
            self.selectionModel.select(self.index(0),
                                       QItemSelectionModel.Select)
        self.layerRemoved.emit(layer, row.row())
        self.updateGUI()

    def moveSelectedUp(self):
        assert len(self.selectionModel.selectedRows()) == 1
        row = self.selectionModel.selectedRows()[0]
        if row.row() != 0:
            oldRow = row.row()
            newRow = oldRow - 1
            self._moveToRow(oldRow, newRow)

    def moveSelectedDown(self):
        assert len(self.selectionModel.selectedRows()) == 1
        row = self.selectionModel.selectedRows()[0]
        if row.row() != self.rowCount() - 1:
            oldRow = row.row()
            newRow = oldRow + 1
            self._moveToRow(oldRow, newRow)

    def moveSelectedToTop(self):
        assert len(self.selectionModel.selectedRows()) == 1
        row = self.selectionModel.selectedRows()[0]
        if row.row() != 0:
            oldRow = row.row()
            newRow = 0
            self._moveToRow(oldRow, newRow)

    def moveSelectedToBottom(self):
        assert len(self.selectionModel.selectedRows()) == 1
        row = self.selectionModel.selectedRows()[0]
        if row.row() != self.rowCount() - 1:
            oldRow = row.row()
            newRow = self.rowCount() - 1
            self._moveToRow(oldRow, newRow)

    def moveSelectedToRow(self, newRow):
        assert len(self.selectionModel.selectedRows()) == 1
        row = self.selectionModel.selectedRows()[0]
        if row.row() != newRow:
            oldRow = row.row()
            self._moveToRow(oldRow, newRow)

    def _moveToRow(self, oldRow, newRow):
        d = self._layerStack[oldRow]
        self.removeRow(oldRow)
        self.insertRow(newRow)
        self.setData(self.index(newRow), d)
        self.selectionModel.select(self.index(newRow),
                                   QItemSelectionModel.Select)
        self.orderChanged.emit()
        self.updateGUI()

    ####
    ## Low level API. To add, remove etc. layers use the high level API from above.
    ####

    def updateGUI(self):
        self.canMoveSelectedUp.emit(self.selectedRow() > 0)
        self.canMoveSelectedDown.emit(self.selectedRow() < self.rowCount() - 1)
        self.canDeleteSelected.emit(self.rowCount() > 0)
        self.wantsUpdate()

    def selectedRow(self):
        selected = self.selectionModel.selectedRows()
        if len(selected) == 1:
            return selected[0].row()
        return -1

    def selectedIndex(self):
        row = self.selectedRow()
        if row >= 0:
            return self.index(self.selectedRow())
        else:
            return QModelIndex()

    def rowCount(self, parent=QModelIndex()):
        if not parent.isValid():
            return len(self._layerStack)
        return 0

    def insertRows(self, row, count, parent=QModelIndex()):
        '''Insert empty rows in the stack. 
        
        DO NOT USE THIS METHOD TO INSERT NEW LAYERS!
        Always use the insert() or append() method.
        
        '''
        if parent.isValid():
            return False
        oldRowCount = self.rowCount()
        #for some reason, row can be negative!
        beginRow = max(0, row)
        endRow = min(beginRow + count - 1, len(self._layerStack))
        self.beginInsertRows(parent, beginRow, endRow)
        while (beginRow <= endRow):
            self._layerStack.insert(row, Layer(datasources=[]))
            beginRow += 1
        self.endInsertRows()
        assert self.rowCount(
        ) == oldRowCount + 1, "oldRowCount = %d, self.rowCount() = %d" % (
            oldRowCount, self.rowCount())
        return True

    def removeRows(self, row, count, parent=QModelIndex()):
        '''Remove rows from the stack. 
        
        DO NOT USE THIS METHOD TO REMOVE LAYERS!
        Use the deleteSelected() method instead.
        
        '''

        if parent.isValid():
            return False
        if row + count <= 0 or row >= len(self._layerStack):
            return False
        oldRowCount = self.rowCount()
        beginRow = max(0, row)
        endRow = min(row + count - 1, len(self._layerStack) - 1)
        self.beginRemoveRows(parent, beginRow, endRow)
        while (beginRow <= endRow):
            del self._layerStack[row]
            beginRow += 1
        self.endRemoveRows()
        return True

    def flags(self, index):
        defaultFlags = Qt.ItemIsSelectable | Qt.ItemIsEditable | Qt.ItemIsEnabled
        if index.isValid():
            return Qt.ItemIsDragEnabled | defaultFlags
        else:
            return Qt.ItemIsDropEnabled | defaultFlags

    def supportedDropActions(self):
        return Qt.MoveAction

    def data(self, index, role=Qt.DisplayRole):
        if not index.isValid():
            return None
        if index.row() >= len(self._layerStack):
            return None

        if role == Qt.DisplayRole or role == Qt.EditRole:
            return self._layerStack[index.row()]
        elif role == Qt.ToolTipRole:
            return self._layerStack[index.row()].toolTip()
        else:
            return None

    def setData(self, index, value, role=Qt.EditRole):
        '''Replace one layer with another. 
        
        DO NOT USE THIS METHOD TO INSERT NEW LAYERS!
        Use deleteSelected() followed by insert() or append().
        
        '''
        if role == Qt.EditRole:
            layer = value
            if not isinstance(value, Layer):
                layer = value
            self._layerStack[index.row()] = layer
            self.dataChanged.emit(index, index)
            return True
        elif role == Qt.ToolTipRole:
            self._layerStack[index.row()].setToolTip()
            return True
        return False

    def headerData(self, section, orientation, role=Qt.DisplayRole):
        if role != Qt.DisplayRole:
            return None
        if orientation == Qt.Horizontal:
            return "Column %r" % section
        else:
            return "Row %r" % section

    def wantsUpdate(self):
        self.layoutChanged.emit()

    def _onLayerChanged(self, idx):
        self.dataChanged.emit(idx, idx)
        self.updateGUI()

    def _onSelectionChanged(self, selected, deselected):
        for idx in deselected.indexes():
            self[idx.row()].setActive(False)
        for idx in selected.indexes():
            self[idx.row()].setActive(True)
Beispiel #17
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.qSplitter)
        self.__ColCount = 6
        self.itemModel = QStandardItemModel(5, self.__ColCount, self)
        self.selectionModel = QItemSelectionModel(self.itemModel)
        self.selectionModel.currentChanged.connect(self.do_curChanged)

        self.__lastColumnTitle = "测井取样"
        self.__lastColumnFlags = (Qt.ItemIsSelectable | Qt.ItemIsUserCheckable
                                  | Qt.ItemIsEnabled)

        self.ui.qTableView.setModel(self.itemModel)
        self.ui.qTableView.setSelectionModel(self.selectionModel)

        oneOrMore = QAbstractItemView.ExtendedSelection
        self.ui.qTableView.setSelectionMode(oneOrMore)

        itemOrRow = QAbstractItemView.SelectItems
        self.ui.qTableView.setSelectionBehavior(itemOrRow)

        self.ui.qTableView.verticalHeader().setDefaultSectionSize(22)
        self.ui.qTableView.setAlternatingRowColors(True)

        self.ui.qTableView.setEnabled(False)

        self.qLabel1 = QLabel("当前单元格:", self)
        self.qLabel1.setMinimumWidth(180)
        self.qLabel2 = QLabel("单元格内容:", self)
        self.qLabel2.setMinimumWidth(150)
        self.qLabel3 = QLabel("当前文件:", self)
        self.ui.qStatusBar.addWidget(self.qLabel1)
        self.ui.qStatusBar.addWidget(self.qLabel2)
        self.ui.qStatusBar.addPermanentWidget(self.qLabel3)

    def __iniModelFromStringList(self, allLines):
        rowCnt = len(allLines)
        self.itemModel.setRowCount(rowCnt - 1)
        headerText = allLines[0].strip()
        headerList = headerText.split("\t")
        self.itemModel.setHorizontalHeaderLabels(headerList)
        self.__lastColumnTitle = headerList[len(headerList) - 1]
        lastColNo = self.__ColCount - 1
        for i in range(rowCnt - 1):
            lineText = allLines[i + 1].strip()
            strList = lineText.split("\t")
            for j in range(self.__ColCount - 1):
                item = QStandardItem(strList[j])
                self.itemModel.setItem(i, j, item)

            item = QStandardItem(self.__lastColumnTitle)
            item.setFlags(self.__lastColumnFlags)
            item.setCheckable(True)
            if (strList[lastColNo] == "0"):
                item.setCheckState(Qt.Unchecked)
            else:
                item.setCheckState(Qt.Checked)
            self.itemModel.setItem(i, lastColNo, item)

    def __setCellAlignment(self, align=Qt.AlignHCenter):
        if (not self.selectionModel.hasSelection()):
            return
        selectedIndex = self.selectionModel.selectedIndexes()
        count = len(selectedIndex)
        for i in range(count):
            index = selectedIndex[i]
            item = self.itemModel.itemFromIndex(index)
            item.setTextAlignment(align)

    @pyqtSlot()
    def on_qAction1_triggered(self):  # 打开文件
        curPath = os.getcwd()
        filename, flt = QFileDialog.getOpenFileName(
            self, "打开一个文件", curPath, "井斜数据文件(*.txt);;所有文件(*.*)")
        if (filename == ""):
            return
        self.qLabel3.setText("当前文件:" + filename)
        self.ui.qPlainTextEdit.clear()
        aFile = open(filename, 'r')
        allLines = aFile.readlines()
        aFile.close()

        for strLine in allLines:
            self.ui.qPlainTextEdit.appendPlainText(strLine.strip())

        self.__iniModelFromStringList(allLines)
        self.ui.qTableView.setEnabled(True)
        self.ui.qAction2.setEnabled(True)
        self.ui.qAction3.setEnabled(True)
        self.ui.qAction4.setEnabled(True)
        self.ui.qAction5.setEnabled(True)
        self.ui.qAction6.setEnabled(True)

    @pyqtSlot()
    def on_qAction2_triggered(self):  # 另存文件
        curPath = os.getcwd()
        filename, flt = QFileDialog.getSaveFileName(
            self, "保存文件", curPath, "井斜数据文件(*.txt);;所有文件(*.*)")
        if (filename == ""):
            return
        self.on_qAction3_triggered()
        aFile = open(filename, "w")
        aFile.write(self.ui.qPlainTextEdit.toPlainText())
        aFile.close()

    @pyqtSlot()
    def on_qAction4_triggered(self):  # 添加行
        itemList = []
        for i in range(self.__ColCount - 1):
            item = QStandardItem("0")
            itemList.append(item)

        item = QStandardItem(self.__lastColumnTitle)
        item.setCheckable(True)
        item.setFlags(self.__lastColumnFlags)
        itemList.append(item)

        self.itemModel.appendRow(itemList)
        curIndex = self.itemModel.index(self.itemModel.rowCount() - 1, 0)
        self.selectionModel.clearSelection()
        self.selectionModel.setCurrentIndex(curIndex,
                                            QItemSelectionModel.Select)

    @pyqtSlot()
    def on_qAction5_triggered(self):  # 插入行
        itemlist = []
        for i in range(self.__ColCount - 1):
            item = QStandardItem("0")
            itemlist.append(item)

        item = QStandardItem(self.__lastColumnTitle)
        item.setFlags(self.__lastColumnFlags)
        item.setCheckable(True)
        item.setCheckState(Qt.Checked)
        itemlist.append(item)

        curIndex = self.selectionModel.currentIndex()
        self.itemModel.insertRow(curIndex.row(), itemlist)
        self.selectionModel.clearSelection()
        self.selectionModel.setCurrentIndex(curIndex,
                                            QItemSelectionModel.Select)

    @pyqtSlot()
    def on_qAction6_triggered(self):  # 删除行
        curIndex = self.selectionModel.currentIndex()
        self.itemModel.removeRow(curIndex.row())

    @pyqtSlot()
    def on_qAction7_triggered(self):  # 居左
        self.__setCellAlignment(Qt.AlignLeft | Qt.AlignVCenter)

    @pyqtSlot()
    def on_qAction8_triggered(self):  # 居中
        self.__setCellAlignment(Qt.AlignHCenter | Qt.AlignVCenter)

    @pyqtSlot()
    def on_qAction9_triggered(self):  # 居右
        self.__setCellAlignment(Qt.AlignRight | Qt.AlignVCenter)

    @pyqtSlot(bool)
    def on_qAction10_triggered(self, checked):  # 粗体
        if (not self.selectionModel.hasSelection()):
            return
        selectedIndex = self.selectionModel.selectedIndexes()
        count = len(selectedIndex)
        for i in range(count):
            index = selectedIndex[i]
            item = self.itemModel.itemFromIndex(index)
            font = item.font()
            font.setBold(checked)
            item.setFont(font)

    @pyqtSlot()
    def on_qAction3_triggered(self):  # 模型数据
        self.ui.qPlainTextEdit.clear()
        lineStr = ""
        for i in range(self.itemModel.columnCount() - 1):
            item = self.itemModel.horizontalHeaderItem(i)
            lineStr = lineStr + item.text() + "\t"
        item = self.itemModel.horizontalHeaderItem(self.__ColCount - 1)
        lineStr = lineStr + item.text()
        self.ui.qPlainTextEdit.appendPlainText(lineStr)

        for i in range(self.itemModel.rowCount()):
            lineStr = ""
            for j in range(self.itemModel.columnCount() - 1):
                item = self.itemModel.item(i, j)
                lineStr = lineStr + item.text() + "\t"
            item = self.itemModel.item(i, self.__ColCount - 1)
            if (item.checkState() == Qt.Checked):
                lineStr = lineStr + "1"
            else:
                lineStr = lineStr + "0"
            self.ui.qPlainTextEdit.appendPlainText(lineStr)

    def do_curChanged(self, current, previous):
        if (current != None):
            text = "当前单元格:%d行,%d列" % (current.row(), current.column())
            self.qLabel1.setText(text)
            item = self.itemModel.itemFromIndex(current)
            self.qLabel2.setText("单元格内容:" + item.text())
            font = item.font()
            self.ui.qAction10.setChecked(font.bold())
Beispiel #18
0
class LayerStackModel(QAbstractListModel):
    canMoveSelectedUp = pyqtSignal("bool")
    canMoveSelectedDown = pyqtSignal("bool")
    canDeleteSelected = pyqtSignal("bool")

    orderChanged = pyqtSignal()
    layerAdded = pyqtSignal(Layer, int)  # is now in row
    layerRemoved = pyqtSignal(Layer, int)  # was in row
    stackCleared = pyqtSignal()

    def __init__(self, parent=None):
        QAbstractListModel.__init__(self, parent)
        self._layerStack = []
        self.selectionModel = QItemSelectionModel(self)
        self.selectionModel.selectionChanged.connect(self.updateGUI)
        self.selectionModel.selectionChanged.connect(self._onSelectionChanged)
        self._movingRows = False
        QTimer.singleShot(0, self.updateGUI)

        def _handleRemovedLayer(layer):
            # Layerstacks *own* the layers they hold, and thus are
            #  responsible for cleaning them up when they are removed:
            layer.clean_up()

        self.layerRemoved.connect(_handleRemovedLayer)

    ####
    ## High level API to manipulate the layerstack
    ###

    def __len__(self):
        return self.rowCount()

    def __repr__(self):
        return "<LayerStackModel: layerStack='%r'>" % (self._layerStack,)

    def __getitem__(self, i):
        return self._layerStack[i]

    def __iter__(self):
        return self._layerStack.__iter__()

    def layerIndex(self, layer):
        # note that the 'index' function already has a different implementation
        # from Qt side
        return self._layerStack.index(layer)

    def findMatchingIndex(self, func):
        """Call the given function with each layer and return the index of the first layer for which f is True."""
        for index, layer in enumerate(self._layerStack):
            if func(layer):
                return index
        raise ValueError("No matching layer in stack.")

    def append(self, data):
        self.insert(0, data)

    def clear(self):
        if len(self) > 0:
            self.removeRows(0, len(self))
            self.stackCleared.emit()

    def insert(self, index, data):
        """
        Insert a layer into this layer stack, which *takes ownership* of the layer.
        """
        assert isinstance(data, Layer), "Only Layers can be added to a LayerStackModel"
        self.insertRow(index)
        self.setData(self.index(index), data)
        if self.selectedRow() >= 0:
            self.selectionModel.select(self.index(self.selectedRow()), QItemSelectionModel.Deselect)
        self.selectionModel.select(self.index(index), QItemSelectionModel.Select)

        data.changed.connect(functools.partial(self._onLayerChanged, self.index(index)))
        index = self._layerStack.index(data)
        self.layerAdded.emit(data, index)

        self.updateGUI()

    def selectRow(self, row):
        already_selected_rows = self.selectionModel.selectedRows()
        if len(already_selected_rows) == 1 and row == already_selected_rows[0]:
            # Nothing to do if this row is already selected
            return
        self.selectionModel.clear()
        self.selectionModel.setCurrentIndex(self.index(row), QItemSelectionModel.SelectCurrent)

    def deleteSelected(self):
        num_rows = len(self.selectionModel.selectedRows())
        assert num_rows == 1, "Can't delete selected row: {} layers are currently selected.".format(num_rows)
        row = self.selectionModel.selectedRows()[0]
        layer = self._layerStack[row.row()]
        assert (
            not layer._cleaned_up
        ), "This layer ({}) has already been cleaned up.  Shouldn't it already be removed from the layerstack?".format(
            layer.name
        )
        self.removeRow(row.row())
        if self.rowCount() > 0:
            self.selectionModel.select(self.index(0), QItemSelectionModel.Select)
        self.layerRemoved.emit(layer, row.row())
        self.updateGUI()

    def moveSelectedUp(self):
        assert len(self.selectionModel.selectedRows()) == 1
        row = self.selectionModel.selectedRows()[0]
        if row.row() != 0:
            oldRow = row.row()
            newRow = oldRow - 1
            self._moveToRow(oldRow, newRow)

    def moveSelectedDown(self):
        assert len(self.selectionModel.selectedRows()) == 1
        row = self.selectionModel.selectedRows()[0]
        if row.row() != self.rowCount() - 1:
            oldRow = row.row()
            newRow = oldRow + 1
            self._moveToRow(oldRow, newRow)

    def moveSelectedToTop(self):
        assert len(self.selectionModel.selectedRows()) == 1
        row = self.selectionModel.selectedRows()[0]
        if row.row() != 0:
            oldRow = row.row()
            newRow = 0
            self._moveToRow(oldRow, newRow)

    def moveSelectedToBottom(self):
        assert len(self.selectionModel.selectedRows()) == 1
        row = self.selectionModel.selectedRows()[0]
        if row.row() != self.rowCount() - 1:
            oldRow = row.row()
            newRow = self.rowCount() - 1
            self._moveToRow(oldRow, newRow)

    def moveSelectedToRow(self, newRow):
        assert len(self.selectionModel.selectedRows()) == 1
        row = self.selectionModel.selectedRows()[0]
        if row.row() != newRow:
            oldRow = row.row()
            self._moveToRow(oldRow, newRow)

    def _moveToRow(self, oldRow, newRow):
        d = self._layerStack[oldRow]
        self.removeRow(oldRow)
        self.insertRow(newRow)
        self.setData(self.index(newRow), d)
        self.selectionModel.select(self.index(newRow), QItemSelectionModel.Select)
        self.orderChanged.emit()
        self.updateGUI()

    ####
    ## Low level API. To add, remove etc. layers use the high level API from above.
    ####

    def updateGUI(self):
        self.canMoveSelectedUp.emit(self.selectedRow() > 0)
        self.canMoveSelectedDown.emit(self.selectedRow() < self.rowCount() - 1)
        self.canDeleteSelected.emit(self.rowCount() > 0)
        self.wantsUpdate()

    def selectedRow(self):
        selected = self.selectionModel.selectedRows()
        if len(selected) == 1:
            return selected[0].row()
        return -1

    def selectedIndex(self):
        row = self.selectedRow()
        if row >= 0:
            return self.index(self.selectedRow())
        else:
            return QModelIndex()

    def rowCount(self, parent=QModelIndex()):
        if not parent.isValid():
            return len(self._layerStack)
        return 0

    def insertRows(self, row, count, parent=QModelIndex()):
        """Insert empty rows in the stack.

        DO NOT USE THIS METHOD TO INSERT NEW LAYERS!
        Always use the insert() or append() method.

        """
        if parent.isValid():
            return False
        oldRowCount = self.rowCount()
        # for some reason, row can be negative!
        beginRow = max(0, row)
        endRow = min(beginRow + count - 1, len(self._layerStack))
        self.beginInsertRows(parent, beginRow, endRow)
        while beginRow <= endRow:
            self._layerStack.insert(row, Layer(datasources=[]))
            beginRow += 1
        self.endInsertRows()
        assert self.rowCount() == oldRowCount + 1, "oldRowCount = %d, self.rowCount() = %d" % (
            oldRowCount,
            self.rowCount(),
        )
        return True

    def removeRows(self, row, count, parent=QModelIndex()):
        """Remove rows from the stack.

        DO NOT USE THIS METHOD TO REMOVE LAYERS!
        Use the deleteSelected() method instead.

        """

        if parent.isValid():
            return False
        if row + count <= 0 or row >= len(self._layerStack):
            return False
        oldRowCount = self.rowCount()
        beginRow = max(0, row)
        endRow = min(row + count - 1, len(self._layerStack) - 1)
        self.beginRemoveRows(parent, beginRow, endRow)
        while beginRow <= endRow:
            del self._layerStack[row]
            beginRow += 1
        self.endRemoveRows()
        return True

    def flags(self, index):
        defaultFlags = Qt.ItemIsSelectable | Qt.ItemIsEditable | Qt.ItemIsEnabled
        if index.isValid():
            return Qt.ItemIsDragEnabled | defaultFlags
        else:
            return Qt.ItemIsDropEnabled | defaultFlags

    def supportedDropActions(self):
        return Qt.MoveAction

    def data(self, index, role=Qt.DisplayRole):
        if not index.isValid():
            return None
        if index.row() >= len(self._layerStack):
            return None

        if role == Qt.DisplayRole or role == Qt.EditRole:
            return self._layerStack[index.row()]
        elif role == Qt.ToolTipRole:
            return self._layerStack[index.row()].toolTip()
        else:
            return None

    def setData(self, index, value, role=Qt.EditRole):
        """Replace one layer with another.

        DO NOT USE THIS METHOD TO INSERT NEW LAYERS!
        Use deleteSelected() followed by insert() or append().

        """
        if role == Qt.EditRole:
            layer = value
            if not isinstance(value, Layer):
                layer = value
            self._layerStack[index.row()] = layer
            self.dataChanged.emit(index, index)
            return True
        elif role == Qt.ToolTipRole:
            self._layerStack[index.row()].setToolTip()
            return True
        return False

    def headerData(self, section, orientation, role=Qt.DisplayRole):
        if role != Qt.DisplayRole:
            return None
        if orientation == Qt.Horizontal:
            return "Column %r" % section
        else:
            return "Row %r" % section

    def wantsUpdate(self):
        self.layoutChanged.emit()

    def _onLayerChanged(self, idx):
        self.dataChanged.emit(idx, idx)
        self.updateGUI()

    def _onSelectionChanged(self, selected, deselected):
        for idx in deselected.indexes():
            self[idx.row()].setActive(False)
        for idx in selected.indexes():
            self[idx.row()].setActive(True)