Пример #1
0
class QtStyleTools:
    """"""
    extra_colors = {}

    # ----------------------------------------------------------------------
    def set_extra_colors(self, extra):
        """"""
        self.extra_colors = extra

    # ----------------------------------------------------------------------
    def add_menu_theme(self, parent, menu):
        """"""
        for theme in ['default'] + list_themes():
            action = QAction(parent)
            action.setText(theme)
            action.triggered.connect(
                self._wrapper(parent, theme, self.extra_colors,
                              self.update_buttons))
            menu.addAction(action)

    # ----------------------------------------------------------------------
    def _wrapper(self, parent, theme, extra, callable_):
        """"""
        def iner():
            self._apply_theme(parent, theme, extra, callable_)

        return iner

    # ----------------------------------------------------------------------
    def _apply_theme(self, parent, theme, extra={}, callable_=None):
        """"""
        self.apply_stylesheet(parent,
                              theme=theme,
                              invert_secondary=theme.startswith('light'),
                              extra=extra,
                              callable_=callable_)

    # ----------------------------------------------------------------------
    def apply_stylesheet(self,
                         parent,
                         theme,
                         invert_secondary=False,
                         extra={},
                         callable_=None):
        """"""
        if theme == 'default':
            parent.setStyleSheet('')
            return
        apply_stylesheet(parent,
                         theme=theme,
                         invert_secondary=invert_secondary,
                         extra=extra)

        if callable_:
            callable_()

    # ----------------------------------------------------------------------
    def update_buttons(self):
        """"""
        if not hasattr(self, 'colors'):
            return

        theme = {
            color_: os.environ[f'QTMATERIAL_{color_.upper()}']
            for color_ in self.colors
        }

        if 'light' in os.environ['QTMATERIAL_THEME']:
            self.dock_theme.checkBox_ligh_theme.setChecked(True)
        elif 'dark' in os.environ['QTMATERIAL_THEME']:
            self.dock_theme.checkBox_ligh_theme.setChecked(False)

        if self.dock_theme.checkBox_ligh_theme.isChecked():
            theme['secondaryColor'], theme['secondaryLightColor'], theme[
                'secondaryDarkColor'] = theme['secondaryColor'], theme[
                    'secondaryDarkColor'], theme['secondaryLightColor']

        for color_ in self.colors:
            button = getattr(self.dock_theme, f'pushButton_{color_}')

            color = theme[color_]

            if self.get_color(color).getHsv()[2] < 128:
                text_color = '#ffffff'
            else:
                text_color = '#000000'

            button.setStyleSheet(f"""
            *{{
            background-color: {color};
            color: {text_color};
            border: none;
            }}""")

            self.custom_colors[color_] = color

    # ----------------------------------------------------------------------
    def get_color(self, color):
        """"""
        return QColor(*[int(color[s:s + 2], 16) for s in range(1, 6, 2)])

    # ----------------------------------------------------------------------
    def update_theme(self, parent):
        """"""
        with open('my_theme.xml', 'w') as file:
            file.write("""
            <resources>
                <color name="primaryColor">{primaryColor}</color>
                <color name="primaryLightColor">{primaryLightColor}</color>
                <color name="secondaryColor">{secondaryColor}</color>
                <color name="secondaryLightColor">{secondaryLightColor}</color>
                <color name="secondaryDarkColor">{secondaryDarkColor}</color>
                <color name="primaryTextColor">{primaryTextColor}</color>
                <color name="secondaryTextColor">{secondaryTextColor}</color>
              </resources>
            """.format(**self.custom_colors))
        light = self.dock_theme.checkBox_ligh_theme.isChecked()
        self.apply_stylesheet(parent,
                              'my_theme.xml',
                              invert_secondary=light,
                              extra=self.extra_colors,
                              callable_=self.update_buttons)

    # ----------------------------------------------------------------------
    def set_color(self, parent, button_):
        """"""
        def iner():
            initial = self.get_color(self.custom_colors[button_])
            color_dialog = QColorDialog(parent=parent)
            color_dialog.setCurrentColor(initial)
            done = color_dialog.exec_()
            color_ = color_dialog.currentColor()

            if done and color_.isValid():
                color = '#' + ''.join(
                    [hex(v)[2:].ljust(2, '0') for v in color_.toTuple()[:3]])
                self.custom_colors[button_] = color
                self.update_theme(parent)

        return iner

    # ----------------------------------------------------------------------
    def show_dock_theme(self, parent):
        """"""
        self.colors = [
            'primaryColor', 'primaryLightColor', 'secondaryColor',
            'secondaryLightColor', 'secondaryDarkColor', 'primaryTextColor',
            'secondaryTextColor'
        ]

        self.custom_colors = {
            v: os.environ[f'QTMATERIAL_{v.upper()}']
            for v in self.colors
        }

        if 'PySide2' in sys.modules or 'PySide6' in sys.modules:
            self.dock_theme = QUiLoader().load(
                os.path.join(os.path.dirname(__file__), 'dock_theme.ui'))
        elif 'PyQt5' in sys.modules:
            self.dock_theme = uic.loadUi(
                os.path.join(os.path.dirname(__file__), 'dock_theme.ui'))

        parent.addDockWidget(Qt.LeftDockWidgetArea, self.dock_theme)
        self.dock_theme.setFloating(True)

        self.update_buttons()
        self.dock_theme.checkBox_ligh_theme.clicked.connect(
            lambda: self.update_theme(self.main))

        for color in self.colors:
            button = getattr(self.dock_theme, f'pushButton_{color}')
            button.clicked.connect(self.set_color(parent, color))
