Esempio n. 1
0
    def exportCSV(self):
        if self.focusWidget().__class__.__name__ != 'QTableView':
            print('Not TableView')
            return
        exportModel = QStandardItemModel(self)
        exportModel = self.focusWidget().model()
        if not  exportModel:
            return

        nrOfRows = exportModel.rowCount()
        nrOfCols = exportModel.columnCount()
        exportCSVStr = StringIO()

        for ch in range(nrOfCols):
            exportCSVStr.write(exportModel.horizontalHeaderItem(ch).text())
            exportCSVStr.write('\t')

        exportCSVStr.write('\n')

        for i in range(nrOfRows):
            for c in range(nrOfCols):
                endData = exportModel.data(exportModel.index(i, c)).encode(encoding='iso-8859-1', errors='ignore')
                exportCSVStr.write(str(endData, 'iso-8859-1').replace('\r', ''))
                exportCSVStr.write('\t')

            exportCSVStr.write('\n')

        if not self.exportCSV_:
            pyperclip.copy(exportCSVStr.getvalue())
            return

        text, okPressed = QInputDialog.getText(self, "Get text", "File Name:", QLineEdit.Normal, "")
        if okPressed and text != '':
            file = open(text+'.csv', 'w', encoding='iso-8859-1')
            file.write(exportCSVStr.getvalue())
            file.close()
class AddressList(MyTreeView):
    class Columns(IntEnum):
        TYPE = 0
        ADDRESS = 1
        LABEL = 2
        COIN_BALANCE = 3
        FIAT_BALANCE = 4
        NUM_TXS = 5

    filter_columns = [
        Columns.TYPE, Columns.ADDRESS, Columns.LABEL, Columns.COIN_BALANCE
    ]

    ROLE_SORT_ORDER = Qt.UserRole + 1000

    def __init__(self, parent):
        super().__init__(parent,
                         self.create_menu,
                         stretch_column=self.Columns.LABEL)
        self.wallet = self.parent.wallet
        self.setSelectionMode(QAbstractItemView.ExtendedSelection)
        self.setSortingEnabled(True)
        self.show_change = AddressTypeFilter.ALL  # type: AddressTypeFilter
        self.show_used = AddressUsageStateFilter.ALL  # type: AddressUsageStateFilter
        self.change_button = QComboBox(self)
        self.change_button.currentIndexChanged.connect(self.toggle_change)
        for addr_type in AddressTypeFilter.__members__.values(
        ):  # type: AddressTypeFilter
            self.change_button.addItem(addr_type.ui_text())
        self.used_button = QComboBox(self)
        self.used_button.currentIndexChanged.connect(self.toggle_used)
        for addr_usage_state in AddressUsageStateFilter.__members__.values(
        ):  # type: AddressUsageStateFilter
            self.used_button.addItem(addr_usage_state.ui_text())
        self.std_model = QStandardItemModel(self)
        self.proxy = MySortModel(self, sort_role=self.ROLE_SORT_ORDER)
        self.proxy.setSourceModel(self.std_model)
        self.setModel(self.proxy)
        self.update()
        self.sortByColumn(self.Columns.TYPE, Qt.AscendingOrder)

    def get_toolbar_buttons(self):
        return QLabel(_("Filter:")), self.change_button, self.used_button

    def on_hide_toolbar(self):
        self.show_change = AddressTypeFilter.ALL  # type: AddressTypeFilter
        self.show_used = AddressUsageStateFilter.ALL  # type: AddressUsageStateFilter
        self.update()

    def save_toolbar_state(self, state, config):
        config.set_key('show_toolbar_addresses', state)

    def refresh_headers(self):
        fx = self.parent.fx
        if fx and fx.get_fiat_address_config():
            ccy = fx.get_currency()
        else:
            ccy = _('Fiat')
        headers = {
            self.Columns.TYPE: _('Type'),
            self.Columns.ADDRESS: _('Address'),
            self.Columns.LABEL: _('Label'),
            self.Columns.COIN_BALANCE: _('Balance'),
            self.Columns.FIAT_BALANCE: ccy + ' ' + _('Balance'),
            self.Columns.NUM_TXS: _('Tx'),
        }
        self.update_headers(headers)

    def toggle_change(self, state: int):
        if state == self.show_change:
            return
        self.show_change = AddressTypeFilter(state)
        self.update()

    def toggle_used(self, state: int):
        if state == self.show_used:
            return
        self.show_used = AddressUsageStateFilter(state)
        self.update()

    @profiler
    def update(self):
        if self.maybe_defer_update():
            return
        current_address = self.current_item_user_role(col=self.Columns.LABEL)
        if self.show_change == AddressTypeFilter.RECEIVING:
            addr_list = self.wallet.get_receiving_addresses()
        elif self.show_change == AddressTypeFilter.CHANGE:
            addr_list = self.wallet.get_change_addresses()
        else:
            addr_list = self.wallet.get_addresses()
        self.proxy.setDynamicSortFilter(
            False)  # temp. disable re-sorting after every change
        self.std_model.clear()
        self.refresh_headers()
        fx = self.parent.fx
        set_address = None
        addresses_beyond_gap_limit = self.wallet.get_all_known_addresses_beyond_gap_limit(
        )
        for address in addr_list:
            num = self.wallet.get_address_history_len(address)
            label = self.wallet.labels.get(address, '')
            c, u, x = self.wallet.get_addr_balance(address)
            balance = c + u + x
            is_used_and_empty = self.wallet.is_used(address) and balance == 0
            if self.show_used == AddressUsageStateFilter.UNUSED and (
                    balance or is_used_and_empty):
                continue
            if self.show_used == AddressUsageStateFilter.FUNDED and balance == 0:
                continue
            if self.show_used == AddressUsageStateFilter.USED_AND_EMPTY and not is_used_and_empty:
                continue
            balance_text = self.parent.format_amount(balance, whitespaces=True)
            # create item
            if fx and fx.get_fiat_address_config():
                rate = fx.exchange_rate()
                fiat_balance = fx.value_str(balance, rate)
            else:
                fiat_balance = ''
            labels = [
                '', address, label, balance_text, fiat_balance,
                "%d" % num
            ]
            address_item = [QStandardItem(e) for e in labels]
            # align text and set fonts
            for i, item in enumerate(address_item):
                item.setTextAlignment(Qt.AlignVCenter)
                if i not in (self.Columns.TYPE, self.Columns.LABEL):
                    item.setFont(QFont(MONOSPACE_FONT))
            self.set_editability(address_item)
            address_item[self.Columns.FIAT_BALANCE].setTextAlignment(
                Qt.AlignRight | Qt.AlignVCenter)
            # setup column 0
            if self.wallet.is_change(address):
                address_item[self.Columns.TYPE].setText(_('change'))
                address_item[self.Columns.TYPE].setBackground(
                    ColorScheme.YELLOW.as_color(True))
            else:
                address_item[self.Columns.TYPE].setText(_('receiving'))
                address_item[self.Columns.TYPE].setBackground(
                    ColorScheme.GREEN.as_color(True))
            address_item[self.Columns.LABEL].setData(address, Qt.UserRole)
            address_path = self.wallet.get_address_index(address)
            address_item[self.Columns.TYPE].setData(address_path,
                                                    self.ROLE_SORT_ORDER)
            address_path_str = self.wallet.get_address_path_str(address)
            if address_path_str is not None:
                address_item[self.Columns.TYPE].setToolTip(address_path_str)
            address_item[self.Columns.FIAT_BALANCE].setData(
                balance, self.ROLE_SORT_ORDER)
            # setup column 1
            if self.wallet.is_frozen_address(address):
                address_item[self.Columns.ADDRESS].setBackground(
                    ColorScheme.BLUE.as_color(True))
            if address in addresses_beyond_gap_limit:
                address_item[self.Columns.ADDRESS].setBackground(
                    ColorScheme.RED.as_color(True))
            # add item
            count = self.std_model.rowCount()
            self.std_model.insertRow(count, address_item)
            address_idx = self.std_model.index(count, self.Columns.LABEL)
            if address == current_address:
                set_address = QPersistentModelIndex(address_idx)
        self.set_current_idx(set_address)
        # show/hide columns
        if fx and fx.get_fiat_address_config():
            self.showColumn(self.Columns.FIAT_BALANCE)
        else:
            self.hideColumn(self.Columns.FIAT_BALANCE)
        self.filter()
        self.proxy.setDynamicSortFilter(True)

    def create_menu(self, position):
        from electrum.wallet import Multisig_Wallet
        is_multisig = isinstance(self.wallet, Multisig_Wallet)
        can_delete = self.wallet.can_delete_address()
        selected = self.selected_in_column(self.Columns.ADDRESS)
        if not selected:
            return
        multi_select = len(selected) > 1
        addrs = [self.item_from_index(item).text() for item in selected]
        menu = QMenu()
        if not multi_select:
            idx = self.indexAt(position)
            if not idx.isValid():
                return
            item = self.item_from_index(idx)
            if not item:
                return
            addr = addrs[0]
            addr_column_title = self.std_model.horizontalHeaderItem(
                self.Columns.LABEL).text()
            addr_idx = idx.sibling(idx.row(), self.Columns.LABEL)
            self.add_copy_menu(menu, idx)
            menu.addAction(_('Details'),
                           lambda: self.parent.show_address(addr))
            persistent = QPersistentModelIndex(addr_idx)
            menu.addAction(_("Edit {}").format(addr_column_title),
                           lambda p=persistent: self.edit(QModelIndex(p)))
            #menu.addAction(_("Request payment"), lambda: self.parent.receive_at(addr))
            if self.wallet.can_export():
                menu.addAction(_("Private key"),
                               lambda: self.parent.show_private_key(addr))
            if not is_multisig and not self.wallet.is_watching_only():
                menu.addAction(_("Sign/verify message"),
                               lambda: self.parent.sign_verify_message(addr))
                menu.addAction(_("Encrypt/decrypt message"),
                               lambda: self.parent.encrypt_message(addr))
            if can_delete:
                menu.addAction(_("Remove from wallet"),
                               lambda: self.parent.remove_address(addr))
            addr_URL = block_explorer_URL(self.config, 'addr', addr)
            if addr_URL:
                menu.addAction(_("View on block explorer"),
                               lambda: webopen(addr_URL))

            if not self.wallet.is_frozen_address(addr):
                menu.addAction(
                    _("Freeze"), lambda: self.parent.
                    set_frozen_state_of_addresses([addr], True))
            else:
                menu.addAction(
                    _("Unfreeze"), lambda: self.parent.
                    set_frozen_state_of_addresses([addr], False))

        coins = self.wallet.get_spendable_coins(addrs)
        if coins:
            menu.addAction(_("Spend from"),
                           lambda: self.parent.utxo_list.set_spend_list(coins))

        run_hook('receive_menu', menu, addrs, self.wallet)
        menu.exec_(self.viewport().mapToGlobal(position))

    def place_text_on_clipboard(self, text: str, *, title: str = None) -> None:
        if is_address(text):
            try:
                self.wallet.check_address_for_corruption(text)
            except InternalAddressCorruption as e:
                self.parent.show_error(str(e))
                raise
        super().place_text_on_clipboard(text, title=title)
