class HistoryManagerWidget(QWidget): def __init__(self): super().__init__() self.listHistory = [] self.nam = QtNetwork.QNetworkAccessManager() self.setting = QSettings() self.searchLineEdit = QLineEdit() self.tableView = QTableView() self.columnComboBox = QComboBox() self.searchLabel = QLabel() self.searchLabel.setText("Filter") self.model = QStandardItemModel(self) searchHbox = QHBoxLayout() searchHbox.addWidget(self.searchLabel) searchHbox.addWidget(self.searchLineEdit) searchHbox.addWidget(self.columnComboBox) self.header = "Order ID;Order Status;Card ID;Menu ID;Menu Name;Price;Qty;" \ "Item Status;Table Number;Order Time;Modified Time".split(";") self.model.setHorizontalHeaderLabels(self.header) self.tableView.horizontalHeader().setStretchLastSection(True) hboxLayout = QHBoxLayout() self.backButton = QPushButton() self.backButton.setText("Back") self.refreshButton = QPushButton() self.refreshButton.setText("Refresh") self.refreshButton.clicked.connect(self.refresh) self.saveCSVButton = QPushButton() self.saveCSVButton.setText("Save as CSV") self.saveCSVButton.clicked.connect(self.saveCSV) hboxLayout.addWidget(self.backButton) hboxLayout.addWidget(self.refreshButton) hboxLayout.addWidget(self.saveCSVButton) widgetTitleLabel = QLabel() widgetTitleLabel.setAlignment(Qt.AlignCenter) widgetTitleLabel.setText("History Manager") mainLayout = QVBoxLayout() mainLayout.addWidget(widgetTitleLabel) mainLayout.addLayout(searchHbox) mainLayout.addWidget(self.tableView) mainLayout.addLayout(hboxLayout) self.proxy = QSortFilterProxyModel(self) self.proxy.setSourceModel(self.model) self.tableView.setModel(self.proxy) self.columnComboBox.addItems(self.header) self.searchLineEdit.textChanged.connect(self.on_lineEdit_textChanged) self.columnComboBox.currentIndexChanged.connect(self.on_comboBox_currentIndexChanged) self.horizontalHeader = self.tableView.horizontalHeader() self.setLayout(mainLayout) def saveCSV(self): data = "" rows = self.model.rowCount() columns = self.model.columnCount() if rows>0: for title in self.header: data += title data += "," data += "\n" for i in range(rows): for j in range(columns): index = self.model.index(i,j) # print(str(self.model.data(index))) data += str(self.model.data(index)) data += "," data += "\n" name, _ = QFileDialog.getSaveFileName(self, 'Save File', "History SELFO.csv", "csv(*.csv)") if name: file = open(name, 'w') file.write(data) file.close() else: QMessageBox.critical(self, "Error", "No Data") def clear(self): self.listHistory.clear() self.model.clear() self.model.setHorizontalHeaderLabels(self.header) def refresh(self): self.clear() self.doRequestOrderDetail() def populateList(self): for rowName in range(len(self.listHistory)): self.model.invisibleRootItem().appendRow( [QStandardItem("{}".format(self.listHistory[rowName][column])) for column in range(len(self.header)) ] ) self.tableView.resizeColumnsToContents() def closeHistoryManager(self): self.mainWindow.stackedWidget.removeWidget(self) def doRequestOrderDetail(self): url = self.setting.value("baseURL", "") url += "/orderdetail/?sellerID=" + str(self.setting.value("sellerID", "")) \ # + "&itemStatus=" + "placed" req = QtNetwork.QNetworkRequest(QUrl(url)) reply = self.nam.get(req) reply.finished.connect(self.handleResponseOrderDetail) def handleResponseOrderDetail(self): reply = self.sender() er = reply.error() if er == QtNetwork.QNetworkReply.NoError: bytes_string = reply.readAll() data = json.loads(str(bytes_string, 'utf-8')) # print(data) for history in data: # id = history['id'] orderID = history['orderID'] orderStatus = history['orderStatus'] cardID = history['cardID'] # sellerID = history['sellerID'] menuID = history['menuID'] menuName = history['menuName'] itemStatus = history['itemStatus'] price = formatRupiah(history['price']) qty = history['qty'] tableNumber = history['tableNumber'] rawOrderTime = history['orderTime'] orderTime = datetime.datetime.strptime( rawOrderTime, "%Y-%m-%dT%H:%M:%S.%f+07:00").strftime("%d %b %Y %H:%M:%S") rawModifiedTime = history['modifiedTime'] if rawModifiedTime is not None: modifiedTime = datetime.datetime.strptime( rawModifiedTime, "%Y-%m-%dT%H:%M:%S.%f+07:00").strftime("%d %b %Y %H:%M:%S") else: modifiedTime = "null" historyItem = [orderID, orderStatus, cardID, menuID, menuName, price, qty, itemStatus, tableNumber, orderTime, modifiedTime] self.listHistory.append(historyItem) self.populateList() else: errorMessage = "Error occured: " + str(er) + "\n" + str(reply.errorString()) QMessageBox.critical(self, "Error Order Detail", errorMessage) reply.deleteLater() def on_view_horizontalHeader_sectionClicked(self, logicalIndex): self.logicalIndex = logicalIndex self.menuValues = QMenu(self) self.signalMapper = QSignalMapper(self) self.columnComboBox.blockSignals(True) self.columnComboBox.setCurrentIndex(self.logicalIndex) self.columnComboBox.blockSignals(True) valuesUnique = [ self.model.item(row, self.logicalIndex).text() for row in range(self.model.rowCount()) ] actionAll = QAction("All", self) actionAll.triggered.connect(self.on_actionAll_triggered) self.menuValues.addAction(actionAll) self.menuValues.addSeparator() for actionNumber, actionName in enumerate(sorted(list(set(valuesUnique)))): action = QAction(actionName, self) self.signalMapper.setMapping(action, actionNumber) action.triggered.connect(self.signalMapper.map) self.menuValues.addAction(action) self.signalMapper.mapped.connect(self.on_signalMapper_mapped) headerPos = self.tableView.mapToGlobal(self.horizontalHeader.pos()) posY = headerPos.y() + self.horizontalHeader.height() posX = headerPos.x() + self.horizontalHeader.sectionPosition(self.logicalIndex) self.menuValues.exec_(QPoint(posX, posY)) def on_actionAll_triggered(self): filterColumn = self.logicalIndex filterString = QRegExp( "", Qt.CaseInsensitive, QRegExp.RegExp ) self.proxy.setFilterRegExp(filterString) self.proxy.setFilterKeyColumn(filterColumn) def on_signalMapper_mapped(self, i): stringAction = self.signalMapper.mapping(i).text() filterColumn = self.logicalIndex filterString = QRegExp( stringAction, Qt.CaseSensitive, QRegExp.FixedString ) self.proxy.setFilterRegExp(filterString) self.proxy.setFilterKeyColumn(filterColumn) def on_lineEdit_textChanged(self, text): search = QRegExp( text, Qt.CaseInsensitive, QRegExp.RegExp ) self.proxy.setFilterRegExp(search) def on_comboBox_currentIndexChanged(self, index): self.proxy.setFilterKeyColumn(index)
class ScanTableWidget(QWidget): """ Used for displaying information in a table. =============================== ========================================= **Signals:** sigScanClicked Emitted when the user has clicked on a row of the table and returns the current index. This index contains information about the current rows column data. =============================== ========================================= """ sigScanClicked = pyqtSignal(QModelIndex, name="scanClicked") header = [ "MS level", "Index", "RT (min)", "precursor m/z", "charge", "ID", "PeptideSeq", "PeptideIons", ] def __init__(self, ms_experiment, *args): QWidget.__init__(self, *args) self.ms_experiment = ms_experiment self.table_model = ScanTableModel(self, self.ms_experiment, self.header) self.table_view = QTableView() # register a proxy class for filering and sorting the scan table self.proxy = QSortFilterProxyModel(self) self.proxy.setSourceModel(self.table_model) self.table_view.sortByColumn(1, Qt.AscendingOrder) # setup selection model self.table_view.setSelectionMode(QAbstractItemView.SingleSelection) self.table_view.setSelectionBehavior(QAbstractItemView.SelectRows) self.table_view.setModel(self.proxy) self.table_view.setSelectionModel(QItemSelectionModel(self.proxy)) # header self.horizontalHeader = self.table_view.horizontalHeader() self.horizontalHeader.sectionClicked.connect(self.onHeaderClicked) # enable sorting self.table_view.setSortingEnabled(True) # connect signals to slots self.table_view.selectionModel().currentChanged.connect( self.onCurrentChanged) # keyboard moves to new row self.horizontalHeader.sectionClicked.connect(self.onHeaderClicked) layout = QVBoxLayout(self) layout.addWidget(self.table_view) self.setLayout(layout) # hide column 7 with the PepIon data, intern information usage self.table_view.setColumnHidden(7, True) # Add rt in minutes for better TIC interaction self.table_view.setItemDelegateForColumn(2, RTUnitDelegate(self)) self.table_view.setColumnWidth(2, 160) # default : first row selected. in OpenMSWidgets def onRowSelected(self, index): """se_comment: hard-refactoring to comply to pep8""" if index.siblingAtColumn(1).data() is None: return # prevents crash if row gets filtered out self.curr_spec = self.ms_experiment.getSpectrum( index.siblingAtColumn(1).data()) self.scanClicked.emit(index) def onCurrentChanged(self, new_index, old_index): self.onRowSelected(new_index) def onHeaderClicked(self, logicalIndex): if logicalIndex != 0: return # allow filter on first column only for now self.logicalIndex = logicalIndex self.menuValues = QMenu(self) self.signalMapper = QSignalMapper(self) # get unique values from (unfiltered) model valuesUnique = set([ self.table_model.index(row, self.logicalIndex).data() for row in range( self.table_model.rowCount( self.table_model.index(-1, self.logicalIndex))) ]) if len(valuesUnique) == 1: return # no need to select anything actionAll = QAction("Show All", self) actionAll.triggered.connect(self.onShowAllRows) self.menuValues.addAction(actionAll) self.menuValues.addSeparator() """se_comment: hard-refactoring to comply to pep8""" l: enumerate = enumerate(sorted(list(set(valuesUnique)))) for actionNumber, actionName in l: action = QAction(actionName, self) self.signalMapper.setMapping(action, actionNumber) action.triggered.connect(self.signalMapper.map) self.menuValues.addAction(action) self.signalMapper.mapped.connect(self.onSignalMapper) # get screen position of table header and open menu headerPos = self.table_view.mapToGlobal(self.horizontalHeader.pos()) posY = headerPos.y() + self.horizontalHeader.height() posX = headerPos.x() + \ self.horizontalHeader.sectionPosition(self.logicalIndex) self.menuValues.exec_(QPoint(posX, posY)) def onShowAllRows(self): filterColumn = self.logicalIndex filterString = QRegExp("", Qt.CaseInsensitive, QRegExp.RegExp) self.proxy.setFilterRegExp(filterString) self.proxy.setFilterKeyColumn(filterColumn) def onSignalMapper(self, i): stringAction = self.signalMapper.mapping(i).text() filterColumn = self.logicalIndex filterString = QRegExp(stringAction, Qt.CaseSensitive, QRegExp.FixedString) self.proxy.setFilterRegExp(filterString) self.proxy.setFilterKeyColumn(filterColumn)
class FilterableTable(SQLTable): """a filterable Table Widget that displays content of an SQLite table; for individual widgets, subclass and overwrite the create_model method; add_color_proxy should be an (INT allele_status-column, INT lab_status-column) tuple """ def __init__(self, log, mydb = ": memory :", add_color_proxy = False, header_dic = None): super().__init__(log, mydb) self.add_color_proxy = add_color_proxy self.header_dic = header_dic self.create_model() self.fill_UI() self.create_filter_model() self.update_filterbox() def fill_UI(self): """sets up the layout """ self.log.debug("\t- Setting up the table...") self.table = QTableView() self.table.setContextMenuPolicy(Qt.CustomContextMenu) self.header = self.table.horizontalHeader() # table header self.header.setSectionResizeMode(QHeaderView.ResizeToContents) self.table.setSelectionBehavior(QAbstractItemView.SelectRows) self.table.setAlternatingRowColors(True) # self.header.sectionClicked.connect(self.on_header_sectionClicked) mode = QAbstractItemView.SingleSelection self.table.setSelectionMode(mode) self.grid.addWidget(self.table, 2, 0, 10, 10) self.filter_lbl = QLabel("Filter:", self) self.grid.addWidget(self.filter_lbl, 1, 2) self.filter_entry = QLineEdit(self) self.grid.addWidget(self.filter_entry, 1, 3) self.filter_entry.textChanged.connect(self.on_filter_entry_textChanged) self.filter_text = "" self.filter_cb = QComboBox(self) self.grid.addWidget(self.filter_cb, 1, 4) self.filter_cb.currentIndexChanged.connect(self.on_filter_cb_IndexChanged) self.filter_btn = QPushButton("Filter!", self) self.grid.addWidget(self.filter_btn, 1, 5) self.filter_btn.clicked.connect(self.on_filter_btn_clicked) self.unfilter_btn = QPushButton("Remove Filter", self) self.grid.addWidget(self.unfilter_btn, 1, 6) self.unfilter_btn.clicked.connect(self.on_actionAll_triggered) self.log.debug("\t=> Done!") def update_filterbox(self): """fills the filter-combobox with the header values after the model has been created and set """ column_num = self.model.columnCount() if self.header_dic: columns = [self.header_dic[i] for i in self.header_dic] else: columns = [self.proxy.headerData(i, Qt.Horizontal) for i in range(column_num)] self.filter_cb.addItems(columns) def create_filter_model(self): """creates the filter-proxy-model on top of self.model """ self.log.debug("Creating filter model...") self.proxy = QSortFilterProxyModel(self) if self.add_color_proxy: (allele_status_column, lab_status_column) = self.add_color_proxy self.log.debug("adding color filter to columns {} and {}".format(allele_status_column, lab_status_column)) self.color_proxy = ColorProxyModel(self, allele_status_column, lab_status_column) self.color_proxy.setSourceModel(self.model) self.proxy.setSourceModel(self.color_proxy) else: self.proxy.setSourceModel(self.model) self.table.setSortingEnabled(True) self.table.setModel(self.proxy) def on_filter_cb_IndexChanged(self, index): """restricts RegEx filter to selected column """ self.log.debug("Combobox: colum {} selected".format(index)) self.proxy.setFilterKeyColumn(index) def on_filter_entry_textChanged(self, text): """stores content of filter_entry as self.text """ self.log.debug("filter text: '{}'".format(text)) self.filter_text = text def on_filter_btn_clicked(self): """activates RegEx filter to current content of filter_entry and filter_cb """ column = self.filter_cb.currentIndex() self.log.debug("Filtering column {} for '{}'".format(column, self.filter_text)) self.proxy.setFilterKeyColumn(column) search = QRegExp(self.filter_text, Qt.CaseInsensitive, QRegExp.RegExp) self.proxy.setFilterRegExp(search) def on_header_sectionClicked(self, logicalIndex): """opens a dialog to choose between all unique values for this column, or revert to 'All' """ self.log.debug("Header clicked: column {}".format(logicalIndex)) self.logicalIndex = logicalIndex menuValues = QMenu(self) self.signalMapper = QSignalMapper(self) self.filter_cb.setCurrentIndex(self.logicalIndex) self.filter_cb.blockSignals(True) self.proxy.setFilterKeyColumn(self.logicalIndex) valuesUnique = [str(self.model.index(row, self.logicalIndex).data()) for row in range(self.model.rowCount()) ] actionAll = QAction("All", self) actionAll.triggered.connect(self.on_actionAll_triggered) menuValues.addAction(actionAll) menuValues.addSeparator() for actionNumber, actionName in enumerate(sorted(list(set(valuesUnique)))): action = QAction(actionName, self) self.signalMapper.setMapping(action, actionNumber) action.triggered.connect(self.signalMapper.map) menuValues.addAction(action) self.signalMapper.mapped.connect(self.on_signalMapper_mapped) headerPos = self.table.mapToGlobal(self.header.pos()) posY = headerPos.y() + self.header.height() posX = headerPos.x() + self.header.sectionViewportPosition(self.logicalIndex) menuValues.exec_(QPoint(posX, posY)) def on_actionAll_triggered(self): """reverts table to unfiltered state """ self.log.debug("Unfiltering...") filterString = QRegExp("", Qt.CaseInsensitive, QRegExp.RegExp) self.proxy.setFilterRegExp(filterString) self.filter_entry.setText("") def on_signalMapper_mapped(self, i): """filters current column to mapping text """ text = self.signalMapper.mapping(i).text() self.log.debug("Filtering column {} to '{}'".format(self.logicalIndex, text)) filterString = QRegExp(text, Qt.CaseSensitive, QRegExp.FixedString) self.proxy.setFilterRegExp(filterString)