Compare commits

...

4 Commits

Author SHA1 Message Date
kdusek
2b3d9eb07f Add search feature for Gotify alerts
Some checks failed
build / build-win64 (push) Waiting to run
build / build-macos (push) Waiting to run
build / build-pip (push) Failing after 12s
2025-12-06 03:10:41 +01:00
kdusek
d0941fd7ab Update gotify-tray.spec
Some checks failed
build / build-win64 (push) Waiting to run
build / build-macos (push) Waiting to run
build / build-pip (push) Failing after 13s
2025-12-06 03:06:03 +01:00
kdusek
efdc63e1ab Remove subject filtering, keep only priority buttons
Some checks failed
build / build-pip (push) Failing after 12s
build / build-win64 (push) Has been cancelled
build / build-macos (push) Has been cancelled
- Remove subject filter menu and related code
- Simplify filtering to priority groups only
- Keep Remove Filters button for priority reset
- Clean up unused code and UI elements
2025-12-01 18:03:54 +01:00
kdusek
4c3b6925e5 Add message filtering by priority and subject, with CRITICAL always visible
- Implement MessagesProxyModel for client-side filtering
- Add priority filter buttons (LOW 0-3, NORMAL 4-8, HIGH 9, CRITICAL 10 always shown)
- Add subject filter menu with checkable actions for message titles
- Add Remove Filters button to reset all filters
- Restore priority 10 persistent notification setting in options
- Fix settings dialog errors and update UI layouts
- Ensure CRITICAL priority messages cannot be filtered out but can toggle persistent pop-ups
2025-12-01 18:02:05 +01:00
12 changed files with 360 additions and 222 deletions

View File

@@ -8,7 +8,7 @@ logo = "gotify_tray/gui/images/logo.ico" if platform.system() != "Darwin" else "
a = Analysis(['gotify_tray/__main__.py'], a = Analysis(['gotify_tray/__main__.py'],
pathex=[os.getcwd()], pathex=[os.getcwd()],
binaries=[], binaries=[('/lib/x86_64-linux-gnu/libpython3.10.so', '.'), ('/lib/x86_64-linux-gnu/libpython3.10.so.1', '.')],
datas=[('gotify_tray/gui/images', 'gotify_tray/gui/images'), ('gotify_tray/gui/themes', 'gotify_tray/gui/themes')], datas=[('gotify_tray/gui/images', 'gotify_tray/gui/images'), ('gotify_tray/gui/themes', 'gotify_tray/gui/themes')],
hiddenimports=[], hiddenimports=[],
hookspath=[], hookspath=[],

View File

@@ -34,6 +34,7 @@ from .models import (
ApplicationProxyModel, ApplicationProxyModel,
MessagesModel, MessagesModel,
MessagesModelItem, MessagesModelItem,
MessagesProxyModel,
MessageItemDataRole, MessageItemDataRole,
) )
from .widgets import ImagePopup, MainWindow, MessageWidget, SettingsDialog, Tray from .widgets import ImagePopup, MainWindow, MessageWidget, SettingsDialog, Tray
@@ -92,11 +93,16 @@ class MainApplication(QtWidgets.QApplication):
self.downloader = Downloader() self.downloader = Downloader()
self.messages_model = MessagesModel() self.messages_model = MessagesModel()
self.messages_proxy_model = MessagesProxyModel()
self.messages_proxy_model.setSourceModel(self.messages_model)
self.application_model = ApplicationModel() self.application_model = ApplicationModel()
self.application_proxy_model = ApplicationProxyModel(self.application_model) self.application_proxy_model = ApplicationProxyModel(self.application_model)
self.main_window = MainWindow( self.main_window = MainWindow(
self.application_model, self.application_proxy_model, self.messages_model self.application_model,
self.application_proxy_model,
self.messages_model,
self.messages_proxy_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)
@@ -112,6 +118,9 @@ class MainApplication(QtWidgets.QApplication):
self.watchdog = ServerConnectionWatchdogTask(self.gotify_client) self.watchdog = ServerConnectionWatchdogTask(self.gotify_client)
self.link_callbacks() self.link_callbacks()
self.main_window.priority_filter_changed.connect(
self.on_priority_filter_changed
)
self.init_shortcuts() self.init_shortcuts()
self.gotify_client.listen() self.gotify_client.listen()
@@ -199,6 +208,9 @@ class MainApplication(QtWidgets.QApplication):
else: else:
self.gotify_client.stop() self.gotify_client.stop()
def on_priority_filter_changed(self, priorities: set[int]):
self.messages_proxy_model.set_allowed_priorities(priorities)
def abort_get_messages_task(self): def abort_get_messages_task(self):
""" """
Abort any tasks that will result in new messages getting appended to messages_model Abort any tasks that will result in new messages getting appended to messages_model

View File

@@ -1,6 +1,6 @@
# Form implementation generated from reading ui file 'gotify_tray/gui/designs\widget_main.ui' # Form implementation generated from reading ui file 'gotify_tray/gui/designs/widget_main.ui'
# #
# Created by: PyQt6 UI code generator 6.5.0 # Created by: PyQt6 UI code generator 6.9.1
# #
# WARNING: Any manual changes made to this file will be lost when pyuic6 is # WARNING: Any manual changes made to this file will be lost when pyuic6 is
# run again. Do not edit this file unless you know what you are doing. # run again. Do not edit this file unless you know what you are doing.
@@ -47,6 +47,40 @@ class Ui_MainWindow(object):
self.pb_delete_all.setObjectName("pb_delete_all") self.pb_delete_all.setObjectName("pb_delete_all")
self.horizontalLayout.addWidget(self.pb_delete_all) self.horizontalLayout.addWidget(self.pb_delete_all)
self.verticalLayout_2.addLayout(self.horizontalLayout) self.verticalLayout_2.addLayout(self.horizontalLayout)
self.filtersLayout = QtWidgets.QHBoxLayout()
self.filtersLayout.setObjectName("filtersLayout")
self.label_priority = QtWidgets.QLabel(parent=self.verticalLayoutWidget)
self.label_priority.setObjectName("label_priority")
self.filtersLayout.addWidget(self.label_priority)
self.pb_low = QtWidgets.QPushButton(parent=self.verticalLayoutWidget)
self.pb_low.setCheckable(True)
self.pb_low.setChecked(True)
self.pb_low.setObjectName("pb_low")
self.filtersLayout.addWidget(self.pb_low)
self.pb_normal = QtWidgets.QPushButton(parent=self.verticalLayoutWidget)
self.pb_normal.setCheckable(True)
self.pb_normal.setChecked(True)
self.pb_normal.setObjectName("pb_normal")
self.filtersLayout.addWidget(self.pb_normal)
self.pb_high = QtWidgets.QPushButton(parent=self.verticalLayoutWidget)
self.pb_high.setCheckable(True)
self.pb_high.setChecked(True)
self.pb_high.setObjectName("pb_high")
self.filtersLayout.addWidget(self.pb_high)
self.pb_critical = QtWidgets.QPushButton(parent=self.verticalLayoutWidget)
self.pb_critical.setCheckable(True)
self.pb_critical.setChecked(True)
self.pb_critical.setObjectName("pb_critical")
self.filtersLayout.addWidget(self.pb_critical)
self.le_search = QtWidgets.QLineEdit(parent=self.verticalLayoutWidget)
self.le_search.setObjectName("le_search")
self.filtersLayout.addWidget(self.le_search)
spacerItem2 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum)
self.filtersLayout.addItem(spacerItem2)
self.pb_remove_filters = QtWidgets.QPushButton(parent=self.verticalLayoutWidget)
self.pb_remove_filters.setObjectName("pb_remove_filters")
self.filtersLayout.addWidget(self.pb_remove_filters)
self.verticalLayout_2.addLayout(self.filtersLayout)
self.listView_messages = QtWidgets.QListView(parent=self.verticalLayoutWidget) self.listView_messages = QtWidgets.QListView(parent=self.verticalLayoutWidget)
self.listView_messages.setAutoScroll(True) self.listView_messages.setAutoScroll(True)
self.listView_messages.setEditTriggers(QtWidgets.QAbstractItemView.EditTrigger.NoEditTriggers) self.listView_messages.setEditTriggers(QtWidgets.QAbstractItemView.EditTrigger.NoEditTriggers)
@@ -66,6 +100,13 @@ class Ui_MainWindow(object):
_translate = QtCore.QCoreApplication.translate _translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "Form")) MainWindow.setWindowTitle(_translate("MainWindow", "Form"))
self.label_application.setText(_translate("MainWindow", "Application")) self.label_application.setText(_translate("MainWindow", "Application"))
self.label_priority.setText(_translate("MainWindow", "Priority:"))
self.pb_low.setText(_translate("MainWindow", "LOW"))
self.pb_normal.setText(_translate("MainWindow", "NORMAL"))
self.pb_high.setText(_translate("MainWindow", "HIGH"))
self.pb_critical.setText(_translate("MainWindow", "CRITICAL"))
self.le_search.setPlaceholderText(_translate("MainWindow", "Search messages..."))
self.pb_remove_filters.setText(_translate("MainWindow", "Remove Filters"))
if __name__ == "__main__": if __name__ == "__main__":