Esempio n. 3
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())
Esempio n. 4
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状态
Esempio n. 5
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
Esempio n. 6
0
class PopupHaloDescriptorWidget(PopupWidget):
    def __init__(self, parent):
        super().__init__(parent, 0.25, 0.5)
        self.setWindowTitle("Halo descriptor")

        self.__widget_label_title = QLabel("Set the halos for each dimension.",
                                           parent=self)

        self.__halo_model = QStandardItemModel(0, 2)
        self.__halo_model.setHorizontalHeaderLabels(["Minus", "Plus"])
        self.__halo_model.horizontalHeaderItem(0).setToolTip(
            "Negative halo extent")
        self.__halo_model.horizontalHeaderItem(1).setToolTip(
            "Positive halo extent")

        self.__widget_table = QTableView(self)
        self.__widget_table.setModel(self.__halo_model)
        self.__widget_table.setStyleSheet('''
                QTableWidget::item:selected:active {
                    background: transparent;
                    border-width: 0px;
                }
            ''')

        self.__widget_table.horizontalHeader().setSectionResizeMode(
            QHeaderView.Stretch)

        # Assume 3 dimension by default
        for i in range(3):
            self.add_row()

        self.__widget_button_add = QPushButton(self)
        self.__widget_button_add.setIcon(Icon("edit_add.png"))
        self.__widget_button_add.clicked.connect(self.add_row)
        self.__widget_button_add.setToolTip("Add a dimension")

        self.__widget_button_remove = QPushButton(self)
        self.__widget_button_remove.setIcon(Icon("edit_remove.png"))
        self.__widget_button_remove.clicked.connect(self.remove_row)
        self.__widget_button_remove.setToolTip("Remove last dimension")

        self.__widget_button_ok = QPushButton("Done", parent=self)
        self.__widget_button_ok.clicked.connect(self.done)

        hbox_bottom = QHBoxLayout()
        hbox_bottom.addWidget(self.__widget_button_add)
        hbox_bottom.addWidget(self.__widget_button_remove)
        hbox_bottom.addStretch(1)
        hbox_bottom.addWidget(self.__widget_button_ok)

        vbox = QVBoxLayout()
        vbox.addWidget(self.__widget_label_title)
        vbox.addWidget(self.__widget_table)
        vbox.addLayout(hbox_bottom)

        self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        self.setLayout(vbox)

    def add_row(self):
        Logger.info("Adding row")

        minus = QStandardItem()
        minus.setTextAlignment(Qt.AlignCenter)
        minus.setText("0")

        plus = QStandardItem()
        plus.setTextAlignment(Qt.AlignCenter)
        plus.setText("0")

        self.__halo_model.appendRow([minus, plus])

    def remove_row(self):
        Logger.info("Removing row")
        self.__halo_model.removeRow(self.__halo_model.rowCount() - 1)

    def done(self):
        self.close()

    def get_halos(self):
        halos = []
        try:
            for i in range(self.__halo_model.rowCount()):
                minus = int(self.__halo_model.item(i, 0).text())
                plus = int(self.__halo_model.item(i, 1).text())

                if minus < 0 or plus < 0:
                    raise RuntimeError(
                        "Invalid halo boundary (%i, %i) in dimension %s: halo boundaries must be positive numbers."
                        % (minus, plus, i))

                halos += [[minus, None if plus is 0 else plus]]
        except ValueError as e:
            raise RuntimeError(str(e))
        return Halos(halos)
Esempio n. 7
0
class ResultsTable(QWidget):
    def __init__(self, connection_helper):
        super().__init__()
        self.connection_helper = connection_helper
        self.model = QStandardItemModel()
        self.model.itemChanged.connect(self.edit_cell)

        # self.database = QSqlDatabase("QPSQL7")
        # self.database.setHostName('127.0.0.1')
        # self.database.setUserName('root')
        # self.database.setPassword('root')
        # self.database.setPort(5432)
        # self.database.setDatabaseName('pydb')
        # self.database.open()
        # self.sql_model = QSqlTableModel(None, self.database)
        # self.sql_model.setHeaderData(0, Qt.Horizontal, "id")
        # self.sql_model.setTable('testing')
        # print(self.sql_model.selectStatement())
        # self.sql_model.select()
        # print(self.sql_model.selectStatement())
        # print(self.sql_model.lastError().text())
        # print(self.sql_model.rowCount())
        # print(self.sql_model.columnCount())

        self.init_ui()

    def init_ui(self):
        uic.loadUi(ui_file, self)
        self.ResultsTable.setSortingEnabled(True)
        # self.ResultsTable.sortByColumn(0, Qt.AscendingOrder)

    def edit_cell(self, item):
        # revert update command if failed to reset cell and display warning message
        column = item.column()
        row = item.row()
        row_values = [self.model.item(row, column).text() for column in range(self.model.columnCount())]
        column_value = self.model.horizontalHeaderItem(column).text()
        value = item.data(Qt.EditRole)

        result = self.connection_helper.update_query(None, column, column_value, row, value, row_values)
        print(result)

    def set_headers(self, headers):
        self.headers = headers
        for idx, header in enumerate(headers):
            self.model.setHorizontalHeaderItem(idx, QStandardItem(header))

    def set_blank(self):
        self.set_headers(['Results'])
        self.set_rows([{'value': 'No Results'}])

    def clear(self):
        self.model.clear()

    def set_rows(self, rows):
        for idx, row in enumerate(rows):
            items = []
            for column, item in row.items():
                standard_item = QStandardItem()

                if item is None:
                    font = QFont()
                    font.setItalic(True)
                    font.setBold(True)
                    standard_item.setData(QVariant("NULL"), Qt.EditRole)
                    standard_item.setFont(font)
                elif isinstance(item, datetime.datetime):
                    standard_item.setData(QDateTime(item), Qt.EditRole)
                elif isinstance(item, datetime.date):
                    standard_item.setData(QDate(item), Qt.EditRole)
                elif isinstance(item, str):
                    standard_item.setData(QVariant(item), Qt.EditRole)
                else:
                    standard_item.setData(QVariant(item), Qt.EditRole)
                items.append(standard_item)
            self.model.insertRow(idx, items)

    def get_sort(self):
        sort_column = self.ResultsTable.horizontalHeader().sortIndicatorSection()
        sort_type = self.ResultsTable.horizontalHeader().sortIndicatorOrder()
        return {'column': sort_column, 'type': sort_type}

    def update_sort(self, column, type):
        self.ResultsTable.sortByColumn(column, type)

    def display(self):
        self.ResultsTable.setModel(self.model)
Esempio n. 8
0
class LogDialogClass(QtWidgets.QDialog, Ui_Dialog):
    def __init__(self):
        super(LogDialogClass, self).__init__()
        self.setupUi(self)

        self.model = QStandardItemModel()
        self.model.setHorizontalHeaderLabels(['日志时间', '日志信息'])

        # 实例化表格视图,设置模型为自定义的模型
        self.tableView = QTableView()
        self.tableView.setModel(self.model)

        self.tableView.horizontalHeader().setStretchLastSection(True)
        # self.tableView.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
        self.tableView.setColumnWidth(0, 130)
        self.tableView.verticalHeader().hide()
        self.tableView.horizontalHeader().setDefaultAlignment(
            QtCore.Qt.AlignLeft)

        # 设置布局 horizontalLayout
        layout = QVBoxLayout(self, spacing=0)
        layout.setContentsMargins(0, 0, 0, 30)
        layout.addWidget(self.tableView)
        """
        layout.addWidget(self.pushButton)
        layout.addWidget(self.pushButton_2)
        layout.addWidget(self.label)
        """
        self.setLayout(layout)

        threadSocket = threading.Thread(target=self.Initsocket, args=())
        threadSocket.start()

        self.pushButton_clrear.clicked.connect(self.ClearAllMessage)
        self.pushButton_export.clicked.connect(self.LogExport)

    def Initsocket(self):
        serverSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        serverSocket.bind((logsocketAddress, logsocketPort))
        serverSocket.listen(5)  # 监听
        print('starting....')

        while True:
            conn, addr = serverSocket.accept()  # 接收客户端信号
            print(conn)
            print('client addr', addr)
            print('ready to read msg')
            client_msg = conn.recv(1024)  # 收消息
            print('client msg: %s' % client_msg)

            decodejson = json.loads(client_msg)
            print(type(decodejson))
            print(decodejson)

            strType = decodejson['type']
            strMsg = decodejson['msg']

            if (strType == 'OutputMessage'):
                self.SendMessage(strMsg)
            elif (strType == 'ClearAllMessage'):
                self.ClearAllMessage()
            elif (strType == 'CloseWindow'):
                self.CloseWindow()
                break

        conn.close()
        serverSocket.close()

        print('The end....')

    def SendMessage(self, msg):
        # 第iRow+1行
        iRow = self.model.rowCount()
        item10 = QStandardItem(
            time.strftime("%Y/%m/%d %H:%M:%S", time.localtime()))
        self.model.setItem(iRow, 0, item10)
        item11 = QStandardItem(msg)
        self.model.setItem(iRow, 1, item11)

    def ClearAllMessage(self):
        irowCount = self.model.rowCount()
        print(irowCount)
        while (irowCount > 0):
            self.model.removeRow(irowCount - 1)
            irowCount = irowCount - 1

    def CloseWindow(self):
        self.pushButton_close.click()

    def LogExport(self):

        fileName_choose, filetype = QFileDialog.getSaveFileName(
            self,
            "文件保存",
            "C:/",  # 起始路径
            "All Files (*);;Text Files (*.txt)")

        if fileName_choose == "":
            return

        print("\n你选择要保存的文件为:")
        print(fileName_choose)
        print("文件筛选器类型: ", filetype)

        irowCount = self.model.rowCount()
        icolumn = self.model.columnCount()
        print(irowCount)
        print(icolumn)

        # 获取表头文字
        strLog = ''
        for icol1 in range(icolumn):
            aItem = self.model.horizontalHeaderItem(icol1)  # 获取表头的项数据
            strLog = strLog + aItem.text() + "\t\t\t"  # //以TAB见隔开
            print(strLog)

        strLog = strLog + '\n'
        File.Write(fileName_choose, strLog)

        for irow in range(irowCount):
            str = ""
            for icol in range(icolumn):
                item = self.model.item(irow, icol)
                print('行:', irow)
                print('列:', icol)
                print(item.text())
                str = str + item.text() + ("\t\t")
            File.Append(fileName_choose, str + "\r\n")
