Compare commits
10 Commits
3ee3942c01
...
2108568f50
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2108568f50 | ||
|
|
4e4fd9cdc9 | ||
|
|
a8a03321f2 | ||
|
|
490044d9a7 | ||
|
|
a3ae246580 | ||
|
|
0730c160f6 | ||
|
|
ed815fb459 | ||
|
|
05da3a8295 | ||
|
|
f40f154f30 | ||
|
|
4e34c5e614 |
54
.github/workflows/develop.yml
vendored
54
.github/workflows/develop.yml
vendored
@@ -12,11 +12,11 @@ jobs:
|
||||
build-win64:
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v4
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.10.8'
|
||||
python-version: '3.13'
|
||||
- name: Upgrade pip and enable wheel support
|
||||
run: python -m pip install --upgrade pip setuptools wheel
|
||||
- name: Install Requirements
|
||||
@@ -30,49 +30,19 @@ jobs:
|
||||
mv inno-output\gotify-tray-installer.exe gotify-tray-installer-win.exe
|
||||
shell: cmd
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: gotify-tray-installer-win.exe
|
||||
path: gotify-tray-installer-win.exe
|
||||
|
||||
build-ubuntu:
|
||||
strategy:
|
||||
matrix:
|
||||
tag: [jammy]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.10.8'
|
||||
- name: Upgrade pip and enable wheel support
|
||||
run: python -m pip install --upgrade pip setuptools wheel
|
||||
- uses: ruby/setup-ruby@v1
|
||||
with:
|
||||
ruby-version: '3.0'
|
||||
- name: Build
|
||||
run: |
|
||||
pip install -r requirements.txt
|
||||
pip install pyinstaller
|
||||
gem install fpm
|
||||
chmod +x build-linux.sh
|
||||
./build-linux.sh deb
|
||||
mv "dist/gotify-tray_$(cat version.txt)_amd64.deb" "gotify-tray_$(cat version.txt)_amd64_${{ matrix.tag }}.deb"
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
path: "gotify-tray_*_amd64_${{ matrix.tag }}.deb"
|
||||
|
||||
|
||||
build-macos:
|
||||
runs-on: macos-12
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v4
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.10.8'
|
||||
python-version: '3.13'
|
||||
- name: Upgrade pip and enable wheel support
|
||||
run: python -m pip install --upgrade pip setuptools wheel
|
||||
- name: Build
|
||||
@@ -81,7 +51,7 @@ jobs:
|
||||
brew install create-dmg
|
||||
create-dmg --volname "Gotify Tray" --app-drop-link 0 0 --no-internet-enable "gotify-tray.dmg" "./dist/Gotify Tray.app"
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: gotify-tray.dmg
|
||||
path: gotify-tray.dmg
|
||||
@@ -89,11 +59,11 @@ jobs:
|
||||
build-pip:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v4
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.10.8'
|
||||
python-version: '3.13'
|
||||
- name: Upgrade pip and enable wheel support
|
||||
run: python -m pip install --upgrade pip setuptools wheel
|
||||
- name: install requirements
|
||||
@@ -103,6 +73,6 @@ jobs:
|
||||
- name: create pip package
|
||||
run: python -m build
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
path: dist/gotify_tray-*.whl
|
||||
|
||||
62
.github/workflows/release.yml
vendored
62
.github/workflows/release.yml
vendored
@@ -10,11 +10,11 @@ jobs:
|
||||
build-win64:
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v4
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.10.8'
|
||||
python-version: '3.13'
|
||||
- name: Upgrade pip and enable wheel support
|
||||
run: python -m pip install --upgrade pip setuptools wheel
|
||||
- name: Install Requirements
|
||||
@@ -28,49 +28,19 @@ jobs:
|
||||
mv inno-output\gotify-tray-installer.exe gotify-tray-installer-win.exe
|
||||
shell: cmd
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: gotify-tray-installer-win.exe
|
||||
path: gotify-tray-installer-win.exe
|
||||
|
||||
build-debian:
|
||||
strategy:
|
||||
matrix:
|
||||
tag: [bullseye, bookworm]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.10.8'
|
||||
- name: Upgrade pip and enable wheel support
|
||||
run: python -m pip install --upgrade pip setuptools wheel
|
||||
- uses: ruby/setup-ruby@v1
|
||||
with:
|
||||
ruby-version: '3.0'
|
||||
- name: Build
|
||||
run: |
|
||||
pip install -r requirements.txt
|
||||
pip install pyinstaller
|
||||
gem install fpm
|
||||
chmod +x build-linux.sh
|
||||
./build-linux.sh deb
|
||||
mv "dist/gotify-tray_$(cat version.txt)_amd64.deb" "gotify-tray_$(cat version.txt)_amd64_${{ matrix.tag }}.deb"
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: gotify-tray_${{github.ref_name}}_amd64_${{ matrix.tag }}.deb
|
||||
path: gotify-tray_${{github.ref_name}}_amd64_${{ matrix.tag }}.deb
|
||||
|
||||
build-macos:
|
||||
runs-on: macos-12
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v4
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.10.8'
|
||||
python-version: '3.13'
|
||||
- name: Upgrade pip and enable wheel support
|
||||
run: python -m pip install --upgrade pip setuptools wheel
|
||||
- name: Build
|
||||
@@ -79,7 +49,7 @@ jobs:
|
||||
brew install create-dmg
|
||||
create-dmg --volname "Gotify Tray" --app-drop-link 0 0 --no-internet-enable "gotify-tray.dmg" "./dist/Gotify Tray.app"
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: gotify-tray.dmg
|
||||
path: gotify-tray.dmg
|
||||
@@ -92,11 +62,11 @@ jobs:
|
||||
permissions:
|
||||
id-token: write
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v4
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.10.8'
|
||||
python-version: '3.13'
|
||||
- name: Upgrade pip and enable wheel support
|
||||
run: python -m pip install --upgrade pip setuptools wheel
|
||||
- name: install requirements
|
||||
@@ -108,17 +78,17 @@ jobs:
|
||||
- name: upload to pypi
|
||||
uses: pypa/gh-action-pypi-publish@release/v1
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: gotify_tray-${{github.ref_name}}-py3-none-any.whl
|
||||
path: dist/gotify_tray-${{github.ref_name}}-py3-none-any.whl
|
||||
|
||||
release:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [build-win64, build-debian, build-macos, pypi]
|
||||
needs: [build-win64, build-macos, pypi]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/download-artifact@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/download-artifact@v4
|
||||
- name: Release
|
||||
uses: marvinpinto/action-automatic-releases@latest
|
||||
with:
|
||||
@@ -127,6 +97,4 @@ jobs:
|
||||
files: |
|
||||
gotify-tray-installer-win.exe
|
||||
gotify-tray.dmg
|
||||
gotify-tray_${{github.ref_name}}_amd64_bullseye.deb
|
||||
gotify-tray_${{github.ref_name}}_amd64_bookworm.deb
|
||||
gotify_tray-${{github.ref_name}}-py3-none-any.whl
|
||||
|
||||
19
AGENTS.md
Normal file
19
AGENTS.md
Normal file
@@ -0,0 +1,19 @@
|
||||
# Agent Guidelines
|
||||
|
||||
## Type Checking
|
||||
Run `pyright .` in the project root to perform static type checking with Pyright. Address any critical errors before committing changes.
|
||||
|
||||
Note: Pyright may report many Qt-related type issues that are false positives due to PyQt6 stubs limitations. Focus on logical errors rather than Qt API mismatches.
|
||||
|
||||
To ignore PyQt6-related errors, create a `pyrightconfig.json` in the project root with:
|
||||
```json
|
||||
{
|
||||
"reportOptionalMemberAccess": false,
|
||||
"reportAttributeAccessIssue": false,
|
||||
"reportIncompatibleMethodOverride": false,
|
||||
"reportArgumentType": false,
|
||||
"reportAssignmentType": false,
|
||||
"reportReturnType": false
|
||||
}
|
||||
```
|
||||
This suppresses common PyQt6 false positives while still catching real issues.
|
||||
0
build-linux.sh
Normal file → Executable file
0
build-linux.sh
Normal file → Executable file
@@ -3,4 +3,4 @@ __description__ = (
|
||||
"A tray notification application for receiving messages from a Gotify server."
|
||||
)
|
||||
__url__ = "https://github.com/seird/gotify-tray"
|
||||
__version__ = "0.5.2"
|
||||
__version__ = "0.5.3"
|
||||
|
||||
@@ -16,6 +16,8 @@ DEFAULT_SETTINGS = {
|
||||
"tray/notifications/duration_ms": 5000,
|
||||
"tray/notifications/icon/show": True,
|
||||
"tray/notifications/click": True,
|
||||
"tray/notifications/priority10_persistent": True,
|
||||
"tray/notifications/sound_only_priority10": True,
|
||||
"tray/icon/unread": False,
|
||||
"watchdog/enabled": True,
|
||||
"watchdog/interval/s": 60,
|
||||
|
||||
@@ -8,6 +8,7 @@ import tempfile
|
||||
from gotify_tray import gotify
|
||||
from gotify_tray.__version__ import __title__
|
||||
from gotify_tray.database import Downloader, Settings
|
||||
from .widgets.PersistentNotification import PersistentNotification
|
||||
from gotify_tray.tasks import (
|
||||
ClearCacheTask,
|
||||
DeleteApplicationMessagesTask,
|
||||
@@ -22,6 +23,7 @@ from gotify_tray.tasks import (
|
||||
from gotify_tray.gui.themes import set_theme
|
||||
from gotify_tray.utils import get_icon, verify_server
|
||||
from PyQt6 import QtCore, QtGui, QtWidgets
|
||||
from PyQt6.QtMultimedia import QSoundEffect
|
||||
|
||||
from ..__version__ import __title__
|
||||
from .models import (
|
||||
@@ -47,7 +49,9 @@ def init_logger(logger: logging.Logger):
|
||||
else:
|
||||
logging.disable()
|
||||
|
||||
logdir = QtCore.QStandardPaths.standardLocations(QtCore.QStandardPaths.StandardLocation.AppDataLocation)[0]
|
||||
logdir = QtCore.QStandardPaths.standardLocations(
|
||||
QtCore.QStandardPaths.StandardLocation.AppDataLocation
|
||||
)[0]
|
||||
if not os.path.exists(logdir):
|
||||
os.mkdir(logdir)
|
||||
logging.basicConfig(
|
||||
@@ -57,6 +61,28 @@ def init_logger(logger: logging.Logger):
|
||||
|
||||
|
||||
class MainApplication(QtWidgets.QApplication):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
# Initialize notification sound effect
|
||||
self.notification_sound = QSoundEffect()
|
||||
sound_path = os.path.join(
|
||||
os.path.dirname(__file__), "images", "notification.wav"
|
||||
)
|
||||
self.notification_sound.setSource(QtCore.QUrl.fromLocalFile(sound_path))
|
||||
self.notification_sound.setVolume(0.5) # Set volume (0.0 to 1.0)
|
||||
self.persistent_notifications = []
|
||||
self.next_y_offset = 0
|
||||
|
||||
def close_all_persistent_notifications(self):
|
||||
for notification in self.persistent_notifications:
|
||||
notification.close()
|
||||
self.persistent_notifications.clear()
|
||||
self.next_y_offset = 0
|
||||
|
||||
def _on_tray_activated(self, reason):
|
||||
if reason == QtWidgets.QSystemTrayIcon.ActivationReason.Trigger:
|
||||
self.close_all_persistent_notifications()
|
||||
|
||||
def init_ui(self):
|
||||
self.gotify_client = gotify.GotifyClient(
|
||||
settings.value("Server/url", type=str),
|
||||
@@ -69,7 +95,9 @@ class MainApplication(QtWidgets.QApplication):
|
||||
self.application_model = ApplicationModel()
|
||||
self.application_proxy_model = ApplicationProxyModel(self.application_model)
|
||||
|
||||
self.main_window = MainWindow(self.application_model, self.application_proxy_model, self.messages_model)
|
||||
self.main_window = MainWindow(
|
||||
self.application_model, self.application_proxy_model, self.messages_model
|
||||
)
|
||||
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)
|
||||
|
||||
@@ -77,6 +105,7 @@ class MainApplication(QtWidgets.QApplication):
|
||||
|
||||
self.tray = Tray()
|
||||
self.tray.show()
|
||||
self.tray.activated.connect(self._on_tray_activated)
|
||||
|
||||
self.first_connect = True
|
||||
|
||||
@@ -100,17 +129,30 @@ class MainApplication(QtWidgets.QApplication):
|
||||
self.application_model.setItem(0, 0, ApplicationAllMessagesItem())
|
||||
|
||||
self.get_applications_task = GetApplicationsTask(self.gotify_client)
|
||||
self.get_applications_task.success.connect(self.get_applications_success_callback)
|
||||
self.get_applications_task.started.connect(self.main_window.disable_applications)
|
||||
self.get_applications_task.finished.connect(self.main_window.enable_applications)
|
||||
self.get_applications_task.success.connect(
|
||||
self.get_applications_success_callback
|
||||
)
|
||||
self.get_applications_task.started.connect(
|
||||
self.main_window.disable_applications
|
||||
)
|
||||
self.get_applications_task.finished.connect(
|
||||
self.main_window.enable_applications
|
||||
)
|
||||
self.get_applications_task.start()
|
||||
|
||||
def get_applications_success_callback(
|
||||
self, applications: list[gotify.GotifyApplicationModel],
|
||||
self,
|
||||
applications: list[gotify.GotifyApplicationModel],
|
||||
):
|
||||
for i, application in enumerate(applications):
|
||||
icon = QtGui.QIcon(self.downloader.get_filename(f"{self.gotify_client.url}/{application.image}"))
|
||||
self.application_model.setItem(i + 1, 0, ApplicationModelItem(application, icon))
|
||||
icon = QtGui.QIcon(
|
||||
self.downloader.get_filename(
|
||||
f"{self.gotify_client.url}/{application.image}"
|
||||
)
|
||||
)
|
||||
self.application_model.setItem(
|
||||
i + 1, 0, ApplicationModelItem(application, icon)
|
||||
)
|
||||
|
||||
def update_last_id(self, i: int):
|
||||
if i > settings.value("message/last", type=int):
|
||||
@@ -174,15 +216,24 @@ class MainApplication(QtWidgets.QApplication):
|
||||
for task in aborted_tasks:
|
||||
task.wait()
|
||||
|
||||
def application_selection_changed_callback(self, item: ApplicationModelItem | ApplicationAllMessagesItem):
|
||||
def application_selection_changed_callback(
|
||||
self, item: ApplicationModelItem | ApplicationAllMessagesItem
|
||||
):
|
||||
self.main_window.disable_buttons()
|
||||
self.abort_get_messages_task()
|
||||
self.messages_model.clear()
|
||||
|
||||
if isinstance(item, ApplicationModelItem):
|
||||
self.get_application_messages_task = GetApplicationMessagesTask(item.data(ApplicationItemDataRole.ApplicationRole).id, self.gotify_client)
|
||||
self.get_application_messages_task.message.connect(self.messages_model.append_message)
|
||||
self.get_application_messages_task.finished.connect(self.main_window.enable_buttons)
|
||||
self.get_application_messages_task = GetApplicationMessagesTask(
|
||||
item.data(ApplicationItemDataRole.ApplicationRole).id,
|
||||
self.gotify_client,
|
||||
)
|
||||
self.get_application_messages_task.message.connect(
|
||||
self.messages_model.append_message
|
||||
)
|
||||
self.get_application_messages_task.finished.connect(
|
||||
self.main_window.enable_buttons
|
||||
)
|
||||
self.get_application_messages_task.start()
|
||||
|
||||
elif isinstance(item, ApplicationAllMessagesItem):
|
||||
@@ -191,10 +242,14 @@ class MainApplication(QtWidgets.QApplication):
|
||||
self.get_messages_task.finished.connect(self.main_window.enable_buttons)
|
||||
self.get_messages_task.start()
|
||||
|
||||
def add_message_to_model(self, message: gotify.GotifyMessageModel, process: bool = True):
|
||||
def add_message_to_model(
|
||||
self, message: gotify.GotifyMessageModel, process: bool = True
|
||||
):
|
||||
if self.application_model.itemFromId(message.appid):
|
||||
application_index = self.main_window.currentApplicationIndex()
|
||||
if selected_application_item := self.application_model.itemFromIndex(self.application_proxy_model.mapToSource(application_index)):
|
||||
if selected_application_item := self.application_model.itemFromIndex(
|
||||
self.application_proxy_model.mapToSource(application_index)
|
||||
):
|
||||
|
||||
def insert_message_helper():
|
||||
if isinstance(selected_application_item, ApplicationModelItem):
|
||||
@@ -202,10 +257,14 @@ class MainApplication(QtWidgets.QApplication):
|
||||
# -> Only insert the message if the appid matches the selected appid
|
||||
if (
|
||||
message.appid
|
||||
== selected_application_item.data(ApplicationItemDataRole.ApplicationRole).id
|
||||
== selected_application_item.data(
|
||||
ApplicationItemDataRole.ApplicationRole
|
||||
).id
|
||||
):
|
||||
self.messages_model.insert_message(0, message)
|
||||
elif isinstance(selected_application_item, ApplicationAllMessagesItem):
|
||||
elif isinstance(
|
||||
selected_application_item, ApplicationAllMessagesItem
|
||||
):
|
||||
# "All messages' is selected
|
||||
self.messages_model.insert_message(0, message)
|
||||
|
||||
@@ -216,10 +275,14 @@ class MainApplication(QtWidgets.QApplication):
|
||||
else:
|
||||
insert_message_helper()
|
||||
else:
|
||||
logger.error(f"App id {message.appid} could not be found. Refreshing applications.")
|
||||
logger.error(
|
||||
f"App id {message.appid} could not be found. Refreshing applications."
|
||||
)
|
||||
self.refresh_applications()
|
||||
|
||||
def new_message_callback(self, message: gotify.GotifyMessageModel, process: bool = True):
|
||||
def new_message_callback(
|
||||
self, message: gotify.GotifyMessageModel, process: bool = True
|
||||
):
|
||||
self.add_message_to_model(message, process=process)
|
||||
|
||||
# Don't show a notification if it's low priority or the window is active
|
||||
@@ -237,21 +300,52 @@ class MainApplication(QtWidgets.QApplication):
|
||||
self.tray.set_icon_unread()
|
||||
|
||||
# Get the application icon
|
||||
if (
|
||||
settings.value("tray/notifications/icon/show", type=bool)
|
||||
and (application_item := self.application_model.itemFromId(message.appid))
|
||||
if settings.value("tray/notifications/icon/show", type=bool) and (
|
||||
application_item := self.application_model.itemFromId(message.appid)
|
||||
):
|
||||
icon = application_item.icon()
|
||||
else:
|
||||
icon = QtWidgets.QSystemTrayIcon.MessageIcon.Information
|
||||
|
||||
# Show notification
|
||||
if message.priority == 10 and settings.value(
|
||||
"tray/notifications/priority10_persistent", type=bool
|
||||
):
|
||||
# Create persistent notification
|
||||
notification = PersistentNotification(
|
||||
message.title or "",
|
||||
message.message or "",
|
||||
icon,
|
||||
y_offset=self.next_y_offset,
|
||||
flash=True,
|
||||
)
|
||||
notification.close_all_requested.connect(
|
||||
self.close_all_persistent_notifications
|
||||
)
|
||||
self.persistent_notifications.append(notification)
|
||||
notification.show()
|
||||
self.next_y_offset += notification.height() + 10
|
||||
else:
|
||||
# Use system tray notification
|
||||
msecs = settings.value("tray/notifications/duration_ms", type=int)
|
||||
self.tray.showMessage(
|
||||
message.title,
|
||||
message.message,
|
||||
icon,
|
||||
msecs=settings.value("tray/notifications/duration_ms", type=int),
|
||||
msecs=msecs,
|
||||
)
|
||||
|
||||
# Play notification sound
|
||||
if (
|
||||
not settings.value("tray/notifications/sound_only_priority10", type=bool)
|
||||
or message.priority == 10
|
||||
):
|
||||
if self.notification_sound.isLoaded():
|
||||
self.notification_sound.play()
|
||||
else:
|
||||
# Try to play anyway (QSoundEffect will queue if not loaded yet)
|
||||
self.notification_sound.play()
|
||||
|
||||
def delete_message_callback(self, message_item: MessagesModelItem):
|
||||
self.delete_message_task = DeleteMessageTask(
|
||||
message_item.data(MessageItemDataRole.MessageRole).id, self.gotify_client
|
||||
@@ -299,7 +393,11 @@ class MainApplication(QtWidgets.QApplication):
|
||||
|
||||
# Update the message widget icons
|
||||
for r in range(self.messages_model.rowCount()):
|
||||
message_widget: MessageWidget = self.main_window.listView_messages.indexWidget(self.messages_model.index(r, 0))
|
||||
message_widget: MessageWidget = (
|
||||
self.main_window.listView_messages.indexWidget(
|
||||
self.messages_model.index(r, 0)
|
||||
)
|
||||
)
|
||||
message_widget.set_icons()
|
||||
|
||||
def settings_callback(self):
|
||||
@@ -341,15 +439,21 @@ class MainApplication(QtWidgets.QApplication):
|
||||
|
||||
self.main_window.refresh.connect(self.refresh_applications)
|
||||
self.main_window.delete_all.connect(self.delete_all_messages_callback)
|
||||
self.main_window.application_selection_changed.connect(self.application_selection_changed_callback)
|
||||
self.main_window.application_selection_changed.connect(
|
||||
self.application_selection_changed_callback
|
||||
)
|
||||
self.main_window.delete_message.connect(self.delete_message_callback)
|
||||
self.main_window.image_popup.connect(self.image_popup_callback)
|
||||
self.main_window.hidden.connect(self.main_window_hidden_callback)
|
||||
self.main_window.activated.connect(self.tray.revert_icon)
|
||||
|
||||
self.styleHints().colorSchemeChanged.connect(self.theme_change_requested_callback)
|
||||
self.styleHints().colorSchemeChanged.connect(
|
||||
self.theme_change_requested_callback
|
||||
)
|
||||
|
||||
self.messages_model.rowsInserted.connect(self.main_window.display_message_widgets)
|
||||
self.messages_model.rowsInserted.connect(
|
||||
self.main_window.display_message_widgets
|
||||
)
|
||||
|
||||
self.gotify_client.opened.connect(self.listener_opened_callback)
|
||||
self.gotify_client.closed.connect(self.listener_closed_callback)
|
||||
@@ -366,7 +470,9 @@ class MainApplication(QtWidgets.QApplication):
|
||||
|
||||
def acquire_lock(self) -> bool:
|
||||
temp_dir = tempfile.gettempdir()
|
||||
lock_filename = os.path.join(temp_dir, __title__ + "-" + getpass.getuser() + ".lock")
|
||||
lock_filename = os.path.join(
|
||||
temp_dir, __title__ + "-" + getpass.getuser() + ".lock"
|
||||
)
|
||||
self.lock_file = QtCore.QLockFile(lock_filename)
|
||||
self.lock_file.setStaleLockTime(0)
|
||||
return self.lock_file.tryLock()
|
||||
|
||||
@@ -17,7 +17,11 @@ class Ui_Dialog(object):
|
||||
self.gridLayout.setObjectName("gridLayout")
|
||||
self.buttonBox = QtWidgets.QDialogButtonBox(parent=Dialog)
|
||||
self.buttonBox.setOrientation(QtCore.Qt.Orientation.Horizontal)
|
||||
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.StandardButton.Apply|QtWidgets.QDialogButtonBox.StandardButton.Cancel|QtWidgets.QDialogButtonBox.StandardButton.Ok)
|
||||
self.buttonBox.setStandardButtons(
|
||||
QtWidgets.QDialogButtonBox.StandardButton.Apply
|
||||
| QtWidgets.QDialogButtonBox.StandardButton.Cancel
|
||||
| QtWidgets.QDialogButtonBox.StandardButton.Ok
|
||||
)
|
||||
self.buttonBox.setObjectName("buttonBox")
|
||||
self.gridLayout.addWidget(self.buttonBox, 1, 4, 1, 1)
|
||||
self.tabWidget = QtWidgets.QTabWidget(parent=Dialog)
|
||||
@@ -30,7 +34,9 @@ class Ui_Dialog(object):
|
||||
self.groupBox_notifications.setObjectName("groupBox_notifications")
|
||||
self.gridLayout_4 = QtWidgets.QGridLayout(self.groupBox_notifications)
|
||||
self.gridLayout_4.setObjectName("gridLayout_4")
|
||||
self.label_notification_duration = QtWidgets.QLabel(parent=self.groupBox_notifications)
|
||||
self.label_notification_duration = QtWidgets.QLabel(
|
||||
parent=self.groupBox_notifications
|
||||
)
|
||||
self.label_notification_duration.setObjectName("label_notification_duration")
|
||||
self.gridLayout_4.addWidget(self.label_notification_duration, 1, 0, 1, 1)
|
||||
self.spin_duration = QtWidgets.QSpinBox(parent=self.groupBox_notifications)
|
||||
@@ -39,29 +45,54 @@ class Ui_Dialog(object):
|
||||
self.spin_duration.setSingleStep(100)
|
||||
self.spin_duration.setObjectName("spin_duration")
|
||||
self.gridLayout_4.addWidget(self.spin_duration, 1, 1, 1, 1)
|
||||
self.cb_notification_click = QtWidgets.QCheckBox(parent=self.groupBox_notifications)
|
||||
self.cb_notification_click = QtWidgets.QCheckBox(
|
||||
parent=self.groupBox_notifications
|
||||
)
|
||||
self.cb_notification_click.setObjectName("cb_notification_click")
|
||||
self.gridLayout_4.addWidget(self.cb_notification_click, 3, 0, 1, 3)
|
||||
self.label_notification_duration_ms = QtWidgets.QLabel(parent=self.groupBox_notifications)
|
||||
self.label_notification_duration_ms.setObjectName("label_notification_duration_ms")
|
||||
self.label_notification_duration_ms = QtWidgets.QLabel(
|
||||
parent=self.groupBox_notifications
|
||||
)
|
||||
self.label_notification_duration_ms.setObjectName(
|
||||
"label_notification_duration_ms"
|
||||
)
|
||||
self.gridLayout_4.addWidget(self.label_notification_duration_ms, 1, 2, 1, 1)
|
||||
spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum)
|
||||
spacerItem = QtWidgets.QSpacerItem(
|
||||
40,
|
||||
20,
|
||||
QtWidgets.QSizePolicy.Policy.Expanding,
|
||||
QtWidgets.QSizePolicy.Policy.Minimum,
|
||||
)
|
||||
self.gridLayout_4.addItem(spacerItem, 0, 2, 1, 1)
|
||||
self.cb_notify = QtWidgets.QCheckBox(parent=self.groupBox_notifications)
|
||||
self.cb_notify.setObjectName("cb_notify")
|
||||
self.gridLayout_4.addWidget(self.cb_notify, 2, 0, 1, 3)
|
||||
self.spin_priority = QtWidgets.QSpinBox(parent=self.groupBox_notifications)
|
||||
self.spin_priority.setMinimum(1)
|
||||
self.spin_priority.setMinimum(0)
|
||||
self.spin_priority.setMaximum(10)
|
||||
self.spin_priority.setProperty("value", 5)
|
||||
self.spin_priority.setObjectName("spin_priority")
|
||||
self.gridLayout_4.addWidget(self.spin_priority, 0, 1, 1, 1)
|
||||
self.label_notification_priority = QtWidgets.QLabel(parent=self.groupBox_notifications)
|
||||
self.label_notification_priority = QtWidgets.QLabel(
|
||||
parent=self.groupBox_notifications
|
||||
)
|
||||
self.label_notification_priority.setObjectName("label_notification_priority")
|
||||
self.gridLayout_4.addWidget(self.label_notification_priority, 0, 0, 1, 1)
|
||||
self.cb_tray_icon_unread = QtWidgets.QCheckBox(parent=self.groupBox_notifications)
|
||||
self.cb_tray_icon_unread = QtWidgets.QCheckBox(
|
||||
parent=self.groupBox_notifications
|
||||
)
|
||||
self.cb_tray_icon_unread.setObjectName("cb_tray_icon_unread")
|
||||
self.gridLayout_4.addWidget(self.cb_tray_icon_unread, 4, 0, 1, 3)
|
||||
self.cb_priority10_persistent = QtWidgets.QCheckBox(
|
||||
parent=self.groupBox_notifications
|
||||
)
|
||||
self.cb_priority10_persistent.setObjectName("cb_priority10_persistent")
|
||||
self.gridLayout_4.addWidget(self.cb_priority10_persistent, 5, 0, 1, 3)
|
||||
self.cb_sound_only_priority10 = QtWidgets.QCheckBox(
|
||||
parent=self.groupBox_notifications
|
||||
)
|
||||
self.cb_sound_only_priority10.setObjectName("cb_sound_only_priority10")
|
||||
self.gridLayout_4.addWidget(self.cb_sound_only_priority10, 6, 0, 1, 3)
|
||||
self.verticalLayout_4.addWidget(self.groupBox_notifications)
|
||||
self.groupBox_2 = QtWidgets.QGroupBox(parent=self.tab_general)
|
||||
self.groupBox_2.setObjectName("groupBox_2")
|
||||
@@ -84,13 +115,25 @@ class Ui_Dialog(object):
|
||||
self.groupBox_server_info.setObjectName("groupBox_server_info")
|
||||
self.gridLayout_3 = QtWidgets.QGridLayout(self.groupBox_server_info)
|
||||
self.gridLayout_3.setObjectName("gridLayout_3")
|
||||
self.pb_change_server_info = QtWidgets.QPushButton(parent=self.groupBox_server_info)
|
||||
self.pb_change_server_info = QtWidgets.QPushButton(
|
||||
parent=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)
|
||||
spacerItem1 = QtWidgets.QSpacerItem(
|
||||
40,
|
||||
20,
|
||||
QtWidgets.QSizePolicy.Policy.Expanding,
|
||||
QtWidgets.QSizePolicy.Policy.Minimum,
|
||||
)
|
||||
self.gridLayout_3.addItem(spacerItem1, 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)
|
||||
spacerItem2 = QtWidgets.QSpacerItem(
|
||||
20,
|
||||
40,
|
||||
QtWidgets.QSizePolicy.Policy.Minimum,
|
||||
QtWidgets.QSizePolicy.Policy.Expanding,
|
||||
)
|
||||
self.verticalLayout_4.addItem(spacerItem2)
|
||||
self.tabWidget.addTab(self.tab_general, "")
|
||||
self.tab_fonts = QtWidgets.QWidget()
|
||||
@@ -111,18 +154,29 @@ class Ui_Dialog(object):
|
||||
self.layout_fonts_message.setObjectName("layout_fonts_message")
|
||||
self.horizontalLayout = QtWidgets.QHBoxLayout()
|
||||
self.horizontalLayout.setObjectName("horizontalLayout")
|
||||
self.pb_font_message_title = QtWidgets.QPushButton(parent=self.groupBox_fonts_message)
|
||||
self.pb_font_message_title = QtWidgets.QPushButton(
|
||||
parent=self.groupBox_fonts_message
|
||||
)
|
||||
self.pb_font_message_title.setObjectName("pb_font_message_title")
|
||||
self.horizontalLayout.addWidget(self.pb_font_message_title)
|
||||
self.pb_font_message_date = QtWidgets.QPushButton(parent=self.groupBox_fonts_message)
|
||||
self.pb_font_message_date = QtWidgets.QPushButton(
|
||||
parent=self.groupBox_fonts_message
|
||||
)
|
||||
self.pb_font_message_date.setObjectName("pb_font_message_date")
|
||||
self.horizontalLayout.addWidget(self.pb_font_message_date)
|
||||
self.pb_font_message_content = QtWidgets.QPushButton(parent=self.groupBox_fonts_message)
|
||||
self.pb_font_message_content = QtWidgets.QPushButton(
|
||||
parent=self.groupBox_fonts_message
|
||||
)
|
||||
self.pb_font_message_content.setObjectName("pb_font_message_content")
|
||||
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)
|
||||
spacerItem3 = QtWidgets.QSpacerItem(
|
||||
20,
|
||||
40,
|
||||
QtWidgets.QSizePolicy.Policy.Minimum,
|
||||
QtWidgets.QSizePolicy.Policy.Expanding,
|
||||
)
|
||||
self.verticalLayout_5.addItem(spacerItem3)
|
||||
self.tabWidget.addTab(self.tab_fonts, "")
|
||||
self.tab_advanced = QtWidgets.QWidget()
|
||||
@@ -168,7 +222,12 @@ 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)
|
||||
spacerItem4 = QtWidgets.QSpacerItem(
|
||||
40,
|
||||
20,
|
||||
QtWidgets.QSizePolicy.Policy.Expanding,
|
||||
QtWidgets.QSizePolicy.Policy.Minimum,
|
||||
)
|
||||
self.horizontalLayout_4.addItem(spacerItem4)
|
||||
self.gridLayout_2.addLayout(self.horizontalLayout_4, 0, 0, 1, 1)
|
||||
self.verticalLayout.addWidget(self.groupbox_image_popup)
|
||||
@@ -190,7 +249,12 @@ class Ui_Dialog(object):
|
||||
self.label_watchdog_interval_s = QtWidgets.QLabel(parent=self.groupbox_watchdog)
|
||||
self.label_watchdog_interval_s.setObjectName("label_watchdog_interval_s")
|
||||
self.horizontalLayout_3.addWidget(self.label_watchdog_interval_s)
|
||||
spacerItem5 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum)
|
||||
spacerItem5 = QtWidgets.QSpacerItem(
|
||||
40,
|
||||
20,
|
||||
QtWidgets.QSizePolicy.Policy.Expanding,
|
||||
QtWidgets.QSizePolicy.Policy.Minimum,
|
||||
)
|
||||
self.horizontalLayout_3.addItem(spacerItem5)
|
||||
self.verticalLayout_3.addLayout(self.horizontalLayout_3)
|
||||
self.verticalLayout.addWidget(self.groupbox_watchdog)
|
||||
@@ -207,7 +271,12 @@ class Ui_Dialog(object):
|
||||
self.label_cache = QtWidgets.QLabel(parent=self.groupBox_cache)
|
||||
self.label_cache.setObjectName("label_cache")
|
||||
self.horizontalLayout_6.addWidget(self.label_cache)
|
||||
spacerItem6 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum)
|
||||
spacerItem6 = QtWidgets.QSpacerItem(
|
||||
40,
|
||||
20,
|
||||
QtWidgets.QSizePolicy.Policy.Expanding,
|
||||
QtWidgets.QSizePolicy.Policy.Minimum,
|
||||
)
|
||||
self.horizontalLayout_6.addItem(spacerItem6)
|
||||
self.verticalLayout.addWidget(self.groupBox_cache)
|
||||
self.groupBox_logging = QtWidgets.QGroupBox(parent=self.tab_advanced)
|
||||
@@ -217,7 +286,12 @@ class Ui_Dialog(object):
|
||||
self.combo_logging = QtWidgets.QComboBox(parent=self.groupBox_logging)
|
||||
self.combo_logging.setObjectName("combo_logging")
|
||||
self.gridLayout_6.addWidget(self.combo_logging, 0, 1, 1, 1)
|
||||
spacerItem7 = QtWidgets.QSpacerItem(190, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum)
|
||||
spacerItem7 = QtWidgets.QSpacerItem(
|
||||
190,
|
||||
20,
|
||||
QtWidgets.QSizePolicy.Policy.Expanding,
|
||||
QtWidgets.QSizePolicy.Policy.Minimum,
|
||||
)
|
||||
self.gridLayout_6.addItem(spacerItem7, 0, 3, 1, 1)
|
||||
self.pb_open_log = QtWidgets.QPushButton(parent=self.groupBox_logging)
|
||||
self.pb_open_log.setMaximumSize(QtCore.QSize(30, 16777215))
|
||||
@@ -227,7 +301,12 @@ 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)
|
||||
spacerItem8 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Policy.Minimum, QtWidgets.QSizePolicy.Policy.Expanding)
|
||||
spacerItem8 = QtWidgets.QSpacerItem(
|
||||
20,
|
||||
40,
|
||||
QtWidgets.QSizePolicy.Policy.Minimum,
|
||||
QtWidgets.QSizePolicy.Policy.Expanding,
|
||||
)
|
||||
self.verticalLayout.addItem(spacerItem8)
|
||||
self.tabWidget.addTab(self.tab_advanced, "")
|
||||
self.gridLayout.addWidget(self.tabWidget, 0, 0, 1, 5)
|
||||
@@ -258,7 +337,9 @@ class Ui_Dialog(object):
|
||||
Dialog.setTabOrder(self.spin_duration, self.cb_notify)
|
||||
Dialog.setTabOrder(self.cb_notify, self.cb_notification_click)
|
||||
Dialog.setTabOrder(self.cb_notification_click, self.cb_tray_icon_unread)
|
||||
Dialog.setTabOrder(self.cb_tray_icon_unread, self.cb_priority_colors)
|
||||
Dialog.setTabOrder(self.cb_tray_icon_unread, self.cb_priority10_persistent)
|
||||
Dialog.setTabOrder(self.cb_priority10_persistent, self.cb_sound_only_priority10)
|
||||
Dialog.setTabOrder(self.cb_sound_only_priority10, self.cb_priority_colors)
|
||||
Dialog.setTabOrder(self.cb_priority_colors, self.cb_image_urls)
|
||||
Dialog.setTabOrder(self.cb_image_urls, self.cb_locale)
|
||||
Dialog.setTabOrder(self.cb_locale, self.cb_sort_applications)
|
||||
@@ -284,40 +365,88 @@ class Ui_Dialog(object):
|
||||
_translate = QtCore.QCoreApplication.translate
|
||||
Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
|
||||
self.groupBox_notifications.setTitle(_translate("Dialog", "Notifications"))
|
||||
self.label_notification_duration.setText(_translate("Dialog", "Notification duration:"))
|
||||
self.cb_notification_click.setText(_translate("Dialog", "Clicking the notification pop-up opens the main window"))
|
||||
self.label_notification_duration.setText(
|
||||
_translate("Dialog", "Notification duration:")
|
||||
)
|
||||
self.cb_notification_click.setText(
|
||||
_translate(
|
||||
"Dialog", "Clicking the notification pop-up opens the main window"
|
||||
)
|
||||
)
|
||||
self.label_notification_duration_ms.setText(_translate("Dialog", "ms"))
|
||||
self.cb_notify.setText(_translate("Dialog", "Show a notification for missed messages after reconnecting"))
|
||||
self.label_notification_priority.setText(_translate("Dialog", "Minimum priority to show notifications:"))
|
||||
self.cb_tray_icon_unread.setText(_translate("Dialog", "Change the tray icon color when there are unread notifications"))
|
||||
self.cb_notify.setText(
|
||||
_translate(
|
||||
"Dialog", "Show a notification for missed messages after reconnecting"
|
||||
)
|
||||
)
|
||||
self.label_notification_priority.setText(
|
||||
_translate("Dialog", "Minimum priority to show notifications:")
|
||||
)
|
||||
self.cb_tray_icon_unread.setText(
|
||||
_translate(
|
||||
"Dialog",
|
||||
"Change the tray icon color when there are unread notifications",
|
||||
)
|
||||
)
|
||||
self.cb_priority10_persistent.setText(
|
||||
_translate(
|
||||
"Dialog",
|
||||
"Make priority 10 notifications persistent (stay until clicked)",
|
||||
)
|
||||
)
|
||||
self.cb_sound_only_priority10.setText(
|
||||
_translate(
|
||||
"Dialog",
|
||||
"Play notification sound only for priority 10 messages",
|
||||
)
|
||||
)
|
||||
self.groupBox_2.setTitle(_translate("Dialog", "Interface"))
|
||||
self.cb_priority_colors.setToolTip(_translate("Dialog", "4..7 -> medium\n"
|
||||
"8..10 -> high"))
|
||||
self.cb_priority_colors.setText(_translate("Dialog", "Show message priority colors"))
|
||||
self.cb_priority_colors.setToolTip(
|
||||
_translate("Dialog", "4..7 -> medium\n8..10 -> high")
|
||||
)
|
||||
self.cb_priority_colors.setText(
|
||||
_translate("Dialog", "Show message priority colors")
|
||||
)
|
||||
self.cb_image_urls.setText(_translate("Dialog", "Show image urls as images"))
|
||||
self.cb_locale.setText(_translate("Dialog", "Display date in the system locale format"))
|
||||
self.cb_sort_applications.setText(_translate("Dialog", "Sort the application list alphabetically (requires restart)"))
|
||||
self.groupBox_server_info.setTitle(_translate("Dialog", "Server info"))
|
||||
self.cb_locale.setText(
|
||||
_translate("Dialog", "Display date in the system locale format")
|
||||
)
|
||||
self.cb_sort_applications.setText(
|
||||
_translate(
|
||||
"Dialog", "Sort the application list alphabetically (requires restart)"
|
||||
)
|
||||
)
|
||||
self.groupBox_server_info.setTitle(
|
||||
_translate("Dialog", "Server info - kadu customized")
|
||||
)
|
||||
self.pb_change_server_info.setText(_translate("Dialog", "Change server info"))
|
||||
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_general), _translate("Dialog", "General"))
|
||||
self.tabWidget.setTabText(
|
||||
self.tabWidget.indexOf(self.tab_general), _translate("Dialog", "General")
|
||||
)
|
||||
self.pb_reset_fonts.setText(_translate("Dialog", "Reset all fonts"))
|
||||
self.groupBox_fonts_message.setTitle(_translate("Dialog", "Message"))
|
||||
self.pb_font_message_title.setText(_translate("Dialog", "Title"))
|
||||
self.pb_font_message_date.setText(_translate("Dialog", "Date"))
|
||||
self.pb_font_message_content.setText(_translate("Dialog", "Message"))
|
||||
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_fonts), _translate("Dialog", "Fonts"))
|
||||
self.tabWidget.setTabText(
|
||||
self.tabWidget.indexOf(self.tab_fonts), _translate("Dialog", "Fonts")
|
||||
)
|
||||
self.groupBox.setTitle(_translate("Dialog", "Settings"))
|
||||
self.pb_reset.setText(_translate("Dialog", "Reset"))
|
||||
self.pb_import.setText(_translate("Dialog", "Import"))
|
||||
self.pb_export.setText(_translate("Dialog", "Export"))
|
||||
self.groupbox_image_popup.setTitle(_translate("Dialog", "Image pop-up for URLs"))
|
||||
self.groupbox_image_popup.setTitle(
|
||||
_translate("Dialog", "Image pop-up for URLs")
|
||||
)
|
||||
self.label.setToolTip(_translate("Dialog", "Maximum pop-up width"))
|
||||
self.label.setText(_translate("Dialog", "Width"))
|
||||
self.spin_popup_w.setToolTip(_translate("Dialog", "Maximum pop-up width"))
|
||||
self.label_2.setToolTip(_translate("Dialog", "Maximum pop-up height"))
|
||||
self.label_2.setText(_translate("Dialog", "Height"))
|
||||
self.spin_popup_h.setToolTip(_translate("Dialog", "Maximum pop-up height"))
|
||||
self.groupbox_watchdog.setTitle(_translate("Dialog", "Server watchdog thread (requires restart)"))
|
||||
self.groupbox_watchdog.setTitle(
|
||||
_translate("Dialog", "Server watchdog thread (requires restart)")
|
||||
)
|
||||
self.label_watchdog_interval.setText(_translate("Dialog", "Interval:"))
|
||||
self.label_watchdog_interval_s.setText(_translate("Dialog", "s"))
|
||||
self.groupBox_cache.setTitle(_translate("Dialog", "Cache"))
|
||||
@@ -328,11 +457,14 @@ class Ui_Dialog(object):
|
||||
self.pb_open_log.setToolTip(_translate("Dialog", "Open logfile"))
|
||||
self.pb_open_log.setText(_translate("Dialog", "..."))
|
||||
self.label_logging.setText(_translate("Dialog", "Level"))
|
||||
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_advanced), _translate("Dialog", "Advanced"))
|
||||
self.tabWidget.setTabText(
|
||||
self.tabWidget.indexOf(self.tab_advanced), _translate("Dialog", "Advanced")
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
|
||||
app = QtWidgets.QApplication(sys.argv)
|
||||
Dialog = QtWidgets.QDialog()
|
||||
ui = Ui_Dialog()
|
||||
|
||||
@@ -97,7 +97,7 @@
|
||||
<item row="0" column="1">
|
||||
<widget class="QSpinBox" name="spin_priority">
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>10</number>
|
||||
|
||||
BIN
gotify_tray/gui/images/notification.wav
Normal file
BIN
gotify_tray/gui/images/notification.wav
Normal file
Binary file not shown.
@@ -69,6 +69,10 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
|
||||
|
||||
self.link_callbacks()
|
||||
|
||||
# set refresh shortcut (usually ctrl-r)
|
||||
# unfortunately this cannot be done with designer
|
||||
self.pb_refresh.setShortcut(QtGui.QKeySequence(QtGui.QKeySequence.StandardKey.Refresh))
|
||||
|
||||
def set_icons(self):
|
||||
# Set button icons
|
||||
self.pb_refresh.setIcon(QtGui.QIcon(get_theme_file("refresh.svg")))
|
||||
|
||||
145
gotify_tray/gui/widgets/PersistentNotification.py
Normal file
145
gotify_tray/gui/widgets/PersistentNotification.py
Normal file
@@ -0,0 +1,145 @@
|
||||
import logging
|
||||
|
||||
from PyQt6 import QtCore, QtGui, QtWidgets
|
||||
|
||||
logger = logging.getLogger("gotify-tray")
|
||||
|
||||
|
||||
class PersistentNotification(QtWidgets.QWidget):
|
||||
close_all_requested = QtCore.pyqtSignal()
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
title: str,
|
||||
message: str,
|
||||
icon: QtGui.QIcon | QtWidgets.QSystemTrayIcon.MessageIcon,
|
||||
y_offset: int = 0,
|
||||
flash: bool = False,
|
||||
parent=None,
|
||||
):
|
||||
super().__init__(parent)
|
||||
self.y_offset = y_offset
|
||||
self.flash = flash
|
||||
self.flash_state = False
|
||||
self.original_stylesheet = ""
|
||||
self.setWindowFlags(
|
||||
QtCore.Qt.WindowType.Window
|
||||
| QtCore.Qt.WindowType.FramelessWindowHint
|
||||
| QtCore.Qt.WindowType.WindowStaysOnTopHint
|
||||
)
|
||||
self.setAttribute(QtCore.Qt.WidgetAttribute.WA_OpaquePaintEvent, True)
|
||||
self.setAttribute(QtCore.Qt.WidgetAttribute.WA_ShowWithoutActivating)
|
||||
|
||||
# Layout
|
||||
layout = QtWidgets.QHBoxLayout(self)
|
||||
layout.setContentsMargins(10, 10, 10, 10)
|
||||
layout.setSpacing(10)
|
||||
|
||||
# Icon
|
||||
self.icon_label = QtWidgets.QLabel()
|
||||
if isinstance(icon, QtGui.QIcon):
|
||||
self.icon_label.setPixmap(icon.pixmap(32, 32))
|
||||
else:
|
||||
# For MessageIcon
|
||||
if icon == QtWidgets.QSystemTrayIcon.MessageIcon.Information:
|
||||
standard_icon = QtWidgets.QStyle.StandardPixmap.SP_MessageBoxInformation
|
||||
elif icon == QtWidgets.QSystemTrayIcon.MessageIcon.Warning:
|
||||
standard_icon = QtWidgets.QStyle.StandardPixmap.SP_MessageBoxWarning
|
||||
elif icon == QtWidgets.QSystemTrayIcon.MessageIcon.Critical:
|
||||
standard_icon = QtWidgets.QStyle.StandardPixmap.SP_MessageBoxCritical
|
||||
else:
|
||||
standard_icon = QtWidgets.QStyle.StandardPixmap.SP_MessageBoxInformation
|
||||
system_icon = self.style().standardIcon(standard_icon)
|
||||
self.icon_label.setPixmap(system_icon.pixmap(32, 32))
|
||||
layout.addWidget(self.icon_label)
|
||||
|
||||
# Text
|
||||
text_layout = QtWidgets.QVBoxLayout()
|
||||
self.title_label = QtWidgets.QLabel(title)
|
||||
self.title_label.setStyleSheet("font-weight: bold;")
|
||||
text_layout.addWidget(self.title_label)
|
||||
|
||||
self.message_label = QtWidgets.QLabel(message)
|
||||
self.message_label.setWordWrap(True)
|
||||
text_layout.addWidget(self.message_label)
|
||||
|
||||
layout.addLayout(text_layout, 1)
|
||||
|
||||
# Close button
|
||||
self.close_button = QtWidgets.QPushButton("×")
|
||||
self.close_button.setFixedSize(20, 20)
|
||||
self.close_button.clicked.connect(self._on_close)
|
||||
layout.addWidget(self.close_button)
|
||||
|
||||
# Style
|
||||
self.setAutoFillBackground(True)
|
||||
self.setBackgroundRole(QtGui.QPalette.ColorRole.Window)
|
||||
palette = self.palette()
|
||||
palette.setColor(QtGui.QPalette.ColorRole.Window, QtGui.QColor("white"))
|
||||
palette.setColor(QtGui.QPalette.ColorRole.WindowText, QtGui.QColor("red"))
|
||||
self.setPalette(palette)
|
||||
|
||||
self.setStyleSheet("""
|
||||
PersistentNotification {
|
||||
border-radius: 10px;
|
||||
border: 1px solid rgba(100, 100, 100, 200);
|
||||
}
|
||||
QPushButton {
|
||||
background-color: transparent;
|
||||
color: white;
|
||||
border: none;
|
||||
font-size: 16px;
|
||||
}
|
||||
QPushButton:hover {
|
||||
background-color: rgba(100, 100, 100, 100);
|
||||
}
|
||||
""")
|
||||
|
||||
if self.flash:
|
||||
self.flash_timer = QtCore.QTimer(self)
|
||||
self.flash_timer.timeout.connect(self._toggle_flash)
|
||||
|
||||
# Size and position
|
||||
self.adjustSize()
|
||||
self.setFixedWidth(300)
|
||||
self._position()
|
||||
|
||||
# Timer for fade out if not clicked, but since persistent, maybe not needed
|
||||
# But to avoid staying forever if forgotten, perhaps auto-close after long time
|
||||
# But user wants until clicked, so no timer.
|
||||
|
||||
def _position(self):
|
||||
screen = QtWidgets.QApplication.primaryScreen().availableGeometry()
|
||||
# Stack from bottom right
|
||||
self.move(
|
||||
screen.width() - self.width() - 10,
|
||||
screen.height() - self.height() - 50 - self.y_offset,
|
||||
)
|
||||
|
||||
def _toggle_flash(self):
|
||||
self.flash_state = not self.flash_state
|
||||
palette = self.palette()
|
||||
if self.flash_state:
|
||||
palette.setColor(QtGui.QPalette.ColorRole.Window, QtGui.QColor("red"))
|
||||
palette.setColor(QtGui.QPalette.ColorRole.WindowText, QtGui.QColor("white"))
|
||||
else:
|
||||
palette.setColor(QtGui.QPalette.ColorRole.Window, QtGui.QColor("white"))
|
||||
palette.setColor(QtGui.QPalette.ColorRole.WindowText, QtGui.QColor("red"))
|
||||
self.setPalette(palette)
|
||||
self.update()
|
||||
self.repaint()
|
||||
|
||||
def mousePressEvent(self, event):
|
||||
self._on_close()
|
||||
|
||||
def _on_close(self):
|
||||
if self.flash:
|
||||
self.flash_timer.stop()
|
||||
self.close_all_requested.emit()
|
||||
self.close()
|
||||
|
||||
def showEvent(self, event):
|
||||
super().showEvent(event)
|
||||
self.raise_()
|
||||
if self.flash:
|
||||
self.flash_timer.start(1000)
|
||||
@@ -41,29 +41,55 @@ class SettingsDialog(QtWidgets.QDialog, Ui_Dialog):
|
||||
self.link_callbacks()
|
||||
|
||||
def initUI(self):
|
||||
self.buttonBox.button(QtWidgets.QDialogButtonBox.StandardButton.Apply).setEnabled(False)
|
||||
self.buttonBox.button(
|
||||
QtWidgets.QDialogButtonBox.StandardButton.Apply
|
||||
).setEnabled(False)
|
||||
|
||||
# Notifications
|
||||
self.spin_priority.setValue(settings.value("tray/notifications/priority", type=int))
|
||||
self.spin_priority.setValue(
|
||||
settings.value("tray/notifications/priority", type=int)
|
||||
)
|
||||
|
||||
self.spin_duration.setValue(settings.value("tray/notifications/duration_ms", type=int))
|
||||
self.spin_duration.setValue(
|
||||
settings.value("tray/notifications/duration_ms", type=int)
|
||||
)
|
||||
if platform.system() == "Windows":
|
||||
# The notification duration setting is ignored by windows
|
||||
self.label_notification_duration.hide()
|
||||
self.spin_duration.hide()
|
||||
self.label_notification_duration_ms.hide()
|
||||
|
||||
self.cb_notify.setChecked(settings.value("message/check_missed/notify", type=bool))
|
||||
self.cb_notify.setChecked(
|
||||
settings.value("message/check_missed/notify", type=bool)
|
||||
)
|
||||
|
||||
self.cb_notification_click.setChecked(settings.value("tray/notifications/click", type=bool))
|
||||
self.cb_notification_click.setChecked(
|
||||
settings.value("tray/notifications/click", type=bool)
|
||||
)
|
||||
|
||||
self.cb_tray_icon_unread.setChecked(settings.value("tray/icon/unread", type=bool))
|
||||
self.cb_tray_icon_unread.setChecked(
|
||||
settings.value("tray/icon/unread", type=bool)
|
||||
)
|
||||
|
||||
self.cb_priority10_persistent.setChecked(
|
||||
settings.value("tray/notifications/priority10_persistent", type=bool)
|
||||
)
|
||||
|
||||
self.cb_sound_only_priority10.setChecked(
|
||||
settings.value("tray/notifications/sound_only_priority10", type=bool)
|
||||
)
|
||||
|
||||
# Interface
|
||||
self.cb_priority_colors.setChecked(settings.value("MessageWidget/priority_color", type=bool))
|
||||
self.cb_image_urls.setChecked(settings.value("MessageWidget/image_urls", type=bool))
|
||||
self.cb_priority_colors.setChecked(
|
||||
settings.value("MessageWidget/priority_color", type=bool)
|
||||
)
|
||||
self.cb_image_urls.setChecked(
|
||||
settings.value("MessageWidget/image_urls", type=bool)
|
||||
)
|
||||
self.cb_locale.setChecked(settings.value("locale", type=bool))
|
||||
self.cb_sort_applications.setChecked(settings.value("ApplicationModel/sort", type=bool))
|
||||
self.cb_sort_applications.setChecked(
|
||||
settings.value("ApplicationModel/sort", type=bool)
|
||||
)
|
||||
|
||||
# Logging
|
||||
self.combo_logging.addItems(
|
||||
@@ -81,18 +107,22 @@ class SettingsDialog(QtWidgets.QDialog, Ui_Dialog):
|
||||
self.add_message_widget()
|
||||
|
||||
# Advanced
|
||||
self.groupbox_image_popup.setChecked(settings.value("ImagePopup/enabled", type=bool))
|
||||
self.groupbox_image_popup.setChecked(
|
||||
settings.value("ImagePopup/enabled", type=bool)
|
||||
)
|
||||
self.spin_popup_w.setValue(settings.value("ImagePopup/w", type=int))
|
||||
self.spin_popup_h.setValue(settings.value("ImagePopup/h", type=int))
|
||||
self.label_cache.setText("0 MB")
|
||||
self.compute_cache_size()
|
||||
self.groupbox_watchdog.setChecked(settings.value("watchdog/enabled", type=bool))
|
||||
self.spin_watchdog_interval.setValue(settings.value("watchdog/interval/s", type=int))
|
||||
self.spin_watchdog_interval.setValue(
|
||||
settings.value("watchdog/interval/s", type=int)
|
||||
)
|
||||
|
||||
self.label_app_version.setText(__version__)
|
||||
self.label_qt_version.setText(QtCore.QT_VERSION_STR)
|
||||
self.label_app_icon.setPixmap(QtGui.QIcon(get_image("logo.ico")).pixmap(22,22))
|
||||
self.label_qt_icon.setPixmap(QtGui.QIcon(get_image("qt.png")).pixmap(22,22))
|
||||
self.label_app_icon.setPixmap(QtGui.QIcon(get_image("logo.ico")).pixmap(22, 22))
|
||||
self.label_qt_icon.setPixmap(QtGui.QIcon(get_image("qt.png")).pixmap(22, 22))
|
||||
|
||||
def add_message_widget(self):
|
||||
self.message_widget = MessageWidget(
|
||||
@@ -113,18 +143,18 @@ class SettingsDialog(QtWidgets.QDialog, Ui_Dialog):
|
||||
|
||||
def compute_cache_size(self):
|
||||
self.cache_size_task = CacheSizeTask()
|
||||
self.cache_size_task.size.connect(lambda size: self.label_cache.setText(f"{round(size/1e6, 1)} MB"))
|
||||
self.cache_size_task.size.connect(
|
||||
lambda size: self.label_cache.setText(f"{round(size / 1e6, 1)} MB")
|
||||
)
|
||||
self.cache_size_task.start()
|
||||
|
||||
def set_value(self, key: str, value: Any, widget: QtWidgets.QWidget):
|
||||
"""Set a Settings value, only if the widget's value_changed attribute has been set
|
||||
"""
|
||||
"""Set a Settings value, only if the widget's value_changed attribute has been set"""
|
||||
if hasattr(widget, "value_changed"):
|
||||
settings.setValue(key, value)
|
||||
|
||||
def connect_signal(self, signal: QtCore.pyqtBoundSignal, widget: QtWidgets.QWidget):
|
||||
"""Connect to a signal and set the value_changed attribute for a widget on trigger
|
||||
"""
|
||||
"""Connect to a signal and set the value_changed attribute for a widget on trigger"""
|
||||
signal.connect(lambda *args: self.setting_changed_callback(widget))
|
||||
|
||||
def change_server_info_callback(self):
|
||||
@@ -132,13 +162,17 @@ class SettingsDialog(QtWidgets.QDialog, Ui_Dialog):
|
||||
|
||||
def setting_changed_callback(self, widget: QtWidgets.QWidget):
|
||||
self.settings_changed = True
|
||||
self.buttonBox.button(QtWidgets.QDialogButtonBox.StandardButton.Apply).setEnabled(True)
|
||||
self.buttonBox.button(
|
||||
QtWidgets.QDialogButtonBox.StandardButton.Apply
|
||||
).setEnabled(True)
|
||||
setattr(widget, "value_changed", True)
|
||||
|
||||
def change_font_callback(self, name: str):
|
||||
label: QtWidgets.QLabel = getattr(self.message_widget, "label_" + name)
|
||||
|
||||
font, accepted = QtWidgets.QFontDialog.getFont(label.font(), self, f"Select a {name} font")
|
||||
font, accepted = QtWidgets.QFontDialog.getFont(
|
||||
label.font(), self, f"Select a {name} font"
|
||||
)
|
||||
|
||||
if accepted:
|
||||
self.setting_changed_callback(label)
|
||||
@@ -146,7 +180,10 @@ class SettingsDialog(QtWidgets.QDialog, Ui_Dialog):
|
||||
|
||||
def export_callback(self):
|
||||
fname = QtWidgets.QFileDialog.getSaveFileName(
|
||||
self, "Export Settings", settings.value("export/path", type=str), "*",
|
||||
self,
|
||||
"Export Settings",
|
||||
settings.value("export/path", type=str),
|
||||
"*",
|
||||
)[0]
|
||||
if fname and os.path.exists(os.path.dirname(fname)):
|
||||
self.export_settings_task = ExportSettingsTask(fname)
|
||||
@@ -162,7 +199,10 @@ class SettingsDialog(QtWidgets.QDialog, Ui_Dialog):
|
||||
|
||||
def import_callback(self):
|
||||
fname = QtWidgets.QFileDialog.getOpenFileName(
|
||||
self, "Import Settings", settings.value("export/path", type=str), "*",
|
||||
self,
|
||||
"Import Settings",
|
||||
settings.value("export/path", type=str),
|
||||
"*",
|
||||
)[0]
|
||||
if fname and os.path.exists(fname):
|
||||
self.import_settings_task = ImportSettingsTask(fname)
|
||||
@@ -202,60 +242,128 @@ class SettingsDialog(QtWidgets.QDialog, Ui_Dialog):
|
||||
self.label_cache.setText("0 MB")
|
||||
|
||||
def link_callbacks(self):
|
||||
self.buttonBox.button(QtWidgets.QDialogButtonBox.StandardButton.Apply).clicked.connect(self.apply_settings)
|
||||
self.buttonBox.button(
|
||||
QtWidgets.QDialogButtonBox.StandardButton.Apply
|
||||
).clicked.connect(self.apply_settings)
|
||||
|
||||
# Notifications
|
||||
self.connect_signal(self.spin_priority.valueChanged, self.spin_priority)
|
||||
self.connect_signal(self.spin_duration.valueChanged, self.spin_duration)
|
||||
self.connect_signal(self.cb_notify.stateChanged, self.cb_notify)
|
||||
self.connect_signal(self.cb_notification_click.stateChanged, self.cb_notification_click)
|
||||
self.connect_signal(self.cb_tray_icon_unread.stateChanged, self.cb_tray_icon_unread)
|
||||
self.connect_signal(
|
||||
self.cb_notification_click.stateChanged, self.cb_notification_click
|
||||
)
|
||||
self.connect_signal(
|
||||
self.cb_tray_icon_unread.stateChanged, self.cb_tray_icon_unread
|
||||
)
|
||||
self.connect_signal(
|
||||
self.cb_priority10_persistent.stateChanged, self.cb_priority10_persistent
|
||||
)
|
||||
self.connect_signal(
|
||||
self.cb_sound_only_priority10.stateChanged, self.cb_sound_only_priority10
|
||||
)
|
||||
|
||||
# Interface
|
||||
self.connect_signal(self.cb_priority_colors.stateChanged, self.cb_priority_colors)
|
||||
self.connect_signal(
|
||||
self.cb_priority_colors.stateChanged, self.cb_priority_colors
|
||||
)
|
||||
self.connect_signal(self.cb_image_urls.stateChanged, self.cb_image_urls)
|
||||
self.connect_signal(self.cb_locale.stateChanged, self.cb_locale)
|
||||
self.connect_signal(self.cb_sort_applications.stateChanged, self.cb_sort_applications)
|
||||
self.connect_signal(
|
||||
self.cb_sort_applications.stateChanged, self.cb_sort_applications
|
||||
)
|
||||
|
||||
# Server info
|
||||
self.pb_change_server_info.clicked.connect(self.change_server_info_callback)
|
||||
|
||||
# Logging
|
||||
self.connect_signal(self.combo_logging.currentTextChanged, self.combo_logging)
|
||||
self.pb_open_log.clicked.connect(lambda: open_file(logger.root.handlers[0].baseFilename))
|
||||
self.pb_open_log.clicked.connect(
|
||||
lambda: open_file(logger.root.handlers[0].baseFilename)
|
||||
)
|
||||
|
||||
# Fonts
|
||||
self.pb_reset_fonts.clicked.connect(self.reset_fonts_callback)
|
||||
|
||||
self.pb_font_message_title.clicked.connect(lambda: self.change_font_callback("title"))
|
||||
self.pb_font_message_date.clicked.connect(lambda: self.change_font_callback("date"))
|
||||
self.pb_font_message_content.clicked.connect(lambda: self.change_font_callback("message"))
|
||||
self.pb_font_message_title.clicked.connect(
|
||||
lambda: self.change_font_callback("title")
|
||||
)
|
||||
self.pb_font_message_date.clicked.connect(
|
||||
lambda: self.change_font_callback("date")
|
||||
)
|
||||
self.pb_font_message_content.clicked.connect(
|
||||
lambda: self.change_font_callback("message")
|
||||
)
|
||||
|
||||
# Advanced
|
||||
self.pb_export.clicked.connect(self.export_callback)
|
||||
self.pb_import.clicked.connect(self.import_callback)
|
||||
self.pb_reset.clicked.connect(self.reset_callback)
|
||||
self.connect_signal(self.groupbox_image_popup.toggled, self.groupbox_image_popup)
|
||||
self.connect_signal(
|
||||
self.groupbox_image_popup.toggled, self.groupbox_image_popup
|
||||
)
|
||||
self.connect_signal(self.spin_popup_w.valueChanged, self.spin_popup_w)
|
||||
self.connect_signal(self.spin_popup_h.valueChanged, self.spin_popup_h)
|
||||
self.pb_clear_cache.clicked.connect(self.clear_cache_callback)
|
||||
self.pb_open_cache_dir.clicked.connect(lambda: open_file(Cache().directory()))
|
||||
self.connect_signal(self.groupbox_watchdog.toggled, self.groupbox_watchdog)
|
||||
self.connect_signal(self.spin_watchdog_interval.valueChanged, self.spin_watchdog_interval)
|
||||
self.connect_signal(
|
||||
self.spin_watchdog_interval.valueChanged, self.spin_watchdog_interval
|
||||
)
|
||||
|
||||
def apply_settings(self):
|
||||
# Priority
|
||||
self.set_value("tray/notifications/priority", self.spin_priority.value(), self.spin_priority)
|
||||
self.set_value("tray/notifications/duration_ms", self.spin_duration.value(), self.spin_duration)
|
||||
self.set_value("message/check_missed/notify", self.cb_notify.isChecked(), self.cb_notify)
|
||||
self.set_value("tray/notifications/click", self.cb_notification_click.isChecked(), self.cb_notification_click)
|
||||
self.set_value("tray/icon/unread", self.cb_tray_icon_unread.isChecked(), self.cb_tray_icon_unread)
|
||||
self.set_value(
|
||||
"tray/notifications/priority",
|
||||
self.spin_priority.value(),
|
||||
self.spin_priority,
|
||||
)
|
||||
self.set_value(
|
||||
"tray/notifications/duration_ms",
|
||||
self.spin_duration.value(),
|
||||
self.spin_duration,
|
||||
)
|
||||
self.set_value(
|
||||
"message/check_missed/notify", self.cb_notify.isChecked(), self.cb_notify
|
||||
)
|
||||
self.set_value(
|
||||
"tray/notifications/click",
|
||||
self.cb_notification_click.isChecked(),
|
||||
self.cb_notification_click,
|
||||
)
|
||||
self.set_value(
|
||||
"tray/icon/unread",
|
||||
self.cb_tray_icon_unread.isChecked(),
|
||||
self.cb_tray_icon_unread,
|
||||
)
|
||||
self.set_value(
|
||||
"tray/notifications/priority10_persistent",
|
||||
self.cb_priority10_persistent.isChecked(),
|
||||
self.cb_priority10_persistent,
|
||||
)
|
||||
self.set_value(
|
||||
"tray/notifications/sound_only_priority10",
|
||||
self.cb_sound_only_priority10.isChecked(),
|
||||
self.cb_sound_only_priority10,
|
||||
)
|
||||
|
||||
# Interface
|
||||
self.set_value("MessageWidget/priority_color", self.cb_priority_colors.isChecked(), self.cb_priority_colors)
|
||||
self.set_value("MessageWidget/image_urls", self.cb_image_urls.isChecked(), self.cb_image_urls)
|
||||
self.set_value(
|
||||
"MessageWidget/priority_color",
|
||||
self.cb_priority_colors.isChecked(),
|
||||
self.cb_priority_colors,
|
||||
)
|
||||
self.set_value(
|
||||
"MessageWidget/image_urls",
|
||||
self.cb_image_urls.isChecked(),
|
||||
self.cb_image_urls,
|
||||
)
|
||||
self.set_value("locale", self.cb_locale.isChecked(), self.cb_locale)
|
||||
self.set_value("ApplicationModel/sort", self.cb_sort_applications.isChecked(), self.cb_sort_applications)
|
||||
self.set_value(
|
||||
"ApplicationModel/sort",
|
||||
self.cb_sort_applications.isChecked(),
|
||||
self.cb_sort_applications,
|
||||
)
|
||||
|
||||
# Logging
|
||||
selected_level = self.combo_logging.currentText()
|
||||
@@ -267,18 +375,44 @@ class SettingsDialog(QtWidgets.QDialog, Ui_Dialog):
|
||||
logger.setLevel(selected_level)
|
||||
|
||||
# Fonts
|
||||
self.set_value("MessageWidget/font/title", self.message_widget.label_title.font().toString(), self.message_widget.label_title)
|
||||
self.set_value("MessageWidget/font/date", self.message_widget.label_date.font().toString(), self.message_widget.label_date)
|
||||
self.set_value("MessageWidget/font/message", self.message_widget.label_message.font().toString(), self.message_widget.label_message)
|
||||
self.set_value(
|
||||
"MessageWidget/font/title",
|
||||
self.message_widget.label_title.font().toString(),
|
||||
self.message_widget.label_title,
|
||||
)
|
||||
self.set_value(
|
||||
"MessageWidget/font/date",
|
||||
self.message_widget.label_date.font().toString(),
|
||||
self.message_widget.label_date,
|
||||
)
|
||||
self.set_value(
|
||||
"MessageWidget/font/message",
|
||||
self.message_widget.label_message.font().toString(),
|
||||
self.message_widget.label_message,
|
||||
)
|
||||
|
||||
# Advanced
|
||||
self.set_value("ImagePopup/enabled", self.groupbox_image_popup.isChecked(), self.groupbox_image_popup)
|
||||
self.set_value(
|
||||
"ImagePopup/enabled",
|
||||
self.groupbox_image_popup.isChecked(),
|
||||
self.groupbox_image_popup,
|
||||
)
|
||||
self.set_value("ImagePopup/w", self.spin_popup_w.value(), self.spin_popup_w)
|
||||
self.set_value("ImagePopup/h", self.spin_popup_h.value(), self.spin_popup_h)
|
||||
self.set_value("watchdog/enabled", self.groupbox_watchdog.isChecked(), self.groupbox_watchdog)
|
||||
self.set_value("watchdog/interval/s", self.spin_watchdog_interval.value(), self.spin_watchdog_interval)
|
||||
self.set_value(
|
||||
"watchdog/enabled",
|
||||
self.groupbox_watchdog.isChecked(),
|
||||
self.groupbox_watchdog,
|
||||
)
|
||||
self.set_value(
|
||||
"watchdog/interval/s",
|
||||
self.spin_watchdog_interval.value(),
|
||||
self.spin_watchdog_interval,
|
||||
)
|
||||
|
||||
self.settings_changed = False
|
||||
self.buttonBox.button(QtWidgets.QDialogButtonBox.StandardButton.Apply).setEnabled(False)
|
||||
self.buttonBox.button(
|
||||
QtWidgets.QDialogButtonBox.StandardButton.Apply
|
||||
).setEnabled(False)
|
||||
|
||||
self.changes_applied = True
|
||||
|
||||
8
pyrightconfig.json
Normal file
8
pyrightconfig.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"reportOptionalMemberAccess": false,
|
||||
"reportAttributeAccessIssue": false,
|
||||
"reportIncompatibleMethodOverride": false,
|
||||
"reportArgumentType": false,
|
||||
"reportAssignmentType": false,
|
||||
"reportReturnType": false
|
||||
}
|
||||
@@ -1,2 +1,4 @@
|
||||
requests==2.32.3
|
||||
pyqt6==6.7.1
|
||||
requests
|
||||
pyqt6>=6.7.1
|
||||
pyqt6-qt6
|
||||
pyqt6-qt6-multimedia
|
||||
|
||||
5
setup.py
5
setup.py
@@ -15,7 +15,7 @@ with open("version.txt", "r") as f:
|
||||
|
||||
# What packages are required for this module to be executed?
|
||||
REQUIRED = [
|
||||
'requests==2.32.3', 'pyqt6==6.7.1'
|
||||
'requests', 'pyqt6>=6.7.1'
|
||||
]
|
||||
|
||||
# What packages are optional?
|
||||
@@ -86,6 +86,7 @@ setup(
|
||||
'Programming Language :: Python :: 3',
|
||||
'Programming Language :: Python :: 3.10',
|
||||
'Programming Language :: Python :: 3.11',
|
||||
'Programming Language :: Python :: 3.12'
|
||||
'Programming Language :: Python :: 3.12',
|
||||
'Programming Language :: Python :: 3.13'
|
||||
]
|
||||
)
|
||||
|
||||
@@ -6,8 +6,8 @@ VSVersionInfo(
|
||||
ffi=FixedFileInfo(
|
||||
# filevers and prodvers should be always a tuple with four items: (1, 2, 3, 4)
|
||||
# Set not needed items to zero 0.
|
||||
filevers=(0, 5, 2, 0),
|
||||
prodvers=(0, 5, 2, 0),
|
||||
filevers=(0, 5, 3, 0),
|
||||
prodvers=(0, 5, 3, 0),
|
||||
# Contains a bitmask that specifies the valid bits 'flags'r
|
||||
mask=0x3F,
|
||||
# Contains a bitmask that specifies the Boolean attributes of the file.
|
||||
@@ -34,12 +34,12 @@ VSVersionInfo(
|
||||
StringStruct(u"Comments", u"Gotify Tray"),
|
||||
StringStruct(u"CompanyName", u""),
|
||||
StringStruct(u"FileDescription", u"Gotifiy Tray"),
|
||||
StringStruct(u"FileVersion", u"0.5.2"),
|
||||
StringStruct(u"FileVersion", u"0.5.3"),
|
||||
StringStruct(u"InternalName", u"gotify-tray"),
|
||||
StringStruct(u"LegalCopyright", u""),
|
||||
StringStruct(u"OriginalFilename", u"gotify-tray.exe"),
|
||||
StringStruct(u"ProductName", u"Gotify Tray"),
|
||||
StringStruct(u"ProductVersion", u"0.5.2"),
|
||||
StringStruct(u"ProductVersion", u"0.5.3"),
|
||||
],
|
||||
)
|
||||
]
|
||||
|
||||
@@ -1 +1 @@
|
||||
0.5.2
|
||||
0.5.3
|
||||
Reference in New Issue
Block a user