From a8a854ce6be137053b7157e04b15f38c9c07e5e8 Mon Sep 17 00:00:00 2001 From: seird Date: Wed, 2 Nov 2022 19:31:56 +0100 Subject: [PATCH] Add basic dark & light theme (#18) --- MANIFEST.in | 6 ++ gotify-tray.spec | 2 +- gotify_tray/database/default_settings.py | 1 + gotify_tray/gui/MainApplication.py | 11 ++-- gotify_tray/gui/designs/widget_message.py | 4 +- gotify_tray/gui/designs/widget_message.ui | 2 +- gotify_tray/gui/designs/widget_settings.py | 44 +++++++++---- gotify_tray/gui/designs/widget_settings.ui | 38 ++++++++++- gotify_tray/gui/themes/__init__.py | 38 +++++++++++ .../gui/themes/dark_purple/__init__.py | 1 + gotify_tray/gui/themes/dark_purple/palette.py | 65 +++++++++++++++++++ .../dark_purple}/refresh.svg | 0 .../gui/themes/dark_purple/status_active.svg | 49 ++++++++++++++ .../themes/dark_purple/status_connecting.svg | 49 ++++++++++++++ .../gui/themes/dark_purple/status_error.svg | 49 ++++++++++++++ .../themes/dark_purple/status_inactive.svg | 49 ++++++++++++++ gotify_tray/gui/themes/dark_purple/style.qss | 20 ++++++ .../dark_purple}/trashcan.svg | 0 gotify_tray/gui/themes/default/__init__.py | 1 + gotify_tray/gui/themes/default/palette.py | 7 ++ gotify_tray/gui/themes/default/refresh.svg | 45 +++++++++++++ .../default}/status_active.svg | 0 .../default}/status_connecting.svg | 0 .../default}/status_error.svg | 0 .../default}/status_inactive.svg | 0 gotify_tray/gui/themes/default/style.qss | 3 + gotify_tray/gui/themes/default/trashcan.svg | 1 + .../gui/themes/light_purple/__init__.py | 1 + .../gui/themes/light_purple/palette.py | 61 +++++++++++++++++ .../gui/themes/light_purple/refresh.svg | 45 +++++++++++++ .../gui/themes/light_purple/status_active.svg | 49 ++++++++++++++ .../themes/light_purple/status_connecting.svg | 49 ++++++++++++++ .../gui/themes/light_purple/status_error.svg | 49 ++++++++++++++ .../themes/light_purple/status_inactive.svg | 49 ++++++++++++++ gotify_tray/gui/themes/light_purple/style.qss | 20 ++++++ .../gui/themes/light_purple/trashcan.svg | 1 + gotify_tray/gui/widgets/MainWindow.py | 42 ++++++------ gotify_tray/gui/widgets/MessageWidget.py | 9 ++- gotify_tray/gui/widgets/SettingsDialog.py | 16 +++++ gotify_tray/gui/widgets/StatusWidget.py | 4 +- setup.py | 5 +- 41 files changed, 833 insertions(+), 52 deletions(-) create mode 100644 gotify_tray/gui/themes/__init__.py create mode 100644 gotify_tray/gui/themes/dark_purple/__init__.py create mode 100644 gotify_tray/gui/themes/dark_purple/palette.py rename gotify_tray/gui/{images => themes/dark_purple}/refresh.svg (100%) create mode 100644 gotify_tray/gui/themes/dark_purple/status_active.svg create mode 100644 gotify_tray/gui/themes/dark_purple/status_connecting.svg create mode 100644 gotify_tray/gui/themes/dark_purple/status_error.svg create mode 100644 gotify_tray/gui/themes/dark_purple/status_inactive.svg create mode 100644 gotify_tray/gui/themes/dark_purple/style.qss rename gotify_tray/gui/{images => themes/dark_purple}/trashcan.svg (100%) create mode 100644 gotify_tray/gui/themes/default/__init__.py create mode 100644 gotify_tray/gui/themes/default/palette.py create mode 100644 gotify_tray/gui/themes/default/refresh.svg rename gotify_tray/gui/{images => themes/default}/status_active.svg (100%) rename gotify_tray/gui/{images => themes/default}/status_connecting.svg (100%) rename gotify_tray/gui/{images => themes/default}/status_error.svg (100%) rename gotify_tray/gui/{images => themes/default}/status_inactive.svg (100%) create mode 100644 gotify_tray/gui/themes/default/style.qss create mode 100644 gotify_tray/gui/themes/default/trashcan.svg create mode 100644 gotify_tray/gui/themes/light_purple/__init__.py create mode 100644 gotify_tray/gui/themes/light_purple/palette.py create mode 100644 gotify_tray/gui/themes/light_purple/refresh.svg create mode 100644 gotify_tray/gui/themes/light_purple/status_active.svg create mode 100644 gotify_tray/gui/themes/light_purple/status_connecting.svg create mode 100644 gotify_tray/gui/themes/light_purple/status_error.svg create mode 100644 gotify_tray/gui/themes/light_purple/status_inactive.svg create mode 100644 gotify_tray/gui/themes/light_purple/style.qss create mode 100644 gotify_tray/gui/themes/light_purple/trashcan.svg diff --git a/MANIFEST.in b/MANIFEST.in index 4a6ebed..5a85169 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,3 +1,9 @@ include README.md version.txt include gotify_tray/gui/images/*.png include gotify_tray/gui/images/*.svg +include gotify_tray/gui/themes/default/*.svg +include gotify_tray/gui/themes/default/*.qss +include gotify_tray/gui/themes/dark_purple/*.svg +include gotify_tray/gui/themes/dark_purple/*.qss +include gotify_tray/gui/themes/light_purple/*.svg +include gotify_tray/gui/themes/light_purple/*.qss diff --git a/gotify-tray.spec b/gotify-tray.spec index 848f1cc..ae67d6d 100644 --- a/gotify-tray.spec +++ b/gotify-tray.spec @@ -9,7 +9,7 @@ logo = "gotify_tray/gui/images/logo.ico" if platform.system() != "Darwin" else " a = Analysis(['gotify_tray/__main__.py'], pathex=[os.getcwd()], binaries=[], - datas=[('gotify_tray/gui/images', 'gotify_tray/gui/images')], + datas=[('gotify_tray/gui/images', 'gotify_tray/gui/images'), ('gotify_tray/gui/themes', 'gotify_tray/gui/themes')], hiddenimports=[], hookspath=[], runtime_hooks=[], diff --git a/gotify_tray/database/default_settings.py b/gotify_tray/database/default_settings.py index 2c8b65a..80d9190 100644 --- a/gotify_tray/database/default_settings.py +++ b/gotify_tray/database/default_settings.py @@ -5,6 +5,7 @@ from ..__version__ import __title__ DEFAULT_SETTINGS = { + "theme": "default", "message/check_missed/notify": True, "logging/level": "Disabled", "export/path": os.path.join( diff --git a/gotify_tray/gui/MainApplication.py b/gotify_tray/gui/MainApplication.py index e28d4a4..3df6d56 100644 --- a/gotify_tray/gui/MainApplication.py +++ b/gotify_tray/gui/MainApplication.py @@ -18,6 +18,7 @@ from gotify_tray.tasks import ( GetMessagesTask, ServerConnectionWatchdogTask, ) +from gotify_tray.gui.themes import set_theme from gotify_tray.utils import get_icon, verify_server from PyQt6 import QtCore, QtGui, QtWidgets @@ -60,6 +61,8 @@ def init_logger(logger: logging.Logger): class MainApplication(QtWidgets.QApplication): def init_ui(self): + set_theme(self, settings.value("theme", type=str)) + self.gotify_client = gotify.GotifyClient( settings.value("Server/url", type=str), settings.value("Server/client_token", type=str), @@ -83,7 +86,7 @@ class MainApplication(QtWidgets.QApplication): new_message_callback=self.new_message_callback, opened_callback=self.listener_opened_callback, closed_callback=self.listener_closed_callback, - error_callback=self.listener_error_callback + error_callback=self.listener_error_callback, ) self.watchdog = ServerConnectionWatchdogTask(self.gotify_client) @@ -164,7 +167,7 @@ class MainApplication(QtWidgets.QApplication): QtCore.QTimer.singleShot( self.gotify_client.get_wait_time() * 1000, self.gotify_client.reconnect ) - + def listener_error_callback(self, exception: Exception): self.main_window.set_connecting() self.tray.set_icon_error() @@ -333,6 +336,7 @@ class MainApplication(QtWidgets.QApplication): def settings_callback(self): settings_dialog = SettingsDialog() settings_dialog.quit_requested.connect(self.quit) + settings_dialog.theme_change_requested.connect(lambda theme: set_theme(self, theme)) accepted = settings_dialog.exec() if accepted and settings_dialog.settings_changed: @@ -349,7 +353,7 @@ class MainApplication(QtWidgets.QApplication): new_message_callback=self.new_message_callback, opened_callback=self.listener_opened_callback, closed_callback=self.listener_closed_callback, - error_callback=self.listener_error_callback + error_callback=self.listener_error_callback, ) def tray_notification_clicked_callback(self): @@ -417,7 +421,6 @@ def start_gui(): app.setApplicationName(title) app.setQuitOnLastWindowClosed(False) app.setWindowIcon(QtGui.QIcon(get_icon("gotify-small"))) - app.setStyle("fusion") init_logger(logger) diff --git a/gotify_tray/gui/designs/widget_message.py b/gotify_tray/gui/designs/widget_message.py index 8c2c14f..e0a2ee6 100644 --- a/gotify_tray/gui/designs/widget_message.py +++ b/gotify_tray/gui/designs/widget_message.py @@ -1,6 +1,6 @@ # Form implementation generated from reading ui file 'gotify_tray/gui/designs\widget_message.ui' # -# Created by: PyQt6 UI code generator 6.1.0 +# Created by: PyQt6 UI code generator 6.3.1 # # WARNING: Any manual changes made to this file will be lost when pyuic6 is # run again. Do not edit this file unless you know what you are doing. @@ -27,7 +27,7 @@ class Ui_Form(object): self.gridLayout_frame.setObjectName("gridLayout_frame") self.pb_delete = QtWidgets.QPushButton(self.frame) self.pb_delete.setText("") - self.pb_delete.setFlat(True) + self.pb_delete.setFlat(False) self.pb_delete.setObjectName("pb_delete") self.gridLayout_frame.addWidget(self.pb_delete, 0, 4, 1, 1) spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Maximum, QtWidgets.QSizePolicy.Policy.Minimum) diff --git a/gotify_tray/gui/designs/widget_message.ui b/gotify_tray/gui/designs/widget_message.ui index 74d453b..7f579b5 100644 --- a/gotify_tray/gui/designs/widget_message.ui +++ b/gotify_tray/gui/designs/widget_message.ui @@ -53,7 +53,7 @@ - true + false diff --git a/gotify_tray/gui/designs/widget_settings.py b/gotify_tray/gui/designs/widget_settings.py index fe146ac..e24d091 100644 --- a/gotify_tray/gui/designs/widget_settings.py +++ b/gotify_tray/gui/designs/widget_settings.py @@ -12,7 +12,7 @@ from PyQt6 import QtCore, QtGui, QtWidgets class Ui_Dialog(object): def setupUi(self, Dialog): Dialog.setObjectName("Dialog") - Dialog.resize(384, 285) + Dialog.resize(384, 346) self.gridLayout = QtWidgets.QGridLayout(Dialog) self.gridLayout.setObjectName("gridLayout") self.buttonBox = QtWidgets.QDialogButtonBox(Dialog) @@ -60,6 +60,22 @@ class Ui_Dialog(object): self.cb_notification_click.setObjectName("cb_notification_click") self.gridLayout_4.addWidget(self.cb_notification_click, 3, 0, 1, 3) self.verticalLayout_4.addWidget(self.groupBox_notifications) + self.groupBox_2 = QtWidgets.QGroupBox(self.tab_general) + self.groupBox_2.setObjectName("groupBox_2") + self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.groupBox_2) + self.verticalLayout_2.setObjectName("verticalLayout_2") + self.horizontalLayout_3 = QtWidgets.QHBoxLayout() + self.horizontalLayout_3.setObjectName("horizontalLayout_3") + self.label_theme = QtWidgets.QLabel(self.groupBox_2) + self.label_theme.setObjectName("label_theme") + self.horizontalLayout_3.addWidget(self.label_theme) + self.combo_theme = QtWidgets.QComboBox(self.groupBox_2) + self.combo_theme.setObjectName("combo_theme") + self.horizontalLayout_3.addWidget(self.combo_theme) + spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum) + self.horizontalLayout_3.addItem(spacerItem1) + self.verticalLayout_2.addLayout(self.horizontalLayout_3) + self.verticalLayout_4.addWidget(self.groupBox_2) self.groupBox_server_info = QtWidgets.QGroupBox(self.tab_general) self.groupBox_server_info.setObjectName("groupBox_server_info") self.gridLayout_3 = QtWidgets.QGridLayout(self.groupBox_server_info) @@ -67,11 +83,11 @@ class Ui_Dialog(object): self.pb_change_server_info = QtWidgets.QPushButton(self.groupBox_server_info) self.pb_change_server_info.setObjectName("pb_change_server_info") self.gridLayout_3.addWidget(self.pb_change_server_info, 0, 0, 1, 1) - spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum) - self.gridLayout_3.addItem(spacerItem1, 0, 1, 1, 1) + spacerItem2 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum) + self.gridLayout_3.addItem(spacerItem2, 0, 1, 1, 1) self.verticalLayout_4.addWidget(self.groupBox_server_info) - spacerItem2 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Policy.Minimum, QtWidgets.QSizePolicy.Policy.Expanding) - self.verticalLayout_4.addItem(spacerItem2) + spacerItem3 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Policy.Minimum, QtWidgets.QSizePolicy.Policy.Expanding) + self.verticalLayout_4.addItem(spacerItem3) self.tabWidget.addTab(self.tab_general, "") self.tab_fonts = QtWidgets.QWidget() self.tab_fonts.setObjectName("tab_fonts") @@ -96,8 +112,8 @@ class Ui_Dialog(object): self.horizontalLayout.addWidget(self.pb_font_message_content) self.layout_fonts_message.addLayout(self.horizontalLayout) self.verticalLayout_5.addWidget(self.groupBox_fonts_message) - spacerItem3 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Policy.Minimum, QtWidgets.QSizePolicy.Policy.Expanding) - self.verticalLayout_5.addItem(spacerItem3) + spacerItem4 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Policy.Minimum, QtWidgets.QSizePolicy.Policy.Expanding) + self.verticalLayout_5.addItem(spacerItem4) self.tabWidget.addTab(self.tab_fonts, "") self.tab_advanced = QtWidgets.QWidget() self.tab_advanced.setObjectName("tab_advanced") @@ -142,8 +158,8 @@ class Ui_Dialog(object): self.spin_popup_h.setMaximum(10000) self.spin_popup_h.setObjectName("spin_popup_h") self.horizontalLayout_4.addWidget(self.spin_popup_h) - spacerItem4 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum) - self.horizontalLayout_4.addItem(spacerItem4) + spacerItem5 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum) + self.horizontalLayout_4.addItem(spacerItem5) self.gridLayout_2.addLayout(self.horizontalLayout_4, 0, 0, 1, 1) self.verticalLayout.addWidget(self.groupbox_image_popup) self.groupBox_logging = QtWidgets.QGroupBox(self.tab_advanced) @@ -153,8 +169,8 @@ class Ui_Dialog(object): self.combo_logging = QtWidgets.QComboBox(self.groupBox_logging) self.combo_logging.setObjectName("combo_logging") self.gridLayout_6.addWidget(self.combo_logging, 0, 1, 1, 1) - spacerItem5 = QtWidgets.QSpacerItem(190, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum) - self.gridLayout_6.addItem(spacerItem5, 0, 3, 1, 1) + spacerItem6 = QtWidgets.QSpacerItem(190, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum) + self.gridLayout_6.addItem(spacerItem6, 0, 3, 1, 1) self.pb_open_log = QtWidgets.QPushButton(self.groupBox_logging) self.pb_open_log.setMaximumSize(QtCore.QSize(30, 16777215)) self.pb_open_log.setObjectName("pb_open_log") @@ -163,8 +179,8 @@ class Ui_Dialog(object): self.label_logging.setObjectName("label_logging") self.gridLayout_6.addWidget(self.label_logging, 0, 0, 1, 1) self.verticalLayout.addWidget(self.groupBox_logging) - spacerItem6 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Policy.Minimum, QtWidgets.QSizePolicy.Policy.Expanding) - self.verticalLayout.addItem(spacerItem6) + spacerItem7 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Policy.Minimum, QtWidgets.QSizePolicy.Policy.Expanding) + self.verticalLayout.addItem(spacerItem7) self.tabWidget.addTab(self.tab_advanced, "") self.gridLayout.addWidget(self.tabWidget, 0, 0, 1, 1) @@ -190,6 +206,8 @@ class Ui_Dialog(object): self.label_notification_duration_ms.setText(_translate("Dialog", "ms")) self.label_notification_priority.setText(_translate("Dialog", "Minimum priority to show notifications:")) self.cb_notification_click.setText(_translate("Dialog", "Clicking the notification pop-up opens the main window")) + self.groupBox_2.setTitle(_translate("Dialog", "Interface")) + self.label_theme.setText(_translate("Dialog", "Theme:")) self.groupBox_server_info.setTitle(_translate("Dialog", "Server info")) self.pb_change_server_info.setText(_translate("Dialog", "Change server info")) self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_general), _translate("Dialog", "General")) diff --git a/gotify_tray/gui/designs/widget_settings.ui b/gotify_tray/gui/designs/widget_settings.ui index 2b32ffa..f06b655 100644 --- a/gotify_tray/gui/designs/widget_settings.ui +++ b/gotify_tray/gui/designs/widget_settings.ui @@ -7,7 +7,7 @@ 0 0 384 - 285 + 346 @@ -117,6 +117,42 @@ + + + + Interface + + + + + + + + Theme: + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + diff --git a/gotify_tray/gui/themes/__init__.py b/gotify_tray/gui/themes/__init__.py new file mode 100644 index 0000000..48d3a63 --- /dev/null +++ b/gotify_tray/gui/themes/__init__.py @@ -0,0 +1,38 @@ +import logging +from PyQt6 import QtGui, QtWidgets +from gotify_tray.utils import get_abs_path +from . import default, dark_purple, light_purple +from gotify_tray.database import Settings + + +settings = Settings("gotify-tray") +logger = logging.getLogger("gotify-tray") + + +styles = { + "default": default, + "dark_purple": dark_purple, + "light_purple": light_purple, +} + + +def set_theme(app: QtWidgets.QApplication, style: str = "default"): + app.setStyle("fusion") + + if style not in styles.keys(): + logger.error(f"set_style: style {style} is unsupported.") + return + + stylesheet = "" + with open(get_abs_path(f"gotify_tray/gui/themes/{style}/style.qss"), "r") as f: + stylesheet += f.read() + + app.setPalette(styles[style].get_palette()) + app.setStyleSheet(stylesheet) + +def get_themes(): + return styles.keys() + +def get_theme_file(file: str, theme: str = None) -> str: + theme = settings.value("theme", type=str) if not theme else theme + return get_abs_path(f"gotify_tray/gui/themes/{theme}/{file}") diff --git a/gotify_tray/gui/themes/dark_purple/__init__.py b/gotify_tray/gui/themes/dark_purple/__init__.py new file mode 100644 index 0000000..30e805f --- /dev/null +++ b/gotify_tray/gui/themes/dark_purple/__init__.py @@ -0,0 +1 @@ +from .palette import get_palette diff --git a/gotify_tray/gui/themes/dark_purple/palette.py b/gotify_tray/gui/themes/dark_purple/palette.py new file mode 100644 index 0000000..e6b0afd --- /dev/null +++ b/gotify_tray/gui/themes/dark_purple/palette.py @@ -0,0 +1,65 @@ +from PyQt6 import QtGui + + +def get_palette() -> QtGui.QPalette: + palette = QtGui.QPalette() + + palette.setColor(QtGui.QPalette.ColorGroup.Active, QtGui.QPalette.ColorRole.Window, QtGui.QColor(0x3B3B3D)) + palette.setColor(QtGui.QPalette.ColorGroup.Inactive, QtGui.QPalette.ColorRole.Window, QtGui.QColor(0x404042)) + palette.setColor(QtGui.QPalette.ColorGroup.Disabled, QtGui.QPalette.ColorRole.Window, QtGui.QColor(0x424242)) + + palette.setColor(QtGui.QPalette.ColorGroup.Active, QtGui.QPalette.ColorRole.WindowText, QtGui.QColor(0xCACBCE)) + palette.setColor(QtGui.QPalette.ColorGroup.Inactive, QtGui.QPalette.ColorRole.WindowText, QtGui.QColor(0xC8C8C6)) + palette.setColor(QtGui.QPalette.ColorGroup.Disabled, QtGui.QPalette.ColorRole.WindowText, QtGui.QColor(0x707070)) + + palette.setColor(QtGui.QPalette.ColorGroup.Active, QtGui.QPalette.ColorRole.Text, QtGui.QColor(0xCACBCE)) + palette.setColor(QtGui.QPalette.ColorGroup.Inactive, QtGui.QPalette.ColorRole.Text, QtGui.QColor(0xC8C8C6)) + palette.setColor(QtGui.QPalette.ColorGroup.Disabled, QtGui.QPalette.ColorRole.Text, QtGui.QColor(0x707070)) + + palette.setColor(QtGui.QPalette.ColorGroup.Active, QtGui.QPalette.ColorRole.PlaceholderText, QtGui.QColor(0x7D7D82)) + palette.setColor(QtGui.QPalette.ColorGroup.Inactive, QtGui.QPalette.ColorRole.PlaceholderText, QtGui.QColor(0x87888C)) + palette.setColor(QtGui.QPalette.ColorGroup.Disabled, QtGui.QPalette.ColorRole.PlaceholderText, QtGui.QColor(0x737373)) + + palette.setColor(QtGui.QPalette.ColorGroup.Active, QtGui.QPalette.ColorRole.BrightText, QtGui.QColor(0x252627)) + palette.setColor(QtGui.QPalette.ColorGroup.Inactive, QtGui.QPalette.ColorRole.BrightText, QtGui.QColor(0x2D2D2F)) + palette.setColor(QtGui.QPalette.ColorGroup.Disabled, QtGui.QPalette.ColorRole.BrightText, QtGui.QColor(0x333333)) + + palette.setColor(QtGui.QPalette.ColorGroup.Active, QtGui.QPalette.ColorRole.Base, QtGui.QColor(0x27272A)) + palette.setColor(QtGui.QPalette.ColorGroup.Inactive, QtGui.QPalette.ColorRole.Base, QtGui.QColor(0x2A2A2D)) + palette.setColor(QtGui.QPalette.ColorGroup.Disabled, QtGui.QPalette.ColorRole.Base, QtGui.QColor(0x343437)) + + palette.setColor(QtGui.QPalette.ColorGroup.Active, QtGui.QPalette.ColorRole.AlternateBase, QtGui.QColor(0x2C2C30)) + palette.setColor(QtGui.QPalette.ColorGroup.Inactive, QtGui.QPalette.ColorRole.AlternateBase, QtGui.QColor(0x2B2B2F)) + palette.setColor(QtGui.QPalette.ColorGroup.Disabled, QtGui.QPalette.ColorRole.AlternateBase, QtGui.QColor(0x36363A)) + + palette.setColor(QtGui.QPalette.ColorGroup.All, QtGui.QPalette.ColorRole.ToolTipBase, QtGui.QColor(0x5522a8)) + palette.setColor(QtGui.QPalette.ColorGroup.All, QtGui.QPalette.ColorRole.ToolTipText, QtGui.QColor(0xBFBFBF)) + + palette.setColor(QtGui.QPalette.ColorGroup.Active, QtGui.QPalette.ColorRole.Button, QtGui.QColor(0x28282B)) + palette.setColor(QtGui.QPalette.ColorGroup.Inactive, QtGui.QPalette.ColorRole.Button, QtGui.QColor(0x28282B)) + palette.setColor(QtGui.QPalette.ColorGroup.Disabled, QtGui.QPalette.ColorRole.Button, QtGui.QColor(0x2B2A2A)) + + palette.setColor(QtGui.QPalette.ColorGroup.Active, QtGui.QPalette.ColorRole.ButtonText, QtGui.QColor(0xB9B9BE)) + palette.setColor(QtGui.QPalette.ColorGroup.Inactive, QtGui.QPalette.ColorRole.ButtonText, QtGui.QColor(0x9E9FA5)) + palette.setColor(QtGui.QPalette.ColorGroup.Disabled, QtGui.QPalette.ColorRole.ButtonText, QtGui.QColor(0x73747E)) + + palette.setColor(QtGui.QPalette.ColorGroup.Active, QtGui.QPalette.ColorRole.Highlight, QtGui.QColor(0x6D29DC)) + palette.setColor(QtGui.QPalette.ColorGroup.Inactive, QtGui.QPalette.ColorRole.Highlight, QtGui.QColor(0x5522a8)) + palette.setColor(QtGui.QPalette.ColorGroup.Disabled, QtGui.QPalette.ColorRole.Highlight, QtGui.QColor(0x5522a8)) + + palette.setColor(QtGui.QPalette.ColorGroup.Active, QtGui.QPalette.ColorRole.HighlightedText, QtGui.QColor(0xCCCCCC)) + palette.setColor(QtGui.QPalette.ColorGroup.Inactive, QtGui.QPalette.ColorRole.HighlightedText, QtGui.QColor(0xCECECE)) + palette.setColor(QtGui.QPalette.ColorGroup.Disabled, QtGui.QPalette.ColorRole.HighlightedText, QtGui.QColor(0x707070)) + + palette.setColor(QtGui.QPalette.ColorGroup.All, QtGui.QPalette.ColorRole.Light, QtGui.QColor(0x414145)) + palette.setColor(QtGui.QPalette.ColorGroup.All, QtGui.QPalette.ColorRole.Midlight, QtGui.QColor(0x39393C)) + palette.setColor(QtGui.QPalette.ColorGroup.All, QtGui.QPalette.ColorRole.Mid, QtGui.QColor(0x2F2F32)) + palette.setColor(QtGui.QPalette.ColorGroup.All, QtGui.QPalette.ColorRole.Dark, QtGui.QColor(0x202022)) + palette.setColor(QtGui.QPalette.ColorGroup.All, QtGui.QPalette.ColorRole.Shadow, QtGui.QColor(0x19191A)) + + palette.setColor(QtGui.QPalette.ColorGroup.All, QtGui.QPalette.ColorRole.Link, QtGui.QColor(0xAE7AFF)) + palette.setColor(QtGui.QPalette.ColorGroup.Disabled, QtGui.QPalette.ColorRole.Link, QtGui.QColor(0xAE7AFF)) + palette.setColor(QtGui.QPalette.ColorGroup.All, QtGui.QPalette.ColorRole.LinkVisited, QtGui.QColor(0x5522a8)) + palette.setColor(QtGui.QPalette.ColorGroup.Disabled, QtGui.QPalette.ColorRole.LinkVisited, QtGui.QColor(0x6D29DC)) + + return palette diff --git a/gotify_tray/gui/images/refresh.svg b/gotify_tray/gui/themes/dark_purple/refresh.svg similarity index 100% rename from gotify_tray/gui/images/refresh.svg rename to gotify_tray/gui/themes/dark_purple/refresh.svg diff --git a/gotify_tray/gui/themes/dark_purple/status_active.svg b/gotify_tray/gui/themes/dark_purple/status_active.svg new file mode 100644 index 0000000..eb03e66 --- /dev/null +++ b/gotify_tray/gui/themes/dark_purple/status_active.svg @@ -0,0 +1,49 @@ + + + + + + + + + + diff --git a/gotify_tray/gui/themes/dark_purple/status_connecting.svg b/gotify_tray/gui/themes/dark_purple/status_connecting.svg new file mode 100644 index 0000000..3e9d9f7 --- /dev/null +++ b/gotify_tray/gui/themes/dark_purple/status_connecting.svg @@ -0,0 +1,49 @@ + + + + + + + + + + diff --git a/gotify_tray/gui/themes/dark_purple/status_error.svg b/gotify_tray/gui/themes/dark_purple/status_error.svg new file mode 100644 index 0000000..7620aa2 --- /dev/null +++ b/gotify_tray/gui/themes/dark_purple/status_error.svg @@ -0,0 +1,49 @@ + + + + + + + + + + diff --git a/gotify_tray/gui/themes/dark_purple/status_inactive.svg b/gotify_tray/gui/themes/dark_purple/status_inactive.svg new file mode 100644 index 0000000..1de384b --- /dev/null +++ b/gotify_tray/gui/themes/dark_purple/status_inactive.svg @@ -0,0 +1,49 @@ + + + + + + + + + + diff --git a/gotify_tray/gui/themes/dark_purple/style.qss b/gotify_tray/gui/themes/dark_purple/style.qss new file mode 100644 index 0000000..4e33865 --- /dev/null +++ b/gotify_tray/gui/themes/dark_purple/style.qss @@ -0,0 +1,20 @@ +QPushButton:!default:hover { + background: #441b85; +} + +QPushButton:default:hover, QPushButton:checked:hover { + background: #441b85; +} + +QToolTip { + color: #BFBFBF; + background-color: #5522a8; +} + +MessageWidget QPushButton { + border: 0px; +} + +MessageWidget QPushButton:!default:hover { + background: #7249b5; +} diff --git a/gotify_tray/gui/images/trashcan.svg b/gotify_tray/gui/themes/dark_purple/trashcan.svg similarity index 100% rename from gotify_tray/gui/images/trashcan.svg rename to gotify_tray/gui/themes/dark_purple/trashcan.svg diff --git a/gotify_tray/gui/themes/default/__init__.py b/gotify_tray/gui/themes/default/__init__.py new file mode 100644 index 0000000..30e805f --- /dev/null +++ b/gotify_tray/gui/themes/default/__init__.py @@ -0,0 +1 @@ +from .palette import get_palette diff --git a/gotify_tray/gui/themes/default/palette.py b/gotify_tray/gui/themes/default/palette.py new file mode 100644 index 0000000..0b63eb9 --- /dev/null +++ b/gotify_tray/gui/themes/default/palette.py @@ -0,0 +1,7 @@ +from PyQt6 import QtGui + + +def get_palette() -> QtGui.QPalette: + palette = QtGui.QPalette() + + return palette diff --git a/gotify_tray/gui/themes/default/refresh.svg b/gotify_tray/gui/themes/default/refresh.svg new file mode 100644 index 0000000..3257974 --- /dev/null +++ b/gotify_tray/gui/themes/default/refresh.svg @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gotify_tray/gui/images/status_active.svg b/gotify_tray/gui/themes/default/status_active.svg similarity index 100% rename from gotify_tray/gui/images/status_active.svg rename to gotify_tray/gui/themes/default/status_active.svg diff --git a/gotify_tray/gui/images/status_connecting.svg b/gotify_tray/gui/themes/default/status_connecting.svg similarity index 100% rename from gotify_tray/gui/images/status_connecting.svg rename to gotify_tray/gui/themes/default/status_connecting.svg diff --git a/gotify_tray/gui/images/status_error.svg b/gotify_tray/gui/themes/default/status_error.svg similarity index 100% rename from gotify_tray/gui/images/status_error.svg rename to gotify_tray/gui/themes/default/status_error.svg diff --git a/gotify_tray/gui/images/status_inactive.svg b/gotify_tray/gui/themes/default/status_inactive.svg similarity index 100% rename from gotify_tray/gui/images/status_inactive.svg rename to gotify_tray/gui/themes/default/status_inactive.svg diff --git a/gotify_tray/gui/themes/default/style.qss b/gotify_tray/gui/themes/default/style.qss new file mode 100644 index 0000000..cbf3a31 --- /dev/null +++ b/gotify_tray/gui/themes/default/style.qss @@ -0,0 +1,3 @@ +MessageWidget QPushButton { + border: 0px; +} diff --git a/gotify_tray/gui/themes/default/trashcan.svg b/gotify_tray/gui/themes/default/trashcan.svg new file mode 100644 index 0000000..94b811f --- /dev/null +++ b/gotify_tray/gui/themes/default/trashcan.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/gotify_tray/gui/themes/light_purple/__init__.py b/gotify_tray/gui/themes/light_purple/__init__.py new file mode 100644 index 0000000..30e805f --- /dev/null +++ b/gotify_tray/gui/themes/light_purple/__init__.py @@ -0,0 +1 @@ +from .palette import get_palette diff --git a/gotify_tray/gui/themes/light_purple/palette.py b/gotify_tray/gui/themes/light_purple/palette.py new file mode 100644 index 0000000..8e54a51 --- /dev/null +++ b/gotify_tray/gui/themes/light_purple/palette.py @@ -0,0 +1,61 @@ +from PyQt6 import QtGui + + +def get_palette() -> QtGui.QPalette: + palette = QtGui.QPalette() + + palette.setColor(QtGui.QPalette.ColorGroup.Active, QtGui.QPalette.ColorRole.Window, QtGui.QColor(0xF7F7F7)) + palette.setColor(QtGui.QPalette.ColorGroup.Inactive, QtGui.QPalette.ColorRole.Window, QtGui.QColor(0xFCFCFC)) + palette.setColor(QtGui.QPalette.ColorGroup.Disabled, QtGui.QPalette.ColorRole.Window, QtGui.QColor(0xEDEDED)) + + palette.setColor(QtGui.QPalette.ColorGroup.Active, QtGui.QPalette.ColorRole.WindowText, QtGui.QColor(0x1D1D20)) + palette.setColor(QtGui.QPalette.ColorGroup.Inactive, QtGui.QPalette.ColorRole.WindowText, QtGui.QColor(0x252528)) + palette.setColor(QtGui.QPalette.ColorGroup.Disabled, QtGui.QPalette.ColorRole.WindowText, QtGui.QColor(0x8C8C92)) + + palette.setColor(QtGui.QPalette.ColorGroup.Active, QtGui.QPalette.ColorRole.Text, QtGui.QColor(0x1D1D20)) + palette.setColor(QtGui.QPalette.ColorGroup.Inactive, QtGui.QPalette.ColorRole.Text, QtGui.QColor(0x252528)) + palette.setColor(QtGui.QPalette.ColorGroup.Disabled, QtGui.QPalette.ColorRole.Text, QtGui.QColor(0x8C8C92)) + + palette.setColor(QtGui.QPalette.ColorGroup.Active, QtGui.QPalette.ColorRole.PlaceholderText, QtGui.QColor(0x71727D)) + palette.setColor(QtGui.QPalette.ColorGroup.Inactive, QtGui.QPalette.ColorRole.PlaceholderText, QtGui.QColor(0x878893)) + palette.setColor(QtGui.QPalette.ColorGroup.Disabled, QtGui.QPalette.ColorRole.PlaceholderText, QtGui.QColor(0xA3A4AC)) + + palette.setColor(QtGui.QPalette.ColorGroup.Active, QtGui.QPalette.ColorRole.BrightText, QtGui.QColor(0xF3F3F4)) + palette.setColor(QtGui.QPalette.ColorGroup.Inactive, QtGui.QPalette.ColorRole.BrightText, QtGui.QColor(0xEAEAEB)) + palette.setColor(QtGui.QPalette.ColorGroup.Disabled, QtGui.QPalette.ColorRole.BrightText, QtGui.QColor(0xE4E5E7)) + + palette.setColor(QtGui.QPalette.ColorGroup.Active, QtGui.QPalette.ColorRole.Base, QtGui.QColor(0xF9F9F9)) + palette.setColor(QtGui.QPalette.ColorGroup.Inactive, QtGui.QPalette.ColorRole.Base, QtGui.QColor(0xFCFCFC)) + palette.setColor(QtGui.QPalette.ColorGroup.Disabled, QtGui.QPalette.ColorRole.Base, QtGui.QColor(0xEFEFF2)) + + palette.setColor(QtGui.QPalette.ColorGroup.Active, QtGui.QPalette.ColorRole.AlternateBase, QtGui.QColor(0xECF3E8)) + palette.setColor(QtGui.QPalette.ColorGroup.Inactive, QtGui.QPalette.ColorRole.AlternateBase, QtGui.QColor(0xF1F6EE)) + palette.setColor(QtGui.QPalette.ColorGroup.Disabled, QtGui.QPalette.ColorRole.AlternateBase, QtGui.QColor(0xE1E9DD)) + + palette.setColor(QtGui.QPalette.ColorGroup.All, QtGui.QPalette.ColorRole.ToolTipBase, QtGui.QColor(0x5522a8)) + palette.setColor(QtGui.QPalette.ColorGroup.All, QtGui.QPalette.ColorRole.ToolTipText, QtGui.QColor(0xBFBFBF)) + + palette.setColor(QtGui.QPalette.ColorGroup.Active, QtGui.QPalette.ColorRole.ButtonText, QtGui.QColor(0x181A18)) + palette.setColor(QtGui.QPalette.ColorGroup.Inactive, QtGui.QPalette.ColorRole.ButtonText, QtGui.QColor(0x454A54)) + palette.setColor(QtGui.QPalette.ColorGroup.Disabled, QtGui.QPalette.ColorRole.ButtonText, QtGui.QColor(0x97979B)) + + palette.setColor(QtGui.QPalette.ColorGroup.Active, QtGui.QPalette.ColorRole.Highlight, QtGui.QColor(0x6D29DC)) + palette.setColor(QtGui.QPalette.ColorGroup.Inactive, QtGui.QPalette.ColorRole.Highlight, QtGui.QColor(0x5522a8)) + palette.setColor(QtGui.QPalette.ColorGroup.Disabled, QtGui.QPalette.ColorRole.Highlight, QtGui.QColor(0x5522a8)) + + palette.setColor(QtGui.QPalette.ColorGroup.Active, QtGui.QPalette.ColorRole.HighlightedText, QtGui.QColor(0xCCCCCC)) + palette.setColor(QtGui.QPalette.ColorGroup.Inactive, QtGui.QPalette.ColorRole.HighlightedText, QtGui.QColor(0xCECECE)) + palette.setColor(QtGui.QPalette.ColorGroup.Disabled, QtGui.QPalette.ColorRole.HighlightedText, QtGui.QColor(0x707070)) + + palette.setColor(QtGui.QPalette.ColorGroup.All, QtGui.QPalette.ColorRole.Light, QtGui.QColor(0xF9F9F9)) + palette.setColor(QtGui.QPalette.ColorGroup.All, QtGui.QPalette.ColorRole.Midlight, QtGui.QColor(0xE9E9EB)) + palette.setColor(QtGui.QPalette.ColorGroup.All, QtGui.QPalette.ColorRole.Mid, QtGui.QColor(0xC9C9CF)) + palette.setColor(QtGui.QPalette.ColorGroup.All, QtGui.QPalette.ColorRole.Dark, QtGui.QColor(0xBBBBC2)) + palette.setColor(QtGui.QPalette.ColorGroup.All, QtGui.QPalette.ColorRole.Shadow, QtGui.QColor(0x6C6D79)) + + palette.setColor(QtGui.QPalette.ColorGroup.All, QtGui.QPalette.ColorRole.Link, QtGui.QColor(0x723BC4)) + palette.setColor(QtGui.QPalette.ColorGroup.Disabled, QtGui.QPalette.ColorRole.Link, QtGui.QColor(0x723BC4)) + palette.setColor(QtGui.QPalette.ColorGroup.All, QtGui.QPalette.ColorRole.LinkVisited, QtGui.QColor(0x5522a8)) + palette.setColor(QtGui.QPalette.ColorGroup.Disabled, QtGui.QPalette.ColorRole.LinkVisited, QtGui.QColor(0x6D29DC)) + + return palette diff --git a/gotify_tray/gui/themes/light_purple/refresh.svg b/gotify_tray/gui/themes/light_purple/refresh.svg new file mode 100644 index 0000000..3257974 --- /dev/null +++ b/gotify_tray/gui/themes/light_purple/refresh.svg @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gotify_tray/gui/themes/light_purple/status_active.svg b/gotify_tray/gui/themes/light_purple/status_active.svg new file mode 100644 index 0000000..7af0e8e --- /dev/null +++ b/gotify_tray/gui/themes/light_purple/status_active.svg @@ -0,0 +1,49 @@ + + + + + + + + + + diff --git a/gotify_tray/gui/themes/light_purple/status_connecting.svg b/gotify_tray/gui/themes/light_purple/status_connecting.svg new file mode 100644 index 0000000..8b1a364 --- /dev/null +++ b/gotify_tray/gui/themes/light_purple/status_connecting.svg @@ -0,0 +1,49 @@ + + + + + + + + + + diff --git a/gotify_tray/gui/themes/light_purple/status_error.svg b/gotify_tray/gui/themes/light_purple/status_error.svg new file mode 100644 index 0000000..2f89ca1 --- /dev/null +++ b/gotify_tray/gui/themes/light_purple/status_error.svg @@ -0,0 +1,49 @@ + + + + + + + + + + diff --git a/gotify_tray/gui/themes/light_purple/status_inactive.svg b/gotify_tray/gui/themes/light_purple/status_inactive.svg new file mode 100644 index 0000000..2d0eba9 --- /dev/null +++ b/gotify_tray/gui/themes/light_purple/status_inactive.svg @@ -0,0 +1,49 @@ + + + + + + + + + + diff --git a/gotify_tray/gui/themes/light_purple/style.qss b/gotify_tray/gui/themes/light_purple/style.qss new file mode 100644 index 0000000..487de1e --- /dev/null +++ b/gotify_tray/gui/themes/light_purple/style.qss @@ -0,0 +1,20 @@ +QPushButton:!default:hover { + background: #5c24b6; +} + +QPushButton:default:hover, QPushButton:checked:hover { + background: #5c24b6; +} + +QToolTip { + color: #BFBFBF; + background-color: #5522a8; +} + +MessageWidget QPushButton { + border: 0px; +} + +MessageWidget QPushButton:!default:hover { + background: #9662ea; +} diff --git a/gotify_tray/gui/themes/light_purple/trashcan.svg b/gotify_tray/gui/themes/light_purple/trashcan.svg new file mode 100644 index 0000000..94b811f --- /dev/null +++ b/gotify_tray/gui/themes/light_purple/trashcan.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/gotify_tray/gui/widgets/MainWindow.py b/gotify_tray/gui/widgets/MainWindow.py index c8c95c1..0992c38 100644 --- a/gotify_tray/gui/widgets/MainWindow.py +++ b/gotify_tray/gui/widgets/MainWindow.py @@ -10,7 +10,7 @@ from . import MessageWidget from gotify_tray.__version__ import __title__ from gotify_tray.database import Settings -from gotify_tray.utils import get_abs_path +from gotify_tray.gui.themes import get_theme_file settings = Settings("gotify-tray") @@ -44,30 +44,10 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow): # Do not collapse the message list self.splitter.setCollapsible(1, False) - self.status_widget = StatusWidget() self.horizontalLayout.insertWidget(0, self.status_widget) - # Set button icons - self.pb_refresh.setIcon( - QtGui.QIcon(get_abs_path(f"gotify_tray/gui/images/refresh.svg")) - ) - self.pb_delete_all.setIcon( - QtGui.QIcon(get_abs_path(f"gotify_tray/gui/images/trashcan.svg")) - ) - - # Resize the labels and icons - size = settings.value("MainWindow/label/size", type=int) - self.status_widget.setFixedSize(QtCore.QSize(size, size)) - - size = settings.value("MainWindow/button/size", type=int) - self.pb_refresh.setFixedSize(QtCore.QSize(size, size)) - self.pb_delete_all.setFixedSize(QtCore.QSize(size, size)) - self.pb_refresh.setIconSize(QtCore.QSize(int(0.7 * size), int(0.7 * size))) - self.pb_delete_all.setIconSize(QtCore.QSize(int(0.9 * size), int(0.9 * size))) - - size = settings.value("MainWindow/application/icon/size", type=int) - self.listView_applications.setIconSize(QtCore.QSize(size, size)) + self.set_icons() font_title = QtGui.QFont() if s := settings.value("MainWindow/font/application", type=str): @@ -85,6 +65,24 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow): self.link_callbacks() + def set_icons(self): + # Set button icons + self.pb_refresh.setIcon(QtGui.QIcon(get_theme_file("refresh.svg"))) + self.pb_delete_all.setIcon(QtGui.QIcon(get_theme_file("trashcan.svg"))) + + # Resize the labels and icons + size = settings.value("MainWindow/label/size", type=int) + self.status_widget.setFixedSize(QtCore.QSize(size, size)) + + size = settings.value("MainWindow/button/size", type=int) + self.pb_refresh.setFixedSize(QtCore.QSize(size, size)) + self.pb_delete_all.setFixedSize(QtCore.QSize(size, size)) + self.pb_refresh.setIconSize(QtCore.QSize(int(0.7 * size), int(0.7 * size))) + self.pb_delete_all.setIconSize(QtCore.QSize(int(0.9 * size), int(0.9 * size))) + + size = settings.value("MainWindow/application/icon/size", type=int) + self.listView_applications.setIconSize(QtCore.QSize(size, size)) + def set_active(self): self.status_widget.set_active() diff --git a/gotify_tray/gui/widgets/MessageWidget.py b/gotify_tray/gui/widgets/MessageWidget.py index 3aab648..8faa806 100644 --- a/gotify_tray/gui/widgets/MessageWidget.py +++ b/gotify_tray/gui/widgets/MessageWidget.py @@ -5,7 +5,8 @@ from PyQt6 import QtCore, QtGui, QtWidgets from ..models.MessagesModel import MessageItemDataRole, MessagesModelItem from ..designs.widget_message import Ui_Form from gotify_tray.database import Settings -from gotify_tray.utils import convert_links, get_abs_path +from gotify_tray.utils import convert_links +from gotify_tray.gui.themes import get_theme_file settings = Settings("gotify-tray") @@ -60,9 +61,7 @@ class MessageWidget(QtWidgets.QWidget, Ui_Form): size_hint = self.message_item.sizeHint() self.message_item.setSizeHint(QtCore.QSize(size_hint.width(), self.height())) - self.pb_delete.setIcon( - QtGui.QIcon(get_abs_path("gotify_tray/gui/images/trashcan.svg")) - ) + self.pb_delete.setIcon(QtGui.QIcon(get_theme_file("trashcan.svg"))) self.pb_delete.setIconSize(QtCore.QSize(24, 24)) self.link_callbacks() @@ -92,7 +91,7 @@ class MessageWidget(QtWidgets.QWidget, Ui_Form): def link_hovered_callback(self, link: str): if not settings.value("ImagePopup/enabled", type=bool): return - + qurl = QtCore.QUrl(link) _, ext = os.path.splitext(qurl.fileName()) if ext in settings.value("ImagePopup/extensions", type=list): diff --git a/gotify_tray/gui/widgets/SettingsDialog.py b/gotify_tray/gui/widgets/SettingsDialog.py index 1cd7622..6a2a64f 100644 --- a/gotify_tray/gui/widgets/SettingsDialog.py +++ b/gotify_tray/gui/widgets/SettingsDialog.py @@ -8,6 +8,7 @@ from gotify_tray.gui.models import MessagesModelItem from . import MessageWidget from gotify_tray.utils import get_icon, verify_server, open_file from gotify_tray.tasks import ExportSettingsTask, ImportSettingsTask +from gotify_tray.gui.themes import get_themes from PyQt6 import QtCore, QtGui, QtWidgets from ..designs.widget_settings import Ui_Dialog @@ -19,6 +20,7 @@ settings = Settings("gotify-tray") class SettingsDialog(QtWidgets.QDialog, Ui_Dialog): quit_requested = QtCore.pyqtSignal() + theme_change_requested = QtCore.pyqtSignal(str) def __init__(self): super(SettingsDialog, self).__init__() @@ -60,6 +62,10 @@ class SettingsDialog(QtWidgets.QDialog, Ui_Dialog): settings.value("tray/notifications/click", type=bool) ) + # Theme + self.combo_theme.addItems(get_themes()) + self.combo_theme.setCurrentText(settings.value("theme", type=str)) + # Logging self.combo_logging.addItems( [ @@ -163,6 +169,9 @@ class SettingsDialog(QtWidgets.QDialog, Ui_Dialog): self.cb_notify.stateChanged.connect(self.settings_changed_callback) self.cb_notification_click.stateChanged.connect(self.settings_changed_callback) + # Theme + self.combo_theme.currentTextChanged.connect(self.settings_changed_callback) + # Server info self.pb_change_server_info.clicked.connect(self.change_server_info_callback) @@ -200,6 +209,13 @@ class SettingsDialog(QtWidgets.QDialog, Ui_Dialog): "tray/notifications/click", self.cb_notification_click.isChecked() ) + # Theme + current_theme = settings.value("theme", type=str) + selected_theme = self.combo_theme.currentText() + if current_theme != selected_theme: + settings.setValue("theme", selected_theme) + self.theme_change_requested.emit(selected_theme) + # Logging selected_level = self.combo_logging.currentText() settings.setValue("logging/level", selected_level) diff --git a/gotify_tray/gui/widgets/StatusWidget.py b/gotify_tray/gui/widgets/StatusWidget.py index 25ff5ae..41c9756 100644 --- a/gotify_tray/gui/widgets/StatusWidget.py +++ b/gotify_tray/gui/widgets/StatusWidget.py @@ -1,7 +1,7 @@ from PyQt6 import QtCore, QtGui, QtWidgets from gotify_tray.database import Settings -from gotify_tray.utils import get_abs_path +from gotify_tray.gui.themes import get_theme_file settings = Settings("gotify-tray") @@ -15,7 +15,7 @@ class StatusWidget(QtWidgets.QLabel): self.set_connecting() def set_status(self, image: str): - self.setPixmap(QtGui.QPixmap(get_abs_path(f"gotify_tray/gui/images/{image}"))) + self.setPixmap(QtGui.QPixmap(get_theme_file(image))) def set_active(self): self.setToolTip("Listening for new messages") diff --git a/setup.py b/setup.py index a11ee3e..80d3e4a 100644 --- a/setup.py +++ b/setup.py @@ -63,7 +63,10 @@ setup( # If your package is a single module, use this instead of 'packages': packages=find_packages(), package_data={ - 'gotify_tray.gui.images': ['*.svg', '*.png'] + 'gotify_tray.gui.images': ['*.ico', '*.png'], + 'gotify_tray.gui.themes.default': ['*.qss', '*.svg', '*.png'], + 'gotify_tray.gui.themes.dark_purple': ['*.qss', '*.svg', '*.png'], + 'gotify_tray.gui.themes.light_purple': ['*.qss', '*.svg', '*.png'], }, data_files = [ ],