Esempio n. 9
0
class Controller(object):
    """
    The Controller class is for loading the specific guis from the GUI folder.
    It also implements and fill the required GUI with logic.
    """
    def __init__(self, path: str):
        # the actual path
        self.actualPath = path
        # A IDatabaseManager to communicate with the database
        self.database = DatabaseManager()
        # Tries to create the required tables
        self.database.createTables()

        # The path to the different GUIs
        self.pathMainGui = self.actualPath + '/GUI' + '/MainGui.ui'
        self.pathStartDownload = self.actualPath + '/GUI' + '/StartDownload.ui'
        self.pathCurrentDownload = self.actualPath + '/GUI' + '/CurrentDownload.ui'
        self.pathSettings = self.actualPath + '/GUI' + '/Settings.ui'
        self.pathError = self.actualPath + '/GUI' + '/ErrorMessage.ui'
        self.pathHelp = self.actualPath + '/GUI' + '/Help.ui'
        self.pathMoodleSummary = self.actualPath + '/GUI' + '/MoodleSummary.ui'

        # path to the folder, where temporary files shall be stored
        self.pathTempFolder = self.actualPath + '/temp/'

        app = QtWidgets.QApplication(sys.argv)

        # the main and error window
        self.MainWindow = None
        self.ErrorWindow = None
        # courseData, which was selected from the user
        self.selectedCourseData = None
        # The filter (lecturer name, semester, course name) which is selected
        self.selectedFilter = None
        # The model of the courseData which is selected
        self.modelCourseData = None
        # Will set on True, when the moodle download was started, because
        #    scrapy can only run one time per program run
        self.startedMoodleCrawler = False

        # The IFileHandler to handle the CourseData
        self.fileHandler = FileHandler()
        # The used ITextAbstraction
        self.textSummarizer = TextAbstraction(database=self.database)

        user = self.database.getUser()
        # check if the program has already a user
        if user is None:
            # no user in the database
            # go to settings
            self.openSettings()
        else:
            # go to main page
            self.goBackMainPage()
        sys.exit(app.exec_())

    # Guis
    # Open MainPage
    def goBackMainPage(self):
        """
        goBackMainPage will start the MainPage and will connect everything with
        the required functions and print the required information to the gui.
        """
        # close and clean up the old Main Window
        self.cleanMainWindow()

        # Load and show the new Main Window
        self.MainWindow = loadUi(self.pathMainGui)
        self.MainWindow.showMaximized()
        self.MainWindow.show()

        # disable that the user can edit the entries from table for general course information
        self.MainWindow.tab_courses.setEditTriggers(
            QAbstractItemView.NoEditTriggers)
        self.MainWindow.tab_courses.setSortingEnabled(True)
        # Fill the table for the general course information with data
        self.printGeneralCourseInformation()
        # if some data from the general course information is clicked, show all data for this filter
        # in tab_data
        self.MainWindow.tab_courses.clicked.connect(
            self.selectGeneralCourseInformation)

        # disable that the user can edit the entries from table for course data
        self.MainWindow.tab_data.setEditTriggers(
            QAbstractItemView.NoEditTriggers)
        self.MainWindow.tab_data.setSortingEnabled(True)
        # if an cell was selected in table for course data, mark the whole row
        self.MainWindow.tab_data.setSelectionBehavior(
            QAbstractItemView.SelectRows)
        # if some data from the CourseData is clicked, load the summary to the field text_Abstract
        self.MainWindow.tab_data.clicked.connect(self.selectCourseData)

        # Connect the Buttons with functionality

        # open Window for checking, if it is necessary to download moodle-data
        self.MainWindow.but_downloadMoodle.clicked.connect(
            self.openWindowStartDownload)
        # open Window for storing username and password
        self.MainWindow.but_settings.clicked.connect(self.openSettings)
        # open Window for help
        self.MainWindow.but_help.clicked.connect(self.openHelp)
        # open Window for get the summary from the last moodle download
        self.MainWindow.but_moodleSummary.clicked.connect(
            lambda: self.openMoodleSummary(destination="Main Page"))

        # search functions
        self.MainWindow.but_searchAll.clicked.connect(
            lambda: self.searchData(filter="All"))
        self.MainWindow.but_searchCell.clicked.connect(
            lambda: self.searchData(filter="Cell"))
        # show Text without Text-Mining
        self.MainWindow.but_withoutTextMiningAll.clicked.connect(
            lambda: self.showDataWithoutTextMining(filter="All"))
        self.MainWindow.but_withoutTextMiningCell.clicked.connect(
            lambda: self.showDataWithoutTextMining(filter="Cell"))

        # open Data
        self.MainWindow.but_openData.clicked.connect(self.openData)
        self.MainWindow.but_openAllData.clicked.connect(self.openAllData)

        # save Data
        self.MainWindow.but_saveData.clicked.connect(self.saveData)
        self.MainWindow.but_saveAllData.clicked.connect(self.saveAllData)

        # close program
        self.MainWindow.but_close.clicked.connect(self.quitProgram)

    # StartDownloadPage
    def openWindowStartDownload(self):
        """
        open the gui to ask the user, if he really wants to download the moodle data.
        It will connect everything with the required functions and print the required information to the gui.
        """
        self.cleanMainWindow()
        self.MainWindow = loadUi(self.pathStartDownload)

        # Check if the Crawler was executed, because you can´t start again a Crawler
        if (self.startedMoodleCrawler):
            # Crawler was executed
            # deactivate the Button for starting the Crawler
            self.MainWindow.but_startDownload.setEnabled(False)
            # inform the user that he can not start again the crawler
            self.MainWindow.label_info.setText(
                """<html><head/><body><p align="center">Achtung:</p><p align="center">Es ist nur möglich einen Moodledownload pro </p><p align="center">Programmstart auszuführen.</p><p align="center">Falls Sie erneut den Download starten wollen, starten Sie das Porgramm neu!<br/></p></body></html>"""
            )
        else:
            # Crawler was not executed

            # get the las date of Crawling
            lastDateOfCrawling = self.database.getMaxDateOfCrawling()
            if lastDateOfCrawling is None:
                # inform the user, that he never start a download process from moodle
                self.MainWindow.label_info.setText(
                    self.MainWindow.label_info.text().replace(
                        '%String',
                        'Sie haben noch keinen Download gestartet!'))
            else:
                # inform the user, when his last download was
                self.MainWindow.label_info.setText(
                    self.MainWindow.label_info.text().replace(
                        '%String',
                        lastDateOfCrawling.dateCrawling.strftime(
                            "%H:%M:%S %d.%m.%Y ")))
        self.MainWindow.show()

        # connect button to go back to Main Page
        self.MainWindow.but_abortDownload.clicked.connect(self.goBackMainPage)
        # connect button to start moodle download
        self.MainWindow.but_startDownload.clicked.connect(
            self.openCurrentDownload)

    def openCurrentDownload(self):
        """
        Will open the current download gui and connect the scrapy logger to the gui.
        It start also the Crawler, if the user stored all required information.
        """
        self.cleanMainWindow()
        self.MainWindow = loadUi(self.pathCurrentDownload)
        self.MainWindow.showMaximized()

        # Activate logger to textbox
        logTextBox = QTextEditLogger(self.MainWindow)
        # You can format what is printed to text box
        logTextBox.setFormatter(
            logging.Formatter('%(asctime)s - %(levelname)s - %(message)s'))
        logging.getLogger().addHandler(logTextBox)
        # You can control the logging level
        logging.getLogger().setLevel(logging.INFO)

        # disable button done until the crawler finished
        self.MainWindow.but_done.setEnabled(False)
        # the log output is only readable
        self.MainWindow.plainTextEdit.setReadOnly(True)
        self.MainWindow.show()

        # get the moodle user
        user = self.database.getUser()

        # Check if a user is in the database or none of his attributes is null
        if (user is None or not user.username or not user.password):
            logTextBox.deactivate()
            self.goBackMainPage()
            self.errorMessage(e="""Sie haben noch keinen Nutzer angelegt. \n
                                Bitte legen Sie bei \"Einstellungen\" auf dem Startbildschirm, einen Nutzer an!"""
                              )

        else:
            # the user has all attributes
            # start the moodle crawler
            crawler = MoodleCrawlerHTWBerlin()
            crawler.startCrawler(self.database, user.username, user.password)

            # set the information, that the crawler was started on true
            self.startedMoodleCrawler = True

            # move the cursor to the end of the text field
            self.MainWindow.plainTextEdit.moveCursor(QTextCursor.End)
            logTextBox.deactivate()
            # check if the login was sucessfully
            if not self.database.loginSuccessfully():
                self.errorMessage(e="""
                Das Passwort oder der Nutzername sind falsch. \n
                Bitte ändern Sie bei \"Einstellungen\" auf dem Startbildschirm den Nutzer!"""
                                  )
                self.MainWindow.but_done.setEnabled(True)
                self.MainWindow.but_done.clicked.connect(self.goBackMainPage)
            else:
                # login was a success
                self.MainWindow.but_done.setEnabled(True)
                self.MainWindow.but_done.clicked.connect(
                    lambda: self.openMoodleSummary(destination="Text Process"))

    def openMoodleSummary(self, destination: str = "Main Page"):
        """
        Open the GUI for the getMoodleSummary. And print all informations to the gui. This GUI is
        for informing the user about what data per course is new, old  and could not be downloaded.
        Also every specific error in the download process will be shown.

        :param destination: Which GUI shall load after this gui.
        """
        self.cleanMainWindow()
        self.MainWindow = loadUi(self.pathMoodleSummary)

        # Fill the moodle data summary with data
        modelMoodleSummaryData = QStandardItemModel()
        self.MainWindow.tab_numberOfData.setEditTriggers(
            QAbstractItemView.NoEditTriggers)
        self.MainWindow.tab_numberOfData.setSortingEnabled(True)
        self.MainWindow.tab_numberOfData.setModel(modelMoodleSummaryData)
        # get the summary from the database
        moodleSummaryData = self.database.getMoodleSummary()
        # get the header from the table
        header = MoodleSummary.getHeader()

        modelMoodleSummaryData.setHorizontalHeaderLabels(header)
        for moodleSummaryItem in moodleSummaryData:
            listOfValues = moodleSummaryItem.getListForPrinting()
            row = []
            for value in listOfValues:
                cell = QStandardItem()
                cell.setData(value, Qt.DisplayRole)
                row.append(cell)
            modelMoodleSummaryData.appendRow(row)

        # Fill the moodle error data summary with data
        modelMoodleError = QStandardItemModel()
        self.MainWindow.tab_errorData.setModel(modelMoodleError)
        self.MainWindow.tab_errorData.setEditTriggers(
            QAbstractItemView.NoEditTriggers)
        self.MainWindow.tab_errorData.setSortingEnabled(True)
        # get the error summary from the database
        moodleErrorData = self.database.getMoodleErrorSummary()
        # get the header from the table
        header = MoodleErrorSummary.getHeader()

        modelMoodleError.setHorizontalHeaderLabels(header)
        for moodleErrorItem in moodleErrorData:
            listOfValues = moodleErrorItem.getListForPrinting()
            row = []
            for value in listOfValues:
                cell = QStandardItem()
                cell.setData(value, Qt.DisplayRole)
                row.append(cell)
            modelMoodleError.appendRow(row)

        self.MainWindow.showMaximized()
        self.MainWindow.show()

        if destination == "Main Page":
            self.MainWindow.but_back.setText("Zurück zur Hauptseite")
            self.MainWindow.but_back.clicked.connect(self.goBackMainPage)
        elif destination == "Text Process":
            self.MainWindow.but_back.clicked.connect(self.openTextProcessing)

    def openSettings(self):
        """
        open the GUI for settings. It is for saving the user information password
        and username from moodle.
        """
        self.cleanMainWindow()
        self.MainWindow = loadUi(self.pathSettings)
        self.MainWindow.show()

        # get the user from the database
        user = self.database.getUser()

        # set passwordline on password, that the password is not readable for the user
        self.MainWindow.linePassword.setEchoMode(QLineEdit.Password)

        # check if in the database is an user
        if user is not None:
            # in the database is an user
            # fill the text fields with his information
            self.MainWindow.lineUsername.setText(user.username)
            self.MainWindow.linePassword.setText(user.password)
        else:
            self.MainWindow.lineUsername.setPlaceholderText('s0111111')
            self.MainWindow.linePassword.setPlaceholderText(
                'Hier dein Passwort')
        # go back to main page, without saving
        self.MainWindow.but_abortSettings.clicked.connect(self.goBackMainPage)
        # go back to main page, with saving
        self.MainWindow.but_save.clicked.connect(self.saveSettings)

    def openHelp(self):
        """ open the help GUI. This is for helping the user to work with the application
        """
        self.cleanMainWindow()
        self.MainWindow = loadUi(self.pathHelp)
        self.MainWindow.showMaximized()
        self.MainWindow.show()

        # the user can not edit the help text
        self.MainWindow.helpText.setReadOnly(True)

        # go back to main page
        self.MainWindow.but_back.clicked.connect(self.goBackMainPage)

    # open textProcessing Page
    def openTextProcessing(self):
        """
        open the GUI CurrentDownload and start the text processing. Also it connects the logger
        to the edit line. This Gui informs the user about which CourseData will be textually
        processed.
        """
        self.cleanMainWindow()
        self.MainWindow = loadUi(self.pathCurrentDownload)
        self.MainWindow.showMaximized()

        # Activate logger to textbox
        logTextBox = QTextEditLogger(self.MainWindow)
        # You can format what is printed to text box
        logTextBox.setFormatter(
            logging.Formatter('%(asctime)s - %(levelname)s - %(message)s'))
        logging.getLogger().addHandler(logTextBox)
        # You can control the logging level
        logging.getLogger().setLevel(logging.INFO)

        # disable button until the text process is finished
        self.MainWindow.but_done.setEnabled(False)
        self.MainWindow.plainTextEdit.setReadOnly(True)
        self.MainWindow.show()

        # create the text mining logic
        textProcessing = TextProcessing(database=self.database,
                                        path=self.pathTempFolder,
                                        textSummarizer=self.textSummarizer)
        # get the CourseData from the database, which do not have a text abstraction and not raised an error in a past process
        fileTypes = ['pdf', 'docx', 'pptx', 'html']
        dataWithoutTextMining = self.database.getCourseDataWithoutTextMiningForParsing(
            fileTypes)

        # i is the position of the course data in the list
        i = 1
        countDataWithoutTextMining = len(dataWithoutTextMining)
        self.MainWindow.plainTextEdit.appendPlainText(
            "Es sind insgesamt %d Dateien textuell aufzuarbeiten!".replace(
                "%d", str(countDataWithoutTextMining)))
        # start for each data the text mining process
        for data in dataWithoutTextMining:
            self.MainWindow.plainTextEdit.appendPlainText(
                "Beginn mit der %d1. Datei von %d2!".replace(
                    "%d1", str(i)).replace("%d2",
                                           str(countDataWithoutTextMining)))
            textProcessing.textProcessing(data)
            self.MainWindow.plainTextEdit.appendPlainText(
                "Fertig mit der %d1. Datei von %d2!".replace(
                    "%d1", str(i)).replace("%d2",
                                           str(countDataWithoutTextMining)))
            i += 1
            QtWidgets.QApplication.processEvents()

        # enable the button for finish this
        self.MainWindow.but_done.setEnabled(True)

        # deactivate the logger
        logTextBox.deactivate()
        # go back to main page
        self.MainWindow.but_done.clicked.connect(self.goBackMainPage)

    def saveSettings(self):
        """
        It tries to save the informations from the settings to the database.
        If every field is filled save the information to the database and go back to the
        main page.
        Otherwise print an error message and do nothing.
        """
        # read the arguments of the user
        username = self.MainWindow.lineUsername.text()
        password = self.MainWindow.linePassword.text()
        if username == "" or password == "":
            self.errorMessage(e="""Der Nuzername oder das Passwort sind leer.
            Bitte füllen Sie die Felder aus!""")
        else:
            user = User(username=username, password=password)
            # delete the current user from the database
            self.database.deleteUsers()
            # insert the new user
            self.database.insertObject(user)
            # go back to main page
            self.goBackMainPage()

    def quitProgram(self):
        """
        Tries to delete every file in the temp folder. Only the files, which are not any more
        in use will be deleted.
        After this quit the program.
        """
        self.fileHandler.deleteAllFilesInFolder(self.pathTempFolder)
        sys.exit()

    def printGeneralCourseInformation(self):
        """
        print the generalCourseInformation to the table tab_courses
        """
        self.modelGeneralCourseInformation = QStandardItemModel()
        self.MainWindow.tab_courses.setModel(
            self.modelGeneralCourseInformation)

        courses = self.database.getGeneralCourseInformation()

        header = GeneralCourseInformation.getHeader()

        self.modelGeneralCourseInformation.setHorizontalHeaderLabels(header)
        # fill the table with the information
        for course in courses:
            listOfValues = course.getListForPrinting()
            row = []
            for value in listOfValues:
                cell = QStandardItem()
                cell.setData(value, Qt.DisplayRole)
                row.append(cell)
            self.modelGeneralCourseInformation.appendRow(row)

    def printCourseData(self, table=""):
        """
        print all CourseData from the table to the table tab_data.

        :param table: the table which shall be printed
        """
        self.modelCourseData = QStandardItemModel()
        self.MainWindow.tab_data.setModel(self.modelCourseData)
        header = CourseDataWithInformation.getHeader()

        self.modelCourseData.setHorizontalHeaderLabels(header)
        for course in table:
            listOfValues = course.getListForPrinting()
            row = []
            for value in listOfValues:
                cell = QStandardItem()
                cell.setData(value, Qt.DisplayRole)
                row.append(cell)
            self.modelCourseData.appendRow(row)

    def searchData(self, filter: str):
        """
        search for data if filter is all search for all data for search string otherwise for the selected filter
        after this print the searched data to table tab_data

        :param filter: filter = "All" if all data shall be searched; filter = "Cell" if only for the specific
        selected filter data shall be searched
        """
        searchString = self.MainWindow.line_search.text()
        table = None
        if filter == 'All':
            table = self.database.getCourseDataByText(
                searchString=searchString, filter="")
        elif filter == 'Cell':
            if self.selectedFilter:
                table = self.database.getCourseDataByText(
                    searchString=searchString, filter=self.selectedFilter)
            else:
                self.errorMessage(
                    e="""Sie haben keine Zelle ausgewählt. \n Bitte drücken Sie in der linken Tabelle 
                auf Ihren gewünschten Suchbegriff""")
        if table:
            self.printCourseData(table)

    def showDataWithoutTextMining(self, filter: str):
        """
        Search for data without text mining and print them to the table tab_data.

        :param filter: filter = "All" if all data without text-mining shall be searched; filter = "Cell" if only for the specific
        selected filter data without text-mining shall be searched
        """
        table = None
        if filter == 'All':
            table = self.database.getCourseDataWithoutTextMining(filter="")
        elif filter == 'Cell':
            if self.selectedFilter:
                table = self.database.getCourseDataWithoutTextMining(
                    filter=self.selectedFilter)
            else:
                self.errorMessage(e="""Sie haben keine Zelle ausgewählt. \n
                                                            Bitte drücken Sie in der linken Tabelle auf Ihren gewünschten Suchbegriff"""
                                  )
        if table:
            self.printCourseData(table)

    def openData(self):
        """
        open the the selected CourseData
        if None is selected inform the user that he has to select a CourseData in the table
        """
        if self.selectedCourseData is not None:
            self.fileHandler.openFile(courseData=self.selectedCourseData,
                                      path=self.pathTempFolder)
        else:
            self.errorMessage(e="""Sie haben keine Datei ausgewählt. \n
                                                        Bitte drücken Sie in der mittleren Tabelle auf Ihren gewünschte Datei."""
                              )

    def openAllData(self):
        """
        open all Data which are in the tab_data(modle = modelCourseData) printed
        If no data is printed inform the user that he has to search for CourseData to open a data
        """
        if self.modelCourseData is not None:
            courseDataID_list = []
            self.modelCourseData.columnCount()
            for y in range(self.modelCourseData.columnCount()):
                header = self.modelCourseData.horizontalHeaderItem(y).text()
                if header == "DataID":
                    column = y
                    continue
            for x in range(self.modelCourseData.rowCount()):
                index = self.modelCourseData.index(x, column)
                courseDataID_list.append(
                    self.modelCourseData.itemData(index).get(0))
            for courseDataId in courseDataID_list:
                courseData = self.database.getCourseDataByID(int(courseDataId))
                self.fileHandler.openFile(courseData=courseData,
                                          path=self.pathTempFolder)
        else:
            self.errorMessage(
                e="""Sie haben keine Dateien gesucht, die Sie auswählen können. \n
                                                        Bitte drücken Sie in der linken Tabelle auf Ihren gewünschten Suchbegriff, um die zugehörigen Dateien anzuzeigen."""
            )

    def selectGeneralCourseInformation(self, signal):
        """
        Set the selectedFilter on the selected Value, which the user selected.
        And print all Data for the specific filter to the tab_data
        """
        cell_dict = self.modelGeneralCourseInformation.itemData(signal)
        self.selectedFilter = cell_dict.get(0)

        result = self.database.getAllCourseData(filter=self.selectedFilter)
        self.printCourseData(table=result)

    def errorMessage(self, e: str):
        """
        open the error Gui and print the error message

        :param e: the error message
        """
        if self.ErrorWindow is not None:
            self.ErrorWindow.close()
        self.ErrorWindow = loadUi(self.pathError)
        self.ErrorWindow.label_info.setText(
            self.ErrorWindow.label_info.text().replace('%String', str(e)))
        self.ErrorWindow.but_ok.clicked.connect(self.ErrorWindow.close)
        self.ErrorWindow.show()

    def saveData(self):
        """
        save the selected data to a folder, which the user select.
        if None is selected inform the user that he has to select a CourseData in the table
        """
        if self.selectedCourseData is not None:
            saveFolder = QFileDialog.getExistingDirectory(
                self.MainWindow, "Select Directory")
            saveFolder += '/'
            if len(saveFolder) > 0:
                self.fileHandler.saveFile(courseData=self.selectedCourseData,
                                          path=saveFolder)
        else:
            self.errorMessage(e="""Sie haben keine Datei ausgewählt. \n
                                                        Bitte drücken Sie in der mittleren Tabelle auf Ihren gewünschte Datei."""
                              )

    def saveAllData(self):
        """
        save all CourseData which are printed in the tab_data(modle = modelCourseData)
        If no data is printed inform the user that he has to search for CourseData to open a data
        """
        if self.modelCourseData is not None:
            saveFolder = str(
                QFileDialog.getExistingDirectory(self.MainWindow,
                                                 "Select Directory"))
            if len(saveFolder) > 0:
                saveFolder += '/'
                courseDataID_list = []
                self.modelCourseData.columnCount()
                for y in range(self.modelCourseData.columnCount()):
                    header = self.modelCourseData.horizontalHeaderItem(
                        y).text()
                    if header == "DataID":
                        column = y
                        continue
                for row in range(self.modelCourseData.rowCount()):
                    index = self.modelCourseData.index(row, column)
                    courseDataID_list.append(
                        self.modelCourseData.itemData(index).get(0))
                for courseDataId in courseDataID_list:
                    courseData = self.database.getCourseDataByID(
                        int(courseDataId))
                    self.fileHandler.saveFile(courseData=courseData,
                                              path=saveFolder)
        else:
            self.errorMessage(
                e="""Sie haben keine Dateien gesucht, die Sie auswählen können. \n
                                                                        Bitte drücken Sie in der linken Tabelle auf Ihren gewünschten Suchbegriff, um die zugehörigen Dateien anzuzeigen."""
            )

    def selectCourseData(self, signal):
        """
        set the  selectedCourseData on the data which was selected.
        Print the abstract, the frequency of words and the errors from the data to the text field "text_Abstract"
        """
        row = signal.row()
        for y in range(self.modelCourseData.columnCount()):
            header = self.modelCourseData.horizontalHeaderItem(y).text()
            if header == "DataID":
                column = y
                break

        index = self.modelCourseData.index(row, column)
        courseDataID = self.modelCourseData.itemData(index).get(0)
        self.selectedCourseData = self.database.getCourseDataByID(
            idCourseData=courseDataID)

        self.MainWindow.text_Abstract.clear()

        if self.selectedCourseData.abstract is not None:
            self.MainWindow.text_Abstract.appendPlainText(
                self.selectedCourseData.abstract)
        if self.selectedCourseData.abstractWordFrequency is not None:
            self.MainWindow.text_Abstract.appendPlainText(
                self.selectedCourseData.abstractWordFrequency)
        if self.selectedCourseData.error is not None:
            self.MainWindow.text_Abstract.appendPlainText(
                self.selectedCourseData.error)
        self.MainWindow.text_Abstract.setReadOnly(True)

    def cleanMainWindow(self):
        """
        reset all fields
        """
        if self.MainWindow is not None:
            self.selectedCourseData = None
            self.selectedFilter = None
            self.modelCourseData = None