View File

@@ -90,6 +90,96 @@
</item> </item>
</layout> </layout>
</item> </item>
<item>
<layout class="QHBoxLayout" name="filtersLayout">
<item>
<widget class="QLabel" name="label_priority">
<property name="text">
<string>Priority:</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pb_low">
<property name="text">
<string>LOW</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pb_normal">
<property name="text">
<string>NORMAL</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pb_high">
<property name="text">
<string>HIGH</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pb_critical">
<property name="text">
<string>CRITICAL</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="le_search">
<property name="placeholderText">
<string>Search messages...</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="pb_remove_filters">
<property name="text">
<string>Remove Filters</string>
</property>
</widget>
</item>
</layout>
</item>
<item> <item>
<widget class="QListView" name="listView_messages"> <widget class="QListView" name="listView_messages">
<property name="autoScroll"> <property name="autoScroll">

View File

@@ -1,6 +1,6 @@
# Form implementation generated from reading ui file 'gotify_tray/gui/designs\widget_message.ui' # Form implementation generated from reading ui file 'gotify_tray/gui/designs/widget_message.ui'
# #
# Created by: PyQt6 UI code generator 6.5.0 # Created by: PyQt6 UI code generator 6.9.1
# #
# WARNING: Any manual changes made to this file will be lost when pyuic6 is # WARNING: Any manual changes made to this file will be lost when pyuic6 is
# run again. Do not edit this file unless you know what you are doing. # run again. Do not edit this file unless you know what you are doing.

View File

@@ -1,6 +1,6 @@
# Form implementation generated from reading ui file 'gotify_tray/gui/designs\widget_server.ui' # Form implementation generated from reading ui file 'gotify_tray/gui/designs/widget_server.ui'
# #
# Created by: PyQt6 UI code generator 6.5.0 # Created by: PyQt6 UI code generator 6.9.1
# #
# WARNING: Any manual changes made to this file will be lost when pyuic6 is # WARNING: Any manual changes made to this file will be lost when pyuic6 is
# run again. Do not edit this file unless you know what you are doing. # run again. Do not edit this file unless you know what you are doing.

View File

