Package flumotion :: Package component :: Package base :: Module admin_gtk
[hide private]

Source Code for Module flumotion.component.base.admin_gtk

  1  # -*- Mode: Python; test-case-name: flumotion.test.test_feedcomponent010 -*- 
  2  # vi:si:et:sw=4:sts=4:ts=4 
  3   
  4  # Flumotion - a streaming media server 
  5  # Copyright (C) 2004,2005,2006,2007,2008,2009 Fluendo, S.L. 
  6  # Copyright (C) 2010,2011 Flumotion Services, S.A. 
  7  # All rights reserved. 
  8  # 
  9  # This file may be distributed and/or modified under the terms of 
 10  # the GNU Lesser General Public License version 2.1 as published by 
 11  # the Free Software Foundation. 
 12  # This file is distributed without any warranty; without even the implied 
 13  # warranty of merchantability or fitness for a particular purpose. 
 14  # See "LICENSE.LGPL" in the source distribution for more information. 
 15  # 
 16  # Headers in this file shall remain intact. 
 17   
 18  """ 
 19  Base classes for component UI's using GTK+ 
 20  """ 
 21   
 22  import gettext 
 23  import locale 
 24  import os 
 25   
 26  from twisted.python import util 
 27  from twisted.internet import defer 
 28   
 29  from flumotion.common import log 
 30  from flumotion.common.errors import SleepingComponentError 
 31  from flumotion.common.i18n import getLL, gettexter 
 32  from flumotion.component.base.componentnode import ComponentAdminGtkNode 
 33  from flumotion.component.base.eatersnode import EatersAdminGtkNode 
 34  from flumotion.component.base.feedersnode import FeedersAdminGtkNode 
 35  from flumotion.component.base.propertiesnode import PropertiesAdminGtkNode 
 36   
 37  _ = gettext.gettext 
 38  __version__ = "$Rev$" 
 39  T_ = gettexter() 
 40   
 41  # stupid pychecker 
 42  dir(locale) 
 43   
 44   
45 -class BaseAdminGtk(log.Loggable):
46 """ 47 I am a base class for all GTK+-based Admin views. 48 I am a view on one component's properties. 49 50 @type nodes: L{twisted.python.util.OrderedDict} 51 @ivar nodes: an ordered dict of name -> L{BaseAdminGtkNode} 52 """ 53 54 logCategory = "admingtk" 55 gettextDomain = None 56
57 - def __init__(self, state, admin):
58 """ 59 @param state: state of component this is a UI for 60 @type state: L{flumotion.common.planet.AdminComponentState} 61 @type admin: L{flumotion.admin.admin.AdminModel} 62 @param admin: the admin model that interfaces with the manager for us 63 """ 64 self._debugEnabled = False 65 self.state = state 66 self.name = state.get('name') 67 self.admin = admin 68 self.debug('creating admin gtk for state %r' % state) 69 self.uiState = None 70 self.nodes = util.OrderedDict() 71 72 d = admin.componentCallRemote(state, 'getUIState') 73 d.addCallback(self.setUIState) 74 d.addErrback(lambda failure: failure.trap(SleepingComponentError))
75
76 - def setDebugEnabled(self, enabled):
77 """Set if debug should be enabled. 78 Not all pages are visible unless debugging is set to true 79 80 @param enabled: whether debug should be enabled 81 @type enabled: bool 82 """ 83 self._debugEnabled = enabled 84 for node in self.getNodes().values(): 85 node.setDebugEnabled(enabled)
86
87 - def cleanup(self):
88 if self.uiState: 89 self.uiState.removeListener(self) 90 self.uiState = None 91 for node in self.getNodes().values(): 92 node.cleanup()
93
94 - def setUIState(self, state):
95 self.debug('starting listening to state %r', state) 96 state.addListener(self, set_=self.stateSet, append=self.stateAppend, 97 remove=self.stateRemove) 98 self.uiState = state 99 for node in self.getNodes().values(): 100 node.gotUIState(state) 101 self.uiStateChanged(state)
102
103 - def callRemote(self, methodName, *args, **kwargs):
104 return self.admin.componentCallRemote(self.state, methodName, 105 *args, **kwargs)
106 107 # FIXME: .setup() is subclassable, while .render() on nodes has 108 # haveWidgetTree. choose one of the two patterns in general 109
110 - def setup(self):
111 """ 112 Set up the admin view so it can display nodes. 113 """ 114 self.debug('BaseAdminGtk.setup()') 115 116 def fetchTranslations(): 117 if not self.gettextDomain: 118 return defer.succeed(None) 119 120 def haveBundle(localedatadir): 121 localeDir = os.path.join(localedatadir, 'locale') 122 self.debug("Loading locales for %s from %s" % ( 123 self.gettextDomain, localeDir)) 124 gettext.bindtextdomain(self.gettextDomain, localeDir) 125 locale.bindtextdomain(self.gettextDomain, localeDir)
126 127 lang = getLL() 128 self.debug("loading bundle for %s locales" % lang) 129 bundleName = '%s-locale-%s' % (self.gettextDomain, lang) 130 d = self.admin.bundleLoader.getBundleByName(bundleName) 131 d.addCallbacks(haveBundle, lambda _: None) 132 return d
133 134 def addPages(_): 135 # FIXME: node order should be fixed somehow, so e.g. Component 136 # always comes last, together with eater/feeder ? 137 138 # add a generic component node 139 self.nodes['Component'] = ComponentAdminGtkNode(self.state, 140 self.admin) 141 142 config = self.state.get('config') 143 144 # add feeder node, if component has feeders 145 if config['feed']: 146 self.debug("Component has feeders, show Feeders node") 147 self.nodes['Feeders'] = FeedersAdminGtkNode( 148 self.state, self.admin) 149 150 # add eater node, if component has eaters 151 if 'eater' in config and config['eater']: 152 self.debug("Component has eaters, show Eaters node") 153 self.nodes['Eaters'] = EatersAdminGtkNode( 154 self.state, self.admin) 155 156 # add a properties node 157 self.nodes['Properties'] = PropertiesAdminGtkNode(self.state, 158 self.admin) 159 160 d = fetchTranslations() 161 d.addCallback(addPages) 162 163 # FIXME: why are we not returning the deferred here ? If there is 164 # a good reason, it should be commented here 165 return 166
167 - def getNodes(self):
168 """ 169 Return a dict of admin UI nodes. 170 171 @rtype: dict of str -> L{BaseAdminGtkNode} 172 @returns: dict of name (untranslated) -> admin node 173 """ 174 return self.nodes
175 176 # FIXME: deprecated 177
178 - def render(self):
179 """ 180 Render the GTK+ admin view for this component and return the 181 main widget for embedding. 182 """ 183 raise NotImplementedError
184
185 - def uiStateChanged(self, stateObject):
186 # so, this is still here, but I'd prefer people to (1) just use 187 # the nodes and not the global admin; and (2) use the state 188 # listener stuff more than the chunkier 'uistatechanged' 189 pass
190
191 - def stateSet(self, object, key, value):
192 self.uiStateChanged(object)
193
194 - def stateAppend(self, object, key, value):
195 self.uiStateChanged(object)
196
197 - def stateRemove(self, object, key, value):
198 self.uiStateChanged(object)
199