1# -*- coding: UTF-8 -*- 2 3__revision__ = '$Id$' 4 5# Copyright © 2009 Piotr Ożarowski 6# 7# This program is free software; you can redistribute it and/or modify 8# it under the terms of the GNU General Public License as published byp 9# the Free Software Foundation; either version 2 of the License, or 10# (at your option) any later version. 11# 12# This program is distributed in the hope that it will be useful, 13# but WITHOUT ANY WARRANTY; without even the implied warranty of 14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15# GNU Library General Public License for more details. 16# 17# You should have received a copy of the GNU General Public License 18# along with this program; if not, write to the Free Software 19# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 20 21# You may use and distribute this software under the terms of the 22# GNU General Public License, version 2 or later 23 24import glob 25import logging 26import os.path 27import sys 28 29import db 30 31log = logging.getLogger('Griffith') 32 33# minimum and maximum supported extension API 34COMPAT = (1, 1) 35 36 37class GriffithExtensionBase(object): 38 """Griffith Extension 39 40 :attr config: configuration 41 :attr db: database 42 :attr locations: dictionary with Griffth locations 43 :attr widgets: dictionary with GUI widgets 44 :attr preferences: dictionary used to generate new widgets in preferences window 45 every key points to another dictionary that contains: 46 * name: will be shown to user 47 * type: int, unicode (type) or list, tuple, dict (instance) 48 * min: minimum value (int) or length (unicode) 49 * max: maximum value (int) or length (unicode) 50 :attr app: application reference (use only if really needed) 51 """ 52 name = None 53 description = None 54 author = None 55 email = None 56 version = None 57 api = 1 # required Griffith Extension API 58 59 enabled = True # default state (can be changed in preferences later) 60 toolbar_icon = None # None or stock icon name 61 preferences = {} 62 63 toolbar_icon_widget = None # will be constructed from toolbar_icon 64 65 def __new__(class_, *args, **kwargs): 66 if class_.api < COMPAT[0]: 67 raise DeprecationWarning("Extension is using API that is no longer supported: %s (api=%d)" % (class_.name, class_.api)) 68 if class_.api > COMPAT[1]: 69 raise NotImplementedError("Extension is using API that is not yet supported: %s (api=%d)" % (class_.name, class_.api)) 70 obj = object.__new__(class_) 71 obj.app = app = args[0] 72 obj.widgets = app.widgets 73 obj.config = app.config 74 obj.db = app.db 75 obj.locations = app.locations 76 return obj 77 78 def __repr__(self): 79 return "<GriffithExtension api=%d name=%s version=%s>" % (self.api, self.name, self.version) 80 81 def get_config_value(self, key, default=None): 82 return self.config.get("%s_%s" % (self.id, key), default, section='extensions') 83 84 def set_config_value(self, key, value=None): 85 self.config.set("%s_%s" % (self.id, key), value, section='extensions') 86 self.config.save() 87 88 def _on_toolbar_icon_clicked(self, button_widget): 89 session = self.db.Session() 90 movie = session.query(db.Movie).filter(db.Movie.movie_id == self.app._movie_id).first() 91 if not movie: 92 log.error('No movie selected') 93 else: 94 self.toolbar_icon_clicked(button_widget, movie) 95 96 # methods that can be overwritten: 97 98 def __init__(self, griffith): 99 """Initializes extension""" 100 101 def clear(self): # __del__ cannot be used here (signal reference issue) 102 """Invoked when extension is about to be disabled""" 103 if self.toolbar_icon_widget: 104 self.toolbar_icon_widget.destroy() 105 106 def maintree_clicked(self, selection, movie): 107 """Invoked every time new movie is selected""" 108 109 def toolbar_icon_clicked(self, widget, movie): 110 """Invoked when toolbar icon is clicked""" 111 112 def filter_movies(self, conditions): 113 """Modifies movie selection (via search conditions)""" 114 return conditions 115 116 117by_name = {} # extension modules by name 118 119 120def scan_for_extensions(path): 121 """Adds new extensions from given path""" 122 123 names = dict((os.path.basename(x)[:-3], x) for x in glob.glob("%s/ge_[a-zA-Z]*.py" % path)) 124 names.update(dict((os.path.basename(x)[:-4], x) for x in glob.glob("%s/ge_[a-zA-Z]*.pyo" % path))) 125 names.update(dict((os.path.basename(x)[:-4], x) for x in glob.glob("%s/ge_[a-zA-Z]*.pyc" % path))) 126 127 if names: 128 remove_from_syspath = False 129 if path not in sys.path: 130 remove_from_syspath = True 131 sys.path.append(path) 132 133 for ext_name in names: 134 #module = __import__("plugins.extensions.%s" % ext_name, fromlist=[ext_name]) 135 module = __import__(ext_name) 136 id_ = ext_name[3:] # skip the "ge_" 137 extension = module.GriffithExtension 138 extension.id = id_ 139 extension.__file__ = names[ext_name] 140 by_name[id_] = extension 141 142 if remove_from_syspath: 143 del sys.path[-1] 144 145scan_for_extensions(os.path.dirname(__file__)) # user's directory will be added later (in app) 146