예제 #1
0
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
예제 #2
0
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
예제 #3
0
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
예제 #4
0
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)
예제 #5
0
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