@@ -1,6 +1,6 @@
# Form implementation generated from reading ui file 'gotify_tray/gui/designs/widget_settings.ui' # Form implementation generated from reading ui file 'gotify_tray/gui/designs/widget_settings.ui'
# #
# Created by: PyQt6 UI code generator 6.4.2 # Created by: PyQt6 UI code generator 6.9.1
# #
# WARNING: Any manual changes made to this file will be lost when pyuic6 is # WARNING: Any manual changes made to this file will be lost when pyuic6 is
# run again. Do not edit this file unless you know what you are doing. # run again. Do not edit this file unless you know what you are doing.
@@ -17,11 +17,7 @@ class Ui_Dialog(object):
self.gridLayout.setObjectName("gridLayout") self.gridLayout.setObjectName("gridLayout")
self.buttonBox = QtWidgets.QDialogButtonBox(parent=Dialog) self.buttonBox = QtWidgets.QDialogButtonBox(parent=Dialog)
self.buttonBox.setOrientation(QtCore.Qt.Orientation.Horizontal) self.buttonBox.setOrientation(QtCore.Qt.Orientation.Horizontal)
self.buttonBox.setStandardButtons( self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.StandardButton.Apply|QtWidgets.QDialogButtonBox.StandardButton.Cancel|QtWidgets.QDialogButtonBox.StandardButton.Ok)
QtWidgets.QDialogButtonBox.StandardButton.Apply
| QtWidgets.QDialogButtonBox.StandardButton.Cancel
| QtWidgets.QDialogButtonBox.StandardButton.Ok
)
self.buttonBox.setObjectName("buttonBox") self.buttonBox.setObjectName("buttonBox")
self.gridLayout.addWidget(self.buttonBox, 1, 4, 1, 1) self.gridLayout.addWidget(self.buttonBox, 1, 4, 1, 1)
self.tabWidget = QtWidgets.QTabWidget(parent=Dialog) self.tabWidget = QtWidgets.QTabWidget(parent=Dialog)
@@ -34,9 +30,7 @@ class Ui_Dialog(object):
self.groupBox_notifications.setObjectName("groupBox_notifications") self.groupBox_notifications.setObjectName("groupBox_notifications")
self.gridLayout_4 = QtWidgets.QGridLayout(self.groupBox_notifications) self.gridLayout_4 = QtWidgets.QGridLayout(self.groupBox_notifications)
self.gridLayout_4.setObjectName("gridLayout_4") self.gridLayout_4.setObjectName("gridLayout_4")
self.label_notification_duration = QtWidgets.QLabel( self.label_notification_duration = QtWidgets.QLabel(parent=self.groupBox_notifications)
parent=self.groupBox_notifications
)
self.label_notification_duration.setObjectName("label_notification_duration") self.label_notification_duration.setObjectName("label_notification_duration")
self.gridLayout_4.addWidget(self.label_notification_duration, 1, 0, 1, 1) self.gridLayout_4.addWidget(self.label_notification_duration, 1, 0, 1, 1)
self.spin_duration = QtWidgets.QSpinBox(parent=self.groupBox_notifications) self.spin_duration = QtWidgets.QSpinBox(parent=self.groupBox_notifications)
@@ -45,24 +39,13 @@ class Ui_Dialog(object):
self.spin_duration.setSingleStep(100) self.spin_duration.setSingleStep(100)
self.spin_duration.setObjectName("spin_duration") self.spin_duration.setObjectName("spin_duration")
self.gridLayout_4.addWidget(self.spin_duration, 1, 1, 1, 1) self.gridLayout_4.addWidget(self.spin_duration, 1, 1, 1, 1)
self.cb_notification_click = QtWidgets.QCheckBox( self.cb_notification_click = QtWidgets.QCheckBox(parent=self.groupBox_notifications)
parent=self.groupBox_notifications
)
self.cb_notification_click.setObjectName("cb_notification_click") self.cb_notification_click.setObjectName("cb_notification_click")
self.gridLayout_4.addWidget(self.cb_notification_click, 3, 0, 1, 3) self.gridLayout_4.addWidget(self.cb_notification_click, 3, 0, 1, 3)
self.label_notification_duration_ms = QtWidgets.QLabel( self.label_notification_duration_ms = QtWidgets.QLabel(parent=self.groupBox_notifications)
parent=self.groupBox_notifications self.label_notification_duration_ms.setObjectName("label_notification_duration_ms")
)
self.label_notification_duration_ms.setObjectName(
"label_notification_duration_ms"
)
self.gridLayout_4.addWidget(self.label_notification_duration_ms, 1, 2, 1, 1) self.gridLayout_4.addWidget(self.label_notification_duration_ms, 1, 2, 1, 1)
spacerItem = QtWidgets.QSpacerItem( spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum)
40,
20,
QtWidgets.QSizePolicy.Policy.Expanding,
QtWidgets.QSizePolicy.Policy.Minimum,
)
self.gridLayout_4.addItem(spacerItem, 0, 2, 1, 1) self.gridLayout_4.addItem(spacerItem, 0, 2, 1, 1)
self.cb_notify = QtWidgets.QCheckBox(parent=self.groupBox_notifications) self.cb_notify = QtWidgets.QCheckBox(parent=self.groupBox_notifications)
self.cb_notify.setObjectName("cb_notify") self.cb_notify.setObjectName("cb_notify")
@@ -73,26 +56,15 @@ class Ui_Dialog(object):
self.spin_priority.setProperty("value", 5) self.spin_priority.setProperty("value", 5)
self.spin_priority.setObjectName("spin_priority") self.spin_priority.setObjectName("spin_priority")
self.gridLayout_4.addWidget(self.spin_priority, 0, 1, 1, 1) self.gridLayout_4.addWidget(self.spin_priority, 0, 1, 1, 1)
self.label_notification_priority = QtWidgets.QLabel( self.label_notification_priority = QtWidgets.QLabel(parent=self.groupBox_notifications)
parent=self.groupBox_notifications
)
self.label_notification_priority.setObjectName("label_notification_priority") self.label_notification_priority.setObjectName("label_notification_priority")
self.gridLayout_4.addWidget(self.label_notification_priority, 0, 0, 1, 1) self.gridLayout_4.addWidget(self.label_notification_priority, 0, 0, 1, 1)
self.cb_tray_icon_unread = QtWidgets.QCheckBox( self.cb_tray_icon_unread = QtWidgets.QCheckBox(parent=self.groupBox_notifications)
parent=self.groupBox_notifications
)
self.cb_tray_icon_unread.setObjectName("cb_tray_icon_unread") self.cb_tray_icon_unread.setObjectName("cb_tray_icon_unread")
self.gridLayout_4.addWidget(self.cb_tray_icon_unread, 4, 0, 1, 3) self.gridLayout_4.addWidget(self.cb_tray_icon_unread, 4, 0, 1, 3)
self.cb_priority10_persistent = QtWidgets.QCheckBox( self.cb_priority10_persistent = QtWidgets.QCheckBox(parent=self.groupBox_notifications)
parent=self.groupBox_notifications
)
self.cb_priority10_persistent.setObjectName("cb_priority10_persistent") self.cb_priority10_persistent.setObjectName("cb_priority10_persistent")
self.gridLayout_4.addWidget(self.cb_priority10_persistent, 5, 0, 1, 3) 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.verticalLayout_4.addWidget(self.groupBox_notifications)
self.groupBox_2 = QtWidgets.QGroupBox(parent=self.tab_general) self.groupBox_2 = QtWidgets.QGroupBox(parent=self.tab_general)
self.groupBox_2.setObjectName("groupBox_2") self.groupBox_2.setObjectName("groupBox_2")
@@ -115,25 +87,13 @@ class Ui_Dialog(object):
self.groupBox_server_info.setObjectName("groupBox_server_info") self.groupBox_server_info.setObjectName("groupBox_server_info")
self.gridLayout_3 = QtWidgets.QGridLayout(self.groupBox_server_info) self.gridLayout_3 = QtWidgets.QGridLayout(self.groupBox_server_info)
self.gridLayout_3.setObjectName("gridLayout_3") self.gridLayout_3.setObjectName("gridLayout_3")
self.pb_change_server_info = QtWidgets.QPushButton( self.pb_change_server_info = QtWidgets.QPushButton(parent=self.groupBox_server_info)
parent=self.groupBox_server_info
)
self.pb_change_server_info.setObjectName("pb_change_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) self.gridLayout_3.addWidget(self.pb_change_server_info, 0, 0, 1, 1)
spacerItem1 = QtWidgets.QSpacerItem( spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum)
40,
20,
QtWidgets.QSizePolicy.Policy.Expanding,
QtWidgets.QSizePolicy.Policy.Minimum,
)
self.gridLayout_3.addItem(spacerItem1, 0, 1, 1, 1) self.gridLayout_3.addItem(spacerItem1, 0, 1, 1, 1)
self.verticalLayout_4.addWidget(self.groupBox_server_info) self.verticalLayout_4.addWidget(self.groupBox_server_info)
spacerItem2 = QtWidgets.QSpacerItem( spacerItem2 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Policy.Minimum, QtWidgets.QSizePolicy.Policy.Expanding)
20,
40,
QtWidgets.QSizePolicy.Policy.Minimum,
QtWidgets.QSizePolicy.Policy.Expanding,
)
self.verticalLayout_4.addItem(spacerItem2) self.verticalLayout_4.addItem(spacerItem2)
self.tabWidget.addTab(self.tab_general, "") self.tabWidget.addTab(self.tab_general, "")
self.tab_fonts = QtWidgets.QWidget() self.tab_fonts = QtWidgets.QWidget()
@@ -154,29 +114,18 @@ class Ui_Dialog(object):
self.layout_fonts_message.setObjectName("layout_fonts_message") self.layout_fonts_message.setObjectName("layout_fonts_message")
self.horizontalLayout = QtWidgets.QHBoxLayout() self.horizontalLayout = QtWidgets.QHBoxLayout()
self.horizontalLayout.setObjectName("horizontalLayout") self.horizontalLayout.setObjectName("horizontalLayout")
self.pb_font_message_title = QtWidgets.QPushButton( self.pb_font_message_title = QtWidgets.QPushButton(parent=self.groupBox_fonts_message)
parent=self.groupBox_fonts_message
)
self.pb_font_message_title.setObjectName("pb_font_message_title") self.pb_font_message_title.setObjectName("pb_font_message_title")
self.horizontalLayout.addWidget(self.pb_font_message_title) self.horizontalLayout.addWidget(self.pb_font_message_title)
self.pb_font_message_date = QtWidgets.QPushButton( self.pb_font_message_date = QtWidgets.QPushButton(parent=self.groupBox_fonts_message)
parent=self.groupBox_fonts_message
)
self.pb_font_message_date.setObjectName("pb_font_message_date") self.pb_font_message_date.setObjectName("pb_font_message_date")
self.horizontalLayout.addWidget(self.pb_font_message_date) self.horizontalLayout.addWidget(self.pb_font_message_date)
self.pb_font_message_content = QtWidgets.QPushButton( self.pb_font_message_content = QtWidgets.QPushButton(parent=self.groupBox_fonts_message)
parent=self.groupBox_fonts_message
)
self.pb_font_message_content.setObjectName("pb_font_message_content") self.pb_font_message_content.setObjectName("pb_font_message_content")
self.horizontalLayout.addWidget(self.pb_font_message_content) self.horizontalLayout.addWidget(self.pb_font_message_content)
self.layout_fonts_message.addLayout(self.horizontalLayout) self.layout_fonts_message.addLayout(self.horizontalLayout)
self.verticalLayout_5.addWidget(self.groupBox_fonts_message) self.verticalLayout_5.addWidget(self.groupBox_fonts_message)
spacerItem3 = QtWidgets.QSpacerItem( spacerItem3 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Policy.Minimum, QtWidgets.QSizePolicy.Policy.Expanding)
20,
40,
QtWidgets.QSizePolicy.Policy.Minimum,
QtWidgets.QSizePolicy.Policy.Expanding,
)
self.verticalLayout_5.addItem(spacerItem3) self.verticalLayout_5.addItem(spacerItem3)
self.tabWidget.addTab(self.tab_fonts, "") self.tabWidget.addTab(self.tab_fonts, "")
self.tab_advanced = QtWidgets.QWidget() self.tab_advanced = QtWidgets.QWidget()
@@ -222,12 +171,7 @@ class Ui_Dialog(object):
self.spin_popup_h.setMaximum(10000) self.spin_popup_h.setMaximum(10000)
self.spin_popup_h.setObjectName("spin_popup_h") self.spin_popup_h.setObjectName("spin_popup_h")
self.horizontalLayout_4.addWidget(self.spin_popup_h) self.horizontalLayout_4.addWidget(self.spin_popup_h)
spacerItem4 = QtWidgets.QSpacerItem( spacerItem4 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum)
40,
20,
QtWidgets.QSizePolicy.Policy.Expanding,
QtWidgets.QSizePolicy.Policy.Minimum,
)
self.horizontalLayout_4.addItem(spacerItem4) self.horizontalLayout_4.addItem(spacerItem4)
self.gridLayout_2.addLayout(self.horizontalLayout_4, 0, 0, 1, 1) self.gridLayout_2.addLayout(self.horizontalLayout_4, 0, 0, 1, 1)
self.verticalLayout.addWidget(self.groupbox_image_popup) self.verticalLayout.addWidget(self.groupbox_image_popup)
@@ -249,12 +193,7 @@ class Ui_Dialog(object):
self.label_watchdog_interval_s = QtWidgets.QLabel(parent=self.groupbox_watchdog) self.label_watchdog_interval_s = QtWidgets.QLabel(parent=self.groupbox_watchdog)
self.label_watchdog_interval_s.setObjectName("label_watchdog_interval_s") self.label_watchdog_interval_s.setObjectName("label_watchdog_interval_s")
self.horizontalLayout_3.addWidget(self.label_watchdog_interval_s) self.horizontalLayout_3.addWidget(self.label_watchdog_interval_s)
spacerItem5 = QtWidgets.QSpacerItem( spacerItem5 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum)
40,
20,
QtWidgets.QSizePolicy.Policy.Expanding,
QtWidgets.QSizePolicy.Policy.Minimum,
)
self.horizontalLayout_3.addItem(spacerItem5) self.horizontalLayout_3.addItem(spacerItem5)
self.verticalLayout_3.addLayout(self.horizontalLayout_3) self.verticalLayout_3.addLayout(self.horizontalLayout_3)
self.verticalLayout.addWidget(self.groupbox_watchdog) self.verticalLayout.addWidget(self.groupbox_watchdog)
@@ -271,12 +210,7 @@ class Ui_Dialog(object):
self.label_cache = QtWidgets.QLabel(parent=self.groupBox_cache) self.label_cache = QtWidgets.QLabel(parent=self.groupBox_cache)
self.label_cache.setObjectName("label_cache") self.label_cache.setObjectName("label_cache")
self.horizontalLayout_6.addWidget(self.label_cache) self.horizontalLayout_6.addWidget(self.label_cache)
spacerItem6 = QtWidgets.QSpacerItem( spacerItem6 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum)
40,
20,
QtWidgets.QSizePolicy.Policy.Expanding,
QtWidgets.QSizePolicy.Policy.Minimum,
)
self.horizontalLayout_6.addItem(spacerItem6) self.horizontalLayout_6.addItem(spacerItem6)
self.verticalLayout.addWidget(self.groupBox_cache) self.verticalLayout.addWidget(self.groupBox_cache)
self.groupBox_logging = QtWidgets.QGroupBox(parent=self.tab_advanced) self.groupBox_logging = QtWidgets.QGroupBox(parent=self.tab_advanced)
@@ -286,12 +220,7 @@ class Ui_Dialog(object):
self.combo_logging = QtWidgets.QComboBox(parent=self.groupBox_logging) self.combo_logging = QtWidgets.QComboBox(parent=self.groupBox_logging)
self.combo_logging.setObjectName("combo_logging") self.combo_logging.setObjectName("combo_logging")
self.gridLayout_6.addWidget(self.combo_logging, 0, 1, 1, 1) self.gridLayout_6.addWidget(self.combo_logging, 0, 1, 1, 1)
spacerItem7 = QtWidgets.QSpacerItem( spacerItem7 = QtWidgets.QSpacerItem(190, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum)
190,
20,
QtWidgets.QSizePolicy.Policy.Expanding,
QtWidgets.QSizePolicy.Policy.Minimum,
)
self.gridLayout_6.addItem(spacerItem7, 0, 3, 1, 1) self.gridLayout_6.addItem(spacerItem7, 0, 3, 1, 1)
self.pb_open_log = QtWidgets.QPushButton(parent=self.groupBox_logging) self.pb_open_log = QtWidgets.QPushButton(parent=self.groupBox_logging)
self.pb_open_log.setMaximumSize(QtCore.QSize(30, 16777215)) self.pb_open_log.setMaximumSize(QtCore.QSize(30, 16777215))
@@ -301,12 +230,7 @@ class Ui_Dialog(object):
self.label_logging.setObjectName("label_logging") self.label_logging.setObjectName("label_logging")
self.gridLayout_6.addWidget(self.label_logging, 0, 0, 1, 1) self.gridLayout_6.addWidget(self.label_logging, 0, 0, 1, 1)
self.verticalLayout.addWidget(self.groupBox_logging) self.verticalLayout.addWidget(self.groupBox_logging)
spacerItem8 = QtWidgets.QSpacerItem( spacerItem8 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Policy.Minimum, QtWidgets.QSizePolicy.Policy.Expanding)
20,
40,
QtWidgets.QSizePolicy.Policy.Minimum,
QtWidgets.QSizePolicy.Policy.Expanding,
)
self.verticalLayout.addItem(spacerItem8) self.verticalLayout.addItem(spacerItem8)
self.tabWidget.addTab(self.tab_advanced, "") self.tabWidget.addTab(self.tab_advanced, "")
self.gridLayout.addWidget(self.tabWidget, 0, 0, 1, 5) self.gridLayout.addWidget(self.tabWidget, 0, 0, 1, 5)
@@ -337,9 +261,7 @@ class Ui_Dialog(object):
Dialog.setTabOrder(self.spin_duration, self.cb_notify) Dialog.setTabOrder(self.spin_duration, self.cb_notify)
Dialog.setTabOrder(self.cb_notify, self.cb_notification_click) Dialog.setTabOrder(self.cb_notify, self.cb_notification_click)
Dialog.setTabOrder(self.cb_notification_click, self.cb_tray_icon_unread) Dialog.setTabOrder(self.cb_notification_click, self.cb_tray_icon_unread)
Dialog.setTabOrder(self.cb_tray_icon_unread, self.cb_priority10_persistent) Dialog.setTabOrder(self.cb_tray_icon_unread, self.cb_priority_colors)
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_priority_colors, self.cb_image_urls)
Dialog.setTabOrder(self.cb_image_urls, self.cb_locale) Dialog.setTabOrder(self.cb_image_urls, self.cb_locale)
Dialog.setTabOrder(self.cb_locale, self.cb_sort_applications) Dialog.setTabOrder(self.cb_locale, self.cb_sort_applications)
@@ -365,88 +287,41 @@ class Ui_Dialog(object):
_translate = QtCore.QCoreApplication.translate _translate = QtCore.QCoreApplication.translate
Dialog.setWindowTitle(_translate("Dialog", "Dialog")) Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
self.groupBox_notifications.setTitle(_translate("Dialog", "Notifications")) self.groupBox_notifications.setTitle(_translate("Dialog", "Notifications"))
self.label_notification_duration.setText( self.label_notification_duration.setText(_translate("Dialog", "Notification duration:"))
_translate("Dialog", "Notification duration:") self.cb_notification_click.setText(_translate("Dialog", "Clicking the notification pop-up opens the main window"))
)
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.label_notification_duration_ms.setText(_translate("Dialog", "ms"))
self.cb_notify.setText( self.cb_notify.setText(_translate("Dialog", "Show a notification for missed messages after reconnecting"))
_translate( self.label_notification_priority.setText(_translate("Dialog", "Minimum priority to show notifications:"))
"Dialog", "Show a notification for missed messages after reconnecting" 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", "Show persistent notifications for priority 10 messages"))
)
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.groupBox_2.setTitle(_translate("Dialog", "Interface"))
self.cb_priority_colors.setToolTip( self.cb_priority_colors.setToolTip(_translate("Dialog", "4..7 -> medium\n"
_translate("Dialog", "4..7 -> medium\n8..10 -> high") "8..10 -> high"))
) self.cb_priority_colors.setText(_translate("Dialog", "Show message priority colors"))
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_image_urls.setText(_translate("Dialog", "Show image urls as images"))
self.cb_locale.setText( self.cb_locale.setText(_translate("Dialog", "Display date in the system locale format"))
_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_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.pb_change_server_info.setText(_translate("Dialog", "Change server info"))
self.tabWidget.setTabText( self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_general), _translate("Dialog", "General"))
self.tabWidget.indexOf(self.tab_general), _translate("Dialog", "General")
)
self.pb_reset_fonts.setText(_translate("Dialog", "Reset all fonts")) self.pb_reset_fonts.setText(_translate("Dialog", "Reset all fonts"))
self.groupBox_fonts_message.setTitle(_translate("Dialog", "Message")) self.groupBox_fonts_message.setTitle(_translate("Dialog", "Message"))
self.pb_font_message_title.setText(_translate("Dialog", "Title")) self.pb_font_message_title.setText(_translate("Dialog", "Title"))
self.pb_font_message_date.setText(_translate("Dialog", "Date")) self.pb_font_message_date.setText(_translate("Dialog", "Date"))
self.pb_font_message_content.setText(_translate("Dialog", "Message")) self.pb_font_message_content.setText(_translate("Dialog", "Message"))
self.tabWidget.setTabText( self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_fonts), _translate("Dialog", "Fonts"))
self.tabWidget.indexOf(self.tab_fonts), _translate("Dialog", "Fonts")
)
self.groupBox.setTitle(_translate("Dialog", "Settings")) self.groupBox.setTitle(_translate("Dialog", "Settings"))
self.pb_reset.setText(_translate("Dialog", "Reset")) self.pb_reset.setText(_translate("Dialog", "Reset"))
self.pb_import.setText(_translate("Dialog", "Import")) self.pb_import.setText(_translate("Dialog", "Import"))
self.pb_export.setText(_translate("Dialog", "Export")) self.pb_export.setText(_translate("Dialog", "Export"))
self.groupbox_image_popup.setTitle( self.groupbox_image_popup.setTitle(_translate("Dialog", "Image pop-up for URLs"))
_translate("Dialog", "Image pop-up for URLs")
)
self.label.setToolTip(_translate("Dialog", "Maximum pop-up width")) self.label.setToolTip(_translate("Dialog", "Maximum pop-up width"))
self.label.setText(_translate("Dialog", "Width")) self.label.setText(_translate("Dialog", "Width"))
self.spin_popup_w.setToolTip(_translate("Dialog", "Maximum pop-up 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.setToolTip(_translate("Dialog", "Maximum pop-up height"))
self.label_2.setText(_translate("Dialog", "Height")) self.label_2.setText(_translate("Dialog", "Height"))
self.spin_popup_h.setToolTip(_translate("Dialog", "Maximum pop-up height")) self.spin_popup_h.setToolTip(_translate("Dialog", "Maximum pop-up height"))
self.groupbox_watchdog.setTitle( self.groupbox_watchdog.setTitle(_translate("Dialog", "Server watchdog thread (requires restart)"))
_translate("Dialog", "Server watchdog thread (requires restart)")
)
self.label_watchdog_interval.setText(_translate("Dialog", "Interval:")) self.label_watchdog_interval.setText(_translate("Dialog", "Interval:"))
self.label_watchdog_interval_s.setText(_translate("Dialog", "s")) self.label_watchdog_interval_s.setText(_translate("Dialog", "s"))
self.groupBox_cache.setTitle(_translate("Dialog", "Cache")) self.groupBox_cache.setTitle(_translate("Dialog", "Cache"))
@@ -457,14 +332,11 @@ class Ui_Dialog(object):
self.pb_open_log.setToolTip(_translate("Dialog", "Open logfile")) self.pb_open_log.setToolTip(_translate("Dialog", "Open logfile"))
self.pb_open_log.setText(_translate("Dialog", "...")) self.pb_open_log.setText(_translate("Dialog", "..."))
self.label_logging.setText(_translate("Dialog", "Level")) self.label_logging.setText(_translate("Dialog", "Level"))
self.tabWidget.setTabText( self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_advanced), _translate("Dialog", "Advanced"))
self.tabWidget.indexOf(self.tab_advanced), _translate("Dialog", "Advanced")
)
if __name__ == "__main__": if __name__ == "__main__":
import sys import sys
app = QtWidgets.QApplication(sys.argv) app = QtWidgets.QApplication(sys.argv)
Dialog = QtWidgets.QDialog() Dialog = QtWidgets.QDialog()
ui = Ui_Dialog() ui = Ui_Dialog()

