Package flumotion :: Package admin :: Package gtk :: Module componentview
[hide private]

Source Code for Module flumotion.admin.gtk.componentview

  1  # -*- Mode: Python -*- 
  2  # vi:si:et:sw=4:sts=4:ts=4 
  3  # 
  4  # Flumotion - a streaming media server 
  5  # Copyright (C) 2004,2005,2006,2007 Fluendo, S.L. (www.fluendo.com). 
  6  # All rights reserved. 
  7   
  8  # This file may be distributed and/or modified under the terms of 
  9  # the GNU General Public License version 2 as published by 
 10  # the Free Software Foundation. 
 11  # This file is distributed without any warranty; without even the implied 
 12  # warranty of merchantability or fitness for a particular purpose. 
 13  # See "LICENSE.GPL" in the source distribution for more information. 
 14   
 15  # Licensees having purchased or holding a valid Flumotion Advanced 
 16  # Streaming Server license may use this file in accordance with the 
 17  # Flumotion Advanced Streaming Server Commercial License Agreement. 
 18  # See "LICENSE.Flumotion" in the source distribution for more information. 
 19   
 20  # Headers in this file shall remain intact. 
 21   
 22   
 23  import gobject 
 24  import gtk 
 25   
 26  from flumotion.common import planet, errors, common, log 
 27   
 28   
29 -class NodeBook(gtk.Notebook):
30 - def __init__(self, admingtk):
31 """ 32 @param admingtk: the GTK Admin with its nodes 33 @type admingtk: L{flumotion.component.base.admin_gtk.BaseAdminGtk} 34 35 """ 36 gtk.Notebook.__init__(self) 37 self.admingtk = admingtk 38 admingtk.setup() 39 self.nodes = admingtk.getNodes() 40 self._setup_pages() 41 self.show()
42
43 - def _setup_pages(self):
44 for name, node in self.nodes.items(): 45 table = gtk.Table(1,1) 46 table.show() 47 table.add(gtk.Label('Loading UI for %s...' % name)) 48 title = node.title 49 if not title: 50 # FIXME: we have no way of showing an error message ? 51 # This should be added so users can file bugs. 52 self.warning("Component node %s does not have a " 53 "translateable title. Please file a bug." % name) 54 55 # fall back for now 56 title = name 57 58 label = gtk.Label(title) 59 label.show() 60 self.append_page(table, label) 61 62 def got_widget(w, name, table, node): 63 # dumb dumb dumb dumb 64 if w.get_parent(): 65 w.get_parent().remove(w) 66 map(table.remove, table.get_children()) 67 table.add(w) 68 w.show()
69 node.render().addCallback(got_widget, name, table, node)
70 71 (OBJECT_UNSET, 72 OBJECT_INACTIVE, 73 OBJECT_ACTIVE) = range(3) 74
75 -class ComponentView(gtk.VBox, log.Loggable):
76 logCategory = 'componentview' 77
78 - def __init__(self):
79 gtk.VBox.__init__(self) 80 self.widget_constructor = None 81 self.widget = None 82 self.object = None 83 self._state = OBJECT_UNSET 84 self._callStamp = 0 85 self.set_single_admin(None)
86
87 - def set_single_admin(self, admin):
88 self.admin = admin
89
90 - def get_admin_for_object(self, object):
91 # override me to do e.g. multi.get_admin_for_object 92 return self.admin
93
94 - def get_widget_constructor(self, state):
95 def not_component_state(): 96 return gtk.Label('')
97 98 def no_bundle(failure): 99 failure.trap(errors.NoBundleError) 100 self.debug( 101 'No specific GTK admin for this component, using default') 102 return ("flumotion/component/base/admin_gtk.py", "BaseAdminGtk")
103 104 def got_entry_point((filename, procname)): 105 # getEntryByType for admin/gtk returns a factory function 106 # for creating 107 # flumotion.component.base.admin_gtk.BaseAdminGtk 108 # subclass instances 109 modname = common.pathToModuleName(filename) 110 return admin.getBundledFunction(modname, procname) 111 112 def got_factory(factory): 113 # instantiate from factory and wrap in a NodeBook 114 return lambda: NodeBook(factory(state, admin)) 115 116 def sleeping_component(failure): 117 failure.trap(errors.SleepingComponentError) 118 return lambda: gtk.Label('Component %s is still sleeping' % 119 state.get('name')) 120 121 admin = self.get_admin_for_object(state) 122 if not isinstance(state, planet.AdminComponentState): 123 return not_component_state 124 125 d = admin.callRemote('getEntryByType', state, 'admin/gtk') 126 d.addErrback(no_bundle) 127 d.addCallback(got_entry_point) 128 d.addCallback(got_factory) 129 d.addErrback(sleeping_component) 130 return d 131
132 - def object_unset_to_inactive(self):
133 def invalidate(_): 134 self._set_state(OBJECT_UNSET)
135 def set(state, key, value): 136 if key == 'mood': 137 if (value != planet.moods.lost.value 138 and value != planet.moods.sleeping.value): 139 self._set_state(OBJECT_ACTIVE) 140 else: 141 self._set_state(OBJECT_INACTIVE) 142 143 assert self.object is not None 144 self.object.addListener(self, invalidate=invalidate, 145 set=set) 146 if self.object.hasKey('mood'): 147 set(self.object, 'mood', self.object.get('mood')) 148
149 - def object_inactive_to_active(self):
150 def got_widget_constructor(proc, callStamp): 151 if callStamp != self._callStamp: 152 # in the time that get_widget_constructor was running, 153 # perhaps the user selected another object; only update 154 # the ui if that did not happen 155 self.debug('ignoring widget constructor %r, state %d, ' 156 'callstamps %d/%d', proc, self._state, 157 callStamp, self._callStamp) 158 return 159 assert self.widget == None 160 self.widget = proc() 161 self.widget.show() 162 self.pack_start(self.widget, True, True) 163 return self.widget
164 165 self._callStamp += 1 166 callStamp = self._callStamp 167 d = self.get_widget_constructor(self.object) 168 d.addCallback(got_widget_constructor, callStamp) 169
170 - def object_active_to_inactive(self):
171 # prevent got_widget_constructor from adding the widget above 172 self._callStamp += 1 173 if self.widget: 174 self.remove(self.widget) 175 # widget maybe a gtk.Label or a NodeBook 176 if hasattr(self.widget, 'admingtk'): 177 if self.widget.admingtk: 178 # needed for compatibility with managers with old code 179 if hasattr(self.widget.admingtk, 'cleanup'): 180 self.widget.admingtk.cleanup() 181 del self.widget.admingtk 182 self.widget = None
183
184 - def object_inactive_to_unset(self):
185 self.object.removeListener(self) 186 self.object = None
187
188 - def _set_state(self, state):
189 uptable = [self.object_unset_to_inactive, 190 self.object_inactive_to_active] 191 downtable = [self.object_inactive_to_unset, 192 self.object_active_to_inactive] 193 if self._state < state: 194 while self._state < state: 195 self.log('object %r state change: %d++', self.object, 196 self._state) 197 self._state += 1 198 uptable[self._state - 1]() 199 else: 200 while self._state > state: 201 self.log('object %r state change: %d--', self.object, 202 self._state) 203 self._state -= 1 204 downtable[self._state]()
205
206 - def show_object(self, state):
207 self._set_state(OBJECT_UNSET) 208 if state: 209 self.object = state 210 self._set_state(OBJECT_INACTIVE)
211 212 gobject.type_register(ComponentView) 213