def setupTabs(self): """ Setup the various tabs in the AddressWidget. """ groups = ["ABC", "DEF", "GHI", "JKL", "MNO", "PQR", "STU", "VW", "XYZ"] for group in groups: proxyModel = QSortFilterProxyModel(self) proxyModel.setSourceModel(self.tableModel) proxyModel.setDynamicSortFilter(True) tableView = QTableView() tableView.setModel(proxyModel) tableView.setSortingEnabled(True) tableView.setSelectionBehavior(QAbstractItemView.SelectRows) tableView.horizontalHeader().setStretchLastSection(True) tableView.verticalHeader().hide() tableView.setEditTriggers(QAbstractItemView.NoEditTriggers) tableView.setSelectionMode(QAbstractItemView.SingleSelection) # This here be the magic: we use the group name (e.g. "ABC") to # build the regex for the QSortFilterProxyModel for the group's # tab. The regex will end up looking like "^[ABC].*", only # allowing this tab to display items where the name starts with # "A", "B", or "C". Notice that we set it to be case-insensitive. reFilter = "^[%s].*" % group proxyModel.setFilterRegExp(QRegExp(reFilter, Qt.CaseInsensitive)) proxyModel.setFilterKeyColumn(0) # Filter on the "name" column proxyModel.sort(0, Qt.AscendingOrder) # This prevents an application crash (see: http://www.qtcentre.org/threads/58874-QListView-SelectionModel-selectionChanged-Crash) viewselectionmodel = tableView.selectionModel() tableView.selectionModel().selectionChanged.connect( self.selectionChanged) self.addTab(tableView, group)
def setupTabs(self): """ Setup the various tabs in the AddressWidget. """ groups = ["ABC", "DEF", "GHI", "JKL", "MNO", "PQR", "STU", "VW", "XYZ"] for group in groups: proxyModel = QSortFilterProxyModel(self) proxyModel.setSourceModel(self.tableModel) proxyModel.setDynamicSortFilter(True) tableView = QTableView() tableView.setModel(proxyModel) tableView.setSortingEnabled(True) tableView.setSelectionBehavior(QAbstractItemView.SelectRows) tableView.horizontalHeader().setStretchLastSection(True) tableView.verticalHeader().hide() tableView.setEditTriggers(QAbstractItemView.NoEditTriggers) tableView.setSelectionMode(QAbstractItemView.SingleSelection) # This here be the magic: we use the group name (e.g. "ABC") to # build the regex for the QSortFilterProxyModel for the group's # tab. The regex will end up looking like "^[ABC].*", only # allowing this tab to display items where the name starts with # "A", "B", or "C". Notice that we set it to be case-insensitive. reFilter = "^[%s].*" % group proxyModel.setFilterRegExp(QRegExp(reFilter, Qt.CaseInsensitive)) proxyModel.setFilterKeyColumn(0) # Filter on the "name" column proxyModel.sort(0, Qt.AscendingOrder) # This prevents an application crash (see: http://www.qtcentre.org/threads/58874-QListView-SelectionModel-selectionChanged-Crash) viewselectionmodel = tableView.selectionModel() tableView.selectionModel().selectionChanged.connect(self.selectionChanged) self.addTab(tableView, group)
class AddressWidget(QDialog): selectionChanged = Signal(QItemSelection) def __init__(self, parent=None): super(AddressWidget, self).__init__(parent) self.tableModel = TableModel() self.tableView = QTableView() self.setupTable() statusLabel = QLabel("Tabular data view demo") layout = QVBoxLayout() layout.addWidget(self.tableView) layout.addWidget(statusLabel) self.setLayout(layout) self.setWindowTitle("Address Book") self.resize(800,500) # add test data self.populateTestData() def setupTable(self): proxyModel = QSortFilterProxyModel(self) proxyModel.setSourceModel(self.tableModel) proxyModel.setDynamicSortFilter(True) self.tableView.setModel(proxyModel) self.tableView.setSortingEnabled(True) self.tableView.setSelectionBehavior(QAbstractItemView.SelectRows) self.tableView.horizontalHeader().setStretchLastSection(True) self.tableView.verticalHeader().hide() self.tableView.setEditTriggers(QAbstractItemView.NoEditTriggers) self.tableView.setSelectionMode(QAbstractItemView.SingleSelection) proxyModel.setFilterKeyColumn(0) # Filter on the "name" column proxyModel.sort(0, Qt.AscendingOrder) viewselectionmodel = self.tableView.selectionModel() self.tableView.selectionModel().selectionChanged.connect(self.selectionChanged) def populateTestData(self): addresses = [{"name": "John Doe", "address": "Alameda"}, {"name": "Alan Turing", "address": "San Deigo"}, {"name": "Bjarne Stroutsup", "address": "Columbia"}, {"name": "Herb Sutter", "address": "Seattle"}, {"name": "Micheal Konin", "address": "Colorado"}] for i in range(len(addresses)): self.tableModel.insertRows(0) ix = self.tableModel.index(0, 0, QModelIndex()) self.tableModel.setData(ix, addresses[i]["name"], Qt.EditRole) ix = self.tableModel.index(0, 1, QModelIndex()) self.tableModel.setData(ix, addresses[i]["address"], Qt.EditRole) self.tableView.resizeRowToContents(ix.row())
def _create_device_table(self) -> QTableView: device_table = QTableView() device_table.setModel(self._device_model) device_table.setSelectionBehavior(QAbstractItemView.SelectRows) device_table.setSelectionMode(QAbstractItemView.SingleSelection) device_table.selectionModel().selectionChanged.connect( self._on_device_table_selection_changed) horizontal_header = device_table.horizontalHeader() vertical_header = device_table.verticalHeader() horizontal_header.setSectionResizeMode(QHeaderView.ResizeToContents) vertical_header.setSectionResizeMode(QHeaderView.ResizeToContents) horizontal_header.setStretchLastSection(True) return device_table
class Window(QtWidgets.QWidget): """ zmiana nagłówka działa tylko dla stylu fusion, działa tylko dla stylu 'fusion" """ def __init__(self): super(Window, self).__init__() self.table = QTableView() self.sti = QStandardItemModel() self.sti.setColumnCount(3) self.table.setModel(self.sti) self.sti.setRowCount(8) #piersza możliwośc przez QStandardItem # item1 = QStandardItem('Red') # item1.setBackground(QBrush(Qt.red)) # self.sti.setHorizontalHeaderItem(1, item1) #Druga możliwosć przez odwołanie modelu: self.table.model().setHeaderData(0, Qt.Horizontal, QBrush(QColor(121, 166, 210)), Qt.BackgroundRole) self.table.model().setHeaderData(0, Qt.Horizontal, "One", Qt.DisplayRole) self.mlayout = QHBoxLayout() self.mlayout.addWidget(self.table) self.setLayout(self.mlayout) def contextMenuEvent(self, event): contextMenu = QMenu(self) newAction = contextMenu.addAction("New") openAction = contextMenu.addAction("Open") quitAction = contextMenu.addAction("Quit") action = contextMenu.exec_(self.mapToGlobal(event.pos())) if action == quitAction: self.close() if action == openAction: # model = self.sti # indices = self.table.selectionModel().selectedRows() # for index in sorted(indices): # model.removeRow(index.row()) index_list = [] for model_index in self.table.selectionModel().selectedRows(): index = QtCore.QPersistentModelIndex(model_index) index_list.append(index) for index in index_list: self.sti.removeRow(index.row())
def table_insert(self, TableModel: TableModel, TableView: QtWidgets.QTableView): print('Inserting a row into table.') # get selected row index selected_indexes = TableView.selectionModel().selectedIndexes() selected_row_index = selected_indexes[-1].row() print(f'row index {selected_row_index}.') # insert TableModel.insertRow(selected_row_index) print(TableView == self.ui.tableView_emitters) TableView.model().layoutChanged.emit() TableView.resizeRowsToContents() self.repaint()
def table_remove(self, TableModel: TableModel, TableView: QtWidgets.QTableView): if TableModel.rowCount(TableView) <= 1: raise ValueError('Not enough rows to delete.') # get selected row index selected_indexes = TableView.selectionModel().selectedIndexes() if len(selected_indexes) > 1: selected_row_index = selected_indexes[-1].row() else: selected_row_index = selected_indexes[0].row() # remove TableModel.removeRow(selected_row_index) TableView.model().layoutChanged.emit() TableView.resizeRowsToContents() self.repaint()
def using_model(): app = QApplication() numbers = ['One', 'Two', 'Three', 'Four', 'Five'] model = QStringListModel() model.setStringList(numbers) list = QListView() list.setModel(model) firstTableView = QTableView() secondTableView = QTableView() firstTableView.setModel(model) secondTableView.setModel(model) secondTableView.setSelectionModel(firstTableView.selectionModel()) list.show() firstTableView.show() secondTableView.show() app.exec_()
class MainWindow(QMainWindow): def __init__(self, parent=None): super(MainWindow, self).__init__(parent) self.setWindowTitle("VW Competitive") self.setWindowIcon(QIcon(':/images/vw.png')) """ Test wstawienia wartosci do tabeli """ self.table = QTableView() self.setCentralWidget(self.table) self.sti = QStandardItemModel() self.sti.setColumnCount(6) self.table.setModel(self.sti) self.table.verticalHeader().setDefaultSectionSize(10) self.table.horizontalHeader().setDefaultSectionSize(200) self.headers = [ 'Year', 'Month', 'Week', 'Sector', 'Category', 'Sub Category', 'Produkt(4)', 'Branża(I)', 'Kategoria(II)', 'Dział(III)', 'Producer', 'Brand', 'Sub Brand', 'Film Code', 'Film Code 2', 'Media', 'Glowne Medium', 'Medium', 'Wydawca Nadawca', 'Periodyczność', 'Duration', 'Typ reklamy', 'Forma Reklamy', 'Typ Strony', 'L.emisji', 'Sum.Str', 'Cost', 'PT/OFF', 'TRP', 'TRP30', 'Channel group', 'Channel type', 'Wyprz', 'Upus', 'Rabat', 'Wyprze Upust Rabat', 'Model', 'Brand final', 'Subbrand (brand+Model)', 'Brand Type', 'Segment_detailed', 'Segment', 'Segment_combined', 'Campaign Type' ] """ Forms """ self.excel_form = ExcelForm(self.headers, self) self.connect_form = ConnectRaports(self) self.filechoser = FileChoser(self) self.for_find_duplicate = FindDuplicate(self) self.filters_manager = FiltersManager(self) self.sti.setHorizontalHeaderLabels(self.headers) self.sti.setColumnCount(len(self.headers)) self.table.setSortingEnabled(True) #self.table.horizontalHeader().connect() self.connect(self.table.horizontalHeader(), SIGNAL("sectionClicked(int)"), self.showfilterforms) self.createActions() self.createMenus() self.createStatusBar() self.readSettings() self.set_color_on_header() def closeEvent(self, event): self.close() def open(self): self.filechoser.show() self.filechoser.clead_data() def save(self): """ save data to data base :return: """ #deleta rows from data base for compative name session = Session() comat = session.query(Competitive).filter( Competitive.name.ilike(f'%{self.compative_name}%')).first() session.query(Data).filter_by(competitive_id=comat.id).delete() #read data from row and save to data base for row in range(self.sti.rowCount()): datas = [] for col in range(self.sti.columnCount()): if col in (0, 1, 2, 20, 24): try: #tutaj poprawic nie chce wpisać if self.sti.item(row, col) is not None: datas.append(int(self.sti.item(row, col).text())) else: datas.append(None) except ValueError: datas.append(None) elif col in (25, 26, 28, 29): try: if self.sti.item(row, col) is not None: datas.append(float(self.sti.item(row, col).text())) else: datas.append(None) except ValueError: datas.append(None) else: if self.sti.item(row, col) is not None: datas.append(self.sti.item(row, col).text()) else: datas.append(None) comat.datas.append(Data(*datas)) session.commit() session.close() QMessageBox.information(self, "Zapis", "Zapis zakonczyl się powodzeniem.") def createActions(self): self.openAct = QAction(QIcon(':/images/open.png'), "&Otwórz...", self, shortcut=QKeySequence.Open, statusTip="Otwóż nowe pliki", triggered=self.open) self.saveAct = QAction(QIcon(':/images/save.png'), "&Zapisz...", self, shortcut=QKeySequence.Save, statusTip="Zapisz plik", triggered=self.save) self.exitAct = QAction("&Zamknij", self, shortcut="Ctrl+Q", statusTip="Zamknij aplikacje", triggered=self.close) self.runWordFilter = QAction("Filtry &Automatyczne", shortcut="Ctrl+A", statusTip="Urchom filtry automatyczne", triggered=self.run_filters) self.showExcelForm = QAction("Generuj plik excel", triggered=self.show_excel_form) self.ConnectRaports = QAction("Połącz raporty", triggered=self.show_connect_raports) self.FindDuplicate = QAction("Znajdz duplikaty", triggered=self.show_duplicate_form) self.FilterManager = QAction("Filtry Manualne", triggered=self.show_filter_manager) def createMenus(self): self.fileMenu = self.menuBar().addMenu("&Plik") self.fileMenu.addAction(self.openAct) self.fileMenu.addAction(self.saveAct) self.fileMenu.addSeparator() self.fileMenu.addAction(self.exitAct) self.filterMenu = self.menuBar().addMenu("&Filtry") self.filterMenu.addAction(self.runWordFilter) self.filterMenu.addAction(self.FilterManager) self.excelMenu = self.menuBar().addMenu("&Raporty") self.excelMenu.addAction(self.showExcelForm) self.excelMenu.addAction(self.ConnectRaports) self.excelMenu.addAction(self.FindDuplicate) def contextMenuEvent(self, event): contextMenu = QMenu(self) removeAction = contextMenu.addAction('Usuń') action = contextMenu.exec_(self.mapToGlobal(event.pos())) if action == removeAction: index_list = [] for model_index in self.table.selectionModel().selectedRows(): index = QPersistentModelIndex(model_index) index_list.append(index) for index in index_list: self.sti.removeRow(index.row()) def createStatusBar(self): self.statusBar().showMessage("Ready") def readSettings(self): settings = QSettings("Trolltech", "Application Example") pos = settings.value("pos", QPoint(200, 200)) size = settings.value("size", QSize(800, 800)) self.resize(size) self.move(pos) def get_data(self, paths, compative_name): """ receives data from the filechose form :param paths: dictionary with paht to techege, adexpert :param compative_name: name of raport :return: """ self.compative_name = compative_name if len(paths[0]) > 0: self.techegedata = Excel.get_data(paths[0]) else: self.techegedata = None if len(paths[1]) > 0: self.adxpert = Excel.get_data(paths[1], False) else: self.adxpert = None #wczytanie arkusza z bazy danych session = Session() self.compativedata = session.query(Competitive).filter_by( name=compative_name).first() self.populate_row() session.close() def populate_row(self): """ read data from compatiedate, techegedata, adxpert and past to rows :return: """ # without this section data in column one don't show self.sti.setRowCount(0) self.sti.setRowCount(1) font = QFont() font.setPointSize(8) #add data from data base if self.compativedata: for row in self.compativedata.datas: rownr = self.sti.rowCount() rowvalue = row.values() for nr, value in enumerate(rowvalue): item = QStandardItem(f'{value}') item.setFont(font) self.sti.setItem(rownr - 1, nr, item) self.sti.setRowCount(rownr + 1) #add data from techegedata if self.techegedata: for rownr in range(len(self.techegedata[0])): self.sti.setRowCount(self.sti.rowCount() + 1) for colnr in range(len(self.techegedata)): if len(self.techegedata[colnr]) == 0: continue item = QStandardItem(f'{self.techegedata[colnr][rownr]}') item.setFont(font) self.sti.setItem(self.sti.rowCount() - 2, colnr, item) #add data from adexpert if self.adxpert: for rownr in range(len(self.adxpert[0])): self.sti.setRowCount(self.sti.rowCount() + 1) for colnr in range(len(self.adxpert)): if len(self.adxpert[colnr]) == 0: continue item = QStandardItem(f'{self.adxpert[colnr][rownr]}') item.setFont(font) self.sti.setItem(self.sti.rowCount() - 2, colnr, item) self.sti.removeRow(self.sti.rowCount() - 1) self.table.horizontalHeader().setSectionResizeMode( QHeaderView.ResizeToContents) QMessageBox.information(self, "Dane", "Dane zostały wczytane") def showfilterforms(self, i): """ Show filters for collumn nr" :param i: :return: """ session = Session() filter_ = session.query(FilterF).filter_by(column_nr=i).one_or_none() if filter_ is not None and filter_.type == 'manual': columns = self.prapercolumns(filter_.columns) headersname = [self.headers[i] for i in filter_.columns] self.filter = FiltersForm(filter_.id, columns, headersname, self) self.filter.show() session.close() def show_excel_form(self): """ Show excel form :return: """ self.excel_form.set_compatives() self.excel_form.show() def show_connect_raports(self): """ Show connect rapot :return: """ self.connect_form.set_raports() self.connect_form.show() def show_duplicate_form(self): """ show duplicate form """ self.for_find_duplicate.set_raports() self.for_find_duplicate.show() def show_filter_manager(self): """ show filter manager form """ self.filters_manager.show() def prapercolumns(self, columns): """ get unic data from sending columns :param args: :return: """ mainlist = [] for col in columns: collist = [] for row in range(self.sti.rowCount()): if self.sti.item(row, col) is not None: collist.append(self.sti.item(row, col).text()) mainlist.append(collist) return list(set(zip(*mainlist))) def replace_column(self, col_nr, assignded_column): """ replace column with new data :param col_nr: :param assignded_column: :return: """ self.sti.takeColumn(col_nr) self.sti.insertColumn(col_nr, assignded_column) self.sti.setHorizontalHeaderLabels(self.headers) self.set_color_on_header() """ Filters """ def assign_value_for_filter(self, filter_id, show=True): """ preper list with value from main filter, send it to make_filter_list. Replace column for filter_id with column with assigned data :param filter_id: :return: """ session = Session() filter_ = session.query(FilterF).get(filter_id) rows = [] for row in range(self.sti.rowCount()): row_value = [ self.sti.item(row, col).text() for col in filter_.columns ] rows.append(row_value) read_rows = self.make_filter_list(filter_id, rows) col_nr = filter_.column_nr self.sti.takeColumn(col_nr) self.sti.insertColumn(col_nr, read_rows) self.sti.setHorizontalHeaderLabels(self.headers) session.close() self.set_color_on_header() if show: QMessageBox.information(self, "Informacja", "Operacja zakończona.") @staticmethod def make_filter_list(filter_id, rows): """ make list with assigned value :param filter_id: :param rows: :return: """ session = Session() filter_ = session.query(FilterF).get(filter_id) ready_valus = [] for row in rows: flag = False row = [i.strip().lower() for i in row] for category in filter_.categorys: items = [[b.strip().lower() for b in a] for a in category.items] if row in items: #make QStandardItem to make column in sti model item = QStandardItem(str(category.name)) ready_valus.append(item) flag = True if flag is False: item = QStandardItem('') ready_valus.append(item) session.close() return ready_valus """ filters: words, cut """ def run_filters(self): """ make filters :return: """ session = Session() # filters_ = session.query(FilterF).filter_by(type='words').all() filters_ = session.query(FilterF).all() for fil in filters_: if fil.type == 'words': rows = self.get_data_from_columns(fil.columns) assignded_column = self.make_words_list(fil.id, rows) self.replace_column(fil.column_nr, assignded_column) elif fil.type == 'cut': if fil.name == 'model': rows = self.get_data_from_columns(fil.columns) assignded_column = self.filter_cut_model(rows) self.replace_column(fil.column_nr, assignded_column) elif fil.name == 'subbrand_brand_model': rows = self.get_data_from_columns(fil.columns) assignded_column = self.join_columns(rows) self.replace_column(fil.column_nr, assignded_column) session.close() QMessageBox.information(self, "Informacja", "Operacja zakończona.") def get_data_from_columns(self, columns_nr): """ get data for sending columns :param columns_nr: :return: return list of value from table """ rows = [] for row in range(self.sti.rowCount()): row_value = [] for col in columns_nr: if self.sti.item(row, col) is not None: row_value.append(self.sti.item(row, col).text()) else: row_value.append('') # row_value = [self.sti.item(row, col).text() for col in columns_nr] rows.append(row_value) return rows @staticmethod def make_words_list(filter_id, rows): """ make words list for filters, if find word in list assigned name of category :param filter_id: :param rows: :return: """ session = Session() filter_ = session.query(FilterF).get(filter_id) ready_valus = [] for row in rows: flag = False row = [i.lower() for i in row] row = ' '.join(row) for category in filter_.categorys: words = [b.lower() for b in category.words] for word in words: if word in row: item = QStandardItem(str(category.name)) ready_valus.append(item) flag = True break if flag is False: item = QStandardItem('') ready_valus.append(item) session.close() return ready_valus def filter_cut_model(self, rows): """ cut ferst word from string :param rows: :return: """ ready_values = [] for row in rows: item = QStandardItem((row[1].replace(row[0], '')).strip()) ready_values.append(item) return ready_values def join_columns(self, rows): """ join column in list rows """ temp = [QStandardItem(' '.join(x)) for x in rows] return temp def set_color_on_header(self): """ changes the color of the header :return: """ session = Session() filtersf = session.query(FilterF).all() for filterf in filtersf: if filterf.type == 'manual': self.table.model().setHeaderData(filterf.column_nr, Qt.Horizontal, QBrush(QColor(121, 166, 210)), Qt.BackgroundRole) self.table.model().setHeaderData( filterf.column_nr, Qt.Horizontal, self.headers[filterf.column_nr], Qt.DisplayRole) if filterf.type in ('words', 'cut'): self.table.model().setHeaderData(filterf.column_nr, Qt.Horizontal, QBrush(QColor(212, 214, 219)), Qt.BackgroundRole) self.table.model().setHeaderData( filterf.column_nr, Qt.Horizontal, self.headers[filterf.column_nr], Qt.DisplayRole) session.close()
class StatsManager: GROUP_BY = ['filename', 'lineno', 'traceback'] # index in the combo box GROUP_BY_FILENAME = 0 GROUP_BY_LINENO = 1 GROUP_BY_TRACEBACK = 2 def __init__(self, window, app): self.app = app self.window = window self.snapshots = window.snapshots self.source = window.source self.filename_parts = 3 self._auto_refresh = False self.filters = [] self.history = History(self) self.model = StatsModel(self) self.view = QTableView(window) self.view.setModel(self.model) self.cumulative_checkbox = QCheckBox(window.tr("Cumulative sizes"), window) self.group_by = QtGui.QComboBox(window) self.group_by.addItems([ window.tr("Filename"), window.tr("Line number"), window.tr("Traceback"), ]) self.filters_label = QLabel(window) self.summary = QLabel(window) self.view.verticalHeader().hide() self.view.resizeColumnsToContents() self.view.setSortingEnabled(True) window.connect(self.group_by, QtCore.SIGNAL("currentIndexChanged(int)"), self.group_by_changed) window.connect(self.view, QtCore.SIGNAL("doubleClicked(const QModelIndex&)"), self.double_clicked) window.connect(self.cumulative_checkbox, QtCore.SIGNAL("stateChanged(int)"), self.change_cumulative) window.connect(self.snapshots.load_button, QtCore.SIGNAL("clicked(bool)"), self.load_snapshots) window.connect( self.view.selectionModel(), QtCore.SIGNAL( "selectionChanged(const QItemSelection&, const QItemSelection&)" ), self.selection_changed) self.clear() self._auto_refresh = True def clear(self): del self.filters[:] self.cumulative_checkbox.setCheckState(Qt.Unchecked) self.group_by.setCurrentIndex(self.GROUP_BY_FILENAME) self.history.clear() self.append_history() self.refresh() def load_snapshots(self, checked): self.source.clear() self.clear() def append_history(self): group_by = self.group_by.currentIndex() filters = self.filters[:] cumulative = self.cumulative_checkbox.checkState() state = HistoryState(group_by, filters, cumulative) self.history.append(state) def restore_state(self, state): self.filters = state.filters[:] self._auto_refresh = False self.cumulative_checkbox.setCheckState(state.cumulative) self.group_by.setCurrentIndex(state.group_by) self._auto_refresh = True self.refresh() def format_filename(self, filename): parts = filename.split(os.path.sep) if len(parts) > self.filename_parts: parts = [MORE_TEXT] + parts[-self.filename_parts:] return os.path.join(*parts) def get_group_by(self): index = self.group_by.currentIndex() return self.GROUP_BY[index] def get_cumulative(self): return (self.cumulative_checkbox.checkState() == Qt.Checked) def refresh(self): group_by = self.get_group_by() if group_by != 'traceback': cumulative = self.get_cumulative() else: # FIXME: add visual feedback cumulative = False snapshot1, snapshot2 = self.snapshots.load_snapshots(self.filters) self.view.clearSelection() group_by = self.get_group_by() self.model.set_stats(snapshot1, snapshot2, group_by, cumulative) self.view.resizeColumnsToContents() self.view.sortByColumn(self.model.get_default_sort_column(), Qt.DescendingOrder) if self.filters: filters = [] for filter in self.filters: text = self.format_filename(filter.filename_pattern) if filter.lineno: text = "%s:%s" % (text, filter.lineno) if filter.all_frames: text += self.window.tr(" (any frame)") if filter.inclusive: text = fmt(self.window.tr("include %s"), text) else: text = fmt(self.window.tr("exclude %s"), text) filters.append(text) filters_text = ", ".join(filters) else: filters_text = self.window.tr("(none)") filters_text = fmt(self.window.tr("Filters: %s"), filters_text) self.filters_label.setText(filters_text) total = self.model.total_text lines = len(self.model.stats) if group_by == 'filename': lines = fmt(self.window.tr("Files: %s"), lines) elif group_by == 'lineno': lines = fmt(self.window.tr("Lines: %s"), lines) else: lines = fmt(self.window.tr("Tracebacks: %s"), lines) total = fmt(self.window.tr("%s - Total: %s"), lines, total) self.summary.setText(total) def selection_changed(self, selected, unselected): indexes = selected.indexes() if not indexes: return stat = self.model.get_stat(indexes[0]) if stat is None: return self.source.set_traceback(stat.traceback, self.get_group_by() != 'filename') self.source.show_frame(stat.traceback[0]) def double_clicked(self, index): stat = self.model.get_stat(index) if stat is None: return group_by = self.get_group_by() if group_by == 'filename': all_frames = self.get_cumulative() self.filters.append( tracemalloc.Filter(True, stat.traceback[0].filename, all_frames=all_frames)) self._auto_refresh = False self.group_by.setCurrentIndex(self.GROUP_BY_LINENO) self.append_history() self._auto_refresh = True self.refresh() elif group_by == 'lineno': # Replace filter by filename with filter by line new_filter = tracemalloc.Filter(True, stat.traceback[0].filename, stat.traceback[0].lineno, all_frames=False) if self.filters: old_filter = self.filters[-1] replace = (old_filter.inclusive == new_filter.inclusive and old_filter.filename_pattern == new_filter.filename_pattern and old_filter.lineno == None) else: replace = False if replace: self.filters[-1] = new_filter else: self.filters.append(new_filter) self._auto_refresh = False self.group_by.setCurrentIndex(self.GROUP_BY_TRACEBACK) self.append_history() self._auto_refresh = True self.refresh() def group_by_changed(self, index): if not self._auto_refresh: return self.append_history() self.refresh() def change_cumulative(self, state): if not self._auto_refresh: return self.append_history() self.refresh()
class App(QWidget): def __init__(self): super().__init__() self.title = 'Thermodynamic data' qd = QDesktopWidget() screen = qd.screenGeometry(qd) width = 600 height = 300 x = screen.width() / 2 - width / 2 y = screen.height() / 2 - height / 2 self.width = width self.height = height self.left = x self.top = y self.ignore_events = False self.initUI() def initUI(self): self.setWindowTitle(self.title) self.setGeometry(self.left, self.top, self.width, self.height) self.tableView1 = QTableView() self.tableWidget1 = QTableWidget() self.model = thTableModel() self.cas_filter = QLineEdit() self.name_filter = QLineEdit() self.formula_filter = QLineEdit() self.phase_filter = QComboBox() self.delete_selected_button = QPushButton() self.copy_selected_button = QPushButton() self.phases_vol_button = QPushButton() self.temp_text = QLineEdit() self.plot_window = PlotWindow() self.cp_button = QPushButton() self.psat_button = QPushButton() self.tableView1.setModel(self.model) self.tableWidget1.setColumnCount( self.tableView1.model().columnCount() + 1 + 1 + 1 + 1 + 1) self.widget_col_names = ['z_i', 'h_ig', 's_ig', 'g_ig', 'cp_ig' ] + self.tableView1.model().column_names self.widget_col_units = ['-', 'J/mol', 'J/mol/K', 'J/mol', 'J/mol/K' ] + self.tableView1.model().column_units self.widget_col_names_units = [ self.widget_col_names[i] + '\n' + self.widget_col_units[i] for i in range(len(self.widget_col_names)) ] self.tableWidget1.setHorizontalHeaderLabels( self.widget_col_names_units) self.phase_filter.addItems(['', 'G', 'L', 'S', 'C']) self.tableWidget1.setEnabled(False) self.tableWidget1.setSelectionBehavior(QTableWidget.SelectRows) self.tableWidget1.installEventFilter(self) self.delete_selected_button.setText('delete selected') self.copy_selected_button.setText('copy selected') self.phases_vol_button.setText('ph, v') self.temp_text.setValidator(QDoubleValidator(0, 6000, 16)) self.temp_text.setPlaceholderText('1000 K') # Add box layout, add table to box layout and add box layout to widget self.layout = QGridLayout() self.layout.addWidget(self.tableView1, 1, 1, 1, 4) self.layout.addWidget(self.cas_filter, 3, 1, 1, 1) self.layout.addWidget(self.name_filter, 3, 2, 1, 1) self.layout.addWidget(self.formula_filter, 3, 3, 1, 1) self.layout.addWidget(self.phase_filter, 3, 4, 1, 1) self.layout.addWidget(QLabel('find by: cas'), 2, 1, 1, 1) self.layout.addWidget(QLabel('name'), 2, 2, 1, 1) self.layout.addWidget(QLabel('formula'), 2, 3, 1, 1) self.layout.addWidget(QLabel('phase'), 2, 4, 1, 1) self.layout.addWidget(QLabel('selection'), 4, 1, 1, 4) self.layout.addWidget(self.tableWidget1, 5, 1, 1, 4) self.layout.addWidget(self.delete_selected_button, 6, 4, 1, 1) self.layout.addWidget(self.copy_selected_button, 6, 1, 1, 1) self.layout.addWidget(self.phases_vol_button, 6, 2, 1, 1) self.layout.addWidget(self.temp_text, 6, 3, 1, 1) self.setLayout(self.layout) for item in [self.cas_filter, self.name_filter, self.formula_filter]: item.textChanged.connect(self.apply_filters) self.phase_filter.currentTextChanged.connect(self.apply_filters) self.tableView1.selectionModel().selectionChanged.connect( partial(self.add_selection_to_widget)) self.tableWidget1.cellChanged.connect(partial(self.update_props)) self.delete_selected_button.clicked.connect( partial(self.delete_selected)) self.copy_selected_button.clicked.connect(partial(self.copy_selection)) self.phases_vol_button.clicked.connect(partial(self.phases_vol)) self.temp_text.editingFinished.connect(partial(self.update_temp)) #self.tableView1.horizontalHeader().setClickable(False) self.props_i = self.tableView1.model().df.iloc[[]] self.props_i['z_i'] = zeros(0) self.props_i['h_ig'] = zeros(0) self.props_i['s_ig'] = zeros(0) self.props_i['g_ig'] = zeros(0) self.props_i['cp_ig'] = zeros(0) # Show widget self.show() def apply_filters(self): cas_filter = self.cas_filter.text().upper().strip().replace(' ', '') name_filter = self.name_filter.text().upper().strip() formula_filter = self.formula_filter.text().upper().strip() phase_filter = self.phase_filter.currentText() self.model.apply_filter(cas_filter, name_filter, formula_filter, phase_filter) def add_selection_to_widget(self, selected, deselected): # indexes = self.tableView1.selectedIndexes() indexes = selected.indexes() index = indexes[0] column_of_cas = self.tableView1.model().column_names.index('cas_no') column_of_phase = self.tableView1.model().column_names.index('phase') phase = self.tableView1.model().index(index.row(), column_of_phase).data() cas = self.tableView1.model().index(index.row(), column_of_cas).data() already_in_table = False for item in self.tableWidget1.findItems(cas, Qt.MatchExactly): if phase == self.tableWidget1.item( item.row(), column_of_phase + 1 + 1 + 1 + 1 + 1).text(): already_in_table = True if not already_in_table: row_index = int(self.tableView1.model().headerData( index.row(), Qt.Vertical)) column_names = self.tableView1.model().column_names header_to_add = QTableWidgetItem(str(row_index)) # save df with new props z_i_orig = self.props_i['z_i'] h_ig_orig = self.props_i['h_ig'] s_ig_orig = self.props_i['s_ig'] g_ig_orig = self.props_i['g_ig'] cp_ig_orig = self.props_i['cp_ig'] index_orig = self.props_i.index self.props_i = self.tableView1.model().df.loc[[ int(self.tableWidget1.verticalHeaderItem(i).text()) for i in range(self.tableWidget1.rowCount()) ] + [row_index], :] self.props_i['z_i'] = zeros(len(self.props_i)) self.props_i['h_ig'] = zeros(len(self.props_i)) self.props_i['s_ig'] = zeros(len(self.props_i)) self.props_i['g_ig'] = zeros(len(self.props_i)) self.props_i['cp_ig'] = zeros(len(self.props_i)) self.props_i.loc[index_orig, 'z_i'] = z_i_orig self.props_i.loc[index_orig, 'h_ig'] = h_ig_orig self.props_i.loc[index_orig, 's_ig'] = s_ig_orig self.props_i.loc[index_orig, 'g_ig'] = g_ig_orig self.props_i.loc[index_orig, 'cp_ig'] = cp_ig_orig self.props_i.loc[row_index, 'z_i'] = float(0) # add item to widget self.tableWidget1.setRowCount(self.tableWidget1.rowCount() + 1) self.tableWidget1.setVerticalHeaderItem( self.tableWidget1.rowCount() - 1, header_to_add) for i in range(len(column_names)): # columns in TableWidget shifted by 1+1+1+1+1 vs. Tableview due to first columns z_i, h_ig, s_ig, g_ig, cp_ig data = self.tableView1.model().index(index.row(), i).data() if isinstance(data, str) or data is None: item_to_add = QTableWidgetItem(data) else: item_to_add = QTableWidgetItem(locale.str(data)) item_to_add.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled | Qt.ItemIsEditable) self.tableWidget1.setItem(self.tableWidget1.rowCount() - 1, i + 1 + 1 + 1 + 1 + 1, item_to_add) # additional column with z_i item_to_add = QTableWidgetItem(locale.str(0)) item_to_add.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled | Qt.ItemIsEditable) self.tableWidget1.setItem(self.tableWidget1.rowCount() - 1, 0, item_to_add) if len(indexes) > 0 or self.tableWidget1.rowCount() > 0: self.tableWidget1.setEnabled(True) def update_props(self, row, col): if col == 0: # change z_i df_index = int(self.tableWidget1.verticalHeaderItem(row).text()) new_value = float( self.tableWidget1.item(row, col).text().replace(',', '.')) self.props_i.loc[df_index, 'z_i'] = new_value else: pass def update_temp(self): if self.temp_text.hasAcceptableInput(): self.temp_text.setPlaceholderText(self.temp_text.text() + ' K') t = float(self.temp_text.text().replace(',', '.')) # K self.temp_text.clear() else: t = 1000 # K self.temp_text.clear() mm_i = (self.props_i['poling_molwt'] / 1000).tolist() # kg/mol tc_i = self.props_i['poling_tc'].tolist() # K pc_i = (self.props_i['poling_pc'] * 1e5).tolist() # Pa omega_i = self.props_i['poling_omega'].tolist() vc_i = (self.props_i['poling_vc'] * 10**-6).tolist() # m^3/mol delhf0_poling = (self.props_i['poling_delhf0'] * 1000).tolist() # J/mol delgf0_poling = (self.props_i['poling_delgf0'] * 1000).tolist() # J/mol delsf0_poling = [(delhf0_poling[i] - delgf0_poling[i]) / 298.15 for i in range(len(self.props_i))] # J/mol/K a_low = [ self.props_i['a' + str(i) + '_low'].tolist() for i in range(1, 7 + 1) ] a_high = [ self.props_i['a' + str(i) + '_high'].tolist() for i in range(1, 7 + 1) ] cp_r_low = [ sum([a_low[j][i] * t**j for j in range(4 + 1)]) for i in range(len(self.props_i)) ] # cp/R cp_r_high = [ sum([a_high[j][i] * t**j for j in range(4 + 1)]) for i in range(len(self.props_i)) ] # cp/R if t > 1000: # poly a_low is for 200 - 1000 K; a_high is for 1000 - 6000 K a = a_high cp_ig = [8.3145 * cp_r_high[i] for i in range(len(self.props_i))] # J/mol/K else: a = a_low cp_ig = [8.3145 * cp_r_low[i] for i in range(len(self.props_i))] # J/mol/K s_cp_r_dt = [ sum([1 / (j + 1) * a[j][i] * t**(j + 1) for j in range(4 + 1)]) - sum([ 1 / (j + 1) * a_low[j][i] * 298.15**(j + 1) for j in range(4 + 1) ]) for i in range(len(self.props_i)) ] # int(Cp/R*dT,298,15K,T) # int(Cp/R/T*dT,298.15K,T) s_cp_r_t_dt = [ a[0][i] * log(t) + a[6][i] + sum([1 / (j) * a[j][i] * t**(j) for j in range(1, 3 + 1)]) for i in range(len(self.props_i)) ] # int(Cp/(RT)*dT,0,T) h_ig = [ delhf0_poling[i] + 8.3145 * s_cp_r_dt[i] for i in range(len(self.props_i)) ] s_ig = [8.3145 * s_cp_r_t_dt[i] for i in range(len(self.props_i))] g_ig = [h_ig[i] - t * s_ig[i] for i in range(len(self.props_i))] for i in range(len(self.props_i)): for j, col in enumerate([h_ig, s_ig, g_ig, cp_ig]): #print(col) item_to_add = QTableWidgetItem(locale.str(col[i])) item_to_add.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled | Qt.ItemIsEditable) self.tableWidget1.setItem(i, j + 1, item_to_add) def copy_selection(self): selection = self.tableWidget1.selectedIndexes() if selection: rows = sorted(index.row() for index in selection) columns = range(len(self.widget_col_names)) rowcount = rows[-1] - rows[0] + 1 colcount = columns[-1] - columns[0] + 1 + 1 table = [[''] * colcount for _ in range(rowcount + 1)] table[0] = [] for i in range(len(self.widget_col_names)): text_to_add = self.widget_col_names[ i] + '/(' + self.widget_col_units[i] + ')' table[0] += [text_to_add] for index in selection: row = index.row() - rows[0] column = index.column() - columns[0] table[row + 1][column] = index.data().replace( chr(34), '' ) # ensure string can be read as csv by removing quotation mark (ascii character 34) table = table + [['T=' + self.temp_text.placeholderText()] + ['' for _ in range(colcount - 1)]] stream = io.StringIO() csv.writer(stream, delimiter=';', quoting=csv.QUOTE_NONE).writerows(table) QApplication.clipboard().setText(stream.getvalue()) def eventFilter(self, source, event): if self.ignore_events: pass elif (event.type() == QEvent.KeyPress and event.matches(QKeySequence.Copy)): self.copy_selection() return True elif (event.type() == QEvent.KeyPress and event.matches(QKeySequence.Delete)): if len(self.tableWidget1.selectedIndexes()) > 1: self.delete_selected() return True return super(App, self).eventFilter(source, event) def delete_selected(self): if len(self.tableWidget1.selectedIndexes()) > 0: while len(self.tableWidget1.selectedIndexes()) > 0: current_row = self.tableWidget1.selectedIndexes()[0].row() row_index = int( self.tableWidget1.verticalHeaderItem(current_row).text()) self.tableWidget1.removeRow(current_row) self.props_i = self.props_i.drop([row_index]) self.tableWidget1.selectRow(current_row) if self.tableWidget1.rowCount() == 0: self.tableWidget1.setEnabled(False) def phases_vol(self): self.plot_window.show() t = linspace(60, 220, 10) p = 1.01325 # bar phase_fraction = empty_like(t) v_l = empty_like(t) v_v = empty_like(t) z_i = self.props_i['z_i'] # normalize z_i sum_z_i = sum(z_i) if sum_z_i <= 0: z_i = 1 / len(z_i) * ones(len(z_i)) z_i = z_i.tolist() elif sum_z_i != 1.0: z_i = z_i / sum_z_i z_i = z_i.to_list() else: z_i = z_i.to_list() mm_i = (self.props_i['poling_molwt'] / 1000).tolist() # kg/mol tc_i = self.props_i['poling_tc'].tolist() # K pc_i = (self.props_i['poling_pc']).tolist() # bar omega_i = self.props_i['poling_omega'].tolist() vc_i = (self.props_i['poling_vc'] * 10**-6).tolist() # m^3/mol state = State(t[0], p, z_i, mm_i, tc_i, pc_i, omega_i, 'pr') for i in range(len(t)): state.set_t(t[i]) phase_fraction[i] = state.v_f v_l[i] = state.v_l v_v[i] = state.v_v self.plot_window.ax[0].plot(t, phase_fraction) self.plot_window.ax[0].set_xlabel('T / K') self.plot_window.ax[0].set_xlabel('V / F') self.plot_window.ax[1].semilogy(t, v_l, label='v_l') self.plot_window.ax[1].semilogy(t, v_v, label='v_v') self.plot_window.ax[1].set_xlabel('T / K') self.plot_window.ax[1].set_xlabel(r'$\frac{V}{m^3 / mol}$') self.plot_window.ax[1].legend() self.plot_window.fig.tight_layout()
class AddressWidget(QDialog): selectionChanged = Signal(QItemSelection) def __init__(self, parent=None): super(AddressWidget, self).__init__(parent) self.tableModel = TableModel() self.tableView = QTableView() self.setupTable() statusLabel = QLabel("Tabular data view demo") layout = QVBoxLayout() layout.addWidget(self.tableView) layout.addWidget(statusLabel) self.setLayout(layout) self.setWindowTitle("Address Book") self.resize(800, 500) # add test data self.populateTestData() def setupTable(self): proxyModel = QSortFilterProxyModel(self) proxyModel.setSourceModel(self.tableModel) proxyModel.setDynamicSortFilter(True) self.tableView.setModel(proxyModel) self.tableView.setSortingEnabled(True) self.tableView.setSelectionBehavior(QAbstractItemView.SelectRows) self.tableView.horizontalHeader().setStretchLastSection(True) self.tableView.verticalHeader().hide() self.tableView.setEditTriggers(QAbstractItemView.NoEditTriggers) self.tableView.setSelectionMode(QAbstractItemView.SingleSelection) proxyModel.setFilterKeyColumn(0) # Filter on the "name" column proxyModel.sort(0, Qt.AscendingOrder) viewselectionmodel = self.tableView.selectionModel() self.tableView.selectionModel().selectionChanged.connect( self.selectionChanged) def populateTestData(self): addresses = [{ "name": "John Doe", "address": "Alameda" }, { "name": "Alan Turing", "address": "San Deigo" }, { "name": "Bjarne Stroutsup", "address": "Columbia" }, { "name": "Herb Sutter", "address": "Seattle" }, { "name": "Micheal Konin", "address": "Colorado" }] for i in range(len(addresses)): self.tableModel.insertRows(0) ix = self.tableModel.index(0, 0, QModelIndex()) self.tableModel.setData(ix, addresses[i]["name"], Qt.EditRole) ix = self.tableModel.index(0, 1, QModelIndex()) self.tableModel.setData(ix, addresses[i]["address"], Qt.EditRole) self.tableView.resizeRowToContents(ix.row())
class IndirectBranchSetterWidget(QDialog): def __init__(self, bv, addr, parent=None): super(IndirectBranchSetterWidget, self).__init__(parent) self.bv = bv self.indirect_jmp_addr = addr # @@FIXME: What happens when there is more than one function for the same addr self.func = self.bv.get_functions_containing(self.indirect_jmp_addr)[0] # Setup widget properties self.setWindowModality(Qt.NonModal) self.showNormal() # Makes 'Qt.NonModal' work. Why? title = QLabel( self.tr("Indirect Branch Editor (for 0x%x)" % (self.indirect_jmp_addr))) self.setWindowTitle(title.text()) # Table initial_data = [] for i in self.func.get_indirect_branches_at(self.indirect_jmp_addr): initial_data.append([i.dest_arch, int(i.dest_addr)]) self.table_model = IndirectBranchModel(initial_data, [self.bv.arch, 0], parent=self) self.table_view = QTableView() self.table_view.setModel(self.table_model) # Buttons and line edit self.line_edit_new_branch = QLineEdit() button_insert_row = QPushButton("Insert branch") button_insert_row.clicked.connect(self.insert_row_clicked) button_remove_row = QPushButton("Remove selected") button_remove_row.clicked.connect(self.remove_row_clicked) button_set_indirect_branches = QPushButton("Done") button_set_indirect_branches.clicked.connect( self.set_indirect_branches_clicked) # Buttons layout buttons_layout = QHBoxLayout() buttons_layout.addWidget(self.line_edit_new_branch) buttons_layout.addWidget(button_insert_row) buttons_layout.addWidget(button_remove_row) buttons_layout.addWidget(button_set_indirect_branches) # Main layout layout = QVBoxLayout(self) layout.addWidget(self.table_view) layout.addLayout(buttons_layout) self.setLayout(layout) def insert_row_clicked(self): new_addrs_str = self.line_edit_new_branch.text().strip() new_addrs_str = new_addrs_str.split(",") for addr_str in new_addrs_str: self.table_model.append_row(addr_str.strip()) def remove_row_clicked(self): select = self.table_view.selectionModel() if select.hasSelection(): rows_selected = set() for i in select.selectedIndexes(): rows_selected.add(i.row()) assert len(rows_selected) >= 1 # Hopefully this sort is enough to delete the correct rows. sorted_rows_selected = sorted(list(rows_selected), reverse=True) for row in sorted_rows_selected: self.table_model.removeRows(row) else: log_error("No selection to remove") def set_indirect_branches_clicked(self): branches = self.table_model.branches log_debug("Setting 0x%x's indirect branches to: %s" % (self.indirect_jmp_addr, branches)) self.func.set_user_indirect_branches(self.indirect_jmp_addr, branches) self.accept()
class TdisMainForm(QMainWindow): def __init__(self, parent=None): super().__init__() self.setWindowTitle("Родословная") self.resize(800, self.height()) self.distance = 1000 self.central_widget = QWidget() self.setCentralWidget(self.central_widget) layout = QGridLayout() self.central_widget.setLayout(layout) self.lb_find = QInvisibleButton('Поиск') self.lb_find.setFont(mainfont) self.te_find = QLineEdit() self.te_find.setFont(mainfont) layout.addWidget(self.te_find, 0, 0, 1, 1) layout.addWidget(self.lb_find, 0, 0, 1, 1) #if mode: # te.setReadOnly(False) self.lb_find.clicked.connect(self.button_pressed) self.te_find.returnPressed.connect(self.line_edit_return_pressed) self.table = QTableView() # Создаём таблицу self.table.doubleClicked.connect(self.viewPerson) layout.addWidget(self.table) self.table.setFocus() timer = QTimer(self) timer.singleShot(0, self.async_init) def async_init(self): self.database = AllTables('database/objects') self.model = TableModel(self.database.get_peoples()) self.table.setModel(self.model) self.table.resizeRowsToContents() self.table.setSelectionBehavior(QAbstractItemView.SelectRows) self.model.dataChanged.connect(self.table.update) # Работаем с выпадающим меню def openMenu(position): menu = QMenu() relAction = menu.addAction('Связи') menu.addSeparator() albAction = menu.addAction('Альбомы') menu.addSeparator() miniatureAction = menu.addAction('Миниатюра') menu.addSeparator() viewAction = menu.addAction('Просмотреть') addAction = menu.addAction('Добавить') editAction = menu.addAction('Редактировать') delAction = menu.addAction('Удалить') menu.addSeparator() drawGraphAction = menu.addAction('Построить дерево') menu.addSeparator() quitAction = menu.addAction('Выход') action = menu.exec_(self.table.mapToGlobal(position)) if action == viewAction: self.viewPerson() if action == miniatureAction: p = self.get_selected_people() print('p = ' + str(p)) if p is not None: photo_ids = self.database.get_all_photo_ids(p['pid']) path = 0 if photo_ids and type(photo_ids) == type( []) and len(photo_ids) > 0: path = self.database.get_photo_path( p['pid'], photo_ids[0]) gm = GalleryMiniature(p['pid'], path) gm.exec() if action == albAction: p = self.get_selected_people() if p is not None: self.albuns = AlbumViewer(p['pid'], self.database, 1) self.albuns.show() if action == addAction: self.personal_card = PersonalCard( self.database.get_people(self.database.add_people({})), self.database, 1) self.personal_card.exec_() self.line_edit_return_pressed() if action == editAction: p = self.get_selected_people() if p is not None: self.personal_card = PersonalCard(p, self.database, 1) self.personal_card.exec_() self.line_edit_return_pressed() if action == delAction: res = QMessageBox.question( self, 'ВНИМАНИЕ!!!', "Вы действительно хотите выполнить удаление?", QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if res == QMessageBox.Yes: select = self.table.selectionModel() if select.hasSelection(): id_list = [ index.data() for index in self.table.selectionModel().selection().indexes() if index.column() == 0 ] print(id_list) self.database.del_people(id_list) self.database.peoples.save() for pid in id_list: print('remove = ' + str(self.model.removeRow(pid))) self.line_edit_return_pressed() if action == relAction: pid = self.get_selected_pid() backup_relations = copy.deepcopy(self.database.relations) self.relation_card = RelationCard(pid, self.database, 2) if not self.relation_card.exec_(): self.database.relations = backup_relations if action == drawGraphAction: print('draw graph') #dialog = MyDialog() #dialog.exec_() #engine = dialog.engine engine = 'dot' self.gd = GraphDrawer(self.database, engine) if action == quitAction: qApp.quit() self.table.setContextMenuPolicy(Qt.CustomContextMenu) self.table.customContextMenuRequested.connect(openMenu) def get_selected_pid(self): pid_list = [ index.data() for index in self.table.selectionModel().selection().indexes() if index.column() == 0 ] if len(pid_list) == 1: return int(pid_list[0]) return None def get_selected_people(self): pid_list = [ index.data() for index in self.table.selectionModel().selection().indexes() if index.column() == 0 ] if len(pid_list) == 1: return self.database.get_people(int(pid_list[0])) return None def viewPerson(self): p = self.get_selected_people() if p is not None: self.personal_card = PersonalCard(p, self.database, 0) self.personal_card.show() def button_pressed(self): self.lb_find.stackUnder(self.te_find) self.te_find.setFocus() def line_edit_return_pressed(self): print(self.te_find.text()) self.model = TableModel(self.database.get_peoples()) self.proxy_model = QSortFilterProxyModel(self.model) self.proxy_model.setSourceModel(self.model) self.proxy_model.setFilterFixedString(self.te_find.text()) self.proxy_model.setFilterKeyColumn(-1) self.table.setModel(self.proxy_model) self.table.update() self.table.resizeRowsToContents() #sender = self.sender() self.te_find.stackUnder(self.lb_find) self.lb_find.setFocus()
class MainWindow(QMainWindow): def __init__(self): super().__init__() hlayout = QHBoxLayout() layout = QVBoxLayout() self.filtert = QLineEdit() self.filtert.setPlaceholderText("Search...") self.table = QTableView() vlayout = QVBoxLayout() vlayout.addWidget(self.filtert) vlayout.addWidget(self.table) # Left/right pane. hlayout.addLayout(vlayout) hlayout.addLayout(layout) form = QFormLayout() self.track_id = QSpinBox() self.track_id.setDisabled(True) self.track_id.setRange(0, 2147483647) self.name = QLineEdit() self.album = QComboBox() self.media_type = QComboBox() self.genre = QComboBox() self.composer = QLineEdit() self.milliseconds = QSpinBox() self.milliseconds.setRange(0, 2147483647) self.milliseconds.setSingleStep(1) self.bytes = QSpinBox() self.bytes.setRange(0, 2147483647) self.bytes.setSingleStep(1) self.unit_price = QDoubleSpinBox() self.unit_price.setRange(0, 999) self.unit_price.setSingleStep(0.01) self.unit_price.setPrefix("$") form.addRow(QLabel("Track ID"), self.track_id) form.addRow(QLabel("Track name"), self.name) form.addRow(QLabel("Composer"), self.composer) form.addRow(QLabel("Milliseconds"), self.milliseconds) form.addRow(QLabel("Bytes"), self.bytes) form.addRow(QLabel("Unit Price"), self.unit_price) self.model = QSqlTableModel(db=db) self.proxy_model = QSortFilterProxyModel() self.proxy_model.setSourceModel(self.model) self.proxy_model.sort(1, Qt.AscendingOrder) self.proxy_model.setFilterKeyColumn(-1) # all columns self.table.setModel(self.proxy_model) # Update search when filter changes. self.filtert.textChanged.connect(self.proxy_model.setFilterFixedString) self.mapper = QDataWidgetMapper() self.mapper.setModel(self.proxy_model) self.mapper.addMapping(self.track_id, 0) self.mapper.addMapping(self.name, 1) self.mapper.addMapping(self.composer, 5) self.mapper.addMapping(self.milliseconds, 6) self.mapper.addMapping(self.bytes, 7) self.mapper.addMapping(self.unit_price, 8) self.model.setTable("Track") self.model.select() # Change the mapper selection using the table. self.table.selectionModel().currentRowChanged.connect( self.mapper.setCurrentModelIndex) self.mapper.toFirst() # tag::controls[] self.setMinimumSize(QSize(800, 400)) controls = QHBoxLayout() prev_rec = QPushButton("Previous") prev_rec.clicked.connect(self.mapper.toPrevious) next_rec = QPushButton("Next") next_rec.clicked.connect(self.mapper.toNext) save_rec = QPushButton("Save Changes") save_rec.clicked.connect(self.mapper.submit) controls.addWidget(prev_rec) controls.addWidget(next_rec) controls.addWidget(save_rec) layout.addLayout(form) layout.addLayout(controls) widget = QWidget() widget.setLayout(hlayout) self.setCentralWidget(widget)
class IncomeSpendingWidget(AbstractOperationDetails): def __init__(self, parent=None): AbstractOperationDetails.__init__(self, parent) self.name = "Income/Spending" self.details_model = None self.category_delegate = CategorySelectorDelegate() self.tag_delegate = TagSelectorDelegate() self.float_delegate = FloatDelegate(2) self.date_label = QLabel(self) self.details_label = QLabel(self) self.account_label = QLabel(self) self.peer_label = QLabel(self) self.main_label.setText(g_tr("IncomeSpendingWidget", "Income / Spending")) self.date_label.setText(g_tr("IncomeSpendingWidget", "Date/Time")) self.details_label.setText(g_tr("IncomeSpendingWidget", "Details")) self.account_label.setText(g_tr("IncomeSpendingWidget", "Account")) self.peer_label.setText(g_tr("IncomeSpendingWidget", "Peer")) self.timestamp_editor = QDateTimeEdit(self) self.timestamp_editor.setCalendarPopup(True) self.timestamp_editor.setTimeSpec(Qt.UTC) self.timestamp_editor.setFixedWidth(self.timestamp_editor.fontMetrics().width("00/00/0000 00:00:00") * 1.25) self.timestamp_editor.setDisplayFormat("dd/MM/yyyy hh:mm:ss") self.account_widget = AccountSelector(self) self.peer_widget = PeerSelector(self) self.a_currency = OptionalCurrencyComboBox(self) self.a_currency.setText(g_tr("IncomeSpendingWidget", "Paid in foreign currency:")) self.add_button = QPushButton(self) self.add_button.setText(" +️ ") self.add_button.setFont(self.bold_font) self.add_button.setFixedWidth(self.add_button.fontMetrics().width("XXX")) self.del_button = QPushButton(self) self.del_button.setText(" — ️") self.del_button.setFont(self.bold_font) self.del_button.setFixedWidth(self.del_button.fontMetrics().width("XXX")) self.copy_button = QPushButton(self) self.copy_button.setText(" >> ️") self.copy_button.setFont(self.bold_font) self.copy_button.setFixedWidth(self.copy_button.fontMetrics().width("XXX")) self.details_table = QTableView(self) self.details_table.horizontalHeader().setFont(self.bold_font) self.details_table.setAlternatingRowColors(True) self.details_table.verticalHeader().setVisible(False) self.details_table.verticalHeader().setMinimumSectionSize(20) self.details_table.verticalHeader().setDefaultSectionSize(20) self.layout.addWidget(self.date_label, 1, 0, 1, 1, Qt.AlignLeft) self.layout.addWidget(self.details_label, 2, 0, 1, 1, Qt.AlignLeft) self.layout.addWidget(self.timestamp_editor, 1, 1, 1, 4) self.layout.addWidget(self.add_button, 2, 1, 1, 1) self.layout.addWidget(self.copy_button, 2, 2, 1, 1) self.layout.addWidget(self.del_button, 2, 3, 1, 1) self.layout.addWidget(self.account_label, 1, 5, 1, 1, Qt.AlignRight) self.layout.addWidget(self.peer_label, 2, 5, 1, 1, Qt.AlignRight) self.layout.addWidget(self.account_widget, 1, 6, 1, 1) self.layout.addWidget(self.peer_widget, 2, 6, 1, 1) self.layout.addWidget(self.a_currency, 1, 7, 1, 1) self.layout.addWidget(self.commit_button, 0, 9, 1, 1) self.layout.addWidget(self.revert_button, 0, 10, 1, 1) self.layout.addWidget(self.details_table, 4, 0, 1, 11) self.layout.addItem(self.horizontalSpacer, 1, 8, 1, 1) self.add_button.clicked.connect(self.addChild) self.del_button.clicked.connect(self.delChild) super()._init_db("actions") self.mapper.setItemDelegate(IncomeSpendingWidgetDelegate(self.mapper)) self.details_model = DetailsModel(self.details_table, db_connection()) self.details_model.setTable("action_details") self.details_model.setEditStrategy(QSqlTableModel.OnManualSubmit) self.details_table.setModel(self.details_model) self.details_model.dataChanged.connect(self.onDataChange) self.account_widget.changed.connect(self.mapper.submit) self.peer_widget.changed.connect(self.mapper.submit) self.a_currency.changed.connect(self.mapper.submit) self.a_currency.updated.connect(self.details_model.setAltCurrency) self.mapper.addMapping(self.timestamp_editor, self.model.fieldIndex("timestamp")) self.mapper.addMapping(self.account_widget, self.model.fieldIndex("account_id")) self.mapper.addMapping(self.peer_widget, self.model.fieldIndex("peer_id")) self.mapper.addMapping(self.a_currency, self.model.fieldIndex("alt_currency_id")) self.details_table.setItemDelegateForColumn(2, self.category_delegate) self.details_table.setItemDelegateForColumn(3, self.tag_delegate) self.details_table.setItemDelegateForColumn(4, self.float_delegate) self.details_table.setItemDelegateForColumn(5, self.float_delegate) self.model.select() self.details_model.select() self.details_model.configureView() def setId(self, id): super().setId(id) self.details_model.setFilter(f"action_details.pid = {id}") @Slot() def addChild(self): new_record = self.details_model.record() new_record.setNull("tag_id") new_record.setValue("amount", 0) new_record.setValue("amount_alt", 0) if not self.details_model.insertRecord(-1, new_record): logging.fatal( g_tr('AbstractOperationDetails', "Failed to add new record: ") + self.details_model.lastError().text()) return @Slot() def delChild(self): idx = self.details_table.selectionModel().selection().indexes() selected_row = idx[0].row() self.details_model.removeRow(selected_row) self.details_table.setRowHidden(selected_row, True) @Slot() def saveChanges(self): if not self.model.submitAll(): logging.fatal( g_tr('AbstractOperationDetails', "Operation submit failed: ") + self.model.lastError().text()) return pid = self.model.data(self.model.index(0, self.model.fieldIndex("id"))) if pid is None: # we just have saved new action record and need last inserted id pid = self.model.query().lastInsertId() for row in range(self.details_model.rowCount()): self.details_model.setData(self.details_model.index(row, self.details_model.fieldIndex("pid")), pid) if not self.details_model.submitAll(): logging.fatal(g_tr('AbstractOperationDetails', "Operation details submit failed: ") + self.details_model.lastError().text()) return self.modified = False self.commit_button.setEnabled(False) self.revert_button.setEnabled(False) self.dbUpdated.emit() return def createNew(self, account_id=0): super().createNew(account_id) self.details_model.setFilter(f"action_details.pid = 0") def prepareNew(self, account_id): new_record = self.model.record() new_record.setNull("id") new_record.setValue("timestamp", int(datetime.now().replace(tzinfo=tz.tzutc()).timestamp())) new_record.setValue("account_id", account_id) new_record.setValue("peer_id", 0) new_record.setValue("alt_currency_id", None) return new_record def copyNew(self): old_id = self.model.record(self.mapper.currentIndex()).value(0) super().copyNew() self.details_model.setFilter(f"action_details.pid = 0") query = executeSQL("SELECT * FROM action_details WHERE pid = :pid ORDER BY id DESC", [(":pid", old_id)]) while query.next(): new_record = query.record() new_record.setNull("id") new_record.setNull("pid") assert self.details_model.insertRows(0, 1) self.details_model.setRecord(0, new_record) def copyToNew(self, row): new_record = self.model.record(row) new_record.setNull("id") new_record.setValue("timestamp", int(datetime.now().replace(tzinfo=tz.tzutc()).timestamp())) return new_record
class TreeCard(QDialog): def __init__(self, db=0, mode=0): super().__init__() layout = QGridLayout() #self.central_widget.setLayout(layout) self.resize(800, self.height()) self.lb_find = QInvisibleButton('Поиск') self.lb_find.setFont(mainfont) self.te_find = QLineEdit() self.te_find.setFont(mainfont) self.pid = 0 layout.addWidget(self.te_find, 0, 0, 1, 1) layout.addWidget(self.lb_find, 0, 0, 1, 1) #if mode: # te.setReadOnly(False) self.lb_find.clicked.connect(self.button_pressed) self.te_find.returnPressed.connect(self.line_edit_return_pressed) self.database = db self.table = QTableView() # Создаём таблицу self.table.doubleClicked.connect(self.viewPerson) #self.table = table self.model = TableModel(self.database.get_peoples()) self.table.setModel(self.model) self.table.resizeRowsToContents() self.table.setSelectionBehavior(QAbstractItemView.SelectRows) #self.table.setSelectionMode(QAbstractItemView.SingleSelection); self.model.dataChanged.connect(self.table.update) layout.addWidget(self.table) self.setLayout(layout) def viewPerson(self): select = self.table.selectionModel() pid_list = [ index.data() for index in self.table.selectionModel().selection().indexes() if index.column() == 0 ] if len(pid_list) == 1: self.pid = int(pid_list[0]) print(int(pid_list[0])) self.accept() return 0 def button_pressed(self): #sender = self.sender() self.lb_find.stackUnder(self.te_find) self.te_find.setFocus() def line_edit_return_pressed(self): print(self.te_find.text()) self.model = TableModel(self.database.get_peoples()) self.proxy_model = QSortFilterProxyModel(self.model) self.proxy_model.setSourceModel(self.model) self.proxy_model.setFilterFixedString(self.te_find.text()) self.proxy_model.setFilterKeyColumn(-1) #print(self.proxy_model.filterKeyColumn()) self.table.setModel(self.proxy_model) self.table.update() self.table.resizeRowsToContents() #sender = self.sender() self.te_find.stackUnder(self.lb_find) self.lb_find.setFocus()
class SydTableWidget(QtWidgets.QWidget, Ui_SydTableWidget): table_reloaded = Signal() def __init__(self, filename, table_name, parent=None): super().__init__(parent) self.setupUi(self) # internal members self._filename = filename self._table_name = table_name self._db = None self._data = None self._model = None self._filter_proxy_model = None self._header = None self._toggle_width_menus = [] self.button_reload.clicked.connect(self.slot_on_reload) self.button_view.hide() self.button_view.clicked.connect(self.slot_on_view) # initial UI # self.setAutoFillBackground(True) self.scrollArea.setVisible(False) self.button_view.setEnabled(False) # pop-up window self.w = None def table_name(self): return self._table_name def model(self): return self._model def set_data(self, data): self._data = data db = self._db table_name = self._table_name # define and set the model self._model = SydTableModel(self._filename, db, table_name, data) # remove previous widget self.table_view.setParent(None) del self.table_view # create new one self.table_view = QTableView(self) self.verticalLayout.addWidget(self.table_view) # define own header (with column filter) self._header = SydColumnFilterHeader(self.table_view) ncol = self._model.columnCount(0) # define and set the filter/sort proxy self._filter_proxy_model = SydTableSortFilterProxyModel(self._header) self._filter_proxy_model.setSourceModel(self._model) self._filter_proxy_model.setSortLocaleAware(True) self._filter_proxy_model.setSortCaseSensitivity(Qt.CaseInsensitive) self.table_view.setModel(self._filter_proxy_model) # selection model for the button_view self.table_view.setSelectionBehavior(QTableView.SelectRows) selection = self.table_view.selectionModel() selection.selectionChanged.connect(self.on_selection_change) # set the columns filters self._header.set_filter_editors(ncol, self._filter_proxy_model) # setup the context menu self._header.setContextMenuPolicy(Qt.CustomContextMenu) self._header.customContextMenuRequested.connect( self.slot_on_column_header_popup) self._header.filterActivated.connect(self.slot_on_col_filter_changed) self.table_view.setHorizontalHeader(self._header) # remove previous col buttons c = self.layout_col_buttons.takeAt(0) while c and c.widget(): c.widget().setParent(None) del c c = self.layout_col_buttons.takeAt(0) # create new col buttons def create_lambda(icol): return lambda: self.slot_on_col_button_clicked(icol) self.col_buttons = [] for i in range(0, ncol): s = self._model._headers[i] b = QPushButton(s) # , parent=self.layout_col_buttons) b.clicked.connect(create_lambda(i)) b.setFlat(True) b.setVisible(False) self.layout_col_buttons.addWidget(b) self.col_buttons.append(b) h = QSpacerItem(878, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) self.layout_col_buttons.addItem(h) # create menu col width for i in range(0, ncol): b = QAction(self) b.setText('Toggle adjust width') b.setCheckable(True) b.setChecked(False) self._toggle_width_menus.append(b) # special case for first column ('id') if i == 0: b.setChecked(True) self.slot_on_auto_width_column(i) # make the area invisible first self.scrollArea.setVisible(False) # self.scrollArea.setAutoFillBackground(True) # self.table_view.setAutoFillBackground(True) self.table_view.setAlternatingRowColors(True) # initial nb of elements self.slot_on_col_filter_changed() # double click header self.table_view.horizontalHeader().sectionDoubleClicked. \ connect(self.slot_on_toggle_auto_width_column) # global filter self.edit_filter.textChanged.connect(self.slot_on_filter_changed) self.edit_filter.setClearButtonEnabled(True) # allow sorting self.table_view.setSortingEnabled(True) self._filter_proxy_model.sort(0, Qt.AscendingOrder) self._filter_proxy_model.invalidateFilter() self._header.updateGeometries() def slot_on_column_header_popup(self, pos): idx = self.table_view.horizontalHeader().logicalIndexAt(pos) menu = QMenu(self.table_view) a = QAction(self) name = self._model._col_names[idx] a.setText(f'Hide {name}') a.triggered.connect(lambda col_name=idx: self.slot_on_hide_column(idx)) b = self._toggle_width_menus[idx] b.triggered.connect( lambda col_name=idx: self.slot_on_auto_width_column(idx)) menu.addAction(a) menu.addAction(b) menu.exec_(self.table_view.mapToGlobal(pos)) def slot_on_hide_column(self, idx): # hide the column self.table_view.setColumnHidden(idx, True) # show the button self.scrollArea.setVisible(True) self.col_buttons[idx].setVisible(True) self._header.updateGeometries() def slot_on_col_button_clicked(self, idx): # show the column self.table_view.setColumnHidden(idx, False) # hide the button self.col_buttons[idx].setVisible(False) for b in self.col_buttons: if b.isVisible(): return self.scrollArea.setVisible(False) self._header.updateGeometries() def slot_on_toggle_auto_width_column(self, idx): b = self._toggle_width_menus[idx] b.setChecked(not b.isChecked()) self.slot_on_auto_width_column(idx) def slot_on_auto_width_column(self, idx): b = self._toggle_width_menus[idx] if b.isChecked(): self._header.setSectionResizeMode( idx, QtWidgets.QHeaderView.ResizeToContents) else: self._header.setSectionResizeMode( idx, QtWidgets.QHeaderView.Interactive) self._header.updateGeometries() def slot_on_col_filter_changed(self): n = self._filter_proxy_model.rowCount() t = self._model.rowCount(None) self.label_tablename.setText(f'{self._table_name}') self.label_status.setText(f'{n}/{t}') if self._table_name == 'Image' or self._table_name == 'DicomSeries': self.button_view.show() elif self._table_name == "DicomSeries_default" or self._table_name == "Image_default": self.button_view.show() def slot_on_filter_changed(self): n = self._filter_proxy_model.rowCount() t = self._model.rowCount(None) self.label_status.setText(f'{n}/{t}') f = self.edit_filter self._filter_proxy_model.set_global_filter(f.text()) def slot_on_reload(self): # later -> keep filters if the columns are identical. # not clear why I need to reopen the db here # (not needed for tables, needed for view) self._db = syd.open_db(self._filename) t = self._db.load_table(self._table_name) elements = syd.find_all(t) self.set_data(elements) # indicate that the table has been reloaded self.table_reloaded.emit() n = self._filter_proxy_model.rowCount() t = self._model.rowCount(None) self.label_status.setText(f'{n}/{t}') self.button_view.setText("view in vv") self.button_view.setEnabled(False) def slot_on_view(self): data = [] path = [] rows = set(index.row() for index in self.table_view.selectedIndexes()) for row in rows: data.append(self._data[row]) self.w = SydCTWindow(data, self._filename, self._table_name) self.w.button_ct_on.setEnabled(False) db = syd.open_db(self._filename) for d in data: e = self.w.get_ct_path(db, d) if e is not None and len(rows) == 1 and d['modality'] != 'CT': self.w.button_ct_on.setEnabled(True) self.w.show() else: if self._table_name == 'DicomSeries' or self._table_name == 'DicomSeries_default': db = syd.open_db(self._filename) dicom_file = syd.find_one(db['DicomFile'], dicom_series_id=d['id']) file = syd.find_one(db['File'], id=dicom_file['file_id']) tmp = db.absolute_data_folder + '/' + file[ 'folder'] + '/' + file['filename'] path.append(tmp) elif self._table_name == 'Image' or self._table_name == 'Image_default': db = syd.open_db(self._filename) file = syd.find_one(db['File'], id=d['file_mhd_id']) path.append(db.absolute_data_folder + '/' + file['folder'] + '/' + file['filename']) else: print('La table séléctionnée ne correspond pas') if path != []: path = ' '.join(path) cmd = f'vv {path}' os.system(cmd) else: print('Path to image has no corresponding file') def on_selection_change(self): rows = set(index.row() for index in self.table_view.selectedIndexes()) if len(rows) == 0: self.button_view.setEnabled(False) self.button_view.setText("view in vv") else: t = self._model.rowCount(None) self.button_view.setText(f"view in vv {len(rows)}/{t}") self.button_view.setEnabled(True)