Пример #2
0
class QtStyleTools:
    """"""
    extra_values = {}

    # ----------------------------------------------------------------------
    @deprecated('set_extra')
    def set_extra_colors(self, extra):
        """"""
        self.extra_values = extra

    # ----------------------------------------------------------------------
    def set_extra(self, extra):
        """"""
        self.extra_values = extra

    # ----------------------------------------------------------------------
    def add_menu_theme(self, parent, menu):
        """"""
        self.menu_theme_ = menu
        action_group = QActionGroup(menu)
        try:
            action_group.setExclusive(True)
        except:
            action_group.exclusive = True

        for i, theme in enumerate(['default'] + list_themes()):
            action = QAction(parent)
            # action.triggered.connect(self._wrapper(parent, theme, self.extra_values, self.update_buttons))
            action.triggered.connect(lambda: self.update_theme_event(parent))
            try:
                action.setText(theme)
                action.setCheckable(True)
                action.setChecked(not bool(i))
                action.setActionGroup(action_group)
                menu.addAction(action)
                action_group.addAction(action)
            except:  # snake_case, true_property
                action.text = theme
                action.checkable = True
                action.checked = not bool(i)
                action.action_group = action_group
                menu.add_action(action)
                action_group.add_action(action)

    # ----------------------------------------------------------------------
    def add_menu_density(self, parent, menu):
        """"""
        self.menu_density_ = menu
        action_group = QActionGroup(menu)

        try:
            action_group.setExclusive(True)
        except:
            action_group.exclusive = True

        for density in map(str, range(-3, 4)):
            action = QAction(parent)
            # action.triggered.connect(self._wrapper(parent, density, self.extra_values, self.update_buttons))
            action.triggered.connect(lambda: self.update_theme_event(parent))
            try:
                action.setText(density)
                action.setCheckable(True)
                action.setChecked(density == '0')
                action.setActionGroup(action_group)
                menu.addAction(action)
                action_group.addAction(action)
            except:  # snake_case, true_property
                action.text = density
                action.checkable = True
                action.checked = density == '0'
                action.action_group = action_group
                menu.add_action(action)
                action_group.add_action(action)

        # menu.add_action(action_group)

    # # ----------------------------------------------------------------------
    # def _wrapper(self, parent, theme, extra, callable_):
        # """"""
        # def iner():
            # self._apply_theme(parent, theme, extra, callable_)
        # return iner

    # # ----------------------------------------------------------------------
    # def _apply_theme(self, parent, theme, extra={}, callable_=None):
        # """"""
        # self.apply_stylesheet(parent, theme=theme, invert_secondary=theme.startswith(
            # 'light'), extra=extra, callable_=callable_)

    # ----------------------------------------------------------------------

    def apply_stylesheet(self, parent, theme, invert_secondary=False, extra={}, callable_=None):
        """"""
        if theme == 'default':
            parent.setStyleSheet('')
            return
        apply_stylesheet(parent, theme=theme,
                         invert_secondary=invert_secondary, extra=extra)

        if callable_:
            callable_()

    # ----------------------------------------------------------------------
    def update_theme_event(self, parent):
        """"""
        try:
            density = [action.text() for action in self.menu_density_.actions(
            ) if action.isChecked()][0]
            theme = [action.text() for action in self.menu_theme_.actions()
                     if action.isChecked()][0]
        except:
            density = [
                action.text for action in self.menu_density_.actions() if action.checked][0]
            theme = [action.text for action in self.menu_theme_.actions()
                     if action.checked][0]

        self.extra_values['density_scale'] = density

        self.apply_stylesheet(parent, theme=theme, invert_secondary=theme.startswith(
            'light'), extra=self.extra_values, callable_=self.update_buttons)

    # ----------------------------------------------------------------------
    def update_buttons(self):
        """"""
        if not hasattr(self, 'colors'):
            return

        theme = {color_: os.environ[f'QTMATERIAL_{color_.upper()}']
                 for color_ in self.colors}

        if 'light' in os.environ['QTMATERIAL_THEME']:
            self.dock_theme.checkBox_ligh_theme.setChecked(True)
        elif 'dark' in os.environ['QTMATERIAL_THEME']:
            self.dock_theme.checkBox_ligh_theme.setChecked(False)

        try:
            if self.dock_theme.checkBox_ligh_theme.isChecked():
                theme['secondaryColor'], theme['secondaryLightColor'], theme['secondaryDarkColor'] = theme[
                    'secondaryColor'], theme['secondaryDarkColor'], theme['secondaryLightColor']
        except:  # snake_case, true_property
            if self.dock_theme.checkBox_ligh_theme.checked:
                theme['secondaryColor'], theme['secondaryLightColor'], theme['secondaryDarkColor'] = theme[
                    'secondaryColor'], theme['secondaryDarkColor'], theme['secondaryLightColor']

        for color_ in self.colors:
            button = getattr(self.dock_theme, f'pushButton_{color_}')

            color = theme[color_]

            try:
                if self.get_color(color).getHsv()[2] < 128:
                    text_color = '#ffffff'
                else:
                    text_color = '#000000'
            except:  # snake_case, true_property
                if self.get_color(color).get_hsv()[2] < 128:
                    text_color = '#ffffff'
                else:
                    text_color = '#000000'

            button.setStyleSheet(f"""
            *{{
            background-color: {color};
            color: {text_color};
            border: none;
            }}""")

            self.custom_colors[color_] = color

    # ----------------------------------------------------------------------
    def get_color(self, color):
        """"""
        return QColor(*[int(color[s:s + 2], 16) for s in range(1, 6, 2)])

    # ----------------------------------------------------------------------
    def update_theme(self, parent):
        """"""
        with open('my_theme.xml', 'w') as file:
            file.write("""
            <resources>
                <color name="primaryColor">{primaryColor}</color>
                <color name="primaryLightColor">{primaryLightColor}</color>
                <color name="secondaryColor">{secondaryColor}</color>
                <color name="secondaryLightColor">{secondaryLightColor}</color>
                <color name="secondaryDarkColor">{secondaryDarkColor}</color>
                <color name="primaryTextColor">{primaryTextColor}</color>
                <color name="secondaryTextColor">{secondaryTextColor}</color>
              </resources>
            """.format(**self.custom_colors))
        try:
            light = self.dock_theme.checkBox_ligh_theme.isChecked()
        except:  # snake_case, true_property
            light = self.dock_theme.checkBox_ligh_theme.checked

        self.apply_stylesheet(parent, 'my_theme.xml', invert_secondary=light,
                              extra=self.extra_values, callable_=self.update_buttons)

    # ----------------------------------------------------------------------
    def set_color(self, parent, button_):
        """"""
        def iner():
            initial = self.get_color(self.custom_colors[button_])
            color_dialog = QColorDialog(parent=parent)
            try:
                color_dialog.setCurrentColor(initial)
            except:  # snake_case, true_property
                color_dialog.current_color = initial
            done = color_dialog.exec_()

            try:
                color_ = color_dialog.currentColor()
            except:  # snake_case, true_property
                color_ = color_dialog.current_color

            try:
                if done and color_.isValid():
                    rgb_255 = [color_.red(), color_.green(), color_.blue()]
                    color = '#' + ''.join([hex(v)[2:].ljust(2, '0')
                                           for v in rgb_255])
                    self.custom_colors[button_] = color
                    self.update_theme(parent)
            except:  # snake_case, true_property
                if done and color_.is_valid():
                    rgb_255 = [color_.red(), color_.green(), color_.blue()]
                    color = '#' + ''.join([hex(v)[2:].ljust(2, '0')
                                           for v in rgb_255])
                    self.custom_colors[button_] = color
                    self.update_theme(parent)

        return iner

    # ----------------------------------------------------------------------
    def show_dock_theme(self, parent):
        """"""
        self.colors = ['primaryColor',
                       'primaryLightColor',
                       'secondaryColor',
                       'secondaryLightColor',
                       'secondaryDarkColor',
                       'primaryTextColor',
                       'secondaryTextColor']

        self.custom_colors = {
            v: os.environ[f'QTMATERIAL_{v.upper()}'] for v in self.colors}

        if 'PySide2' in sys.modules or 'PySide6' in sys.modules:
            self.dock_theme = QUiLoader().load(os.path.join(
                os.path.dirname(__file__), 'dock_theme.ui'))
        elif 'PyQt5' in sys.modules or 'PyQt6' in sys.modules:
            self.dock_theme = uic.loadUi(os.path.join(
                os.path.dirname(__file__), 'dock_theme.ui'))

        try:
            parent.addDockWidget(
                Qt.DockWidgetArea.LeftDockWidgetArea, self.dock_theme)
            self.dock_theme.setFloating(True)
        except:  # snake_case, true_property
            parent.add_dock_widget(
                Qt.DockWidgetArea.LeftDockWidgetArea, self.dock_theme)
            self.dock_theme.floating = True

        self.update_buttons()
        self.dock_theme.checkBox_ligh_theme.clicked.connect(
            lambda: self.update_theme(self.main))

        for color in self.colors:
            button = getattr(self.dock_theme, f'pushButton_{color}')
            button.clicked.connect(self.set_color(parent, color))