Esempio n. 10
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状态
Esempio n. 11
0
class Q0Measurement(Display):
    def ui_filename(self):
        return "q0.ui"

    def __init__(self, parent=None, args=None):

        super(Q0Measurement, self).__init__(parent=parent, args=args)

        self.pathHere = path.dirname(sys.modules[self.__module__].__file__)

        # Set up calibration data window
        self.calibrationLiquidLevelCanvas = MplCanvas()
        self.calibrationLineFitCanvas = MplCanvas()
        self.calibrationResultsWindow = None
        self.setupCalibrationDataWindow()

        # Set up RF data window
        self.rfLiquidLevelCanvas = MplCanvas()
        self.rfLineFitCanvas = MplCanvas()
        self.rfResultsWindow = None
        self.setupRfDataWindow()

        self.settingsWindow = Display(ui_filename=self.getPath("settings.ui"))
        self.setupSettingsWindow()

        heaterLineEdits = self.settingsWindow.ui.heaterSettingRepeater.findChildren(
            QLineEdit)
        self.initialCalibrationHeatLoadLineEdit: QLineEdit = findWidget(
            "initialCalibrationHeatLoad", heaterLineEdits)
        self.initialCalibrationHeatLoadLineEdit.setValidator(
            QIntValidator(8, 48))

        # TODO implement custom liveplot (archiver + append callback)
        self.liveSignalsWindow = Display(
            ui_filename=self.getPath("signals.ui"))
        self.ui.liveSignalsButton.clicked.connect(
            partial(self.showDisplay, self.liveSignalsWindow))
        self.plots = TimePlotObjects(
            liquidLevelPlot=self.liveSignalsWindow.ui.liquidLevelPlot,
            pressurePlot=self.liveSignalsWindow.ui.pressurePlot,
            heaterPlot=self.liveSignalsWindow.ui.heaterPlot,
            valvePlot=self.liveSignalsWindow.ui.valvePlot,
            rfPlot=self.liveSignalsWindow.ui.rfPlot,
            radiationPlot=self.liveSignalsWindow.ui.radiationPlot,
            temperaturePlot=self.liveSignalsWindow.ui.temperaturePlot)

        self.calibrationOptionModel = QStandardItemModel(self)

        self.calibrationOptionsWindow = Display(
            ui_filename=self.getPath("options.ui"))
        self.setupCalibrationOptionsWindow()

        self.calibrationSelection = {}

        self.calibrationStatus = None
        self.setupLabels()

        self.calibrationGroupBox = None
        self.rfGroupBox = None
        self.setupFrames()

        self.selectWindow = Display(ui_filename=self.getPath("cmSelection.ui"))
        self.ui.cmSelectButton.clicked.connect(
            partial(self.showDisplay, self.selectWindow))

        self.pathToAmplitudeWindow = self.getPath("amplitude.ui")

        # maps cryomodule names to their checkboxes
        self.cryomoduleRadioButtons = {}  # type: Dict[str, QRadioButton]

        # maps cryomodule names to their buttons
        self.cryomoduleButtons = {}  # type: Dict[str, QPushButton]

        # maps checkboxes to their buttons
        self.cryomoduleRadioButtonMap = {
        }  # type: Dict[QRadioButton, QPushButton]

        # maps cryomodule names to the cavity display
        self.buttonDisplays = {}  # type: Dict[str, Display]

        # maps cyomodule names to desired cavity amplitudes
        self.desiredCavAmpLineEdits = {}  # type: Dict[str, List[QLineEdit]]

        self.maxAmplitudeLabels: Dict[str, PyDMLabel] = {}

        # maps cryomodule names to cavity groupboxes
        self.cavityGroupBoxes = {}  # type: Dict[str, List[QGroupBox]]

        # maps cryomodule names to select all cavities checkbox
        self.selectAllCavitiesCheckboxes = {}  # type: Dict[str, QCheckBox]

        self.selectedDisplayCM: Optional[str] = None
        self.selectedCM: Optional[str] = None

        self.sectors = [[], [], [], []]  # type: List[List[str]]

        self.radioButtonSectorMap: Dict[QRadioButton, int] = {}
        self.buttonGroup = QButtonGroup(self)
        self.populateRadioButtons()

        for sector in self.sectors:
            self.calibrationOptionsWindow.ui.cryomoduleComboBox.addItems(
                sector)

        self.calibrationOptionsWindow.ui.cavityComboBox.addItem("ALL")
        for i in range(1, 9):
            self.calibrationOptionsWindow.ui.cavityComboBox.addItem(str(i))

        self.calibrationSanityCheck = QMessageBox()
        self.setupSanityCheck(self.calibrationSanityCheck,
                              self.calibrationStatus)

        self.setupButtons()

        self.calibration = None

        self.valveParams = {}

        self.selectedCryomoduleObject: Q0Cryomodule = None

    def setupLiveSignals(self):
        self.plots.clearCurves()
        self.plots.valvePlot.addYChannel(self.selectedCryomoduleObject.valvePV)

    def setupCalibrationOptionsWindow(self):
        self.calibrationOptionsWindow.ui.cryomoduleComboBox.currentTextChanged.connect(
            self.populateCryomoduleCalibrationOptions)
        self.calibrationOptionsWindow.ui.cavityComboBox.currentTextChanged.connect(
            self.populateCavityCalibrationOptions)
        self.calibrationOptionsWindow.ui.optionView.setModel(
            self.calibrationOptionModel)
        self.calibrationOptionsWindow.ui.optionView.selectionModel(
        ).selectionChanged.connect(self.selectCalibration)
        self.calibrationOptionsWindow.ui.loadButton.clicked.connect(
            self.loadCalibration)

    def setupRfDataWindow(self):
        self.rfResultsWindow = Display(ui_filename=self.getPath("results.ui"),
                                       macros={"label": "dLL/dt Slope"})
        self.rfResultsWindow.ui.dataLayout.addWidget(self.rfLiquidLevelCanvas)
        self.rfResultsWindow.ui.lineFitLayout.addWidget(self.rfLineFitCanvas)

    def setupCalibrationDataWindow(self):
        self.calibrationResultsWindow = Display(
            ui_filename=self.getPath("results.ui"),
            macros={"label": "dLL/dt Slope"})
        self.calibrationResultsWindow.ui.dataLayout.addWidget(
            self.calibrationLiquidLevelCanvas)
        self.calibrationResultsWindow.ui.lineFitLayout.addWidget(
            self.calibrationLineFitCanvas)

    def getPath(self, fileName):
        return path.join(self.pathHere, fileName)

    # This is some convoluted bullshit
    def selectCalibration(self):

        self.calibrationSelection[
            "CM"] = self.calibrationOptionsWindow.ui.cryomoduleComboBox.currentText(
            )

        calibrationTableView = self.calibrationOptionsWindow.ui.optionView  # type: QTableView
        row = calibrationTableView.selectionModel().selectedRows().pop().row()

        for column in range(self.calibrationOptionModel.columnCount()):
            data = self.calibrationOptionModel.index(row, column).data()
            header = self.calibrationOptionModel.horizontalHeaderItem(
                column).text()
            self.calibrationSelection[header] = data

        # self.calibrationStatus.setStyleSheet("color: blue;")
        self.calibrationStatus.setText(
            "CM {CM} calibration from {START} selected but not loaded".format(
                START=self.calibrationSelection["Start"],
                CM=self.calibrationSelection["CM"]))

        self.calibrationOptionsWindow.ui.loadButton.setEnabled(True)

    def loadCalibration(self):

        linacName = CM_LINAC_MAP[self.calibrationSelection["CM"]]
        cryomodule = Q0_LINAC_OBJECTS[linacName]
        self.calibration: CalibDataSession = cryomodule.addCalibDataSessionFromGUI(
            self.calibrationSelection)

        redrawAxis(self.calibrationLiquidLevelCanvas,
                   title="Liquid Level vs. Time",
                   xlabel="Unix Time (s)",
                   ylabel="Downstream Liquid Level (%)")

        redrawAxis(self.calibrationLineFitCanvas,
                   title="Liquid Level Rate of Change vs. Heat Load",
                   xlabel="Heat Load (W)",
                   ylabel="dLL/dt (%/s)")

        for run in self.calibration.dataRuns:
            self.calibrationLiquidLevelCanvas.axes.plot(run.timeStamps,
                                                        run.data,
                                                        label=run.label)
            self.calibrationLiquidLevelCanvas.axes.plot(
                run.timeStamps,
                [run.slope * x + run.intercept for x in run.timeStamps])

        self.calibrationLineFitCanvas.axes.plot(
            self.calibration.runElecHeatLoadsAdjusted,
            self.calibration.adjustedRunSlopes,
            marker="o",
            linestyle="None",
            label="Heater Calibration Data")

        slopeStr = "{slope} %/(s*W)".format(slope=self.calibration.calibSlope)
        self.calibrationResultsWindow.ui.slope.setText(slopeStr)

        self.calibrationLineFitCanvas.axes.plot(
            self.calibration.runElecHeatLoadsAdjusted, [
                self.calibration.calibSlope * x
                for x in self.calibration.runElecHeatLoadsAdjusted
            ],
            label=slopeStr)

        self.calibrationLineFitCanvas.axes.legend(loc='best')
        self.calibrationLiquidLevelCanvas.axes.legend(loc='best')

        self.calibrationStatus.setStyleSheet("color: green;")
        self.calibrationStatus.setText(
            "CM {CM} calibration from {START} loaded".format(
                START=self.calibrationSelection["Start"],
                CM=self.calibrationSelection["CM"]))

        self.rfGroupBox.setEnabled(True)

    def setupCalibrationTable(self):
        self.calibrationOptionModel.clear()
        parent = path.abspath(path.join(self.pathHere, pardir))
        cmName = self.calibrationOptionsWindow.ui.cryomoduleComboBox.currentText(
        )
        calibrationFolder = path.join(path.join(parent, "calibrations"),
                                      "cm{NAME}".format(NAME=cmName))
        return cmName, calibrationFolder

    def populateCryomoduleCalibrationOptions(self):

        cmName, calFolderPath = self.setupCalibrationTable()

        calibrationFile = path.join(
            calFolderPath,
            FULL_CALIBRATION_FILENAME_TEMPLATE.format(CM=cmName))

        if not path.isfile(calibrationFile):
            return

        self.populateCalibrationTable(calibrationFile)

    def populateCavityCalibrationOptions(self):
        cavity = self.calibrationOptionsWindow.ui.cavityComboBox.currentText()

        if cavity == "ALL":
            self.populateCryomoduleCalibrationOptions()
            return

        cmName, calFolderPath = self.setupCalibrationTable()
        calibrationFile = path.join(
            calFolderPath,
            CAVITY_CALIBRATION_FILENAME_TEMPLATE.format(CM=cmName, CAV=cavity))
        if not path.isfile(calibrationFile):
            print(calibrationFile)
            return

        self.populateCalibrationTable(calibrationFile)

    def populateCalibrationTable(self, calibrationFilePath):
        with open(calibrationFilePath) as calibrationFile:
            data: List[dict] = json.load(calibrationFile)

            header = list(data[0].keys())
            self.calibrationOptionModel.setHorizontalHeaderLabels(header)
            for entry in data:
                items = []
                for column in header:
                    items.append(QStandardItem(entry[column]))
                self.calibrationOptionModel.appendRow(items)

        self.calibrationOptionsWindow.ui.optionView.resizeColumnsToContents()

    def setupFrames(self):
        groupBoxes = {}  # type: Dict[str, QGroupBox]
        for groupBox in self.ui.dialogues.findChildren(QGroupBox):
            if groupBox.accessibleName():
                groupBoxes[groupBox.accessibleName()] = groupBox
        self.calibrationGroupBox = groupBoxes["calibrationGroupBox"]
        self.rfGroupBox = groupBoxes["rfGroupBox"]

        # For some reason, I need to disable these here vs in designer or the
        # conditional enabling doesn't work
        self.calibrationGroupBox.setEnabled(False)
        self.rfGroupBox.setEnabled(False)

    def setupLabels(self):
        name2label = {}  # type: Dict[str, QLabel]
        for label in self.ui.dialogues.findChildren(QLabel):
            name2label[label.accessibleName()] = label
        self.calibrationStatus = name2label["calibrationLabel"]

    def setupButtons(self):
        name2button = {}  # type: Dict[str, QPushButton]
        # Get all the buttons from my template repeater and figure out which
        # one's which with the accessible names (set in dialogues.json)
        for button in self.ui.dialogues.findChildren(QPushButton):
            name2button[button.accessibleName()] = button

        name2button["newCalibrationButton"].clicked.connect(
            self.calibrationSanityCheck.show)
        name2button["loadCalibrationButton"].clicked.connect(
            partial(self.showDisplay, self.calibrationOptionsWindow))
        name2button["calibrationDataButton"].clicked.connect(
            partial(self.showDisplay, self.calibrationResultsWindow))

    def setupSettingsWindow(self):
        self.settingsWindow.ui.valvePosSearchStart.setDateTime(datetime.now())
        self.settingsWindow.ui.valvePosSearchEnd.setDateTime(datetime.now() -
                                                             timedelta(
                                                                 hours=24))
        self.ui.settingsButton.clicked.connect(
            partial(self.showDisplay, self.settingsWindow))

    def populateRadioButtons(self):

        displays: List[PyDMEmbeddedDisplay] = [
            self.selectWindow.ui.cryomodulesL0B,
            self.selectWindow.ui.cryomodulesL1B,
            self.selectWindow.ui.cryomodulesL2B,
            self.selectWindow.ui.cryomodulesL3B
        ]

        for sector, display in enumerate(displays):
            display.loadWhenShown = False

            groupbox: QVBoxLayout = display.findChildren(QVBoxLayout).pop()
            repeater: PyDMTemplateRepeater = groupbox.itemAt(0).widget()

            pairs: List[QHBoxLayout] = repeater.findChildren(QHBoxLayout)

            for pair in pairs:
                button: QPushButton = pair.itemAt(1).widget()
                name = button.text().split()[1]
                self.cryomoduleButtons[name] = button
                button.clicked.connect(
                    partial(self.openAmplitudeWindow, name, sector))

                radioButton: QRadioButton = pair.itemAt(0).widget()
                self.cryomoduleRadioButtons[name] = radioButton

                self.cryomoduleRadioButtonMap[radioButton] = button

                self.buttonGroup.addButton(radioButton)

                radioButton.toggled.connect(
                    partial(self.cryomoduleRadioButtonToggled, name))

                self.sectors[sector].append(name)
                self.radioButtonSectorMap[radioButton] = sector

    def setupSanityCheck(self, sanityCheckWindow, statusLabel):
        def takeMeasurement(decision):
            if "No" in decision.text():
                print("Measurement canceled")
                return
            else:
                print("Taking new measurement")
                self.showDisplay(self.liveSignalsWindow)
                statusLabel.setStyleSheet("color: blue;")
                statusLabel.setText("Starting Procedure")
                self.takeNewCalibration()

        sanityCheckWindow.setWindowTitle("Sanity Check")
        sanityCheckWindow.setText(
            "Are you sure? This will take multiple hours")
        sanityCheckWindow.setIcon(QMessageBox.Warning)
        sanityCheckWindow.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
        sanityCheckWindow.setDefaultButton(QMessageBox.No)
        sanityCheckWindow.buttonClicked.connect(takeMeasurement)

    @Slot()
    def takeNewCalibration(self):
        self.selectedCryomoduleObject.takeNewCalibration(
            int(self.initialCalibrationHeatLoadLineEdit.text()))

    @Slot()
    def showDisplay(self, display):
        # type: (QWidget) -> None
        display.show()

        # brings the display to the front
        display.raise_()

        # gives the display focus
        display.activateWindow()

    @Slot()
    # TODO needs to check all cavities
    def cavityToggled(self, cm):
        # type: (str) -> None

        statusList = list(
            map(lambda groupbox: groupbox.isChecked(),
                self.cavityGroupBoxes[cm]))
        allChecked = reduce(
            (lambda isChecked1, isChecked2: isChecked1 and isChecked2),
            statusList)

        if statusList.count(statusList[0]) != len(statusList):
            self.selectAllCavitiesCheckboxes[cm].setCheckState(1)

        else:
            self.selectAllCavitiesCheckboxes[cm].setCheckState(
                0 if not allChecked else 2)

        self.updateOutputBasedOnDefaultConfig(cm, allChecked)

    @Slot()
    # TODO use AMAX/ops limit
    def checkIfAllCavitiesAtDefault(self, cm, updateOutput=True):
        # type: (str, bool) -> bool

        isDefault = True

        for idx, lineEdit in enumerate(self.desiredCavAmpLineEdits[cm]):
            if lineEdit.text():
                try:
                    amplitude = float(lineEdit.text())
                    maxAmp = float(self.maxAmplitudeLabels[cm][idx].text())
                    if amplitude > maxAmp:
                        lineEdit.clear()
                    elif amplitude != maxAmp:
                        isDefault = False

                except ValueError:
                    lineEdit.clear()
                    isDefault = False
            else:
                isDefault = False

        if updateOutput:
            self.updateOutputBasedOnDefaultConfig(cm, isDefault)

        return isDefault

    def updateOutputBasedOnDefaultConfig(self, cm, isDefault):
        starredName = "{CM}*".format(CM=cm)

        self.selectedDisplayCM = cm if isDefault else starredName

        self.updateSelectedText()

    @Slot()
    def openAmplitudeWindow(self, cm, sector):
        # type: (str, int) -> None

        # Put this here to speed things up (it was suuuuuuuper slow trying to do
        # this on startup)
        if cm not in self.buttonDisplays:
            displayCM = Display(ui_filename=self.pathToAmplitudeWindow,
                                macros={
                                    "cm": cm,
                                    "area": "L{SECTOR}B".format(SECTOR=sector)
                                })
            repeater = displayCM.ui.cavityRepeater

            lineEdits = []
            groupBoxes = []
            amaxLabels = []

            for cav in range(8):
                item = repeater.layout().itemAt(cav)  # type: QWidgetItem
                displayCav = item.widget()  # type: Display

                lineEdit = displayCav.ui.desiredAmplitude  # type: QLineEdit
                validator = QDoubleValidator(0.0, 21.0, 2, lineEdit)
                validator.setNotation(QDoubleValidator.StandardNotation)
                lineEdit.setValidator(validator)
                amaxLabel = displayCav.ui.amaxLabel

                try:
                    maxAmplitude = float(amaxLabel.text())
                except (TypeError, ValueError):
                    maxAmplitude = 0

                lineEdit.setText(str(maxAmplitude))
                lineEdit.textChanged.connect(
                    partial(self.checkIfAllCavitiesAtDefault, cm))
                lineEdits.append(lineEdit)

                groupBox = displayCav.ui.cavityGroupbox  # type: QGroupBox
                groupBox.toggled.connect(partial(self.cavityToggled, cm))
                groupBoxes.append(groupBox)

                amaxLabels.append(amaxLabel)

                restoreDefaultButton: QPushButton = displayCav.ui.restoreDefaultButton
                restoreDefaultButton.clicked.connect(
                    partial(self.restoreDefault, lineEdit,
                            displayCav.ui.amaxLabel))

            self.desiredCavAmpLineEdits[cm] = lineEdits
            self.buttonDisplays[cm] = displayCM
            self.cavityGroupBoxes[cm] = groupBoxes
            self.maxAmplitudeLabels[cm] = amaxLabels

            selectAllCheckbox = displayCM.ui.selectAllCheckbox  # type: QCheckBox
            self.selectAllCavitiesCheckboxes[cm] = selectAllCheckbox
            selectAllCheckbox.stateChanged.connect(
                partial(self.selectAllCavitiesToggled, cm))

        self.buttonDisplays[cm].show()

    @Slot()
    def selectAllCavitiesToggled(self, cm):
        state = self.selectAllCavitiesCheckboxes[cm].checkState()

        if state == 0:
            for cavityGroupbox in self.cavityGroupBoxes[cm]:
                cavityGroupbox.setChecked(False)
        elif state == 2:
            for cavityGroupbox in self.cavityGroupBoxes[cm]:
                cavityGroupbox.setChecked(True)

    @Slot()
    def restoreDefault(self, desiredAmplitude: QLineEdit,
                       amaxLabel: PyDMLabel):
        try:
            maxAmplitude = float(amaxLabel.text())
        except (ValueError, TypeError):
            maxAmplitude = 0

        desiredAmplitude.setText(str(maxAmplitude))

    def updateSelectedText(self):
        if not self.selectedDisplayCM:
            self.ui.cmSelectionLabel.setStyleSheet("color: red;")
            self.ui.cmSelectionLabel.setText("No Cryomodules Selected")
            self.calibrationGroupBox.setEnabled(False)
            self.rfGroupBox.setEnabled(False)

        else:
            self.ui.cmSelectionLabel.setStyleSheet("color: green;")
            self.ui.cmSelectionLabel.setText(self.selectedDisplayCM)
            self.calibrationGroupBox.setEnabled(True)

    @Slot()
    # TODO check if all checkboxes in sector are clicked
    def cryomoduleRadioButtonToggled(self, cryomodule):
        # type:  (str) -> None

        radioButton = self.cryomoduleRadioButtons[cryomodule]
        button = self.cryomoduleButtons[cryomodule]

        if radioButton.isChecked():
            button.setEnabled(True)

            isDefault = (self.checkIfAllCavitiesAtDefault(cryomodule, False) if
                         cryomodule in self.desiredCavAmpLineEdits else True)

            self.selectedDisplayCM = cryomodule + ("*"
                                                   if not isDefault else "")
            self.selectedCM = cryomodule

            linacIdx = CM_LINAC_MAP[self.selectedCM]
            self.selectedCryomoduleObject = Q0_LINAC_OBJECTS[
                linacIdx].cryomodules[self.selectedCM]

            linacIdx = CM_LINAC_MAP[cryomodule]
            cryomoduleObj = Q0_LINAC_OBJECTS[linacIdx].cryomodules[cryomodule]
            self.plots.updateChannels(cryomoduleObj)

        else:
            button.setEnabled(False)

        self.updateSelectedText()
        self.calibrationOptionsWindow.cryomoduleComboBox.setCurrentText(
            self.selectedCM)

    @Slot()
    def selectAllSectorCryomodules(self, selectAllCheckbox, sector):
        # type:  (QCheckBox, int) -> None

        sectorLabel = "L{SECTOR}B".format(SECTOR=sector)

        if selectAllCheckbox.checkState() == 2:

            for name in self.sectors[sector]:
                self.cryomoduleRadioButtons[name].setChecked(True)
                self.selectedDisplayCM.discard(name)

            if (sectorLabel + "*") not in self.selectedDisplayCM:
                self.selectedDisplayCM.add(sectorLabel)

        elif selectAllCheckbox.checkState() == 0:
            for name in self.sectors[sector]:
                self.cryomoduleRadioButtons[name].setChecked(False)

            self.selectedDisplayCM.discard(sectorLabel)
            self.selectedDisplayCM.discard(sectorLabel + "*")

        self.updateSelectedText()
