Package elisa :: Package plugins :: Package good :: Package xmlmenu :: Module xmltreemenu_activity
[hide private]
[frames] | no frames]

Source Code for Module elisa.plugins.good.xmlmenu.xmltreemenu_activity

  1  # -*- coding: utf-8 -*- 
  2  # Elisa - Home multimedia server 
  3  # Copyright (C) 2006-2008 Fluendo Embedded S.L. (www.fluendo.com). 
  4  # All rights reserved. 
  5  # 
  6  # This file is available under one of two license agreements. 
  7  # 
  8  # This file is licensed under the GPL version 3. 
  9  # See "LICENSE.GPL" in the root of this distribution including a special 
 10  # exception to use Elisa with Fluendo's plugins. 
 11  # 
 12  # The GPL part of Elisa is also available under a commercial licensing 
 13  # agreement from Fluendo. 
 14  # See "LICENSE.Elisa" in the root directory of this distribution package 
 15  # for details on that license. 
 16   
 17   
 18  __maintainer__ = 'Benjamin Kampmann <benjamin@fluendo.com>' 
 19   
 20   
 21  import os, weakref 
 22   
 23  from elisa.core.component import InitializeFailure 
 24  from elisa.base_components.activity import Activity 
 25  from elisa.core import common 
 26   
 27  from elisa.extern.coherence.et import parse_xml 
 28   
 29  from twisted.internet import defer 
 30   
31 -class XmltreemenuActivity(Activity):
32 """ 33 Parses an XML description of a tree of media and creates the corresponding 34 tree of Models. 35 36 DOCME MORE 37 """ 38 39 # FIXME: retrieving ~/.elisa should be a facility provided by Elisa core 40 default_config = {'xml_menu' : '%s/.elisa/elisa_menu.xml' % \ 41 os.path.expanduser('~'), 42 'menu_builders' : ['xmlmenu:activity_node_builder', \ 43 'xmlmenu:locations_builder', \ 44 'xmlmenu:xdg_entry_builder', \ 45 'xmlmenu:playlist_node_builder', \ 46 'xmlmenu:menu_node_builder', \ 47 'xmlmenu:uri_node_builder'] 48 } 49 50 config_doc = {'xml_menu' : 'Local path to the XML file containing' \ 51 ' the Elisa menu description', 52 'menu_builders' : 'Components used to build the menu', 53 } 54
55 - def initialize(self):
56 self._xml_menu_path = self.config.get('xml_menu', '') 57 58 self._model_configs = weakref.WeakKeyDictionary() 59 60 #FIXME: This reading is blocking! 61 try: 62 self.debug("Trying to load XML file: %s " % self._xml_menu_path) 63 file = open(self._xml_menu_path, 'r') 64 xml = file.read() 65 except IOError, error: 66 self.info("Could not read %s: %s" % (self._xml_menu_path, error)) 67 self.info("Using default menu description") 68 full_path = self.plugin.get_resource_file('data/default_menu.xml') 69 xml = open(full_path, 'r').read() 70 71 try: 72 self._xml = parse_xml(xml) 73 except Exception, error: 74 raise InitializeFailure('XMLTreeActivity', "Invalid XML in '%s:'"\ 75 " %s" % (self._xml_menu_path, error)) 76 77 # dictionary with keys being identifiers as returned by 78 # menu_entry_identifiers__get and values being builders 79 self._menu_builders = {} 80 builder_paths = self.config.get('menu_builders' , []) 81 registry = common.application.plugin_registry 82 83 def setup_builder(builder): 84 builder.activity = self 85 builder.model_configs = self._model_configs 86 87 # setup builder to be the one managing its supported 88 # menu_entry_identifiers if no other builder is doing it 89 for identifier in builder.menu_entry_identifiers: 90 if self._menu_builders.has_key(identifier): 91 self.warning('Identifier %s already manager by %s' % \ 92 (identifier, self._menu_builders[identifier])) 93 else: 94 self._menu_builders[identifier] = builder
95 96 def builder_failed(failure, builder_paths): 97 # inform the user about the failure 98 self.warning(failure.getErrorMessage()) 99 try: 100 failure.raiseException() 101 except: 102 common.application.handle_traceback() 103 104 # carry on building the remaining builders 105 create_builders(builder_paths)
106 107 def create_builders(builder_paths): 108 """ 109 Create and setup sequentially the builders identified by their path 110 """ 111 if len(builder_paths) == 0: 112 return defer.succeed(None) 113 114 dfr = defer.maybeDeferred(registry.create_component, 115 builder_paths[0]) 116 dfr.addCallback(setup_builder) 117 dfr.addCallback(lambda dummy, builder_paths: 118 create_builders(builder_paths), builder_paths[1:]) 119 dfr.addErrback(builder_failed, builder_paths[1:]) 120 return dfr 121 122 dfr = create_builders(builder_paths) 123 124 # FIXME: in the next API, we should return the dfr 125
126 - def clean(self):
127 Activity.clean(self) 128 # FIXME: write down the default config 129 for builder in self._menu_builders.values(): 130 builder.clean()
131
132 - def unload(self, model):
133 """ 134 Clear the children of the model 135 """ 136 model[:] = []
137
138 - def loadmore(self, model):
139 140 if model.children == None or len(model.children) == 0: 141 registry = common.application.plugin_registry 142 model.children = registry.create_component('base:list_model') 143 model.children.activity = self 144 145 elif len(model.children) > 0: 146 return defer.succeed(model.children) 147 148 if self._model_configs.has_key(model): 149 # FIXME: could this be faulty? 150 config = self._model_configs[model] 151 model.children.content_type = config['ContentType'] 152 if config.has_key('xml_tag'): 153 for node in config['xml_tag'].findall('MenuEntry'): 154 self.handle_menu_entry(model, node) 155 return defer.succeed(model.children) 156 157 return defer.fail(None)
158
159 - def get_model(self):
160 registry = common.application.plugin_registry 161 162 menu_model = registry.create_component('base:menu_model') 163 menu_model.children = registry.create_component('base:list_model') 164 menu_model.children.activity = self 165 166 menu_model.text = 'elisa' 167 menu_model.activity = self 168 menu_model.has_children = True 169 170 # set the root xml_tag 171 root = self._xml.getroot() 172 menu_config = { 173 'DefaultDirsIcon' : 'dir_icon', 174 'DefaultFilesIcon' : 'file_icon', 175 'MediaFilter' : 'ANY', 176 'ContentType' : 'sections' } 177 178 config = root.find('Configuration') 179 if config != None: 180 for key in menu_config.keys(): 181 new_config = config.find(key) 182 if new_config != None: 183 menu_config[key] = new_config.text 184 185 menu_model.children.content_type = menu_config['ContentType'] 186 187 menu_config['xml_tag'] = root 188 self._model_configs[menu_model] = menu_config 189 190 return menu_model
191 192 # private methods
193 - def handle_menu_entry(self, parent, menu_node):
194 tipo = menu_node.get('type', None) 195 if tipo == None: 196 self.warning ('%s misses a type value. Skipped' % menu_node) 197 return dfr.succeed([]) 198 199 if self._menu_builders.has_key(tipo): 200 builder = self._menu_builders[tipo] 201 202 return builder.build_menu_entry(parent, menu_node) 203 return defer.succeed([])
204