1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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
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
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
56 self._xml_menu_path = self.config.get('xml_menu', '')
57
58 self._model_configs = weakref.WeakKeyDictionary()
59
60
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
78
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
88
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
98 self.warning(failure.getErrorMessage())
99 try:
100 failure.raiseException()
101 except:
102 common.application.handle_traceback()
103
104
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
125
131
133 """
134 Clear the children of the model
135 """
136 model[:] = []
137
158
191
192
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