appindicator_integration/0000755000175500017550000000000013751571240015675 5ustar debacledebacleappindicator_integration/org.gajim.Gajim.Plugin.appindicator.metainfo.xml0000644000175500017550000000075113751571240027037 0ustar debacledebacle org.gajim.Gajim.Plugin.appindicator org.gajim.Gajim Ayatana Appindicator integration plugin Integrate Gajim with the Ayatana AppIndicator https://gajim.org/ CC-BY-SA-3.0 GPL-3.0 gajim-devel_AT_gajim.org appindicator_integration/appindicator_integration.png0000644000175500017550000000166613751571240023474 0ustar debacledebaclePNG  IHDRasBIT|d pHYs+tEXtSoftwarewww.inkscape.org<tEXtAuthorJosef VybíralxtEXtCreation Time28.10.2006H/+tEXtSourcehttp://cornelius.gimp.cz'ZIDAT8oTu?7:7mB:DT҅%!&ƅqeaG $Ƥ&@ ?tZ-t:N͛y.Or67{s5p+2'OQqs[o]K`R_(Qo|+~Ͷzg >$>,rp̫i>kts3)V!IU~:@QQcM4,  ޣmnĉ/Uc1il4` R~ ^<@$5$7>nfnk[*4D%)wr~r5:zE3-̶FjWy='_mO\).v{wc,Fw8W8L:swRdNhĩK'ogЇ2,xi`o667 &B9qcÖ0"^%{[:v޺=[: xPU5wrF1V`Յ((A3[GZt56o r|\a"G/(_+T(5zw&Q`hӈ5i?'ccOued}"|J"k6=MT{sb+tj{YK2}IENDB`appindicator_integration/__init__.py0000644000175500017550000000006213751571240020004 0ustar debacledebaclefrom .plugin import AppindicatorIntegrationPlugin appindicator_integration/manifest.ini0000644000175500017550000000070613751571240020207 0ustar debacledebacle[info] name: Ayatana Appindicator integration short_name: appindicator_integration version: 1.3.3 description: This plugin integrates Gajim with the Ayatana AppIndicator. You must have libappindicator3 installed to enable this plugin. homepage: https://dev.gajim.org/gajim/gajim-plugins/wikis/AppindicatorSupportPlugin authors: Denis Borenko Philipp Hörist min_gajim_version: 1.2.91 max_gajim_version: 1.3.90 appindicator_integration/plugin.py0000644000175500017550000002004213751571240017543 0ustar debacledebacle# -*- coding: utf-8 -*- """ Appindicator integration plugin. Rewritten from Ubuntu Ayatana Integration plugin 2013 Denis Borenko 2017 Philipp Hörist :license: GPLv3 """ import time import gi from gi.repository import Gtk, GLib, Gdk try: gi.require_version('AppIndicator3', '0.1') from gi.repository import AppIndicator3 as appindicator HAS_ERROR = False except (ValueError, ImportError): try: gi.require_version('AyatanaAppIndicator3', '0.1') from gi.repository import AyatanaAppIndicator3 as appindicator HAS_ERROR = False except (ValueError, ImportError): HAS_ERROR = True from gajim.common import app, ged from gajim.common import configpaths from gajim.plugins import GajimPlugin from gajim.plugins.helpers import log_calls from gajim.plugins.plugins_i18n import _ class AppindicatorIntegrationPlugin(GajimPlugin): @log_calls("AppindicatorIntegrationPlugin") def init(self): self.description = _('This plugin integrates Gajim with the Ayatana ' 'AppIndicator.') self.config_dialog = None if HAS_ERROR: self.activatable = False self.available_text += _('Please install libappindicator3') return self.events_handlers = {'our-show': (ged.GUI2, self.set_indicator_icon)} self.windowstate = None @log_calls("AppindicatorIntegrationPlugin") def activate(self): self.events = {} self.online_icon = 'org.gajim.Gajim' self.offline_icon = 'org.gajim.Gajim-symbolic' self.connected = 0 self.connect_menu_item = Gtk.MenuItem(label=_('Connect')) self.connect_menu_item.connect("activate", self.connect) self.show_gajim_menu_item = Gtk.MenuItem( label=_('Show/hide contact list')) self.show_gajim_menu_item.connect("activate", self.roster_raise) self.show_gajim_menu_item.show() self.event_separator = Gtk.SeparatorMenuItem() self.menuEventInsertIndex = 3 itemExitSeparator = Gtk.SeparatorMenuItem() itemExitSeparator.show() itemExit = Gtk.MenuItem(label=_('Quit')) itemExit.connect("activate", self.on_exit_menuitem_activate) itemExit.show() self.menu = Gtk.Menu() self.menu.append(self.connect_menu_item) self.menu.append(self.show_gajim_menu_item) self.menu.append(self.event_separator) self.menu.append(itemExitSeparator) self.menu.append(itemExit) self.menu.show() self.indicator = appindicator.Indicator.new( 'Gajim', self.offline_icon, appindicator.IndicatorCategory.COMMUNICATIONS) self.indicator.set_icon_theme_path(str(configpaths.get('ICONS'))) self.indicator.set_attention_icon_full('mail-unread', 'New Message') self.indicator.set_status(appindicator.IndicatorStatus.ACTIVE) self.indicator.set_menu(self.menu) self.set_indicator_icon() app.events.event_added_subscribe(self.on_event_added) app.events.event_removed_subscribe(self.on_event_removed) self.roster = app.interface.roster.window self.handlerid = self.roster.connect('window-state-event', self.window_state_event_cb) def connect(self, widget, data=None): for account in app.connections: if app.settings.get_account_setting(account, 'sync_with_global_status'): app.connections[account].change_status('online', 'online') def window_state_event_cb(self, win, event): if event.new_window_state & Gdk.WindowState.ICONIFIED: self.windowstate = 'iconified' elif event.new_window_state & Gdk.WindowState.WITHDRAWN: self.windowstate = 'hidden' def set_indicator_icon(self, *args): is_connected = 0 for account in app.connections: if not app.settings.get_account_setting(account, 'sync_with_global_status'): continue if app.account_is_connected(account): is_connected = 1 break if self.connected != is_connected: self.connected = is_connected if self.connected == 1: self.indicator.set_icon_full(self.online_icon, _('Online')) self.connect_menu_item.hide() else: self.indicator.set_icon_full(self.offline_icon, _('Offline')) self.connect_menu_item.show() @log_calls("AppindicatorPlugin") def deactivate(self): app.events.event_added_unsubscribe(self.on_event_added) app.events.event_removed_unsubscribe(self.on_event_removed) if hasattr(self, 'indicator'): self.indicator.set_status(appindicator.IndicatorStatus.PASSIVE) del self.indicator self.roster.disconnect(self.handlerid) def roster_raise(self, widget, data=None): win = app.interface.roster.window if win.get_property("visible") and self.windowstate != 'iconified': GLib.idle_add(win.hide) else: win.present() self.windowstate = 'shown' def on_exit_menuitem_activate(self, widget, data=None): app.interface.roster.on_quit_request() def event_raise(self, widget, event): app.interface.handle_event(event.account, event.jid, event.type_) win = app.interface.roster.window if not win.is_active(): win.present() def on_event_added(self, event): account = event.account jid = event.jid when = time.time() contact = "" key = (account, jid) events = ['chat', 'printed_chat', 'printed_normal', 'normal', 'file-request', 'jingle-incoming'] if event.type_ in events: contact = app.contacts.get_contact_from_full_jid(account, jid) if contact: contact = contact.get_shown_name() else: contact = jid elif event.type_ == "pm" or event.type_ == "printed_pm": contact = app.get_nick_from_jid(app.get_room_from_fjid(jid)) + \ "/" + app.get_room_and_nick_from_fjid(jid)[1] elif event.type_ == "printed_marked_gc_msg": contact = app.get_nick_from_jid(app.get_room_from_fjid(jid)) else: return event.time = when if key not in self.events: item = Gtk.MenuItem(label=contact + " (1)") item.connect("activate", self.event_raise, event) item.show() self.menu.insert(item, self.menuEventInsertIndex) self.event_separator.show() self.events[key] = {} self.events[key]['item'] = item self.events[key]['contact'] = contact self.events[key]['events'] = [event] else: self.events[key]['events'].append(event) item = self.events[key]['item'] item.set_label(self.events[key]['contact'] + " (" + str(len(self.events[key]['events'])) + ")") self.indicator.set_status(appindicator.IndicatorStatus.ATTENTION) def on_event_removed(self, events): for event in events: key = (event.account, event.jid) if key in self.events and event in self.events[key]['events']: self.events[key]['events'].remove(event) if len(self.events[key]['events']) == 0: # remove indicator self.menu.remove(self.events[key]['item']) del self.events[key] else: self.events[key]['item'].connect("activate", self.event_raise, self.events[key]['events'][-1]) if len(self.events) == 0: self.event_separator.hide() self.indicator.set_status(appindicator.IndicatorStatus.ACTIVE)