def init_table_model(table_model: QtGui.QStandardItemModel): sensor_count = 8 column0 = [QtGui.QStandardItem('Sensor ' + str(i + 1)) for i in range(0, sensor_count // 2)] column1 = [QtGui.QStandardItem("-") for i in range(0, sensor_count // 2)] column2 = [QtGui.QStandardItem('Sensor ' + str(i + 1)) for i in range(sensor_count // 2, sensor_count)] column3 = [QtGui.QStandardItem("-") for i in range(0, sensor_count // 2)] for item in column0 + column2: font = QtGui.QFont(item.font()) font.setBold(True) item.setFont(font) table_model.appendColumn(column0) table_model.appendColumn(column1) table_model.appendColumn(column2) table_model.appendColumn(column3)
class FavoriteTreeView(QTreeView): def __init__(self, window, parent=None): self.mainWindow = window try: super(FavoriteTreeView, self).__init__(parent) self.treeModel = QStandardItemModel() self.favorites = QStandardItem(ROOT_FAVORITES) self.buildFavoritesTree() self.providerQueryHistory = QStandardItem( ROOT_PROVIDERQUERYHISTORY) self.buildQueryHistory() self.treeModel.appendColumn( [self.favorites, self.providerQueryHistory]) self.treeModel.setHeaderData(0, Qt.Horizontal, 'Record') self.setModel(self.treeModel) self.setEditTriggers(QAbstractItemView.NoEditTriggers) self.setContextMenuPolicy(Qt.CustomContextMenu) self.customContextMenuRequested.connect(self.openContextMenu) self.doubleClicked.connect(self.onTreeItemDoubleClicked) self.setSelectionBehavior(QAbstractItemView.SelectItems) # 设置该控件可以多选 self.setSelectionMode(QAbstractItemView.ExtendedSelection) # self.clicked.connect(self.clickState) except Exception as e: STCLogger().e(e) def buildFavoritesTree(self): self.favorites.removeRows(0, self.favorites.rowCount()) rows = FavoriteDB.selectFavorites(" order by name asc") for row in rows: providerItem = QStandardItem(row[1] + " " + row[3]) providerItem.type = ITEM_TYPE_FAVORITES providerItem.id = row[0] providerItem.name = row[1] providerItem.url = row[2] providerItem.date = row[3] providerItem.historyId = row[4] urlItem = QStandardItem(row[2]) urlItem.type = ITEM_TYPE_URL providerItem.appendRow(urlItem) self.favorites.appendRow(providerItem) def buildQueryHistory(self): self.providerQueryHistory.removeRows( 0, self.providerQueryHistory.rowCount()) rows = FavoriteDB.selectHistory('order by date desc') for row in rows: providerItem = QStandardItem(row[1] + " " + row[3]) providerItem.type = ITEM_TYPE_HISTORY providerItem.id = row[0] providerItem.name = row[1] providerItem.url = row[2] providerItem.date = row[3] providerItem.favorite = row[4] urlItem = QStandardItem(row[2]) urlItem.type = ITEM_TYPE_URL providerItem.appendRow(urlItem) self.providerQueryHistory.appendRow(providerItem) @pyqtSlot(QModelIndex) def onTreeItemDoubleClicked(self, index): item = self.treeModel.itemFromIndex(index) dateTime = time.strftime("%Y/%m/%d %H:%M:%S", time.localtime(time.time())) if item.type == ITEM_TYPE_FAVORITES: #更新收藏记录的时候要先更新历史记录,在更新收藏记录时将最新的历史记录和收藏记录关联起来 FavoriteDB.insertHistory(item.name, item.url, dateTime, 1) rows = FavoriteDB.selectBySQL('select max(id) from ' + FavoriteDB.TABLE_HISTORY) for row in rows: historyMaxId = row[0] FavoriteDB.updateFavorites('and id = ' + str(item.id), name=item.name, url=item.url, date=dateTime, history_id=historyMaxId) FavoriteDB.updateHistory('and id = ' + str(item.historyId), favorite=1) self.mainWindow.onGetQueryUrl(item.url) elif item.type == ITEM_TYPE_HISTORY: FavoriteDB.insertHistory(item.name, item.url, dateTime, 0) self.mainWindow.onGetQueryUrl(item.url) @pyqtSlot(QPoint) def openContextMenu(self, point): list = self.selectedIndexes() if len(list) > 1: self.menuBatchOperation(list) elif len(list) == 1: self.menuOperation(point) def menuOperation(self, point): index = self.indexAt(point) if not index.isValid(): return item = self.treeModel.itemFromIndex(index) menu = QMenu() if item.type == ITEM_TYPE_HISTORY: queryAction = QAction(IconTool.buildQIcon('data.png'), '&Edit ...', self, triggered=lambda: self.showQueryDialog(item)) queryAction.setShortcut('Alt+E') menu.addAction(queryAction) favoritesAction = QAction( IconTool.buildQIcon('star.png'), 'Add to &favorites', self, triggered=lambda: self.add2Favorites(item)) favoritesAction.setShortcut('Alt+F') menu.addAction(favoritesAction) deleteAction = QAction(IconTool.buildQIcon('clear.png'), '&Delete', self, triggered=lambda: self.deleteHistory(item)) deleteAction.setShortcut('Ctrl+D') menu.addAction(deleteAction) if item.type == ITEM_TYPE_FAVORITES: queryAction = QAction(IconTool.buildQIcon('data.png'), '&Edit ...', self, triggered=lambda: self.showQueryDialog(item)) queryAction.setShortcut('Alt+E') menu.addAction(queryAction) disFavoritesAction = QAction( IconTool.buildQIcon('remove_favorites.png'), 'Remove from &favorites', self, triggered=lambda: self.remove2Favorites(item)) disFavoritesAction.setShortcut('Alt+F') menu.addAction(disFavoritesAction) deleteAction = QAction(IconTool.buildQIcon('clear.png'), '&Delete', self, triggered=lambda: self.deleteFavorite(item)) deleteAction.setShortcut('Ctrl+D') menu.addAction(deleteAction) if item.type == ITEM_TYPE_URL: copyAction = QAction( IconTool.buildQIcon('copy.png'), 'Copy', self, triggered=lambda: pyperclip.copy('%s' % index.data())) copyAction.setShortcut('Ctrl+C') menu.addAction(copyAction) menu.exec_(self.viewport().mapToGlobal(point)) def menuBatchOperation(self, list): itemList = [] #标记本次批量操作所有记录的类别是否一致,如果不一致就不进行右键批量操作 itemTpye = None for modelIndex in list: item = self.treeModel.itemFromIndex(modelIndex) if itemTpye != None: if itemTpye != item.type: return itemTpye = item.type itemList.append(item) menu = QMenu() if itemTpye == ITEM_TYPE_HISTORY: deleteAction = QAction( IconTool.buildQIcon('clear.png'), '&Delete', self, triggered=lambda: self.deleteHistoryBatch(itemList)) deleteAction.setShortcut('Ctrl+D') menu.addAction(deleteAction) if itemTpye == ITEM_TYPE_FAVORITES: deleteAction = QAction( IconTool.buildQIcon('clear.png'), '&Delete', self, triggered=lambda: self.deleteFavoritesBatch(itemList)) deleteAction.setShortcut('Ctrl+D') menu.addAction(deleteAction) menu.exec_(QCursor.pos()) def showQueryDialog(self, item): self.dialog = DataQueryDialog(item) self.dialog.finishSignal.connect(self.mainWindow.onGetQueryUrl) self.dialog.show() STCLogger().i('show queryDataDialog') def add2Favorites(self, item): if item.type == ITEM_TYPE_HISTORY: dateTime = time.strftime("%Y/%m/%d %H:%M:%S", time.localtime(time.time())) FavoriteDB.insertFavorites(item.name, item.url, dateTime, item.id) STCLogger().i('the history record add to DataBase of favorites :' + item.url) self.updateTree() def deleteFavorite(self, item): if item.type == ITEM_TYPE_FAVORITES: FavoriteDB.deleteFavorites('and id = ' + str(item.id)) FavoriteDB.deleteHistory(' and id = ' + str(item.historyId)) STCLogger().i('this record delete from DataBase:' + item.url) self.updateTree() def deleteFavoritesBatch(self, list): FavoriteDB.deleteFavoritesBatch(list) STCLogger().i('A batch of favorite records was deleted') self.updateTree() def deleteHistory(self, item): if item.type == ITEM_TYPE_HISTORY: FavoriteDB.deleteHistory('and id = ' + str(item.id)) STCLogger().i('this record delete from DataBase:' + item.url) self.updateTree() def deleteHistoryBatch(self, list): FavoriteDB.deleteHistoryBatch(list) STCLogger().i('A batch of historical records was deleted') self.updateTree() def remove2Favorites(self, item): if item.type == ITEM_TYPE_FAVORITES: FavoriteDB.deleteFavorites('and id = ' + str(item.id)) STCLogger().i('this record remove from DataBase of favorites:' + item.url) self.updateTree() def updateTree(self): self.buildFavoritesTree() self.buildQueryHistory()
class GpsDataModel(object): """ :keyword Model QStandItemModel """ def __init__(self): self.__stand_item_model = QStandardItemModel() @property def Model(self): return self.__stand_item_model @property def HeadData(self): return [str(self.__stand_item_model.headerData(i, Qt.Horizontal)) for i in range(0, self.__stand_item_model.columnCount())] # 插入单行 def insertSingleRow(self,Data : tuple): item = [] count = len(Data) for i in range(0,count): item.append(QStandardItem(str(Data[i]))) self.__stand_item_model.appendRow(item) # 插入多行 def insertMultiRows(self, DataList : list): for i in range(0, len(DataList)): self.insertSingleRow(DataList[i]) def insertSingleColumn(self, headData, Data:tuple, column): """ :keyword 插入单列 :param HeadData : label Data : tuple column : to insert into column """ list_stand_item = [QStandardItem(str(data)) for data in Data] self.__stand_item_model.insertColumn(4, list_stand_item) self.__stand_item_model.setHorizontalHeaderItem(column, QStandardItem(headData)) # 插入多列 def insertHeadColumn(self, headData:list): self.__stand_item_model.setHorizontalHeaderLabels(headData) def appendColumnLast(self,headData:tuple, Data): """ 在最后插入一列 :param: headData: (label,Last_column_number) Data : iter """ list_stand_item = [QStandardItem(str(item)) for item in Data] self.__stand_item_model.appendColumn(list_stand_item) self.__stand_item_model.setHorizontalHeaderItem(headData[1], QStandardItem(headData[0])) def ergodic(self): """ 遍历所有单元格并将数据导出到本地 :return: tuple """ # 获得行列数 rows = self.__stand_item_model.rowCount() columns = self.__stand_item_model.columnCount() # 按行列获取单元格 data = [] for i in range(0, rows): row = [] for j in range(0, columns): try: row.append(self.__stand_item_model.item(i, j).text()) except: row.append('') data.append(row) return data def ergodic_column(self, column): data = [] rows = self.__stand_item_model.rowCount() for i in range(0, rows): data.append(self.__stand_item_model.item(i, column).text()) return data
class AnalyzerView(QWidget): def __init__(self, cols: dict, parent=None, address_space: dict = None): super(AnalyzerView, self).__init__(parent) self.cols = cols self.address_space = address_space self.dataformat = {} self.entry = QLineEdit(self) self.entry.setClearButtonEnabled(True) self.entry.setPlaceholderText('Base Address or Register Name') completer = QCompleter() completer.setCaseSensitivity(Qt.CaseInsensitive) completer.setFilterMode(Qt.MatchContains) self.entry.setCompleter(completer) self.entry.setMinimumWidth(500) self.close_btn = QPushButton( 'X', self, ) self.close_btn.setMaximumWidth(40) hbox1 = QHBoxLayout() hbox1.addWidget(self.entry) hbox1.addStretch(1) # hbox1.addWidget() ctrl_box = QHBoxLayout() self.show_detail = QCheckBox('Show Detail', self) self.show_reserved = QCheckBox('Show Reserved', self) self.add_col = QPushButton( 'Add Column', self, ) self.add_col.setDisabled(True) ctrl_box.addWidget(self.show_detail) # ctrl_box.addWidget(detail_label) ctrl_box.addWidget(self.show_reserved) ctrl_box.addWidget(self.add_col) ctrl_box.addStretch(1) ctrl_box.addWidget(self.close_btn) self.string_model = QStringListModel() completer.setModel(self.string_model) self.string_model.setStringList(self.address_space.keys()) self.model = QStandardItemModel() self.table = TableView(self) self.table.setWordWrap(True) self.table.setModel(self.model) vbox = QVBoxLayout() vbox.addLayout(hbox1) # vbox.addWidget(self.entry) vbox.addLayout(ctrl_box) vbox.addWidget(self.table) self.setLayout(vbox) # self.table.horizontalHeader().setHidden(True) self.table.verticalHeader().setHidden(True) self.table.setShowGrid(False) # self.table.setMinimumHeight(600) self.reserved_row = [] self.add_col.clicked.connect(self.add_column) self.close_btn.clicked.connect(self.close) self.show_detail.stateChanged.connect(self.detail) self.show_reserved.stateChanged.connect(self.hide_reserved) self.entry.textChanged.connect(self.create_rows) # self.table.dataChangedSignal.connect(self.test) self.create_cols() self.detail() def set_address_space(self, address): self.entry.setText(address) def dataChangeEvent(self, index_0: QModelIndex, new: str, old: str): if not index_0.isValid(): return chg_row = index_0.row() chg_col = index_0.column() if chg_col < len(self.cols.keys()): return if chg_row == 0: item = self.model.itemFromIndex(index_0) item.setText(new) return last_row = self.model.rowCount() - 1 if chg_row != 0: item = self.model.item(0, chg_col) total = item.text().strip() if total == '': total = '0x0' total = self.tobinary(total, width=32)[::-1] total = list(total) # print(len(total), total) values = self.dataformat.get(chg_row) msb = values[0] lsb = values[1] width = msb - lsb + 1 value_chg = new value_chg = list(self.tobinary(value_chg, width=width)[::-1])[0:width] total[lsb:msb + 1] = value_chg total = ''.join(total[0:32]) item.setText(self.binary2hex(total[::-1], width=8)) item_chg = self.model.itemFromIndex(index_0) value_chg = ''.join(value_chg)[::-1] item_chg.setText(self.binary2hex(value_chg, width=width // 4)) else: total = new total = self.tobinary(total, width=32)[::-1] for row, values in self.dataformat.items(): msb = values[0] lsb = values[1] width = msb - lsb + 1 item = self.model.item(row, chg_col) item.setText( self.binary2hex(total[lsb:msb + 1][::-1], width=width // 4)) def create_cols(self): rows = [QStandardItem(col) for col in self.cols.keys()] self.model.appendRow(rows) def create_rows(self): self.reserved_row = [] adddress = self.entry.text() fields = self.address_space.get(adddress, None) if fields: self.model.clear() self.create_cols() # last_row = [] for row, field in enumerate(fields): is_reserved = (field.get('Field', '') == 'RESERVED') rows = [] if is_reserved: self.reserved_row.append(row + 1) for col in self.cols.keys(): cell = QStandardItem(str(field[col])) cell.setEditable(False) rows.append(cell) self.model.appendRow(rows) self.detail() self.dataformatting(fields) for _ in range(2): self.add_column() self.hide_reserved() self.table.setMinimumHeight( (self.model.rowCount() + 1) * self.table.rowHeight(0)) self.add_col.setDisabled(False) def hide_reserved(self): # self.table.blockSignals(True) hide = self.show_reserved.checkState() == Qt.Unchecked for row in self.reserved_row: for col in range(self.model.columnCount()): # QStandardItem().st item = self.model.item(row, col) if hide: item.setFont( QFont(self.font().family(), self.font().pointSize() * 2 // 3)) item.setForeground(QColor.fromRgb(204, 204, 204)) else: self.table.setStyleSheet("") item.setFont(self.font()) item.setForeground(QColor.fromRgb(0, 0, 0)) # self.table.blockSignals(False) def add_column(self): self.model.appendColumn([ QStandardItem(self.dataformat[row][-1]) for row in range(self.model.rowCount()) ]) self.table.setColumnWidth(self.model.columnCount() - 1, 150) delegate = LineEditDelegate(self.table, validator='hex') delegate.dataBeforeChanged.connect(self.dataChangeEvent) self.table.setItemDelegateForColumn(self.model.columnCount() - 1, delegate) self.hide_reserved() def detail(self): for col, (header, config) in enumerate(self.cols.items()): to_hide = ['Description', 'Testable', 'Public'] width = config.get('width', None) if header in to_hide: if self.show_detail.checkState() != Qt.Checked: self.table.hideColumn(col) else: self.table.showColumn(col) if width: self.table.setColumnWidth(col, width) # self.table.resizeColumnToContents(col) for row in range(self.model.rowCount()): self.table.resizeRowToContents(row) # self.table.setMinimumHeight(self.table.size().height()) def reload_address(self, address_space: dict): self.address_space = address_space self.string_model.setStringList(address_space.keys()) def dataformatting(self, fields): self.dataformat = {} total = '' for row, field in enumerate(fields): row += 1 msb = int(field.get('MSB')) lsb = int(field.get('LSB')) bitwidth = msb - lsb + 1 default = field.get('Default') try: default = self.tobinary(default, bitwidth) total += default default = self.binary2hex(default, width=bitwidth // 4) self.dataformat[row] = [msb, lsb, default] # default = self.binary2hex(default) except Exception as e: self.dataformat[row] = [msb, lsb, '0x0'] self.dataformat[0] = [31, 0, self.binary2hex(total, width=8)] @staticmethod def binary2hex(binary: str, width: int): return f"0x{int(binary, 2):0{width}X}" def tobinary(self, value: str, width: int): try: value = value.lower().strip() if value == '' or value == '0x': return f"{0:0{width}b}" if value.startswith('0x'): return f"{int(value, 16):0{width}b}" else: return f"{int(value):0{width}b}" except Exception as e: return f"{0:0{width}b}"