View File

@@ -121,6 +121,13 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="5" column="0" colspan="3">
<widget class="QCheckBox" name="cb_priority10_persistent">
<property name="text">
<string>Show persistent notifications for priority 10 messages</string>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
</item> </item>

View File

@@ -1,5 +1,4 @@
import enum import enum
from typing import cast from typing import cast
from PyQt6 import QtCore, QtGui from PyQt6 import QtCore, QtGui
from gotify_tray import gotify from gotify_tray import gotify
@@ -39,3 +38,34 @@ class MessagesModel(QtGui.QStandardItemModel):
def itemFromIndex(self, index: QtCore.QModelIndex) -> MessagesModelItem: def itemFromIndex(self, index: QtCore.QModelIndex) -> MessagesModelItem:
return cast(MessagesModelItem, super(MessagesModel, self).itemFromIndex(index)) return cast(MessagesModelItem, super(MessagesModel, self).itemFromIndex(index))
class MessagesProxyModel(QtCore.QSortFilterProxyModel):
def __init__(self, parent=None):
super().__init__(parent)
self.allowed_priorities = set(range(11)) # 0-10
self.text_filter = ""
def set_allowed_priorities(self, priorities: set[int]):
self.allowed_priorities = priorities
self.invalidateFilter()
def set_text_filter(self, text: str):
self.text_filter = text.lower()
self.invalidateFilter()
def filterAcceptsRow(
self, source_row: int, source_parent: QtCore.QModelIndex
) -> bool:
index = self.sourceModel().index(source_row, 0, source_parent)
item = self.sourceModel().itemFromIndex(index)
message = item.data(MessageItemDataRole.MessageRole)
priority = message.priority if message.priority is not None else 0
if self.allowed_priorities and priority not in self.allowed_priorities:
return False
if self.text_filter:
title = (message.title or "").lower()
msg = message.message.lower()
if self.text_filter not in title and self.text_filter not in msg:
return False
return True

