class LivSupp_SegmentedImagesWidget(QWidget): def __init__(self): super().__init__() self.init_ui() def init_ui(self): self.view = QTableView() self.model = LiverSupport_SegmentedImagesModel(LiverSupportCtrl().get_images()) self.view.setModel(self.model) self.view.setColumnHidden(2, True) self.view.setColumnHidden(3, True) self.view.setColumnHidden(4, True) layout = QVBoxLayout(self) layout.addWidget(self.view)
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)