Esempio n. 12
0
class MyWindow(QMainWindow):
    def __init__(self):
        super(MyWindow, self).__init__()
        self.lz = []
        self.ts = 0
        self.zahlenListe = []
        dir = os.path.dirname(sys.argv[0])
        self.settingsfile = "%s/%s" % (dir, "Lotto.conf")
        self.zahlen = "%s/%s" % (dir, "zahlen.txt")
        print(self.settingsfile)
        self.settings = QSettings(self.settingsfile, QSettings.IniFormat)
        self.setStyleSheet(stylesheet(self))
        self.lottolink = 'https://www.dielottozahlende.net/lotto-6-aus-49'
        self.mysuper = 5
        self.model = QStandardItemModel(self)
        self.model.setRowCount(7)
        self.tableview = QTableView(self)
        self.tableview.setSortingEnabled(False)
        self.tableview.setGridStyle(1)
        if int(sys.version[0]) > 2:
            self.tableview.setFixedHeight(149)
        else:
            self.tableview.setFixedHeight(171)
        self.tableview.setSizeAdjustPolicy(QAbstractScrollArea.AdjustIgnored)
        self.tableview.horizontalHeader().setStretchLastSection(True)
        self.tableview.verticalHeader().setStretchLastSection(False)
        self.tableview.setCornerButtonEnabled(True)
        self.tableview.setShowGrid(True)
        self.tableview.setModel(self.model)
        self.tableview.hideRow(6)
        self.tableview.hideColumn(13)
        self.pushButtonLoad = QPushButton()
        self.pushButtonLoad.setText("Zahlen holen")
        self.pushButtonLoad.setIcon(QIcon.fromTheme("view-refresh"))
        self.pushButtonLoad.clicked.connect(self.getLotto)
        self.pushButtonLoad.setFixedWidth(110)
        self.pushButtonLoad.setFixedHeight(24)

        self.zahlenAction = QAction(QIcon.fromTheme("edit"),
                                    "Editor",
                                    self,
                                    triggered=self.edit_Tipps,
                                    shortcut="F5")
        self.addAction(self.zahlenAction)

        self.superAction = QAction(QIcon.fromTheme("edit"),
                                   "Superzahl",
                                   self,
                                   triggered=self.setMySuper,
                                   shortcut="F6")
        self.addAction(self.superAction)

        self.infoAction = QAction(QIcon.fromTheme("help-info"),
                                  "Information",
                                  self,
                                  triggered=self.showInfo,
                                  shortcut="F1")
        self.addAction(self.infoAction)

        self.lbl = QLabel()

        self.hbox = QHBoxLayout()
        self.hbox.addWidget(self.pushButtonLoad)

        grid = QVBoxLayout()
        grid.setSpacing(10)
        grid.addLayout(self.hbox)
        grid.addWidget(self.tableview)
        grid.addWidget(self.lbl)

        mywidget = QWidget()
        mywidget.setLayout(grid)
        self.setCentralWidget(mywidget)

        self.readSettings()
        self.tableview.resizeColumnsToContents()
        self.tableview.resizeRowsToContents()
        self.setHeaders()

        print("Wilkommen bei Lotto")
        self.statusBar().showMessage(
            "%s %s" % ("Willkommen bei LottoCheck",
                       " *** F5 Lottozahlen ändern *** F6 Superzahl ändern"),
            0)

    def findTableItems(self):
        model = self.tableview.model()
        self.tableview.selectionModel().clearSelection()
        print(self.zahlenListe)
        for column in range(12):
            start = model.index(0, column)
            for zahl in self.zahlenListe:

                matches = model.match(start, Qt.DisplayRole, str(zahl), 1,
                                      Qt.MatchExactly)
                if matches:
                    index = matches[0]
                    self.tableview.selectionModel().select(
                        index, QItemSelectionModel.Select)

    def saveNumbers(self):
        print(self.model.columnCount(), "Columns")
        textData = ""
        fileName, _ = QFileDialog.getSaveFileName(self, "Open File",
                                                  "~/lottozahlen.csv",
                                                  "CSV Files (*.csv)")
        if fileName:
            print("%s %s" % (fileName, "saved"))
            f = open(fileName, 'w')
            for col in range(self.model.columnCount()):
                textData += str(self.model.horizontalHeaderItem(col).text())
                textData += "\t"
            textData += "\n"
            for row in range(self.model.rowCount() - 1):
                for col in range(self.model.columnCount()):
                    textData += str(self.model.data(self.model.index(row,
                                                                     col)))
                    textData += "\t"
                textData += "\n"
            f.write(textData)
            f.close()

    def edit_Tipps(self):
        self.edWin = Editor()
        with open(self.zahlen, 'r') as f:
            text = f.read()
            self.edWin.tipp_editor.setPlainText(text)
            f.close()
        self.edWin.isModified = False

    def showInfo(self):
        link = "<p><a title='Axel Schneider' href='http://goodoldsongs.jimdo.com' target='_blank'> \
                Axel Schneider</a></p>"
        message = "<h2>LottoCheck 1.0</h2><h4>6 aus 49</h4>created by " + link + " with PyQt5<br>©September 2019<br>" \
                            + "<br>Copyright © 2017 The Qt Company Ltd and other contributors." \
                            + "<br>Qt and the Qt logo are trademarks of The Qt Company Ltd."  \
                            + "<br><br>F5 = Tipps ändern" \
                            + "<br>F6 = Superzahl ändern"
        self.msgbox(message)

    def msgbox(self, message):
        msg = QMessageBox(1, "Information", message, QMessageBox.Ok)
        msg.exec_()

    def getLotto(self):
        if not self.lz == []:
            print("values already here", self.lz)
            self.compare()
        else:
            self.lottolink = "https://www.lotto.de/lotto-6aus49/lottozahlen"
            print("getting Values")
            source = requests.get(self.lottolink).text
            soup = bsoup(source, 'lxml')
            lottoliste = []

            for td in soup.find_all(class_='LottoBall__circle'):
                lottoliste.append(td.text)

            result = lottoliste
            self.zahlenListe = result[:6]
            self.lz = result
            theSuper = lottoliste[6]
            print("Gewinnzahlen:\n", self.zahlenListe)
            self.ts = theSuper
            print("theSuper", self.ts)
            for i in range(6):
                self.model.setData(self.model.index(i, 12), result[i])
                self.model.item(i, 12).setTextAlignment(Qt.AlignCenter)
            self.compare()

    def getSpiel77(self):
        self.lottolink = "https://www.lotto.de/lotto-6aus49/lottozahlen"
        source = requests.get(self.lottolink).text
        soup = bsoup(source, 'lxml')
        result = soup.find(class_='WinningNumbersAdditionalGame__text').text

        print("Spiel 77: ", result)

        super6 = soup.find(class_='WinningNumbersAdditionalGame__text'
                           ).parent.find_next_siblings()[0].text
        print("Super 6: ", super6)

        date = soup.find(class_="WinningNumbers__date").text

        self.lbl.setText(self.lbl.text() + "\n" + date + "\n\n" +
                         result.replace("Spiel 77", "Spiel 77: ") + "\n" +
                         super6.replace("Super 6", "Super 6: "))

    def compare(self):
        ### compare all tipps
        print("self.lz: ", self.lz)
        self.lz = [int(x) for x in self.lz[:6]]
        print(self.mysuper, self.lz)
        self.lbl.clear()
        tipp = []
        for x in range(len(self.tliste)):
            t = []
            tipp = [int(x) for x in self.tliste[x]]
            #            print(tipp)
            for a in self.lz:
                if int(a) in tipp:
                    print(a, "in tipp", str(x + 1))
                    t.append(a)

            rtext = ""
            print("len(t) ", len(t))
            if len(t) == 2 and self.mysuper == self.ts:
                rtext += self.lbl.text()
                rtext += '\ngewonnen in Tipp '
                rtext += str(int(x) + 1)
                rtext += " : "
                rtext += str(t)
                rtext += " *** "
                rtext += str(len(t))
                rtext += "er ***"
                rtext += ' + Superzahl'
                self.lbl.setText(rtext)
            elif len(t) > 2:
                if self.mysuper == self.ts:
                    rtext += self.lbl.text()
                    rtext += '\ngewonnen in Tipp '
                    rtext += str(int(x) + 1)
                    rtext += " : "
                    rtext += str(t)
                    rtext += " *** "
                    rtext += str(len(t))
                    rtext += "er ***"
                    rtext += ' + Superzahl'
                    self.lbl.setText(rtext)
                else:
                    rtext += self.lbl.text()
                    rtext += '\ngewonnen in Tipp '
                    rtext += str(int(x) + 1)
                    rtext += " : "
                    rtext += str(t)
                    rtext += " *** "
                    rtext += str(len(t))
                    rtext += "er ***"
                    self.lbl.setText(rtext)

        if self.lbl.text() == "":
            self.lbl.setText("leider nichts gewonnen ...\n")
        self.statusBar().showMessage(
            "%s %s %s %s" %
            ("Gewinnzahlen: ",
             (', '.join(str(x)
                        for x in self.lz)), " *** Superzahl: ", str(self.ts)),
            0)
        self.getSpiel77()
        self.findTableItems()

    def setHeaders(self):
        self.tableview.horizontalHeader().setVisible(True)
        self.tableview.verticalHeader().setVisible(False)
        for x in range(self.model.columnCount() - 1):
            self.model.setHeaderData(x, Qt.Horizontal,
                                     "%s %s" % ("Tipp", (x + 1)))
        self.model.setHeaderData(self.model.columnCount() - 1, Qt.Horizontal,
                                 "Gewinnzahlen")
        self.tableview.setAlternatingRowColors(True)
        self.tableview.resizeColumnsToContents()
        self.tableview.resizeRowsToContents()

    def closeEvent(self, event):
        print("Goodbye ...")
        self.writeSettings()

    def setMySuper(self):
        s = int(self.mysuper)
        dlg = QInputDialog()
        ms, ok = dlg.getInt(self, 'Superzahl:', "", s, 0, 9, 1, Qt.Dialog)
        if ok:
            self.mysuper = ms
            print("Superzahl =", self.mysuper)

    def readSettings(self):
        if self.settings.contains("mysuper"):
            self.mysuper = self.settings.value("mysuper")
        else:
            self.setMySuper()
        print("Superzahl:", self.mysuper)
        self.tliste = []
        with open(self.zahlen, 'r') as f:
            text = f.read()
            f.close()
            for line in text.splitlines():
                self.tliste.append(line.split(","))
            self.model.setColumnCount(len(self.tliste) + 1)
            for x in range(0, len(self.tliste)):
                tipp = self.tliste[x]
                for i in range(len(tipp)):
                    self.model.setData(self.model.index(i, x), tipp[i])
                    self.model.item(i, x).setTextAlignment(Qt.AlignCenter)

    def writeSettings(self):
        self.settings.setValue("mysuper", self.mysuper)
