plugin.py 8.08 KB
Newer Older
1
2
# -*- coding: utf-8 -*-
"""
3
Appindicator integration plugin.
4
5

Rewriten from Ubuntu Ayatana Integration plugin
6
2013 Denis Borenko <borenko@rambler.ru>
Dicson's avatar
Dicson committed
7
:license: GPLv3
8
9
"""
# Python
10
import os
11
import time
12
import gobject
13
# GTK
14
15
import gtkgui_helpers
import gtk
16
ERRORMSG = ''
17
18
try:
    import appindicator
19
except:
20
21
22
    ERRORMSG = 'python-appindicator is missing!<br/>Please install it.'
if os.name == 'nt':
    ERRORMSG = 'This is a Plugin for Linux'
23
# Gajim
24
from common import gajim, ged
25
26
27
28
29
from plugins import GajimPlugin
from plugins.plugin import GajimPluginException
from plugins.helpers import log_calls


30
class AppindicatorIntegrationPlugin(GajimPlugin):
31

32
    @log_calls("AppindicatorIntegrationPlugin")
33
    def init(self):
34
        if ERRORMSG:
35
            self.activatable = False
36
37
38
39
40
41
42
            self.available_text += _(ERRORMSG)
            return
        else:
            self.config_dialog = None
            self.events_handlers = {'our-show': (ged.GUI2,
                                                 self.set_indicator_icon)}
            self.windowstate = None
43

44
    @log_calls("AppindicatorIntegrationPlugin")
45
46
    def activate(self):

47
        self.events = {}
48

49
50
51
        self.attention_icon  = "mail-unread"
        self.online_icon     = "user-available"
        self.offline_icon    = "user-offline"
52
        self.connected       = 0
53
54
55
56

        self.connect_menu_item = gtk.MenuItem('Connect')
        self.connect_menu_item.connect("activate", self.connect)

57
58
59
60
        self.show_gajim_menu_item = gtk.MenuItem('Show/hide roster')
        self.show_gajim_menu_item.connect("activate", self.roster_raise)
        self.show_gajim_menu_item.show()

61
        self.event_separator = gtk.SeparatorMenuItem()
62
        self.menuEventInsertIndex = 3
63

64
65
        itemExitSeparator = gtk.SeparatorMenuItem()
        itemExitSeparator.show()
66

67
68
69
        itemExit = gtk.MenuItem('Exit')
        itemExit.connect("activate", self.on_exit_menuitem_activate)
        itemExit.show()
70

71
        self.menu = gtk.Menu()
72
        self.menu.append(self.connect_menu_item)
73
74
75
76
77
        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()
78

79
        self.indicator = appindicator.Indicator("Gajim", self.offline_icon,
80
            appindicator.CATEGORY_APPLICATION_STATUS)
81
        self.indicator.set_attention_icon(self.attention_icon)
82
        self.indicator.set_status(appindicator.STATUS_ACTIVE)
83
84
        self.indicator.set_menu(self.menu)

85
86
        self.set_indicator_icon()

87
88
        gajim.events.event_added_subscribe(self.on_event_added)
        gajim.events.event_removed_subscribe(self.on_event_removed)
89

90
91
92
93
        self.roster = gajim.interface.roster.window
        self.handlerid = self.roster.connect('window-state-event',
                                             self.window_state_event_cb)

94
95
96
    def connect(self, widget, data=None):
        for account in gajim.connections:
            if gajim.config.get_per('accounts', account,
97
98
99
                                    'sync_with_global_status'):
                gajim.connections[account].change_status('online',
                                                         'online')
Dicson's avatar
Dicson committed
100

101
102
103
104
105
    def window_state_event_cb(self, win, event):
        if event.new_window_state & gtk.gdk.WINDOW_STATE_ICONIFIED:
            self.windowstate = 'iconified'
        elif event.new_window_state & gtk.gdk.WINDOW_STATE_WITHDRAWN:
            self.windowstate = 'hidden'
Dicson's avatar
Dicson committed
106

