allow reordering of applications
This commit is contained in:
@@ -1,6 +1,17 @@
|
|||||||
|
import enum
|
||||||
|
|
||||||
from typing import Optional, Union
|
from typing import Optional, Union
|
||||||
from PyQt6 import QtCore, QtGui
|
from PyQt6 import QtCore, QtGui
|
||||||
from gotify_tray import gotify
|
from gotify_tray import gotify
|
||||||
|
from gotify_tray.database import Settings
|
||||||
|
|
||||||
|
|
||||||
|
settings = Settings("gotify-tray")
|
||||||
|
|
||||||
|
|
||||||
|
class ApplicationItemDataRole(enum.IntEnum):
|
||||||
|
ApplicationRole = QtCore.Qt.ItemDataRole.UserRole + 1
|
||||||
|
IconRole = QtCore.Qt.ItemDataRole.UserRole + 2
|
||||||
|
|
||||||
|
|
||||||
class ApplicationModelItem(QtGui.QStandardItem):
|
class ApplicationModelItem(QtGui.QStandardItem):
|
||||||
@@ -12,18 +23,39 @@ class ApplicationModelItem(QtGui.QStandardItem):
|
|||||||
**kwargs
|
**kwargs
|
||||||
):
|
):
|
||||||
super(ApplicationModelItem, self).__init__(application.name)
|
super(ApplicationModelItem, self).__init__(application.name)
|
||||||
self.application = application
|
self.setDropEnabled(False)
|
||||||
|
self.setData(application, ApplicationItemDataRole.ApplicationRole)
|
||||||
|
self.setData(icon, ApplicationItemDataRole.IconRole)
|
||||||
if icon:
|
if icon:
|
||||||
self.setIcon(icon)
|
self.setIcon(icon)
|
||||||
|
|
||||||
|
def clone(self):
|
||||||
|
return ApplicationModelItem(
|
||||||
|
self.data(ApplicationItemDataRole.ApplicationRole),
|
||||||
|
self.data(ApplicationItemDataRole.IconRole),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class ApplicationAllMessagesItem(QtGui.QStandardItem):
|
class ApplicationAllMessagesItem(QtGui.QStandardItem):
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super(ApplicationAllMessagesItem, self).__init__("ALL MESSAGES")
|
super(ApplicationAllMessagesItem, self).__init__("ALL MESSAGES")
|
||||||
|
self.setDropEnabled(False)
|
||||||
|
self.setDragEnabled(False)
|
||||||
|
|
||||||
|
|
||||||
class ApplicationModel(QtGui.QStandardItemModel):
|
class ApplicationModel(QtGui.QStandardItemModel):
|
||||||
def setItem(self, row: int, column: int, item: Union[ApplicationModelItem, ApplicationAllMessagesItem]) -> None:
|
def __init__(self):
|
||||||
|
super(ApplicationModel, self).__init__()
|
||||||
|
self.setItemPrototype(
|
||||||
|
ApplicationModelItem(gotify.GotifyApplicationModel({"name": ""}), None)
|
||||||
|
)
|
||||||
|
|
||||||
|
def setItem(
|
||||||
|
self,
|
||||||
|
row: int,
|
||||||
|
column: int,
|
||||||
|
item: Union[ApplicationModelItem, ApplicationAllMessagesItem],
|
||||||
|
) -> None:
|
||||||
super(ApplicationModel, self).setItem(row, column, item)
|
super(ApplicationModel, self).setItem(row, column, item)
|
||||||
|
|
||||||
def itemFromIndex(
|
def itemFromIndex(
|
||||||
@@ -36,6 +68,17 @@ class ApplicationModel(QtGui.QStandardItemModel):
|
|||||||
item = self.item(row, 0)
|
item = self.item(row, 0)
|
||||||
if not isinstance(item, ApplicationModelItem):
|
if not isinstance(item, ApplicationModelItem):
|
||||||
continue
|
continue
|
||||||
if item.application.id == appid:
|
if item.data(ApplicationItemDataRole.ApplicationRole).id == appid:
|
||||||
return item
|
return item
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def save_order(self, *args):
|
||||||
|
try:
|
||||||
|
application_ids = [
|
||||||
|
self.item(i, 0).data(ApplicationItemDataRole.ApplicationRole).id
|
||||||
|
for i in range(1, self.rowCount())
|
||||||
|
]
|
||||||
|
except AttributeError:
|
||||||
|
return
|
||||||
|
|
||||||
|
settings.setValue("ApplicationModel/order", application_ids)
|
||||||
|
|||||||
@@ -18,13 +18,14 @@ from PyQt6 import QtCore, QtGui, QtWidgets
|
|||||||
|
|
||||||
from ..__version__ import __title__
|
from ..__version__ import __title__
|
||||||
from .ApplicationModel import (
|
from .ApplicationModel import (
|
||||||
|
ApplicationItemDataRole,
|
||||||
ApplicationAllMessagesItem,
|
ApplicationAllMessagesItem,
|
||||||
ApplicationModel,
|
ApplicationModel,
|
||||||
ApplicationModelItem,
|
ApplicationModelItem,
|
||||||
)
|
)
|
||||||
from .designs.widget_main import Ui_Form as Ui_Main
|
from .designs.widget_main import Ui_Form as Ui_Main
|
||||||
from .themes import set_theme
|
from .themes import set_theme
|
||||||
from .MessagesModel import MessagesModel, MessagesModelItem
|
from .MessagesModel import MessageItemDataRole, MessagesModel, MessagesModelItem
|
||||||
from .MessageWidget import MessageWidget
|
from .MessageWidget import MessageWidget
|
||||||
from .SettingsDialog import SettingsDialog
|
from .SettingsDialog import SettingsDialog
|
||||||
from .Tray import Tray
|
from .Tray import Tray
|
||||||
@@ -126,7 +127,32 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||||||
def get_applications_callback(
|
def get_applications_callback(
|
||||||
applications: List[gotify.GotifyApplicationModel],
|
applications: List[gotify.GotifyApplicationModel],
|
||||||
):
|
):
|
||||||
for i, application in enumerate(applications):
|
stored_application_ids_order = [
|
||||||
|
int(x) for x in settings.value("ApplicationModel/order", type=list)
|
||||||
|
]
|
||||||
|
fetched_application_ids = [application.id for application in applications]
|
||||||
|
# Remove ids from stored_application_ids that are not in fetched_application_ids
|
||||||
|
application_ids_order = list(
|
||||||
|
filter(
|
||||||
|
lambda x: x in fetched_application_ids, stored_application_ids_order
|
||||||
|
)
|
||||||
|
)
|
||||||
|
# Add new ids to the back of the list
|
||||||
|
application_ids_order += list(
|
||||||
|
filter(
|
||||||
|
lambda x: x not in stored_application_ids_order,
|
||||||
|
fetched_application_ids,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
for i, application_id in enumerate(application_ids_order):
|
||||||
|
application = list(
|
||||||
|
filter(
|
||||||
|
lambda application: application.id == application_id,
|
||||||
|
applications,
|
||||||
|
)
|
||||||
|
)[0]
|
||||||
|
|
||||||
icon = (
|
icon = (
|
||||||
QtGui.QIcon(
|
QtGui.QIcon(
|
||||||
downloader.get_filename(
|
downloader.get_filename(
|
||||||
@@ -140,6 +166,8 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||||||
i + 1, 0, ApplicationModelItem(application, icon),
|
i + 1, 0, ApplicationModelItem(application, icon),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
self.application_model.save_order()
|
||||||
|
|
||||||
self.get_applications_task = GetApplicationsTask(self.gotify_client)
|
self.get_applications_task = GetApplicationsTask(self.gotify_client)
|
||||||
self.get_applications_task.success.connect(get_applications_callback)
|
self.get_applications_task.success.connect(get_applications_callback)
|
||||||
self.get_applications_task.finished.connect(
|
self.get_applications_task.finished.connect(
|
||||||
@@ -200,10 +228,15 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||||||
page: gotify.GotifyPagedMessagesModel,
|
page: gotify.GotifyPagedMessagesModel,
|
||||||
):
|
):
|
||||||
for i, message in enumerate(page.messages):
|
for i, message in enumerate(page.messages):
|
||||||
self.insert_message(i, message, item.application)
|
self.insert_message(
|
||||||
|
i,
|
||||||
|
message,
|
||||||
|
item.data(ApplicationItemDataRole.ApplicationRole),
|
||||||
|
)
|
||||||
|
|
||||||
self.get_application_messages_task = GetApplicationMessagesTask(
|
self.get_application_messages_task = GetApplicationMessagesTask(
|
||||||
item.application.id, self.gotify_client
|
item.data(ApplicationItemDataRole.ApplicationRole).id,
|
||||||
|
self.gotify_client,
|
||||||
)
|
)
|
||||||
self.get_application_messages_task.success.connect(
|
self.get_application_messages_task.success.connect(
|
||||||
get_application_messages_callback
|
get_application_messages_callback
|
||||||
@@ -215,16 +248,18 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||||||
def get_messages_callback(page: gotify.GotifyPagedMessagesModel):
|
def get_messages_callback(page: gotify.GotifyPagedMessagesModel):
|
||||||
for i, message in enumerate(page.messages):
|
for i, message in enumerate(page.messages):
|
||||||
if item := self.application_model.itemFromId(message.appid):
|
if item := self.application_model.itemFromId(message.appid):
|
||||||
self.insert_message(i, message, item.application)
|
self.insert_message(
|
||||||
|
i,
|
||||||
|
message,
|
||||||
|
item.data(ApplicationItemDataRole.ApplicationRole),
|
||||||
|
)
|
||||||
|
|
||||||
self.get_messages_task = GetMessagesTask(self.gotify_client)
|
self.get_messages_task = GetMessagesTask(self.gotify_client)
|
||||||
self.get_messages_task.success.connect(get_messages_callback)
|
self.get_messages_task.success.connect(get_messages_callback)
|
||||||
self.get_messages_task.start()
|
self.get_messages_task.start()
|
||||||
|
|
||||||
def refresh_callback(self):
|
def refresh_callback(self):
|
||||||
self.application_model.clear()
|
self.application_model.save_order()
|
||||||
self.messages_model.clear()
|
|
||||||
|
|
||||||
self.refresh_applications()
|
self.refresh_applications()
|
||||||
if not self.gotify_client.listener.running:
|
if not self.gotify_client.listener.running:
|
||||||
self.gotify_client.listener.reset_wait_time()
|
self.gotify_client.listener.reset_wait_time()
|
||||||
@@ -239,7 +274,8 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||||||
|
|
||||||
if isinstance(item, ApplicationModelItem):
|
if isinstance(item, ApplicationModelItem):
|
||||||
self.delete_application_messages_task = DeleteApplicationMessagesTask(
|
self.delete_application_messages_task = DeleteApplicationMessagesTask(
|
||||||
item.application.id, self.gotify_client
|
item.data(ApplicationItemDataRole.ApplicationRole).id,
|
||||||
|
self.gotify_client,
|
||||||
)
|
)
|
||||||
self.delete_application_messages_task.start()
|
self.delete_application_messages_task.start()
|
||||||
elif isinstance(item, ApplicationAllMessagesItem):
|
elif isinstance(item, ApplicationAllMessagesItem):
|
||||||
@@ -254,13 +290,14 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||||||
logger.error(
|
logger.error(
|
||||||
f"MainWindow.new_message_callback: App id {message.appid} could not be found. Refreshing applications."
|
f"MainWindow.new_message_callback: App id {message.appid} could not be found. Refreshing applications."
|
||||||
)
|
)
|
||||||
|
self.application_model.save_order()
|
||||||
self.refresh_applications()
|
self.refresh_applications()
|
||||||
return
|
return
|
||||||
|
|
||||||
if not self.isActiveWindow() and message.priority >= settings.value(
|
if not self.isActiveWindow() and message.priority >= settings.value(
|
||||||
"tray/notifications/priority", type=int
|
"tray/notifications/priority", type=int
|
||||||
):
|
):
|
||||||
image_url = f"{self.gotify_client.url}/{application_item.application.image}"
|
image_url = f"{self.gotify_client.url}/{application_item.data(ApplicationItemDataRole.ApplicationRole).image}"
|
||||||
self.tray.showMessage(
|
self.tray.showMessage(
|
||||||
message.title,
|
message.title,
|
||||||
message.message,
|
message.message,
|
||||||
@@ -279,17 +316,30 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||||||
):
|
):
|
||||||
if isinstance(selected_application_item, ApplicationModelItem):
|
if isinstance(selected_application_item, ApplicationModelItem):
|
||||||
# A single application is selected
|
# A single application is selected
|
||||||
if message.appid == selected_application_item.application.id:
|
if (
|
||||||
self.insert_message(0, message, application_item.application)
|
message.appid
|
||||||
|
== selected_application_item.data(
|
||||||
|
ApplicationItemDataRole.ApplicationRole
|
||||||
|
).id
|
||||||
|
):
|
||||||
|
self.insert_message(
|
||||||
|
0,
|
||||||
|
message,
|
||||||
|
application_item.data(ApplicationItemDataRole.ApplicationRole),
|
||||||
|
)
|
||||||
elif isinstance(selected_application_item, ApplicationAllMessagesItem):
|
elif isinstance(selected_application_item, ApplicationAllMessagesItem):
|
||||||
# "All messages' is selected
|
# "All messages' is selected
|
||||||
self.insert_message(0, message, application_item.application)
|
self.insert_message(
|
||||||
|
0,
|
||||||
|
message,
|
||||||
|
application_item.data(ApplicationItemDataRole.ApplicationRole),
|
||||||
|
)
|
||||||
|
|
||||||
def message_deletion_requested_callback(self, message_item: MessagesModelItem):
|
def message_deletion_requested_callback(self, message_item: MessagesModelItem):
|
||||||
self.messages_model.removeRow(message_item.row())
|
|
||||||
self.delete_message_task = DeleteMessageTask(
|
self.delete_message_task = DeleteMessageTask(
|
||||||
message_item.message.id, self.gotify_client
|
message_item.data(MessageItemDataRole.MessageRole).id, self.gotify_client
|
||||||
)
|
)
|
||||||
|
self.messages_model.removeRow(message_item.row())
|
||||||
self.delete_message_task.start()
|
self.delete_message_task.start()
|
||||||
|
|
||||||
def tray_activated_callback(
|
def tray_activated_callback(
|
||||||
@@ -392,6 +442,7 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||||||
|
|
||||||
def closeEvent(self, e: QtGui.QCloseEvent) -> None:
|
def closeEvent(self, e: QtGui.QCloseEvent) -> None:
|
||||||
self.save_window_state()
|
self.save_window_state()
|
||||||
|
self.application_model.save_order()
|
||||||
|
|
||||||
if settings.value("tray/show", type=bool):
|
if settings.value("tray/show", type=bool):
|
||||||
self.tray.hide()
|
self.tray.hide()
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import re
|
|||||||
|
|
||||||
from PyQt6 import QtCore, QtGui, QtWidgets
|
from PyQt6 import QtCore, QtGui, QtWidgets
|
||||||
|
|
||||||
from .MessagesModel import MessagesModelItem
|
from .MessagesModel import MessageItemDataRole, MessagesModelItem
|
||||||
from .designs.widget_message import Ui_Form
|
from .designs.widget_message import Ui_Form
|
||||||
from gotify_tray.database import Settings
|
from gotify_tray.database import Settings
|
||||||
|
|
||||||
@@ -36,7 +36,7 @@ class MessageWidget(QtWidgets.QWidget, Ui_Form):
|
|||||||
self.setAutoFillBackground(True)
|
self.setAutoFillBackground(True)
|
||||||
|
|
||||||
self.message_item = message_item
|
self.message_item = message_item
|
||||||
message = self.message_item.message
|
message = message_item.data(MessageItemDataRole.MessageRole)
|
||||||
|
|
||||||
# Fonts
|
# Fonts
|
||||||
font_title = QtGui.QFont()
|
font_title = QtGui.QFont()
|
||||||
|
|||||||
@@ -1,12 +1,18 @@
|
|||||||
|
import enum
|
||||||
|
|
||||||
from typing import cast
|
from typing import cast
|
||||||
from PyQt6 import QtCore, QtGui, QtWidgets
|
from PyQt6 import QtCore, QtGui, QtWidgets
|
||||||
from gotify_tray import gotify
|
from gotify_tray import gotify
|
||||||
|
|
||||||
|
|
||||||
|
class MessageItemDataRole(enum.IntEnum):
|
||||||
|
MessageRole = QtCore.Qt.ItemDataRole.UserRole + 1
|
||||||
|
|
||||||
|
|
||||||
class MessagesModelItem(QtGui.QStandardItem):
|
class MessagesModelItem(QtGui.QStandardItem):
|
||||||
def __init__(self, message: gotify.GotifyMessageModel, *args, **kwargs):
|
def __init__(self, message: gotify.GotifyMessageModel, *args, **kwargs):
|
||||||
super(MessagesModelItem, self).__init__()
|
super(MessagesModelItem, self).__init__()
|
||||||
self.message = message
|
self.setData(message, MessageItemDataRole.MessageRole)
|
||||||
|
|
||||||
|
|
||||||
class MessagesModel(QtGui.QStandardItemModel):
|
class MessagesModel(QtGui.QStandardItemModel):
|
||||||
|
|||||||
@@ -25,6 +25,8 @@ class Ui_Form(object):
|
|||||||
font.setPointSize(13)
|
font.setPointSize(13)
|
||||||
self.listView_applications.setFont(font)
|
self.listView_applications.setFont(font)
|
||||||
self.listView_applications.setEditTriggers(QtWidgets.QAbstractItemView.EditTrigger.NoEditTriggers)
|
self.listView_applications.setEditTriggers(QtWidgets.QAbstractItemView.EditTrigger.NoEditTriggers)
|
||||||
|
self.listView_applications.setDragEnabled(True)
|
||||||
|
self.listView_applications.setDragDropMode(QtWidgets.QAbstractItemView.DragDropMode.InternalMove)
|
||||||
self.listView_applications.setWordWrap(True)
|
self.listView_applications.setWordWrap(True)
|
||||||
self.listView_applications.setObjectName("listView_applications")
|
self.listView_applications.setObjectName("listView_applications")
|
||||||
self.gridLayout_2.addWidget(self.listView_applications, 0, 0, 1, 1)
|
self.gridLayout_2.addWidget(self.listView_applications, 0, 0, 1, 1)
|
||||||
@@ -45,6 +47,7 @@ class Ui_Form(object):
|
|||||||
font.setPointSize(15)
|
font.setPointSize(15)
|
||||||
font.setBold(True)
|
font.setBold(True)
|
||||||
self.label_selected.setFont(font)
|
self.label_selected.setFont(font)
|
||||||
|
self.label_selected.setText("")
|
||||||
self.label_selected.setObjectName("label_selected")
|
self.label_selected.setObjectName("label_selected")
|
||||||
self.gridLayout.addWidget(self.label_selected, 0, 2, 1, 1)
|
self.gridLayout.addWidget(self.label_selected, 0, 2, 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)
|
||||||
@@ -81,7 +84,6 @@ class Ui_Form(object):
|
|||||||
_translate = QtCore.QCoreApplication.translate
|
_translate = QtCore.QCoreApplication.translate
|
||||||
Form.setWindowTitle(_translate("Form", "Form"))
|
Form.setWindowTitle(_translate("Form", "Form"))
|
||||||
self.pb_delete_all.setText(_translate("Form", "Delete All"))
|
self.pb_delete_all.setText(_translate("Form", "Delete All"))
|
||||||
self.label_selected.setText(_translate("Form", "TextLabel"))
|
|
||||||
self.pb_refresh.setText(_translate("Form", "Refresh"))
|
self.pb_refresh.setText(_translate("Form", "Refresh"))
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -30,6 +30,12 @@
|
|||||||
<property name="editTriggers">
|
<property name="editTriggers">
|
||||||
<set>QAbstractItemView::NoEditTriggers</set>
|
<set>QAbstractItemView::NoEditTriggers</set>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="dragEnabled">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="dragDropMode">
|
||||||
|
<enum>QAbstractItemView::InternalMove</enum>
|
||||||
|
</property>
|
||||||
<property name="wordWrap">
|
<property name="wordWrap">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
@@ -83,7 +89,7 @@
|
|||||||
</font>
|
</font>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>TextLabel</string>
|
<string/>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
|||||||
Reference in New Issue
Block a user