Esempio n. 13
0
class SchemaWidget(QWidget):
    def __init__(self, connection_helper):
        super().__init__()
        self.connection_helper = connection_helper
        self.model = QStandardItemModel()
        self.edit_cell_value = None
        self.schema = None
        self.model.itemChanged.connect(self.edit_cell)
        self.column_labels = ["Field", "Type", "Unsigned", "Zerofill",
                              "Allow Null", "Key", "Default", "Extra"]

        # need index form for adding new keys. Not a separate table..just a button
        # need columns resized
        self.init_ui()
        self.refresh()
        
    def init_ui(self):
        uic.loadUi(ui_file, self)
        self.RefreshButton.clicked.connect(self.refresh)
        self.AddRowButton.clicked.connect(self.add_row)
        self.RemoveRowButton.clicked.connect(self.remove_row)
        self.SchemaTable.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.SchemaTable.setSelectionMode(QAbstractItemView.SingleSelection)

    def add_row(self):
        print('')

    def remove_row(self):
        reply = QMessageBox.question(self, 'Wait!', f"Are you sure you want to delete this column?", 
        QMessageBox.Yes|QMessageBox.No)

        if reply == QMessageBox.Yes:
            rows = self.SchemaTable.selectionModel().selectedRows()
            for row in rows:
                row_index = row.row()
                column_name = self.model.item(row_index, 0).text()
                self.connection_helper.drop_table_column(None, column_name)
        self.refresh()

    def edit_cell(self, item):
        row = item.row()
        row_values = {}
        table_column = self.model.item(row, 0).text()
        simple_type = self.schema['columns'][table_column]['Simple_Type']
        for column_index in range(self.model.columnCount()):
            column_header = self.model.horizontalHeaderItem(column_index).text()
            item = self.model.item(row, column_index)
            if item.isCheckable():
                value = True if item.checkState() == 2 else False
            else:
                value = item.data(Qt.EditRole)
            row_values[column_header] = value
        result = self.connection_helper.modify_table_column(None, row_values, simple_type)
        if isinstance(result, str):
            QMessageBox.about(self, 'Oops!', f'You have an error: \n {result}')
            self.refresh()

    def refresh(self):
        self.model.clear()
        self.schema = self.connection_helper.get_standardized_schema(None, None)
        self.model.setHorizontalHeaderLabels(self.column_labels)
        row_index = 0
        for key, val in self.schema['columns'].items():
            items = []

            standard_item = QStandardItem()
            standard_item.setData(QVariant(key), Qt.EditRole)
            items.append(standard_item)

            standard_item = QStandardItem()
            standard_item.setData(QVariant(val['Type'].upper()), Qt.EditRole)
            items.append(standard_item)

            standard_item = QStandardItem()
            if val['Simple_Type'] != 'number':
                standard_item.setCheckable(False)
            else:
                standard_item.setCheckable(True)
            if val['Unsigned'] is True:
                standard_item.setCheckState(Qt.CheckState.Checked)
            items.append(standard_item)

            standard_item = QStandardItem()
            if val['Simple_Type'] != 'number':
                standard_item.setCheckable(False)
            else:
                standard_item.setCheckable(True)
            if val['Zerofill'] is True:
                standard_item.setCheckState(Qt.CheckState.Checked)
            items.append(standard_item)

            standard_item = QStandardItem()
            if val['Null'] is True:
                standard_item.setCheckState(Qt.CheckState.Checked)
            standard_item.setCheckable(True)
            items.append(standard_item)

            standard_item = QStandardItem()
            standard_item.setEditable(False)
            standard_item.setData(QVariant(val['Key']), Qt.EditRole)
            items.append(standard_item)

            standard_item = QStandardItem()
            standard_item.setData(QVariant(val['Default']), Qt.EditRole)
            items.append(standard_item)

            standard_item = QStandardItem()
            standard_item.setData(QVariant(val['Extra']), Qt.EditRole)
            items.append(standard_item)

            self.model.insertRow(row_index, items)
            row_index += 1
        self.SchemaTable.setModel(self.model)
        self.SchemaTable.resizeColumnsToContents()

    def update(self):
        self.refresh()
