class Preferences(QDialog): # configuration = {} weight = 0 # savePreferences = pyqtSignal() # def __init__(self, parent=None): super(Preferences, self).__init__(parent, Qt.Dialog) self.setWindowTitle(translations.TR_PREFERENCES_TITLE) self.setMinimumSize(QSize(900, 600)) vbox = QVBoxLayout(self) hbox = QHBoxLayout() vbox.setContentsMargins(0, 0, 5, 5) hbox.setContentsMargins(0, 0, 0, 0) # self.tree = QTreeWidget() self.tree.header().setHidden(True) self.tree.setSelectionMode(QTreeWidget.SingleSelection) self.tree.setAnimated(True) self.tree.header().setHorizontalScrollMode( QAbstractItemView.ScrollPerPixel) self.tree.header().setSectionResizeMode(0, QHeaderView.ResizeToContents) self.tree.header().setStretchLastSection(False) self.tree.setFixedWidth(200) self.stacked = QStackedLayout() hbox.addWidget(self.tree) hbox.addLayout(self.stacked) vbox.addLayout(hbox) # hbox_footer = QHBoxLayout() self._btnSave = QPushButton(translations.TR_SAVE) self._btnCancel = QPushButton(translations.TR_CANCEL) hbox_footer.addSpacerItem(QSpacerItem(1, 0, QSizePolicy.Expanding)) hbox_footer.addWidget(self._btnCancel) hbox_footer.addWidget(self._btnSave) vbox.addLayout(hbox_footer) # self.tree.itemSelectionChanged.connect(self._change_current) self._btnCancel.clicked['bool'].connect(self.close) self._btnSave.clicked['bool'].connect(self._save_preferences) # self.load_ui() self.tree.setCurrentItem(self.tree.topLevelItem(0)) # def _save_preferences(self): self.savePreferences.emit() self.close() # def load_ui(self): sections = sorted( list(Preferences.configuration.keys()), key=lambda item: Preferences.configuration[item]['weight']) for section in sections: text = Preferences.configuration[section]['text'] Widget = Preferences.configuration[section]['widget'] widget = Widget(self) area = QScrollArea() area.setWidgetResizable(True) area.setWidget(widget) self.stacked.addWidget(area) index = self.stacked.indexOf(area) item = QTreeWidgetItem([text]) item.setData(0, Qt.UserRole, index) self.tree.addTopLevelItem(item) # #Sort Item Children subcontent = Preferences.configuration[section].get( 'subsections', {}) subsections = sorted(list(subcontent.keys()), key=lambda item: subcontent[item]['weight']) for sub in subsections: text = subcontent[sub]['text'] Widget = subcontent[sub]['widget'] widget = Widget(self) area = QScrollArea() area.setWidgetResizable(True) area.setWidget(widget) self.stacked.addWidget(area) index = self.stacked.indexOf(area) subitem = QTreeWidgetItem([text]) subitem.setData(0, Qt.UserRole, index) item.addChild(subitem) # self.tree.expandAll() # def _change_current(self): item = self.tree.currentItem() index = item.data(0, Qt.UserRole) self.stacked.setCurrentIndex(index) # @classmethod def register_configuration(cls, section, widget, text, weight=None, subsection=None): if weight is None: Preferences.weight += 1 weight = Preferences.weight if not subsection: Preferences.configuration[section] = { 'widget': widget, 'weight': weight, 'text': text } else: config = Preferences.configuration.get(section, {}) if not config: config[section] = {'widget': None, 'weight': 100} subconfig = config.get('subsections', {}) subconfig[subsection] = { 'widget': widget, 'weight': weight, 'text': text } config['subsections'] = subconfig Preferences.configuration[section] = config
class Preferences(QDialog): configuration = {} weight = 0 # Signals savePreferences = pyqtSignal() def __init__(self, parent=None): super().__init__(parent, Qt.Dialog) self.setWindowTitle(translations.TR_PREFERENCES_TITLE) self.setMinimumSize(900, 600) box = QVBoxLayout(self) box.setContentsMargins(5, 5, 5, 5) # Header self._header_label = QLabel("") header_font = self._header_label.font() header_font.setBold(True) header_font.setPointSize(header_font.pointSize() + 4) self._header_label.setFont(header_font) hbox = QHBoxLayout() hbox.setContentsMargins(0, 0, 0, 0) self.tree = QTreeWidget() self.tree.header().setHidden(True) self.tree.setSelectionMode(QTreeWidget.SingleSelection) self.tree.setAnimated(True) self.tree.header().setSectionResizeMode(0, QHeaderView.ResizeToContents) self.tree.setFixedWidth(200) hbox.addWidget(self.tree) self.stacked = QStackedLayout() header_layout = QVBoxLayout() header_layout.addWidget(self._header_label) header_layout.addLayout(self.stacked) hbox.addLayout(header_layout) box.addLayout(hbox) # Footer buttons button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) box.addWidget(button_box) # Connections button_box.rejected.connect(self.close) button_box.accepted.connect(self._save_preferences) self.tree.selectionModel().currentRowChanged.connect( self._change_current) self.load_ui() @pyqtSlot() def _save_preferences(self): self.savePreferences.emit() self.close() def load_ui(self): sections = sorted( Preferences.configuration.keys(), key=lambda item: Preferences.configuration[item]['weight']) for section in sections: text = Preferences.configuration[section]['text'] Widget = Preferences.configuration[section]['widget'] widget = Widget(self) area = QScrollArea() area.setWidgetResizable(True) area.setWidget(widget) self.stacked.addWidget(area) index = self.stacked.indexOf(area) item = QTreeWidgetItem([text]) item.setData(0, Qt.UserRole, index) self.tree.addTopLevelItem(item) # Sort Item Children subcontent = Preferences.configuration[section].get( 'subsections', {}) subsections = subcontent.keys() for sub in subsections: text = subcontent[sub]['text'] Widget = subcontent[sub]['widget'] widget = Widget(self) area = QScrollArea() area.setWidgetResizable(True) area.setWidget(widget) self.stacked.addWidget(area) index = self.stacked.indexOf(area) subitem = QTreeWidgetItem([text]) subitem.setData(0, Qt.UserRole, index) item.addChild(subitem) self.tree.expandAll() self.tree.setCurrentIndex(self.tree.model().index(0, 0)) def _change_current(self): item = self.tree.currentItem() index = item.data(0, Qt.UserRole) self.stacked.setCurrentIndex(index) self._header_label.setText(item.text(0)) @classmethod def register_configuration(cls, section, widget, text, weight=None, subsection=None): if weight is None: Preferences.weight += 1 weight = Preferences.weight if subsection is None: Preferences.configuration[section] = { 'widget': widget, 'weight': weight, 'text': text } else: config = Preferences.configuration.get(section, {}) if not config: config[section] = {'widget': None, 'weight': 100} subconfig = config.get('subsections', {}) subconfig[subsection] = { 'widget': widget, 'weight': weight, 'text': text } config['subsections'] = subconfig Preferences.configuration[section] = config
class Preferences(QDialog): # configuration = {} weight = 0 # savePreferences = pyqtSignal() # def __init__(self, parent=None): super(Preferences, self).__init__(parent, Qt.Dialog) self.setWindowTitle(translations.TR_PREFERENCES_TITLE) self.setMinimumSize(QSize(900, 600)) vbox = QVBoxLayout(self) hbox = QHBoxLayout() vbox.setContentsMargins(0, 0, 5, 5) hbox.setContentsMargins(0, 0, 0, 0) # self.tree = QTreeWidget() self.tree.header().setHidden(True) self.tree.setSelectionMode(QTreeWidget.SingleSelection) self.tree.setAnimated(True) self.tree.header().setHorizontalScrollMode( QAbstractItemView.ScrollPerPixel) self.tree.header().setSectionResizeMode(0, QHeaderView.ResizeToContents) self.tree.header().setStretchLastSection(False) self.tree.setFixedWidth(200) self.stacked = QStackedLayout() hbox.addWidget(self.tree) hbox.addLayout(self.stacked) vbox.addLayout(hbox) # hbox_footer = QHBoxLayout() self._btnSave = QPushButton(translations.TR_SAVE) self._btnCancel = QPushButton(translations.TR_CANCEL) hbox_footer.addSpacerItem(QSpacerItem(1, 0, QSizePolicy.Expanding)) hbox_footer.addWidget(self._btnCancel) hbox_footer.addWidget(self._btnSave) vbox.addLayout(hbox_footer) # self.tree.itemSelectionChanged.connect(self._change_current) self._btnCancel.clicked['bool'].connect(self.close) self._btnSave.clicked['bool'].connect(self._save_preferences) # self.load_ui() self.tree.setCurrentItem(self.tree.topLevelItem(0)) # def _save_preferences(self): self.savePreferences.emit() self.close() # def load_ui(self): sections = sorted( list(Preferences.configuration.keys()), key=lambda item: Preferences.configuration[item]['weight']) for section in sections: text = Preferences.configuration[section]['text'] Widget = Preferences.configuration[section]['widget'] widget = Widget(self) area = QScrollArea() area.setWidgetResizable(True) area.setWidget(widget) self.stacked.addWidget(area) index = self.stacked.indexOf(area) item = QTreeWidgetItem([text]) item.setData(0, Qt.UserRole, index) self.tree.addTopLevelItem(item) # #Sort Item Children subcontent = Preferences.configuration[section].get( 'subsections', {}) subsections = sorted(list(subcontent.keys()), key=lambda item: subcontent[item]['weight']) for sub in subsections: text = subcontent[sub]['text'] Widget = subcontent[sub]['widget'] widget = Widget(self) area = QScrollArea() area.setWidgetResizable(True) area.setWidget(widget) self.stacked.addWidget(area) index = self.stacked.indexOf(area) subitem = QTreeWidgetItem([text]) subitem.setData(0, Qt.UserRole, index) item.addChild(subitem) # self.tree.expandAll() # def _change_current(self): item = self.tree.currentItem() index = item.data(0, Qt.UserRole) self.stacked.setCurrentIndex(index) # @classmethod def register_configuration(cls, section, widget, text, weight=None, subsection=None): if weight is None: Preferences.weight += 1 weight = Preferences.weight if not subsection: Preferences.configuration[section] = {'widget': widget, 'weight': weight, 'text': text} else: config = Preferences.configuration.get(section, {}) if not config: config[section] = {'widget': None, 'weight': 100} subconfig = config.get('subsections', {}) subconfig[subsection] = {'widget': widget, 'weight': weight, 'text': text} config['subsections'] = subconfig Preferences.configuration[section] = config
class HistogramDisplayControl(QWidget): class Layout(Enum): STACKED = 0 HORIZONTAL = 1 VERTICAL = 2 class DisplayType(Enum): GREY_SCALE = 0 RBG = 1 __LOG: Logger = LogHelper.logger("HistogramDisplayControl") limit_changed = pyqtSignal(LimitChangeEvent) limits_reset = pyqtSignal(LimitResetEvent) layout_changed = pyqtSignal(Layout) def __init__(self, parent=None): super().__init__(parent) self.__menu = None self.__plots = dict() # Use stacked layout as default self.__create_stacked_layout() def __create_horizontal_layout(self): self.__plot_layout = QHBoxLayout() self.__plot_layout.setSpacing(1) self.__plot_layout.setContentsMargins(1, 1, 1, 1) self.setLayout(self.__plot_layout) self.__current_layout = HistogramDisplayControl.Layout.HORIZONTAL def __create_vertical_layout(self): self.__plot_layout = QVBoxLayout() self.__plot_layout.setSpacing(1) self.__plot_layout.setContentsMargins(1, 1, 1, 1) self.setLayout(self.__plot_layout) self.__current_layout = HistogramDisplayControl.Layout.VERTICAL def __create_stacked_layout(self): layout = QVBoxLayout() layout.setSpacing(1) layout.setContentsMargins(1, 1, 1, 1) self.__plot_layout = QStackedLayout() self.__plot_layout.setContentsMargins(1, 1, 1, 1) self.__plot_layout.setSpacing(1) self.__tab_widget = QWidget() self.__tab_widget.setFixedHeight(20) self.__tab_widget.hide() self.__tab_layout = QHBoxLayout() self.__tab_layout.setContentsMargins(1, 1, 1, 1) self.__tab_layout.setAlignment(Qt.AlignLeft) self.__tab_layout.addSpacing(10) self.__red_button = QRadioButton("Red") self.__red_button.setStyleSheet("QRadioButton {color: red}") self.__red_button.toggled.connect(self.__handle_red_toggled) self.__tab_layout.addWidget(self.__red_button) self.__red_plot_index = None self.__green_button = QRadioButton("Green") self.__green_button.setStyleSheet("QRadioButton {color: green}") self.__green_button.toggled.connect(self.__handle_green_toggled) self.__tab_layout.addWidget(self.__green_button) self.__green_plot_index = None self.__blue_button = QRadioButton("Blue") self.__blue_button.setStyleSheet("QRadioButton {color: blue}") self.__blue_button.toggled.connect(self.__handle_blue_toggled) self.__tab_layout.addWidget(self.__blue_button) self.__tab_widget.setLayout(self.__tab_layout) self.__blue_plot_index = None layout.addWidget(self.__tab_widget) layout.addLayout(self.__plot_layout) self.setLayout(layout) self.__current_layout = HistogramDisplayControl.Layout.STACKED def __init_menu(self): self.__menu: QMenu = QMenu(self) stacked_action = QAction("Stacked", self) stacked_action.triggered.connect(self.__handle_stacked_selected) self.__menu.addAction(stacked_action) horizontal_action = QAction("Horizontal", self) horizontal_action.triggered.connect(self.__handle_horizontal_selected) self.__menu.addAction(horizontal_action) vertical_action = QAction("Vertical", self) vertical_action.triggered.connect(self.__handle_vertical_selected) self.__menu.addAction(vertical_action) self.setContextMenuPolicy(Qt.CustomContextMenu) self.customContextMenuRequested.connect( self.__handle_custom_context_menu) def __handle_custom_context_menu(self, position: QPoint): HistogramDisplayControl.__LOG.debug( "__handle_custom_context_menu called position: {0}", position) self.__menu.popup(self.mapToGlobal(position)) def __handle_stacked_selected(self): self.__swap_layout(HistogramDisplayControl.Layout.STACKED) def __handle_horizontal_selected(self): self.__swap_layout(HistogramDisplayControl.Layout.HORIZONTAL) def __handle_vertical_selected(self): self.__swap_layout(HistogramDisplayControl.Layout.VERTICAL) def __swap_layout(self, new_layout: Layout): # The plot's will have had their parent set to the layout so first # we undo that so they won't get deleted when the layout does. for band, plot in self.__plots.items(): plot.setParent(None) if self.__current_layout == HistogramDisplayControl.Layout.STACKED: self.__red_button.setParent(None) self.__green_button.setParent(None) self.__blue_button.setParent(None) self.__tab_widget.setParent(None) # Per Qt docs we need to delete the current layout before we can set a new one # And it turns out we can't delete the layout until we reassign it to another widget # who becomes it's parent, then we delete the parent. tmp = QWidget() tmp.setLayout(self.layout()) del tmp if new_layout == HistogramDisplayControl.Layout.STACKED: self.__create_stacked_layout() if new_layout == HistogramDisplayControl.Layout.HORIZONTAL: self.__create_horizontal_layout() if new_layout == HistogramDisplayControl.Layout.VERTICAL: self.__create_vertical_layout() for band, plot in self.__plots.items(): self.__plot_layout.addWidget(plot) self.__wire_band(band, plot) if new_layout != HistogramDisplayControl.Layout.STACKED: # stacked layout hides plots not displayed so set them back plot.show() self.layout_changed.emit(new_layout) def __wire_band(self, band: Band, plot: AdjustableHistogramControl): if self.__current_layout == HistogramDisplayControl.Layout.STACKED: set_checked: bool = False if self.__plot_layout.count() == 1: set_checked = True self.__tab_widget.show() if band == Band.RED: self.__red_plot_index = self.__plot_layout.indexOf(plot) self.__red_button.setChecked(set_checked) if band == Band.GREEN: self.__green_plot_index = self.__plot_layout.indexOf(plot) self.__green_button.setChecked(set_checked) if band == Band.BLUE: self.__blue_plot_index = self.__plot_layout.indexOf(plot) self.__blue_button.setChecked(set_checked) @pyqtSlot(bool) def __handle_red_toggled(self, checked: bool): if checked: HistogramDisplayControl.__LOG.debug("red toggle checked") self.__plot_layout.setCurrentIndex(self.__red_plot_index) @pyqtSlot(bool) def __handle_green_toggled(self, checked: bool): if checked: HistogramDisplayControl.__LOG.debug("green toggle checked") self.__plot_layout.setCurrentIndex(self.__green_plot_index) @pyqtSlot(bool) def __handle_blue_toggled(self, checked: bool): if checked: HistogramDisplayControl.__LOG.debug("blue toggle checked") self.__plot_layout.setCurrentIndex(self.__blue_plot_index) def add_plot(self, raw_data: HistogramPlotData, adjusted_data: HistogramPlotData, band: Band): """Expects either one band with band of Band.GREY or three bands one each of Band.RED, Band.GREEN, Band.BLUE. If these conditions are not met the code will attempt to be accommodating and won't throw and error but you might get strange results.""" plots = AdjustableHistogramControl(band) plots.set_raw_data(raw_data) plots.set_adjusted_data(adjusted_data) plots.limit_changed.connect(self.limit_changed) plots.limits_reset.connect(self.limits_reset) self.__plots[band] = plots self.__plot_layout.addWidget(plots) if self.__plot_layout.count() == 2: self.__init_menu() if band == Band.RED or band == Band.GREEN or band == Band.BLUE: self.__wire_band(band, plots) def set_adjusted_data(self, data: HistogramPlotData, band: Band): """Update the adjusted data for a Band that has already been added using add_plot""" plots: AdjustableHistogramControl = self.__plots[band] if plots is not None: plots.set_adjusted_data(data) def update_limits(self, data: HistogramPlotData, band: Band): plots: AdjustableHistogramControl = self.__plots[band] if plots is not None: plots.update_limits(data)
class Preferences(QDialog): configuration = {} weight = 0 # Signals savePreferences = pyqtSignal() def __init__(self, parent=None): super().__init__(parent, Qt.Dialog) self.setWindowTitle(translations.TR_PREFERENCES_TITLE) self.setMinimumSize(900, 650) box = QVBoxLayout(self) box.setContentsMargins(3, 3, 3, 3) self.setAutoFillBackground(True) # Header self._header_label = QLabel("") header_font = self._header_label.font() header_font.setBold(True) header_font.setPointSize(header_font.pointSize() + 4) self._header_label.setFont(header_font) hbox = QHBoxLayout() hbox.setContentsMargins(0, 0, 0, 0) self.tree = QTreeWidget() self.tree.header().setHidden(True) self.tree.setSelectionMode(QTreeWidget.SingleSelection) self.tree.setAnimated(True) self.tree.header().setSectionResizeMode( 0, QHeaderView.ResizeToContents) self.tree.setFixedWidth(200) hbox.addWidget(self.tree) self.stacked = QStackedLayout() header_layout = QVBoxLayout() header_layout.setContentsMargins(0, 0, 0, 0) header_layout.addWidget(self._header_label) header_layout.addLayout(self.stacked) hbox.addLayout(header_layout) box.addLayout(hbox) # Footer buttons button_box = QDialogButtonBox( QDialogButtonBox.Ok | QDialogButtonBox.Cancel) box.addWidget(button_box) # Connections button_box.rejected.connect(self.close) button_box.accepted.connect(self._save_preferences) self.tree.selectionModel().currentRowChanged.connect( self._change_current) self.load_ui() @pyqtSlot() def _save_preferences(self): self.savePreferences.emit() self.close() def load_ui(self): sections = sorted( Preferences.configuration.keys(), key=lambda item: Preferences.configuration[item]['weight']) for section in sections: text = Preferences.configuration[section]['text'] Widget = Preferences.configuration[section]['widget'] widget = Widget(self) area = QScrollArea() area.setWidgetResizable(True) area.setWidget(widget) self.stacked.addWidget(area) index = self.stacked.indexOf(area) item = QTreeWidgetItem([text]) item.setData(0, Qt.UserRole, index) self.tree.addTopLevelItem(item) # Sort Item Children subcontent = Preferences.configuration[section].get( 'subsections', {}) subsections = sorted( subcontent.keys(), key=lambda item: subcontent[item]['weight']) for sub in subsections: text = subcontent[sub]['text'] Widget = subcontent[sub]['widget'] widget = Widget(self) area = QScrollArea() area.setWidgetResizable(True) area.setWidget(widget) self.stacked.addWidget(area) index = self.stacked.indexOf(area) subitem = QTreeWidgetItem([text]) subitem.setData(0, Qt.UserRole, index) item.addChild(subitem) self.tree.expandAll() self.tree.setCurrentIndex(self.tree.model().index(0, 0)) def _change_current(self): item = self.tree.currentItem() index = item.data(0, Qt.UserRole) self.stacked.setCurrentIndex(index) self._header_label.setText(item.text(0)) @classmethod def register_configuration(cls, section, widget, text, weight=None, subsection=None): if weight is None: Preferences.weight += 1 weight = Preferences.weight if subsection is None: Preferences.configuration[section] = { 'widget': widget, 'weight': weight, 'text': text } else: config = Preferences.configuration.get(section, {}) if not config: config[section] = { 'widget': None, 'weight': 100 } subconfig = config.get('subsections', {}) subconfig[subsection] = { 'widget': widget, 'weight': weight, 'text': text } config['subsections'] = subconfig Preferences.configuration[section] = config