View File

@@ -5,4 +5,9 @@ from .ApplicationModel import (
ApplicationProxyModel, ApplicationProxyModel,
ApplicationItemDataRole, ApplicationItemDataRole,
) )
from .MessagesModel import MessagesModelItem, MessagesModel, MessageItemDataRole from .MessagesModel import (
MessagesModelItem,
MessagesModel,
MessagesProxyModel,
MessageItemDataRole,
)

View File

@@ -5,6 +5,7 @@ from ..models import (
ApplicationModel, ApplicationModel,
MessagesModel, MessagesModel,
MessagesModelItem, MessagesModelItem,
MessagesProxyModel,
) )
from . import MessageWidget from . import MessageWidget
@@ -26,8 +27,15 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
image_popup = QtCore.pyqtSignal(str, QtCore.QPoint) image_popup = QtCore.pyqtSignal(str, QtCore.QPoint)
hidden = QtCore.pyqtSignal() hidden = QtCore.pyqtSignal()
activated = QtCore.pyqtSignal() activated = QtCore.pyqtSignal()
priority_filter_changed = QtCore.pyqtSignal(set)
def __init__(self, application_model: ApplicationModel, application_proxy_model: QtCore.QSortFilterProxyModel, messages_model: MessagesModel): def __init__(
self,
application_model: ApplicationModel,
application_proxy_model: QtCore.QSortFilterProxyModel,
messages_model: MessagesModel,
messages_proxy_model: MessagesProxyModel,
):
super(MainWindow, self).__init__() super(MainWindow, self).__init__()
self.setupUi(self) self.setupUi(self)
@@ -38,9 +46,13 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
self.application_model = application_model self.application_model = application_model
self.application_proxy_model = application_proxy_model self.application_proxy_model = application_proxy_model
self.messages_model = messages_model self.messages_model = messages_model
self.messages_proxy_model = messages_proxy_model
self.listView_applications.setModel(application_proxy_model) self.listView_applications.setModel(application_proxy_model)
self.listView_messages.setModel(messages_model) self.listView_messages.setModel(messages_proxy_model)
self.messages_proxy_model.rowsInserted.connect(self.display_message_widgets)
self.messages_proxy_model.layoutChanged.connect(self.redisplay_message_widgets)
# Do not expand the applications listview when resizing # Do not expand the applications listview when resizing
self.splitter.setStretchFactor(0, 0) self.splitter.setStretchFactor(0, 0)
@@ -69,9 +81,32 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
self.link_callbacks() self.link_callbacks()
# Setup filters
self.pb_low.toggled.connect(self.on_priority_button_toggled)
self.pb_normal.toggled.connect(self.on_priority_button_toggled)
self.pb_high.toggled.connect(self.on_priority_button_toggled)
# Critical is always shown, no toggle
# Set styles for priority buttons
button_style = "QPushButton { background-color: grey; border: 1px solid black; } QPushButton:checked { background-color: green; }"
self.pb_low.setStyleSheet(button_style)
self.pb_normal.setStyleSheet(button_style)
self.pb_high.setStyleSheet(button_style)
# Critical always green
self.pb_critical.setStyleSheet(
"QPushButton { background-color: green; border: 1px solid black; }"
)
self.pb_critical.setChecked(True)
self.pb_critical.setCheckable(False)
self.pb_remove_filters.clicked.connect(self.on_remove_filters_clicked)
self.le_search.returnPressed.connect(self.on_search_return_pressed)
# set refresh shortcut (usually ctrl-r) # set refresh shortcut (usually ctrl-r)
# unfortunately this cannot be done with designer # unfortunately this cannot be done with designer
self.pb_refresh.setShortcut(QtGui.QKeySequence(QtGui.QKeySequence.StandardKey.Refresh)) self.pb_refresh.setShortcut(
QtGui.QKeySequence(QtGui.QKeySequence.StandardKey.Refresh)
)
def set_icons(self): def set_icons(self):
# Set button icons # Set button icons
@@ -106,20 +141,36 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
def set_error(self): def set_error(self):
self.status_widget.set_error() self.status_widget.set_error()
def display_message_widgets(self, parent: QtCore.QModelIndex, first: int, last: int): def display_message_widgets(
self, parent: QtCore.QModelIndex, first: int, last: int
):
for i in range(first, last + 1): for i in range(first, last + 1):
if index := self.messages_model.index(i, 0, parent): if proxy_index := self.messages_proxy_model.index(i, 0, parent):
message_item = self.messages_model.itemFromIndex(index) source_index = self.messages_proxy_model.mapToSource(proxy_index)
message_item = self.messages_model.itemFromIndex(source_index)
message: gotify.GotifyMessageModel = self.messages_model.data(index, MessageItemDataRole.MessageRole) message: gotify.GotifyMessageModel = message_item.data(
MessageItemDataRole.MessageRole
)
application_item = self.application_model.itemFromId(message.appid) application_item = self.application_model.itemFromId(message.appid)
message_widget = MessageWidget(self.listView_messages, message_item, icon=application_item.icon()) message_widget = MessageWidget(
self.listView_messages, message_item, icon=application_item.icon()
)
message_widget.deletion_requested.connect(self.delete_message.emit) message_widget.deletion_requested.connect(self.delete_message.emit)
message_widget.image_popup.connect(self.image_popup.emit) message_widget.image_popup.connect(self.image_popup.emit)
self.listView_messages.setIndexWidget(index, message_widget) self.listView_messages.setIndexWidget(proxy_index, message_widget)
def redisplay_message_widgets(self):
# Clear existing widgets
for row in range(self.messages_proxy_model.rowCount()):
index = self.messages_proxy_model.index(row, 0)
self.listView_messages.setIndexWidget(index, None)
# Redisplay for current visible rows
self.display_message_widgets(
QtCore.QModelIndex(), 0, self.messages_proxy_model.rowCount() - 1
)
def currentApplicationIndex(self) -> QtCore.QModelIndex: def currentApplicationIndex(self) -> QtCore.QModelIndex:
return self.listView_applications.selectionModel().currentIndex() return self.listView_applications.selectionModel().currentIndex()
@@ -127,13 +178,15 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
def application_selection_changed_callback( def application_selection_changed_callback(
self, current: QtCore.QModelIndex, previous: QtCore.QModelIndex self, current: QtCore.QModelIndex, previous: QtCore.QModelIndex
): ):
if item := self.application_model.itemFromIndex(self.application_proxy_model.mapToSource(current)): if item := self.application_model.itemFromIndex(
self.application_proxy_model.mapToSource(current)
):
self.label_application.setText(item.text()) self.label_application.setText(item.text())
self.application_selection_changed.emit(item) self.application_selection_changed.emit(item)
def delete_all_callback(self): def delete_all_callback(self):
if ( if (
self.messages_model.rowCount() == 0 self.messages_proxy_model.rowCount() == 0
or QtWidgets.QMessageBox.warning( or QtWidgets.QMessageBox.warning(
self, self,
"Are you sure?", "Are you sure?",
@@ -147,7 +200,9 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
return return
index = self.currentApplicationIndex() index = self.currentApplicationIndex()
if item := self.application_model.itemFromIndex(self.application_proxy_model.mapToSource(index)): if item := self.application_model.itemFromIndex(
self.application_proxy_model.mapToSource(index)
):
self.delete_all.emit(item) self.delete_all.emit(item)
def disable_applications(self): def disable_applications(self):
@@ -156,7 +211,9 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
def enable_applications(self): def enable_applications(self):
self.listView_applications.setEnabled(True) self.listView_applications.setEnabled(True)
self.listView_applications.setCurrentIndex(self.application_proxy_model.index(0, 0)) self.listView_applications.setCurrentIndex(
self.application_proxy_model.index(0, 0)
)
def disable_buttons(self): def disable_buttons(self):
self.pb_delete_all.setDisabled(True) self.pb_delete_all.setDisabled(True)
@@ -181,7 +238,9 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
self.pb_refresh.clicked.connect(self.refresh.emit) self.pb_refresh.clicked.connect(self.refresh.emit)
self.pb_delete_all.clicked.connect(self.delete_all_callback) self.pb_delete_all.clicked.connect(self.delete_all_callback)
self.listView_applications.selectionModel().currentChanged.connect(self.application_selection_changed_callback) self.listView_applications.selectionModel().currentChanged.connect(
self.application_selection_changed_callback
)
def store_state(self): def store_state(self):
settings.setValue("MainWindow/geometry", self.saveGeometry()) settings.setValue("MainWindow/geometry", self.saveGeometry())
@@ -206,3 +265,27 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
self.activated.emit() self.activated.emit()
return super().eventFilter(object, event) return super().eventFilter(object, event)
def on_priority_button_toggled(self, checked):
priorities = {10} # Critical always included
if self.pb_low.isChecked():
priorities.update({0, 1, 2, 3})
if self.pb_normal.isChecked():
priorities.update({4, 5, 6, 7, 8})
if self.pb_high.isChecked():
priorities.add(9)
self.priority_filter_changed.emit(priorities)
def on_remove_filters_clicked(self):
# Reset priority buttons
self.pb_low.setChecked(True)
self.pb_normal.setChecked(True)
self.pb_high.setChecked(True)
# Critical is always on
# Clear search
self.le_search.clear()
self.messages_proxy_model.set_text_filter("")
def on_search_return_pressed(self):
text = self.le_search.text()
self.messages_proxy_model.set_text_filter(text)

View File

@@ -75,10 +75,6 @@ class SettingsDialog(QtWidgets.QDialog, Ui_Dialog):
settings.value("tray/notifications/priority10_persistent", type=bool) settings.value("tray/notifications/priority10_persistent", type=bool)
) )
self.cb_sound_only_priority10.setChecked(
settings.value("tray/notifications/sound_only_priority10", type=bool)
)
# Interface # Interface
self.cb_priority_colors.setChecked( self.cb_priority_colors.setChecked(
settings.value("MessageWidget/priority_color", type=bool) settings.value("MessageWidget/priority_color", type=bool)
@@ -259,9 +255,6 @@ class SettingsDialog(QtWidgets.QDialog, Ui_Dialog):
self.connect_signal( self.connect_signal(
self.cb_priority10_persistent.stateChanged, self.cb_priority10_persistent self.cb_priority10_persistent.stateChanged, self.cb_priority10_persistent
) )
self.connect_signal(
self.cb_sound_only_priority10.stateChanged, self.cb_sound_only_priority10
)
# Interface # Interface
self.connect_signal( self.connect_signal(
@@ -341,13 +334,18 @@ class SettingsDialog(QtWidgets.QDialog, Ui_Dialog):
self.cb_priority10_persistent.isChecked(), self.cb_priority10_persistent.isChecked(),
self.cb_priority10_persistent, self.cb_priority10_persistent,
) )
self.set_value(
"tray/notifications/sound_only_priority10",
self.cb_sound_only_priority10.isChecked(),
self.cb_sound_only_priority10,
)
# Interface # Interface
self.set_value(
"tray/notifications/priority10_persistent",
True, # Always persistent for priority 10
None,
)
self.set_value(
"tray/notifications/sound_only_priority10",
False, # Not sound only
None,
)
self.set_value( self.set_value(
"MessageWidget/priority_color", "MessageWidget/priority_color",
self.cb_priority_colors.isChecked(), self.cb_priority_colors.isChecked(),