diff --git a/example.py b/example.py index d18c887..de2bbdf 100755 --- a/example.py +++ b/example.py @@ -79,14 +79,18 @@ def getEvents(mail_user, mail_password, proxy): encoder = json.JSONEncoder() res = {'group':'Mail', 'items':[]} res['items'] += getMail(mail_user, mail_password) - proxy.notify(encoder.encode(res), dbus_interface='com.soutade.GenericMonitor') + try: + proxy.notify(encoder.encode(res), dbus_interface='com.soutade.GenericMonitor') + except dbus.exceptions.DBusException as e: + print(str(e)) + pass class StockThread(Thread): SLEEP_TIME = 30 - + def stop(self): self._stopLoop = True - + def run(self): self._stopLoop = False mail_password = getpass.getpass('Enter password for address %s: ' % (MAIL_ADDRESS)) @@ -96,14 +100,17 @@ class StockThread(Thread): for i in range(0, StockThread.SLEEP_TIME): if self._stopLoop: break time.sleep(1) - + def signalHandler(signal_received, frame): stockThread.stop() mainLoop.quit() stockThread.join() encoder = json.JSONEncoder() res = {'groups':['Mail', 'Pidgin']} - systray_proxy.deleteGroups(encoder.encode(res), dbus_interface='com.soutade.GenericMonitor') + try: + systray_proxy.deleteGroups(encoder.encode(res), dbus_interface='com.soutade.GenericMonitor') + except Exception as e: + pass sys.exit(0) PURPLE_CONV_UPDATE_UNSEEN = 4 @@ -112,7 +119,7 @@ PURPLE_MESSAGE_SEND = 0 class PidginConversation: STATUS_SEEN = 0 STATUS_UNSEEN = 1 - + def __init__(self, _id): self._id = _id self.status = PidginConversation.STATUS_SEEN @@ -134,10 +141,10 @@ class PidginConversation: return (self.status == PidginConversation.STATUS_SEEN) pidgin_conversations = {} - + def pidginMessageReceived(account, sender, message, conversation, flags): pidginConversation = pidgin_conversations.get(conversation, None) - if not pidginConversation: + if not pidginConversation: pidgin_conversations[conversation] = PidginConversation(conversation) else: pidginConversation.updateNbMessages() @@ -146,7 +153,7 @@ def pidginMessageWrote(account, sender, message, conversation, flags): if not (flags & (1 << PURPLE_MESSAGE_SEND)): return pidginConversation = pidgin_conversations.get(conversation, None) - if not pidginConversation: + if not pidginConversation: pidgin_conversations[conversation] = PidginConversation(conversation) pidginConversation = pidgin_conversations[conversation] pidginConversation.setSeen() @@ -171,7 +178,11 @@ def pidginConversationUpdated(conversation, _type): if not pidginConversation.isSeen(): res = {'group':'Pidgin', 'items':[]} res['items'] += DBUSItem('pidgin', icon='/usr/share/icons/hicolor/22x22/apps/pidgin.png', iconStyle='icon-size:22px').toMap() - systray_proxy.notify(encoder.encode(res), dbus_interface='com.soutade.GenericMonitor') + try: + systray_proxy.notify(encoder.encode(res), dbus_interface='com.soutade.GenericMonitor') + except dbus.exceptions.DBusException as e: + print(str(e)) + pass else: deleteIcon = True # Are all messages seen ? @@ -181,17 +192,21 @@ def pidginConversationUpdated(conversation, _type): break if deleteIcon: res = {'items':['pidgin@Pidgin']} - systray_proxy.deleteItems(encoder.encode(res), dbus_interface='com.soutade.GenericMonitor') - + try: + systray_proxy.deleteItems(encoder.encode(res), dbus_interface='com.soutade.GenericMonitor') + except dbus.exceptions.DBusException as e: + print(str(e)) + pass + dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) bus = dbus.SessionBus() systray_proxy = bus.get_object('org.gnome.Shell', '/com/soutade/GenericMonitor') -bus.add_signal_receiver(pidginMessageReceived, 'ReceivedImMsg', 'im.pidgin.purple.PurpleInterface') -bus.add_signal_receiver(pidginMessageReceived, 'ReceivedChatMsg', 'im.pidgin.purple.PurpleInterface') -bus.add_signal_receiver(pidginMessageWrote, 'WroteImMsg', 'im.pidgin.purple.PurpleInterface') -bus.add_signal_receiver(pidginMessageWrote, 'WroteChatMsg', 'im.pidgin.purple.PurpleInterface') +bus.add_signal_receiver(pidginMessageReceived, 'ReceivedImMsg', 'im.pidgin.purple.PurpleInterface') +bus.add_signal_receiver(pidginMessageReceived, 'ReceivedChatMsg', 'im.pidgin.purple.PurpleInterface') +bus.add_signal_receiver(pidginMessageWrote, 'WroteImMsg', 'im.pidgin.purple.PurpleInterface') +bus.add_signal_receiver(pidginMessageWrote, 'WroteChatMsg', 'im.pidgin.purple.PurpleInterface') bus.add_signal_receiver(pidginConversationUpdated, 'ConversationUpdated', 'im.pidgin.purple.PurpleInterface') stockThread = StockThread() diff --git a/extension.js b/extension.js index c2b142b..f8d8f7d 100644 --- a/extension.js +++ b/extension.js @@ -20,64 +20,54 @@ const St = imports.gi.St; const Gio = imports.gi.Gio; -const Lang = imports.lang; const Main = imports.ui.main; class MonitorWidget { constructor(name, group, text, style, icon, iconStyle) { - this.name = name; - this.group = group; - this._createIcon(icon, iconStyle); - this._createText(text, style); + this.name = name; + this.group = group; + this._createIcon(icon, iconStyle); + this._createText(text, style); } - _createText(text, style) - { - this.style = style; - if (text == "") - this.widget = null; - else - { - this.widget = new St.Button({ label: text}); - this.widget.set_style(this.style); - } + _createText(text, style) { + this.style = style; + if (text === '') { + this.widget = null; + } else { + this.widget = new St.Button({ label: text }); + this.widget.set_style(this.style); + } } - - _createIcon(icon, style) - { - this.iconStyle = style; - if (icon == "") - this.icon = null; - else - { - let gicon = Gio.icon_new_for_string(icon); - this.icon = new St.Icon({ gicon }); - this.icon.set_style(this.iconStyle); - } - } - - update(text, style, icon, iconStyle) - { - if (!this.widget) - this._createText(text, style) - else - { - if (text != "") - this.widget.label = text; - this.style = style; - this.widget.set_style(this.style); - } - if (icon != "") - this._createIcon(icon, iconStyle); - else - { - if (iconStyle != "" && this.icon) - { - this.iconStyle = style; - this.icon.set_style(this.iconStyle); - } - } + _createIcon(icon, style) { + this.iconStyle = style; + if (icon === '') { + this.icon = null; + } else { + let gicon = Gio.icon_new_for_string(icon); + this.icon = new St.Icon({ gicon }); + this.icon.set_style(this.iconStyle); + } + } + + update(text, style, icon, iconStyle) { + if (!this.widget) { + this._createText(text, style); + } else { + if (text !== '') + this.widget.label = text; + this.style = style; + this.widget.set_style(this.style); + } + + if (icon !== '') + this._createIcon(icon, iconStyle); + + if (icon === '' && iconStyle !== '' && this.icon) { + this.iconStyle = style; + this.icon.set_style(this.iconStyle); + } } } @@ -86,220 +76,204 @@ class MonitorWidget { function loadInterfaceXml(filename) { let extension = imports.misc.extensionUtils.getCurrentExtension(); - let interfaces_dir = extension.dir.get_child(".") + let interfacesDir = extension.dir.get_child('.'); - let file = interfaces_dir.get_child(filename); + let file = interfacesDir.get_child(filename); - let [ result, contents ] = imports.gi.GLib.file_get_contents(file.get_path()); + let [result, contents] = imports.gi.GLib.file_get_contents(file.get_path()); if (result) { - //HACK: The "" + trick is important as hell because file_get_contents returns + // HACK: The "" + trick is important as hell because file_get_contents returns // an object (WTF?) but Gio.makeProxyWrapper requires `typeof() == "string"` // Otherwise, it will try to check `instanceof XML` and fail miserably because there // is no `XML` on very recent SpiderMonkey releases (or, if SpiderMonkey is old enough, // will spit out a TypeError soon). if (contents instanceof Uint8Array) - contents = imports.byteArray.toString(contents); - return "" + contents + ""; + contents = imports.byteArray.toString(contents); + let res = `${contents}`; + return res; } else { - throw new Error("Generic monitor: Could not load file: "+filename); + throw new Error(`Generic monitor: Could not load file: ${filename}`); } } -const GenericMonitorDBUS = new Lang.Class({ - Name: 'GenericMonitor', - - _init: function() { - this.monitor_groups = {}; - this.box = Main.panel._centerBox; +class GenericMonitorDBUS { + constructor() { + this.monitor_groups = {}; + this.box = Main.panel._centerBox; this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(loadInterfaceXml('dbus.xml'), this); this._dbusImpl.export(Gio.DBus.session, '/com/soutade/GenericMonitor'); - }, - - _checkParmeters: function(parameters) - { - if (!parameters.hasOwnProperty("group")) - throw new Error("No group defined"); - - if (!parameters.hasOwnProperty("items")) - throw new Error("No items defined"); - - for (let itemIndex in parameters["items"]) { - let item = parameters["items"][itemIndex]; - if (!item.hasOwnProperty("name")) - throw new Error("No name defined for item"); - if (!item.hasOwnProperty("text") && !item.hasOwnProperty("icon")) - throw new Error("No text not icon defined for item"); - } - }, - - _getItemFromGroup: function(group, name) - { - for (let groupItemIndex in group) - { - let groupItem = group[groupItemIndex]; - if (groupItem.name == name) - return groupItem; - } - - return null; - }, - - notify: function(str) { - let parameters = JSON.parse(str); - this._checkParmeters(parameters); - - let groupName = parameters["group"]; - let group; - if (!this.monitor_groups.hasOwnProperty(groupName)) - { - group = []; - this.monitor_groups[groupName] = group; - } - else - group = this.monitor_groups[groupName]; - - for (let itemIndex in parameters["items"]) { - let item = parameters["items"][itemIndex]; - let style = ""; - if (item.hasOwnProperty("style")) - style = item["style"]; - let text = ""; - if (item.hasOwnProperty("text")) - text = item["text"]; - let icon = ""; - if (item.hasOwnProperty("icon")) - icon = item["icon"]; - let iconStyle = ""; - if (item.hasOwnProperty("icon-style")) - iconStyle = item["icon-style"]; - - let monitorWidget = this._getItemFromGroup(group, item["name"]); - let lastWidget = null; - - // New widget - if (monitorWidget == null) - { - monitorWidget = new MonitorWidget(item["name"], groupName, text, style, icon, iconStyle); - if (group.length) - lastWidget = group[group.length-1].widget; - group.push(monitorWidget); - // lastWidget => NULL, insert at the end - if (monitorWidget.icon) - { - this.box.insert_child_above(monitorWidget.icon, lastWidget); - lastWidget = monitorWidget.icon; - } - if (monitorWidget.widget) - this.box.insert_child_above(monitorWidget.widget, lastWidget); - } - else - { - let prevWidget = monitorWidget.widget; - let prevIcon = monitorWidget.icon; - - monitorWidget.update(text, style, icon, iconStyle); - - if (monitorWidget.icon) - { - if (prevIcon) - this.box.remove_child(prevIcon); - this.box.insert_child_above(monitorWidget.icon, lastWidget); - lastWidget = monitorWidget.icon; - } - - if (!prevWidget && monitorWidget.widget) - this.box.insert_child_above(monitorWidget.widget, lastWidget); - } - } - }, - - _removeItemFromBox: function(item) { - if (item.widget) - this.box.remove_child(item.widget); - if (item.icon) - this.box.remove_child(item.icon); - }, - - deleteItems: function(str) { - let parameters = JSON.parse(str); - - if (!parameters.hasOwnProperty("items")) - throw new Error("No items defined"); - - for (let itemIndex in parameters["items"]) { - let itemName = parameters["items"][itemIndex]; - let fullName = itemName.split("@"); - if (fullName.length != 2) - throw new Error("Invalid name " + itemName); - itemName = fullName[0]; - let groupName = fullName[1]; - if (!this.monitor_groups.hasOwnProperty(groupName)) - continue; - let group = this.monitor_groups[groupName]; - let item = this._getItemFromGroup(group, itemName); - if (item != null) - { - this._removeItemFromBox(item); - delete group[item["name"]]; - if (group.length == 0) - delete this.monitor_groups[groupName]; - } - } - }, - - deleteGroups: function(str) { - let parameters = JSON.parse(str); - - if (!parameters.hasOwnProperty("groups")) - throw new Error("No groups defined"); - - let groupsToDelete = []; - for (let groupIndex in parameters["groups"]) { - groupName = parameters["groups"][groupIndex]; - if (!this.monitor_groups.hasOwnProperty(groupName)) - continue; - let group = this.monitor_groups[groupName]; - for (let itemIndex in group) { - this._removeItemFromBox(group[itemIndex]); - } - groupsToDelete.push(groupName); - } - for(let groupDeleteIndex in groupsToDelete) - { - let groupName = groupsToDelete[groupDeleteIndex]; - delete this.monitor_groups[groupName]; - } - }, - - deleteAll: function() { - for (let groupIndex in this.monitor_groups) { - let group = this.monitor_groups[groupIndex]; - for (let itemIndex in group) { - this._removeItemFromBox(group[itemIndex]); - } - } - this.monitor_groups = {} - }, -}); - -class Extension { - constructor() { - this.textDBusService = new GenericMonitorDBUS(); } + _checkParmeters(parameters) { + if (!parameters.hasOwnProperty('group')) + throw new Error('No group defined'); + + if (!parameters.hasOwnProperty('items')) + throw new Error('No items defined'); + + for (let itemIndex in parameters['items']) { + let item = parameters['items'][itemIndex]; + if (!item.hasOwnProperty('name')) + throw new Error('No name defined for item'); + if (!item.hasOwnProperty('text') && !item.hasOwnProperty('icon')) + throw new Error('No text not icon defined for item'); + } + } + + _getItemFromGroup(group, name) { + for (let groupItemIndex in group) { + let groupItem = group[groupItemIndex]; + if (groupItem.name === name) + return groupItem; + } + + return null; + } + + notify(str) { + let parameters = JSON.parse(str); + this._checkParmeters(parameters); + + let groupName = parameters['group']; + let group; + if (!this.monitor_groups.hasOwnProperty(groupName)) { + group = []; + this.monitor_groups[groupName] = group; + } else { + group = this.monitor_groups[groupName]; + } + + for (let itemIndex in parameters['items']) { + let item = parameters['items'][itemIndex]; + let style = ''; + if (item.hasOwnProperty('style')) + style = item['style']; + let text = ''; + if (item.hasOwnProperty('text')) + text = item['text']; + let icon = ''; + if (item.hasOwnProperty('icon')) + icon = item['icon']; + let iconStyle = ''; + if (item.hasOwnProperty('icon-style')) + iconStyle = item['icon-style']; + + let monitorWidget = this._getItemFromGroup(group, item['name']); + let lastWidget = null; + + // New widget + if (monitorWidget === null) { + monitorWidget = new MonitorWidget(item['name'], groupName, text, style, icon, iconStyle); + if (group.length) + lastWidget = group[group.length - 1].widget; + group.push(monitorWidget); + // lastWidget => NULL, insert at the end + if (monitorWidget.icon) { + this.box.insert_child_above(monitorWidget.icon, lastWidget); + lastWidget = monitorWidget.icon; + } + if (monitorWidget.widget) + this.box.insert_child_above(monitorWidget.widget, lastWidget); + } else { + let prevWidget = monitorWidget.widget; + let prevIcon = monitorWidget.icon; + + monitorWidget.update(text, style, icon, iconStyle); + + if (monitorWidget.icon) { + if (prevIcon) + this.box.remove_child(prevIcon); + this.box.insert_child_above(monitorWidget.icon, lastWidget); + lastWidget = monitorWidget.icon; + } + + if (!prevWidget && monitorWidget.widget) + this.box.insert_child_above(monitorWidget.widget, lastWidget); + } + } + } + + _removeItemFromBox(item) { + if (item.widget) + this.box.remove_child(item.widget); + if (item.icon) + this.box.remove_child(item.icon); + } + + deleteItems(str) { + let parameters = JSON.parse(str); + + if (!parameters.hasOwnProperty('items')) + throw new Error('No items defined'); + + for (let itemIndex in parameters['items']) { + let itemName = parameters['items'][itemIndex]; + let fullName = itemName.split('@'); + if (fullName.length !== 2) + throw new Error(`Invalid name ${itemName}`); + itemName = fullName[0]; + let groupName = fullName[1]; + if (!this.monitor_groups.hasOwnProperty(groupName)) + continue; + let group = this.monitor_groups[groupName]; + let item = this._getItemFromGroup(group, itemName); + if (item !== null) { + this._removeItemFromBox(item); + delete group[item['name']]; + if (group.length === 0) + delete this.monitor_groups[groupName]; + } + } + } + + deleteGroups(str) { + let parameters = JSON.parse(str); + + if (!parameters.hasOwnProperty('groups')) + throw new Error('No groups defined'); + + let groupsToDelete = []; + for (let groupIndex in parameters['groups']) { + let groupName = parameters['groups'][groupIndex]; + if (!this.monitor_groups.hasOwnProperty(groupName)) + continue; + let group = this.monitor_groups[groupName]; + for (let itemIndex in group) + this._removeItemFromBox(group[itemIndex]); + groupsToDelete.push(groupName); + } + for (let groupDeleteIndex in groupsToDelete) { + let groupName = groupsToDelete[groupDeleteIndex]; + delete this.monitor_groups[groupName]; + } + } + + destructor() { + for (let groupIndex in this.monitor_groups) { + let group = this.monitor_groups[groupIndex]; + for (let itemIndex in group) + this._removeItemFromBox(group[itemIndex]); + } + this.monitor_groups = {}; + this._dbusImpl.unexport(); + } +} + +class Extension { enable() { + this.textDBusService = new GenericMonitorDBUS(); } disable() { - this.textDBusService.deleteAll(); + this.textDBusService.destructor(); + delete this.textDBusService; } } -let extension = null; +let extension = new Extension(); function init() { - extension = new Extension(); } function enable() {