diff options
author | Éric Araujo <merwok@netwok.org> | 2010-04-08 03:20:17 +0400 |
---|---|---|
committer | Éric Araujo <merwok@netwok.org> | 2010-04-08 03:20:17 +0400 |
commit | 9b5ee1e13b3a3e9f31aeec48e62fa69271c35e1e (patch) | |
tree | c5adfc610d64e6b8428f3fb2e780021b81c4e374 /plugins | |
parent | 57cd53aea13ecd05fdd1782534b9921901e1ec62 (diff) |
convert tabs to spaces in source code thanks to reindent.py
Also use sed to remove now unneeded Vim lines, 2to3 -f ws_comma to fix
some whitespace, and fix some other madness manually.
Diffstat (limited to 'plugins')
-rw-r--r-- | plugins/acronyms_expander.py | 123 | ||||
-rw-r--r-- | plugins/banner_tweaks/__init__.py | 2 | ||||
-rw-r--r-- | plugins/banner_tweaks/plugin.py | 316 | ||||
-rw-r--r-- | plugins/dbus_plugin/__init__.py | 2 | ||||
-rw-r--r-- | plugins/dbus_plugin/plugin.py | 1371 | ||||
-rw-r--r-- | plugins/events_dump/__init__.py | 2 | ||||
-rw-r--r-- | plugins/events_dump/plugin.py | 190 | ||||
-rw-r--r-- | plugins/google_translation/__init__.py | 2 | ||||
-rw-r--r-- | plugins/google_translation/plugin.py | 151 | ||||
-rw-r--r-- | plugins/length_notifier/__init__.py | 2 | ||||
-rw-r--r-- | plugins/length_notifier/length_notifier.py | 249 | ||||
-rw-r--r-- | plugins/new_events_example/__init__.py | 2 | ||||
-rw-r--r-- | plugins/new_events_example/plugin.py | 206 | ||||
-rw-r--r-- | plugins/roster_buttons/plugin.py | 101 | ||||
-rwxr-xr-x | plugins/snarl_notifications/PySnarl.py | 1544 | ||||
-rw-r--r-- | plugins/snarl_notifications/__init__.py | 2 | ||||
-rw-r--r-- | plugins/snarl_notifications/plugin.py | 97 |
17 files changed, 2178 insertions, 2184 deletions
diff --git a/plugins/acronyms_expander.py b/plugins/acronyms_expander.py index 69e2448e5..12ad677b0 100644 --- a/plugins/acronyms_expander.py +++ b/plugins/acronyms_expander.py @@ -33,69 +33,70 @@ from plugins import GajimPlugin from plugins.helpers import log, log_calls class AcronymsExpanderPlugin(GajimPlugin): - name = u'Acronyms Expander' - short_name = u'acronyms_expander' - version = u'0.1' - description = u'''Replaces acronyms (or other strings) with given expansions/substitutes.''' - authors = [u'Mateusz Biliński <mateusz@bilinski.it>'] - homepage = u'http://blog.bilinski.it' - - @log_calls('AcronymsExpanderPlugin') - def init(self): - self.config_dialog = None - - self.gui_extension_points = { - 'chat_control_base' : (self.connect_with_chat_control_base, - self.disconnect_from_chat_control_base) - } + name = u'Acronyms Expander' + short_name = u'acronyms_expander' + version = u'0.1' + description = u'''Replaces acronyms (or other strings) with given expansions/substitutes.''' + authors = [u'Mateusz Biliński <mateusz@bilinski.it>'] + homepage = u'http://blog.bilinski.it' - self.config_default_values = {'INVOKER' : (' ', _('')), - 'ACRONYMS' : ({'RTFM' : 'Read The Friendly Manual', - '/slap' : '/me slaps', - 'PS-' : 'plug-in system', - 'G-' : 'Gajim', - 'GNT-' : 'http://trac.gajim.org/newticket', - 'GW-' : 'http://trac.gajim.org/', - 'GTS-' : 'http://trac.gajim.org/report' - }, _('')), - } + @log_calls('AcronymsExpanderPlugin') + def init(self): + self.config_dialog = None - @log_calls('AcronymsExpanderPlugin') - def textbuffer_live_acronym_expander(self, tb): - """ - @param tb gtk.TextBuffer - """ - #assert isinstance(tb,gtk.TextBuffer) - ACRONYMS = self.config['ACRONYMS'] - INVOKER = self.config['INVOKER'] - t = tb.get_text(tb.get_start_iter(), tb.get_end_iter()) - #log.debug('%s %d'%(t, len(t))) - if t and t[-1] == INVOKER: - #log.debug('changing msg text') - base,sep,head=t[:-1].rpartition(INVOKER) - log.debug('%s | %s | %s'%(base, sep, head)) - if head in ACRONYMS: - head = ACRONYMS[head] - #log.debug('head: %s'%(head)) - t = ''.join((base, sep, head, INVOKER)) - #log.debug("setting text: '%s'"%(t)) - gobject.idle_add(tb.set_text, t) - - @log_calls('AcronymsExpanderPlugin') - def connect_with_chat_control_base(self, chat_control): - d = {} - tv = chat_control.msg_textview - tb = tv.get_buffer() - h_id = tb.connect('changed', self.textbuffer_live_acronym_expander) - d['h_id'] = h_id + self.gui_extension_points = { + 'chat_control_base': (self.connect_with_chat_control_base, + self.disconnect_from_chat_control_base) + } - chat_control.acronyms_expander_plugin_data = d + self.config_default_values = { + 'INVOKER': (' ', _('')), + 'ACRONYMS': ({'RTFM': 'Read The Friendly Manual', + '/slap': '/me slaps', + 'PS-': 'plug-in system', + 'G-': 'Gajim', + 'GNT-': 'http://trac.gajim.org/newticket', + 'GW-': 'http://trac.gajim.org/', + 'GTS-': 'http://trac.gajim.org/report', + }, + _('')), + } - return True + @log_calls('AcronymsExpanderPlugin') + def textbuffer_live_acronym_expander(self, tb): + """ + @param tb gtk.TextBuffer + """ + #assert isinstance(tb,gtk.TextBuffer) + ACRONYMS = self.config['ACRONYMS'] + INVOKER = self.config['INVOKER'] + t = tb.get_text(tb.get_start_iter(), tb.get_end_iter()) + #log.debug('%s %d'%(t, len(t))) + if t and t[-1] == INVOKER: + #log.debug('changing msg text') + base, sep, head=t[:-1].rpartition(INVOKER) + log.debug('%s | %s | %s'%(base, sep, head)) + if head in ACRONYMS: + head = ACRONYMS[head] + #log.debug('head: %s'%(head)) + t = ''.join((base, sep, head, INVOKER)) + #log.debug("setting text: '%s'"%(t)) + gobject.idle_add(tb.set_text, t) - @log_calls('AcronymsExpanderPlugin') - def disconnect_from_chat_control_base(self, chat_control): - d = chat_control.acronyms_expander_plugin_data - tv = chat_control.msg_textview - tv.get_buffer().disconnect(d['h_id']) - + @log_calls('AcronymsExpanderPlugin') + def connect_with_chat_control_base(self, chat_control): + d = {} + tv = chat_control.msg_textview + tb = tv.get_buffer() + h_id = tb.connect('changed', self.textbuffer_live_acronym_expander) + d['h_id'] = h_id + + chat_control.acronyms_expander_plugin_data = d + + return True + + @log_calls('AcronymsExpanderPlugin') + def disconnect_from_chat_control_base(self, chat_control): + d = chat_control.acronyms_expander_plugin_data + tv = chat_control.msg_textview + tv.get_buffer().disconnect(d['h_id']) diff --git a/plugins/banner_tweaks/__init__.py b/plugins/banner_tweaks/__init__.py index f8266d228..a328f68ee 100644 --- a/plugins/banner_tweaks/__init__.py +++ b/plugins/banner_tweaks/__init__.py @@ -1,2 +1,2 @@ -from plugin import BannerTweaksPlugin
\ No newline at end of file +from plugin import BannerTweaksPlugin diff --git a/plugins/banner_tweaks/plugin.py b/plugins/banner_tweaks/plugin.py index ad03765db..121606aa4 100644 --- a/plugins/banner_tweaks/plugin.py +++ b/plugins/banner_tweaks/plugin.py @@ -43,163 +43,163 @@ from plugins.helpers import log, log_calls from plugins.gui import GajimPluginConfigDialog class BannerTweaksPlugin(GajimPlugin): - name = u'Banner Tweaks' - short_name = u'banner_tweaks' - version = u'0.1' - description = u'''Allows user to tweak chat window banner appearance (eg. make it compact). - -Based on patch by pb in ticket #4133: + name = u'Banner Tweaks' + short_name = u'banner_tweaks' + version = u'0.1' + description = u'''Allows user to tweak chat window banner appearance (eg. make it compact). + +Based on patch by pb in ticket #4133: http://trac.gajim.org/attachment/ticket/4133''' - authors = [u'Mateusz Biliński <mateusz@bilinski.it>'] - homepage = u'http://blog.bilinski.it' - - @log_calls('BannerTweaksPlugin') - def init(self): - self.config_dialog = BannerTweaksPluginConfigDialog(self) - - self.gui_extension_points = { - 'chat_control_base_draw_banner' : (self.chat_control_base_draw_banner_called, - self.chat_control_base_draw_banner_deactivation) - } - - self.config_default_values = {'show_banner_image': (True, _('If True, Gajim will display a status icon in the banner of chat windows.')), - 'show_banner_online_msg': (True, _('If True, Gajim will display the status message of the contact in the banner of chat windows.')), - 'show_banner_resource': (False, _('If True, Gajim will display the resource name of the contact in the banner of chat windows.')), - 'banner_small_fonts': (False, _('If True, Gajim will use small fonts for contact name and resource name in the banner of chat windows.')), - 'old_chat_avatar_height' : (52, _('chat_avatar_height value before plugin was activated')), - } - - @log_calls('BannerTweaksPlugin') - def activate(self): - self.config['old_chat_avatar_height'] = gajim.config.get('chat_avatar_height') - #gajim.config.set('chat_avatar_height', 28) - - @log_calls('BannerTweaksPlugin') - def deactivate(self): - gajim.config.set('chat_avatar_height', self.config['old_chat_avatar_height']) - - @log_calls('BannerTweaksPlugin') - def chat_control_base_draw_banner_called(self, chat_control): - if not self.config['show_banner_online_msg']: - chat_control.banner_status_label.hide() - chat_control.banner_status_label.set_no_show_all(True) - status_text = '' - chat_control.banner_status_label.set_markup(status_text) - - if not self.config['show_banner_image']: - banner_status_img = chat_control.xml.get_object('banner_status_image') - banner_status_img.clear() - - # TODO: part below repeats a lot of code from ChatControl.draw_banner_text() - # This could be rewritten using re module: getting markup text from - # banner_name_label and replacing some elements based on plugin config. - # Would it be faster? - if self.config['show_banner_resource'] or self.config['banner_small_fonts']: - banner_name_label = chat_control.xml.get_object('banner_name_label') - label_text = banner_name_label.get_label() - - contact = chat_control.contact - jid = contact.jid - - name = contact.get_shown_name() - if chat_control.resource: - name += '/' + chat_control.resource - elif contact.resource and self.config['show_banner_resource']: - name += '/' + contact.resource - - if chat_control.TYPE_ID == message_control.TYPE_PM: - name = _('%(nickname)s from group chat %(room_name)s') %\ - {'nickname': name, 'room_name': chat_control.room_name} - name = gobject.markup_escape_text(name) - - # We know our contacts nick, but if another contact has the same nick - # in another account we need to also display the account. - # except if we are talking to two different resources of the same contact - acct_info = '' - for account in gajim.contacts.get_accounts(): - if account == chat_control.account: - continue - if acct_info: # We already found a contact with same nick - break - for jid in gajim.contacts.get_jid_list(account): - other_contact_ = \ - gajim.contacts.get_first_contact_from_jid(account, jid) - if other_contact_.get_shown_name() == chat_control.contact.get_shown_name(): - acct_info = ' (%s)' % \ - gobject.markup_escape_text(chat_control.account) - break - - font_attrs, font_attrs_small = chat_control.get_font_attrs() - if self.config['banner_small_fonts']: - font_attrs = font_attrs_small - - st = gajim.config.get('displayed_chat_state_notifications') - cs = contact.chatstate - if cs and st in ('composing_only', 'all'): - if contact.show == 'offline': - chatstate = '' - elif contact.composing_xep == 'XEP-0085': - if st == 'all' or cs == 'composing': - chatstate = helpers.get_uf_chatstate(cs) - else: - chatstate = '' - elif contact.composing_xep == 'XEP-0022': - if cs in ('composing', 'paused'): - # only print composing, paused - chatstate = helpers.get_uf_chatstate(cs) - else: - chatstate = '' - else: - # When does that happen ? See [7797] and [7804] - chatstate = helpers.get_uf_chatstate(cs) - - label_text = '<span %s>%s</span><span %s>%s %s</span>' % \ - (font_attrs, name, font_attrs_small, acct_info, chatstate) - else: - # weight="heavy" size="x-large" - label_text = '<span %s>%s</span><span %s>%s</span>' % \ - (font_attrs, name, font_attrs_small, acct_info) - - banner_name_label.set_markup(label_text) - - @log_calls('BannerTweaksPlugin') - def chat_control_base_draw_banner_deactivation(self, chat_control): - pass - #chat_control.draw_banner() - + authors = [u'Mateusz Biliński <mateusz@bilinski.it>'] + homepage = u'http://blog.bilinski.it' + + @log_calls('BannerTweaksPlugin') + def init(self): + self.config_dialog = BannerTweaksPluginConfigDialog(self) + + self.gui_extension_points = { + 'chat_control_base_draw_banner': (self.chat_control_base_draw_banner_called, + self.chat_control_base_draw_banner_deactivation) + } + + self.config_default_values = { + 'show_banner_image': (True, _('If True, Gajim will display a status icon in the banner of chat windows.')), + 'show_banner_online_msg': (True, _('If True, Gajim will display the status message of the contact in the banner of chat windows.')), + 'show_banner_resource': (False, _('If True, Gajim will display the resource name of the contact in the banner of chat windows.')), + 'banner_small_fonts': (False, _('If True, Gajim will use small fonts for contact name and resource name in the banner of chat windows.')), + 'old_chat_avatar_height': (52, _('chat_avatar_height value before plugin was activated')), + } + + @log_calls('BannerTweaksPlugin') + def activate(self): + self.config['old_chat_avatar_height'] = gajim.config.get('chat_avatar_height') + #gajim.config.set('chat_avatar_height', 28) + + @log_calls('BannerTweaksPlugin') + def deactivate(self): + gajim.config.set('chat_avatar_height', self.config['old_chat_avatar_height']) + + @log_calls('BannerTweaksPlugin') + def chat_control_base_draw_banner_called(self, chat_control): + if not self.config['show_banner_online_msg']: + chat_control.banner_status_label.hide() + chat_control.banner_status_label.set_no_show_all(True) + status_text = '' + chat_control.banner_status_label.set_markup(status_text) + + if not self.config['show_banner_image']: + banner_status_img = chat_control.xml.get_object('banner_status_image') + banner_status_img.clear() + + # TODO: part below repeats a lot of code from ChatControl.draw_banner_text() + # This could be rewritten using re module: getting markup text from + # banner_name_label and replacing some elements based on plugin config. + # Would it be faster? + if self.config['show_banner_resource'] or self.config['banner_small_fonts']: + banner_name_label = chat_control.xml.get_object('banner_name_label') + label_text = banner_name_label.get_label() + + contact = chat_control.contact + jid = contact.jid + + name = contact.get_shown_name() + if chat_control.resource: + name += '/' + chat_control.resource + elif contact.resource and self.config['show_banner_resource']: + name += '/' + contact.resource + + if chat_control.TYPE_ID == message_control.TYPE_PM: + name = _('%(nickname)s from group chat %(room_name)s') %\ + {'nickname': name, 'room_name': chat_control.room_name} + name = gobject.markup_escape_text(name) + + # We know our contacts nick, but if another contact has the same nick + # in another account we need to also display the account. + # except if we are talking to two different resources of the same contact + acct_info = '' + for account in gajim.contacts.get_accounts(): + if account == chat_control.account: + continue + if acct_info: # We already found a contact with same nick + break + for jid in gajim.contacts.get_jid_list(account): + other_contact_ = \ + gajim.contacts.get_first_contact_from_jid(account, jid) + if other_contact_.get_shown_name() == chat_control.contact.get_shown_name(): + acct_info = ' (%s)' % \ + gobject.markup_escape_text(chat_control.account) + break + + font_attrs, font_attrs_small = chat_control.get_font_attrs() + if self.config['banner_small_fonts']: + font_attrs = font_attrs_small + + st = gajim.config.get('displayed_chat_state_notifications') + cs = contact.chatstate + if cs and st in ('composing_only', 'all'): + if contact.show == 'offline': + chatstate = '' + elif contact.composing_xep == 'XEP-0085': + if st == 'all' or cs == 'composing': + chatstate = helpers.get_uf_chatstate(cs) + else: + chatstate = '' + elif contact.composing_xep == 'XEP-0022': + if cs in ('composing', 'paused'): + # only print composing, paused + chatstate = helpers.get_uf_chatstate(cs) + else: + chatstate = '' + else: + # When does that happen ? See [7797] and [7804] + chatstate = helpers.get_uf_chatstate(cs) + + label_text = '<span %s>%s</span><span %s>%s %s</span>' % \ + (font_attrs, name, font_attrs_small, acct_info, chatstate) + else: + # weight="heavy" size="x-large" + label_text = '<span %s>%s</span><span %s>%s</span>' % \ + (font_attrs, name, font_attrs_small, acct_info) + + banner_name_label.set_markup(label_text) + + @log_calls('BannerTweaksPlugin') + def chat_control_base_draw_banner_deactivation(self, chat_control): + pass + #chat_control.draw_banner() + class BannerTweaksPluginConfigDialog(GajimPluginConfigDialog): - def init(self): - self.GTK_BUILDER_FILE_PATH = self.plugin.local_file_path( - 'config_dialog.ui') - self.xml = gtk.Builder() - self.xml.set_translation_domain(i18n.APP) - self.xml.add_objects_from_file(self.GTK_BUILDER_FILE_PATH, - ['banner_tweaks_config_vbox']) - self.config_vbox = self.xml.get_object('banner_tweaks_config_vbox') - self.child.pack_start(self.config_vbox) - - self.show_banner_image_checkbutton = self.xml.get_object('show_banner_image_checkbutton') - self.show_banner_online_msg_checkbutton = self.xml.get_object('show_banner_online_msg_checkbutton') - self.show_banner_resource_checkbutton = self.xml.get_object('show_banner_resource_checkbutton') - self.banner_small_fonts_checkbutton = self.xml.get_object('banner_small_fonts_checkbutton') - - self.xml.connect_signals(self) - - def on_run(self): - self.show_banner_image_checkbutton.set_active(self.plugin.config['show_banner_image']) - self.show_banner_online_msg_checkbutton.set_active(self.plugin.config['show_banner_online_msg']) - self.show_banner_resource_checkbutton.set_active(self.plugin.config['show_banner_resource']) - self.banner_small_fonts_checkbutton.set_active(self.plugin.config['banner_small_fonts']) - - def on_show_banner_image_checkbutton_toggled(self, button): - self.plugin.config['show_banner_image'] = button.get_active() - - def on_show_banner_online_msg_checkbutton_toggled(self, button): - self.plugin.config['show_banner_online_msg'] = button.get_active() - - def on_show_banner_resource_checkbutton_toggled(self, button): - self.plugin.config['show_banner_resource'] = button.get_active() - - def on_banner_small_fonts_checkbutton_toggled(self, button): - self.plugin.config['banner_small_fonts'] = button.get_active() - + def init(self): + self.GTK_BUILDER_FILE_PATH = self.plugin.local_file_path( + 'config_dialog.ui') + self.xml = gtk.Builder() + self.xml.set_translation_domain(i18n.APP) + self.xml.add_objects_from_file(self.GTK_BUILDER_FILE_PATH, + ['banner_tweaks_config_vbox']) + self.config_vbox = self.xml.get_object('banner_tweaks_config_vbox') + self.child.pack_start(self.config_vbox) + + self.show_banner_image_checkbutton = self.xml.get_object('show_banner_image_checkbutton') + self.show_banner_online_msg_checkbutton = self.xml.get_object('show_banner_online_msg_checkbutton') + self.show_banner_resource_checkbutton = self.xml.get_object('show_banner_resource_checkbutton') + self.banner_small_fonts_checkbutton = self.xml.get_object('banner_small_fonts_checkbutton') + + self.xml.connect_signals(self) + + def on_run(self): + self.show_banner_image_checkbutton.set_active(self.plugin.config['show_banner_image']) + self.show_banner_online_msg_checkbutton.set_active(self.plugin.config['show_banner_online_msg']) + self.show_banner_resource_checkbutton.set_active(self.plugin.config['show_banner_resource']) + self.banner_small_fonts_checkbutton.set_active(self.plugin.config['banner_small_fonts']) + + def on_show_banner_image_checkbutton_toggled(self, button): + self.plugin.config['show_banner_image'] = button.get_active() + + def on_show_banner_online_msg_checkbutton_toggled(self, button): + self.plugin.config['show_banner_online_msg'] = button.get_active() + + def on_show_banner_resource_checkbutton_toggled(self, button): + self.plugin.config['show_banner_resource'] = button.get_active() + + def on_banner_small_fonts_checkbutton_toggled(self, button): + self.plugin.config['banner_small_fonts'] = button.get_active() diff --git a/plugins/dbus_plugin/__init__.py b/plugins/dbus_plugin/__init__.py index c5c296ad7..3851c6bb9 100644 --- a/plugins/dbus_plugin/__init__.py +++ b/plugins/dbus_plugin/__init__.py @@ -1 +1 @@ -from plugin import DBusPlugin
\ No newline at end of file +from plugin import DBusPlugin diff --git a/plugins/dbus_plugin/plugin.py b/plugins/dbus_plugin/plugin.py index ac26c3b1d..c34e0ad0c 100644 --- a/plugins/dbus_plugin/plugin.py +++ b/plugins/dbus_plugin/plugin.py @@ -6,7 +6,7 @@ ## Copyright (C) 2005-2006 Andrew Sayman <lorien420@myrealbox.com> ## Copyright (C) 2007 Lukas Petrovicky <lukas@petrovicky.net> ## Copyright (C) 2007 Julien Pivotto <roidelapluie@gmail.com> -## Copyright (C) 2007 Travis Shirk <travis@pobox.com> +## Copyright (C) 2007 Travis Shirk <travis@pobox.com> ## Copyright (C) 2008 Mateusz Biliński <mateusz@bilinski.it> ## ## This file is part of Gajim. @@ -41,634 +41,634 @@ import gobject from common import dbus_support if dbus_support.supported: - import dbus - if dbus_support: - INTERFACE = 'org.gajim.dbusplugin.RemoteInterface' - OBJ_PATH = '/org/gajim/dbusplugin/RemoteObject' - SERVICE = 'org.gajim.dbusplugin' - - import dbus.service - import dbus.glib - # type mapping - - # in most cases it is a utf-8 string - DBUS_STRING = dbus.String - - # general type (for use in dicts, where all values should have the same type) - DBUS_BOOLEAN = dbus.Boolean - DBUS_DOUBLE = dbus.Double - DBUS_INT32 = dbus.Int32 - # dictionary with string key and binary value - DBUS_DICT_SV = lambda : dbus.Dictionary({}, signature="sv") - # dictionary with string key and value - DBUS_DICT_SS = lambda : dbus.Dictionary({}, signature="ss") - # empty type (there is no equivalent of None on D-Bus, but historically gajim - # used 0 instead) - DBUS_NONE = lambda : dbus.Int32(0) - - def get_dbus_struct(obj): - ''' recursively go through all the items and replace - them with their casted dbus equivalents - ''' - if obj is None: - return DBUS_NONE() - if isinstance(obj, (unicode, str)): - return DBUS_STRING(obj) - if isinstance(obj, int): - return DBUS_INT32(obj) - if isinstance(obj, float): - return DBUS_DOUBLE(obj) - if isinstance(obj, bool): - return DBUS_BOOLEAN(obj) - if isinstance(obj, (list, tuple)): - result = dbus.Array([get_dbus_struct(i) for i in obj], - signature='v') - if result == []: - return DBUS_NONE() - return result - if isinstance(obj, dict): - result = DBUS_DICT_SV() - for key, value in obj.items(): - result[DBUS_STRING(key)] = get_dbus_struct(value) - if result == {}: - return DBUS_NONE() - return result - # unknown type - return DBUS_NONE() - - class SignalObject(dbus.service.Object): - ''' Local object definition for /org/gajim/dbus/RemoteObject. - (This docstring is not be visible, because the clients can access only the remote object.)''' - - def __init__(self, bus_name): - self.first_show = True - self.vcard_account = None - - # register our dbus API - dbus.service.Object.__init__(self, bus_name, OBJ_PATH) - - @dbus.service.signal(INTERFACE, signature='av') - def Roster(self, account_and_data): - pass - - @dbus.service.signal(INTERFACE, signature='av') - def AccountPresence(self, status_and_account): - pass - - @dbus.service.signal(INTERFACE, signature='av') - def ContactPresence(self, account_and_array): - pass - - @dbus.service.signal(INTERFACE, signature='av') - def ContactAbsence(self, account_and_array): - pass - - @dbus.service.signal(INTERFACE, signature='av') - def ContactStatus(self, account_and_array): - pass - - @dbus.service.signal(INTERFACE, signature='av') - def NewMessage(self, account_and_array): - pass - - @dbus.service.signal(INTERFACE, signature='av') - def Subscribe(self, account_and_array): - pass - - @dbus.service.signal(INTERFACE, signature='av') - def Subscribed(self, account_and_array): - pass - - @dbus.service.signal(INTERFACE, signature='av') - def Unsubscribed(self, account_and_jid): - pass - - @dbus.service.signal(INTERFACE, signature='av') - def NewAccount(self, account_and_array): - pass - - @dbus.service.signal(INTERFACE, signature='av') - def VcardInfo(self, account_and_vcard): - pass - - @dbus.service.signal(INTERFACE, signature='av') - def LastStatusTime(self, account_and_array): - pass - - @dbus.service.signal(INTERFACE, signature='av') - def OsInfo(self, account_and_array): - pass - - @dbus.service.signal(INTERFACE, signature='av') - def GCPresence(self, account_and_array): - pass - - @dbus.service.signal(INTERFACE, signature='av') - def GCMessage(self, account_and_array): - pass - - @dbus.service.signal(INTERFACE, signature='av') - def RosterInfo(self, account_and_array): - pass - - @dbus.service.signal(INTERFACE, signature='av') - def NewGmail(self, account_and_array): - pass - - def raise_signal(self, signal, arg): - '''raise a signal, with a single argument of unspecified type - Instead of obj.raise_signal("Foo", bar), use obj.Foo(bar).''' - getattr(self, signal)(arg) - - @dbus.service.method(INTERFACE, in_signature='s', out_signature='s') - def get_status(self, account): - '''Returns status (show to be exact) which is the global one - unless account is given''' - if not account: - # If user did not ask for account, returns the global status - return DBUS_STRING(helpers.get_global_show()) - # return show for the given account - index = gajim.connections[account].connected - return DBUS_STRING(gajim.SHOW_LIST[index]) - - @dbus.service.method(INTERFACE, in_signature='s', out_signature='s') - def get_status_message(self, account): - '''Returns status which is the global one - unless account is given''' - if not account: - # If user did not ask for account, returns the global status - return DBUS_STRING(str(helpers.get_global_status())) - # return show for the given account - status = gajim.connections[account].status - return DBUS_STRING(status) - - def _get_account_and_contact(self, account, jid): - '''get the account (if not given) and contact instance from jid''' - connected_account = None - contact = None - accounts = gajim.contacts.get_accounts() - # if there is only one account in roster, take it as default - # if user did not ask for account - if not account and len(accounts) == 1: - account = accounts[0] - if account: - if gajim.connections[account].connected > 1: # account is connected - connected_account = account - contact = gajim.contacts.get_contact_with_highest_priority(account, - jid) - else: - for account in accounts: - contact = gajim.contacts.get_contact_with_highest_priority(account, - jid) - if contact and gajim.connections[account].connected > 1: - # account is connected - connected_account = account - break - if not contact: - contact = jid - - return connected_account, contact - - def _get_account_for_groupchat(self, account, room_jid): - '''get the account which is connected to groupchat (if not given) - or check if the given account is connected to the groupchat''' - connected_account = None - accounts = gajim.contacts.get_accounts() - # if there is only one account in roster, take it as default - # if user did not ask for account - if not account and len(accounts) == 1: - account = accounts[0] - if account: - if gajim.connections[account].connected > 1 and \ - room_jid in gajim.gc_connected[account] and \ - gajim.gc_connected[account][room_jid]: - # account and groupchat are connected - connected_account = account - else: - for account in accounts: - if gajim.connections[account].connected > 1 and \ - room_jid in gajim.gc_connected[account] and \ - gajim.gc_connected[account][room_jid]: - # account and groupchat are connected - connected_account = account - break - return connected_account - - @dbus.service.method(INTERFACE, in_signature='sss', out_signature='b') - def send_file(self, file_path, jid, account): - '''send file, located at 'file_path' to 'jid', using account - (optional) 'account' ''' - jid = self._get_real_jid(jid, account) - connected_account, contact = self._get_account_and_contact(account, jid) - - if connected_account: - if file_path[:7] == 'file://': - file_path=file_path[7:] - if os.path.isfile(file_path): # is it file? - gajim.interface.instances['file_transfers'].send_file( - connected_account, contact, file_path) - return DBUS_BOOLEAN(True) - return DBUS_BOOLEAN(False) - - def _send_message(self, jid, message, keyID, account, type = 'chat', - subject = None): - '''can be called from send_chat_message (default when send_message) - or send_single_message''' - if not jid or not message: - return DBUS_BOOLEAN(False) - if not keyID: - keyID = '' - - connected_account, contact = self._get_account_and_contact(account, jid) - if connected_account: - connection = gajim.connections[connected_account] - connection.send_message(jid, message, keyID, type, subject) - return DBUS_BOOLEAN(True) - return DBUS_BOOLEAN(False) - - @dbus.service.method(INTERFACE, in_signature='ssss', out_signature='b') - def send_chat_message(self, jid, message, keyID, account): - '''Send chat 'message' to 'jid', using account (optional) 'account'. - if keyID is specified, encrypt the message with the pgp key ''' - jid = self._get_real_jid(jid, account) - return self._send_message(jid, message, keyID, account) - - @dbus.service.method(INTERFACE, in_signature='sssss', out_signature='b') - def send_single_message(self, jid, subject, message, keyID, account): - '''Send single 'message' to 'jid', using account (optional) 'account'. - if keyID is specified, encrypt the message with the pgp key ''' - jid = self._get_real_jid(jid, account) - return self._send_message(jid, message, keyID, account, type, subject) - - @dbus.service.method(INTERFACE, in_signature='sss', out_signature='b') - def send_groupchat_message(self, room_jid, message, account): - '''Send 'message' to groupchat 'room_jid', - using account (optional) 'account'.''' - if not room_jid or not message: - return DBUS_BOOLEAN(False) - connected_account = self._get_account_for_groupchat(account, room_jid) - if connected_account: - connection = gajim.connections[connected_account] - connection.send_gc_message(room_jid, message) - return DBUS_BOOLEAN(True) - return DBUS_BOOLEAN(False) - - @dbus.service.method(INTERFACE, in_signature='ss', out_signature='b') - def open_chat(self, jid, account): - '''Shows the tabbed window for new message to 'jid', using account - (optional) 'account' ''' - if not jid: - raise MissingArgument - return DBUS_BOOLEAN(False) - jid = self._get_real_jid(jid, account) - try: - jid = helpers.parse_jid(jid) - except: - # Jid is not conform, ignore it - return DBUS_BOOLEAN(False) - - if account: - accounts = [account] - else: - accounts = gajim.connections.keys() - if len(accounts) == 1: - account = accounts[0] - connected_account = None - first_connected_acct = None - for acct in accounts: - if gajim.connections[acct].connected > 1: # account is online - contact = gajim.contacts.get_first_contact_from_jid(acct, jid) - if gajim.interface.msg_win_mgr.has_window(jid, acct): - connected_account = acct - break - # jid is in roster - elif contact: - connected_account = acct - break - # we send the message to jid not in roster, because account is - # specified, or there is only one account - elif account: - connected_account = acct - elif first_connected_acct is None: - first_connected_acct = acct - - # if jid is not a conntact, open-chat with first connected account - if connected_account is None and first_connected_acct: - connected_account = first_connected_acct - - if connected_account: - gajim.interface.new_chat_from_jid(connected_account, jid) - # preserve the 'steal focus preservation' - win = gajim.interface.msg_win_mgr.get_window(jid, - connected_account).window - if win.get_property('visible'): - win.window.focus() - return DBUS_BOOLEAN(True) - return DBUS_BOOLEAN(False) - - @dbus.service.method(INTERFACE, in_signature='sss', out_signature='b') - def change_status(self, status, message, account): - ''' change_status(status, message, account). account is optional - - if not specified status is changed for all accounts. ''' - if status not in ('offline', 'online', 'chat', - 'away', 'xa', 'dnd', 'invisible'): - return DBUS_BOOLEAN(False) - if account: - gobject.idle_add(gajim.interface.roster.send_status, account, - status, message) - else: - # account not specified, so change the status of all accounts - for acc in gajim.contacts.get_accounts(): - if not gajim.config.get_per('accounts', acc, - 'sync_with_global_status'): - continue - gobject.idle_add(gajim.interface.roster.send_status, acc, - status, message) - return DBUS_BOOLEAN(False) - - @dbus.service.method(INTERFACE, in_signature='', out_signature='') - def show_next_pending_event(self): - '''Show the window(s) with next pending event in tabbed/group chats.''' - if gajim.events.get_nb_events(): - gajim.interface.systray.handle_first_event() - - @dbus.service.method(INTERFACE, in_signature='s', out_signature='a{sv}') - def contact_info(self, jid): - '''get vcard info for a contact. Return cached value of the vcard. - ''' - if not isinstance(jid, unicode): - jid = unicode(jid) - if not jid: - raise MissingArgument - return DBUS_DICT_SV() - jid = self._get_real_jid(jid) - - cached_vcard = gajim.connections.values()[0].get_cached_vcard(jid) - if cached_vcard: - return get_dbus_struct(cached_vcard) - - # return empty dict - return DBUS_DICT_SV() - - @dbus.service.method(INTERFACE, in_signature='', out_signature='as') - def list_accounts(self): - '''list register accounts''' - result = gajim.contacts.get_accounts() - result_array = dbus.Array([], signature='s') - if result and len(result) > 0: - for account in result: - result_array.append(DBUS_STRING(account)) - return result_array - - @dbus.service.method(INTERFACE, in_signature='s', out_signature='a{ss}') - def account_info(self, account): - '''show info on account: resource, jid, nick, prio, message''' - result = DBUS_DICT_SS() - if gajim.connections.has_key(account): - # account is valid - con = gajim.connections[account] - index = con.connected - result['status'] = DBUS_STRING(gajim.SHOW_LIST[index]) - result['name'] = DBUS_STRING(con.name) - result['jid'] = DBUS_STRING(gajim.get_jid_from_account(con.name)) - result['message'] = DBUS_STRING(con.status) - result['priority'] = DBUS_STRING(unicode(con.priority)) - result['resource'] = DBUS_STRING(unicode(gajim.config.get_per( - 'accounts', con.name, 'resource'))) - return result - - @dbus.service.method(INTERFACE, in_signature='s', out_signature='aa{sv}') - def list_contacts(self, account): - '''list all contacts in the roster. If the first argument is specified, - then return the contacts for the specified account''' - result = dbus.Array([], signature='aa{sv}') - accounts = gajim.contacts.get_accounts() - if len(accounts) == 0: - return result - if account: - accounts_to_search = [account] - else: - accounts_to_search = accounts - for acct in accounts_to_search: - if acct in accounts: - for jid in gajim.contacts.get_jid_list(acct): - item = self._contacts_as_dbus_structure( - gajim.contacts.get_contacts(acct, jid)) - if item: - result.append(item) - return result - - @dbus.service.method(INTERFACE, in_signature='', out_signature='') - def toggle_roster_appearance(self): - ''' shows/hides the roster window ''' - win = gajim.interface.roster.window - if win.get_property('visible'): - gobject.idle_add(win.hide) - else: - win.present() - # preserve the 'steal focus preservation' - if self._is_first(): - win.window.focus() - else: - win.window.focus(long(time())) - - @dbus.service.method(INTERFACE, in_signature='', out_signature='') - def toggle_ipython(self): - ''' shows/hides the ipython window ''' - win = gajim.ipython_window - if win: - if win.window.is_visible(): - gobject.idle_add(win.hide) - else: - win.show_all() - win.present() - else: - gajim.interface.create_ipython_window() - - @dbus.service.method(INTERFACE, in_signature='', out_signature='a{ss}') - def prefs_list(self): - prefs_dict = DBUS_DICT_SS() - def get_prefs(data, name, path, value): - if value is None: - return - key = '' - if path is not None: - for node in path: - key += node + '#' - key += name - prefs_dict[DBUS_STRING(key)] = DBUS_STRING(value[1]) - gajim.config.foreach(get_prefs) - return prefs_dict - - @dbus.service.method(INTERFACE, in_signature='', out_signature='b') - def prefs_store(self): - try: - gajim.interface.save_config() - except Exception, e: - return DBUS_BOOLEAN(False) - return DBUS_BOOLEAN(True) - - @dbus.service.method(INTERFACE, in_signature='s', out_signature='b') - def prefs_del(self, key): - if not key: - return DBUS_BOOLEAN(False) - key_path = key.split('#', 2) - if len(key_path) != 3: - return DBUS_BOOLEAN(False) - if key_path[2] == '*': - gajim.config.del_per(key_path[0], key_path[1]) - else: - gajim.config.del_per(key_path[0], key_path[1], key_path[2]) - return DBUS_BOOLEAN(True) - - @dbus.service.method(INTERFACE, in_signature='s', out_signature='b') - def prefs_put(self, key): - if not key: - return DBUS_BOOLEAN(False) - key_path = key.split('#', 2) - if len(key_path) < 3: - subname, value = key.split('=', 1) - gajim.config.set(subname, value) - return DBUS_BOOLEAN(True) - subname, value = key_path[2].split('=', 1) - gajim.config.set_per(key_path[0], key_path[1], subname, value) - return DBUS_BOOLEAN(True) - - @dbus.service.method(INTERFACE, in_signature='ss', out_signature='b') - def add_contact(self, jid, account): - if account: - if account in gajim.connections and \ - gajim.connections[account].connected > 1: - # if given account is active, use it - AddNewContactWindow(account = account, jid = jid) - else: - # wrong account - return DBUS_BOOLEAN(False) - else: - # if account is not given, show account combobox - AddNewContactWindow(account = None, jid = jid) - return DBUS_BOOLEAN(True) - - @dbus.service.method(INTERFACE, in_signature='ss', out_signature='b') - def remove_contact(self, jid, account): - jid = self._get_real_jid(jid, account) - accounts = gajim.contacts.get_accounts() - - # if there is only one account in roster, take it as default - if account: - accounts = [account] - contact_exists = False - for account in accounts: - contacts = gajim.contacts.get_contacts(account, jid) - if contacts: - gajim.connections[account].unsubscribe(jid) - for contact in contacts: - gajim.interface.roster.remove_contact(contact, account) - gajim.contacts.remove_jid(account, jid) - contact_exists = True - return DBUS_BOOLEAN(contact_exists) - - def _is_first(self): - if self.first_show: - self.first_show = False - return True - return False - - def _get_real_jid(self, jid, account = None): - '''get the real jid from the given one: removes xmpp: or get jid from nick - if account is specified, search only in this account - ''' - if account: - accounts = [account] - else: - accounts = gajim.connections.keys() - if jid.startswith('xmpp:'): - return jid[5:] # len('xmpp:') = 5 - nick_in_roster = None # Is jid a nick ? - for account in accounts: - # Does jid exists in roster of one account ? - if gajim.contacts.get_contacts(account, jid): - return jid - if not nick_in_roster: - # look in all contact if one has jid as nick - for jid_ in gajim.contacts.get_jid_list(account): - c = gajim.contacts.get_contacts(account, jid_) - if c[0].name == jid: - nick_in_roster = jid_ - break - if nick_in_roster: - # We have not found jid in roster, but we found is as a nick - return nick_in_roster - # We have not found it as jid nor as nick, probably a not in roster jid - return jid - - def _contacts_as_dbus_structure(self, contacts): - ''' get info from list of Contact objects and create dbus dict ''' - if not contacts: - return None - prim_contact = None # primary contact - for contact in contacts: - if prim_contact is None or contact.priority > prim_contact.priority: - prim_contact = contact - contact_dict = DBUS_DICT_SV() - contact_dict['name'] = DBUS_STRING(prim_contact.name) - contact_dict['show'] = DBUS_STRING(prim_contact.show) - contact_dict['jid'] = DBUS_STRING(prim_contact.jid) - if prim_contact.keyID: - keyID = None - if len(prim_contact.keyID) == 8: - keyID = prim_contact.keyID - elif len(prim_contact.keyID) == 16: - keyID = prim_contact.keyID[8:] - if keyID: - contact_dict['openpgp'] = keyID - contact_dict['resources'] = dbus.Array([], signature='(sis)') - for contact in contacts: - resource_props = dbus.Struct((DBUS_STRING(contact.resource), - dbus.Int32(contact.priority), DBUS_STRING(contact.status))) - contact_dict['resources'].append(resource_props) - contact_dict['groups'] = dbus.Array([], signature='(s)') - for group in prim_contact.groups: - contact_dict['groups'].append((DBUS_STRING(group),)) - return contact_dict - - @dbus.service.method(INTERFACE, in_signature='', out_signature='s') - def get_unread_msgs_number(self): - return DBUS_STRING(str(gajim.events.get_nb_events())) - - @dbus.service.method(INTERFACE, in_signature='s', out_signature='b') - def start_chat(self, account): - if not account: - # error is shown in gajim-remote check_arguments(..) - return DBUS_BOOLEAN(False) - NewChatDialog(account) - return DBUS_BOOLEAN(True) - - @dbus.service.method(INTERFACE, in_signature='ss', out_signature='') - def send_xml(self, xml, account): - if account: - gajim.connections[account].send_stanza(xml) - else: - for acc in gajim.contacts.get_accounts(): - gajim.connections[acc].send_stanza(xml) - - @dbus.service.method(INTERFACE, in_signature='ssss', out_signature='') - def join_room(self, room_jid, nick, password, account): - if not account: - # get the first connected account - accounts = gajim.connections.keys() - for acct in accounts: - if gajim.account_is_connected(acct): - account = acct - break - if not account: - return - if not nick: - nick = '' - gajim.interface.instances[account]['join_gc'] = \ - JoinGroupchatWindow(account, room_jid, nick) - else: - gajim.interface.join_gc_room(account, room_jid, nick, password) + import dbus + if dbus_support: + INTERFACE = 'org.gajim.dbusplugin.RemoteInterface' + OBJ_PATH = '/org/gajim/dbusplugin/RemoteObject' + SERVICE = 'org.gajim.dbusplugin' + + import dbus.service + import dbus.glib + # type mapping + + # in most cases it is a utf-8 string + DBUS_STRING = dbus.String + + # general type (for use in dicts, where all values should have the same type) + DBUS_BOOLEAN = dbus.Boolean + DBUS_DOUBLE = dbus.Double + DBUS_INT32 = dbus.Int32 + # dictionary with string key and binary value + DBUS_DICT_SV = lambda : dbus.Dictionary({}, signature="sv") + # dictionary with string key and value + DBUS_DICT_SS = lambda : dbus.Dictionary({}, signature="ss") + # empty type (there is no equivalent of None on D-Bus, but historically gajim + # used 0 instead) + DBUS_NONE = lambda : dbus.Int32(0) + + def get_dbus_struct(obj): + ''' recursively go through all the items and replace + them with their casted dbus equivalents + ''' + if obj is None: + return DBUS_NONE() + if isinstance(obj, (unicode, str)): + return DBUS_STRING(obj) + if isinstance(obj, int): + return DBUS_INT32(obj) + if isinstance(obj, float): + return DBUS_DOUBLE(obj) + if isinstance(obj, bool): + return DBUS_BOOLEAN(obj) + if isinstance(obj, (list, tuple)): + result = dbus.Array([get_dbus_struct(i) for i in obj], + signature='v') + if result == []: + return DBUS_NONE() + return result + if isinstance(obj, dict): + result = DBUS_DICT_SV() + for key, value in obj.items(): + result[DBUS_STRING(key)] = get_dbus_struct(value) + if result == {}: + return DBUS_NONE() + return result + # unknown type + return DBUS_NONE() + + class SignalObject(dbus.service.Object): + ''' Local object definition for /org/gajim/dbus/RemoteObject. + (This docstring is not be visible, because the clients can access only the remote object.)''' + + def __init__(self, bus_name): + self.first_show = True + self.vcard_account = None + + # register our dbus API + dbus.service.Object.__init__(self, bus_name, OBJ_PATH) + + @dbus.service.signal(INTERFACE, signature='av') + def Roster(self, account_and_data): + pass + + @dbus.service.signal(INTERFACE, signature='av') + def AccountPresence(self, status_and_account): + pass + + @dbus.service.signal(INTERFACE, signature='av') + def ContactPresence(self, account_and_array): + pass + + @dbus.service.signal(INTERFACE, signature='av') + def ContactAbsence(self, account_and_array): + pass + + @dbus.service.signal(INTERFACE, signature='av') + def ContactStatus(self, account_and_array): + pass + + @dbus.service.signal(INTERFACE, signature='av') + def NewMessage(self, account_and_array): + pass + + @dbus.service.signal(INTERFACE, signature='av') + def Subscribe(self, account_and_array): + pass + + @dbus.service.signal(INTERFACE, signature='av') + def Subscribed(self, account_and_array): + pass + + @dbus.service.signal(INTERFACE, signature='av') + def Unsubscribed(self, account_and_jid): + pass + + @dbus.service.signal(INTERFACE, signature='av') + def NewAccount(self, account_and_array): + pass + + @dbus.service.signal(INTERFACE, signature='av') + def VcardInfo(self, account_and_vcard): + pass + + @dbus.service.signal(INTERFACE, signature='av') + def LastStatusTime(self, account_and_array): + pass + + @dbus.service.signal(INTERFACE, signature='av') + def OsInfo(self, account_and_array): + pass + + @dbus.service.signal(INTERFACE, signature='av') + def GCPresence(self, account_and_array): + pass + + @dbus.service.signal(INTERFACE, signature='av') + def GCMessage(self, account_and_array): + pass + + @dbus.service.signal(INTERFACE, signature='av') + def RosterInfo(self, account_and_array): + pass + + @dbus.service.signal(INTERFACE, signature='av') + def NewGmail(self, account_and_array): + pass + + def raise_signal(self, signal, arg): + '''raise a signal, with a single argument of unspecified type + Instead of obj.raise_signal("Foo", bar), use obj.Foo(bar).''' + getattr(self, signal)(arg) + + @dbus.service.method(INTERFACE, in_signature='s', out_signature='s') + def get_status(self, account): + '''Returns status (show to be exact) which is the global one + unless account is given''' + if not account: + # If user did not ask for account, returns the global status + return DBUS_STRING(helpers.get_global_show()) + # return show for the given account + index = gajim.connections[account].connected + return DBUS_STRING(gajim.SHOW_LIST[index]) + + @dbus.service.method(INTERFACE, in_signature='s', out_signature='s') + def get_status_message(self, account): + '''Returns status which is the global one + unless account is given''' + if not account: + # If user did not ask for account, returns the global status + return DBUS_STRING(str(helpers.get_global_status())) + # return show for the given account + status = gajim.connections[account].status + return DBUS_STRING(status) + + def _get_account_and_contact(self, account, jid): + '''get the account (if not given) and contact instance from jid''' + connected_account = None + contact = None + accounts = gajim.contacts.get_accounts() + # if there is only one account in roster, take it as default + # if user did not ask for account + if not account and len(accounts) == 1: + account = accounts[0] + if account: + if gajim.connections[account].connected > 1: # account is connected + connected_account = account + contact = gajim.contacts.get_contact_with_highest_priority(account, + jid) + else: + for account in accounts: + contact = gajim.contacts.get_contact_with_highest_priority(account, + jid) + if contact and gajim.connections[account].connected > 1: + # account is connected + connected_account = account + break + if not contact: + contact = jid + + return connected_account, contact + + def _get_account_for_groupchat(self, account, room_jid): + '''get the account which is connected to groupchat (if not given) + or check if the given account is connected to the groupchat''' + connected_account = None + accounts = gajim.contacts.get_accounts() + # if there is only one account in roster, take it as default + # if user did not ask for account + if not account and len(accounts) == 1: + account = accounts[0] + if account: + if gajim.connections[account].connected > 1 and \ + room_jid in gajim.gc_connected[account] and \ + gajim.gc_connected[account][room_jid]: + # account and groupchat are connected + connected_account = account + else: + for account in accounts: + if gajim.connections[account].connected > 1 and \ + room_jid in gajim.gc_connected[account] and \ + gajim.gc_connected[account][room_jid]: + # account and groupchat are connected + connected_account = account + break + return connected_account + + @dbus.service.method(INTERFACE, in_signature='sss', out_signature='b') + def send_file(self, file_path, jid, account): + '''send file, located at 'file_path' to 'jid', using account + (optional) 'account' ''' + jid = self._get_real_jid(jid, account) + connected_account, contact = self._get_account_and_contact(account, jid) + + if connected_account: + if file_path[:7] == 'file://': + file_path=file_path[7:] + if os.path.isfile(file_path): # is it file? + gajim.interface.instances['file_transfers'].send_file( + connected_account, contact, file_path) + return DBUS_BOOLEAN(True) + return DBUS_BOOLEAN(False) + + def _send_message(self, jid, message, keyID, account, type = 'chat', + subject = None): + '''can be called from send_chat_message (default when send_message) + or send_single_message''' + if not jid or not message: + return DBUS_BOOLEAN(False) + if not keyID: + keyID = '' + + connected_account, contact = self._get_account_and_contact(account, jid) + if connected_account: + connection = gajim.connections[connected_account] + connection.send_message(jid, message, keyID, type, subject) + return DBUS_BOOLEAN(True) + return DBUS_BOOLEAN(False) + + @dbus.service.method(INTERFACE, in_signature='ssss', out_signature='b') + def send_chat_message(self, jid, message, keyID, account): + '''Send chat 'message' to 'jid', using account (optional) 'account'. + if keyID is specified, encrypt the message with the pgp key ''' + jid = self._get_real_jid(jid, account) + return self._send_message(jid, message, keyID, account) + + @dbus.service.method(INTERFACE, in_signature='sssss', out_signature='b') + def send_single_message(self, jid, subject, message, keyID, account): + '''Send single 'message' to 'jid', using account (optional) 'account'. + if keyID is specified, encrypt the message with the pgp key ''' + jid = self._get_real_jid(jid, account) + return self._send_message(jid, message, keyID, account, type, subject) + + @dbus.service.method(INTERFACE, in_signature='sss', out_signature='b') + def send_groupchat_message(self, room_jid, message, account): + '''Send 'message' to groupchat 'room_jid', + using account (optional) 'account'.''' + if not room_jid or not message: + return DBUS_BOOLEAN(False) + connected_account = self._get_account_for_groupchat(account, room_jid) + if connected_account: + connection = gajim.connections[connected_account] + connection.send_gc_message(room_jid, message) + return DBUS_BOOLEAN(True) + return DBUS_BOOLEAN(False) + + @dbus.service.method(INTERFACE, in_signature='ss', out_signature='b') + def open_chat(self, jid, account): + '''Shows the tabbed window for new message to 'jid', using account + (optional) 'account' ''' + if not jid: + raise MissingArgument + return DBUS_BOOLEAN(False) + jid = self._get_real_jid(jid, account) + try: + jid = helpers.parse_jid(jid) + except: + # Jid is not conform, ignore it + return DBUS_BOOLEAN(False) + + if account: + accounts = [account] + else: + accounts = gajim.connections.keys() + if len(accounts) == 1: + account = accounts[0] + connected_account = None + first_connected_acct = None + for acct in accounts: + if gajim.connections[acct].connected > 1: # account is online + contact = gajim.contacts.get_first_contact_from_jid(acct, jid) + if gajim.interface.msg_win_mgr.has_window(jid, acct): + connected_account = acct + break + # jid is in roster + elif contact: + connected_account = acct + break + # we send the message to jid not in roster, because account is + # specified, or there is only one account + elif account: + connected_account = acct + elif first_connected_acct is None: + first_connected_acct = acct + + # if jid is not a conntact, open-chat with first connected account + if connected_account is None and first_connected_acct: + connected_account = first_connected_acct + + if connected_account: + gajim.interface.new_chat_from_jid(connected_account, jid) + # preserve the 'steal focus preservation' + win = gajim.interface.msg_win_mgr.get_window(jid, + connected_account).window + if win.get_property('visible'): + win.window.focus() + return DBUS_BOOLEAN(True) + return DBUS_BOOLEAN(False) + + @dbus.service.method(INTERFACE, in_signature='sss', out_signature='b') + def change_status(self, status, message, account): + ''' change_status(status, message, account). account is optional - + if not specified status is changed for all accounts. ''' + if status not in ('offline', 'online', 'chat', + 'away', 'xa', 'dnd', 'invisible'): + return DBUS_BOOLEAN(False) + if account: + gobject.idle_add(gajim.interface.roster.send_status, account, + status, message) + else: + # account not specified, so change the status of all accounts + for acc in gajim.contacts.get_accounts(): + if not gajim.config.get_per('accounts', acc, + 'sync_with_global_status'): + continue + gobject.idle_add(gajim.interface.roster.send_status, acc, + status, message) + return DBUS_BOOLEAN(False) + + @dbus.service.method(INTERFACE, in_signature='', out_signature='') + def show_next_pending_event(self): + '''Show the window(s) with next pending event in tabbed/group chats.''' + if gajim.events.get_nb_events(): + gajim.interface.systray.handle_first_event() + + @dbus.service.method(INTERFACE, in_signature='s', out_signature='a{sv}') + def contact_info(self, jid): + '''get vcard info for a contact. Return cached value of the vcard. + ''' + if not isinstance(jid, unicode): + jid = unicode(jid) + if not jid: + raise MissingArgument + return DBUS_DICT_SV() + jid = self._get_real_jid(jid) + + cached_vcard = gajim.connections.values()[0].get_cached_vcard(jid) + if cached_vcard: + return get_dbus_struct(cached_vcard) + + # return empty dict + return DBUS_DICT_SV() + + @dbus.service.method(INTERFACE, in_signature='', out_signature='as') + def list_accounts(self): + '''list register accounts''' + result = gajim.contacts.get_accounts() + result_array = dbus.Array([], signature='s') + if result and len(result) > 0: + for account in result: + result_array.append(DBUS_STRING(account)) + return result_array + + @dbus.service.method(INTERFACE, in_signature='s', out_signature='a{ss}') + def account_info(self, account): + '''show info on account: resource, jid, nick, prio, message''' + result = DBUS_DICT_SS() + if gajim.connections.has_key(account): + # account is valid + con = gajim.connections[account] + index = con.connected + result['status'] = DBUS_STRING(gajim.SHOW_LIST[index]) + result['name'] = DBUS_STRING(con.name) + result['jid'] = DBUS_STRING(gajim.get_jid_from_account(con.name)) + result['message'] = DBUS_STRING(con.status) + result['priority'] = DBUS_STRING(unicode(con.priority)) + result['resource'] = DBUS_STRING(unicode(gajim.config.get_per( + 'accounts', con.name, 'resource'))) + return result + + @dbus.service.method(INTERFACE, in_signature='s', out_signature='aa{sv}') + def list_contacts(self, account): + '''list all contacts in the roster. If the first argument is specified, + then return the contacts for the specified account''' + result = dbus.Array([], signature='aa{sv}') + accounts = gajim.contacts.get_accounts() + if len(accounts) == 0: + return result + if account: + accounts_to_search = [account] + else: + accounts_to_search = accounts + for acct in accounts_to_search: + if acct in accounts: + for jid in gajim.contacts.get_jid_list(acct): + item = self._contacts_as_dbus_structure( + gajim.contacts.get_contacts(acct, jid)) + if item: + result.append(item) + return result + + @dbus.service.method(INTERFACE, in_signature='', out_signature='') + def toggle_roster_appearance(self): + ''' shows/hides the roster window ''' + win = gajim.interface.roster.window + if win.get_property('visible'): + gobject.idle_add(win.hide) + else: + win.present() + # preserve the 'steal focus preservation' + if self._is_first(): + win.window.focus() + else: + win.window.focus(long(time())) + + @dbus.service.method(INTERFACE, in_signature='', out_signature='') + def toggle_ipython(self): + ''' shows/hides the ipython window ''' + win = gajim.ipython_window + if win: + if win.window.is_visible(): + gobject.idle_add(win.hide) + else: + win.show_all() + win.present() + else: + gajim.interface.create_ipython_window() + + @dbus.service.method(INTERFACE, in_signature='', out_signature='a{ss}') + def prefs_list(self): + prefs_dict = DBUS_DICT_SS() + def get_prefs(data, name, path, value): + if value is None: + return + key = '' + if path is not None: + for node in path: + key += node + '#' + key += name + prefs_dict[DBUS_STRING(key)] = DBUS_STRING(value[1]) + gajim.config.foreach(get_prefs) + return prefs_dict + + @dbus.service.method(INTERFACE, in_signature='', out_signature='b') + def prefs_store(self): + try: + gajim.interface.save_config() + except Exception, e: + return DBUS_BOOLEAN(False) + return DBUS_BOOLEAN(True) + + @dbus.service.method(INTERFACE, in_signature='s', out_signature='b') + def prefs_del(self, key): + if not key: + return DBUS_BOOLEAN(False) + key_path = key.split('#', 2) + if len(key_path) != 3: + return DBUS_BOOLEAN(False) + if key_path[2] == '*': + gajim.config.del_per(key_path[0], key_path[1]) + else: + gajim.config.del_per(key_path[0], key_path[1], key_path[2]) + return DBUS_BOOLEAN(True) + + @dbus.service.method(INTERFACE, in_signature='s', out_signature='b') + def prefs_put(self, key): + if not key: + return DBUS_BOOLEAN(False) + key_path = key.split('#', 2) + if len(key_path) < 3: + subname, value = key.split('=', 1) + gajim.config.set(subname, value) + return DBUS_BOOLEAN(True) + subname, value = key_path[2].split('=', 1) + gajim.config.set_per(key_path[0], key_path[1], subname, value) + return DBUS_BOOLEAN(True) + + @dbus.service.method(INTERFACE, in_signature='ss', out_signature='b') + def add_contact(self, jid, account): + if account: + if account in gajim.connections and \ + gajim.connections[account].connected > 1: + # if given account is active, use it + AddNewContactWindow(account = account, jid = jid) + else: + # wrong account + return DBUS_BOOLEAN(False) + else: + # if account is not given, show account combobox + AddNewContactWindow(account = None, jid = jid) + return DBUS_BOOLEAN(True) + + @dbus.service.method(INTERFACE, in_signature='ss', out_signature='b') + def remove_contact(self, jid, account): + jid = self._get_real_jid(jid, account) + accounts = gajim.contacts.get_accounts() + + # if there is only one account in roster, take it as default + if account: + accounts = [account] + contact_exists = False + for account in accounts: + contacts = gajim.contacts.get_contacts(account, jid) + if contacts: + gajim.connections[account].unsubscribe(jid) + for contact in contacts: + gajim.interface.roster.remove_contact(contact, account) + gajim.contacts.remove_jid(account, jid) + contact_exists = True + return DBUS_BOOLEAN(contact_exists) + + def _is_first(self): + if self.first_show: + self.first_show = False + return True + return False + + def _get_real_jid(self, jid, account = None): + '''get the real jid from the given one: removes xmpp: or get jid from nick + if account is specified, search only in this account + ''' + if account: + accounts = [account] + else: + accounts = gajim.connections.keys() + if jid.startswith('xmpp:'): + return jid[5:] # len('xmpp:') = 5 + nick_in_roster = None # Is jid a nick ? + for account in accounts: + # Does jid exists in roster of one account ? + if gajim.contacts.get_contacts(account, jid): + return jid + if not nick_in_roster: + # look in all contact if one has jid as nick + for jid_ in gajim.contacts.get_jid_list(account): + c = gajim.contacts.get_contacts(account, jid_) + if c[0].name == jid: + nick_in_roster = jid_ + break + if nick_in_roster: + # We have not found jid in roster, but we found is as a nick + return nick_in_roster + # We have not found it as jid nor as nick, probably a not in roster jid + return jid + + def _contacts_as_dbus_structure(self, contacts): + ''' get info from list of Contact objects and create dbus dict ''' + if not contacts: + return None + prim_contact = None # primary contact + for contact in contacts: + if prim_contact is None or contact.priority > prim_contact.priority: + prim_contact = contact + contact_dict = DBUS_DICT_SV() + contact_dict['name'] = DBUS_STRING(prim_contact.name) + contact_dict['show'] = DBUS_STRING(prim_contact.show) + contact_dict['jid'] = DBUS_STRING(prim_contact.jid) + if prim_contact.keyID: + keyID = None + if len(prim_contact.keyID) == 8: + keyID = prim_contact.keyID + elif len(prim_contact.keyID) == 16: + keyID = prim_contact.keyID[8:] + if keyID: + contact_dict['openpgp'] = keyID + contact_dict['resources'] = dbus.Array([], signature='(sis)') + for contact in contacts: + resource_props = dbus.Struct((DBUS_STRING(contact.resource), + dbus.Int32(contact.priority), DBUS_STRING(contact.status))) + contact_dict['resources'].append(resource_props) + contact_dict['groups'] = dbus.Array([], signature='(s)') + for group in prim_contact.groups: + contact_dict['groups'].append((DBUS_STRING(group),)) + return contact_dict + + @dbus.service.method(INTERFACE, in_signature='', out_signature='s') + def get_unread_msgs_number(self): + return DBUS_STRING(str(gajim.events.get_nb_events())) + + @dbus.service.method(INTERFACE, in_signature='s', out_signature='b') + def start_chat(self, account): + if not account: + # error is shown in gajim-remote check_arguments(..) + return DBUS_BOOLEAN(False) + NewChatDialog(account) + return DBUS_BOOLEAN(True) + + @dbus.service.method(INTERFACE, in_signature='ss', out_signature='') + def send_xml(self, xml, account): + if account: + gajim.connections[account].send_stanza(xml) + else: + for acc in gajim.contacts.get_accounts(): + gajim.connections[acc].send_stanza(xml) + + @dbus.service.method(INTERFACE, in_signature='ssss', out_signature='') + def join_room(self, room_jid, nick, password, account): + if not account: + # get the first connected account + accounts = gajim.connections.keys() + for acct in accounts: + if gajim.account_is_connected(acct): + account = acct + break + if not account: + return + if not nick: + nick = '' + gajim.interface.instances[account]['join_gc'] = \ + JoinGroupchatWindow(account, room_jid, nick) + else: + gajim.interface.join_gc_room(account, room_jid, nick, password) from common import gajim from common import helpers @@ -680,62 +680,59 @@ from plugins.helpers import log_calls, log from common import ged class DBusPlugin(GajimPlugin): - name = u'D-Bus Support' - short_name = u'dbus' - version = u'0.1' - description = u'''D-Bus support. Based on remote_control module from + name = u'D-Bus Support' + short_name = u'dbus' + version = u'0.1' + description = u'''D-Bus support. Based on remote_control module from Gajim core but uses new events handling system.''' - authors = [u'Mateusz Biliński <mateusz@bilinski.it>'] - homepage = u'http://blog.bilinski.it' - - @log_calls('DBusPlugin') - def init(self): - self.config_dialog = None - #self.gui_extension_points = {} - #self.config_default_values = {} - - self.events_names = ['Roster', 'AccountPresence', 'ContactPresence', - 'ContactAbsence', 'ContactStatus', 'NewMessage', - 'Subscribe', 'Subscribed', 'Unsubscribed', - 'NewAccount', 'VcardInfo', 'LastStatusTime', - 'OsInfo', 'GCPresence', 'GCMessage', 'RosterInfo', - 'NewGmail'] - - self.signal_object = None - - self.events_handlers = {} - self._set_handling_methods() - - @log_calls('DBusPlugin') - def activate(self): - session_bus = dbus_support.session_bus.SessionBus() - - bus_name = dbus.service.BusName(SERVICE, bus=session_bus) - self.signal_object = SignalObject(bus_name) - - @log_calls('DBusPlugin') - def deactivate(self): - self.signal_object.remove_from_connection() - self.signal_object = None - - @log_calls('DBusPlugin') - def _set_handling_methods(self): - for event_name in self.events_names: - setattr(self, event_name, - new.instancemethod( - self._generate_handling_method(event_name), - self, - DBusPlugin)) - self.events_handlers[event_name] = (ged.POSTCORE, - getattr(self, event_name)) - - def _generate_handling_method(self, event_name): - def handler(self, arg): - #print "Handler of event %s called"%(event_name) - if self.signal_object: - getattr(self.signal_object, event_name)(get_dbus_struct(arg)) - - return handler - - -
\ No newline at end of file + authors = [u'Mateusz Biliński <mateusz@bilinski.it>'] + homepage = u'http://blog.bilinski.it' + + @log_calls('DBusPlugin') + def init(self): + self.config_dialog = None + #self.gui_extension_points = {} + #self.config_default_values = {} + + self.events_names = ['Roster', 'AccountPresence', 'ContactPresence', + 'ContactAbsence', 'ContactStatus', 'NewMessage', + 'Subscribe', 'Subscribed', 'Unsubscribed', + 'NewAccount', 'VcardInfo', 'LastStatusTime', + 'OsInfo', 'GCPresence', 'GCMessage', 'RosterInfo', + 'NewGmail'] + + self.signal_object = None + + self.events_handlers = {} + self._set_handling_methods() + + @log_calls('DBusPlugin') + def activate(self): + session_bus = dbus_support.session_bus.SessionBus() + + bus_name = dbus.service.BusName(SERVICE, bus=session_bus) + self.signal_object = SignalObject(bus_name) + + @log_calls('DBusPlugin') + def deactivate(self): + self.signal_object.remove_from_connection() + self.signal_object = None + + @log_calls('DBusPlugin') + def _set_handling_methods(self): + for event_name in self.events_names: + setattr(self, event_name, + new.instancemethod( + self._generate_handling_method(event_name), + self, + DBusPlugin)) + self.events_handlers[event_name] = (ged.POSTCORE, + getattr(self, event_name)) + + def _generate_handling_method(self, event_name): + def handler(self, arg): + #print "Handler of event %s called"%(event_name) + if self.signal_object: + getattr(self.signal_object, event_name)(get_dbus_struct(arg)) + + return handler diff --git a/plugins/events_dump/__init__.py b/plugins/events_dump/__init__.py index fc198d87d..de174c1b9 100644 --- a/plugins/events_dump/__init__.py +++ b/plugins/events_dump/__init__.py @@ -1 +1 @@ -from plugin import EventsDumpPlugin
\ No newline at end of file +from plugin import EventsDumpPlugin diff --git a/plugins/events_dump/plugin.py b/plugins/events_dump/plugin.py index 9aa4565b1..3e816ae3a 100644 --- a/plugins/events_dump/plugin.py +++ b/plugins/events_dump/plugin.py @@ -17,7 +17,7 @@ ''' Events Dump plugin. -Dumps info about selected events to console. +Dumps info about selected events to console. :author: Mateusz Biliński <mateusz@bilinski.it> :since: 10th August 2008 @@ -33,97 +33,97 @@ from plugins.helpers import log_calls, log from common import ged class EventsDumpPlugin(GajimPlugin): - name = u'Events Dump' - short_name = u'events_dump' - version = u'0.1' - description = u'''Dumps info about selected events to console.''' - authors = [u'Mateusz Biliński <mateusz@bilinski.it>'] - homepage = u'http://blog.bilinski.it' - - @log_calls('EventsDumpPlugin') - def init(self): - self.config_dialog = None - #self.gui_extension_points = {} - #self.config_default_values = {} - events_from_old_dbus_support = [ - 'Roster', 'AccountPresence', 'ContactPresence', - 'ContactAbsence', 'ContactStatus', 'NewMessage', - 'Subscribe', 'Subscribed', 'Unsubscribed', - 'NewAccount', 'VcardInfo', 'LastStatusTime', - 'OsInfo', 'GCPresence', 'GCMessage', 'RosterInfo', - 'NewGmail'] - - events_from_src_gajim = [ - 'ROSTER', 'WARNING', 'ERROR', - 'INFORMATION', 'ERROR_ANSWER', 'STATUS', - 'NOTIFY', 'MSGERROR', 'MSGSENT', 'MSGNOTSENT', - 'SUBSCRIBED', 'UNSUBSCRIBED', 'SUBSCRIBE', - 'AGENT_ERROR_INFO', 'AGENT_ERROR_ITEMS', - 'AGENT_REMOVED', 'REGISTER_AGENT_INFO', - 'AGENT_INFO_ITEMS', 'AGENT_INFO_INFO', - 'QUIT', 'NEW_ACC_CONNECTED', - 'NEW_ACC_NOT_CONNECTED', 'ACC_OK', 'ACC_NOT_OK', - 'MYVCARD', 'VCARD', 'LAST_STATUS_TIME', 'OS_INFO', - 'GC_NOTIFY', 'GC_MSG', 'GC_SUBJECT', 'GC_CONFIG', - 'GC_CONFIG_CHANGE', 'GC_INVITATION', - 'GC_AFFILIATION', 'GC_PASSWORD_REQUIRED', - 'BAD_PASSPHRASE', 'ROSTER_INFO', 'BOOKMARKS', - 'CON_TYPE', 'CONNECTION_LOST', 'FILE_REQUEST', - 'GMAIL_NOTIFY', 'FILE_REQUEST_ERROR', - 'FILE_SEND_ERROR', 'STANZA_ARRIVED', 'STANZA_SENT', - 'HTTP_AUTH', 'VCARD_PUBLISHED', - 'VCARD_NOT_PUBLISHED', 'ASK_NEW_NICK', 'SIGNED_IN', - 'METACONTACTS', 'ATOM_ENTRY', 'FAILED_DECRYPT', - 'PRIVACY_LISTS_RECEIVED', 'PRIVACY_LIST_RECEIVED', - 'PRIVACY_LISTS_ACTIVE_DEFAULT', - 'PRIVACY_LIST_REMOVED', 'ZC_NAME_CONFLICT', - 'PING_SENT', 'PING_REPLY', 'PING_ERROR', - 'SEARCH_FORM', 'SEARCH_RESULT', - 'RESOURCE_CONFLICT', 'PEP_CONFIG', - 'UNIQUE_ROOM_ID_UNSUPPORTED', - 'UNIQUE_ROOM_ID_SUPPORTED', 'SESSION_NEG', - 'GPG_PASSWORD_REQUIRED', 'SSL_ERROR', - 'FINGERPRINT_ERROR', 'PLAIN_CONNECTION', - 'PUBSUB_NODE_REMOVED', 'PUBSUB_NODE_NOT_REMOVED'] - - network_events_from_core = ['raw-message-received', - 'raw-iq-received', - 'raw-pres-received'] - - network_events_generated_in_nec = [ - 'customized-message-received', - 'more-customized-message-received', - 'modify-only-message-received', - 'enriched-chat-message-received'] - - self.events_names = [] - self.events_names += network_events_from_core - self.events_names += network_events_generated_in_nec - - self.events_handlers = {} - self._set_handling_methods() - - @log_calls('EventsDumpPlugin') - def activate(self): - pass - - @log_calls('EventsDumpPlugin') - def deactivate(self): - pass - - @log_calls('EventsDumpPlugin') - def _set_handling_methods(self): - for event_name in self.events_names: - setattr(self, event_name, - new.instancemethod( - self._generate_handling_method(event_name), - self, - EventsDumpPlugin)) - self.events_handlers[event_name] = (ged.POSTCORE, - getattr(self, event_name)) - - def _generate_handling_method(self, event_name): - def handler(self, *args): - print "Event '%s' occured. Arguments: %s\n\n===\n"%(event_name, pformat(args)) - - return handler
\ No newline at end of file + name = u'Events Dump' + short_name = u'events_dump' + version = u'0.1' + description = u'''Dumps info about selected events to console.''' + authors = [u'Mateusz Biliński <mateusz@bilinski.it>'] + homepage = u'http://blog.bilinski.it' + + @log_calls('EventsDumpPlugin') + def init(self): + self.config_dialog = None + #self.gui_extension_points = {} + #self.config_default_values = {} + events_from_old_dbus_support = [ + 'Roster', 'AccountPresence', 'ContactPresence', + 'ContactAbsence', 'ContactStatus', 'NewMessage', + 'Subscribe', 'Subscribed', 'Unsubscribed', + 'NewAccount', 'VcardInfo', 'LastStatusTime', + 'OsInfo', 'GCPresence', 'GCMessage', 'RosterInfo', + 'NewGmail'] + + events_from_src_gajim = [ + 'ROSTER', 'WARNING', 'ERROR', + 'INFORMATION', 'ERROR_ANSWER', 'STATUS', + 'NOTIFY', 'MSGERROR', 'MSGSENT', 'MSGNOTSENT', + 'SUBSCRIBED', 'UNSUBSCRIBED', 'SUBSCRIBE', + 'AGENT_ERROR_INFO', 'AGENT_ERROR_ITEMS', + 'AGENT_REMOVED', 'REGISTER_AGENT_INFO', + 'AGENT_INFO_ITEMS', 'AGENT_INFO_INFO', + 'QUIT', 'NEW_ACC_CONNECTED', + 'NEW_ACC_NOT_CONNECTED', 'ACC_OK', 'ACC_NOT_OK', + 'MYVCARD', 'VCARD', 'LAST_STATUS_TIME', 'OS_INFO', + 'GC_NOTIFY', 'GC_MSG', 'GC_SUBJECT', 'GC_CONFIG', + 'GC_CONFIG_CHANGE', 'GC_INVITATION', + 'GC_AFFILIATION', 'GC_PASSWORD_REQUIRED', + 'BAD_PASSPHRASE', 'ROSTER_INFO', 'BOOKMARKS', + 'CON_TYPE', 'CONNECTION_LOST', 'FILE_REQUEST', + 'GMAIL_NOTIFY', 'FILE_REQUEST_ERROR', + 'FILE_SEND_ERROR', 'STANZA_ARRIVED', 'STANZA_SENT', + 'HTTP_AUTH', 'VCARD_PUBLISHED', + 'VCARD_NOT_PUBLISHED', 'ASK_NEW_NICK', 'SIGNED_IN', + 'METACONTACTS', 'ATOM_ENTRY', 'FAILED_DECRYPT', + 'PRIVACY_LISTS_RECEIVED', 'PRIVACY_LIST_RECEIVED', + 'PRIVACY_LISTS_ACTIVE_DEFAULT', + 'PRIVACY_LIST_REMOVED', 'ZC_NAME_CONFLICT', + 'PING_SENT', 'PING_REPLY', 'PING_ERROR', + 'SEARCH_FORM', 'SEARCH_RESULT', + 'RESOURCE_CONFLICT', 'PEP_CONFIG', + 'UNIQUE_ROOM_ID_UNSUPPORTED', + 'UNIQUE_ROOM_ID_SUPPORTED', 'SESSION_NEG', + 'GPG_PASSWORD_REQUIRED', 'SSL_ERROR', + 'FINGERPRINT_ERROR', 'PLAIN_CONNECTION', + 'PUBSUB_NODE_REMOVED', 'PUBSUB_NODE_NOT_REMOVED'] + + network_events_from_core = ['raw-message-received', + 'raw-iq-received', + 'raw-pres-received'] + + network_events_generated_in_nec = [ + 'customized-message-received', + 'more-customized-message-received', + 'modify-only-message-received', + 'enriched-chat-message-received'] + + self.events_names = [] + self.events_names += network_events_from_core + self.events_names += network_events_generated_in_nec + + self.events_handlers = {} + self._set_handling_methods() + + @log_calls('EventsDumpPlugin') + def activate(self): + pass + + @log_calls('EventsDumpPlugin') + def deactivate(self): + pass + + @log_calls('EventsDumpPlugin') + def _set_handling_methods(self): + for event_name in self.events_names: + setattr(self, event_name, + new.instancemethod( + self._generate_handling_method(event_name), + self, + EventsDumpPlugin)) + self.events_handlers[event_name] = (ged.POSTCORE, + getattr(self, event_name)) + + def _generate_handling_method(self, event_name): + def handler(self, *args): + print "Event '%s' occured. Arguments: %s\n\n===\n"%(event_name, pformat(args)) + + return handler diff --git a/plugins/google_translation/__init__.py b/plugins/google_translation/__init__.py index 33fb27f0f..dc2c3bc36 100644 --- a/plugins/google_translation/__init__.py +++ b/plugins/google_translation/__init__.py @@ -1 +1 @@ -from plugin import GoogleTranslationPlugin
\ No newline at end of file +from plugin import GoogleTranslationPlugin diff --git a/plugins/google_translation/plugin.py b/plugins/google_translation/plugin.py index b2f920e37..a20664060 100644 --- a/plugins/google_translation/plugin.py +++ b/plugins/google_translation/plugin.py @@ -40,80 +40,79 @@ from common import ged from common import nec class GoogleTranslationPlugin(GajimPlugin): - name = u'Google Translation' - short_name = u'google_translation' - version = u'0.1' - description = u'''Translates (currently only incoming) messages using Google Translate.''' - authors = [u'Mateusz Biliński <mateusz@bilinski.it>'] - homepage = u'http://blog.bilinski.it' - - @log_calls('GoogleTranslationPlugin') - def init(self): - self.config_dialog = None - #self.gui_extension_points = {} - self.config_default_values = {'from_lang' : (u'en', _(u'Language of text to be translated')), - 'to_lang' : (u'fr', _(u'Language to which translation will be made')), - 'user_agent' : (u'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.12) Gecko/20080213 Firefox/2.0.0.11', - _(u'User Agent data to be used with urllib2 when connecting to Google Translate service'))} - - #self.events_handlers = {} - - self.events = [GoogleTranslateMessageReceivedEvent] - - self.translated_text_re = \ - re.compile(r'google.language.callbacks.id100\(\'22\',{"translatedText":"(?P<text>[^"]*)"}, 200, null, 200\)') - - @log_calls('GoogleTranslationPlugin') - def translate_text(self, text, from_lang, to_lang): - text = self.prepare_text_for_url(text) - headers = { 'User-Agent' : self.config['user_agent'] } - translation_url = u'http://www.google.com/uds/Gtranslate?callback=google.language.callbacks.id100&context=22&q=%(text)s&langpair=%(from_lang)s%%7C%(to_lang)s&key=notsupplied&v=1.0'%locals() - - request = urllib2.Request(translation_url, headers=headers) - response = urllib2.urlopen(request) - results = response.read() - - translated_text = self.translated_text_re.search(results).group('text') - - return translated_text - - @log_calls('GoogleTranslationPlugin') - def prepare_text_for_url(self, text): - ''' - Converts text so it can be used within URL as query to Google Translate. - ''' - - # There should be more replacements for plugin to work in any case: - char_replacements = { ' ' : '%20', - '+' : '%2B'} - - for char, replacement in char_replacements.iteritems(): - text = text.replace(char, replacement) - - return text - - @log_calls('GoogleTranslationPlugin') - def activate(self): - pass - - @log_calls('GoogleTranslationPlugin') - def deactivate(self): - pass - + name = u'Google Translation' + short_name = u'google_translation' + version = u'0.1' + description = u'''Translates (currently only incoming) messages using Google Translate.''' + authors = [u'Mateusz Biliński <mateusz@bilinski.it>'] + homepage = u'http://blog.bilinski.it' + + @log_calls('GoogleTranslationPlugin') + def init(self): + self.config_dialog = None + #self.gui_extension_points = {} + self.config_default_values = {'from_lang' : (u'en', _(u'Language of text to be translated')), + 'to_lang' : (u'fr', _(u'Language to which translation will be made')), + 'user_agent' : (u'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.12) Gecko/20080213 Firefox/2.0.0.11', + _(u'User Agent data to be used with urllib2 when connecting to Google Translate service'))} + + #self.events_handlers = {} + + self.events = [GoogleTranslateMessageReceivedEvent] + + self.translated_text_re = \ + re.compile(r'google.language.callbacks.id100\(\'22\',{"translatedText":"(?P<text>[^"]*)"}, 200, null, 200\)') + + @log_calls('GoogleTranslationPlugin') + def translate_text(self, text, from_lang, to_lang): + text = self.prepare_text_for_url(text) + headers = { 'User-Agent' : self.config['user_agent'] } + translation_url = u'http://www.google.com/uds/Gtranslate?callback=google.language.callbacks.id100&context=22&q=%(text)s&langpair=%(from_lang)s%%7C%(to_lang)s&key=notsupplied&v=1.0'%locals() + + request = urllib2.Request(translation_url, headers=headers) + response = urllib2.urlopen(request) + results = response.read() + + translated_text = self.translated_text_re.search(results).group('text') + + return translated_text + + @log_calls('GoogleTranslationPlugin') + def prepare_text_for_url(self, text): + ''' + Converts text so it can be used within URL as query to Google Translate. + ''' + + # There should be more replacements for plugin to work in any case: + char_replacements = { ' ' : '%20', + '+' : '%2B'} + + for char, replacement in char_replacements.iteritems(): + text = text.replace(char, replacement) + + return text + + @log_calls('GoogleTranslationPlugin') + def activate(self): + pass + + @log_calls('GoogleTranslationPlugin') + def deactivate(self): + pass + class GoogleTranslateMessageReceivedEvent(nec.NetworkIncomingEvent): - name = 'google-translate-message-received' - base_network_events = ['raw-message-received'] - - def generate(self): - msg_type = self.base_event.xmpp_msg.attrs.get('type', None) - if msg_type == u'chat': - msg_text = "".join(self.base_event.xmpp_msg.kids[0].data) - if msg_text: - from_lang = self.plugin.config['from_lang'] - to_lang = self.plugin.config['to_lang'] - self.base_event.xmpp_msg.kids[0].setData( - self.plugin.translate_text(msg_text, from_lang, to_lang)) - - return False # We only want to modify old event, not emit another, - # so we return False here. - + name = 'google-translate-message-received' + base_network_events = ['raw-message-received'] + + def generate(self): + msg_type = self.base_event.xmpp_msg.attrs.get('type', None) + if msg_type == u'chat': + msg_text = "".join(self.base_event.xmpp_msg.kids[0].data) + if msg_text: + from_lang = self.plugin.config['from_lang'] + to_lang = self.plugin.config['to_lang'] + self.base_event.xmpp_msg.kids[0].setData( + self.plugin.translate_text(msg_text, from_lang, to_lang)) + + return False # We only want to modify old event, not emit another, + # so we return False here. diff --git a/plugins/length_notifier/__init__.py b/plugins/length_notifier/__init__.py index fc433a0af..67c8c614a 100644 --- a/plugins/length_notifier/__init__.py +++ b/plugins/length_notifier/__init__.py @@ -1,2 +1,2 @@ -from length_notifier import LengthNotifierPlugin
\ No newline at end of file +from length_notifier import LengthNotifierPlugin diff --git a/plugins/length_notifier/length_notifier.py b/plugins/length_notifier/length_notifier.py index 86413ba13..cde132208 100644 --- a/plugins/length_notifier/length_notifier.py +++ b/plugins/length_notifier/length_notifier.py @@ -34,129 +34,128 @@ from plugins.helpers import log, log_calls from plugins.gui import GajimPluginConfigDialog class LengthNotifierPlugin(GajimPlugin): - name = u'Message Length Notifier' - short_name = u'length_notifier' - version = u'0.1' - description = u'''Highlights message entry field in chat window when given length of message is exceeded.''' - authors = [u'Mateusz Biliński <mateusz@bilinski.it>'] - homepage = u'http://blog.bilinski.it' - - @log_calls('LengthNotifierPlugin') - def init(self): - self.config_dialog = LengthNotifierPluginConfigDialog(self) - - self.gui_extension_points = { - 'chat_control' : (self.connect_with_chat_control, - self.disconnect_from_chat_control) - } - - self.config_default_values = {'MESSAGE_WARNING_LENGTH' : (140, _('Message length at which notification is invoked.')), - 'WARNING_COLOR' : ('#F0DB3E', _('Background color of text entry field in chat window when notification is invoked.')), - 'JIDS' : ([], _('JabberIDs that plugin should be used with (eg. restrict only to one microblogging bot). If empty plugin is used with every JID. [not implemented]')) - } - - @log_calls('LengthNotifierPlugin') - def textview_length_warning(self, tb, chat_control): - tv = chat_control.msg_textview - d = chat_control.length_notifier_plugin_data - t = tb.get_text(tb.get_start_iter(), tb.get_end_iter()) - if t: - len_t = len(t) - #print("len_t: %d"%(len_t)) - if len_t>self.config['MESSAGE_WARNING_LENGTH']: - if not d['prev_color']: - d['prev_color'] = tv.style.copy().base[gtk.STATE_NORMAL] - tv.modify_base(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.config['WARNING_COLOR'])) - elif d['prev_color']: - tv.modify_base(gtk.STATE_NORMAL, d['prev_color']) - d['prev_color'] = None - - @log_calls('LengthNotifierPlugin') - def connect_with_chat_control(self, chat_control): - jid = chat_control.contact.jid - if self.jid_is_ok(jid): - d = {'prev_color' : None} - tv = chat_control.msg_textview - tb = tv.get_buffer() - h_id = tb.connect('changed', self.textview_length_warning, chat_control) - d['h_id'] = h_id - - t = tb.get_text(tb.get_start_iter(), tb.get_end_iter()) - if t: - len_t = len(t) - if len_t>self.config['MESSAGE_WARNING_LENGTH']: - d['prev_color'] = tv.style.copy().base[gtk.STATE_NORMAL] - tv.modify_base(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.config['WARNING_COLOR'])) - - chat_control.length_notifier_plugin_data = d - - return True - - return False - - @log_calls('LengthNotifierPlugin') - def disconnect_from_chat_control(self, chat_control): - try: - d = chat_control.length_notifier_plugin_data - tv = chat_control.msg_textview - tv.get_buffer().disconnect(d['h_id']) - if d['prev_color']: - tv.modify_base(gtk.STATE_NORMAL, d['prev_color']) - except AttributeError, error: - pass - #log.debug('Length Notifier Plugin was (probably) never connected with this chat window.\n Error: %s' % (error)) - - @log_calls('LengthNotifierPlugin') - def jid_is_ok(self, jid): - if jid in self.config['JIDS'] or not self.config['JIDS']: - return True - - return False - + name = u'Message Length Notifier' + short_name = u'length_notifier' + version = u'0.1' + description = u'''Highlights message entry field in chat window when given length of message is exceeded.''' + authors = [u'Mateusz Biliński <mateusz@bilinski.it>'] + homepage = u'http://blog.bilinski.it' + + @log_calls('LengthNotifierPlugin') + def init(self): + self.config_dialog = LengthNotifierPluginConfigDialog(self) + + self.gui_extension_points = { + 'chat_control' : (self.connect_with_chat_control, + self.disconnect_from_chat_control) + } + + self.config_default_values = {'MESSAGE_WARNING_LENGTH' : (140, _('Message length at which notification is invoked.')), + 'WARNING_COLOR' : ('#F0DB3E', _('Background color of text entry field in chat window when notification is invoked.')), + 'JIDS' : ([], _('JabberIDs that plugin should be used with (eg. restrict only to one microblogging bot). If empty plugin is used with every JID. [not implemented]')) + } + + @log_calls('LengthNotifierPlugin') + def textview_length_warning(self, tb, chat_control): + tv = chat_control.msg_textview + d = chat_control.length_notifier_plugin_data + t = tb.get_text(tb.get_start_iter(), tb.get_end_iter()) + if t: + len_t = len(t) + #print("len_t: %d"%(len_t)) + if len_t>self.config['MESSAGE_WARNING_LENGTH']: + if not d['prev_color']: + d['prev_color'] = tv.style.copy().base[gtk.STATE_NORMAL] + tv.modify_base(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.config['WARNING_COLOR'])) + elif d['prev_color']: + tv.modify_base(gtk.STATE_NORMAL, d['prev_color']) + d['prev_color'] = None + + @log_calls('LengthNotifierPlugin') + def connect_with_chat_control(self, chat_control): + jid = chat_control.contact.jid + if self.jid_is_ok(jid): + d = {'prev_color' : None} + tv = chat_control.msg_textview + tb = tv.get_buffer() + h_id = tb.connect('changed', self.textview_length_warning, chat_control) + d['h_id'] = h_id + + t = tb.get_text(tb.get_start_iter(), tb.get_end_iter()) + if t: + len_t = len(t) + if len_t>self.config['MESSAGE_WARNING_LENGTH']: + d['prev_color'] = tv.style.copy().base[gtk.STATE_NORMAL] + tv.modify_base(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.config['WARNING_COLOR'])) + + chat_control.length_notifier_plugin_data = d + + return True + + return False + + @log_calls('LengthNotifierPlugin') + def disconnect_from_chat_control(self, chat_control): + try: + d = chat_control.length_notifier_plugin_data + tv = chat_control.msg_textview + tv.get_buffer().disconnect(d['h_id']) + if d['prev_color']: + tv.modify_base(gtk.STATE_NORMAL, d['prev_color']) + except AttributeError, error: + pass + #log.debug('Length Notifier Plugin was (probably) never connected with this chat window.\n Error: %s' % (error)) + + @log_calls('LengthNotifierPlugin') + def jid_is_ok(self, jid): + if jid in self.config['JIDS'] or not self.config['JIDS']: + return True + + return False + class LengthNotifierPluginConfigDialog(GajimPluginConfigDialog): - def init(self): - self.GTK_BUILDER_FILE_PATH = self.plugin.local_file_path( - 'config_dialog.ui') - self.xml = gtk.Builder() - self.xml.set_translation_domain(i18n.APP) - self.xml.add_objects_from_file(self.GTK_BUILDER_FILE_PATH, - ['length_notifier_config_table']) - self.config_table = self.xml.get_object('length_notifier_config_table') - self.child.pack_start(self.config_table) - - self.message_length_spinbutton = self.xml.get_object( - 'message_length_spinbutton') - self.message_length_spinbutton.get_adjustment().set_all(140, 0, 500, 1, - 10, 0) - self.notification_colorbutton = self.xml.get_object( - 'notification_colorbutton') - self.jids_entry = self.xml.get_object('jids_entry') - - self.xml.connect_signals(self) - - def on_run(self): - self.message_length_spinbutton.set_value(self.plugin.config['MESSAGE_WARNING_LENGTH']) - self.notification_colorbutton.set_color(gtk.gdk.color_parse(self.plugin.config['WARNING_COLOR'])) - #self.jids_entry.set_text(self.plugin.config['JIDS']) - self.jids_entry.set_text(','.join(self.plugin.config['JIDS'])) - - @log_calls('LengthNotifierPluginConfigDialog') - def on_message_length_spinbutton_value_changed(self, spinbutton): - self.plugin.config['MESSAGE_WARNING_LENGTH'] = spinbutton.get_value() - - @log_calls('LengthNotifierPluginConfigDialog') - def on_notification_colorbutton_color_set(self, colorbutton): - self.plugin.config['WARNING_COLOR'] = colorbutton.get_color().to_string() - - @log_calls('LengthNotifierPluginConfigDialog') - def on_jids_entry_changed(self, entry): - text = entry.get_text() - if len(text)>0: - self.plugin.config['JIDS'] = entry.get_text().split(',') - else: - self.plugin.config['JIDS'] = [] - - @log_calls('LengthNotifierPluginConfigDialog') - def on_jids_entry_editing_done(self, entry): - pass - + def init(self): + self.GTK_BUILDER_FILE_PATH = self.plugin.local_file_path( + 'config_dialog.ui') + self.xml = gtk.Builder() + self.xml.set_translation_domain(i18n.APP) + self.xml.add_objects_from_file(self.GTK_BUILDER_FILE_PATH, + ['length_notifier_config_table']) + self.config_table = self.xml.get_object('length_notifier_config_table') + self.child.pack_start(self.config_table) + + self.message_length_spinbutton = self.xml.get_object( + 'message_length_spinbutton') + self.message_length_spinbutton.get_adjustment().set_all(140, 0, 500, 1, + 10, 0) + self.notification_colorbutton = self.xml.get_object( + 'notification_colorbutton') + self.jids_entry = self.xml.get_object('jids_entry') + + self.xml.connect_signals(self) + + def on_run(self): + self.message_length_spinbutton.set_value(self.plugin.config['MESSAGE_WARNING_LENGTH']) + self.notification_colorbutton.set_color(gtk.gdk.color_parse(self.plugin.config['WARNING_COLOR'])) + #self.jids_entry.set_text(self.plugin.config['JIDS']) + self.jids_entry.set_text(','.join(self.plugin.config['JIDS'])) + + @log_calls('LengthNotifierPluginConfigDialog') + def on_message_length_spinbutton_value_changed(self, spinbutton): + self.plugin.config['MESSAGE_WARNING_LENGTH'] = spinbutton.get_value() + + @log_calls('LengthNotifierPluginConfigDialog') + def on_notification_colorbutton_color_set(self, colorbutton): + self.plugin.config['WARNING_COLOR'] = colorbutton.get_color().to_string() + + @log_calls('LengthNotifierPluginConfigDialog') + def on_jids_entry_changed(self, entry): + text = entry.get_text() + if len(text)>0: + self.plugin.config['JIDS'] = entry.get_text().split(',') + else: + self.plugin.config['JIDS'] = [] + + @log_calls('LengthNotifierPluginConfigDialog') + def on_jids_entry_editing_done(self, entry): + pass diff --git a/plugins/new_events_example/__init__.py b/plugins/new_events_example/__init__.py index a0eca896c..523d43e14 100644 --- a/plugins/new_events_example/__init__.py +++ b/plugins/new_events_example/__init__.py @@ -1 +1 @@ -from plugin import NewEventsExamplePlugin
\ No newline at end of file +from plugin import NewEventsExamplePlugin diff --git a/plugins/new_events_example/plugin.py b/plugins/new_events_example/plugin.py index 29740d1a4..ff40dd56f 100644 --- a/plugins/new_events_example/plugin.py +++ b/plugins/new_events_example/plugin.py @@ -38,110 +38,110 @@ from common import ged from common import nec class NewEventsExamplePlugin(GajimPlugin): - name = u'New Events Example' - short_name = u'new_events_example' - version = u'0.1' - description = u'''Shows how to generate new network events based on existing one using Network Events Controller.''' - authors = [u'Mateusz Biliński <mateusz@bilinski.it>'] - homepage = u'http://blog.bilinski.it' - - @log_calls('NewEventsExamplePlugin') - def init(self): - self.config_dialog = None - #self.gui_extension_points = {} - #self.config_default_values = {} - - self.events_handlers = {'raw-message-received' : - (ged.POSTCORE, - self.raw_message_received), - 'customized-message-received' : - (ged.POSTCORE, - self.customized_message_received), - 'enriched-chat-message-received' : - (ged.POSTCORE, - self.enriched_chat_message_received)} - - self.events = [CustomizedMessageReceivedEvent, - MoreCustomizedMessageReceivedEvent, - ModifyOnlyMessageReceivedEvent, - EnrichedChatMessageReceivedEvent] - - def enriched_chat_message_received(self, event_object): - pass - #print "Event '%s' occured. Event object: %s\n\n===\n"%(event_object.name, - #event_object) - - def raw_message_received(self, event_object): - pass - #print "Event '%s' occured. Event object: %s\n\n===\n"%(event_object.name, - #event_object) - - def customized_message_received(self, event_object): - pass - #print "Event '%s' occured. Event object: %s\n\n===\n"%(event_object.name, - #event_object - - @log_calls('NewEventsExamplePlugin') - def activate(self): - pass - - @log_calls('NewEventsExamplePlugin') - def deactivate(self): - pass - + name = u'New Events Example' + short_name = u'new_events_example' + version = u'0.1' + description = u'''Shows how to generate new network events based on existing one using Network Events Controller.''' + authors = [u'Mateusz Biliński <mateusz@bilinski.it>'] + homepage = u'http://blog.bilinski.it' + + @log_calls('NewEventsExamplePlugin') + def init(self): + self.config_dialog = None + #self.gui_extension_points = {} + #self.config_default_values = {} + + self.events_handlers = {'raw-message-received' : + (ged.POSTCORE, + self.raw_message_received), + 'customized-message-received' : + (ged.POSTCORE, + self.customized_message_received), + 'enriched-chat-message-received' : + (ged.POSTCORE, + self.enriched_chat_message_received)} + + self.events = [CustomizedMessageReceivedEvent, + MoreCustomizedMessageReceivedEvent, + ModifyOnlyMessageReceivedEvent, + EnrichedChatMessageReceivedEvent] + + def enriched_chat_message_received(self, event_object): + pass + #print "Event '%s' occured. Event object: %s\n\n===\n"%(event_object.name, + #event_object) + + def raw_message_received(self, event_object): + pass + #print "Event '%s' occured. Event object: %s\n\n===\n"%(event_object.name, + #event_object) + + def customized_message_received(self, event_object): + pass + #print "Event '%s' occured. Event object: %s\n\n===\n"%(event_object.name, + #event_object + + @log_calls('NewEventsExamplePlugin') + def activate(self): + pass + + @log_calls('NewEventsExamplePlugin') + def deactivate(self): + pass + class CustomizedMessageReceivedEvent(nec.NetworkIncomingEvent): - name = 'customized-message-received' - base_network_events = ['raw-message-received'] - - def generate(self): - return True - + name = 'customized-message-received' + base_network_events = ['raw-message-received'] + + def generate(self): + return True + class MoreCustomizedMessageReceivedEvent(nec.NetworkIncomingEvent): - ''' - Shows chain of custom created events. - - This one is based on custom 'customized-messsage-received'. - ''' - name = 'more-customized-message-received' - base_network_events = ['customized-message-received'] - - def generate(self): - return True - + ''' + Shows chain of custom created events. + + This one is based on custom 'customized-messsage-received'. + ''' + name = 'more-customized-message-received' + base_network_events = ['customized-message-received'] + + def generate(self): + return True + class ModifyOnlyMessageReceivedEvent(nec.NetworkIncomingEvent): - name = 'modify-only-message-received' - base_network_events = ['raw-message-received'] - - def generate(self): - msg_type = self.base_event.xmpp_msg.attrs.get('type', None) - if msg_type == u'chat': - msg_text = "".join(self.base_event.xmpp_msg.kids[0].data) - self.base_event.xmpp_msg.kids[0].setData( - u'%s [MODIFIED BY CUSTOM NETWORK EVENT]'%(msg_text)) - - return False - + name = 'modify-only-message-received' + base_network_events = ['raw-message-received'] + + def generate(self): + msg_type = self.base_event.xmpp_msg.attrs.get('type', None) + if msg_type == u'chat': + msg_text = "".join(self.base_event.xmpp_msg.kids[0].data) + self.base_event.xmpp_msg.kids[0].setData( + u'%s [MODIFIED BY CUSTOM NETWORK EVENT]'%(msg_text)) + + return False + class EnrichedChatMessageReceivedEvent(nec.NetworkIncomingEvent): - ''' - Generates more friendly (in use by handlers) network event for - received chat message. - ''' - name = 'enriched-chat-message-received' - base_network_events = ['raw-message-received'] - - def generate(self): - msg_type = self.base_event.xmpp_msg.attrs.get('type', None) - if msg_type == u'chat': - self.xmpp_msg = self.base_event.xmpp_msg - self.conn = self.base_event.conn - self.from_jid = helpers.get_full_jid_from_iq(self.xmpp_msg) - self.from_jid_without_resource = gajim.get_jid_without_resource(self.from_jid) - self.account = self.base_event.account - self.from_nickname = gajim.get_contact_name_from_jid( - self.account, - self.from_jid_without_resource) - self.msg_text = "".join(self.xmpp_msg.kids[0].data) - - return True - - return False + ''' + Generates more friendly (in use by handlers) network event for + received chat message. + ''' + name = 'enriched-chat-message-received' + base_network_events = ['raw-message-received'] + + def generate(self): + msg_type = self.base_event.xmpp_msg.attrs.get('type', None) + if msg_type == u'chat': + self.xmpp_msg = self.base_event.xmpp_msg + self.conn = self.base_event.conn + self.from_jid = helpers.get_full_jid_from_iq(self.xmpp_msg) + self.from_jid_without_resource = gajim.get_jid_without_resource(self.from_jid) + self.account = self.base_event.account + self.from_nickname = gajim.get_contact_name_from_jid( + self.account, + self.from_jid_without_resource) + self.msg_text = "".join(self.xmpp_msg.kids[0].data) + + return True + + return False diff --git a/plugins/roster_buttons/plugin.py b/plugins/roster_buttons/plugin.py index 90a636ce5..a75fd8c6c 100644 --- a/plugins/roster_buttons/plugin.py +++ b/plugins/roster_buttons/plugin.py @@ -34,54 +34,53 @@ from plugins import GajimPlugin from plugins.helpers import log, log_calls class RosterButtonsPlugin(GajimPlugin): - name = u'Roster Buttons' - short_name = u'roster_buttons' - version = u'0.1' - description = u'''Adds quick action buttons to roster window.''' - authors = [u'Mateusz Biliński <mateusz@bilinski.it>'] - homepage = u'http://blog.bilinski.it' - - @log_calls('RosterButtonsPlugin') - def init(self): - self.GTK_BUILDER_FILE_PATH = self.local_file_path('roster_buttons.ui') - self.roster_vbox = gajim.interface.roster.xml.get_object('roster_vbox2') - self.show_offline_contacts_menuitem = gajim.interface.roster.xml.get_object('show_offline_contacts_menuitem') - - self.config_dialog = None - - @log_calls('RosterButtonsPlugin') - def activate(self): - self.xml = gtk.Builder() - self.xml.set_translation_domain(i18n.APP) - self.xml.add_objects_from_file(self.GTK_BUILDER_FILE_PATH, - ['roster_buttons_buttonbox']) - self.buttonbox = self.xml.get_object('roster_buttons_buttonbox') - - self.roster_vbox.pack_start(self.buttonbox, expand=False) - self.roster_vbox.reorder_child(self.buttonbox, 0) - self.xml.connect_signals(self) - - @log_calls('RosterButtonsPlugin') - def deactivate(self): - self.roster_vbox.remove(self.buttonbox) - - self.buttonbox = None - self.xml = None - - @log_calls('RosterButtonsPlugin') - def on_roster_button_1_clicked(self, button): - #gajim.interface.roster.on_show_offline_contacts_menuitem_activate(None) - self.show_offline_contacts_menuitem.set_active(not self.show_offline_contacts_menuitem.get_active()) - - @log_calls('RosterButtonsPlugin') - def on_roster_button_2_clicked(self, button): - pass - - @log_calls('RosterButtonsPlugin') - def on_roster_button_3_clicked(self, button): - pass - - @log_calls('RosterButtonsPlugin') - def on_roster_button_4_clicked(self, button): - pass - + name = u'Roster Buttons' + short_name = u'roster_buttons' + version = u'0.1' + description = u'''Adds quick action buttons to roster window.''' + authors = [u'Mateusz Biliński <mateusz@bilinski.it>'] + homepage = u'http://blog.bilinski.it' + + @log_calls('RosterButtonsPlugin') + def init(self): + self.GTK_BUILDER_FILE_PATH = self.local_file_path('roster_buttons.ui') + self.roster_vbox = gajim.interface.roster.xml.get_object('roster_vbox2') + self.show_offline_contacts_menuitem = gajim.interface.roster.xml.get_object('show_offline_contacts_menuitem') + + self.config_dialog = None + + @log_calls('RosterButtonsPlugin') + def activate(self): + self.xml = gtk.Builder() + self.xml.set_translation_domain(i18n.APP) + self.xml.add_objects_from_file(self.GTK_BUILDER_FILE_PATH, + ['roster_buttons_buttonbox']) + self.buttonbox = self.xml.get_object('roster_buttons_buttonbox') + + self.roster_vbox.pack_start(self.buttonbox, expand=False) + self.roster_vbox.reorder_child(self.buttonbox, 0) + self.xml.connect_signals(self) + + @log_calls('RosterButtonsPlugin') + def deactivate(self): + self.roster_vbox.remove(self.buttonbox) + + self.buttonbox = None + self.xml = None + + @log_calls('RosterButtonsPlugin') + def on_roster_button_1_clicked(self, button): + #gajim.interface.roster.on_show_offline_contacts_menuitem_activate(None) + self.show_offline_contacts_menuitem.set_active(not self.show_offline_contacts_menuitem.get_active()) + + @log_calls('RosterButtonsPlugin') + def on_roster_button_2_clicked(self, button): + pass + + @log_calls('RosterButtonsPlugin') + def on_roster_button_3_clicked(self, button): + pass + + @log_calls('RosterButtonsPlugin') + def on_roster_button_4_clicked(self, button): + pass diff --git a/plugins/snarl_notifications/PySnarl.py b/plugins/snarl_notifications/PySnarl.py index 118a7b25c..c3c657e56 100755 --- a/plugins/snarl_notifications/PySnarl.py +++ b/plugins/snarl_notifications/PySnarl.py @@ -1,772 +1,772 @@ -"""
-A python version of the main functions to use Snarl
-(http://www.fullphat.net/snarl)
-
-Version 1.0
-
-This module can be used in two ways. One is the normal way
-the other snarl interfaces work. This means you can call snShowMessage
-and get an ID back for manipulations.
-
-The other way is there is a class this module exposes called SnarlMessage.
-This allows you to keep track of the message as a python object. If you
-use the send without specifying False as the argument it will set the ID
-to what the return of the last SendMessage was. This is of course only
-useful for the SHOW message.
-
-Requires one of:
- pywin32 extensions from http://pywin32.sourceforge.net
- ctypes (included in Python 2.5, downloadable for earlier versions)
-
-Creator: Sam Listopad II (samlii@users.sourceforge.net)
-
-Copyright 2006-2008 Samuel Listopad II
-
-Licensed under the Apache License, Version 2.0 (the "License"); you may not
-use this file except in compliance with the License. You may obtain a copy
-of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required
-by applicable law or agreed to in writing, software distributed under the
-License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
-OF ANY KIND, either express or implied. See the License for the specific
-language governing permissions and limitations under the License.
-"""
-
-import array, struct
-
-def LOWORD(dword):
- """Return the low WORD of the passed in integer"""
- return dword & 0x0000ffff
-#get the hi word
-def HIWORD(dword):
- """Return the high WORD of the passed in integer"""
- return dword >> 16
-
-class Win32FuncException(Exception):
- def __init__(self, value):
- self.value = value
-
- def __str__(self):
- return repr(self.value)
-
-class Win32Funcs:
- """Just a little class to hide the details of finding and using the
-correct win32 functions. The functions may throw a UnicodeEncodeError if
-there is not a unicode version and it is sent a unicode string that cannot
-be converted to ASCII."""
- WM_USER = 0x400
- WM_COPYDATA = 0x4a
- #Type of String the functions are expecting.
- #Used like function(myWin32Funcs.strType(param)).
- __strType = str
- #FindWindow function to use
- __FindWindow = None
- #FindWindow function to use
- __FindWindowEx = None
- #SendMessage function to use
- __SendMessage = None
- #SendMessageTimeout function to use
- __SendMessageTimeout = None
- #IsWindow function to use
- __IsWindow = None
- #RegisterWindowMessage to use
- __RegisterWindowMessage = None
- #GetWindowText to use
- __GetWindowText = None
-
- def FindWindow(self, lpClassName, lpWindowName):
- """Wraps the windows API call of FindWindow"""
- if lpClassName is not None:
- lpClassName = self.__strType(lpClassName)
- if lpWindowName is not None:
- lpWindowName = self.__strType(lpWindowName)
- return self.__FindWindow(lpClassName, lpWindowName)
-
- def FindWindowEx(self, hwndParent, hwndChildAfter, lpClassName, lpWindowName):
- """Wraps the windows API call of FindWindow"""
- if lpClassName is not None:
- lpClassName = self.__strType(lpClassName)
- if lpWindowName is not None:
- lpWindowName = self.__strType(lpWindowName)
- return self.__FindWindowEx(hwndParent, hwndChildAfter, lpClassName, lpWindowName)
-
- def SendMessage(self, hWnd, Msg, wParam, lParam):
- """Wraps the windows API call of SendMessage"""
- return self.__SendMessage(hWnd, Msg, wParam, lParam)
-
- def SendMessageTimeout(self, hWnd, Msg,
- wParam, lParam, fuFlags,
- uTimeout, lpdwResult = None):
- """Wraps the windows API call of SendMessageTimeout"""
- idToRet = None
- try:
- idFromMsg = array.array('I', [0])
- result = idFromMsg.buffer_info()[0]
- response = self.__SendMessageTimeout(hWnd, Msg, wParam,
- lParam, fuFlags,
- uTimeout, result)
- if response == 0:
- raise Win32FuncException, "SendMessageTimeout TimedOut"
-
- idToRet = idFromMsg[0]
- except TypeError:
- idToRet = self.__SendMessageTimeout(hWnd, Msg, wParam,
- lParam, fuFlags,
- uTimeout)
-
- if lpdwResult is not None and lpdwResult.typecode == 'I':
- lpdwResult[0] = idToRet
-
- return idToRet
-
- def IsWindow(self, hWnd):
- """Wraps the windows API call of IsWindow"""
- return self.__IsWindow(hWnd)
-
- def RegisterWindowMessage(self, lpString):
- """Wraps the windows API call of RegisterWindowMessage"""
- return self.__RegisterWindowMessage(self.__strType(lpString))
-
- def GetWindowText(self, hWnd, lpString = None, nMaxCount = None):
- """Wraps the windows API call of SendMessageTimeout"""
- text = ''
- if hWnd == 0:
- return text
-
- if nMaxCount is None:
- nMaxCount = 1025
-
- try:
- arrayType = 'c'
- if self.__strType == unicode:
- arrayType = 'u'
- path_string = array.array(arrayType, self.__strType('\x00') * nMaxCount)
- path_buffer = path_string.buffer_info()[0]
- result = self.__GetWindowText(hWnd,
- path_buffer,
- nMaxCount)
- if result > 0:
- if self.__strType == unicode:
- text = path_string[0:result].tounicode()
- else:
- text = path_string[0:result].tostring()
- except TypeError:
- text = self.__GetWindowText(hWnd)
-
- if lpString is not None and lpString.typecode == 'c':
- lpdwResult[0:len(text)] = array.array('c',str(text));
-
- if lpString is not None and lpString.typecode == 'u':
- lpdwResult[0:len(text)] = array.array('u',unicode(text));
-
- return text
-
- def __init__(self):
- """Load up my needed functions"""
- # First see if they already have win32gui imported. If so use it.
- # This has to be checked first since the auto check looks for ctypes
- # first.
- try:
- self.__FindWindow = win32gui.FindWindow
- self.__FindWindowEx = win32gui.FindWindowEx
- self.__GetWindowText = win32gui.GetWindowText
- self.__IsWindow = win32gui.IsWindow
- self.__SendMessage = win32gui.SendMessage
- self.__SendMessageTimeout = win32gui.SendMessageTimeout
- self.__RegisterWindowMessage = win32gui.RegisterWindowMessage
- self.__strType = unicode
-
- #Something threw a NameError, most likely the win32gui lines
- #so do auto check
- except NameError:
- try:
- from ctypes import windll
- self.__FindWindow = windll.user32.FindWindowW
- self.__FindWindowEx = windll.user32.FindWindowExW
- self.__GetWindowText = windll.user32.GetWindowTextW
- self.__IsWindow = windll.user32.IsWindow
- self.__SendMessage = windll.user32.SendMessageW
- self.__SendMessageTimeout = windll.user32.SendMessageTimeoutW
- self.__RegisterWindowMessage = windll.user32.RegisterWindowMessageW
- self.__strType = unicode
-
- #FindWindowW wasn't found, look for FindWindowA
- except AttributeError:
- try:
- self.__FindWindow = windll.user32.FindWindowA
- self.__FindWindowEx = windll.user32.FindWindowExA
- self.__GetWindowText = windll.user32.GetWindowTextA
- self.__IsWindow = windll.user32.IsWindow
- self.__SendMessage = windll.user32.SendMessageA
- self.__SendMessageTimeout = windll.user32.SendMessageTimeoutA
- self.__RegisterWindowMessage = windll.user32.RegisterWindowMessageA
- # Couldn't find either so Die and tell user why.
- except AttributeError:
- import sys
- sys.stderr.write("Your Windows TM setup seems to be corrupt."+
- " No FindWindow found in user32.\n")
- sys.stderr.flush()
- sys.exit(3)
-
- except ImportError:
- try:
- import win32gui
- self.__FindWindow = win32gui.FindWindow
- self.__FindWindowEx = win32gui.FindWindowEx
- self.__GetWindowText = win32gui.GetWindowText
- self.__IsWindow = win32gui.IsWindow
- self.__SendMessage = win32gui.SendMessage
- self.__SendMessageTimeout = win32gui.SendMessageTimeout
- self.__RegisterWindowMessage = win32gui.RegisterWindowMessage
- self.__strType = unicode
-
- except ImportError:
- import sys
- sys.stderr.write("You need to have either"+
- " ctypes or pywin32 installed.\n")
- sys.stderr.flush()
- #sys.exit(2)
-
-
-myWin32Funcs = Win32Funcs()
-
-
-SHOW = 1
-HIDE = 2
-UPDATE = 3
-IS_VISIBLE = 4
-GET_VERSION = 5
-REGISTER_CONFIG_WINDOW = 6
-REVOKE_CONFIG_WINDOW = 7
-REGISTER_ALERT = 8
-REVOKE_ALERT = 9
-REGISTER_CONFIG_WINDOW_2 = 10
-GET_VERSION_EX = 11
-SET_TIMEOUT = 12
-
-EX_SHOW = 32
-
-GLOBAL_MESSAGE = "SnarlGlobalMessage"
-GLOBAL_MSG = "SnarlGlobalEvent"
-
-#Messages That may be received from Snarl
-SNARL_LAUNCHED = 1
-SNARL_QUIT = 2
-SNARL_ASK_APPLET_VER = 3
-SNARL_SHOW_APP_UI = 4
-
-SNARL_NOTIFICATION_CLICKED = 32 #notification was right-clicked by user
-SNARL_NOTIFICATION_CANCELLED = SNARL_NOTIFICATION_CLICKED #Name clarified
-SNARL_NOTIFICATION_TIMED_OUT = 33
-SNARL_NOTIFICATION_ACK = 34 #notification was left-clicked by user
-
-#Snarl Test Message
-WM_SNARLTEST = myWin32Funcs.WM_USER + 237
-
-M_ABORTED = 0x80000007L
-M_ACCESS_DENIED = 0x80000009L
-M_ALREADY_EXISTS = 0x8000000CL
-M_BAD_HANDLE = 0x80000006L
-M_BAD_POINTER = 0x80000005L
-M_FAILED = 0x80000008L
-M_INVALID_ARGS = 0x80000003L
-M_NO_INTERFACE = 0x80000004L
-M_NOT_FOUND = 0x8000000BL
-M_NOT_IMPLEMENTED = 0x80000001L
-M_OK = 0x00000000L
-M_OUT_OF_MEMORY = 0x80000002L
-M_TIMED_OUT = 0x8000000AL
-
-ErrorCodeRev = {
- 0x80000007L : "M_ABORTED",
- 0x80000009L : "M_ACCESS_DENIED",
- 0x8000000CL : "M_ALREADY_EXISTS",
- 0x80000006L : "M_BAD_HANDLE",
- 0x80000005L : "M_BAD_POINTER",
- 0x80000008L : "M_FAILED",
- 0x80000003L : "M_INVALID_ARGS",
- 0x80000004L : "M_NO_INTERFACE",
- 0x8000000BL : "M_NOT_FOUND",
- 0x80000001L : "M_NOT_IMPLEMENTED",
- 0x00000000L : "M_OK",
- 0x80000002L : "M_OUT_OF_MEMORY",
- 0x8000000AL : "M_TIMED_OUT"
- }
-
-class SnarlMessage(object):
- """The main Snarl interface object.
-
- ID = Snarl Message ID for most operations. See SDK for more info
- as to other values to put here.
- type = Snarl Message Type. Valid values are : SHOW, HIDE, UPDATE,
- IS_VISIBLE, GET_VERSION, REGISTER_CONFIG_WINDOW, REVOKE_CONFIG_WINDOW
- all which are constants in the PySnarl module.
- timeout = Timeout in seconds for the Snarl Message
- data = Snarl Message data. This is dependant upon message type. See SDK
- title = Snarl Message title.
- text = Snarl Message text.
- icon = Path to the icon to display in the Snarl Message.
- """
- __msgType = 0
- __msgID = 0
- __msgTimeout = 0
- __msgData = 0
- __msgTitle = ""
- __msgText = ""
- __msgIcon = ""
- __msgClass = ""
- __msgExtra = ""
- __msgExtra2 = ""
- __msgRsvd1 = 0
- __msgRsvd2 = 0
- __msgHWnd = 0
-
- lastKnownHWnd = 0
-
- def getType(self):
- """Type Attribute getter."""
- return self.__msgType
- def setType(self, value):
- """Type Attribute setter."""
- if( isinstance(value, (int, long)) ):
- self.__msgType = value
- type = property(getType, setType, doc="The Snarl Message Type")
-
- def getID(self):
- """ID Attribute getter."""
- return self.__msgID
- def setID(self, value):
- """ID Attribute setter."""
- if( isinstance(value, (int, long)) ):
- self.__msgID = value
- ID = property(getID, setID, doc="The Snarl Message ID")
-
- def getTimeout(self):
- """Timeout Attribute getter."""
- return self.__msgTimeout
- def updateTimeout(self, value):
- """Timeout Attribute setter."""
- if( isinstance(value, (int, long)) ):
- self.__msgTimeout = value
- timeout = property(getTimeout, updateTimeout,
- doc="The Snarl Message Timeout")
-
- def getData(self):
- """Data Attribute getter."""
- return self.__msgData
- def setData(self, value):
- """Data Attribute setter."""
- if( isinstance(value, (int, long)) ):
- self.__msgData = value
- data = property(getData, setData, doc="The Snarl Message Data")
-
- def getTitle(self):
- """Title Attribute getter."""
- return self.__msgTitle
- def setTitle(self, value):
- """Title Attribute setter."""
- if( isinstance(value, basestring) ):
- self.__msgTitle = value
- title = property(getTitle, setTitle, doc="The Snarl Message Title")
-
- def getText(self):
- """Text Attribute getter."""
- return self.__msgText
- def setText(self, value):
- """Text Attribute setter."""
- if( isinstance(value, basestring) ):
- self.__msgText = value
- text = property(getText, setText, doc="The Snarl Message Text")
-
- def getIcon(self):
- """Icon Attribute getter."""
- return self.__msgIcon
- def setIcon(self, value):
- """Icon Attribute setter."""
- if( isinstance(value, basestring) ):
- self.__msgIcon = value
- icon = property(getIcon, setIcon, doc="The Snarl Message Icon")
-
- def getClass(self):
- """Class Attribute getter."""
- return self.__msgClass
- def setClass(self, value):
- """Class Attribute setter."""
- if( isinstance(value, basestring) ):
- self.__msgClass = value
- msgclass = property(getClass, setClass, doc="The Snarl Message Class")
-
- def getExtra(self):
- """Extra Attribute getter."""
- return self.__msgExtra
- def setExtra(self, value):
- """Extra Attribute setter."""
- if( isinstance(value, basestring) ):
- self.__msgExtra = value
- extra = property(getExtra, setExtra, doc="Extra Info for the Snarl Message")
-
- def getExtra2(self):
- """Extra2 Attribute getter."""
- return self.__msgExtra2
- def setExtra2(self, value):
- """Extra2 Attribute setter."""
- if( isinstance(value, basestring) ):
- self.__msgExtra2 = value
- extra2 = property(getExtra2, setExtra2,
- doc="More Extra Info for the Snarl Message")
-
- def getRsvd1(self):
- """Rsvd1 Attribute getter."""
- return self.__msgRsvd1
- def setRsvd1(self, value):
- """Rsvd1 Attribute setter."""
- if( isinstance(value, (int, long)) ):
- self.__msgRsvd1 = value
- rsvd1 = property(getRsvd1, setRsvd1, doc="The Snarl Message Field Rsvd1")
-
- def getRsvd2(self):
- """Rsvd2 Attribute getter."""
- return self.__msgRsvd2
- def setRsvd2(self, value):
- """Rsvd2 Attribute setter."""
- if( isinstance(value, (int, long)) ):
- self.__msgRsvd2 = value
- rsvd2 = property(getRsvd2, setRsvd2, doc="The Snarl Message Field Rsvd2")
-
- def getHwnd(self):
- """hWnd Attribute getter."""
- return self.__msgHWnd
- def setHwnd(self, value):
- """hWnd Attribute setter."""
- if( isinstance(value, (int, long)) ):
- self.__msgHWnd = value
-
- hWnd = property(getHwnd, setHwnd, doc="The hWnd of the window this message is being sent from")
-
-
- def __init__(self, title="", text="", icon="", msg_type=1, msg_id=0):
- self.__msgTimeout = 0
- self.__msgData = 0
- self.__msgClass = ""
- self.__msgExtra = ""
- self.__msgExtra2 = ""
- self.__msgRsvd1 = 0
- self.__msgRsvd2 = 0
- self.__msgType = msg_type
- self.__msgText = text
- self.__msgTitle = title
- self.__msgIcon = icon
- self.__msgID = msg_id
-
- def createCopyStruct(self):
- """Creates the struct to send as the copyData in the message."""
- return struct.pack("ILLL1024s1024s1024s1024s1024s1024sLL",
- self.__msgType,
- self.__msgID,
- self.__msgTimeout,
- self.__msgData,
- self.__msgTitle.encode('utf-8'),
- self.__msgText.encode('utf-8'),
- self.__msgIcon.encode('utf-8'),
- self.__msgClass.encode('utf-8'),
- self.__msgExtra.encode('utf-8'),
- self.__msgExtra2.encode('utf-8'),
- self.__msgRsvd1,
- self.__msgRsvd2
- )
- __lpData = None
- __cds = None
-
- def packData(self, dwData):
- """This packs the data in the necessary format for a
-WM_COPYDATA message."""
- self.__lpData = None
- self.__cds = None
- item = self.createCopyStruct()
- self.__lpData = array.array('c', item)
- lpData_ad = self.__lpData.buffer_info()[0]
- cbData = self.__lpData.buffer_info()[1]
- self.__cds = array.array('c',
- struct.pack("IIP",
- dwData,
- cbData,
- lpData_ad)
- )
- cds_ad = self.__cds.buffer_info()[0]
- return cds_ad
-
- def reset(self):
- """Reset this SnarlMessage to the default state."""
- self.__msgType = 0
- self.__msgID = 0
- self.__msgTimeout = 0
- self.__msgData = 0
- self.__msgTitle = ""
- self.__msgText = ""
- self.__msgIcon = ""
- self.__msgClass = ""
- self.__msgExtra = ""
- self.__msgExtra2 = ""
- self.__msgRsvd1 = 0
- self.__msgRsvd2 = 0
-
-
- def send(self, setid=True):
- """Send this SnarlMessage to the Snarl window.
-Args:
- setid - Boolean defining whether or not to set the ID
- of this SnarlMessage to the return value of
- the SendMessage call. Default is True to
- make simple case of SHOW easy.
- """
- hwnd = myWin32Funcs.FindWindow(None, "Snarl")
- if myWin32Funcs.IsWindow(hwnd):
- if self.type == REGISTER_CONFIG_WINDOW or self.type == REGISTER_CONFIG_WINDOW_2:
- self.hWnd = self.data
- try:
- response = myWin32Funcs.SendMessageTimeout(hwnd,
- myWin32Funcs.WM_COPYDATA,
- self.hWnd, self.packData(2),
- 2, 500)
- except Win32FuncException:
- return False
-
- idFromMsg = response
- if setid:
- self.ID = idFromMsg
- return True
- else:
- return idFromMsg
- print "No snarl window found"
- return False
-
- def hide(self):
- """Hide this message. Type will revert to type before calling hide
-to allow for better reuse of object."""
- oldType = self.__msgType
- self.__msgType = HIDE
- retVal = bool(self.send(False))
- self.__msgType = oldType
- return retVal
-
- def isVisible(self):
- """Is this message visible. Type will revert to type before calling
-hide to allow for better reuse of object."""
- oldType = self.__msgType
- self.__msgType = IS_VISIBLE
- retVal = bool(self.send(False))
- self.__msgType = oldType
- return retVal
-
- def update(self, title=None, text=None, icon=None):
- """Update this message with given title and text. Type will revert
-to type before calling hide to allow for better reuse of object."""
- oldType = self.__msgType
- self.__msgType = UPDATE
- if text:
- self.__msgText = text
- if title:
- self.__msgTitle = title
- if icon:
- self.__msgIcon = icon
- retVal = self.send(False)
- self.__msgType = oldType
- return retVal
-
- def setTimeout(self, timeout):
- """Set the timeout in seconds of the message"""
- oldType = self.__msgType
- oldData = self.__msgData
- self.__msgType = SET_TIMEOUT
- #self.timeout = timeout
- #self.__msgData = self.__msgTimeout
- self.__msgData = timeout
- retVal = self.send(False)
- self.__msgType = oldType
- self.__msgData = oldData
- return retVal
-
- def show(self, timeout=None, title=None,
- text=None, icon=None,
- replyWindow=None, replyMsg=None, msgclass=None, soundPath=None):
- """Show a message"""
- oldType = self.__msgType
- oldTimeout = self.__msgTimeout
- self.__msgType = SHOW
- if text:
- self.__msgText = text
- if title:
- self.__msgTitle = title
- if timeout:
- self.__msgTimeout = timeout
- if icon:
- self.__msgIcon = icon
- if replyWindow:
- self.__msgID = replyMsg
- if replyMsg:
- self.__msgData = replyWindow
- if soundPath:
- self.__msgExtra = soundPath
- if msgclass:
- self.__msgClass = msgclass
-
- if ((self.__msgClass and self.__msgClass != "") or
- (self.__msgExtra and self.__msgExtra != "")):
- self.__msgType = EX_SHOW
-
-
- retVal = bool(self.send())
- self.__msgType = oldType
- self.__msgTimeout = oldTimeout
- return retVal
-
-
-def snGetVersion():
- """ Get the version of Snarl that is running as a tuple. (Major, Minor)
-
-If Snarl is not running or there was an error it will
-return False."""
- msg = SnarlMessage(msg_type=GET_VERSION)
- version = msg.send(False)
- if not version:
- return False
- return (HIWORD(version), LOWORD(version))
-
-def snGetVersionEx():
- """ Get the internal version of Snarl that is running.
-
-If Snarl is not running or there was an error it will
-return False."""
- sm = SnarlMessage(msg_type=GET_VERSION_EX)
- verNum = sm.send(False)
- if not verNum:
- return False
- return verNum
-
-def snGetGlobalMessage():
- """Get the Snarl global message id from windows."""
- return myWin32Funcs.RegisterWindowMessage(GLOBAL_MSG)
-
-def snShowMessage(title, text, timeout=0, iconPath="",
- replyWindow=0, replyMsg=0):
- """Show a message using Snarl and return its ID. See SDK for arguments."""
- sm = SnarlMessage( title, text, iconPath, msg_id=replyMsg)
- sm.data = replyWindow
- if sm.show(timeout):
- return sm.ID
- else:
- return False
-
-def snShowMessageEx(msgClass, title, text, timeout=0, iconPath="",
- replyWindow=0, replyMsg=0, soundFile=None, hWndFrom=None):
- """Show a message using Snarl and return its ID. See SDK for arguments.
- One added argument is hWndFrom that allows one to make the messages appear
- to come from a specific window. This window should be the one you registered
- earlier with RegisterConfig"""
- sm = SnarlMessage( title, text, iconPath, msg_id=replyMsg)
- sm.data = replyWindow
- if hWndFrom is not None:
- sm.hWnd = hWndFrom
- else:
- sm.hWnd = SnarlMessage.lastKnownHWnd
- if sm.show(timeout, msgclass=msgClass, soundPath=soundFile):
- return sm.ID
- else:
- return False
-
-def snUpdateMessage(msgId, msgTitle, msgText, icon=None):
- """Update a message"""
- sm = SnarlMessage(msg_id=msgId)
- if icon:
- sm.icon = icon
- return sm.update(msgTitle, msgText)
-
-def snHideMessage(msgId):
- """Hide a message"""
- return SnarlMessage(msg_id=msgId).hide()
-
-def snSetTimeout(msgId, timeout):
- """Update the timeout of a message already shown."""
- sm = SnarlMessage(msg_id=msgId)
- return sm.setTimeout(timeout)
-
-def snIsMessageVisible(msgId):
- """Returns True if the message is visible False otherwise."""
- return SnarlMessage(msg_id=msgId).isVisible()
-
-def snRegisterConfig(replyWnd, appName, replyMsg):
- """Register a config window. See SDK for more info."""
- global lastRegisteredSnarlMsg
- sm = SnarlMessage(msg_type=REGISTER_CONFIG_WINDOW,
- title=appName,
- msg_id=replyMsg)
- sm.data = replyWnd
- SnarlMessage.lastKnownHWnd = replyWnd
-
- return sm.send(False)
-
-def snRegisterConfig2(replyWnd, appName, replyMsg, icon):
- """Register a config window. See SDK for more info."""
- global lastRegisteredSnarlMsg
- sm = SnarlMessage(msg_type=REGISTER_CONFIG_WINDOW_2,
- title=appName,
- msg_id=replyMsg,
- icon=icon)
- sm.data = replyWnd
- SnarlMessage.lastKnownHWnd = replyWnd
- return sm.send(False)
-
-def snRegisterAlert(appName, classStr) :
- """Register an alert for an already registered config. See SDK for more info."""
- sm = SnarlMessage(msg_type=REGISTER_ALERT,
- title=appName,
- text=classStr)
- return sm.send(False)
-
-def snRevokeConfig(replyWnd):
- """Revoke a config window"""
- sm = SnarlMessage(msg_type=REVOKE_CONFIG_WINDOW)
- sm.data = replyWnd
- if replyWnd == SnarlMessage.lastKnownHWnd:
- SnarlMessage.lastKnownHWnd = 0
- return sm.send(False)
-
-def snGetSnarlWindow():
- """Returns the hWnd of the snarl window"""
- return myWin32Funcs.FindWindow(None, "Snarl")
-
-def snGetAppPath():
- """Returns the application path of the currently running snarl window"""
- app_path = None
- snarl_handle = snGetSnarlWindow()
- if snarl_handle != 0:
- pathwin_handle = myWin32Funcs.FindWindowEx(snarl_handle,
- 0,
- "static",
- None)
- if pathwin_handle != 0:
- try:
- result = myWin32Funcs.GetWindowText(pathwin_handle)
- app_path = result
- except Win32FuncException:
- pass
-
-
- return app_path
-
-def snGetIconsPath():
- """Returns the path to the icons of the program"""
- s = snGetAppPath()
- if s is None:
- return ""
- else:
- return s + "etc\\icons\\"
-
-def snSendTestMessage(data=None):
- """Sends a test message to Snarl. Used to make sure the
-api is connecting"""
- param = 0
- command = 0
- if data:
- param = struct.pack("I", data)
- command = 1
- myWin32Funcs.SendMessage(snGetSnarlWindow(), WM_SNARLTEST, command, param)
+""" +A python version of the main functions to use Snarl +(http://www.fullphat.net/snarl) + +Version 1.0 + +This module can be used in two ways. One is the normal way +the other snarl interfaces work. This means you can call snShowMessage +and get an ID back for manipulations. + +The other way is there is a class this module exposes called SnarlMessage. +This allows you to keep track of the message as a python object. If you +use the send without specifying False as the argument it will set the ID +to what the return of the last SendMessage was. This is of course only +useful for the SHOW message. + +Requires one of: + pywin32 extensions from http://pywin32.sourceforge.net + ctypes (included in Python 2.5, downloadable for earlier versions) + +Creator: Sam Listopad II (samlii@users.sourceforge.net) + +Copyright 2006-2008 Samuel Listopad II + +Licensed under the Apache License, Version 2.0 (the "License"); you may not +use this file except in compliance with the License. You may obtain a copy +of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required +by applicable law or agreed to in writing, software distributed under the +License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS +OF ANY KIND, either express or implied. See the License for the specific +language governing permissions and limitations under the License. +""" + +import array, struct + +def LOWORD(dword): + """Return the low WORD of the passed in integer""" + return dword & 0x0000ffff +#get the hi word +def HIWORD(dword): + """Return the high WORD of the passed in integer""" + return dword >> 16 + +class Win32FuncException(Exception): + def __init__(self, value): + self.value = value + + def __str__(self): + return repr(self.value) + +class Win32Funcs: + """Just a little class to hide the details of finding and using the +correct win32 functions. The functions may throw a UnicodeEncodeError if +there is not a unicode version and it is sent a unicode string that cannot +be converted to ASCII.""" + WM_USER = 0x400 + WM_COPYDATA = 0x4a + #Type of String the functions are expecting. + #Used like function(myWin32Funcs.strType(param)). + __strType = str + #FindWindow function to use + __FindWindow = None + #FindWindow function to use + __FindWindowEx = None + #SendMessage function to use + __SendMessage = None + #SendMessageTimeout function to use + __SendMessageTimeout = None + #IsWindow function to use + __IsWindow = None + #RegisterWindowMessage to use + __RegisterWindowMessage = None + #GetWindowText to use + __GetWindowText = None + + def FindWindow(self, lpClassName, lpWindowName): + """Wraps the windows API call of FindWindow""" + if lpClassName is not None: + lpClassName = self.__strType(lpClassName) + if lpWindowName is not None: + lpWindowName = self.__strType(lpWindowName) + return self.__FindWindow(lpClassName, lpWindowName) + + def FindWindowEx(self, hwndParent, hwndChildAfter, lpClassName, lpWindowName): + """Wraps the windows API call of FindWindow""" + if lpClassName is not None: + lpClassName = self.__strType(lpClassName) + if lpWindowName is not None: + lpWindowName = self.__strType(lpWindowName) + return self.__FindWindowEx(hwndParent, hwndChildAfter, lpClassName, lpWindowName) + + def SendMessage(self, hWnd, Msg, wParam, lParam): + """Wraps the windows API call of SendMessage""" + return self.__SendMessage(hWnd, Msg, wParam, lParam) + + def SendMessageTimeout(self, hWnd, Msg, + wParam, lParam, fuFlags, + uTimeout, lpdwResult = None): + """Wraps the windows API call of SendMessageTimeout""" + idToRet = None + try: + idFromMsg = array.array('I', [0]) + result = idFromMsg.buffer_info()[0] + response = self.__SendMessageTimeout(hWnd, Msg, wParam, + lParam, fuFlags, + uTimeout, result) + if response == 0: + raise Win32FuncException, "SendMessageTimeout TimedOut" + + idToRet = idFromMsg[0] + except TypeError: + idToRet = self.__SendMessageTimeout(hWnd, Msg, wParam, + lParam, fuFlags, + uTimeout) + + if lpdwResult is not None and lpdwResult.typecode == 'I': + lpdwResult[0] = idToRet + + return idToRet + + def IsWindow(self, hWnd): + """Wraps the windows API call of IsWindow""" + return self.__IsWindow(hWnd) + + def RegisterWindowMessage(self, lpString): + """Wraps the windows API call of RegisterWindowMessage""" + return self.__RegisterWindowMessage(self.__strType(lpString)) + + def GetWindowText(self, hWnd, lpString = None, nMaxCount = None): + """Wraps the windows API call of SendMessageTimeout""" + text = '' + if hWnd == 0: + return text + + if nMaxCount is None: + nMaxCount = 1025 + + try: + arrayType = 'c' + if self.__strType == unicode: + arrayType = 'u' + path_string = array.array(arrayType, self.__strType('\x00') * nMaxCount) + path_buffer = path_string.buffer_info()[0] + result = self.__GetWindowText(hWnd, + path_buffer, + nMaxCount) + if result > 0: + if self.__strType == unicode: + text = path_string[0:result].tounicode() + else: + text = path_string[0:result].tostring() + except TypeError: + text = self.__GetWindowText(hWnd) + + if lpString is not None and lpString.typecode == 'c': + lpdwResult[0:len(text)] = array.array('c', str(text)); + + if lpString is not None and lpString.typecode == 'u': + lpdwResult[0:len(text)] = array.array('u', unicode(text)); + + return text + + def __init__(self): + """Load up my needed functions""" + # First see if they already have win32gui imported. If so use it. + # This has to be checked first since the auto check looks for ctypes + # first. + try: + self.__FindWindow = win32gui.FindWindow + self.__FindWindowEx = win32gui.FindWindowEx + self.__GetWindowText = win32gui.GetWindowText + self.__IsWindow = win32gui.IsWindow + self.__SendMessage = win32gui.SendMessage + self.__SendMessageTimeout = win32gui.SendMessageTimeout + self.__RegisterWindowMessage = win32gui.RegisterWindowMessage + self.__strType = unicode + + #Something threw a NameError, most likely the win32gui lines + #so do auto check + except NameError: + try: + from ctypes import windll + self.__FindWindow = windll.user32.FindWindowW + self.__FindWindowEx = windll.user32.FindWindowExW + self.__GetWindowText = windll.user32.GetWindowTextW + self.__IsWindow = windll.user32.IsWindow + self.__SendMessage = windll.user32.SendMessageW + self.__SendMessageTimeout = windll.user32.SendMessageTimeoutW + self.__RegisterWindowMessage = windll.user32.RegisterWindowMessageW + self.__strType = unicode + + #FindWindowW wasn't found, look for FindWindowA + except AttributeError: + try: + self.__FindWindow = windll.user32.FindWindowA + self.__FindWindowEx = windll.user32.FindWindowExA + self.__GetWindowText = windll.user32.GetWindowTextA + self.__IsWindow = windll.user32.IsWindow + self.__SendMessage = windll.user32.SendMessageA + self.__SendMessageTimeout = windll.user32.SendMessageTimeoutA + self.__RegisterWindowMessage = windll.user32.RegisterWindowMessageA + # Couldn't find either so Die and tell user why. + except AttributeError: + import sys + sys.stderr.write("Your Windows TM setup seems to be corrupt."+ + " No FindWindow found in user32.\n") + sys.stderr.flush() + sys.exit(3) + + except ImportError: + try: + import win32gui + self.__FindWindow = win32gui.FindWindow + self.__FindWindowEx = win32gui.FindWindowEx + self.__GetWindowText = win32gui.GetWindowText + self.__IsWindow = win32gui.IsWindow + self.__SendMessage = win32gui.SendMessage + self.__SendMessageTimeout = win32gui.SendMessageTimeout + self.__RegisterWindowMessage = win32gui.RegisterWindowMessage + self.__strType = unicode + + except ImportError: + import sys + sys.stderr.write("You need to have either"+ + " ctypes or pywin32 installed.\n") + sys.stderr.flush() + #sys.exit(2) + + +myWin32Funcs = Win32Funcs() + + +SHOW = 1 +HIDE = 2 +UPDATE = 3 +IS_VISIBLE = 4 +GET_VERSION = 5 +REGISTER_CONFIG_WINDOW = 6 +REVOKE_CONFIG_WINDOW = 7 +REGISTER_ALERT = 8 +REVOKE_ALERT = 9 +REGISTER_CONFIG_WINDOW_2 = 10 +GET_VERSION_EX = 11 +SET_TIMEOUT = 12 + +EX_SHOW = 32 + +GLOBAL_MESSAGE = "SnarlGlobalMessage" +GLOBAL_MSG = "SnarlGlobalEvent" + +#Messages That may be received from Snarl +SNARL_LAUNCHED = 1 +SNARL_QUIT = 2 +SNARL_ASK_APPLET_VER = 3 +SNARL_SHOW_APP_UI = 4 + +SNARL_NOTIFICATION_CLICKED = 32 #notification was right-clicked by user +SNARL_NOTIFICATION_CANCELLED = SNARL_NOTIFICATION_CLICKED #Name clarified +SNARL_NOTIFICATION_TIMED_OUT = 33 +SNARL_NOTIFICATION_ACK = 34 #notification was left-clicked by user + +#Snarl Test Message +WM_SNARLTEST = myWin32Funcs.WM_USER + 237 + +M_ABORTED = 0x80000007L +M_ACCESS_DENIED = 0x80000009L +M_ALREADY_EXISTS = 0x8000000CL +M_BAD_HANDLE = 0x80000006L +M_BAD_POINTER = 0x80000005L +M_FAILED = 0x80000008L +M_INVALID_ARGS = 0x80000003L +M_NO_INTERFACE = 0x80000004L +M_NOT_FOUND = 0x8000000BL +M_NOT_IMPLEMENTED = 0x80000001L +M_OK = 0x00000000L +M_OUT_OF_MEMORY = 0x80000002L +M_TIMED_OUT = 0x8000000AL + +ErrorCodeRev = { + 0x80000007L : "M_ABORTED", + 0x80000009L : "M_ACCESS_DENIED", + 0x8000000CL : "M_ALREADY_EXISTS", + 0x80000006L : "M_BAD_HANDLE", + 0x80000005L : "M_BAD_POINTER", + 0x80000008L : "M_FAILED", + 0x80000003L : "M_INVALID_ARGS", + 0x80000004L : "M_NO_INTERFACE", + 0x8000000BL : "M_NOT_FOUND", + 0x80000001L : "M_NOT_IMPLEMENTED", + 0x00000000L : "M_OK", + 0x80000002L : "M_OUT_OF_MEMORY", + 0x8000000AL : "M_TIMED_OUT" + } + +class SnarlMessage(object): + """The main Snarl interface object. + + ID = Snarl Message ID for most operations. See SDK for more info + as to other values to put here. + type = Snarl Message Type. Valid values are : SHOW, HIDE, UPDATE, + IS_VISIBLE, GET_VERSION, REGISTER_CONFIG_WINDOW, REVOKE_CONFIG_WINDOW + all which are constants in the PySnarl module. + timeout = Timeout in seconds for the Snarl Message + data = Snarl Message data. This is dependant upon message type. See SDK + title = Snarl Message title. + text = Snarl Message text. + icon = Path to the icon to display in the Snarl Message. + """ + __msgType = 0 + __msgID = 0 + __msgTimeout = 0 + __msgData = 0 + __msgTitle = "" + __msgText = "" + __msgIcon = "" + __msgClass = "" + __msgExtra = "" + __msgExtra2 = "" + __msgRsvd1 = 0 + __msgRsvd2 = 0 + __msgHWnd = 0 + + lastKnownHWnd = 0 + + def getType(self): + """Type Attribute getter.""" + return self.__msgType + def setType(self, value): + """Type Attribute setter.""" + if( isinstance(value, (int, long)) ): + self.__msgType = value + type = property(getType, setType, doc="The Snarl Message Type") + + def getID(self): + """ID Attribute getter.""" + return self.__msgID + def setID(self, value): + """ID Attribute setter.""" + if( isinstance(value, (int, long)) ): + self.__msgID = value + ID = property(getID, setID, doc="The Snarl Message ID") + + def getTimeout(self): + """Timeout Attribute getter.""" + return self.__msgTimeout + def updateTimeout(self, value): + """Timeout Attribute setter.""" + if( isinstance(value, (int, long)) ): + self.__msgTimeout = value + timeout = property(getTimeout, updateTimeout, + doc="The Snarl Message Timeout") + + def getData(self): + """Data Attribute getter.""" + return self.__msgData + def setData(self, value): + """Data Attribute setter.""" + if( isinstance(value, (int, long)) ): + self.__msgData = value + data = property(getData, setData, doc="The Snarl Message Data") + + def getTitle(self): + """Title Attribute getter.""" + return self.__msgTitle + def setTitle(self, value): + """Title Attribute setter.""" + if( isinstance(value, basestring) ): + self.__msgTitle = value + title = property(getTitle, setTitle, doc="The Snarl Message Title") + + def getText(self): + """Text Attribute getter.""" + return self.__msgText + def setText(self, value): + """Text Attribute setter.""" + if( isinstance(value, basestring) ): + self.__msgText = value + text = property(getText, setText, doc="The Snarl Message Text") + + def getIcon(self): + """Icon Attribute getter.""" + return self.__msgIcon + def setIcon(self, value): + """Icon Attribute setter.""" + if( isinstance(value, basestring) ): + self.__msgIcon = value + icon = property(getIcon, setIcon, doc="The Snarl Message Icon") + + def getClass(self): + """Class Attribute getter.""" + return self.__msgClass + def setClass(self, value): + """Class Attribute setter.""" + if( isinstance(value, basestring) ): + self.__msgClass = value + msgclass = property(getClass, setClass, doc="The Snarl Message Class") + + def getExtra(self): + """Extra Attribute getter.""" + return self.__msgExtra + def setExtra(self, value): + """Extra Attribute setter.""" + if( isinstance(value, basestring) ): + self.__msgExtra = value + extra = property(getExtra, setExtra, doc="Extra Info for the Snarl Message") + + def getExtra2(self): + """Extra2 Attribute getter.""" + return self.__msgExtra2 + def setExtra2(self, value): + """Extra2 Attribute setter.""" + if( isinstance(value, basestring) ): + self.__msgExtra2 = value + extra2 = property(getExtra2, setExtra2, + doc="More Extra Info for the Snarl Message") + + def getRsvd1(self): + """Rsvd1 Attribute getter.""" + return self.__msgRsvd1 + def setRsvd1(self, value): + """Rsvd1 Attribute setter.""" + if( isinstance(value, (int, long)) ): + self.__msgRsvd1 = value + rsvd1 = property(getRsvd1, setRsvd1, doc="The Snarl Message Field Rsvd1") + + def getRsvd2(self): + """Rsvd2 Attribute getter.""" + return self.__msgRsvd2 + def setRsvd2(self, value): + """Rsvd2 Attribute setter.""" + if( isinstance(value, (int, long)) ): + self.__msgRsvd2 = value + rsvd2 = property(getRsvd2, setRsvd2, doc="The Snarl Message Field Rsvd2") + + def getHwnd(self): + """hWnd Attribute getter.""" + return self.__msgHWnd + def setHwnd(self, value): + """hWnd Attribute setter.""" + if( isinstance(value, (int, long)) ): + self.__msgHWnd = value + + hWnd = property(getHwnd, setHwnd, doc="The hWnd of the window this message is being sent from") + + + def __init__(self, title="", text="", icon="", msg_type=1, msg_id=0): + self.__msgTimeout = 0 + self.__msgData = 0 + self.__msgClass = "" + self.__msgExtra = "" + self.__msgExtra2 = "" + self.__msgRsvd1 = 0 + self.__msgRsvd2 = 0 + self.__msgType = msg_type + self.__msgText = text + self.__msgTitle = title + self.__msgIcon = icon + self.__msgID = msg_id + + def createCopyStruct(self): + """Creates the struct to send as the copyData in the message.""" + return struct.pack("ILLL1024s1024s1024s1024s1024s1024sLL", + self.__msgType, + self.__msgID, + self.__msgTimeout, + self.__msgData, + self.__msgTitle.encode('utf-8'), + self.__msgText.encode('utf-8'), + self.__msgIcon.encode('utf-8'), + self.__msgClass.encode('utf-8'), + self.__msgExtra.encode('utf-8'), + self.__msgExtra2.encode('utf-8'), + self.__msgRsvd1, + self.__msgRsvd2 + ) + __lpData = None + __cds = None + + def packData(self, dwData): + """This packs the data in the necessary format for a +WM_COPYDATA message.""" + self.__lpData = None + self.__cds = None + item = self.createCopyStruct() + self.__lpData = array.array('c', item) + lpData_ad = self.__lpData.buffer_info()[0] + cbData = self.__lpData.buffer_info()[1] + self.__cds = array.array('c', + struct.pack("IIP", + dwData, + cbData, + lpData_ad) + ) + cds_ad = self.__cds.buffer_info()[0] + return cds_ad + + def reset(self): + """Reset this SnarlMessage to the default state.""" + self.__msgType = 0 + self.__msgID = 0 + self.__msgTimeout = 0 + self.__msgData = 0 + self.__msgTitle = "" + self.__msgText = "" + self.__msgIcon = "" + self.__msgClass = "" + self.__msgExtra = "" + self.__msgExtra2 = "" + self.__msgRsvd1 = 0 + self.__msgRsvd2 = 0 + + + def send(self, setid=True): + """Send this SnarlMessage to the Snarl window. +Args: + setid - Boolean defining whether or not to set the ID + of this SnarlMessage to the return value of + the SendMessage call. Default is True to + make simple case of SHOW easy. + """ + hwnd = myWin32Funcs.FindWindow(None, "Snarl") + if myWin32Funcs.IsWindow(hwnd): + if self.type == REGISTER_CONFIG_WINDOW or self.type == REGISTER_CONFIG_WINDOW_2: + self.hWnd = self.data + try: + response = myWin32Funcs.SendMessageTimeout(hwnd, + myWin32Funcs.WM_COPYDATA, + self.hWnd, self.packData(2), + 2, 500) + except Win32FuncException: + return False + + idFromMsg = response + if setid: + self.ID = idFromMsg + return True + else: + return idFromMsg + print "No snarl window found" + return False + + def hide(self): + """Hide this message. Type will revert to type before calling hide +to allow for better reuse of object.""" + oldType = self.__msgType + self.__msgType = HIDE + retVal = bool(self.send(False)) + self.__msgType = oldType + return retVal + + def isVisible(self): + """Is this message visible. Type will revert to type before calling +hide to allow for better reuse of object.""" + oldType = self.__msgType + self.__msgType = IS_VISIBLE + retVal = bool(self.send(False)) + self.__msgType = oldType + return retVal + + def update(self, title=None, text=None, icon=None): + """Update this message with given title and text. Type will revert +to type before calling hide to allow for better reuse of object.""" + oldType = self.__msgType + self.__msgType = UPDATE + if text: + self.__msgText = text + if title: + self.__msgTitle = title + if icon: + self.__msgIcon = icon + retVal = self.send(False) + self.__msgType = oldType + return retVal + + def setTimeout(self, timeout): + """Set the timeout in seconds of the message""" + oldType = self.__msgType + oldData = self.__msgData + self.__msgType = SET_TIMEOUT + #self.timeout = timeout + #self.__msgData = self.__msgTimeout + self.__msgData = timeout + retVal = self.send(False) + self.__msgType = oldType + self.__msgData = oldData + return retVal + + def show(self, timeout=None, title=None, + text=None, icon=None, + replyWindow=None, replyMsg=None, msgclass=None, soundPath=None): + """Show a message""" + oldType = self.__msgType + oldTimeout = self.__msgTimeout + self.__msgType = SHOW + if text: + self.__msgText = text + if title: + self.__msgTitle = title + if timeout: + self.__msgTimeout = timeout + if icon: + self.__msgIcon = icon + if replyWindow: + self.__msgID = replyMsg + if replyMsg: + self.__msgData = replyWindow + if soundPath: + self.__msgExtra = soundPath + if msgclass: + self.__msgClass = msgclass + + if ((self.__msgClass and self.__msgClass != "") or + (self.__msgExtra and self.__msgExtra != "")): + self.__msgType = EX_SHOW + + + retVal = bool(self.send()) + self.__msgType = oldType + self.__msgTimeout = oldTimeout + return retVal + + +def snGetVersion(): + """ Get the version of Snarl that is running as a tuple. (Major, Minor) + +If Snarl is not running or there was an error it will +return False.""" + msg = SnarlMessage(msg_type=GET_VERSION) + version = msg.send(False) + if not version: + return False + return (HIWORD(version), LOWORD(version)) + +def snGetVersionEx(): + """ Get the internal version of Snarl that is running. + +If Snarl is not running or there was an error it will +return False.""" + sm = SnarlMessage(msg_type=GET_VERSION_EX) + verNum = sm.send(False) + if not verNum: + return False + return verNum + +def snGetGlobalMessage(): + """Get the Snarl global message id from windows.""" + return myWin32Funcs.RegisterWindowMessage(GLOBAL_MSG) + +def snShowMessage(title, text, timeout=0, iconPath="", + replyWindow=0, replyMsg=0): + """Show a message using Snarl and return its ID. See SDK for arguments.""" + sm = SnarlMessage( title, text, iconPath, msg_id=replyMsg) + sm.data = replyWindow + if sm.show(timeout): + return sm.ID + else: + return False + +def snShowMessageEx(msgClass, title, text, timeout=0, iconPath="", + replyWindow=0, replyMsg=0, soundFile=None, hWndFrom=None): + """Show a message using Snarl and return its ID. See SDK for arguments. + One added argument is hWndFrom that allows one to make the messages appear + to come from a specific window. This window should be the one you registered + earlier with RegisterConfig""" + sm = SnarlMessage( title, text, iconPath, msg_id=replyMsg) + sm.data = replyWindow + if hWndFrom is not None: + sm.hWnd = hWndFrom + else: + sm.hWnd = SnarlMessage.lastKnownHWnd + if sm.show(timeout, msgclass=msgClass, soundPath=soundFile): + return sm.ID + else: + return False + +def snUpdateMessage(msgId, msgTitle, msgText, icon=None): + """Update a message""" + sm = SnarlMessage(msg_id=msgId) + if icon: + sm.icon = icon + return sm.update(msgTitle, msgText) + +def snHideMessage(msgId): + """Hide a message""" + return SnarlMessage(msg_id=msgId).hide() + +def snSetTimeout(msgId, timeout): + """Update the timeout of a message already shown.""" + sm = SnarlMessage(msg_id=msgId) + return sm.setTimeout(timeout) + +def snIsMessageVisible(msgId): + """Returns True if the message is visible False otherwise.""" + return SnarlMessage(msg_id=msgId).isVisible() + +def snRegisterConfig(replyWnd, appName, replyMsg): + """Register a config window. See SDK for more info.""" + global lastRegisteredSnarlMsg + sm = SnarlMessage(msg_type=REGISTER_CONFIG_WINDOW, + title=appName, + msg_id=replyMsg) + sm.data = replyWnd + SnarlMessage.lastKnownHWnd = replyWnd + + return sm.send(False) + +def snRegisterConfig2(replyWnd, appName, replyMsg, icon): + """Register a config window. See SDK for more info.""" + global lastRegisteredSnarlMsg + sm = SnarlMessage(msg_type=REGISTER_CONFIG_WINDOW_2, + title=appName, + msg_id=replyMsg, + icon=icon) + sm.data = replyWnd + SnarlMessage.lastKnownHWnd = replyWnd + return sm.send(False) + +def snRegisterAlert(appName, classStr) : + """Register an alert for an already registered config. See SDK for more info.""" + sm = SnarlMessage(msg_type=REGISTER_ALERT, + title=appName, + text=classStr) + return sm.send(False) + +def snRevokeConfig(replyWnd): + """Revoke a config window""" + sm = SnarlMessage(msg_type=REVOKE_CONFIG_WINDOW) + sm.data = replyWnd + if replyWnd == SnarlMessage.lastKnownHWnd: + SnarlMessage.lastKnownHWnd = 0 + return sm.send(False) + +def snGetSnarlWindow(): + """Returns the hWnd of the snarl window""" + return myWin32Funcs.FindWindow(None, "Snarl") + +def snGetAppPath(): + """Returns the application path of the currently running snarl window""" + app_path = None + snarl_handle = snGetSnarlWindow() + if snarl_handle != 0: + pathwin_handle = myWin32Funcs.FindWindowEx(snarl_handle, + 0, + "static", + None) + if pathwin_handle != 0: + try: + result = myWin32Funcs.GetWindowText(pathwin_handle) + app_path = result + except Win32FuncException: + pass + + + return app_path + +def snGetIconsPath(): + """Returns the path to the icons of the program""" + s = snGetAppPath() + if s is None: + return "" + else: + return s + "etc\\icons\\" + +def snSendTestMessage(data=None): + """Sends a test message to Snarl. Used to make sure the +api is connecting""" + param = 0 + command = 0 + if data: + param = struct.pack("I", data) + command = 1 + myWin32Funcs.SendMessage(snGetSnarlWindow(), WM_SNARLTEST, command, param) diff --git a/plugins/snarl_notifications/__init__.py b/plugins/snarl_notifications/__init__.py index ad9c96aaa..b504dfd50 100644 --- a/plugins/snarl_notifications/__init__.py +++ b/plugins/snarl_notifications/__init__.py @@ -1 +1 @@ -from plugin import SnarlNotificationsPlugin
\ No newline at end of file +from plugin import SnarlNotificationsPlugin diff --git a/plugins/snarl_notifications/plugin.py b/plugins/snarl_notifications/plugin.py index 4d831ee39..3e21acb77 100644 --- a/plugins/snarl_notifications/plugin.py +++ b/plugins/snarl_notifications/plugin.py @@ -38,54 +38,53 @@ from plugins.helpers import log_calls, log from common import ged class SnarlNotificationsPlugin(GajimPlugin): - name = u'Snarl Notifications' - short_name = u'snarl_notifications' - version = u'0.1' - description = u'''Shows events notification using Snarl (http://www.fullphat.net/) under Windows. Snarl needs to be installed in system. + name = u'Snarl Notifications' + short_name = u'snarl_notifications' + version = u'0.1' + description = u'''Shows events notification using Snarl (http://www.fullphat.net/) under Windows. Snarl needs to be installed in system. PySnarl bindings are used (http://code.google.com/p/pysnarl/).''' - authors = [u'Mateusz Biliński <mateusz@bilinski.it>'] - homepage = u'http://blog.bilinski.it' - - @log_calls('SnarlNotificationsPlugin') - def init(self): - self.config_dialog = None - #self.gui_extension_points = {} - #self.config_default_values = {} - - self.events_handlers = {'NewMessage' : (ged.POSTCORE, self.newMessage)} + authors = [u'Mateusz Biliński <mateusz@bilinski.it>'] + homepage = u'http://blog.bilinski.it' - @log_calls('SnarlNotificationsPlugin') - def activate(self): - pass - - @log_calls('SnarlNotificationsPlugin') - def deactivate(self): - pass - - @log_calls('SnarlNotificationsPlugin') - def newMessage(self, args): - event_name = "NewMessage" - data = args - account = data[0] - jid = data[1][0] - jid_without_resource = gajim.get_jid_without_resource(jid) - msg = data[1][1] - msg_type = data[1][4] - if msg_type == 'chat': - nickname = gajim.get_contact_name_from_jid(account, - jid_without_resource) - elif msg_type == 'pm': - nickname = gajim.get_resource_from_jid(jid) - - print "Event '%s' occured. Arguments: %s\n\n===\n"%(event_name, pformat(args)) - print "Event '%s' occured. Arguments: \naccount = %s\njid = %s\nmsg = %s\nnickname = %s"%( - event_name, account, jid, msg, nickname) - - - #if PySnarl.snGetVersion() != False: - #(major, minor) = PySnarl.snGetVersion() - #print "Found Snarl version",str(major)+"."+str(minor),"running." - #PySnarl.snShowMessage(nickname, msg[:20]+'...') - #else: - #print "Sorry Snarl does not appear to be running" -
\ No newline at end of file + @log_calls('SnarlNotificationsPlugin') + def init(self): + self.config_dialog = None + #self.gui_extension_points = {} + #self.config_default_values = {} + + self.events_handlers = {'NewMessage' : (ged.POSTCORE, self.newMessage)} + + @log_calls('SnarlNotificationsPlugin') + def activate(self): + pass + + @log_calls('SnarlNotificationsPlugin') + def deactivate(self): + pass + + @log_calls('SnarlNotificationsPlugin') + def newMessage(self, args): + event_name = "NewMessage" + data = args + account = data[0] + jid = data[1][0] + jid_without_resource = gajim.get_jid_without_resource(jid) + msg = data[1][1] + msg_type = data[1][4] + if msg_type == 'chat': + nickname = gajim.get_contact_name_from_jid(account, + jid_without_resource) + elif msg_type == 'pm': + nickname = gajim.get_resource_from_jid(jid) + + print "Event '%s' occured. Arguments: %s\n\n===\n"%(event_name, pformat(args)) + print "Event '%s' occured. Arguments: \naccount = %s\njid = %s\nmsg = %s\nnickname = %s"%( + event_name, account, jid, msg, nickname) + + + #if PySnarl.snGetVersion() != False: + #(major, minor) = PySnarl.snGetVersion() + #print "Found Snarl version",str(major)+"."+str(minor),"running." + #PySnarl.snShowMessage(nickname, msg[:20]+'...') + #else: + #print "Sorry Snarl does not appear to be running" |