Automatic theme (#29)
* add "automatic" theme set the theme and icons based on the system theme * update the default icons based on system theme * update pyqt to 6.5.0 to get the colorSchemeChanged callback * rename style to theme * remove unused svg files for default theme * ServerInfoDialog: update feedback colors in dark mode
This commit is contained in:
@@ -5,7 +5,7 @@ from ..__version__ import __title__
|
|||||||
|
|
||||||
|
|
||||||
DEFAULT_SETTINGS = {
|
DEFAULT_SETTINGS = {
|
||||||
"theme": "default",
|
"theme": "automatic",
|
||||||
"message/check_missed/notify": True,
|
"message/check_missed/notify": True,
|
||||||
"logging/level": "Disabled",
|
"logging/level": "Disabled",
|
||||||
"export/path": os.path.join(
|
"export/path": os.path.join(
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ class MainApplication(QtWidgets.QApplication):
|
|||||||
self.messages_model = MessagesModel()
|
self.messages_model = MessagesModel()
|
||||||
self.application_model = ApplicationModel()
|
self.application_model = ApplicationModel()
|
||||||
|
|
||||||
self.main_window = MainWindow(self.application_model, self.messages_model)
|
self.main_window = MainWindow(self, self.application_model, self.messages_model)
|
||||||
self.main_window.show() # The initial .show() is necessary to get the correct sizes when adding MessageWigets
|
self.main_window.show() # The initial .show() is necessary to get the correct sizes when adding MessageWigets
|
||||||
QtCore.QTimer.singleShot(0, self.main_window.hide)
|
QtCore.QTimer.singleShot(0, self.main_window.hide)
|
||||||
|
|
||||||
@@ -381,7 +381,7 @@ class MainApplication(QtWidgets.QApplication):
|
|||||||
message_widget.set_icons()
|
message_widget.set_icons()
|
||||||
|
|
||||||
def settings_callback(self):
|
def settings_callback(self):
|
||||||
settings_dialog = SettingsDialog()
|
settings_dialog = SettingsDialog(self)
|
||||||
settings_dialog.quit_requested.connect(self.quit)
|
settings_dialog.quit_requested.connect(self.quit)
|
||||||
settings_dialog.theme_change_requested.connect(
|
settings_dialog.theme_change_requested.connect(
|
||||||
self.theme_change_requested_callback
|
self.theme_change_requested_callback
|
||||||
@@ -436,6 +436,8 @@ class MainApplication(QtWidgets.QApplication):
|
|||||||
self.main_window.hidden.connect(self.main_window_hidden_callback)
|
self.main_window.hidden.connect(self.main_window_hidden_callback)
|
||||||
self.main_window.activated.connect(self.tray.revert_icon)
|
self.main_window.activated.connect(self.tray.revert_icon)
|
||||||
|
|
||||||
|
self.styleHints().colorSchemeChanged.connect(lambda _: self.theme_change_requested_callback(settings.value("theme", type=str)))
|
||||||
|
|
||||||
self.watchdog.closed.connect(lambda: self.listener_closed_callback(None, None))
|
self.watchdog.closed.connect(lambda: self.listener_closed_callback(None, None))
|
||||||
|
|
||||||
def init_shortcuts(self):
|
def init_shortcuts(self):
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import logging
|
import logging
|
||||||
from PyQt6 import QtGui, QtWidgets
|
from PyQt6 import QtCore, QtGui, QtWidgets
|
||||||
from gotify_tray.utils import get_abs_path
|
from gotify_tray.utils import get_abs_path
|
||||||
from . import default, dark_purple, light_purple
|
from . import default, dark_purple, light_purple
|
||||||
from gotify_tray.database import Settings
|
from gotify_tray.database import Settings
|
||||||
@@ -9,28 +9,50 @@ settings = Settings("gotify-tray")
|
|||||||
logger = logging.getLogger("gotify-tray")
|
logger = logging.getLogger("gotify-tray")
|
||||||
|
|
||||||
|
|
||||||
styles = {
|
themes = {
|
||||||
"default": default,
|
"default": default,
|
||||||
|
"automatic": None,
|
||||||
"dark purple": dark_purple,
|
"dark purple": dark_purple,
|
||||||
"light purple": light_purple,
|
"light purple": light_purple,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def set_theme(app: QtWidgets.QApplication, style: str = "default"):
|
def get_themes():
|
||||||
if style not in styles.keys():
|
return themes.keys()
|
||||||
logger.error(f"set_style: style {style} is unsupported.")
|
|
||||||
return
|
|
||||||
|
def is_dark_mode(app: QtWidgets.QApplication) -> bool:
|
||||||
|
return app.styleHints().colorScheme() == QtCore.Qt.ColorScheme.Dark
|
||||||
|
|
||||||
|
|
||||||
|
def is_valid_theme(theme: str) -> bool:
|
||||||
|
return theme in get_themes()
|
||||||
|
|
||||||
|
|
||||||
|
def set_theme(app: QtWidgets.QApplication, theme: str = "automatic"):
|
||||||
|
if not is_valid_theme(theme):
|
||||||
|
logger.warning(f"set_theme: theme {theme} is unsupported.")
|
||||||
|
theme = "automatic"
|
||||||
|
|
||||||
|
if theme == "automatic":
|
||||||
|
theme = "dark purple" if is_dark_mode(app) else "light purple"
|
||||||
|
|
||||||
stylesheet = ""
|
stylesheet = ""
|
||||||
with open(get_abs_path(f"gotify_tray/gui/themes/{style.replace(' ', '_')}/style.qss"), "r") as f:
|
with open(get_abs_path(f"gotify_tray/gui/themes/{theme.replace(' ', '_')}/style.qss"), "r") as f:
|
||||||
stylesheet += f.read()
|
stylesheet += f.read()
|
||||||
|
|
||||||
app.setPalette(styles[style].get_palette())
|
app.setPalette(themes[theme].get_palette())
|
||||||
app.setStyleSheet(stylesheet)
|
app.setStyleSheet(stylesheet)
|
||||||
|
|
||||||
def get_themes():
|
|
||||||
return styles.keys()
|
|
||||||
|
|
||||||
def get_theme_file(file: str, theme: str = None) -> str:
|
def get_theme_file(app: QtWidgets.QApplication, file: str, theme: str = None) -> str:
|
||||||
theme = settings.value("theme", type=str) if not theme else theme
|
theme = settings.value("theme", type=str) if not theme else theme
|
||||||
|
|
||||||
|
if not is_valid_theme(theme):
|
||||||
|
logger.warning(f"set_theme: theme {theme} is unsupported.")
|
||||||
|
theme = "automatic"
|
||||||
|
|
||||||
|
if theme in ("automatic", "default"):
|
||||||
|
theme = "dark purple" if is_dark_mode(app) else "light purple"
|
||||||
|
|
||||||
return get_abs_path(f"gotify_tray/gui/themes/{theme.replace(' ', '_')}/{file}")
|
return get_abs_path(f"gotify_tray/gui/themes/{theme.replace(' ', '_')}/{file}")
|
||||||
|
|||||||
@@ -6,6 +6,22 @@ QPushButton:default:hover, QPushButton:checked:hover {
|
|||||||
background: #441b85;
|
background: #441b85;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QPushButton[state="success"] {
|
||||||
|
background-color: #960b7a0b;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
QPushButton[state="failed"] {
|
||||||
|
background-color: #8ebb2929;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
QLineEdit[state="success"] {}
|
||||||
|
|
||||||
|
QLineEdit[state="failed"] {
|
||||||
|
border: 1px solid red;
|
||||||
|
}
|
||||||
|
|
||||||
QToolTip {
|
QToolTip {
|
||||||
color: #BFBFBF;
|
color: #BFBFBF;
|
||||||
background-color: #5522a8;
|
background-color: #5522a8;
|
||||||
|
|||||||
@@ -1,45 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
|
||||||
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
|
||||||
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
|
||||||
viewBox="0 0 492.883 492.883" style="enable-background:new 0 0 492.883 492.883;" xml:space="preserve">
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<path d="M122.941,374.241c-20.1-18.1-34.6-39.8-44.1-63.1c-25.2-61.8-13.4-135.3,35.8-186l45.4,45.4c2.5,2.5,7,0.7,7.6-3
|
|
||||||
l24.8-162.3c0.4-2.7-1.9-5-4.6-4.6l-162.4,24.8c-3.7,0.6-5.5,5.1-3,7.6l45.5,45.5c-75.1,76.8-87.9,192-38.6,282
|
|
||||||
c14.8,27.1,35.3,51.9,61.4,72.7c44.4,35.3,99,52.2,153.2,51.1l10.2-66.7C207.441,421.641,159.441,407.241,122.941,374.241z"/>
|
|
||||||
<path d="M424.941,414.341c75.1-76.8,87.9-192,38.6-282c-14.8-27.1-35.3-51.9-61.4-72.7c-44.4-35.3-99-52.2-153.2-51.1l-10.2,66.7
|
|
||||||
c46.6-4,94.7,10.4,131.2,43.4c20.1,18.1,34.6,39.8,44.1,63.1c25.2,61.8,13.4,135.3-35.8,186l-45.4-45.4c-2.5-2.5-7-0.7-7.6,3
|
|
||||||
l-24.8,162.3c-0.4,2.7,1.9,5,4.6,4.6l162.4-24.8c3.7-0.6,5.4-5.1,3-7.6L424.941,414.341z"/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 1.2 KiB |
@@ -1,49 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
|
||||||
|
|
||||||
<svg
|
|
||||||
width="29.348576mm"
|
|
||||||
height="29.348576mm"
|
|
||||||
viewBox="0 0 29.348576 29.348576"
|
|
||||||
version="1.1"
|
|
||||||
id="svg5"
|
|
||||||
sodipodi:docname="status_ok.svg"
|
|
||||||
inkscape:version="1.1.2 (0a00cf5339, 2022-02-04, custom)"
|
|
||||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
|
||||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
xmlns:svg="http://www.w3.org/2000/svg">
|
|
||||||
<sodipodi:namedview
|
|
||||||
id="namedview7"
|
|
||||||
pagecolor="#ffffff"
|
|
||||||
bordercolor="#666666"
|
|
||||||
borderopacity="1.0"
|
|
||||||
inkscape:pageshadow="2"
|
|
||||||
inkscape:pageopacity="0.0"
|
|
||||||
inkscape:pagecheckerboard="0"
|
|
||||||
inkscape:document-units="mm"
|
|
||||||
showgrid="false"
|
|
||||||
inkscape:zoom="0.77771465"
|
|
||||||
inkscape:cx="188.37243"
|
|
||||||
inkscape:cy="505.96964"
|
|
||||||
inkscape:window-width="1284"
|
|
||||||
inkscape:window-height="1082"
|
|
||||||
inkscape:window-x="1622"
|
|
||||||
inkscape:window-y="248"
|
|
||||||
inkscape:window-maximized="0"
|
|
||||||
inkscape:current-layer="layer1" />
|
|
||||||
<defs
|
|
||||||
id="defs2" />
|
|
||||||
<g
|
|
||||||
inkscape:label="Layer 1"
|
|
||||||
inkscape:groupmode="layer"
|
|
||||||
id="layer1"
|
|
||||||
transform="translate(-24.619528,-14.753546)">
|
|
||||||
<circle
|
|
||||||
style="fill:#00db00;fill-opacity:1;stroke-width:0.264583"
|
|
||||||
id="path846"
|
|
||||||
cx="39.293816"
|
|
||||||
cy="29.427834"
|
|
||||||
r="14.674288" />
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 1.4 KiB |
@@ -1,49 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
|
||||||
|
|
||||||
<svg
|
|
||||||
width="29.348576mm"
|
|
||||||
height="29.348576mm"
|
|
||||||
viewBox="0 0 29.348576 29.348576"
|
|
||||||
version="1.1"
|
|
||||||
id="svg5"
|
|
||||||
sodipodi:docname="status_connecting.svg"
|
|
||||||
inkscape:version="1.1.2 (0a00cf5339, 2022-02-04, custom)"
|
|
||||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
|
||||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
xmlns:svg="http://www.w3.org/2000/svg">
|
|
||||||
<sodipodi:namedview
|
|
||||||
id="namedview7"
|
|
||||||
pagecolor="#ffffff"
|
|
||||||
bordercolor="#666666"
|
|
||||||
borderopacity="1.0"
|
|
||||||
inkscape:pageshadow="2"
|
|
||||||
inkscape:pageopacity="0.0"
|
|
||||||
inkscape:pagecheckerboard="0"
|
|
||||||
inkscape:document-units="mm"
|
|
||||||
showgrid="false"
|
|
||||||
inkscape:zoom="0.77771465"
|
|
||||||
inkscape:cx="188.37243"
|
|
||||||
inkscape:cy="505.96964"
|
|
||||||
inkscape:window-width="1284"
|
|
||||||
inkscape:window-height="1082"
|
|
||||||
inkscape:window-x="1852"
|
|
||||||
inkscape:window-y="271"
|
|
||||||
inkscape:window-maximized="0"
|
|
||||||
inkscape:current-layer="layer1" />
|
|
||||||
<defs
|
|
||||||
id="defs2" />
|
|
||||||
<g
|
|
||||||
inkscape:label="Layer 1"
|
|
||||||
inkscape:groupmode="layer"
|
|
||||||
id="layer1"
|
|
||||||
transform="translate(-24.619528,-14.753546)">
|
|
||||||
<circle
|
|
||||||
style="fill:#ffb200;fill-opacity:1;stroke-width:0.264583"
|
|
||||||
id="path846"
|
|
||||||
cx="39.293816"
|
|
||||||
cy="29.427834"
|
|
||||||
r="14.674288" />
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 1.4 KiB |
@@ -1,49 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
|
||||||
|
|
||||||
<svg
|
|
||||||
width="29.348576mm"
|
|
||||||
height="29.348576mm"
|
|
||||||
viewBox="0 0 29.348576 29.348576"
|
|
||||||
version="1.1"
|
|
||||||
id="svg5"
|
|
||||||
sodipodi:docname="status_error.svg"
|
|
||||||
inkscape:version="1.1.2 (0a00cf5339, 2022-02-04, custom)"
|
|
||||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
|
||||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
xmlns:svg="http://www.w3.org/2000/svg">
|
|
||||||
<sodipodi:namedview
|
|
||||||
id="namedview7"
|
|
||||||
pagecolor="#ffffff"
|
|
||||||
bordercolor="#666666"
|
|
||||||
borderopacity="1.0"
|
|
||||||
inkscape:pageshadow="2"
|
|
||||||
inkscape:pageopacity="0.0"
|
|
||||||
inkscape:pagecheckerboard="0"
|
|
||||||
inkscape:document-units="mm"
|
|
||||||
showgrid="false"
|
|
||||||
inkscape:zoom="0.77771465"
|
|
||||||
inkscape:cx="188.37243"
|
|
||||||
inkscape:cy="505.96964"
|
|
||||||
inkscape:window-width="1284"
|
|
||||||
inkscape:window-height="1082"
|
|
||||||
inkscape:window-x="2013"
|
|
||||||
inkscape:window-y="263"
|
|
||||||
inkscape:window-maximized="0"
|
|
||||||
inkscape:current-layer="layer1" />
|
|
||||||
<defs
|
|
||||||
id="defs2" />
|
|
||||||
<g
|
|
||||||
inkscape:label="Layer 1"
|
|
||||||
inkscape:groupmode="layer"
|
|
||||||
id="layer1"
|
|
||||||
transform="translate(-24.619528,-14.753546)">
|
|
||||||
<circle
|
|
||||||
style="fill:#ff3232;fill-opacity:1;stroke-width:0.264583"
|
|
||||||
id="path846"
|
|
||||||
cx="39.293816"
|
|
||||||
cy="29.427834"
|
|
||||||
r="14.674288" />
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 1.4 KiB |
@@ -1,49 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
|
||||||
|
|
||||||
<svg
|
|
||||||
width="29.348576mm"
|
|
||||||
height="29.348576mm"
|
|
||||||
viewBox="0 0 29.348576 29.348576"
|
|
||||||
version="1.1"
|
|
||||||
id="svg5"
|
|
||||||
sodipodi:docname="status_inactive.svg"
|
|
||||||
inkscape:version="1.1.2 (0a00cf5339, 2022-02-04, custom)"
|
|
||||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
|
||||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
xmlns:svg="http://www.w3.org/2000/svg">
|
|
||||||
<sodipodi:namedview
|
|
||||||
id="namedview7"
|
|
||||||
pagecolor="#ffffff"
|
|
||||||
bordercolor="#666666"
|
|
||||||
borderopacity="1.0"
|
|
||||||
inkscape:pageshadow="2"
|
|
||||||
inkscape:pageopacity="0.0"
|
|
||||||
inkscape:pagecheckerboard="0"
|
|
||||||
inkscape:document-units="mm"
|
|
||||||
showgrid="false"
|
|
||||||
inkscape:zoom="0.77771465"
|
|
||||||
inkscape:cx="188.37243"
|
|
||||||
inkscape:cy="505.96964"
|
|
||||||
inkscape:window-width="1284"
|
|
||||||
inkscape:window-height="1082"
|
|
||||||
inkscape:window-x="1852"
|
|
||||||
inkscape:window-y="271"
|
|
||||||
inkscape:window-maximized="0"
|
|
||||||
inkscape:current-layer="layer1" />
|
|
||||||
<defs
|
|
||||||
id="defs2" />
|
|
||||||
<g
|
|
||||||
inkscape:label="Layer 1"
|
|
||||||
inkscape:groupmode="layer"
|
|
||||||
id="layer1"
|
|
||||||
transform="translate(-24.619528,-14.753546)">
|
|
||||||
<circle
|
|
||||||
style="fill:#b4b4b4;fill-opacity:1;stroke-width:0.264583"
|
|
||||||
id="path846"
|
|
||||||
cx="39.293816"
|
|
||||||
cy="29.427834"
|
|
||||||
r="14.674288" />
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 1.4 KiB |
@@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z"/></svg>
|
|
||||||
|
Before Width: | Height: | Size: 155 B |
@@ -6,6 +6,22 @@ QPushButton:default:hover, QPushButton:checked:hover {
|
|||||||
background: #5c24b6;
|
background: #5c24b6;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QPushButton[state="success"] {
|
||||||
|
background-color: #6400FF00;
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
QPushButton[state="failed"] {
|
||||||
|
background-color: #64FF0000;
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
QLineEdit[state="success"] {}
|
||||||
|
|
||||||
|
QLineEdit[state="failed"] {
|
||||||
|
border: 1px solid red;
|
||||||
|
}
|
||||||
|
|
||||||
QToolTip {
|
QToolTip {
|
||||||
color: #BFBFBF;
|
color: #BFBFBF;
|
||||||
background-color: #5522a8;
|
background-color: #5522a8;
|
||||||
|
|||||||
@@ -26,7 +26,8 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
|
|||||||
activated = QtCore.pyqtSignal()
|
activated = QtCore.pyqtSignal()
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self, application_model: ApplicationModel, messages_model: MessagesModel
|
self, app: QtWidgets.QApplication,
|
||||||
|
application_model: ApplicationModel, messages_model: MessagesModel
|
||||||
):
|
):
|
||||||
super(MainWindow, self).__init__()
|
super(MainWindow, self).__init__()
|
||||||
self.setupUi(self)
|
self.setupUi(self)
|
||||||
@@ -35,6 +36,8 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
|
|||||||
|
|
||||||
self.setWindowTitle(__title__)
|
self.setWindowTitle(__title__)
|
||||||
|
|
||||||
|
self.app = app
|
||||||
|
|
||||||
self.application_model = application_model
|
self.application_model = application_model
|
||||||
self.messages_model = messages_model
|
self.messages_model = messages_model
|
||||||
|
|
||||||
@@ -47,7 +50,7 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
|
|||||||
|
|
||||||
# Do not collapse the message list
|
# Do not collapse the message list
|
||||||
self.splitter.setCollapsible(1, False)
|
self.splitter.setCollapsible(1, False)
|
||||||
self.status_widget = StatusWidget()
|
self.status_widget = StatusWidget(app)
|
||||||
self.horizontalLayout.insertWidget(0, self.status_widget)
|
self.horizontalLayout.insertWidget(0, self.status_widget)
|
||||||
|
|
||||||
self.set_icons()
|
self.set_icons()
|
||||||
@@ -70,8 +73,8 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
|
|||||||
|
|
||||||
def set_icons(self):
|
def set_icons(self):
|
||||||
# Set button icons
|
# Set button icons
|
||||||
self.pb_refresh.setIcon(QtGui.QIcon(get_theme_file("refresh.svg")))
|
self.pb_refresh.setIcon(QtGui.QIcon(get_theme_file(self.app, "refresh.svg")))
|
||||||
self.pb_delete_all.setIcon(QtGui.QIcon(get_theme_file("trashcan.svg")))
|
self.pb_delete_all.setIcon(QtGui.QIcon(get_theme_file(self.app, "trashcan.svg")))
|
||||||
|
|
||||||
# Resize the labels and icons
|
# Resize the labels and icons
|
||||||
size = settings.value("MainWindow/label/size", type=int)
|
size = settings.value("MainWindow/label/size", type=int)
|
||||||
@@ -105,7 +108,7 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
|
|||||||
self, message_item: MessagesModelItem, image_path: str = ""
|
self, message_item: MessagesModelItem, image_path: str = ""
|
||||||
):
|
):
|
||||||
message_widget = MessageWidget(
|
message_widget = MessageWidget(
|
||||||
self.listView_messages, message_item, image_path=image_path
|
self.app, self.listView_messages, message_item, image_path=image_path
|
||||||
)
|
)
|
||||||
self.listView_messages.setIndexWidget(
|
self.listView_messages.setIndexWidget(
|
||||||
self.messages_model.indexFromItem(message_item), message_widget
|
self.messages_model.indexFromItem(message_item), message_widget
|
||||||
|
|||||||
@@ -20,11 +20,13 @@ class MessageWidget(QtWidgets.QWidget, Ui_Form):
|
|||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
|
app: QtWidgets.QApplication,
|
||||||
parent: QtWidgets.QWidget,
|
parent: QtWidgets.QWidget,
|
||||||
message_item: MessagesModelItem,
|
message_item: MessagesModelItem,
|
||||||
image_path: str = "",
|
image_path: str = "",
|
||||||
):
|
):
|
||||||
super(MessageWidget, self).__init__()
|
super(MessageWidget, self).__init__()
|
||||||
|
self.app = app
|
||||||
self.parent = parent
|
self.parent = parent
|
||||||
self.setupUi(self)
|
self.setupUi(self)
|
||||||
self.setAutoFillBackground(True)
|
self.setAutoFillBackground(True)
|
||||||
@@ -104,7 +106,7 @@ class MessageWidget(QtWidgets.QWidget, Ui_Form):
|
|||||||
self.label_message.setFont(font_content)
|
self.label_message.setFont(font_content)
|
||||||
|
|
||||||
def set_icons(self):
|
def set_icons(self):
|
||||||
self.pb_delete.setIcon(QtGui.QIcon(get_theme_file("trashcan.svg")))
|
self.pb_delete.setIcon(QtGui.QIcon(get_theme_file(self.app, "trashcan.svg")))
|
||||||
self.pb_delete.setIconSize(QtCore.QSize(24, 24))
|
self.pb_delete.setIconSize(QtCore.QSize(24, 24))
|
||||||
|
|
||||||
def set_message_image(self, filename: str):
|
def set_message_image(self, filename: str):
|
||||||
|
|||||||
@@ -47,10 +47,18 @@ class ServerInfoDialog(QtWidgets.QDialog, Ui_Dialog):
|
|||||||
self.task.incorrect_url.connect(self.incorrect_url_callback)
|
self.task.incorrect_url.connect(self.incorrect_url_callback)
|
||||||
self.task.start()
|
self.task.start()
|
||||||
|
|
||||||
|
def update_widget_state(self, widget: QtWidgets.QWidget, state: str):
|
||||||
|
widget.setProperty("state", state)
|
||||||
|
widget.style().unpolish(widget)
|
||||||
|
widget.style().polish(widget)
|
||||||
|
widget.update()
|
||||||
|
|
||||||
def server_info_success(self, version: GotifyVersionModel):
|
def server_info_success(self, version: GotifyVersionModel):
|
||||||
self.pb_test.setEnabled(True)
|
self.pb_test.setEnabled(True)
|
||||||
self.label_server_info.setText(f"Version: {version.version}")
|
self.label_server_info.setText(f"Version: {version.version}")
|
||||||
self.pb_test.setStyleSheet("background-color: rgba(0, 255, 0, 100);")
|
self.update_widget_state(self.pb_test, "success")
|
||||||
|
self.update_widget_state(self.line_token, "success")
|
||||||
|
self.update_widget_state(self.line_url, "success")
|
||||||
self.buttonBox.button(QtWidgets.QDialogButtonBox.StandardButton.Ok).setEnabled(
|
self.buttonBox.button(QtWidgets.QDialogButtonBox.StandardButton.Ok).setEnabled(
|
||||||
True
|
True
|
||||||
)
|
)
|
||||||
@@ -59,15 +67,17 @@ class ServerInfoDialog(QtWidgets.QDialog, Ui_Dialog):
|
|||||||
def incorrect_token_callback(self, version: GotifyVersionModel):
|
def incorrect_token_callback(self, version: GotifyVersionModel):
|
||||||
self.pb_test.setEnabled(True)
|
self.pb_test.setEnabled(True)
|
||||||
self.label_server_info.setText(f"Version: {version.version}")
|
self.label_server_info.setText(f"Version: {version.version}")
|
||||||
self.pb_test.setStyleSheet("background-color: rgba(255, 0, 0, 100);")
|
self.update_widget_state(self.pb_test, "failed")
|
||||||
self.line_token.setStyleSheet("border: 1px solid red;")
|
self.update_widget_state(self.line_token, "failed")
|
||||||
|
self.update_widget_state(self.line_url, "success")
|
||||||
self.line_token.setFocus()
|
self.line_token.setFocus()
|
||||||
|
|
||||||
def incorrect_url_callback(self):
|
def incorrect_url_callback(self):
|
||||||
self.pb_test.setEnabled(True)
|
self.pb_test.setEnabled(True)
|
||||||
self.label_server_info.clear()
|
self.label_server_info.clear()
|
||||||
self.pb_test.setStyleSheet("background-color: rgba(255, 0, 0, 100);")
|
self.update_widget_state(self.pb_test, "failed")
|
||||||
self.line_url.setStyleSheet("border: 1px solid red;")
|
self.update_widget_state(self.line_token, "success")
|
||||||
|
self.update_widget_state(self.line_url, "failed")
|
||||||
self.line_url.setFocus()
|
self.line_url.setFocus()
|
||||||
|
|
||||||
def import_success_callback(self):
|
def import_success_callback(self):
|
||||||
|
|||||||
@@ -27,11 +27,13 @@ class SettingsDialog(QtWidgets.QDialog, Ui_Dialog):
|
|||||||
quit_requested = QtCore.pyqtSignal()
|
quit_requested = QtCore.pyqtSignal()
|
||||||
theme_change_requested = QtCore.pyqtSignal(str)
|
theme_change_requested = QtCore.pyqtSignal(str)
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self, app: QtWidgets.QApplication):
|
||||||
super(SettingsDialog, self).__init__()
|
super(SettingsDialog, self).__init__()
|
||||||
self.setupUi(self)
|
self.setupUi(self)
|
||||||
self.setWindowTitle("Settings")
|
self.setWindowTitle("Settings")
|
||||||
|
|
||||||
|
self.app = app
|
||||||
|
|
||||||
self.settings_changed = False
|
self.settings_changed = False
|
||||||
self.changes_applied = False
|
self.changes_applied = False
|
||||||
self.server_changed = False
|
self.server_changed = False
|
||||||
@@ -104,6 +106,7 @@ class SettingsDialog(QtWidgets.QDialog, Ui_Dialog):
|
|||||||
|
|
||||||
def add_message_widget(self):
|
def add_message_widget(self):
|
||||||
self.message_widget = MessageWidget(
|
self.message_widget = MessageWidget(
|
||||||
|
self.app,
|
||||||
self,
|
self,
|
||||||
MessagesModelItem(
|
MessagesModelItem(
|
||||||
GotifyMessageModel(
|
GotifyMessageModel(
|
||||||
|
|||||||
@@ -8,8 +8,9 @@ settings = Settings("gotify-tray")
|
|||||||
|
|
||||||
|
|
||||||
class StatusWidget(QtWidgets.QLabel):
|
class StatusWidget(QtWidgets.QLabel):
|
||||||
def __init__(self):
|
def __init__(self, app: QtWidgets.QApplication):
|
||||||
super(StatusWidget, self).__init__()
|
super(StatusWidget, self).__init__()
|
||||||
|
self.app = app
|
||||||
self.setFixedSize(QtCore.QSize(20, 20))
|
self.setFixedSize(QtCore.QSize(20, 20))
|
||||||
self.setScaledContents(True)
|
self.setScaledContents(True)
|
||||||
self.set_connecting()
|
self.set_connecting()
|
||||||
@@ -17,7 +18,7 @@ class StatusWidget(QtWidgets.QLabel):
|
|||||||
|
|
||||||
def set_status(self, image: str):
|
def set_status(self, image: str):
|
||||||
self.image = image
|
self.image = image
|
||||||
self.setPixmap(QtGui.QPixmap(get_theme_file(image)))
|
self.setPixmap(QtGui.QPixmap(get_theme_file(self.app, image)))
|
||||||
|
|
||||||
def set_active(self):
|
def set_active(self):
|
||||||
self.setToolTip("Listening for new messages")
|
self.setToolTip("Listening for new messages")
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
requests==2.28.2
|
requests==2.28.2
|
||||||
websocket-client==1.5.1
|
websocket-client==1.5.1
|
||||||
pyqt6==6.4.2
|
pyqt6==6.5.0
|
||||||
python-dateutil==2.8.2
|
python-dateutil==2.8.2
|
||||||
|
|||||||
Reference in New Issue
Block a user