Daniel Brötzmann pushed to branch mainwindow at gajim / gajim
Commits: cbb5dcf1 by wurstsalat at 2021-10-09T18:07:56+02:00 Settings: Add show_notifications_away
- - - - - 028f5e50 by wurstsalat at 2021-10-09T18:32:48+02:00 Events: Remove systray dependency
StatusIcon now connects to unread counter
- - - - -
15 changed files:
- gajim/app_actions.py - gajim/application.py - gajim/common/events.py - gajim/common/helpers.py - gajim/common/setting_values.py - gajim/data/gui/systray_context_menu.ui - gajim/gtk/chat_list_stack.py - gajim/gtk/controls/base.py - gajim/gtk/main.py - gajim/gtk/notification.py - gajim/gtk/preferences.py - gajim/gtk/status_icon.py - gajim/gtk/util.py - gajim/gui_interface.py - gajim/remote_control.py
Changes:
===================================== gajim/app_actions.py ===================================== @@ -242,17 +242,6 @@ def toggle_ipython(_action, _param): app.interface.create_ipython_window()
-def show_next_pending_event(_action, _param): - """ - Show the window(s) with next pending event in tabbed/group chats - """ - if app.events.get_nb_events(): - account, jid, event = app.events.get_first_systray_event() - if not event: - return - app.interface.handle_event(account, jid, event.type_) - - def open_mail(_action, param): uri = param.get_string() if not uri.startswith('mailto:'):
===================================== gajim/application.py ===================================== @@ -147,13 +147,6 @@ def __init__(self): _('Sets an environment variable so ' 'GLib debug messages are printed'))
- self.add_main_option( - 'show-next-pending-event', - 0, - GLib.OptionFlags.NONE, - GLib.OptionArg.NONE, - _('Pops up a window with the next pending event')) - self.add_main_option( 'start-chat', 0, GLib.OptionFlags.NONE, @@ -307,7 +300,6 @@ def _command_line(self, _application, command_line):
remote_commands = [ ('ipython', None), - ('show-next-pending-event', None), ('start-chat', GLib.Variant('s', '')), ]
@@ -399,7 +391,6 @@ def add_actions(self): ('about', app_actions.on_about), ('faq', app_actions.on_faq), ('ipython', app_actions.toggle_ipython), - ('show-next-pending-event', app_actions.show_next_pending_event), ('start-chat', 's', app_actions.on_new_chat), ('accounts', 's', app_actions.on_accounts), ('add-contact', 's', app_actions.on_add_contact_jid),
===================================== gajim/common/events.py ===================================== @@ -24,25 +24,20 @@
class Event: - def __init__(self, time_=None, show_in_systray=True): + def __init__(self, time_=None): """ - type_ in chat, normal, file-request, file-error, file-completed, - file-request-error, file-send-error, file-stopped, gc_msg, pm, - printed_chat, printed_gc_msg, printed_marked_gc_msg, printed_pm, - jingle-incoming + type_ in chat-message, group-chat-message, private-chat-message, + file-request, file-request-error, file-error, file-completed, + file-send-error, file-stopped,
parameters is (per type_): file-*: file_props - printed_chat: [message, subject, control, msg_log_id] - printed_*: None - messages that are already printed in chat, but not read - jingle-incoming: (fulljid, sessionid, content_types) + *-chat-message: [message, subject, control, msg_log_id] """ if time_: self.time_ = time_ else: self.time_ = time.time() - self.show_in_systray = show_in_systray # Set when adding the event self.jid = None self.account = None @@ -59,11 +54,8 @@ def __init__(self, msg_log_id, time_=None, message_id=None, - stanza_id=None, - show_in_systray=True): - Event.__init__(self, - time_, - show_in_systray=show_in_systray) + stanza_id=None): + Event.__init__(self, time_) self.message = message self.subject = subject self.control = control @@ -88,11 +80,8 @@ class FileRequestEvent(Event):
def __init__(self, file_props, - time_=None, - show_in_systray=True): - Event.__init__(self, - time_, - show_in_systray=show_in_systray) + time_=None): + Event.__init__(self, time_) self.file_props = file_props
@@ -253,11 +242,6 @@ def change_jid(self, account, old_jid, new_jid): self._events[account][new_jid] = self._events[account][old_jid] del self._events[account][old_jid]
- def get_nb_events(self, types=None, account=None): - if types is None: - types = [] - return self._get_nb_events(types=types, account=account) - def get_events(self, account, jid=None, types=None): """ Return all events from the given account of the form: @@ -318,54 +302,6 @@ def get_first_event(self, account=None, jid=None, type_=None): first_event = event return first_event
- def _get_nb_events(self, account=None, jid=None, attribute=None, - types=None): - """ - Return the number of pending events - """ - if types is None: - types = [] - nb = 0 - if account: - accounts = [account] - else: - accounts = self._events.keys() - for acct in accounts: - if acct not in self._events: - continue - if jid: - jids = [jid] - else: - jids = self._events[acct].keys() - for j in jids: - if j not in self._events[acct]: - continue - for event in self._events[acct][j]: - if types and event.type_ not in types: - continue - if (not attribute or attribute == 'systray' and - event.show_in_systray): - nb += 1 - return nb - - def _get_some_events(self, attribute): - """ - Attribute in systray, roster - """ - events = {} - for account in self._events: - events[account] = {} - for jid in self._events[account]: - events[account][jid] = [] - for event in self._events[account][jid]: - if attribute == 'systray' and event.show_in_systray: - events[account][jid].append(event) - if not events[account][jid]: - del events[account][jid] - if not events[account]: - del events[account] - return events - @staticmethod def _get_first_event_with_attribute(events): """ @@ -386,22 +322,3 @@ def _get_first_event_with_attribute(events): first_jid = jid first_event = event return first_account, first_jid, first_event - - def get_nb_systray_events(self, types=None): - """ - Return the number of events displayed in systray - """ - if types is None: - types = [] - return self._get_nb_events(attribute='systray', types=types) - - def get_systray_events(self): - """ - Return all events that must be displayed in systray: - {account1: {jid1: [ev1, ev2], },. } - """ - return self._get_some_events('systray') - - def get_first_systray_event(self): - events = self.get_systray_events() - return self._get_first_event_with_attribute(events)
===================================== gajim/common/helpers.py ===================================== @@ -681,7 +681,7 @@ def message_needs_highlight(text, nickname, own_jid): def allow_showing_notification(account): if not app.settings.get('show_notifications'): return False - if app.settings.get('autopopupaway'): + if app.settings.get('show_notifications_away'): return True if app.account_is_available(account): return True
===================================== gajim/common/setting_values.py ===================================== @@ -17,6 +17,7 @@ class _ACCOUNT_DEFAULT: APP_SETTINGS = { 'autopopup': False, 'show_notifications': True, + 'show_notifications_away': False, 'autopopupaway': False, 'sounddnd': False, 'showoffline': True,
===================================== gajim/data/gui/systray_context_menu.ui ===================================== @@ -28,15 +28,6 @@ <property name="can-focus">False</property> </object> </child> - <child> - <object class="GtkMenuItem" id="show_all_events_menuitem"> - <property name="visible">True</property> - <property name="can-focus">False</property> - <property name="label" translatable="yes">Show All Pending _Events</property> - <property name="use-underline">True</property> - <signal name="activate" handler="_on_show_all_events" swapped="no"/> - </object> - </child> <child> <object class="GtkCheckMenuItem" id="sounds_mute_menuitem"> <property name="visible">True</property>
===================================== gajim/gtk/chat_list_stack.py ===================================== @@ -233,6 +233,12 @@ def contains_chat(self, account, jid, workspace_id=None): chat_list = self._chat_lists[workspace_id] return chat_list.contains_chat(account, jid)
+ def get_total_unread_count(self): + count = 0 + for chat_list in self._chat_lists.values(): + count += chat_list.get_unread_count() + return count + def process_event(self, event): if event.name not in HANDLED_EVENTS: return
===================================== gajim/gtk/controls/base.py ===================================== @@ -46,6 +46,7 @@ from gajim.common.i18n import _ from gajim.common.nec import EventHelper from gajim.common.helpers import AdditionalDataDict +from gajim.common.helpers import allow_showing_notification from gajim.common.const import KindConstant from gajim.common.structs import OutgoingMessage from gajim.common.connection_handlers_events import NotificationEvent @@ -58,7 +59,6 @@ from gajim.gui.message_input import MessageInputTextView from gajim.gui.util import get_hardware_key_codes from gajim.gui.util import get_builder -from gajim.gui.util import get_show_in_systray from gajim.gui.util import AccountBadge from gajim.gui.const import ControlType # pylint: disable=unused-import from gajim.gui.const import TARGET_TYPE_URI_LIST @@ -1154,11 +1154,11 @@ def _notify(self, name, text, tim): needs_highlight = False
if self.is_chat: - popup_msg_type = 'chat' + popup_msg_type = 'chat-message' sound_event = 'first_message_received'
if self.is_groupchat: - popup_msg_type = 'gc_msg' + popup_msg_type = 'group-chat-message' popup_title += f' ({self.contact.name})' needs_highlight = helpers.message_needs_highlight( text, self.contact.nickname, self._client.get_own_jid().bare) @@ -1170,7 +1170,7 @@ def _notify(self, name, text, tim): sound_event = None
if self.is_privatechat: - popup_msg_type = 'pm' + popup_msg_type = 'private-chat-message' popup_title += f' (private in {self.room_name})' sound_event = 'first_message_received'
@@ -1185,11 +1185,7 @@ def _notify(self, name, text, tim): else: popup_text = text
- popup_enabled = False - if app.settings.get('autopopupaway'): - popup_enabled = True - if self._client.status == 'online': - popup_enabled = True + popup_enabled = allow_showing_notification(self.account) if self.is_groupchat and not self.contact.can_notify(): popup_enabled = False
@@ -1219,16 +1215,13 @@ def _add_message_event(self, text, msg_log_id, message_id, stanza_id): else: event_type = PrivateChatMsgEvent event = 'message_received' - show_in_systray = get_show_in_systray( - event_type.type_, self.account, self.contact.jid)
event = event_type(text, '', self, msg_log_id, message_id=message_id, - stanza_id=stanza_id, - show_in_systray=show_in_systray) + stanza_id=stanza_id) app.events.add_event(self.account, str(self.contact.jid), event)
def toggle_emoticons(self):
===================================== gajim/gtk/main.py ===================================== @@ -8,6 +8,7 @@
from gajim.common import app from gajim.common import ged +from gajim.common.const import Display from gajim.common.helpers import ask_for_status_message from gajim.common.i18n import _ from gajim.common.nec import EventHelper @@ -95,6 +96,10 @@ def __init__(self):
self._prepare_window()
+ if not app.is_display(Display.WAYLAND): + app.interface.systray.connect_unread_changed( + self._chat_page.get_chat_list_stack()) + def _prepare_window(self): if app.settings.get('main_window_skip_taskbar'): self.set_property('skip-taskbar-hint', True) @@ -444,6 +449,10 @@ def get_active_control(self, *args, **kwargs): def chat_exists(self, *args, **kwargs): return self._chat_page.chat_exists(*args, **kwargs)
+ def get_total_unread_count(self): + chat_list_stack = self._chat_page.get_chat_list_stack() + return chat_list_stack.get_total_unread_count() + @staticmethod def contact_info(account, jid): client = app.get_client(account) @@ -602,6 +611,7 @@ def on_continue(message): # user pressed Cancel to change status message dialog return # check if we have unread messages + # TODO: # unread = app.events.get_nb_events()
# for event in app.events.get_all_events(['group-chat-message']):
===================================== gajim/gtk/notification.py ===================================== @@ -33,10 +33,13 @@ from gi.repository import Gtk
from gajim.common import app -from gajim.common import helpers from gajim.common import ged from gajim.common.const import StyleAttr from gajim.common.i18n import _ +from gajim.common.helpers import allow_showing_notification +from gajim.common.helpers import exec_command +from gajim.common.helpers import play_sound +from gajim.common.helpers import play_sound_file from gajim.common.nec import EventHelper
from .util import add_css_to_widget @@ -97,7 +100,7 @@ def on_proxy_ready(_source, res, _data=None): on_proxy_ready)
def _nec_notification(self, event): - if event.popup_enabled and app.settings.get('show_notifications'): + if event.popup_enabled and allow_showing_notification(event.account): icon_name = self._get_icon_name(event) self.popup( event.popup_event_type, @@ -111,15 +114,15 @@ def _nec_notification(self, event): if event.command: # Used by Triggers plugin try: - helpers.exec_command(event.command, use_shell=True) + exec_command(event.command, use_shell=True) except Exception: pass
if event.sound_file: # Allow override here, used by Triggers plugin - helpers.play_sound_file(event.sound_file) + play_sound_file(event.sound_file) elif event.sound_event: - helpers.play_sound(event.sound_event, event.account) + play_sound(event.sound_event, event.account)
def _on_notification(self, event): self.popup(event.type_,
===================================== gajim/gtk/preferences.py ===================================== @@ -416,6 +416,7 @@ def __init__(self, *args): props={'entries': trayicon_items}, callback=self._on_trayicon),
+ # TODO: Setting(SettingKind.SWITCH, _('Open Events'), SettingType.CONFIG, @@ -454,7 +455,7 @@ def __init__(self, account, parent): Setting(SettingKind.SWITCH, _('Notifications When Away'), SettingType.CONFIG, - 'autopopupaway', + 'show_notifications_away', desc=_('Show notifications even if you are Away, ' 'Busy, etc.'), bind='show_notifications'),
===================================== gajim/gtk/status_icon.py ===================================== @@ -71,6 +71,12 @@ def __init__(self): ('account-disconnected', ged.CORE, self._on_account_state), ])
+ def connect_unread_changed(self, chat_list_stack): + # We trigger the signal connection from the main window because it + # is not yet available when initializing StatusIcon + chat_list_stack.connect( + 'unread-count-changed', self._on_unread_count_changed) + def _on_our_show(self, _event): self.update_icon()
@@ -104,16 +110,19 @@ def show_icon(self): 'size-changed', self.update_icon)
self.update_icon() - self._subscribe_events()
def hide_icon(self): if HAS_INDICATOR: self._status_icon.set_status(appindicator.IndicatorStatus.PASSIVE) else: self._status_icon.set_visible(False) - self._unsubscribe_events()
- def update_icon(self, *args): + def _on_unread_count_changed(self, _chat_list_stack, _workspace_id, _count): + if app.settings.get('trayicon_notification_on_events'): + count = app.window.get_total_unread_count() + self.update_icon(count=count) + + def update_icon(self, count=0): if not app.interface.systray_enabled: return if app.settings.get('trayicon') == 'always': @@ -122,7 +131,7 @@ def update_icon(self, *args): appindicator.IndicatorStatus.ACTIVE) else: self._status_icon.set_visible(True) - if app.events.get_nb_systray_events(): + if count > 0: icon_name = get_icon_name('event') if HAS_INDICATOR: self._status_icon.set_icon_full(icon_name, _('Pending Event')) @@ -148,21 +157,6 @@ def update_icon(self, *args): else: self._status_icon.set_from_icon_name(icon_name)
- def _subscribe_events(self): - app.events.event_added_subscribe(self._on_event_added) - app.events.event_removed_subscribe(self._on_event_removed) - - def _unsubscribe_events(self): - app.events.event_added_unsubscribe(self._on_event_added) - app.events.event_removed_unsubscribe(self._on_event_removed) - - def _on_event_added(self, event): - if event.show_in_systray: - self.update_icon() - - def _on_event_removed(self, _event_list): - self.update_icon() - def _on_popup_menu(self, _status_icon, button, activate_time): if button == 1: self._on_activate() @@ -218,14 +212,6 @@ def _add_status_menu(self): def _on_new_chat(_widget): app.app.activate_action('start-chat', GLib.Variant('s', ''))
- @staticmethod - def _on_show_all_events(_widget): - events = app.events.get_systray_events() - for account in events: - for jid in events[account]: - for event in events[account][jid]: - app.interface.handle_event(account, jid, event.type_) - @staticmethod def _on_sounds_mute(widget): app.settings.set('sounds_on', not widget.get_active()) @@ -244,10 +230,6 @@ def _on_quit(_widget): app.window.quit()
def _on_activate(self, *args): - if app.events.get_systray_events(): - self._handle_first_event() - return - if app.window.get_property('has-toplevel-focus'): save_main_window_position() app.window.hide() @@ -262,15 +244,6 @@ def _on_activate(self, *args): app.window.set_property('skip-taskbar-hint', False) app.window.present_with_time(Gtk.get_current_event_time())
- @staticmethod - def _handle_first_event(): - account, jid, event = app.events.get_first_systray_event() - if not event: - return - if not app.window.get_property('visible'): - restore_main_window_position() - app.interface.handle_event(account, jid, event.type_) - @staticmethod def _on_show(_widget, show): app.interface.change_status(status=show)
===================================== gajim/gtk/util.py ===================================== @@ -506,18 +506,6 @@ def get_metacontact_surface(icon_name, expanded, scale): return state_surface
-def get_show_in_systray(type_, account, jid): - """ - Return True if this event must be shown in systray, else False - """ - if type_ == 'group-chat-message': - client = app.get_client(account) - contact = client.get_module('Contacts').get_group_chat_contact(jid) - return contact.can_notify() - - return app.settings.get('trayicon_notification_on_events') - - def get_primary_accel_mod(): """ Returns the primary Gdk.ModifierType modifier.
===================================== gajim/gui_interface.py ===================================== @@ -92,7 +92,6 @@ from gajim.gui.filechoosers import FileChooserDialog from gajim.gui.filetransfer import FileTransfersWindow from gajim.gui.main import MainWindow -from gajim.gui.util import get_show_in_systray from gajim.gui.util import get_app_window from gajim.gui.util import get_app_windows from gajim.gui.util import get_color_for_account @@ -240,18 +239,6 @@ def add_event(self, account, jid, event): """ Add an event to the app.events var """ - # We add it to the app.events queue - # Do we have a queue? - # has_queue = len(app.events.get_events(account, jid)) > 0 - # event can be in common.events.* - # event_type can be in advancedNotificationWindow.events_list - event_types = { - 'file-request': 'ft_request', - 'file-completed': 'ft_finished' - } - event_type = event_types.get(event.type_) - show_in_systray = get_show_in_systray(event_type, account, jid) - event.show_in_systray = show_in_systray app.events.add_event(account, jid, event)
# TODO: set urgency hint; show unread count in window title? @@ -935,8 +922,7 @@ def _popup_ft_result(self, account, jid, file_props): icon_name = None
if (app.settings.get('notify_on_file_complete') and - (app.settings.get('autopopupaway') or - app.connections[account].status in ('online', 'chat'))): + helpers.allow_showing_notification(account)): # We want to be notified and we are online/chat or we don't mind # to be bugged when away/na/busy app.notification.popup(
===================================== gajim/remote_control.py ===================================== @@ -204,7 +204,6 @@ class GajimRemote(Server): <arg name='prio' type='s' /> <arg name='account' type='s' /> </method> - <method name='show_next_pending_event' /> <method name='show_roster' /> <method name='start_chat'> <arg name='jid' type='s' /> @@ -650,16 +649,6 @@ def set_priority(self, prio, account): status = app.connections[acc].status_message GLib.idle_add(app.connections[acc].change_status, show, status)
- def show_next_pending_event(self): - """ - Show the window(s) with next pending event in tabbed/group chats - """ - if app.events.get_nb_events(): - account, jid, event = app.events.get_first_systray_event() - if not event: - return - app.interface.handle_event(account, jid, event.type_) - def list_accounts(self): """ List register accounts @@ -795,6 +784,9 @@ def _contacts_as_dbus_structure(self, bare_contact): return contact_dict
def get_unread_msgs_number(self): + # TODO: + return 0 + unread = app.events.get_nb_events() for event in app.events.get_all_events(['group-chat-message']): client = app.get_client(event.account)
View it on GitLab: https://dev.gajim.org/gajim/gajim/-/compare/6f15260acbd44ff0411b859186d4b93e...