107
108
109
110
    def set_indicator_icon(self, obj=''):
        is_connected = 0
        for account in gajim.connections:
            if not gajim.config.get_per('accounts', account,
111
                                        'sync_with_global_status'):
112
113
114
115
116
117
118
119
                continue
            if gajim.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(self.online_icon)
120
                self.connect_menu_item.hide()
121
122
            else:
                self.indicator.set_icon(self.offline_icon)
123
                self.connect_menu_item.show()
124

125
    @log_calls("AppindicatorPlugin")
126
127
128
129
130
    def deactivate(self):
        gajim.events.event_added_unsubscribe(self.on_event_added)
        gajim.events.event_removed_unsubscribe(self.on_event_removed)

        if hasattr(self, 'indicator'):
131
            self.indicator.set_status(appindicator.STATUS_PASSIVE)
132
133
            del self.indicator

134
135
        self.roster.disconnect(self.handlerid)

136
137
    def roster_raise(self, widget, data=None):
        win = gajim.interface.roster.window
138
        if win.get_property("visible") and self.windowstate != 'iconified':
139
            gobject.idle_add(win.hide)
140
141
        else:
            win.present()
142
143
144
            self.windowstate = 'shown'

        win.window.focus(gtk.get_current_event_time())
145
146
147
148
149
150
151
152
153

    def on_exit_menuitem_activate(self, widget, data=None):
            gajim.interface.roster.on_quit_request()

    def event_raise(self, widget, event):
        gajim.interface.handle_event(event.account, event.jid, event.type_)
        win = gajim.interface.roster.window
        if not win.is_active():
            win.present()
154

155
156
157
    def on_event_added(self, event):
        account = event.account
        jid = event.jid
158
        when = time.localtime()
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
        contact = ""
        key = (account, jid)

        if event.type_ == "chat" or \
        event.type_ == "printed_chat" or \
        event.type_ == "normal" or \
        event.type_ == "printed_normal" or \
        event.type_ == "file-request" or \
        event.type_ == "jingle-incoming":
            contact = gajim.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":
174
            contact = gajim.get_nick_from_jid(gajim.get_room_from_fjid(jid)) + \
175
176
177
178
179
                    "/" + gajim.get_room_and_nick_from_fjid(jid)[1]
        elif event.type_ == "printed_marked_gc_msg":
            contact = gajim.get_nick_from_jid(gajim.get_room_from_fjid(jid))
        else:
            return
180
        #print account, jid, when, contact
181
182
183
184
185
186
        event.time = when
        if key not in self.events:
            icon = None
            if gajim.config.get("show_avatars_in_roster"):
                pixbuf = gtkgui_helpers.get_avatar_pixbuf_from_cache(jid)
                if pixbuf not in (None, "ask"):
187
188
                    icon = gtk.Image()
                    icon.set_from_pixbuf(pixbuf)
189
            item = gtk.ImageMenuItem(contact + " (1)")
190
            if icon:
191
                item.set_image(icon)
192
193
194
195
196
197
                item.set_always_show_image(True)
            item.connect("activate", self.event_raise, event)
            item.show()
            self.menu.insert(item, self.menuEventInsertIndex)
            self.event_separator.show()
            self.events[key] = {}
198
199
200
            self.events[key]['item'] = item
            self.events[key]['contact'] = contact
            self.events[key]['events'] = [event]
201
202
203
        else:
            self.events[key]['events'].append(event)
            item = self.events[key]['item']
204
205
206
            item.set_label(self.events[key]['contact'] +
                " (" + str(len(self.events[key]['events'])) + ")")
        self.indicator.set_status(appindicator.STATUS_ATTENTION)
207
208
209
210

    def on_event_removed(self, events):
        for event in events:
            key = (event.account, event.jid)
211
            if key in self.events and event in self.events[key]['events']:
212
213
214
215
216
                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:
217
218
                    self.events[key]['item'].connect("activate",
                        self.event_raise, self.events[key]['events'][-1])
219
220
                if len(self.events) == 0:
                    self.event_separator.hide()
221
                    self.indicator.set_status(appindicator.STATUS_ACTIVE)