merge presence handling modifications changes
This commit is contained in:
commit
e0ac19678c
31 changed files with 290 additions and 199 deletions
|
@ -270,6 +270,8 @@
|
||||||
<property name="can_focus">True</property>
|
<property name="can_focus">True</property>
|
||||||
<property name="receives_default">True</property>
|
<property name="receives_default">True</property>
|
||||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||||
|
<property name="has_tooltip">True</property>
|
||||||
|
<property name="tooltip_text" translatable="yes">Show a list of emoticons (Alt+M)</property>
|
||||||
<property name="relief">none</property>
|
<property name="relief">none</property>
|
||||||
<property name="focus_on_click">False</property>
|
<property name="focus_on_click">False</property>
|
||||||
<child>
|
<child>
|
||||||
|
@ -292,6 +294,8 @@
|
||||||
<property name="can_focus">True</property>
|
<property name="can_focus">True</property>
|
||||||
<property name="receives_default">True</property>
|
<property name="receives_default">True</property>
|
||||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||||
|
<property name="has_tooltip">True</property>
|
||||||
|
<property name="tooltip_text" translatable="yes">Show a list of formattings</property>
|
||||||
<property name="relief">none</property>
|
<property name="relief">none</property>
|
||||||
<property name="focus_on_click">False</property>
|
<property name="focus_on_click">False</property>
|
||||||
<child>
|
<child>
|
||||||
|
@ -324,6 +328,8 @@
|
||||||
<property name="receives_default">True</property>
|
<property name="receives_default">True</property>
|
||||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||||
<property name="no_show_all">True</property>
|
<property name="no_show_all">True</property>
|
||||||
|
<property name="has_tooltip">True</property>
|
||||||
|
<property name="tooltip_text" translatable="yes">Add this contact to roster (Ctrl+D)</property>
|
||||||
<property name="relief">none</property>
|
<property name="relief">none</property>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkImage" id="image9">
|
<object class="GtkImage" id="image9">
|
||||||
|
@ -365,6 +371,8 @@
|
||||||
<object class="GtkToggleButton" id="audio_togglebutton">
|
<object class="GtkToggleButton" id="audio_togglebutton">
|
||||||
<property name="can_focus">True</property>
|
<property name="can_focus">True</property>
|
||||||
<property name="receives_default">True</property>
|
<property name="receives_default">True</property>
|
||||||
|
<property name="has_tooltip">True</property>
|
||||||
|
<property name="tooltip_text" translatable="yes">Toggle audio session</property>
|
||||||
<property name="relief">none</property>
|
<property name="relief">none</property>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkImage" id="audio_image">
|
<object class="GtkImage" id="audio_image">
|
||||||
|
@ -383,6 +391,8 @@
|
||||||
<object class="GtkToggleButton" id="video_togglebutton">
|
<object class="GtkToggleButton" id="video_togglebutton">
|
||||||
<property name="can_focus">True</property>
|
<property name="can_focus">True</property>
|
||||||
<property name="receives_default">True</property>
|
<property name="receives_default">True</property>
|
||||||
|
<property name="has_tooltip">True</property>
|
||||||
|
<property name="tooltip_text" translatable="yes">Toggle video session</property>
|
||||||
<property name="relief">none</property>
|
<property name="relief">none</property>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkImage" id="video_image">
|
<object class="GtkImage" id="video_image">
|
||||||
|
@ -403,6 +413,8 @@
|
||||||
<property name="can_focus">True</property>
|
<property name="can_focus">True</property>
|
||||||
<property name="receives_default">True</property>
|
<property name="receives_default">True</property>
|
||||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||||
|
<property name="has_tooltip">True</property>
|
||||||
|
<property name="tooltip_text" translatable="yes">Invite contacts to the conversation (Ctrl+G)</property>
|
||||||
<property name="relief">none</property>
|
<property name="relief">none</property>
|
||||||
<property name="focus_on_click">False</property>
|
<property name="focus_on_click">False</property>
|
||||||
<child>
|
<child>
|
||||||
|
@ -425,6 +437,8 @@
|
||||||
<property name="can_focus">True</property>
|
<property name="can_focus">True</property>
|
||||||
<property name="receives_default">True</property>
|
<property name="receives_default">True</property>
|
||||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||||
|
<property name="has_tooltip">True</property>
|
||||||
|
<property name="tooltip_text" translatable="yes">Show the contact's profile (Ctrl+I)</property>
|
||||||
<property name="relief">none</property>
|
<property name="relief">none</property>
|
||||||
<property name="focus_on_click">False</property>
|
<property name="focus_on_click">False</property>
|
||||||
<child>
|
<child>
|
||||||
|
@ -447,6 +461,8 @@
|
||||||
<property name="can_focus">True</property>
|
<property name="can_focus">True</property>
|
||||||
<property name="receives_default">True</property>
|
<property name="receives_default">True</property>
|
||||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||||
|
<property name="has_tooltip">True</property>
|
||||||
|
<property name="tooltip_text" translatable="yes">Browse the chat history (Ctrl+H)</property>
|
||||||
<property name="relief">none</property>
|
<property name="relief">none</property>
|
||||||
<property name="focus_on_click">False</property>
|
<property name="focus_on_click">False</property>
|
||||||
<child>
|
<child>
|
||||||
|
@ -480,6 +496,8 @@
|
||||||
<property name="can_focus">True</property>
|
<property name="can_focus">True</property>
|
||||||
<property name="receives_default">True</property>
|
<property name="receives_default">True</property>
|
||||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||||
|
<property name="has_tooltip">True</property>
|
||||||
|
<property name="tooltip_text" translatable="yes">Show a menu of advanced functions (Alt+D)</property>
|
||||||
<property name="relief">none</property>
|
<property name="relief">none</property>
|
||||||
<property name="focus_on_click">False</property>
|
<property name="focus_on_click">False</property>
|
||||||
<child>
|
<child>
|
||||||
|
|
|
@ -166,6 +166,8 @@
|
||||||
<property name="can_focus">True</property>
|
<property name="can_focus">True</property>
|
||||||
<property name="receives_default">True</property>
|
<property name="receives_default">True</property>
|
||||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||||
|
<property name="has_tooltip">True</property>
|
||||||
|
<property name="tooltip_text" translatable="yes">Show a list of emoticons (Alt+M)</property>
|
||||||
<property name="relief">none</property>
|
<property name="relief">none</property>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkImage" id="emoticons_button_image">
|
<object class="GtkImage" id="emoticons_button_image">
|
||||||
|
@ -193,6 +195,8 @@
|
||||||
<property name="can_focus">True</property>
|
<property name="can_focus">True</property>
|
||||||
<property name="receives_default">True</property>
|
<property name="receives_default">True</property>
|
||||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||||
|
<property name="has_tooltip">True</property>
|
||||||
|
<property name="tooltip_text" translatable="yes">Show a list of formattings</property>
|
||||||
<property name="relief">none</property>
|
<property name="relief">none</property>
|
||||||
<property name="focus_on_click">False</property>
|
<property name="focus_on_click">False</property>
|
||||||
<child>
|
<child>
|
||||||
|
@ -224,6 +228,8 @@
|
||||||
<property name="can_focus">True</property>
|
<property name="can_focus">True</property>
|
||||||
<property name="receives_default">True</property>
|
<property name="receives_default">True</property>
|
||||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||||
|
<property name="has_tooltip">True</property>
|
||||||
|
<property name="tooltip_text" translatable="yes">Change your nickname (Ctrl+N)</property>
|
||||||
<property name="relief">none</property>
|
<property name="relief">none</property>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkImage" id="image4">
|
<object class="GtkImage" id="image4">
|
||||||
|
@ -246,6 +252,8 @@
|
||||||
<property name="can_focus">True</property>
|
<property name="can_focus">True</property>
|
||||||
<property name="receives_default">True</property>
|
<property name="receives_default">True</property>
|
||||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||||
|
<property name="has_tooltip">True</property>
|
||||||
|
<property name="tooltip_text" translatable="yes">Change the room's subject (Alt+T)</property>
|
||||||
<property name="relief">none</property>
|
<property name="relief">none</property>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkImage" id="image6">
|
<object class="GtkImage" id="image6">
|
||||||
|
@ -269,6 +277,8 @@
|
||||||
<property name="receives_default">True</property>
|
<property name="receives_default">True</property>
|
||||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||||
<property name="no_show_all">True</property>
|
<property name="no_show_all">True</property>
|
||||||
|
<property name="has_tooltip">True</property>
|
||||||
|
<property name="tooltip_text" translatable="yes">Bookmark this room (Ctrl+B)</property>
|
||||||
<property name="relief">none</property>
|
<property name="relief">none</property>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkImage" id="image7">
|
<object class="GtkImage" id="image7">
|
||||||
|
@ -291,6 +301,8 @@
|
||||||
<property name="can_focus">True</property>
|
<property name="can_focus">True</property>
|
||||||
<property name="receives_default">True</property>
|
<property name="receives_default">True</property>
|
||||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||||
|
<property name="has_tooltip">True</property>
|
||||||
|
<property name="tooltip_text" translatable="yes">Browse the chat history (Ctrl+H)</property>
|
||||||
<property name="relief">none</property>
|
<property name="relief">none</property>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkImage" id="image8">
|
<object class="GtkImage" id="image8">
|
||||||
|
@ -323,6 +335,8 @@
|
||||||
<property name="can_focus">True</property>
|
<property name="can_focus">True</property>
|
||||||
<property name="receives_default">True</property>
|
<property name="receives_default">True</property>
|
||||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||||
|
<property name="has_tooltip">True</property>
|
||||||
|
<property name="tooltip_text" translatable="yes">Show a menu of advanced functions (Alt+D)</property>
|
||||||
<property name="relief">none</property>
|
<property name="relief">none</property>
|
||||||
<property name="focus_on_click">False</property>
|
<property name="focus_on_click">False</property>
|
||||||
<child>
|
<child>
|
||||||
|
|
|
@ -3,8 +3,8 @@ INCLUDES = \
|
||||||
|
|
||||||
gajimpluginsdir = $(gajim_pluginsdir)
|
gajimpluginsdir = $(gajim_pluginsdir)
|
||||||
nobase_dist_gajimplugins_PYTHON = \
|
nobase_dist_gajimplugins_PYTHON = \
|
||||||
$(srcdir)/*.py \
|
|
||||||
$(srcdir)/*/*.py \
|
$(srcdir)/*/*.py \
|
||||||
|
$(srcdir)/*/manifest.ini \
|
||||||
$(srcdir)/*/*.ui
|
$(srcdir)/*/*.ui
|
||||||
|
|
||||||
MAINTAINERCLEANFILES = Makefile.in
|
MAINTAINERCLEANFILES = Makefile.in
|
||||||
|
|
1
plugins/acronyms_expander/__init__.py
Normal file
1
plugins/acronyms_expander/__init__.py
Normal file
|
@ -0,0 +1 @@
|
||||||
|
from acronyms_expander import AcronymsExpanderPlugin
|
|
@ -33,12 +33,6 @@ from plugins import GajimPlugin
|
||||||
from plugins.helpers import log, log_calls
|
from plugins.helpers import log, log_calls
|
||||||
|
|
||||||
class AcronymsExpanderPlugin(GajimPlugin):
|
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')
|
@log_calls('AcronymsExpanderPlugin')
|
||||||
def init(self):
|
def init(self):
|
9
plugins/acronyms_expander/manifest.ini
Normal file
9
plugins/acronyms_expander/manifest.ini
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
[info]
|
||||||
|
name: Acronyms Expander
|
||||||
|
short_name: acronyms_expander
|
||||||
|
version: 0.1
|
||||||
|
description: Replaces acronyms (or other strings) with given expansions/substitutes.
|
||||||
|
authors: Mateusz Biliński <mateusz@bilinski.it>
|
||||||
|
homepage: http://blog.bilinski.it
|
||||||
|
|
||||||
|
|
10
plugins/banner_tweaks/manifest.ini
Normal file
10
plugins/banner_tweaks/manifest.ini
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
[info]
|
||||||
|
name: Banner Tweaks
|
||||||
|
short_name: banner_tweaks
|
||||||
|
version: 0.1
|
||||||
|
description: 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 = Mateusz Biliński <mateusz@bilinski.it>
|
||||||
|
homepage = http://blog.bilinski.it
|
||||||
|
|
|
@ -43,15 +43,6 @@ from plugins.helpers import log, log_calls
|
||||||
from plugins.gui import GajimPluginConfigDialog
|
from plugins.gui import GajimPluginConfigDialog
|
||||||
|
|
||||||
class BannerTweaksPlugin(GajimPlugin):
|
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:
|
|
||||||
http://trac.gajim.org/attachment/ticket/4133'''
|
|
||||||
authors = [u'Mateusz Biliński <mateusz@bilinski.it>']
|
|
||||||
homepage = u'http://blog.bilinski.it'
|
|
||||||
|
|
||||||
@log_calls('BannerTweaksPlugin')
|
@log_calls('BannerTweaksPlugin')
|
||||||
def init(self):
|
def init(self):
|
||||||
|
|
10
plugins/dbus_plugin/manifest.ini
Normal file
10
plugins/dbus_plugin/manifest.ini
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
[info]
|
||||||
|
name: D-Bus Support
|
||||||
|
short_name: dbus
|
||||||
|
version: 0.1
|
||||||
|
description: D-Bus support. Based on remote_control module from
|
||||||
|
Gajim core but uses new events handling system.
|
||||||
|
authors = Mateusz Biliński <mateusz@bilinski.it>
|
||||||
|
homepage = http://blog.bilinski.it
|
||||||
|
|
||||||
|
|
|
@ -680,13 +680,6 @@ from plugins.helpers import log_calls, log
|
||||||
from common import ged
|
from common import ged
|
||||||
|
|
||||||
class DBusPlugin(GajimPlugin):
|
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
|
|
||||||
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')
|
@log_calls('DBusPlugin')
|
||||||
def init(self):
|
def init(self):
|
||||||
|
|
8
plugins/events_dump/manifest.ini
Normal file
8
plugins/events_dump/manifest.ini
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
[info]
|
||||||
|
name: Events Dump
|
||||||
|
short_name: events_dump
|
||||||
|
version: 0.1
|
||||||
|
description: Dumps info about selected events to console.
|
||||||
|
authors = Mateusz Biliński <mateusz@bilinski.it>
|
||||||
|
homepage = http://blog.bilinski.it
|
||||||
|
|
|
@ -33,12 +33,6 @@ from plugins.helpers import log_calls, log
|
||||||
from common import ged
|
from common import ged
|
||||||
|
|
||||||
class EventsDumpPlugin(GajimPlugin):
|
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')
|
@log_calls('EventsDumpPlugin')
|
||||||
def init(self):
|
def init(self):
|
||||||
|
|
8
plugins/google_translation/manifest.ini
Normal file
8
plugins/google_translation/manifest.ini
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
[info]
|
||||||
|
name: Google Translation
|
||||||
|
short_name: google_translation
|
||||||
|
version: 0.1
|
||||||
|
description: Translates (currently only incoming) messages using Google Translate.
|
||||||
|
authors = Mateusz Biliński <mateusz@bilinski.it>
|
||||||
|
homepage = http://blog.bilinski.it
|
||||||
|
|
|
@ -41,12 +41,6 @@ from common import ged
|
||||||
from common import nec
|
from common import nec
|
||||||
|
|
||||||
class GoogleTranslationPlugin(GajimPlugin):
|
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')
|
@log_calls('GoogleTranslationPlugin')
|
||||||
def init(self):
|
def init(self):
|
||||||
|
|
|
@ -34,12 +34,6 @@ from plugins.helpers import log, log_calls
|
||||||
from plugins.gui import GajimPluginConfigDialog
|
from plugins.gui import GajimPluginConfigDialog
|
||||||
|
|
||||||
class LengthNotifierPlugin(GajimPlugin):
|
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')
|
@log_calls('LengthNotifierPlugin')
|
||||||
def init(self):
|
def init(self):
|
||||||
|
|
9
plugins/length_notifier/manifest.ini
Normal file
9
plugins/length_notifier/manifest.ini
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
[info]
|
||||||
|
name: Message Length Notifier
|
||||||
|
short_name: length_notifier
|
||||||
|
version: 0.1
|
||||||
|
description: Highlights message entry field in chat window when given length of message is exceeded.
|
||||||
|
authors = Mateusz Biliński <mateusz@bilinski.it>
|
||||||
|
homepage = http://blog.bilinski.it
|
||||||
|
|
||||||
|
|
11
plugins/new_events_example/manifest.ini
Normal file
11
plugins/new_events_example/manifest.ini
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
[info]
|
||||||
|
name: New Events Example
|
||||||
|
short_name: new_events_example
|
||||||
|
version: 0.1
|
||||||
|
description: Shows how to generate new network events based on existing one using Network Events Controller.
|
||||||
|
authors = Mateusz Biliński <mateusz@bilinski.it>
|
||||||
|
homepage = http://blog.bilinski.it
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -38,12 +38,6 @@ from common import ged
|
||||||
from common import nec
|
from common import nec
|
||||||
|
|
||||||
class NewEventsExamplePlugin(GajimPlugin):
|
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')
|
@log_calls('NewEventsExamplePlugin')
|
||||||
def init(self):
|
def init(self):
|
||||||
|
|
10
plugins/roster_buttons/manifest.ini
Normal file
10
plugins/roster_buttons/manifest.ini
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
[info]
|
||||||
|
name: Roster Buttons
|
||||||
|
short_name: roster_buttons
|
||||||
|
version: 0.1
|
||||||
|
description: Adds quick action buttons to roster window.
|
||||||
|
authors = Mateusz Biliński <mateusz@bilinski.it>
|
||||||
|
homepage = http://blog.bilinski.it
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -34,12 +34,6 @@ from plugins import GajimPlugin
|
||||||
from plugins.helpers import log, log_calls
|
from plugins.helpers import log, log_calls
|
||||||
|
|
||||||
class RosterButtonsPlugin(GajimPlugin):
|
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')
|
@log_calls('RosterButtonsPlugin')
|
||||||
def init(self):
|
def init(self):
|
||||||
|
|
11
plugins/snarl_notifications/manifest.ini
Normal file
11
plugins/snarl_notifications/manifest.ini
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
[info]
|
||||||
|
name: Snarl Notifications
|
||||||
|
short_name: snarl_notifications
|
||||||
|
version: 0.1
|
||||||
|
description: 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 = Mateusz Biliński <mateusz@bilinski.it>
|
||||||
|
homepage = http://blog.bilinski.it
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -38,13 +38,6 @@ from plugins.helpers import log_calls, log
|
||||||
from common import ged
|
from common import ged
|
||||||
|
|
||||||
class SnarlNotificationsPlugin(GajimPlugin):
|
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.
|
|
||||||
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')
|
@log_calls('SnarlNotificationsPlugin')
|
||||||
def init(self):
|
def init(self):
|
||||||
|
|
|
@ -1777,7 +1777,6 @@ ConnectionJingle, ConnectionIBBytestream):
|
||||||
obj.contact.contact_name != obj.contact_nickname:
|
obj.contact.contact_name != obj.contact_nickname:
|
||||||
obj.contact.contact_name = obj.contact_nickname
|
obj.contact.contact_name = obj.contact_nickname
|
||||||
obj.need_redraw = True
|
obj.need_redraw = True
|
||||||
# gajim.interface.roster.draw_contact(jid, account)
|
|
||||||
|
|
||||||
if obj.old_show == obj.new_show and obj.contact.status == \
|
if obj.old_show == obj.new_show and obj.contact.status == \
|
||||||
obj.status and obj.contact.priority == obj.prio: # no change
|
obj.status and obj.contact.priority == obj.prio: # no change
|
||||||
|
@ -1811,7 +1810,6 @@ ConnectionJingle, ConnectionIBBytestream):
|
||||||
obj.contact.resource = resource
|
obj.contact.resource = resource
|
||||||
|
|
||||||
obj.need_add_in_roster = True
|
obj.need_add_in_roster = True
|
||||||
# gajim.interface.roster.add_contact(jid, account)
|
|
||||||
|
|
||||||
if not gajim.jid_is_transport(jid) and len(obj.contact_list) == 1:
|
if not gajim.jid_is_transport(jid) and len(obj.contact_list) == 1:
|
||||||
# It's not an agent
|
# It's not an agent
|
||||||
|
@ -1827,7 +1825,6 @@ ConnectionJingle, ConnectionIBBytestream):
|
||||||
if jid in gajim.newly_added[account]:
|
if jid in gajim.newly_added[account]:
|
||||||
gajim.newly_added[account].remove(jid)
|
gajim.newly_added[account].remove(jid)
|
||||||
obj.need_redraw = True
|
obj.need_redraw = True
|
||||||
# self.roster.draw_contact(jid, account)
|
|
||||||
|
|
||||||
obj.contact.show = obj.show
|
obj.contact.show = obj.show
|
||||||
obj.contact.status = obj.status
|
obj.contact.status = obj.status
|
||||||
|
|
|
@ -632,9 +632,6 @@ class PresenceReceivedEvent(nec.NetworkIncomingEvent, HelperEvent):
|
||||||
[]))
|
[]))
|
||||||
return
|
return
|
||||||
jid_list = gajim.contacts.get_jid_list(self.conn.name)
|
jid_list = gajim.contacts.get_jid_list(self.conn.name)
|
||||||
# if self.jid not in jid_list and self.jid != gajim.get_jid_from_account(
|
|
||||||
# self.conn.name):
|
|
||||||
# return
|
|
||||||
self.timestamp = None
|
self.timestamp = None
|
||||||
self.get_id()
|
self.get_id()
|
||||||
self.is_gc = False # is it a GC presence ?
|
self.is_gc = False # is it a GC presence ?
|
||||||
|
|
|
@ -246,6 +246,9 @@ class JingleRTPContent(JingleContent):
|
||||||
|
|
||||||
codecs = []
|
codecs = []
|
||||||
for codec in content.getTag('description').iterTags('payload-type'):
|
for codec in content.getTag('description').iterTags('payload-type'):
|
||||||
|
if not codec['id'] or not codec['name'] or not codec['clockrate']:
|
||||||
|
# ignore invalid payload-types
|
||||||
|
continue
|
||||||
c = farsight.Codec(int(codec['id']), codec['name'],
|
c = farsight.Codec(int(codec['id']), codec['name'],
|
||||||
self.farsight_media, int(codec['clockrate']))
|
self.farsight_media, int(codec['clockrate']))
|
||||||
if 'channels' in codec:
|
if 'channels' in codec:
|
||||||
|
|
|
@ -847,12 +847,10 @@ class PreferencesWindow:
|
||||||
gajim.config.set('trayicon', 'on_event')
|
gajim.config.set('trayicon', 'on_event')
|
||||||
gajim.interface.systray_enabled = True
|
gajim.interface.systray_enabled = True
|
||||||
gajim.interface.systray.show_icon()
|
gajim.interface.systray.show_icon()
|
||||||
gajim.interface.systray.set_img()
|
|
||||||
else:
|
else:
|
||||||
gajim.config.set('trayicon', 'always')
|
gajim.config.set('trayicon', 'always')
|
||||||
gajim.interface.systray_enabled = True
|
gajim.interface.systray_enabled = True
|
||||||
gajim.interface.systray.show_icon()
|
gajim.interface.systray.show_icon()
|
||||||
gajim.interface.systray.set_img()
|
|
||||||
|
|
||||||
def on_advanced_notifications_button_clicked(self, widget):
|
def on_advanced_notifications_button_clicked(self, widget):
|
||||||
dialogs.AdvancedNotificationsWindow()
|
dialogs.AdvancedNotificationsWindow()
|
||||||
|
|
|
@ -1480,12 +1480,15 @@ class WarningDialog(HigDialog):
|
||||||
HIG compliant warning dialog
|
HIG compliant warning dialog
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, pritext, sectext=''):
|
def __init__(self, pritext, sectext='', transient_for=None):
|
||||||
HigDialog.__init__(self, None, gtk.MESSAGE_WARNING, gtk.BUTTONS_OK,
|
HigDialog.__init__(self, None, gtk.MESSAGE_WARNING, gtk.BUTTONS_OK,
|
||||||
pritext, sectext)
|
pritext, sectext)
|
||||||
self.set_modal(False)
|
self.set_modal(False)
|
||||||
if hasattr(gajim.interface, 'roster') and gajim.interface.roster:
|
if transient_for is None and hasattr(gajim.interface, 'roster') and \
|
||||||
self.set_transient_for(gajim.interface.roster.window)
|
gajim.interface.roster:
|
||||||
|
transient_for = gajim.interface.roster.window
|
||||||
|
if transient_for:
|
||||||
|
self.set_transient_for(transient_for)
|
||||||
self.popup()
|
self.popup()
|
||||||
|
|
||||||
class InformationDialog(HigDialog):
|
class InformationDialog(HigDialog):
|
||||||
|
|
|
@ -1444,8 +1444,6 @@ class GroupchatControl(ChatControlBase):
|
||||||
con = gajim.connections[self.account]
|
con = gajim.connections[self.account]
|
||||||
if gc_c and gc_c.jid:
|
if gc_c and gc_c.jid:
|
||||||
real_jid = gc_c.jid
|
real_jid = gc_c.jid
|
||||||
if gc_c.resource:
|
|
||||||
real_jid += '/' + gc_c.resource
|
|
||||||
else:
|
else:
|
||||||
real_jid = fake_jid
|
real_jid = fake_jid
|
||||||
if fake_jid in con.vcard_shas:
|
if fake_jid in con.vcard_shas:
|
||||||
|
|
|
@ -30,7 +30,7 @@ import pango
|
||||||
import gtk, gobject
|
import gtk, gobject
|
||||||
|
|
||||||
import gtkgui_helpers
|
import gtkgui_helpers
|
||||||
import dialogs
|
from dialogs import WarningDialog, YesNoDialog, ArchiveChooserDialog
|
||||||
from common import gajim
|
from common import gajim
|
||||||
from plugins.helpers import log_calls, log
|
from plugins.helpers import log_calls, log
|
||||||
from common.exceptions import PluginsystemError
|
from common.exceptions import PluginsystemError
|
||||||
|
@ -104,7 +104,7 @@ class PluginsWindow(object):
|
||||||
def _display_installed_plugin_info(self, plugin):
|
def _display_installed_plugin_info(self, plugin):
|
||||||
self.plugin_name_label.set_text(plugin.name)
|
self.plugin_name_label.set_text(plugin.name)
|
||||||
self.plugin_version_label.set_text(plugin.version)
|
self.plugin_version_label.set_text(plugin.version)
|
||||||
self.plugin_authors_label.set_text(", ".join(plugin.authors))
|
self.plugin_authors_label.set_text(plugin.authors)
|
||||||
self.plugin_homepage_linkbutton.set_uri(plugin.homepage)
|
self.plugin_homepage_linkbutton.set_uri(plugin.homepage)
|
||||||
self.plugin_homepage_linkbutton.set_label(plugin.homepage)
|
self.plugin_homepage_linkbutton.set_label(plugin.homepage)
|
||||||
self.plugin_homepage_linkbutton.set_property('sensitive', True)
|
self.plugin_homepage_linkbutton.set_property('sensitive', True)
|
||||||
|
@ -194,17 +194,26 @@ class PluginsWindow(object):
|
||||||
try:
|
try:
|
||||||
gajim.plugin_manager.remove_plugin(plugin)
|
gajim.plugin_manager.remove_plugin(plugin)
|
||||||
except PluginsystemError, e:
|
except PluginsystemError, e:
|
||||||
dialogs.WarningDialog(_('Unable to properly remove the plugin'),
|
WarningDialog(_('Unable to properly remove the plugin'),
|
||||||
str(e))
|
str(e), self.window)
|
||||||
return
|
return
|
||||||
model.remove(iter)
|
model.remove(iter)
|
||||||
|
|
||||||
@log_calls('PluginsWindow')
|
@log_calls('PluginsWindow')
|
||||||
def on_install_plugin_button_clicked(self, widget):
|
def on_install_plugin_button_clicked(self, widget):
|
||||||
|
def show_warn_dialog():
|
||||||
|
text = _('Archive is malformed')
|
||||||
|
dialog = WarningDialog(text, '', transient_for=self.window)
|
||||||
|
dialog.set_modal(False)
|
||||||
|
dialog.popup()
|
||||||
|
|
||||||
def _on_plugin_exists(zip_filename):
|
def _on_plugin_exists(zip_filename):
|
||||||
def on_yes(is_checked):
|
def on_yes(is_checked):
|
||||||
plugin = gajim.plugin_manager.install_from_zip(zip_filename,
|
plugin = gajim.plugin_manager.install_from_zip(zip_filename,
|
||||||
True)
|
True)
|
||||||
|
if not plugin:
|
||||||
|
show_warn_dialog()
|
||||||
|
return
|
||||||
model = self.installed_plugins_model
|
model = self.installed_plugins_model
|
||||||
|
|
||||||
for row in xrange(len(model)):
|
for row in xrange(len(model)):
|
||||||
|
@ -216,8 +225,8 @@ class PluginsWindow(object):
|
||||||
sel = self.installed_plugins_treeview.get_selection()
|
sel = self.installed_plugins_treeview.get_selection()
|
||||||
sel.select_iter(iter_)
|
sel.select_iter(iter_)
|
||||||
|
|
||||||
dialogs.YesNoDialog(_('Plugin already exists'),
|
YesNoDialog(_('Plugin already exists'), sectext=_('Overwrite?'),
|
||||||
sectext=_('Overwrite?'), on_response_yes=on_yes)
|
on_response_yes=on_yes)
|
||||||
|
|
||||||
def _try_install(zip_filename):
|
def _try_install(zip_filename):
|
||||||
try:
|
try:
|
||||||
|
@ -228,15 +237,17 @@ class PluginsWindow(object):
|
||||||
_on_plugin_exists(zip_filename)
|
_on_plugin_exists(zip_filename)
|
||||||
return
|
return
|
||||||
|
|
||||||
dialogs.WarningDialog(error_text, '"%s"' % zip_filename)
|
WarningDialog(error_text, '"%s"' % zip_filename, self.window)
|
||||||
|
return
|
||||||
|
if not plugin:
|
||||||
|
show_warn_dialog()
|
||||||
return
|
return
|
||||||
|
|
||||||
model = self.installed_plugins_model
|
model = self.installed_plugins_model
|
||||||
iter_ = model.append([plugin, plugin.name, False])
|
iter_ = model.append([plugin, plugin.name, False])
|
||||||
sel = self.installed_plugins_treeview.get_selection()
|
sel = self.installed_plugins_treeview.get_selection()
|
||||||
sel.select_iter(iter_)
|
sel.select_iter(iter_)
|
||||||
|
|
||||||
self.dialog = dialogs.ArchiveChooserDialog(on_response_ok=_try_install)
|
self.dialog = ArchiveChooserDialog(on_response_ok=_try_install)
|
||||||
|
|
||||||
|
|
||||||
class GajimPluginConfigDialog(gtk.Dialog):
|
class GajimPluginConfigDialog(gtk.Dialog):
|
||||||
|
|
|
@ -31,6 +31,7 @@ import sys
|
||||||
import fnmatch
|
import fnmatch
|
||||||
import zipfile
|
import zipfile
|
||||||
from shutil import rmtree
|
from shutil import rmtree
|
||||||
|
import ConfigParser
|
||||||
|
|
||||||
from common import gajim
|
from common import gajim
|
||||||
from common import nec
|
from common import nec
|
||||||
|
@ -46,8 +47,9 @@ class PluginManager(object):
|
||||||
Currently:
|
Currently:
|
||||||
- scans for plugins
|
- scans for plugins
|
||||||
- activates them
|
- activates them
|
||||||
- handles GUI extension points, when called by GUI objects after plugin
|
- handles GUI extension points, when called by GUI objects after
|
||||||
is activated (by dispatching info about call to handlers in plugins)
|
plugin is activated (by dispatching info about call to handlers
|
||||||
|
in plugins)
|
||||||
|
|
||||||
:todo: add more info about how GUI extension points work
|
:todo: add more info about how GUI extension points work
|
||||||
:todo: add list of available GUI extension points
|
:todo: add list of available GUI extension points
|
||||||
|
@ -58,10 +60,11 @@ class PluginManager(object):
|
||||||
deactivation handler) [DONE?]
|
deactivation handler) [DONE?]
|
||||||
:todo: when plug-in is deactivated all GUI extension points are removed
|
:todo: when plug-in is deactivated all GUI extension points are removed
|
||||||
from `PluginManager.gui_extension_points_handlers`. But when
|
from `PluginManager.gui_extension_points_handlers`. But when
|
||||||
object that invoked GUI extension point is abandoned by Gajim, eg.
|
object that invoked GUI extension point is abandoned by Gajim,
|
||||||
closed ChatControl object, the reference to called GUI extension
|
eg. closed ChatControl object, the reference to called GUI
|
||||||
points is still in `PluginManager.gui_extension_points`. These
|
extension points is still in `PluginManager.gui_extension_points`
|
||||||
should be removed, so that object can be destroyed by Python.
|
These should be removed, so that object can be destroyed by
|
||||||
|
Python.
|
||||||
Possible solution: add call to clean up method in classes
|
Possible solution: add call to clean up method in classes
|
||||||
'destructors' (classes that register GUI extension points)
|
'destructors' (classes that register GUI extension points)
|
||||||
'''
|
'''
|
||||||
|
@ -96,16 +99,11 @@ class PluginManager(object):
|
||||||
'''
|
'''
|
||||||
Registered handlers of GUI extension points.
|
Registered handlers of GUI extension points.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
for path in gajim.PLUGINS_DIRS:
|
for path in gajim.PLUGINS_DIRS:
|
||||||
self.add_plugins(PluginManager.scan_dir_for_plugins(path))
|
pc = PluginManager.scan_dir_for_plugins(path)
|
||||||
|
self.add_plugins(pc)
|
||||||
#log.debug('plugins: %s'%(self.plugins))
|
|
||||||
|
|
||||||
self._activate_all_plugins_from_global_config()
|
self._activate_all_plugins_from_global_config()
|
||||||
|
|
||||||
#log.debug('active: %s'%(self.active_plugins))
|
|
||||||
|
|
||||||
@log_calls('PluginManager')
|
@log_calls('PluginManager')
|
||||||
def _plugin_has_entry_in_global_config(self, plugin):
|
def _plugin_has_entry_in_global_config(self, plugin):
|
||||||
if gajim.config.get_per('plugins', plugin.short_name) is None:
|
if gajim.config.get_per('plugins', plugin.short_name) is None:
|
||||||
|
@ -117,6 +115,9 @@ class PluginManager(object):
|
||||||
def _create_plugin_entry_in_global_config(self, plugin):
|
def _create_plugin_entry_in_global_config(self, plugin):
|
||||||
gajim.config.add_per('plugins', plugin.short_name)
|
gajim.config.add_per('plugins', plugin.short_name)
|
||||||
|
|
||||||
|
def _remove_plugin_entry_in_global_config(self, plugin):
|
||||||
|
gajim.config.del_per('plugins', plugin.short_name)
|
||||||
|
|
||||||
@log_calls('PluginManager')
|
@log_calls('PluginManager')
|
||||||
def add_plugin(self, plugin_class):
|
def add_plugin(self, plugin_class):
|
||||||
'''
|
'''
|
||||||
|
@ -132,8 +133,9 @@ class PluginManager(object):
|
||||||
self.plugins.append(plugin)
|
self.plugins.append(plugin)
|
||||||
plugin.active = False
|
plugin.active = False
|
||||||
else:
|
else:
|
||||||
log.info('Not loading plugin %s v%s from module %s (identified by short name: %s). Plugin already loaded.'%(
|
log.info('Not loading plugin %s v%s from module %s (identified by'
|
||||||
plugin.name, plugin.version, plugin.__module__, plugin.short_name))
|
' short name: %s). Plugin already loaded.' % (plugin.name,
|
||||||
|
plugin.version, plugin.__module__, plugin.short_name))
|
||||||
|
|
||||||
@log_calls('PluginManager')
|
@log_calls('PluginManager')
|
||||||
def add_plugins(self, plugin_classes):
|
def add_plugins(self, plugin_classes):
|
||||||
|
@ -144,14 +146,14 @@ class PluginManager(object):
|
||||||
def gui_extension_point(self, gui_extpoint_name, *args):
|
def gui_extension_point(self, gui_extpoint_name, *args):
|
||||||
'''
|
'''
|
||||||
Invokes all handlers (from plugins) for particular GUI extension point
|
Invokes all handlers (from plugins) for particular GUI extension point
|
||||||
and adds it to collection for further processing (eg. by plugins not active
|
and adds it to collection for further processing (eg. by plugins not
|
||||||
yet).
|
active yet).
|
||||||
|
|
||||||
:param gui_extpoint_name: name of GUI extension point.
|
:param gui_extpoint_name: name of GUI extension point.
|
||||||
:type gui_extpoint_name: unicode
|
:type gui_extpoint_name: unicode
|
||||||
:param args: parameters to be passed to extension point handlers
|
:param args: parameters to be passed to extension point handlers
|
||||||
(typically and object that invokes `gui_extension_point`; however,
|
(typically and object that invokes `gui_extension_point`;
|
||||||
this can be practically anything)
|
however, this can be practically anything)
|
||||||
:type args: tuple
|
:type args: tuple
|
||||||
|
|
||||||
:todo: GUI extension points must be documented well - names with
|
:todo: GUI extension points must be documented well - names with
|
||||||
|
@ -162,12 +164,13 @@ class PluginManager(object):
|
||||||
:bug: what if only some handlers are successfully connected? we should
|
:bug: what if only some handlers are successfully connected? we should
|
||||||
revert all those connections that where successfully made. Maybe
|
revert all those connections that where successfully made. Maybe
|
||||||
call 'self._deactivate_plugin()' or sth similar.
|
call 'self._deactivate_plugin()' or sth similar.
|
||||||
Looking closer - we only rewrite tuples here. Real check should be
|
Looking closer - we only rewrite tuples here. Real check should
|
||||||
made in method that invokes gui_extpoints handlers.
|
be made in method that invokes gui_extpoints handlers.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
self._add_gui_extension_point_call_to_list(gui_extpoint_name, *args)
|
self._add_gui_extension_point_call_to_list(gui_extpoint_name, *args)
|
||||||
self._execute_all_handlers_of_gui_extension_point(gui_extpoint_name, *args)
|
self._execute_all_handlers_of_gui_extension_point(gui_extpoint_name,
|
||||||
|
*args)
|
||||||
|
|
||||||
@log_calls('PluginManager')
|
@log_calls('PluginManager')
|
||||||
def remove_gui_extension_point(self, gui_extpoint_name, *args):
|
def remove_gui_extension_point(self, gui_extpoint_name, *args):
|
||||||
|
@ -191,11 +194,11 @@ class PluginManager(object):
|
||||||
extension points. The same arguments and the same name mean
|
extension points. The same arguments and the same name mean
|
||||||
the same extension point.
|
the same extension point.
|
||||||
:todo: instead of using argument to identify which extpoint should be
|
:todo: instead of using argument to identify which extpoint should be
|
||||||
removed, maybe add additional 'id' argument - this would work similar
|
removed, maybe add additional 'id' argument - this would work
|
||||||
hash in Python objects. 'id' would be calculated based on arguments
|
similar hash in Python objects. 'id' would be calculated based
|
||||||
passed or on anything else (even could be constant). This would give
|
on arguments passed or on anything else (even could be constant)
|
||||||
core developers (that add new extpoints) more freedom, but is this
|
This would give core developers (that add new extpoints) more
|
||||||
necessary?
|
freedom, but is this necessary?
|
||||||
|
|
||||||
:param gui_extpoint_name: name of GUI extension point.
|
:param gui_extpoint_name: name of GUI extension point.
|
||||||
:type gui_extpoint_name: unicode
|
:type gui_extpoint_name: unicode
|
||||||
|
@ -206,10 +209,8 @@ class PluginManager(object):
|
||||||
'''
|
'''
|
||||||
|
|
||||||
if gui_extpoint_name in self.gui_extension_points:
|
if gui_extpoint_name in self.gui_extension_points:
|
||||||
#log.debug('Removing GUI extpoint\n name: %s\n args: %s'%(gui_extpoint_name, args))
|
|
||||||
self.gui_extension_points[gui_extpoint_name].remove(args)
|
self.gui_extension_points[gui_extpoint_name].remove(args)
|
||||||
|
|
||||||
|
|
||||||
@log_calls('PluginManager')
|
@log_calls('PluginManager')
|
||||||
def _add_gui_extension_point_call_to_list(self, gui_extpoint_name, *args):
|
def _add_gui_extension_point_call_to_list(self, gui_extpoint_name, *args):
|
||||||
'''
|
'''
|
||||||
|
@ -226,35 +227,36 @@ class PluginManager(object):
|
||||||
:type gui_extpoint_name: str
|
:type gui_extpoint_name: str
|
||||||
|
|
||||||
:param args: parameters to be passed to extension point handlers
|
:param args: parameters to be passed to extension point handlers
|
||||||
(typically and object that invokes `gui_extension_point`; however,
|
(typically and object that invokes `gui_extension_point`;
|
||||||
this can be practically anything)
|
however, this can be practically anything)
|
||||||
:type args: tuple
|
:type args: tuple
|
||||||
|
|
||||||
'''
|
'''
|
||||||
if ((gui_extpoint_name not in self.gui_extension_points)
|
if ((gui_extpoint_name not in self.gui_extension_points)
|
||||||
or (args not in self.gui_extension_points[gui_extpoint_name])):
|
or (args not in self.gui_extension_points[gui_extpoint_name])):
|
||||||
self.gui_extension_points.setdefault(gui_extpoint_name, []).append(args)
|
self.gui_extension_points.setdefault(gui_extpoint_name,[]).append(
|
||||||
|
args)
|
||||||
|
|
||||||
@log_calls('PluginManager')
|
@log_calls('PluginManager')
|
||||||
def _execute_all_handlers_of_gui_extension_point(self, gui_extpoint_name, *args):
|
def _execute_all_handlers_of_gui_extension_point(self, gui_extpoint_name,
|
||||||
|
*args):
|
||||||
if gui_extpoint_name in self.gui_extension_points_handlers:
|
if gui_extpoint_name in self.gui_extension_points_handlers:
|
||||||
for handlers in self.gui_extension_points_handlers[gui_extpoint_name]:
|
for handlers in self.gui_extension_points_handlers[
|
||||||
|
gui_extpoint_name]:
|
||||||
handlers[0](*args)
|
handlers[0](*args)
|
||||||
|
|
||||||
def _register_events_handlers_in_ged(self, plugin):
|
def _register_events_handlers_in_ged(self, plugin):
|
||||||
for event_name, handler in plugin.events_handlers.iteritems():
|
for event_name, handler in plugin.events_handlers.iteritems():
|
||||||
priority = handler[0]
|
priority = handler[0]
|
||||||
handler_function = handler[1]
|
handler_function = handler[1]
|
||||||
gajim.ged.register_event_handler(event_name,
|
gajim.ged.register_event_handler(event_name, priority,
|
||||||
priority,
|
|
||||||
handler_function)
|
handler_function)
|
||||||
|
|
||||||
def _remove_events_handler_from_ged(self, plugin):
|
def _remove_events_handler_from_ged(self, plugin):
|
||||||
for event_name, handler in plugin.events_handlers.iteritems():
|
for event_name, handler in plugin.events_handlers.iteritems():
|
||||||
priority = handler[0]
|
priority = handler[0]
|
||||||
handler_function = handler[1]
|
handler_function = handler[1]
|
||||||
gajim.ged.remove_event_handler(event_name,
|
gajim.ged.remove_event_handler(event_name, priority,
|
||||||
priority,
|
|
||||||
handler_function)
|
handler_function)
|
||||||
|
|
||||||
def _register_network_events_in_nec(self, plugin):
|
def _register_network_events_in_nec(self, plugin):
|
||||||
|
@ -306,7 +308,8 @@ class PluginManager(object):
|
||||||
# handlers list
|
# handlers list
|
||||||
for gui_extpoint_name, gui_extpoint_handlers in \
|
for gui_extpoint_name, gui_extpoint_handlers in \
|
||||||
plugin.gui_extension_points.iteritems():
|
plugin.gui_extension_points.iteritems():
|
||||||
self.gui_extension_points_handlers[gui_extpoint_name].remove(gui_extpoint_handlers)
|
self.gui_extension_points_handlers[gui_extpoint_name].remove(
|
||||||
|
gui_extpoint_handlers)
|
||||||
|
|
||||||
# detaching plug-in from handler GUI extension points (calling
|
# detaching plug-in from handler GUI extension points (calling
|
||||||
# cleaning up method that must be provided by plug-in developer
|
# cleaning up method that must be provided by plug-in developer
|
||||||
|
@ -314,7 +317,8 @@ class PluginManager(object):
|
||||||
for gui_extpoint_name, gui_extpoint_handlers in \
|
for gui_extpoint_name, gui_extpoint_handlers in \
|
||||||
plugin.gui_extension_points.iteritems():
|
plugin.gui_extension_points.iteritems():
|
||||||
if gui_extpoint_name in self.gui_extension_points:
|
if gui_extpoint_name in self.gui_extension_points:
|
||||||
for gui_extension_point_args in self.gui_extension_points[gui_extpoint_name]:
|
for gui_extension_point_args in self.gui_extension_points[
|
||||||
|
gui_extpoint_name]:
|
||||||
handler = gui_extpoint_handlers[1]
|
handler = gui_extpoint_handlers[1]
|
||||||
if handler:
|
if handler:
|
||||||
handler(*gui_extension_point_args)
|
handler(*gui_extension_point_args)
|
||||||
|
@ -336,15 +340,16 @@ class PluginManager(object):
|
||||||
def _add_gui_extension_points_handlers_from_plugin(self, plugin):
|
def _add_gui_extension_points_handlers_from_plugin(self, plugin):
|
||||||
for gui_extpoint_name, gui_extpoint_handlers in \
|
for gui_extpoint_name, gui_extpoint_handlers in \
|
||||||
plugin.gui_extension_points.iteritems():
|
plugin.gui_extension_points.iteritems():
|
||||||
self.gui_extension_points_handlers.setdefault(gui_extpoint_name, []).append(
|
self.gui_extension_points_handlers.setdefault(gui_extpoint_name,
|
||||||
gui_extpoint_handlers)
|
[]).append(gui_extpoint_handlers)
|
||||||
|
|
||||||
@log_calls('PluginManager')
|
@log_calls('PluginManager')
|
||||||
def _handle_all_gui_extension_points_with_plugin(self, plugin):
|
def _handle_all_gui_extension_points_with_plugin(self, plugin):
|
||||||
for gui_extpoint_name, gui_extpoint_handlers in \
|
for gui_extpoint_name, gui_extpoint_handlers in \
|
||||||
plugin.gui_extension_points.iteritems():
|
plugin.gui_extension_points.iteritems():
|
||||||
if gui_extpoint_name in self.gui_extension_points:
|
if gui_extpoint_name in self.gui_extension_points:
|
||||||
for gui_extension_point_args in self.gui_extension_points[gui_extpoint_name]:
|
for gui_extension_point_args in self.gui_extension_points[
|
||||||
|
gui_extpoint_name]:
|
||||||
handler = gui_extpoint_handlers[0]
|
handler = gui_extpoint_handlers[0]
|
||||||
if handler:
|
if handler:
|
||||||
handler(*gui_extension_point_args)
|
handler(*gui_extension_point_args)
|
||||||
|
@ -356,7 +361,6 @@ class PluginManager(object):
|
||||||
|
|
||||||
Activated plugins are appended to `active_plugins` list.
|
Activated plugins are appended to `active_plugins` list.
|
||||||
'''
|
'''
|
||||||
#self.active_plugins = []
|
|
||||||
for plugin in self.plugins:
|
for plugin in self.plugins:
|
||||||
self.activate_plugin(plugin)
|
self.activate_plugin(plugin)
|
||||||
|
|
||||||
|
@ -390,71 +394,78 @@ class PluginManager(object):
|
||||||
:todo: add scanning zipped modules
|
:todo: add scanning zipped modules
|
||||||
'''
|
'''
|
||||||
plugins_found = []
|
plugins_found = []
|
||||||
if os.path.isdir(path):
|
conf = ConfigParser.ConfigParser()
|
||||||
|
fields = ('name', 'short_name', 'version', 'description', 'authors',
|
||||||
|
'homepage')
|
||||||
|
if not os.path.isdir(path):
|
||||||
|
return plugins_found
|
||||||
|
|
||||||
dir_list = os.listdir(path)
|
dir_list = os.listdir(path)
|
||||||
#log.debug(dir_list)
|
|
||||||
|
|
||||||
sys.path.insert(0, path)
|
sys.path.insert(0, path)
|
||||||
#log.debug(sys.path)
|
|
||||||
|
|
||||||
for elem_name in dir_list:
|
for elem_name in dir_list:
|
||||||
#log.debug('- "%s"'%(elem_name))
|
|
||||||
file_path = os.path.join(path, elem_name)
|
file_path = os.path.join(path, elem_name)
|
||||||
#log.debug(' "%s"'%(file_path))
|
|
||||||
|
|
||||||
module = None
|
module = None
|
||||||
|
|
||||||
if os.path.isfile(file_path) and fnmatch.fnmatch(file_path, '*.py'):
|
if os.path.isfile(file_path) and fnmatch.fnmatch(file_path, '*.py'):
|
||||||
module_name = os.path.splitext(elem_name)[0]
|
module_name = os.path.splitext(elem_name)[0]
|
||||||
#log.debug('Possible module detected.')
|
|
||||||
try:
|
try:
|
||||||
module = __import__(module_name)
|
module = __import__(module_name)
|
||||||
#log.debug('Module imported.')
|
|
||||||
except ValueError, value_error:
|
except ValueError, value_error:
|
||||||
pass
|
pass
|
||||||
#log.debug('Module not imported successfully. ValueError: %s'%(value_error))
|
|
||||||
except ImportError, import_error:
|
except ImportError, import_error:
|
||||||
pass
|
pass
|
||||||
#log.debug('Module not imported successfully. ImportError: %s'%(import_error))
|
|
||||||
|
|
||||||
elif os.path.isdir(file_path) and scan_dirs:
|
elif os.path.isdir(file_path) and scan_dirs:
|
||||||
module_name = elem_name
|
module_name = elem_name
|
||||||
file_path += os.path.sep
|
file_path += os.path.sep
|
||||||
#log.debug('Possible package detected.')
|
|
||||||
try:
|
try:
|
||||||
module = __import__(module_name)
|
module = __import__(module_name)
|
||||||
#log.debug('Package imported.')
|
|
||||||
except ValueError, value_error:
|
except ValueError, value_error:
|
||||||
pass
|
pass
|
||||||
#log.debug('Package not imported successfully. ValueError: %s'%(value_error))
|
|
||||||
except ImportError, import_error:
|
except ImportError, import_error:
|
||||||
pass
|
pass
|
||||||
#log.debug('Package not imported successfully. ImportError: %s'%(import_error))
|
|
||||||
|
|
||||||
|
|
||||||
if module:
|
if module is None:
|
||||||
|
continue
|
||||||
|
|
||||||
|
manifest_path = os.path.join(os.path.dirname(file_path),
|
||||||
|
'manifest.ini')
|
||||||
|
if scan_dirs and (not os.path.isfile(manifest_path)):
|
||||||
|
continue
|
||||||
|
|
||||||
log.debug('Attributes processing started')
|
log.debug('Attributes processing started')
|
||||||
for module_attr_name in [attr_name for attr_name in dir(module)
|
for module_attr_name in [attr_name for attr_name in dir(module)
|
||||||
if not (attr_name.startswith('__') or
|
if not (attr_name.startswith('__') or attr_name.endswith('__'))]:
|
||||||
attr_name.endswith('__'))]:
|
|
||||||
module_attr = getattr(module, module_attr_name)
|
module_attr = getattr(module, module_attr_name)
|
||||||
log.debug('%s : %s'%(module_attr_name, module_attr))
|
log.debug('%s : %s' % (module_attr_name, module_attr))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if issubclass(module_attr, GajimPlugin) and \
|
if not issubclass(module_attr, GajimPlugin) or \
|
||||||
not module_attr is GajimPlugin:
|
module_attr is GajimPlugin:
|
||||||
|
continue
|
||||||
log.debug('is subclass of GajimPlugin')
|
log.debug('is subclass of GajimPlugin')
|
||||||
#log.debug('file_path: %s\nabspath: %s\ndirname: %s'%(file_path, os.path.abspath(file_path), os.path.dirname(os.path.abspath(file_path))))
|
module_attr.__path__ = os.path.abspath(
|
||||||
#log.debug('file_path: %s\ndirname: %s\nabspath: %s'%(file_path, os.path.dirname(file_path), os.path.abspath(os.path.dirname(file_path))))
|
os.path.dirname(file_path))
|
||||||
module_attr.__path__ = os.path.abspath(os.path.dirname(file_path))
|
|
||||||
|
# read metadata from manifest.ini
|
||||||
|
conf.readfp(open(manifest_path, 'r'))
|
||||||
|
for option in fields:
|
||||||
|
if conf.get('info', option) is '':
|
||||||
|
raise ConfigParser.NoOptionError, 'field empty'
|
||||||
|
setattr(module_attr, option, conf.get('info', option))
|
||||||
|
conf.remove_section('info')
|
||||||
|
|
||||||
plugins_found.append(module_attr)
|
plugins_found.append(module_attr)
|
||||||
|
|
||||||
except TypeError, type_error:
|
except TypeError, type_error:
|
||||||
pass
|
pass
|
||||||
#log.debug('module_attr: %s, error : %s'%(
|
except ConfigParser.NoOptionError, type_error:
|
||||||
#module_name+'.'+module_attr_name,
|
# all fields are required
|
||||||
#type_error))
|
pass
|
||||||
|
|
||||||
#log.debug(module)
|
|
||||||
|
|
||||||
return plugins_found
|
return plugins_found
|
||||||
|
|
||||||
|
@ -475,6 +486,7 @@ class PluginManager(object):
|
||||||
raise PluginsystemError(_('Archive corrupted'))
|
raise PluginsystemError(_('Archive corrupted'))
|
||||||
|
|
||||||
dirs = []
|
dirs = []
|
||||||
|
manifest = None
|
||||||
for filename in zip_file.namelist():
|
for filename in zip_file.namelist():
|
||||||
if filename.startswith('.') or filename.startswith('/') or \
|
if filename.startswith('.') or filename.startswith('/') or \
|
||||||
('/' not in filename):
|
('/' not in filename):
|
||||||
|
@ -482,16 +494,18 @@ class PluginManager(object):
|
||||||
raise PluginsystemError(_('Archive is malformed'))
|
raise PluginsystemError(_('Archive is malformed'))
|
||||||
if filename.endswith('/') and filename.find('/', 0, -1) < 0:
|
if filename.endswith('/') and filename.find('/', 0, -1) < 0:
|
||||||
dirs.append(filename)
|
dirs.append(filename)
|
||||||
|
if 'manifest.ini' in filename.split('/')[1]:
|
||||||
|
manifest = True
|
||||||
|
if not manifest:
|
||||||
|
return
|
||||||
if len(dirs) > 1:
|
if len(dirs) > 1:
|
||||||
# several directories in the root of the archive
|
|
||||||
raise PluginsystemError(_('Archive is malformed'))
|
raise PluginsystemError(_('Archive is malformed'))
|
||||||
|
|
||||||
base_dir, user_dir = gajim.PLUGINS_DIRS
|
base_dir, user_dir = gajim.PLUGINS_DIRS
|
||||||
plugin_dir = os.path.join(user_dir, dirs[0])
|
plugin_dir = os.path.join(user_dir, dirs[0])
|
||||||
|
|
||||||
if os.path.isdir(plugin_dir):
|
if os.path.isdir(plugin_dir):
|
||||||
# Plugin already exists
|
# Plugin dir already exists
|
||||||
if not owerwrite:
|
if not owerwrite:
|
||||||
raise PluginsystemError(_('Plugin already exists'))
|
raise PluginsystemError(_('Plugin already exists'))
|
||||||
self.remove_plugin(self.get_plugin_by_path(plugin_dir))
|
self.remove_plugin(self.get_plugin_by_path(plugin_dir))
|
||||||
|
@ -499,7 +513,10 @@ class PluginManager(object):
|
||||||
zip_file.extractall(user_dir)
|
zip_file.extractall(user_dir)
|
||||||
zip_file.close()
|
zip_file.close()
|
||||||
path = os.path.join(user_dir, dirs[0])
|
path = os.path.join(user_dir, dirs[0])
|
||||||
self.add_plugin(self.scan_dir_for_plugins(plugin_dir, False)[0])
|
plugins = self.scan_dir_for_plugins(plugin_dir, False)
|
||||||
|
if not plugins:
|
||||||
|
return
|
||||||
|
self.add_plugin(plugins[0])
|
||||||
plugin = self.plugins[-1]
|
plugin = self.plugins[-1]
|
||||||
return plugin
|
return plugin
|
||||||
|
|
||||||
|
@ -513,12 +530,15 @@ class PluginManager(object):
|
||||||
os.unlink(path)
|
os.unlink(path)
|
||||||
return
|
return
|
||||||
# access is denied or other
|
# access is denied or other
|
||||||
raise PluginsystemError(error[1])
|
raise PluginsystemError(error[1][1])
|
||||||
|
|
||||||
|
if plugin:
|
||||||
if plugin.active:
|
if plugin.active:
|
||||||
self.deactivate_plugin(plugin)
|
self.deactivate_plugin(plugin)
|
||||||
rmtree(plugin.__path__, False, on_error)
|
rmtree(plugin.__path__, False, on_error)
|
||||||
self.plugins.remove(plugin)
|
self.plugins.remove(plugin)
|
||||||
|
if self._plugin_has_entry_in_global_config(plugin):
|
||||||
|
self._remove_plugin_entry_in_global_config(plugin)
|
||||||
|
|
||||||
def get_plugin_by_path(self, plugin_dir):
|
def get_plugin_by_path(self, plugin_dir):
|
||||||
for plugin in self.plugins:
|
for plugin in self.plugins:
|
||||||
|
|
|
@ -97,7 +97,6 @@ class StatusIcon:
|
||||||
self.on_status_icon_size_changed)
|
self.on_status_icon_size_changed)
|
||||||
|
|
||||||
self.set_img()
|
self.set_img()
|
||||||
self.status_icon.set_visible(True)
|
|
||||||
self.subscribe_events()
|
self.subscribe_events()
|
||||||
|
|
||||||
def on_status_icon_right_clicked(self, widget, event_button, event_time):
|
def on_status_icon_right_clicked(self, widget, event_button, event_time):
|
||||||
|
@ -131,9 +130,14 @@ class StatusIcon:
|
||||||
"""
|
"""
|
||||||
if not gajim.interface.systray_enabled:
|
if not gajim.interface.systray_enabled:
|
||||||
return
|
return
|
||||||
|
if gajim.config.get('trayicon') == 'always':
|
||||||
|
self.status_icon.set_visible(True)
|
||||||
if gajim.events.get_nb_systray_events():
|
if gajim.events.get_nb_systray_events():
|
||||||
|
self.status_icon.set_visible(True)
|
||||||
self.status_icon.set_blinking(True)
|
self.status_icon.set_blinking(True)
|
||||||
else:
|
else:
|
||||||
|
if gajim.config.get('trayicon') == 'on_event':
|
||||||
|
self.status_icon.set_visible(False)
|
||||||
self.status_icon.set_blinking(False)
|
self.status_icon.set_blinking(False)
|
||||||
|
|
||||||
image = gajim.interface.jabber_state_images[self.statusicon_size][
|
image = gajim.interface.jabber_state_images[self.statusicon_size][
|
||||||
|
|
Loading…
Add table
Reference in a new issue