def test(): class XTest( XBase ): def __init__( self ): XBase.__init__( self ) self.name = "" self.vorname = "" self.alter = 0 self.haarfarbe = "" self.schuhgroesse = 0 self.bemerkung = "" x1 = XTest() x1.name = "Kendel" x1.vorname = "Martin" x1.alter = 66 x1.haarfarbe = "grau" x1.schuhgroesse = 44 x1.bemerkung = "Das ist alles \nein riesengroßer Irrtum" x2 = XTest() x2.name = "Haaretz" x2.vorname = "Yosh" x2.alter = 56 x2.haarfarbe = "schwarz" x2.schuhgroesse = 42 tm = DefaultIccTableModel( (x1, x2 ) ) tm.setSortable( True ) tm.setKeyHeaderMappings( { "Nachname": "name", "Vorname": "vorname", "Alter": "alter", "Bemerkung": "bemerkung" } ) tm.setNumColumnsIndexes( (2,) ) from PySide2.QtWidgets import QApplication app = QApplication() tv = QTableView( ) tv.setModel( tm ) tv.setAlternatingRowColors( True ) tv.setSortingEnabled( True ) tv.resizeColumnsToContents() tv.resizeRowsToContents() tm.layoutChanged.connect( tv.resizeRowsToContents ) ## <======== WICHTIG bei mehrzeiligem Text in einer Zelle! tv.show() app.exec_()
class MetricsDialog(PluginDialog): ENABLE = True def __init__(self, conn=None, parent=None): super().__init__(parent) self.conn = conn self.view = QTableView() self.model = MetricModel() self.buttons = QDialogButtonBox(QDialogButtonBox.Ok) self.view.setModel(self.model) self.view.setAlternatingRowColors(True) self.view.horizontalHeader().hide() self.view.verticalHeader().hide() self.view.setSelectionMode(QAbstractItemView.SingleSelection) self.view.setSelectionBehavior(QAbstractItemView.SelectRows) self.buttons.accepted.connect(self.accept) self.setWindowTitle(self.tr("Project metrics")) v_layout = QVBoxLayout() v_layout.addWidget(self.view) v_layout.addWidget(self.buttons) self.setLayout(v_layout) # Async stuff self.metrics_runnable = None self.populate() def populate(self): """Async implementation to populate the view Notes: When closing the dialog window, the thread is not stopped. """ def compute_metrics(conn): """Async function""" return { "variants": get_variant_count(conn), "snps": get_snp_count(conn), "transitions": get_variant_transition(conn), "transversions": get_variant_transversion(conn), "samples": get_sample_count(conn), } self.model.add_metrics(self.tr("Loading..."), self.tr("data...")) self.metrics_runnable = SqlRunnable(self.conn, compute_metrics) self.metrics_runnable.finished.connect(self.loaded) QThreadPool.globalInstance().start(self.metrics_runnable) def loaded(self): """Called at the end of the thread and populate data""" results = self.metrics_runnable.results self.model.clear() ratio = results["transitions"] / results["transversions"] self.model.add_metrics("Variant count", results["variants"]) self.model.add_metrics("Snp count", results["snps"]) self.model.add_metrics("Transition count", results["transitions"]) self.model.add_metrics("Transversion count", results["transversions"]) self.model.add_metrics("Tr/tv ratio", ratio) self.model.add_metrics("Sample count", results["variants"]) self.view.horizontalHeader().setSectionResizeMode( 0, QHeaderView.ResizeToContents) self.view.horizontalHeader().setSectionResizeMode( 1, QHeaderView.Stretch)
class DictWidget(QWidget): def __init__(self, parent=None): super().__init__() self.view = QTableView() self.model = DictModel() self.proxy_model = QSortFilterProxyModel() self.search_bar = QLineEdit() self._show_loading = False self.proxy_model.setSourceModel(self.model) self.view.setModel(self.proxy_model) self.view.setAlternatingRowColors(True) self.view.horizontalHeader().setStretchLastSection(True) self.view.setSelectionMode(QAbstractItemView.SingleSelection) self.view.setSelectionBehavior(QAbstractItemView.SelectRows) self.view.setSortingEnabled(True) self.view.verticalHeader().hide() self.search_bar.textChanged.connect( self.proxy_model.setFilterRegularExpression) self.search_bar.setVisible(False) self._show_search_action = QAction("show search bar") self._show_search_action.setCheckable(True) self._show_search_action.setShortcutContext(Qt.WidgetShortcut) self._show_search_action.setShortcut(QKeySequence.Find) self._show_search_action.triggered.connect(self._on_show_search) self._close_search_action = QAction() self._close_search_action.setShortcut(QKeySequence(Qt.Key_Escape)) self._close_search_action.setShortcutContext(Qt.WidgetShortcut) self._close_search_action.triggered.connect(self._on_close_search) self.view.addAction(self._show_search_action) self.search_bar.addAction(self._close_search_action) _layout = QVBoxLayout() _layout.addWidget(self.view) _layout.addWidget(self.search_bar) _layout.setContentsMargins(0, 0, 0, 0) self.setLayout(_layout) print("init") def set_dict(self, data: dict): self.model.set_dict(data) def _on_show_search(self): self.search_bar.setVisible(True) self.search_bar.setFocus(Qt.ShortcutFocusReason) def _on_close_search(self): self.search_bar.hide() self.search_bar.clear() self.view.setFocus(Qt.ShortcutFocusReason) def set_header_visible(self, visible=True): self.view.horizontalHeader().setVisible(visible) def clear(self): self.model.clear() def paintEvent(self, event: QPaintEvent): if self._show_loading: painter = QPainter(self) painter.drawText(self.rect(), Qt.AlignCenter, self.tr("Loading ...")) else: super().paintEvent(event) def set_loading(self, show=True): self._show_loading = True self.view.setVisible(not show) self.update()
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 RemoverDialog(QDialog): def __init__(self, parent=None): super(RemoverDialog, self).__init__(parent) self.setupUi() def setupUi(self): self.menuBar = QMenuBar() self.menuBar.show() self.pathInputBox = QLineEdit(self) self.pathInputBox.setEnabled(False) self.pathInputBox.setToolTip( 'Input a path or drag a directory here...') self.openPathButton = QPushButton('Open...', self) self.openPathButton.clicked.connect(self.openPath) inputLayout = QHBoxLayout() inputLayout.addWidget(QLabel('Path:', self)) inputLayout.addWidget(self.pathInputBox) inputLayout.addWidget(self.openPathButton) self.filterFolderCheckBox = QCheckBox('Folders', self) self.filterFolderCheckBox.setChecked(True) self.filterFolderCheckBox.toggled.connect(self.filter) self.filterFileCheckBox = QCheckBox('Files', self) self.filterFileCheckBox.setChecked(True) self.filterFileCheckBox.toggled.connect(self.filter) self.filterSuffixCheckBox = QCheckBox('Suffixes', self) self.filterSuffixCheckBox.setChecked(True) self.filterSuffixCheckBox.toggled.connect(self.filter) filterLayout = QHBoxLayout() filterLayout.addWidget(self.filterFolderCheckBox) filterLayout.addWidget(self.filterFileCheckBox) filterLayout.addWidget(self.filterSuffixCheckBox) filterLayout.addStretch() self.trashButton = QPushButton('Trash', self) self.trashButton.clicked.connect(self.trash) self.deleteButton = QPushButton('Delete', self) self.deleteButton.clicked.connect(self.delete) confirmLayout = QHBoxLayout() confirmLayout.addStretch() confirmLayout.addWidget(self.trashButton) confirmLayout.addWidget(self.deleteButton) layout = QVBoxLayout() layout.addLayout(inputLayout) layout.addLayout(filterLayout) layout.addWidget(self.createResultView()) layout.addLayout(confirmLayout) self.setAcceptDrops(True) self.setLayout(layout) self.setMinimumWidth(600) self.setWindowTitle('Remover') self.setWindowIcon(QApplication.style().standardIcon( QStyle.SP_DirIcon)) def createResultView(self): self.resultModel = ResultModel(self) self.resultView = QTableView(self) self.resultView.setSortingEnabled(True) self.resultView.setShowGrid(False) self.resultView.setAlternatingRowColors(True) self.resultView.verticalHeader().hide() self.resultView.setSelectionBehavior(QAbstractItemView.SelectRows) self.resultView.setSelectionMode(QAbstractItemView.ExtendedSelection) self.sortFilterModel = SortFilterResultModel(self.resultModel, self) self.resultView.setModel(self.sortFilterModel) return self.resultView def dragEnterEvent(self, event): if event.mimeData().hasUrls() and len(event.mimeData().urls()) == 1: event.acceptProposedAction() def dropEvent(self, event): if event.mimeData().hasUrls() and len(event.mimeData().urls()) == 1: self.pathInputBox.setText(event.mimeData().urls()[0].toLocalFile()) self.reloadPath(self.pathInputBox.text()) def openPath(self): path = QFileDialog.getExistingDirectory( parent=self, caption='Open', options=QFileDialog.ShowDirsOnly | QFileDialog.DontResolveSymlinks) if path: self.pathInputBox.setText(path) self.reloadPath(path) def filter(self): filters = [] if self.filterFolderCheckBox.isChecked(): filters.append('folder') if self.filterFileCheckBox.isChecked(): filters.append('file') if self.filterSuffixCheckBox.isChecked(): filters.append('suffix') self.sortFilterModel.setFilterRegularExpression('|'.join(filters)) self.sortFilterModel.filterRegularExpression() self.resultView.resizeRowsToContents() def trash(self): folders, files = self.collectSelectedFolderFiles() try: for file in files: send2trash(file) for folder in folders: if QFile(folder).exists(): send2trash(folder) except: QMessageBox.warning(self, 'Failed', 'Failed to trash selected files/folders') return self.reloadPath(self.pathInputBox.text()) def delete(self): folders, files = self.collectSelectedFolderFiles() try: for file in files: os.remove(file) for folder in folders: shutil.rmtree(folder) except: QMessageBox.warning(self, 'Failed', 'Failed to delete selected files/folders') return self.reloadPath(self.pathInputBox.text()) def collectSelectedFolderFiles(self): folders, files, suffixes = [], [], [] for index in self.resultView.selectedIndexes(): if index.column() != 0: # 忽略第二列的selection continue item = self.sortFilterModel.data(index, Qt.UserRole) if 'folder' == item.type: folders.append(item.name) elif 'file' == item.type: files.append(item.name) elif 'suffix' == item.type: suffixes.append(item.name[2:]) # 将后缀符合选中条件的文件添加到files中 path = self.pathInputBox.text() iterator = QDirIterator(path, filter=QDir.Files | QDir.Dirs | QDir.Hidden | QDir.NoDotAndDotDot, flags=QDirIterator.Subdirectories) folderPaths, filePaths = set(), set() while iterator.hasNext(): file = iterator.next() if '.' == file[-1] or '..' == file[-2]: continue fileInfo = QFileInfo(file) if fileInfo.isDir(): if fileInfo.fileName() in folders: folderPaths.add(fileInfo.absoluteFilePath()) if fileInfo.isFile(): if fileInfo.fileName() in files: filePaths.add(fileInfo.absoluteFilePath()) if fileInfo.suffix() in suffixes: filePaths.add(fileInfo.absoluteFilePath()) return sorted(folderPaths), filePaths def reloadPath(self, path): self.resultModel.reload(path) self.resultView.horizontalHeader().setSectionResizeMode( 0, QHeaderView.Stretch) self.resultView.horizontalHeader().setSectionResizeMode( 1, QHeaderView.ResizeToContents) self.filter() self.resultView.sortByColumn(1, Qt.DescendingOrder)
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)