CoverArt Browser  v2.0
Browse your cover-art albums in Rhythmbox
/home/foss/Downloads/coverart-browser/coverart_external_plugins.py
00001 # -*- Mode: python; coding: utf-8; tab-width: 4; indent-tabs-mode: nil; -*-
00002 #
00003 # Copyright (C) 2012 - fossfreedom
00004 # Copyright (C) 2012 - Agustin Carrasco
00005 #
00006 # This program is free software; you can redistribute it and/or modify
00007 # it under the terms of thie GNU General Public License as published by
00008 # the Free Software Foundation; either version 2, or (at your option)
00009 # any later version.
00010 #
00011 # This program is distributed in the hope that it will be useful,
00012 # but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 # GNU General Public License for more details.
00015 #
00016 # You should have received a copy of the GNU General Public License
00017 # along with this program; if not, write to the Free Software
00018 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA.
00019 
00020 from gi.repository import Peas
00021 from gi.repository import GObject
00022 import lxml.etree as ET
00023 
00024 import rb
00025 from coverart_rb3compat import ActionGroup
00026 from coverart_rb3compat import ApplicationShell
00027 from coverart_utils import CaseInsensitiveDict
00028 
00029 
00030 class ExternalPlugin(GObject.Object):
00031     '''
00032     class for all supported ExternalPlugins
00033     '''
00034 
00035     def __init__(self, **kargs):
00036         super(ExternalPlugin, self).__init__(**kargs)
00037 
00038         # dict of attributes associated with the external plugin
00039         self.attributes = {}
00040         self.attributes['is_album_menu'] = False
00041         self.attributes['new_menu_name'] = ''
00042         self.attributes['action_type'] = ''
00043         self.attributes['action_group_name'] = ''
00044 
00045     def appendattribute(self, key, val):
00046         '''
00047         append another attribute to the dict
00048         
00049         :param key: `str` name of attribute
00050         :param val: `str` value of attribute
00051         '''
00052 
00053         if key == 'is_album_menu':
00054             if val == 'yes':
00055                 self.attributes[key] = True
00056             else:
00057                 self.attributes[key] = False
00058         else:
00059             self.attributes[key] = val
00060 
00061     def is_activated(self):
00062         '''
00063         method to test whether the plugin is actually loaded. Returns a bool
00064         '''
00065         peas = Peas.Engine.get_default()
00066         loaded_plugins = peas.get_loaded_plugins()
00067 
00068         if self.attributes['plugin_name'] in CaseInsensitiveDict(loaded_plugins):
00069             print("found %s" % self.attributes['plugin_name'])
00070             return True
00071 
00072         print("search for %s" % self.attributes['plugin_name'])
00073         print(loaded_plugins)
00074 
00075         return False
00076 
00077     def create_menu_item(self, menubar, section_name, at_position,
00078                          save_actiongroup, save_menu, for_album=False):
00079         '''
00080         method to create the menu item appropriate to the plugin.
00081         A plugin can have many menu items - all menuitems are enclosed
00082         in a section.
00083         
00084         :param menubar: `str` name for the GtkMenu - ignored for RB2.99
00085         :param section_name: `str` unique name of the section holding the menu items
00086         :param at_position: `int` position within the GtkMenu to create menu - ignored for RB2.99
00087         :param save_actiongroup: `ActionGroup` container for all menu-item Actions
00088         :param save_menu: `Menu` whole popupmenu including sub-menus
00089         :param for_album: `bool` create the menu for the album - if not given
00090           then its assumed the menu item is appropriate just for tracks
00091         '''
00092         if for_album and not self.attributes['is_album_menu']:
00093             return False
00094 
00095         if not self.is_activated():
00096             return False
00097 
00098         action = ApplicationShell(save_menu.shell).lookup_action(self.attributes['action_group_name'],
00099                                                                  self.attributes['action_name'],
00100                                                                  self.attributes['action_type'])
00101 
00102         if action:
00103             self.attributes['action'] = action
00104 
00105             if self.attributes['new_menu_name'] != '':
00106                 self.attributes['label'] = self.attributes['new_menu_name']
00107             else:
00108                 self.attributes['label'] = action.label
00109                 #self.attributes['sensitive']=action.get_sensitive()
00110         else:
00111             print("action not found")
00112             print(self.attributes)
00113             return False
00114 
00115         action = save_actiongroup.add_action(func=self.menuitem_callback,
00116                                              action_name=self.attributes['action_name'], album=for_album,
00117                                              shell=save_menu.shell, label=self.attributes['label'])
00118 
00119         new_menu_item = save_menu.insert_menu_item(menubar, section_name,
00120                                                    at_position, action)
00121         return new_menu_item
00122 
00123     def do_deactivate(self):
00124         pass
00125 
00126     def set_entry_view_selected_entries(self, shell):
00127         '''
00128         method called just before the external plugin action is activated
00129 
00130         Normally only called for album menus to mimic selecting all the
00131         EntryView rows
00132         '''
00133         page = shell.props.selected_page
00134         if not hasattr(page, "get_entry_view"):
00135             return
00136 
00137         page.get_entry_view().select_all()
00138 
00139     def activate(self, shell):
00140         '''
00141         method called to initiate the external plugin action
00142         the action is defined by defining the action_group_name, action_name and action_type
00143         '''
00144 
00145         action = ApplicationShell(shell).lookup_action(self.attributes['action_group_name'],
00146                                                          self.attributes['action_name'],
00147                                                          self.attributes['action_type'])
00148 
00149         if action:
00150             action.activate()
00151 
00152     def menuitem_callback(self, action, param, args):
00153         '''
00154         method called when a menu-item is clicked.  Basically, an Action
00155         is activated by the user
00156         
00157         :param action: `Gio.SimpleAction` or `Gtk.Action`
00158         :param param: Not used
00159         :param args: dict associated with the action
00160         '''
00161         for_album = args['album']
00162         shell = args['shell']
00163         if for_album:
00164             self.set_entry_view_selected_entries(shell)
00165 
00166         self.attributes['action'].activate()
00167 
00168 
00169 class CreateExternalPluginMenu(GObject.Object):
00170     '''
00171     This is the key class called to initialise all supported plugins
00172     
00173     :param section_name: `str` unique name of the section holding the menu items
00174     :param at_position: `int` position within the GtkMenu to create menu - ignored for RB2.99
00175     :param popup: `Menu` whole popupmenu including sub-menus
00176     '''
00177 
00178     def __init__(self, section_name, at_position, popup, **kargs):
00179         super(CreateExternalPluginMenu, self).__init__(**kargs)
00180 
00181         self.menu = popup
00182         self.section_name = section_name
00183         self.at_position = at_position
00184 
00185         self._actiongroup = ActionGroup(popup.shell, section_name + '_externalplugins')
00186 
00187         # all supported plugins will be defined in the following array by parsing
00188         # the plugins XML file for the definition.
00189 
00190         self.supported_plugins = []
00191 
00192         extplugins = rb.find_plugin_file(popup.plugin, 'ui/coverart_external_plugins.xml')
00193         root = ET.parse(open(extplugins)).getroot()
00194 
00195         base = 'rb3/plugin'
00196 
00197         for elem in root.xpath(base):
00198             pluginname = elem.attrib['name']
00199 
00200             basemenu = base + "[@name='" + pluginname + "']/menu"
00201 
00202             for menuelem in root.xpath(basemenu):
00203                 ext = ExternalPlugin()
00204                 ext.appendattribute('plugin_name', pluginname)
00205 
00206                 label = menuelem.attrib['label']
00207                 if label != "":
00208                     ext.appendattribute('new_menu_name', label)
00209                     baseattrib = basemenu + "[@label='" + label + "']/attribute"
00210                 else:
00211                     baseattrib = basemenu + "/attribute"
00212 
00213                 for attribelem in root.xpath(baseattrib):
00214                     key = attribelem.attrib['name']
00215                     val = attribelem.text
00216                     ext.appendattribute(key, val)
00217 
00218                 self.supported_plugins.append(ext)
00219 
00220     def create_menu(self, menu_name, for_album=False):
00221         '''
00222         method to create the menu items for all supported plugins
00223 
00224         :param menu_name: `str` unique name (GtkMenu) id for the menu to create
00225         :for_album: `bool` - create a menu applicable for Albums
00226           by default a menu is assumed to be applicable to a track in an
00227           EntryView
00228         '''
00229         self.menu_name = menu_name
00230 
00231         self._actiongroup.remove_actions()
00232         self.menu.remove_menu_items(self.menu_name, self.section_name)
00233 
00234         items_added = False
00235 
00236         for plugin in self.supported_plugins:
00237             new_menu_item = plugin.create_menu_item(self.menu_name, self.section_name,
00238                                                     self.at_position, self._actiongroup, self.menu, for_album)
00239 
00240             if (not items_added) and new_menu_item:
00241                 items_added = True
00242 
00243         if items_added:
00244             self.menu.insert_separator(self.menu_name, self.at_position)
 All Classes Functions