Esempio n. 14
0
class HealthMonitorWindow(QDialog, Ui_HealthMonitor):
    def __init__(self, parent):
        super().__init__(parent, get_modeless_dialog_flags())

        self.setupUi(self)

        self.ipcon_available = False

        self.button_save_report_to_csv_file.clicked.connect(
            self.save_report_to_csv_file)
        self.button_close.clicked.connect(self.hide)

        self.fixed_column_names = [
            'Name', 'UID', 'Position', 'FW Version', 'Metric Errors'
        ]
        self.dynamic_column_names = []
        self.metric_errors = {}  # by uid
        self.old_values = {}  # by uid, by metric name

        self.tree_view_model = QStandardItemModel(self)

        self.tree_view_proxy_model = DevicesProxyModel(self)
        self.tree_view_proxy_model.setSourceModel(self.tree_view_model)
        self.tree_view.setModel(self.tree_view_proxy_model)
        self.tree_view.setSortingEnabled(True)
        self.tree_view.header().setSortIndicator(2, Qt.AscendingOrder)
        self.tree_view.setExpandsOnDoubleClick(False)

        self.delayed_refresh_tree_view_timer = QTimer(self)
        self.delayed_refresh_tree_view_timer.timeout.connect(
            self.delayed_refresh_tree_view)
        self.delayed_refresh_tree_view_timer.setInterval(100)

        inventory.info_changed.connect(
            lambda: self.delayed_refresh_tree_view_timer.start())

        self.update_metric_values_timer = QTimer(self)
        self.update_metric_values_timer.timeout.connect(
            lambda: self.update_metric_values())
        self.update_metric_values_timer.setInterval(1000)
        self.update_metric_values_timer.start()

        self.refresh_tree_view()
        self.update_ui_state()

    def delayed_refresh_tree_view(self):
        self.delayed_refresh_tree_view_timer.stop()

        if self.isVisible():
            self.refresh_tree_view()

    def refresh_tree_view(self):
        sis = self.tree_view.header().sortIndicatorSection()
        sio = self.tree_view.header().sortIndicatorOrder()

        self.tree_view_model.clear()
        self.tree_view_model.setHorizontalHeaderLabels(self.fixed_column_names)

        self.dynamic_column_names = []
        column_offset = len(self.fixed_column_names)

        def create_and_append_row(info, parent):
            try:
                metric_names = info.plugin.get_health_metric_names()
            except:
                metric_names = []

            fw_version = QStandardItem(
                get_version_string(info.firmware_version_installed,
                                   replace_unknown='?'))

            if info.firmware_version_installed < info.firmware_version_latest:
                font = fw_version.font()
                font.setBold(True)
                fw_version.setFont(font)

            row = [
                QStandardItem(info.name),
                QStandardItem(info.uid),
                QStandardItem(info.position.title()), fw_version,
                QStandardItem(str(self.metric_errors.get(info.uid, 0)))
            ]

            for metric_name in metric_names:
                try:
                    i = self.dynamic_column_names.index(metric_name)
                except:
                    self.dynamic_column_names.append(metric_name)

                    i = len(self.dynamic_column_names) - 1

                    self.tree_view_model.setHorizontalHeaderItem(
                        column_offset + i, QStandardItem(metric_name))

                while len(row) <= column_offset + i:
                    row.append(QStandardItem())

                item = row[column_offset + i]

                old_timestamp, old_value = self.old_values.get(
                    info.uid, {}).get(metric_name, (None, None))

                item.setText(str(old_value if old_value != None else '-'))

                if old_timestamp != None and old_timestamp + SETTLE_DURATION >= time.monotonic(
                ):
                    font = item.font()

                    if not font.bold():
                        font.setBold(True)
                        item.setFont(font)

            for item in row:
                item.setFlags(item.flags() & ~Qt.ItemIsEditable)

            parent.appendRow(row)

            return row

        def recurse_on_device(info, parent):
            if not isinstance(info, DeviceInfo):
                return

            row = create_and_append_row(info, parent)

            for child in info.connections_values():
                recurse_on_device(child, row[0])

        for info in inventory.get_infos():
            if not isinstance(info, DeviceInfo):
                continue

            # if a device has a reverse connection, it will be handled as a child below
            if info.reverse_connection != None:
                continue

            row = create_and_append_row(info, self.tree_view_model)

            for child in info.connections_values():
                recurse_on_device(child, row[0])

        self.tree_view.setAnimated(False)
        self.tree_view.expandAll()
        self.tree_view.setAnimated(True)

        self.tree_view.setSortingEnabled(True)
        self.tree_view.header().setSortIndicator(sis, sio)
        self.tree_view.header().setStretchLastSection(False)
        self.tree_view.header().setSectionResizeMode(
            QHeaderView.ResizeToContents)

        self.update_metric_values()

    def get_health_metric_values_async(self, uid, index, metric_values):
        if self.tree_view_model.itemFromIndex(index) == None:
            # FIXME: item was removed in the meantime?
            return

        column_offset = len(self.fixed_column_names)

        for metric_name, metric_value in metric_values.items():
            try:
                i = self.dynamic_column_names.index(metric_name)
            except:
                # FIXME: column for this metric was removed in the meantime?
                continue

            sibling = index.sibling(index.row(), column_offset + i)

            if not sibling.isValid():
                # FIXME: item for this metric was removed in the meantime?
                continue

            item = self.tree_view_model.itemFromIndex(sibling)

            if item == None:
                # FIXME: item for this metric was removed in the meantime?
                continue

            self.update_item_text(uid, item, metric_name, metric_value)

        metric_name = 'Metric Errors'
        sibling = index.sibling(index.row(),
                                self.fixed_column_names.index(metric_name))
        item = self.tree_view_model.itemFromIndex(sibling)

        if item == None:
            # FIXME: item was removed in the meantime?
            return

        self.update_item_text(uid, item, metric_name,
                              self.metric_errors.get(uid, 0))

    def update_item_text(self, uid, item, metric_name, new_value):
        new_timestamp = time.monotonic()
        old_timestamp, old_value = self.old_values.get(uid, {}).get(
            metric_name, (None, None))
        new_value_str = str(new_value)

        if item.text() != new_value_str:
            item.setText(new_value_str)

        if old_value != new_value:
            if uid not in self.old_values:
                self.old_values[uid] = {
                    metric_name: (new_timestamp, new_value)
                }
            else:
                self.old_values[uid][metric_name] = (new_timestamp, new_value)

            font = item.font()

            if not font.bold():
                font.setBold(True)
                item.setFont(font)
        elif old_timestamp + SETTLE_DURATION < new_timestamp:
            font = item.font()

            if font.bold():
                font.setBold(False)
                item.setFont(font)

    def get_health_metric_values_error(self, uid, index):
        if uid in self.metric_errors:
            self.metric_errors[uid] += 1
        else:
            self.metric_errors[uid] = 1

        if self.tree_view_model.itemFromIndex(index) == None:
            # FIXME: item was removed in the meantime?
            return

        metric_name = 'Metric Errors'
        sibling = index.sibling(index.row(),
                                self.fixed_column_names.index(metric_name))
        item = self.tree_view_model.itemFromIndex(sibling)

        if item == None:
            # FIXME: item was removed in the meantime?
            return

        self.update_item_text(uid, item, metric_name, self.metric_errors[uid])

    def update_metric_values(self, parent=None):
        if not self.isVisible():
            return

        self.update_metric_values_timer.stop()

        if parent == None:
            parent = self.tree_view_model.invisibleRootItem()

        def make_async_call(info, uid, index):
            async_call(
                info.plugin.get_health_metric_values, None,
                lambda metric_values: self.get_health_metric_values_async(
                    uid, index, metric_values),
                lambda: self.get_health_metric_values_error(uid, index))

        # FIXME: avoid getter burst!
        for r in range(parent.rowCount()):
            child = parent.child(r, 0)
            index = child.index()
            uid = parent.child(r, 1).text()
            info = inventory.get_info(uid)

            if info == None:
                # FIXME: unknown UID, remove row or mark it as broken?
                continue

            make_async_call(info, uid, index)

            self.update_metric_values(parent=child)

        async_call(lambda: None, None, self.update_metric_values_timer.start,
                   None)

    def collect_metric_values(self, parent=None, indent=''):
        if parent == None:
            parent = self.tree_view_model.invisibleRootItem()

        rows = []

        for r in range(parent.rowCount()):
            row = []

            for c in range(parent.columnCount()):
                child = parent.child(r, c)

                if child == None:
                    text = ''
                else:
                    text = child.text()
                    font = child.font()

                    if c == 0:
                        text = indent + text

                    if font.bold():
                        text += ' <!>'

                row.append(text)

            rows.append(row)
            rows += self.collect_metric_values(parent=parent.child(r, 0),
                                               indent=indent + '  ')

        return rows

    def save_report_to_csv_file(self):
        date = datetime.now().replace(microsecond=0).isoformat().replace(
            'T', '_').replace(':', '-')
        filename = get_save_file_name(
            self, 'Save Report To CSV File',
            os.path.join(get_home_path(),
                         'brickv_health_report_{0}.csv'.format(date)))

        if len(filename) == 0:
            return

        c = 0
        header = []

        while True:
            item = self.tree_view_model.horizontalHeaderItem(c)

            if item == None:
                break

            header.append(item.text())

            c += 1

        rows = [header] + self.collect_metric_values()

        try:
            with open(filename, 'w', newline='') as f:
                csv.writer(f).writerows(rows)
        except Exception as e:
            QMessageBox.critical(
                self, 'Save Report To CSV File',
                'Could not save report to CSV file:\n\n' + str(e),
                QMessageBox.Ok)

    def update_ui_state(self):
        pass

    def set_ipcon_available(self, ipcon_available):
        self.ipcon_available = ipcon_available

        self.update_ui_state()