Plugin can be a package (directory) now. Added example plugin that modifies roster window (with glade file).

Added activate and deactivate methods to Plugin (used in forementioned RosterButtonsPlugin).
This commit is contained in:
Mateusz Biliński 2008-06-14 18:20:24 +00:00
parent 03b982ad50
commit b6593b9493
5 changed files with 212 additions and 12 deletions

View File

@ -0,0 +1,4 @@
__all__ = ['RosterButtonsPlugin']
from plugin import RosterButtonsPlugin

View File

@ -0,0 +1,88 @@
# -*- coding: utf-8 -*-
## This file is part of Gajim.
##
## Gajim is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published
## by the Free Software Foundation; version 3 only.
##
## Gajim is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with Gajim. If not, see <http://www.gnu.org/licenses/>.
##
'''
Roster buttons plug-in.
:author: Mateusz Biliński <mateusz@bilinski.it>
:since: 06/10/2008
:copyright: Copyright (2008) Mateusz Biliński <mateusz@bilinski.it>
:license: GPL
'''
import sys
import gtk
from common import i18n
from common import gajim
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):
#super(RosterButtonsPlugin, self).__init__()
@log_calls('RosterButtonsPlugin')
def activate(self):
#log.debug('self.__path__==%s'%(self.__path__))
self.GLADE_FILE_PATH = self.local_file_path('roster_buttons.glade')
self.xml = gtk.glade.XML(self.GLADE_FILE_PATH, root='roster_buttons_buttonbox', domain=i18n.APP)
self.buttonbox = self.xml.get_widget('roster_buttons_buttonbox')
self.roster_vbox = gajim.interface.roster.xml.get_widget('roster_vbox2')
self.roster_vbox.pack_start(self.buttonbox, expand=False)
self.roster_vbox.reorder_child(self.buttonbox, 0)
self.show_offline_contacts_menuitem = gajim.interface.roster.xml.get_widget('show_offline_contacts_menuitem')
self.xml.signal_autoconnect(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

View File

@ -0,0 +1,64 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
<!--Generated with glade3 3.4.5 on Sat Jun 14 19:55:24 2008 -->
<glade-interface>
<widget class="GtkWindow" id="window1">
<child>
<widget class="GtkHButtonBox" id="roster_buttons_buttonbox">
<property name="visible">True</property>
<property name="homogeneous">True</property>
<property name="layout_style">GTK_BUTTONBOX_SPREAD</property>
<child>
<widget class="GtkButton" id="roster_button_1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="tooltip_text">Show/Hide Offline Contacts</property>
<property name="label" translatable="yes">1</property>
<property name="response_id">0</property>
<signal name="clicked" handler="on_roster_button_1_clicked"/>
</widget>
</child>
<child>
<widget class="GtkButton" id="roster_button_2">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="label" translatable="yes">2</property>
<property name="response_id">0</property>
<signal name="clicked" handler="on_roster_button_2_clicked"/>
</widget>
<packing>
<property name="position">1</property>
</packing>
</child>
<child>
<widget class="GtkButton" id="roster_button_3">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="label" translatable="yes">3</property>
<property name="response_id">0</property>
<signal name="clicked" handler="on_roster_button_3_clicked"/>
</widget>
<packing>
<property name="position">2</property>
</packing>
</child>
<child>
<widget class="GtkButton" id="roster_button_4">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="label" translatable="yes">4</property>
<property name="response_id">0</property>
<signal name="clicked" handler="on_roster_button_4_clicked"/>
</widget>
<packing>
<property name="position">3</property>
</packing>
</child>
</widget>
</child>
</widget>
</glade-interface>

View File

@ -24,6 +24,8 @@ Base class for implementing plugin.
:license: GPL
'''
import os
from plugins.helpers import log_calls
class GajimPlugin(object):
@ -117,6 +119,17 @@ class GajimPlugin(object):
def __del__(self):
self._save_config()
@log_calls('GajimPlugin')
def local_file_path(self, file_name):
return os.path.join(self.__path__, file_name)
@log_calls('GajimPlugin')
def activate(self):
pass
@log_calls('GajimPlugin')
def deactivate(self):
pass
class Config(dict):
pass

View File

@ -171,6 +171,7 @@ class PluginManager(object):
if success:
self.active_plugins.append(plugin_object)
plugin_object.activate()
plugin_class._instance = plugin_object
plugin_class._active = True
@ -193,6 +194,7 @@ class PluginManager(object):
self.gui_extension_points_handlers[gui_extpoint_name].remove(gui_extpoint_handlers)
# removing plug-in from active plug-ins list
plugin_object.deactivate()
self.active_plugins.remove(plugin_object)
plugin_object.__class__._active = False
plugin_object.__class__._instance = None
@ -249,28 +251,57 @@ class PluginManager(object):
plugins_found = []
if os.path.isdir(path):
dir_list = os.listdir(path)
log.debug(dir_list)
#log.debug(dir_list)
sys.path.insert(0, path)
log.debug(sys.path)
#log.debug(sys.path)
for file_name in fnmatch.filter(dir_list, '*.py'):
log.debug('- "%s"'%(file_name))
file_path = os.path.join(path, file_name)
for elem_name in dir_list:
log.debug('- "%s"'%(elem_name))
file_path = os.path.join(path, elem_name)
log.debug(' "%s"'%(file_path))
if os.path.isfile(file_path):
module_name = os.path.splitext(file_name)[0]
module = __import__(module_name)
for module_attr_name in [f_name for f_name in dir(module)
if not (f_name.startswith('__') or
f_name.endswith('__'))]:
module = None
if os.path.isfile(file_path) and fnmatch.fnmatch(file_path,'*.py'):
module_name = os.path.splitext(elem_name)[0]
log.debug('Possible module detected.')
try:
module = __import__(module_name)
log.debug('Module imported.')
except ValueError, value_error:
log.debug('Module not imported successfully. ValueError: %s'%(value_error))
except ImportError, import_error:
log.debug('Module not imported successfully. ImportError: %s'%(import_error))
elif os.path.isdir(file_path):
module_name = elem_name
file_path += os.path.sep
log.debug('Possible package detected.')
try:
module = __import__(module_name)
log.debug('Package imported.')
except ValueError, value_error:
log.debug('Package not imported successfully. ValueError: %s'%(value_error))
except ImportError, import_error:
log.debug('Package not imported successfully. ImportError: %s'%(import_error))
if module:
log.debug('Attributes processing started')
for module_attr_name in [attr_name for attr_name in dir(module)
if not (attr_name.startswith('__') or
attr_name.endswith('__'))]:
module_attr = getattr(module, module_attr_name)
log.debug('%s : %s'%(module_attr_name, module_attr))
try:
if issubclass(module_attr, GajimPlugin) and \
not module_attr is 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))))
#log.debug('file_path: %s\ndirname: %s\nabspath: %s'%(file_path, os.path.dirname(file_path), os.path.abspath(os.path.dirname(file_path))))
module_attr.__path__ = os.path.abspath(os.path.dirname(file_path))
plugins_found.append(module_attr)
except TypeError, type_error:
log.debug('module_attr: %s, error : %s'%(