From 5a493c7e29aa791be211b6afc67d686691488724 Mon Sep 17 00:00:00 2001 From: gatsik <74517072+Gatsik@users.noreply.github.com> Date: Sat, 3 Aug 2024 20:46:34 +0300 Subject: [PATCH] Allow individual override of ingame notification settings which allows to disable ingame notification for everything except the GAME_FULL notification * apply common enabling/disabling rules to party invite notification * fix NEW_GAME notification --- src/notifications/__init__.py | 65 ++++++++++++++++---------------- src/notifications/ns_hook.py | 27 +++++++------ src/notifications/ns_settings.py | 30 ++++++++++++--- 3 files changed, 73 insertions(+), 49 deletions(-) diff --git a/src/notifications/__init__.py b/src/notifications/__init__.py index 590b936cc..4a03a93e2 100644 --- a/src/notifications/__init__.py +++ b/src/notifications/__init__.py @@ -7,6 +7,7 @@ import util from config import Settings from fa import maps +from model.game import Game from model.player import Player from notifications.ns_dialog import NotificationDialog from notifications.ns_settings import IngameNotification @@ -44,10 +45,7 @@ def __init__(self, client, gameset, playerset, me): self.user = util.THEME.icon("client/user.png", pix=True) def _newPlayer(self, player: Player) -> None: - if ( - self.isDisabled() - or not self.settings.popupEnabled(self.USER_ONLINE) - ): + if self.is_disabled(self.USER_ONLINE): return if self.me.player is not None and self.me.player == player: @@ -63,21 +61,21 @@ def _newPlayer(self, player: Player) -> None: self.events.append((self.USER_ONLINE, player.copy())) self.checkEvent() - def _newLobby(self, game): - if self.isDisabled() or not self.settings.popupEnabled(self.NEW_GAME): + def _newLobby(self, game: Game) -> None: + if self.is_disabled(self.NEW_GAME): return host = game.host_player notify_mode = self.settings.getCustomSetting(self.NEW_GAME, 'mode') if notify_mode != 'all': - if host is None or not self.client.user_relations.model.is_friend(host): + if host is None or not self.client.user_relations.model.is_friend(host.id, host.login): return self.events.append((self.NEW_GAME, game.copy())) self.checkEvent() - def _gamefull(self): - if self.isDisabled() or not self.settings.popupEnabled(self.GAME_FULL): + def _gamefull(self) -> None: + if self.is_disabled(self.GAME_FULL): return if (self.GAME_FULL, None) not in self.events: self.events.append((self.GAME_FULL, None)) @@ -95,7 +93,10 @@ def unofficialClient(self, msg): self.events.append((self.UNOFFICIAL_CLIENT, msg)) self.checkEvent() - def partyInvite(self, message): + def partyInvite(self, message: dict) -> None: + if self.is_disabled(self.PARTY_INVITE): + return + notify_mode = self.settings.getCustomSetting(self.PARTY_INVITE, 'mode') if ( notify_mode != 'all' @@ -114,18 +115,22 @@ def gameExit(self): if self.settings.ingame_notifications == IngameNotification.QUEUE: self.checkEvent() - def isDisabled(self): - return ( - self.disabledStartup - or ( - self.game_running - and ( - self.settings.ingame_notifications - == IngameNotification.DISABLE - ) + def is_enabled(self, event_type: str) -> bool: + if not self.settings.enabled or self.disabledStartup: + return False + + if not self.settings.popupEnabled(event_type): + return False + + if self.game_running: + return ( + self.settings.ingame_notifications == IngameNotification.ENABLE + or self.settings.ingame_allowed(event_type) ) - or not self.settings.enabled - ) + return True + + def is_disabled(self, event_type: str) -> bool: + return not self.is_enabled(event_type) def setNotificationEnabled(self, enabled): self.settings.enabled = enabled @@ -233,7 +238,7 @@ def showEvent(self): self.settings.soundEnabled(eventType), ) - def checkEvent(self): + def checkEvent(self) -> None: """ Checks that we are in correct state to show next notification popup @@ -244,15 +249,9 @@ def checkEvent(self): * Game isn't running, or ingame notifications are enabled """ - if ( - len(self.events) > 0 - and self.dialog.isHidden() - and ( - not self.game_running - or ( - self.settings.ingame_notifications - == IngameNotification.ENABLE - ) - ) - ): + if len(self.events) == 0 or not self.dialog.isHidden(): + return + + event_type, _ = self.events[0] + if self.is_enabled(event_type): self.showEvent() diff --git a/src/notifications/ns_hook.py b/src/notifications/ns_hook.py index 00cb15a57..e0da941c5 100644 --- a/src/notifications/ns_hook.py +++ b/src/notifications/ns_hook.py @@ -20,17 +20,15 @@ def __init__(self, eventType): self.button = QtWidgets.QPushButton('More') self.button.setEnabled(False) - def loadSettings(self): - self.popup = Settings.get( - self._settings_key + '/popup', True, type=bool, - ) - self.sound = Settings.get( - self._settings_key + '/sound', True, type=bool, - ) - - def saveSettings(self): - Settings.set(self._settings_key + '/popup', self.popup) - Settings.set(self._settings_key + '/sound', self.sound) + def loadSettings(self) -> None: + self.popup = Settings.get(f"{self._settings_key}/popup", default=True, type=bool) + self.sound = Settings.get(f"{self._settings_key}/sound", default=True, type=bool) + self.ingame = Settings.get(f"{self._settings_key}/ingame", default=False, type=bool) + + def saveSettings(self) -> None: + Settings.set(f"{self._settings_key}/popup", self.popup) + Settings.set(f"{self._settings_key}/sound", self.sound) + Settings.set(f"{self._settings_key}/ingame", self.ingame) def getEventDisplayName(self): return self.eventType @@ -45,6 +43,13 @@ def switchPopup(self): def soundEnabled(self): return self.sound + def ingame_allowed(self) -> bool: + return self.ingame + + def switch_ingame(self) -> None: + self.ingame = not self.ingame + self.saveSettings() + def switchSound(self): self.sound = not self.sound self.saveSettings() diff --git a/src/notifications/ns_settings.py b/src/notifications/ns_settings.py index 8b7b976ec..e4bd94ea2 100644 --- a/src/notifications/ns_settings.py +++ b/src/notifications/ns_settings.py @@ -3,6 +3,7 @@ Each module/hook for the notification system must be registered here. """ from enum import Enum +from typing import Any from PyQt6 import QtCore from PyQt6 import QtWidgets @@ -74,7 +75,7 @@ def __init__(self, client): for row in range(0, model.rowCount(None)): self.tableView.setIndexWidget( - model.createIndex(row, 3), + model.createIndex(row, 4), model.getHook(row).settings(), ) @@ -140,6 +141,11 @@ def soundEnabled(self, eventType): return self.hooks[eventType].soundEnabled() return False + def ingame_allowed(self, event_type: str) -> bool: + if event_type in self.hooks: + return self.hooks[event_type].ingame_allowed() + return False + def getCustomSetting(self, eventType, key): if eventType in self.hooks: if hasattr(self.hooks[eventType], key): @@ -155,17 +161,18 @@ class NotificationHooks(QtCore.QAbstractTableModel): POPUP = 1 SOUND = 2 - SETTINGS = 3 + ALLOW_INGAME = 3 + SETTINGS = 4 def __init__(self, parent, hooks, *args): QtCore.QAbstractTableModel.__init__(self, parent, *args) self.da = True self.hooks = hooks - self.headerdata = ['Type', 'PopUp', 'Sound', '#'] + self.headerdata = ['Type', 'PopUp', 'Sound', 'Allow ingame', '#'] def flags(self, index): flags = super(QtCore.QAbstractTableModel, self).flags(index) - if index.column() == self.POPUP or index.column() == self.SOUND: + if index.column() in (self.POPUP, self.SOUND, self.ALLOW_INGAME): return flags | QtCore.Qt.ItemFlag.ItemIsUserCheckable if index.column() == self.SETTINGS: return flags | QtCore.Qt.ItemFlag.ItemIsEditable @@ -196,6 +203,10 @@ def data(self, index, role=QtCore.Qt.ItemDataRole.DisplayRole.EditRole): return self.returnChecked( self.hooks[index.row()].soundEnabled(), ) + if index.column() == self.ALLOW_INGAME: + return self.returnChecked( + self.hooks[index.row()].ingame_allowed(), + ) return None if role != QtCore.Qt.ItemDataRole.DisplayRole: @@ -208,7 +219,12 @@ def data(self, index, role=QtCore.Qt.ItemDataRole.DisplayRole.EditRole): def returnChecked(self, state): return QtCore.Qt.CheckState.Checked if state else QtCore.Qt.CheckState.Unchecked - def setData(self, index, value, role=QtCore.Qt.ItemDataRole.DisplayRole.EditRole): + def setData( + self, + index: QtCore.QModelIndex, + value: Any, + role: QtCore.Qt.ItemDataRole = QtCore.Qt.ItemDataRole.EditRole, + ) -> bool: if index.column() == self.POPUP: self.hooks[index.row()].switchPopup() self.dataChanged.emit(index, index) @@ -217,6 +233,10 @@ def setData(self, index, value, role=QtCore.Qt.ItemDataRole.DisplayRole.EditRole self.hooks[index.row()].switchSound() self.dataChanged.emit(index, index) return True + if index.column() == self.ALLOW_INGAME: + self.hooks[index.row()].switch_ingame() + self.dataChanged.emit(index, index) + return True return False def headerData(self, col, orientation, role):