1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 """widget holder displaying a component specific views"""
23
24 import gettext
25 import os
26
27 import gobject
28 import gtk
29
30 from flumotion.common import componentui, log, errors, messages
31 from flumotion.common.common import pathToModuleName
32 from flumotion.common.planet import AdminComponentState, moods
33 from flumotion.common.i18n import N_, gettexter
34 from gettext import gettext as _
35
36 T_ = gettexter()
37
38
39 componentui
40
41 __version__ = "$Rev: 7572 $"
42 _ = gettext.gettext
43 _DEBUG_ONLY_PAGES = ['Eaters', 'Feeders', 'Properties']
44 (COMPONENT_UNSET,
45 COMPONENT_INACTIVE,
46 COMPONENT_ACTIVE) = range(3)
47
48
50 """A placeholder contains a Widget subclass of a specific
51 component.
52 """
53
57
59 """Set if debug should be enabled.
60 Not all pages are visible unless debugging is set to true
61 @param enable: if debug should be enabled
62 """
63
65 """Called when the placeholder is inactivated, eg
66 detached from the parent"""
67
68
70 """This is a placeholder containing a notebook with tabs
71 """
72 logCategory = 'nodebook'
73
75 """
76 @param admingtk: the GTK Admin with its nodes
77 @type admingtk: L{flumotion.component.base.admin_gtk.BaseAdminGtk}
78 """
79 self._debugEnabled = False
80 self._admingtk = admingtk
81 self._notebook = None
82 self._pageWidgets = {}
83
84 self._notebook = gtk.Notebook()
85 admingtk.setup()
86 self.nodes = admingtk.getNodes()
87 self._appendPages()
88 self._notebook.show()
89
90
91
94
96 if self._admingtk:
97
98 if hasattr(self._admingtk, 'cleanup'):
99 self._admingtk.cleanup()
100 self._admingtk = None
101
103 self._debugEnabled = enabled
104 if self._admingtk:
105 self._admingtk.setDebugEnabled(enabled)
106 for name in _DEBUG_ONLY_PAGES:
107 widget = self._pageWidgets.get(name)
108 if widget is None:
109 continue
110 widget.set_property('visible', enabled)
111
120
121 - def _addPage(self, name):
122 node = self.nodes.get(name)
123 assert node is not None, name
124
125 table = gtk.Table(1, 1)
126 table.add(gtk.Label(_('Loading UI for %s...') % name))
127 label = self._getTitleLabel(node, name)
128 label.show()
129 self._notebook.append_page(table, label)
130
131 d = node.render()
132 d.addCallback(self._renderWidget, table)
133 return table
134
135 - def _appendPages(self):
136 for name in self.nodes.keys():
137 table = self._addPage(name)
138 self._pageWidgets[name] = table
139
140 if name in _DEBUG_ONLY_PAGES:
141 if self._debugEnabled:
142 continue
143 table.show()
144
157
158
160 """This is a placeholder with a label, with or without a text"""
161
164
167
168
170 """This is a placeholder used to display a Planet"""
171
173 self._widget = gtk.Label('')
174
177
178
180 logCategory = 'componentview'
181
183 gtk.VBox.__init__(self)
184 self._admin = None
185 self._currentComponentState = None
186 self._currentPlaceholder = None
187 self._debugEnabled = False
188 self._state = COMPONENT_UNSET
189
190 self._planetPlaceholder = PlanetPlaceholder()
191 self._addPlaceholder(self._planetPlaceholder)
192
193
194
196 """Find out if debug is enabled
197 @returns: if debug is enabled
198 @rtype: bool
199 """
200 return self._debugEnabled
201
203 """Sets if debug should be enabled
204 @param enabled: if debug should be enabled
205 @type enabled: bool
206 """
207 self._debugEnabled = enabled
208 if self._currentPlaceholder:
209 self._currentPlaceholder.setDebugEnabled(enabled)
210
220
222 """
223 Sets a single global admin for the component view
224
225 @param admin: the admin
226 @type admin: L{flumotion.admin.admin.AdminModel}
227 """
228 self._admin = admin
229
231 """
232 Get the admin for a specific component
233
234 @param component: component
235 @type component: L{flumotion.common.component.AdminComponentState}
236
237 @returns: the admin
238 @rtype: L{flumotion.admin.admin.AdminModel}
239 """
240
241 return self._admin
242
243
244
246 if not isinstance(placeholder, Placeholder):
247 raise AssertionError(
248 "placeholder must be a Placeholder subclass, not %r" % (
249 placeholder, ))
250
251 widget = placeholder.getWidget()
252 widget.show()
253 map(self.remove, self.get_children())
254 self.pack_start(widget, True, True)
255
256 placeholder.setDebugEnabled(self._debugEnabled)
257 self._currentPlaceholder = placeholder
258
264
274
275 def oldVersion(failure):
276
277
278
279
280
281
282
283 failure.trap(AttributeError)
284
285 return admin.callRemote(
286 'getEntryByType', componentState, 'admin/gtk')
287
288 def gotEntryPoint((filename, procname)):
289
290
291
292 filename = filename.replace('/', os.path.sep)
293
294
295
296 modname = pathToModuleName(filename)
297
298
299 d = admin.getBundledFunction(modname, procname)
300 d.addErrback(admin.bundleErrback, filename)
301
302 def handleSyntaxError(failure):
303 failure.trap(errors.EntrySyntaxError)
304 msg = failure.value.args[0]
305
306 m = messages.Error(T_(
307 N_("This component has a UI bug.")), debug=msg)
308 componentState.observe_append('messages', m)
309
310 raise errors.HandledException(failure.value)
311
312 d.addErrback(handleSyntaxError)
313
314 return d
315
316 def gotFactory(factory):
317
318 widget = factory(componentState, admin)
319 return NotebookPlaceholder(widget)
320
321 def sleepingComponent(failure):
322 failure.trap(errors.SleepingComponentError)
323 return LabelPlaceholder(_("Component '%s' is still sleeping.") %
324 componentState.get('name'))
325
326 def handledExceptionErrback(failure):
327
328
329 failure.trap(errors.HandledException)
330 return LabelPlaceholder(_("Component '%s' has a UI bug.") %
331 componentState.get('name'))
332
333 admin = self.getAdminForComponent(componentState)
334 componentType = componentState.get('type')
335 d = admin.callRemote('getEntryByType', componentType, 'admin/gtk')
336 d.addErrback(oldVersion)
337 d.addErrback(noBundle)
338 d.addCallback(gotEntryPoint)
339 d.addCallback(gotFactory)
340 d.addErrback(sleepingComponent)
341 d.addErrback(handledExceptionErrback)
342 return d
343
348
349 def set_(state, key, value):
350 if key != 'mood':
351 return
352 if value not in [moods.lost.value,
353 moods.sleeping.value,
354 moods.sad.value]:
355 self._setState(COMPONENT_ACTIVE)
356 else:
357 self._setState(COMPONENT_INACTIVE)
358
359 current = self._currentComponentState
360 assert current is not None
361 current.addListener(self, invalidate=invalidate, set_=set_)
362 if current.hasKey('mood'):
363 set_(current, 'mood', current.get('mood'))
364
366
367 def gotWidgetConstructor(placeholder, oldComponentState):
368 if oldComponentState != self._currentComponentState:
369
370
371
372 self.debug('ignoring component %r, state %d, state %r/%r' % (
373 placeholder, self._state,
374 oldComponentState, self._currentComponentState))
375 return
376 self._removePlaceholder(self._planetPlaceholder)
377 self._addPlaceholder(placeholder)
378
379 d = self._getWidgetConstructor(self._currentComponentState)
380 d.addCallback(gotWidgetConstructor, self._currentComponentState)
381
385
387 if self._currentComponentState:
388 self._currentComponentState.removeListener(self)
389 self._currentComponentState = None
390
408
409 gobject.type_register(ComponentView)
410