class QtReaderDialog(QDialog): """Dialog for user to select a reader plugin for a given file extension or folder""" def __init__( self, pth: str = '', parent: QWidget = None, extension: str = '', readers: Dict[str, str] = {}, error_message: str = '', ): super().__init__(parent) self.setObjectName('Choose reader') self.setWindowTitle('Choose reader') self._current_file = pth self._extension = extension self._reader_buttons = [] self.setup_ui(error_message, readers) def setup_ui(self, error_message, readers): """Build UI using given error_messsage and readers dict""" # add instruction label layout = QVBoxLayout() label = QLabel( f"{error_message}Choose reader for {self._current_file}:" ) layout.addWidget(label) # add radio button for each reader plugin self.reader_btn_group = QButtonGroup(self) self.add_reader_buttons(layout, readers) if self.reader_btn_group.buttons(): self.reader_btn_group.buttons()[0].toggle() # OK & cancel buttons for the dialog btns = QDialogButtonBox.Ok | QDialogButtonBox.Cancel self.btn_box = QDialogButtonBox(btns) self.btn_box.accepted.connect(self.accept) self.btn_box.rejected.connect(self.reject) # checkbox to remember the choice (doesn't pop up for folders) extension = os.path.splitext(self._current_file)[1] if extension: self.persist_checkbox = QCheckBox( f'Remember this choice for files with a {extension} extension' ) self.persist_checkbox.toggle() layout.addWidget(self.persist_checkbox) layout.addWidget(self.btn_box) self.setLayout(layout) def add_reader_buttons(self, layout, readers): """Add radio button to layout for each reader in readers""" for display_name in sorted(readers): button = QRadioButton(f"{display_name}") self.reader_btn_group.addButton(button) layout.addWidget(button) def _get_plugin_choice(self): """Get user's plugin choice based on the checked button""" checked_btn = self.reader_btn_group.checkedButton() if checked_btn: return checked_btn.text() def _get_persist_choice(self): """Get persistence checkbox choice""" return ( hasattr(self, 'persist_checkbox') and self.persist_checkbox.isChecked() ) def get_user_choices(self) -> Optional[Tuple[str, bool]]: """Execute dialog and get user choices""" dialog_result = self.exec_() # user pressed cancel if not dialog_result: return None # grab the selected radio button text display_name = self._get_plugin_choice() # grab the persistence checkbox choice persist_choice = self._get_persist_choice() return display_name, persist_choice
class PeriodicTableWidget(QWidget): selectionChanged = Signal() def __init__(self, parent=None): QWidget.__init__(self, parent) # Widgets, layouts and signals self._group = QButtonGroup() layout = QGridLayout() layout.setSpacing(0) ## Element for z, position in _ELEMENT_POSITIONS.items(): widget = ElementPushButton(z) widget.setCheckable(True) layout.addWidget(widget, *position) self._group.addButton(widget, z) ## Labels layout.addWidget(QLabel(''), 7, 0) # Dummy layout.addWidget(QLabel('*'), 5, 2, Qt.AlignRight) layout.addWidget(QLabel('*'), 8, 2, Qt.AlignRight) layout.addWidget(QLabel('**'), 6, 2, Qt.AlignRight) layout.addWidget(QLabel('**'), 9, 2, Qt.AlignRight) for row in [0, 1, 2, 3, 4, 5, 6, 8, 9]: layout.setRowStretch(row, 1) self.setLayout(layout) # Signals self._group.buttonClicked.connect(self.selectionChanged) # Default self.setColorFunction(_category_color_function) def setColorFunction(self, func): if not callable(func): raise ValueError('Not a function') self._color_function = func # Redraw for widget in self._group.buttons(): z = self._group.id(widget) bcolor = func(z) fcolor = 'white' if _calculate_brightness(bcolor) < 128 else 'black' sheet = 'background-color: %s; color: %s' % (bcolor.name(), fcolor) widget.setStyleSheet(sheet) def colorFunction(self): return self._color_function def setMultipleSelection(self, multiple): self._group.setExclusive(not multiple) def isMultipleSelection(self): return not self._group.exclusive() def setSelection(self, selection): def _uncheckedAll(): for widget in self._group.buttons(): widget.setChecked(False) if selection is None: _uncheckedAll() self.selectionChanged.emit() return if isinstance(selection, (int, six.string_types)): selection = [selection] if not self.isMultipleSelection() and len(selection) > 1: raise ValueError('Multiple selection mode is off. Cannot select more than one element') _uncheckedAll() for z in selection: if isinstance(z, six.string_types): z = get_atomic_number(z) self._group.button(z).setChecked(True) self.selectionChanged.emit() # def selection(self): selection = set() for widget in self._group.buttons(): if widget.isChecked(): selection.add(self._group.id(widget)) if self.isMultipleSelection(): return frozenset(selection) else: if len(selection) > 0: return list(selection)[0] else: return None def selectionSymbol(self): selection = self.selection() if self.isMultipleSelection(): return frozenset(map(get_symbol, selection)) else: if selection is None: return None else: return get_symbol(selection)