コード例 #1
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())
コード例 #2
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状态
コード例 #3
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
コード例 #4
0
ファイル: myMainWindow.py プロジェクト: likeke201/qt_code
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状态
コード例 #5
0
class MainWindow(QMainWindow, Ui_MainWindow):
    def __init__(self, ):
        super(MainWindow, self).__init__()
        self.setupUi(self)
        self.fig_dict = {}

        self.tabWidget.setCurrentIndex(0)

        self.plotAreaVerticalLayout = QtWidgets.QVBoxLayout()
        self.plotsFrame.setLayout(self.plotAreaVerticalLayout)

        #initialize Table
        self.headerV = self.tableWidget.verticalHeader()
        self.headerV.show()

        # add a widget for previewing plots, they can then be added to the actual plot
        self.plotPreview = PlotWidget()
        self.plotAreaVerticalLayout.addWidget(self.plotPreview)

        # Create tree model to store sim data items and connect it to views
        self.simDataItemTreeModel = SimDataItemTreeModel()
        self.bdTableModel = BdTableModel()
        self.bdUserGeneratedTableModel = BdUserGeneratedCurvesTableModel()
        self.simDataItemTreeView.setModel(self.simDataItemTreeModel)
        self.plotPreview.tableView.setModel(self.bdTableModel)

        # connect a double clicked section of the bd table to a change of the anchor
        self.plotPreview.tableView.horizontalHeader(
        ).sectionDoubleClicked.connect(self.update_bd_table)
        self.plotPreview.tableView.verticalHeader(
        ).sectionDoubleClicked.connect(
            self.update_bd_user_generated_curves_table)

        # Set custom selection model, so that sub items are automatically
        # selected if parent is selected
        self._selection_model = QRecursiveSelectionModel(
            self.simDataItemTreeView.model())
        self.simDataItemTreeView.setSelectionModel(self._selection_model)

        # Connect list view with model for the selected values of tree view
        self.selectedSimulationDataItemListModel = OrderedDictModel()
        self.simDataItemListView.setModel(
            self.selectedSimulationDataItemListModel)
        self._selection_model.selectionChanged.connect(self.change_list)

        # set up signals and slots
        self.selectedSimulationDataItemListModel.items_changed.connect(
            self.update_variable_tree)

        # Connect signals of menus
        self.actionOpen_File.triggered.connect(
            self.simDataItemTreeView.add_file)
        self.actionOpen_Directory.triggered.connect(
            self.simDataItemTreeView.add_folder)
        self.actionOpen_Directory_List.triggered.connect(
            self.simDataItemTreeView.add_folder_list)
        self.actionHide_PlotSettings.triggered.connect(
            self.set_plot_settings_visibility)
        self.actionHide_Sequence.triggered.connect(
            self.set_sequence_widget_visibility)
        self.actionHide_Status.triggered.connect(
            self.set_status_widget_visibility)

        self.actionSave_Table.triggered.connect(self.save_bd_table)

        self.actionExport_Figure_as_Tikzpicture.triggered.connect(
            self.plotPreview.export_plot_tikz)

        self.actionExport_TableWidget.triggered.connect(
            self.export_table_to_csv)

        self.actionSave_Data.triggered.connect(self.save_current_selection)

        self.action_About.triggered.connect(self.open_about_page)

        self.variableTreeModel = VariableTreeModel()
        self.variableTreeView.setModel(self.variableTreeModel)
        self.plotsettings.visibilityChanged.connect(
            self.plot_settings_visibility_changed)
        self.sequenceWidget.visibilityChanged.connect(
            self.sequence_widget_visibility_changed)
        self.statusWidget.visibilityChanged.connect(
            self.status_widget_visibility_changed)

        # Set recursive selection model for variable view
        self._variable_tree_selection_model = QRecursiveSelectionModel(
            self.variableTreeView.model())
        self.variableTreeView.setSelectionModel(
            self._variable_tree_selection_model)

        # set up combo boxes for rate/psnr and interpolation options
        self.combo_interp.addItems(["pchip", "pol"])
        self.combo_rate_psnr.addItems(["drate", "dsnr"])
        self.combo_interp.currentIndexChanged.connect(self.on_combo_box)
        self.combo_rate_psnr.currentIndexChanged.connect(self.on_combo_box)

        # set up bd plot checkbox
        self.checkBox_bdplot.stateChanged.connect(self.update_bd_plot)

        self.curveWidget.hide()
        self.curveListModel = OrderedDictModel()
        self.curveListView.setModel(self.curveListModel)
        self.curveListSelectionModel = QItemSelectionModel(self.curveListModel)
        self.curveListView.setSelectionModel(self.curveListSelectionModel)
        self.curveListView.setSelectionMode(
            QtWidgets.QAbstractItemView.ExtendedSelection)
        self.curveWidget.visibilityChanged.connect(
            self.curve_widget_visibility_changed)

        self.actionGenerate_curve.triggered.connect(self.generate_new_curve)
        self.actionRemove_items.triggered.connect(self.remove)
        self.actionReload_files.triggered.connect(self.reload_files)

        self.settings = QSettings()
        self.get_recent_files()
        self.simDataItemTreeView.itemsOpened.connect(self.add_recent_files)

        self.watcher = QFileSystemWatcher(self)
        self.watcher.fileChanged.connect(self.warning_file_change)
        self.watcher.directoryChanged.connect(self.warning_file_change)
        self.simDataItemTreeView.parserThread.newParsedData.connect(
            self.add_files_to_watcher)
        self.show_file_changed_message = True
        self.reset_timer = QTimer(self)
        self.reset_timer.setSingleShot(True)
        self.reset_timer.setInterval(15000)
        self.reset_timer.timeout.connect(self._reset_file_changed_message)

        self.simDataItemTreeView.customContextMenuRequested.connect(
            self.show_sequences_context_menu)
        # self.curveListView.actionCalculateBD.triggered.connect(self.bd_user_generated_curves)

    # sets Visibility for the Plotsettings Widget
    def set_plot_settings_visibility(self):
        self.plotsettings.visibilityChanged.disconnect(
            self.plot_settings_visibility_changed)
        if self.plotsettings.isHidden():
            self.plotsettings.setVisible(True)
        else:
            self.plotsettings.setHidden(True)
        self.plotsettings.visibilityChanged.connect(
            self.plot_settings_visibility_changed)

    # updates the QAction if Visibility is changed
    def plot_settings_visibility_changed(self):
        if self.plotsettings.isHidden():
            self.actionHide_PlotSettings.setChecked(True)
        else:
            self.actionHide_PlotSettings.setChecked(False)
        self._variable_tree_selection_model.selectionChanged.connect(
            self.update_plot)
        self.curveListSelectionModel.selectionChanged.connect(self.update_plot)
        self.simDataItemTreeView.deleteKey.connect(self.remove)

    # sets Visibility for the Sequence Widget
    def set_sequence_widget_visibility(self):
        self.sequenceWidget.visibilityChanged.disconnect(
            self.sequence_widget_visibility_changed)
        if self.sequenceWidget.isHidden():
            self.sequenceWidget.setVisible(True)
        else:
            self.sequenceWidget.setHidden(True)
        self.sequenceWidget.visibilityChanged.connect(
            self.sequence_widget_visibility_changed)

    def sequence_widget_visibility_changed(self):
        if self.sequenceWidget.isHidden():
            self.actionHide_Sequence.setChecked(True)
        else:
            self.actionHide_Sequence.setChecked(False)

    # Sets Visibility for the Status Widget
    def set_status_widget_visibility(self):
        self.statusWidget.visibilityChanged.disconnect(
            self.status_widget_visibility_changed)
        if self.statusWidget.isHidden():
            self.statusWidget.setVisible(True)
        else:
            self.statusWidget.setHidden(True)
        self.statusWidget.visibilityChanged.connect(
            self.status_widget_visibility_changed)

    def status_widget_visibility_changed(self):
        if self.statusWidget.isHidden():
            self.actionHide_Status.setChecked(True)
        else:
            self.actionHide_Status.setChecked(False)

    def curve_widget_visibility_changed(self):
        if self.curveWidget.isHidden():
            self.curveListView.delete_key.disconnect()
        else:
            self.curveListView.delete_key.connect(self.remove_curves)

    def remove(self):
        values = self.selectedSimulationDataItemListModel.values()

        for value in values:
            self.watcher.removePath(value.path)
        # List call necessary to avoid runtime error because of elements changing
        # during iteration
        self._variable_tree_selection_model.selectionChanged.disconnect()
        # disconnect slot to avoid multiple function triggers by selectionChanged signal
        # not disconnecting slows program down significantly
        self._selection_model.selectionChanged.disconnect(self.change_list)
        self.simDataItemTreeModel.remove(list(values))
        self.change_list(QItemSelection(), QItemSelection())
        self._selection_model.selectionChanged.connect(self.change_list)
        self._variable_tree_selection_model.selectionChanged.connect(
            self.update_plot)
        if len(self.selectedSimulationDataItemListModel.values()) == 0:
            self.update_plot()

    def change_list(self, q_selected, q_deselected):
        """Extend superclass behavior by automatically adding the values of
           all selected items in :param: `q_selected` to value list model. """

        selected_q_indexes = q_deselected.indexes()

        q_reselect_indexes = []
        for q_index in self.simDataItemTreeView.selectedIndexes():
            if q_index not in selected_q_indexes:
                q_reselect_indexes.append(q_index)

        # Find all all values that are contained by selected tree items
        tuples = []
        for q_index in q_selected.indexes() + q_reselect_indexes:
            # Add values, ie. sim data items stored at the item, to the list
            # model.
            sim_data_items = q_index.internalPointer().values
            tuples.extend((e.path, e) for e in sim_data_items)

        # Overwrite all elements in dictionary by selected values
        # Note, that overwriting only issues one `updated` signal, and thus,
        # only rerenders the plots one time. Therefore, simply overwriting
        # is much more efficient, despite it would seem, that selectively
        # overwriting keys is.
        self.selectedSimulationDataItemListModel.clear_and_update_from_tuples(
            tuples)

    def get_selected_simulation_data_items(self):
        return [
            self.selectedSimulationDataItemListModel[key]
            for key in self.selectedSimulationDataItemListModel
        ]

    def get_plot_data_collection_from_selected_variables(self):
        """Get a :class: `dict` with y-variable as key and values as items
        from the current selection of the variable tree.

        :rtype: :class: `dict` of :class: `string` and :class: `list`
        """

        plot_data_collection = []
        for q_index in self.variableTreeView.selectedIndexes():
            item = q_index.internalPointer()
            if len(item.values) > 0:
                plot_data_collection.extend(item.values)

        return plot_data_collection

    def update_variable_tree(self):
        """Collect all SimDataItems currently selected, and create variable
        tree and corresponding data from it. Additionaly reselect all previously
        selected variables.
        """

        # Create a list of all currently selected paths
        # Note, that *q_index* can not be used directly, because it might
        # change if the variable tree is recreated
        selected_path_collection = []
        for q_index in self.variableTreeView.selectedIndexes():
            selected_path_collection.append(
                # Create list of identifiers from path
                # Note, that the root node is excluded from the path
                [
                    item.identifier
                    for item in q_index.internalPointer().path[1:]
                ])

        # Join the data of all currently selected items to a dictionary
        # tree
        sim_data_items = self.get_selected_simulation_data_items()
        dict_tree = dict_tree_from_sim_data_items(sim_data_items)
        # check if qp values are the same
        # self.check_qp(sim_data_items)

        # Reset variable tree and update it with *dict_tree*
        self.variableTreeModel.clear_and_update_from_dict_tree(dict_tree)

        # Auto expand variable tree
        self.variableTreeView.expandToDepth(1)

        # Reselect all variables, which also exist on the new tree
        for path in selected_path_collection:
            # Try to reselect, and do nothing, if path does not exist anymore
            try:
                # Reselect new item corresponding to the previously selected
                # path
                item = self.variableTreeModel.get_item_from_path(*path)
                self.variableTreeView.selectionModel().select(
                    self.variableTreeModel._get_index_from_item(item),
                    QItemSelectionModel.Select,
                )
            except KeyError:
                pass

    # TODO: it might be that some log files do not have a QP value, therefore the check_qp method must be
    #       implemented in a way that these files are not affected
    # def check_qp(self, sim_data_items): # check if qp values are the same for each sequence
    #     if len(sim_data_items) < 2: return
    #     sim_data_items.sort(key=lambda item: (item.sequence))
    #
    #     qp_list,list = [],[]
    #     seq = sim_data_items[0].sequence
    #     config = sim_data_items[0].config
    #
    #     for item in sim_data_items:
    #         if ((seq == item.sequence) & (config == item.config)):
    #             list.append(item.qp)
    #         elif (seq == item.sequence): #same sequence different config
    #             config = item.config
    #             qp_list.append(list)
    #             list = []
    #             list.append(item.qp)
    #         else:  # different sequence
    #             seq = item.sequence
    #             config = item.config
    #             qp_list.append(list)
    #             if not(all(list == qp_list[0] for list in qp_list)):
    #                 QtWidgets.QMessageBox.warning(self, "Warning",
    #                                               "Be careful! You chose a sequence with different QP.")
    #                 return
    #             list, qp_list = [], []
    #             list.append(item.qp)
    #     qp_list.append(list)
    #
    #     if not(all(list == qp_list[0] for list in qp_list )):
    #         QtWidgets.QMessageBox.warning(self, "Warning",
    #                                         "Be careful! You chose a sequence with different QP.")

    def check_labels(self):
        selectionmodel = self.variableTreeView.selectionModel()
        selected = self.variableTreeView.selectedIndexes()
        # return if no comparison needed
        if len(selected) < 2:
            return
        labelx = []
        labely = []
        for index in selected:
            x = index.internalPointer()
            if len(x.values) > 0:
                labelx.append(x.values[0].label[0])
                labely.append(x.values[0].label[1])

        if all(x == labelx[0] for x in labelx) and all(x == labely[0]
                                                       for x in labely):
            return

        else:
            QtWidgets.QMessageBox.information(
                self, "Error!",
                "You should not choose curves with different units.")
            selectionmodel.clearSelection()

    # updates the plot if the plot variable is changed
    def update_plot(self):
        # user-generated curves and curves loaded from files are not supposed to be mixed
        user_generated_curves = False
        if self.sender() == self._variable_tree_selection_model or self.sender(
        ) == self.curveListSelectionModel:
            self.check_labels()
            data_collection = self.get_plot_data_collection_from_selected_variables(
            )
            data_collection_user_generated = []
            for index in self.curveListView.selectedIndexes():
                data_collection_user_generated.append(
                    self.curveListModel[index.data()])
        else:
            return

        plot_data_collection = data_collection + data_collection_user_generated
        if len(data_collection_user_generated):
            self.plotPreview.tableView.setModel(self.bdUserGeneratedTableModel)
            self.plotPreview.change_plot(plot_data_collection, True)
        else:
            self.plotPreview.tableView.setModel(self.bdTableModel)
            self.update_table(data_collection)
            self.plotPreview.change_plot(plot_data_collection, False)
        if len(data_collection) and len(data_collection_user_generated):
            # don't mix user-generated and normal curves
            self.plotPreview.tableView.hide()
            self.plotPreview.label_warning.show()
            return

        self.plotPreview.tableView.show()
        self.plotPreview.label_warning.hide()
        self.plotPreview.tableView.model().update(
            plot_data_collection, self.combo_rate_psnr.currentText(),
            self.combo_interp.currentText(),
            not (self.checkBox_bdplot.isChecked()))

    def get_table_header(self, plot_data_collection):
        tmp_legend = []
        tmp_config = []

        # make legend
        for plot_data in plot_data_collection:
            tmp = []
            for identifiers in plot_data.identifiers[1:]:
                tmp += identifiers.split(sep)
            tmp2 = tmp + plot_data.path
            tmp_legend.append(tmp2)
            tmp_config.append(tmp)

        legend = []
        config = []
        for c in tmp_legend:
            result = list(
                filter(lambda x: all(x in l for l in tmp_legend) == False, c))
            if result == []: result = [plot_data.path[-1]]
            legend.append(" ".join(result))
        if len(tmp_legend) == 1:
            legend = [plot_data.path[-1]]

        #make config
        for c in tmp_config:
            result = list(
                filter(lambda x: all(x in l for l in tmp_config) == False, c))
            if ((set([" ".join(result)]) - set(config) != set()) &
                (result != [])):
                config.append(" ".join(result))

        result = (legend, config)
        return result

    #updates the table
    def update_table(self, plot_data_collection):

        self.tableWidget.clear()
        self.tableWidget.setColumnCount(0)
        self.tableWidget.setRowCount(0)

        if plot_data_collection != []:
            if 'Temporal' in plot_data_collection[0].path:
                self.change_table_temporal(plot_data_collection)
            else:
                self.change_table_summary(plot_data_collection)

        self.tableWidget.resizeColumnsToContents()

    def change_table_temporal(self, plot_data_collect):

        plot_data_collection = plot_data_collect
        self.tableWidget.setRowCount(len(plot_data_collection))
        plot_count = data_count = 0
        data_names = []
        plot_data_collection.sort(
            key=lambda plot_data: (plot_data.identifiers))
        legend = self.get_table_header(plot_data_collection)
        header = legend[0]

        for plot_data in plot_data_collection:
            values = ((float(x), float(y)) for (x, y) in plot_data.values)

            sorted_value_pairs = sorted(values, key=lambda pair: pair[0])
            [xs, ys] = list(zip(*sorted_value_pairs))

            # make header
            if plot_data.identifiers[0] not in data_names:
                self.tableWidget.insertRow(plot_count)
                v_item = QtWidgets.QTableWidgetItem(
                    str(plot_data.identifiers[0]))
                font = self.tableWidget.font()
                v_item.setData(
                    6, QtGui.QFont(self.tableWidget.font().setBold(True)))
                v_item.setData(6, QtGui.QFont("Ubuntu", 11, QtGui.QFont.Bold))
                self.tableWidget.setVerticalHeaderItem(plot_count, v_item)
                header_count = plot_count
                data_names.append(plot_data.identifiers[0])
                plot_count += 1

            # round data
            if plot_data.label[1] == 'dB':
                ys = tuple(map(lambda i: round(i, 1), ys))

            self.tableWidget.horizontalHeader().setVisible(False)
            # fill up column per column
            for column_count in range(0, len(xs)):

                self.tableWidget.setCurrentCell(plot_count, column_count)
                if column_count > self.tableWidget.currentColumn():
                    self.tableWidget.insertColumn(column_count)
                self.tableWidget.setItem(
                    plot_count, column_count,
                    QtWidgets.QTableWidgetItem(str(ys[column_count])))
                self.tableWidget.setVerticalHeaderItem(
                    plot_count,
                    QtWidgets.QTableWidgetItem(
                        str(header[data_count]) + " [" +
                        str(plot_data.label[1]) + "] "))
                new_item = QtWidgets.QTableWidgetItem(str(xs[column_count]))
                new_item.setData(6, QtGui.QFont("Ubuntu", 11,
                                                QtGui.QFont.Bold))
                self.tableWidget.setItem(header_count, column_count, new_item)

                column_count += 1

            plot_count += 1
            data_count += 1

    def change_table_summary(self, plot_data_collect):

        plot_data_collection = plot_data_collect
        header_count = plot_count = data_count = config_count = column_saver = 0
        data_names = []
        plot_data_collection.sort(key=lambda plot_data: plot_data.path[-1])
        plot_data_collection.sort(
            key=lambda plot_data: plot_data.identifiers[0])
        legend = self.get_table_header(plot_data_collection)
        header = legend[0]
        config = legend[1]

        if ((config == []) | (len(config) == 1)):
            self.change_table_temporal(plot_data_collection)
            return

        self.tableWidget.setRowCount(len(plot_data_collection) / len(config))

        for plot_data in plot_data_collection:

            values = ((float(x), float(y)) for (x, y) in plot_data.values)

            sorted_value_pairs = sorted(values, key=lambda pair: pair[0])
            [xs, ys] = list(zip(*sorted_value_pairs))

            # make header, important if more than one plot
            if plot_data.identifiers[0] not in data_names:
                self.tableWidget.insertRow(plot_count)
                v_item = QtWidgets.QTableWidgetItem(
                    str(plot_data.identifiers[0]))
                v_item.setData(6, QtGui.QFont("Ubuntu", 11, QtGui.QFont.Bold))
                self.tableWidget.setVerticalHeaderItem(plot_count, v_item)
                header_count = plot_count
                data_names.append(plot_data.identifiers[0])
                plot_count += 1

            # round data
            if plot_data.label[1] == 'dB':
                ys = tuple(map(lambda i: round(i, 1), ys))

            #horizontal header if more than one config
            if len(config) > 1:
                self.tableWidget.horizontalHeader().setVisible(True)
            else:
                self.tableWidget.horizontalHeader().setVisible(False)

            for column_count in range(0, len(xs)):

                columns = column_saver + column_count
                if (((column_saver + column_count) >=
                     self.tableWidget.columnCount()) |
                    (self.tableWidget.columnCount() == 0)):
                    self.tableWidget.insertColumn(column_saver + column_count)
                if plot_count >= self.tableWidget.rowCount():
                    self.tableWidget.insertRow(plot_count)
                # units in first row of table
                new_item = QtWidgets.QTableWidgetItem(plot_data.label[0] +
                                                      ' | ' +
                                                      plot_data.label[1])
                new_item.setData(6, QtGui.QFont("Ubuntu", 11,
                                                QtGui.QFont.Bold))
                self.tableWidget.setItem(header_count,
                                         column_saver + column_count, new_item)
                #self.tableWidget.setItem(header_count, column_saver + column_count, QtWidgets.QTableWidgetItem(plot_data.label[0] + ' | ' + plot_data.label[1]))
                # x and y-value in one cell
                self.tableWidget.setItem(
                    plot_count, columns,
                    QtWidgets.QTableWidgetItem(
                        str(xs[column_count]) + ' | ' + str(ys[column_count])))
                # header
                self.tableWidget.setHorizontalHeaderItem(
                    column_saver + column_count,
                    QtWidgets.QTableWidgetItem(str(config[config_count])))
                column_count += 1

            if config[config_count] == header[data_count]:
                header[data_count] = header[data_count].replace(
                    config[config_count], plot_data.path[-1])
            elif config[config_count] in header[data_count]:
                header[data_count] = header[data_count].replace(
                    config[config_count], '')

            self.tableWidget.setVerticalHeaderItem(
                plot_count,
                QtWidgets.QTableWidgetItem(str(header[data_count])))
            column_saver = column_saver + column_count
            config_count += 1

            if config_count == len(config):
                plot_count += 1
                column_saver = config_count = 0
            data_count += 1

    def update_bd_table(self, index):
        # update bd table, the index determines the anchor,
        # if it is non integer per default the first config is regarded as
        # anchor

        self.bdTableModel.update_table(self.combo_rate_psnr.currentText(),
                                       self.combo_interp.currentText(), index,
                                       not (self.checkBox_bdplot.isChecked()))

    def update_bd_user_generated_curves_table(self, index):
        clicked_text = self.bdUserGeneratedTableModel.headerData(
            index, Qt.Vertical, Qt.DisplayRole)
        self.bdUserGeneratedTableModel.update(
            None, self.combo_rate_psnr.currentText(),
            self.combo_interp.currentText(),
            not (self.checkBox_bdplot.isChecked()), clicked_text)

    def update_bd_plot(self):
        data_collection = self.get_plot_data_collection_from_selected_variables(
        )
        data_collection_user_generated = []
        for index in self.curveListSelectionModel.selectedIndexes():
            data_collection_user_generated.append(
                self.curveListModel[index.data()])

        if len(data_collection):
            self.bdTableModel.update(data_collection,
                                     self.combo_rate_psnr.currentText(),
                                     self.combo_interp.currentText(),
                                     not (self.checkBox_bdplot.isChecked()))
        elif len(data_collection_user_generated):
            self.bdTableModel.update(data_collection_user_generated,
                                     self.combo_rate_psnr.currentText(),
                                     self.combo_interp.currentText(),
                                     not (self.checkBox_bdplot.isChecked()))

    def export_table_to_csv(self):
        # remember that the decimal mark is '.'
        if self.tableWidget.rowCount() > 0:
            path, extension = QtWidgets.QFileDialog.getSaveFileName(
                self, 'Save Table View as', '.', 'CSV (*.csv)')
            if path != '':
                if '.csv' not in path:
                    path += '.csv'
                with open(str(path), 'w', newline='') as stream:
                    writer = csv.writer(stream)
                    for row in range(self.tableWidget.rowCount()):
                        rowdata = []
                        rowdata.append(
                            str(
                                self.tableWidget.verticalHeaderItem(row).data(
                                    0)))  #data(0) = data(Qt.displayRole)
                        for column in range(self.tableWidget.columnCount()):
                            item = self.tableWidget.item(row, column)
                            if item is not None:
                                rowdata.append(str(item.text()))
                            else:
                                rowdata.append('')
                        writer.writerow(rowdata)

    def save_bd_table(self):
        if self.bdTableModel.rowCount(self) == 0:
            return
        filename, extension = QtWidgets.QFileDialog.getSaveFileName(
            self, 'Save Table as', '.', 'Latex (*.tex)')
        if filename != '':
            if '.tex' not in filename:
                filename += '.tex'
            self.bdTableModel.export_to_latex(filename)

    def on_combo_box(self):
        # just update the bd table but do not change the anchor
        self.update_bd_table(-1)

    def save_current_selection(self):
        """Saves the current selected sim data item collection"""
        if not self.get_selected_simulation_data_items():
            msg = QtWidgets.QMessageBox(self)  # use self as parent here
            msg.setIcon(QtWidgets.QMessageBox.Information)
            msg.setText(
                "You did not select any simulation data item to store\n"
                "Please make a selection and try again.")
            msg.setWindowTitle("Info")
            msg.show()
            return
        filename, extension = QtWidgets.QFileDialog.getSaveFileName(
            self, 'Save RD data as', '.', 'RDPlot (*.rd)')
        if filename != '':
            if '.rd' not in filename:
                filename += '.rd'
            f = open(filename, 'w')
            f.write(
                jsonpickle.encode(self.get_selected_simulation_data_items()))
            f.close()

    def process_cmd_line_args(self, args):
        """Processes cmd line arguments. Those are only pathes or files."""
        for path in args[1:]:
            if not isdir(path) and not isfile(path):
                continue
            if path.endswith('.rd'):
                f = open(path, 'r')
                json_str = f.read()
                sim_data_items = jsonpickle.decode(json_str)
                self.simDataItemTreeModel.update(sim_data_items, False)
                f.close()
                continue

            self.simDataItemTreeView.msg.show()
            self.simDataItemTreeView.parserThread.add_path(path)
            self.simDataItemTreeView.parserThread.start()

    def open_about_page(self):
        """Opens and displays an Html About file"""
        try:
            html_path = path.abspath(here + '/docs/about.html')
            html_file = open(html_path, 'r', encoding='utf-8', errors='ignore')
            source_code = html_file.read()

            try:
                f = open(here + '/version.txt', 'r')
                app_version = f.readline()
            except:
                app_version = 'could not detect version'

            source_code = source_code.replace("##VERSION##", app_version)
            source_code = source_code.replace("##here##", here)
            about_dialog = QtWidgets.QDialog(self)
            about_dialog.setWindowTitle("About RDPlot")
            about_dialog.setMaximumSize(950, 800)
            about_text = QtWidgets.QTextBrowser(about_dialog)
            about_text.setMinimumWidth(950)
            about_text.setMinimumHeight(800)
            about_text.setHtml(source_code)
            about_text.setOpenExternalLinks(True)
            about_text.show()
            about_dialog.exec_()
            about_dialog.close()
            about_text.close()
        except IOError:
            html_error = QtWidgets.QMessageBox()
            html_error.setIcon(QtWidgets.QMessageBox.Critical)
            html_error.setText("Error opening about or help")
            html_error.setInformativeText(
                "The html file from the resource could not be loaded.")
            html_error.exec_()

    def generate_new_curve(self):
        plot_data_collection = self.get_plot_data_collection_from_selected_variables(
        )
        if plot_data_collection:
            new_plot_values = []
            for _plot_data in plot_data_collection:
                new_plot_values.extend(_plot_data.values)
            if len(new_plot_values) < 4:
                QtWidgets.QMessageBox.warning(
                    self, "Warning!", "You didn't select at least 4 points.")
            else:
                curve_name, ok = QtWidgets.QInputDialog.getText(
                    self, "New curve",
                    "Please enter a name for the new curve.\n"
                    "If you enter an already existing name,\nits data will be overwritten."
                )
                curve_name = curve_name.strip()
                if curve_name is not '':
                    new_plot_data = PlotData([curve_name], new_plot_values, [],
                                             plot_data_collection[0].label)
                    self.add_curve(curve_name, new_plot_data)
                else:
                    QtWidgets.QMessageBox.warning(
                        self, "Warning!", "Please enter a valid name.")
        else:
            QtWidgets.QMessageBox.warning(
                self, "Warning!", "You didn't select at least 4 points.")

    def add_curve(self, name, data):
        if self.curveWidget.isHidden():
            self.curveWidget.show()
        data_tuple = (name, data)
        self.curveListModel.update_from_tuples((data_tuple, ))
        # all_indexes = QItemSelection(self.curveListModel.index(0),
        #                             self.curveListModel.index(self.curveListModel.rowCount(QModelIndex())))
        # self.curveListSelectionModel.select(all_indexes, QItemSelectionModel.Clear)
        # self.curveListSelectionModel.select(self.curveListModel.index(self.curveListModel.rowCount(QModelIndex())-1),
        #                                    QItemSelectionModel.Select)
        # self.curveListView.setFocus()

    def remove_curves(self):
        # todo integrate bjontegaard for generated curves(should be fully functional already)
        curves_to_remove = []
        for index in self.curveListSelectionModel.selectedIndexes():
            curves_to_remove.append(index.data())
        self.curveListModel.remove_keys(curves_to_remove)
        if len(self.curveListModel) > 0:
            self.curveListSelectionModel.select(self.curveListModel.index(0),
                                                QItemSelectionModel.Select)
        else:
            self.curveWidget.hide()
            self.update_plot()

    def get_recent_files(self):
        recent_files = self.settings.value('recentFiles')
        if recent_files is not None:
            for recent_file in recent_files:
                if path.exists(recent_file):
                    action = self.menuRecent_files.addAction(recent_file)
                    action.triggered.connect(self.open_recent_file)

    def open_recent_file(self):
        path_recent = self.sender().text()
        if path.isdir(path_recent):
            self.simDataItemTreeView.add_folder(path_recent)
        else:
            self.simDataItemTreeView.add_file(path_recent)

    def add_recent_files(self, files, reload):
        # files doesn't necessarily have to just be a list of files
        # it can also be a directory
        if not reload:
            recent_files = self.settings.value('recentFiles')
            if recent_files is None:
                recent_files = []
            for file in files:

                if file in recent_files:
                    # put our file on top of the list
                    recent_files.remove(file)
                recent_files.insert(0, file)
            while len(recent_files) > 5:
                del recent_files[-1]
            self.settings.setValue('recentFiles', recent_files)

            self.menuRecent_files.clear()
            for recent_file in recent_files:
                if path.exists(recent_file):
                    action = self.menuRecent_files.addAction(recent_file)
                    action.triggered.connect(self.open_recent_file)

    def add_files_to_watcher(self, items):
        for item in items:
            if isfile(item.path):
                self.watcher.addPath(item.path)

    def warning_file_change(self, path_item):
        # inform user about the fact that one of the loaded files has been changed since the application has started
        # timer is used to avoid spamming the user when multiple files are deleted in a row
        # retrieve affected notes and parent nodes
        # change their style in the tree view to indicate which files are affected
        if self.show_file_changed_message:
            self.show_file_changed_message = False
            self.reset_timer.start()
            QtWidgets.QMessageBox.warning(
                self, 'File change',
                'One or more of your loaded files have been changed.\n'
                'You can choose to reload them.\n'
                'Hint: Changed files are greyed out in the sequences widget.')
        else:
            self.reset_timer.stop()
            self.reset_timer.start()

        affected_notes = []
        for leaf in self.simDataItemTreeModel.root.leafs:
            for value in leaf.values:
                if value.path == path_item:
                    affected_notes.append(leaf)
        for node in affected_notes:
            node_index = self.simDataItemTreeModel._get_index_from_item(node)
            node.setProperty('needs_reload', 'True')
            parent = self.simDataItemTreeModel.parent(node_index)
            level = 0
            while parent.isValid() and level < 2:  #MAX_LEVEL
                parent.internalPointer().setProperty('needs_reload', 'True')
                parent = self.simDataItemTreeModel.parent(parent)
                level += 1

    def _reset_file_changed_message(self):
        self.show_file_changed_message = True

    def reload_files(self):
        # remove all selected files first
        # reload available files
        # could possibly limit this to only files that we know have been changed
        def check_children(parent):
            if len(parent.children) > 0:
                for child in parent.children:
                    if not check_children(child):
                        return False
                parent.setProperty('needs_reload', 'False')
                return True
            else:
                if parent.property('needs_reload') == 'True':
                    return False
                return True

        values = self.selectedSimulationDataItemListModel.values()
        if len(values) == 0:
            for index in self.simDataItemTreeModel.root.leafs:
                for sim_data_item in index.values:
                    values.append(sim_data_item)
        items_to_be_reloaded = []
        for value in values:
            if path.exists(value.path):
                # reload file
                items_to_be_reloaded.append(value)

        self._variable_tree_selection_model.selectionChanged.disconnect()
        self._selection_model.selectionChanged.disconnect(self.change_list)
        self.simDataItemTreeModel.remove(values)

        self.simDataItemTreeView.msg.show()
        for item in items_to_be_reloaded:
            self.simDataItemTreeView.add_file(item.path, reload=True)

        self.change_list(QItemSelection(), QItemSelection())
        self._selection_model.selectionChanged.connect(self.change_list)
        self._variable_tree_selection_model.selectionChanged.connect(
            self.update_plot)

        for node in self.simDataItemTreeModel.root.children:
            # remove grey font color if all changed files have been reloaded
            # have to check every single item because possible deletion of older nodes makes things very difficult
            check_children(node)

    def show_sequences_context_menu(self, position):
        self.menuEdit.exec(self.simDataItemTreeView.mapToGlobal(position))
コード例 #6
0
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())