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

Source Code for Module flumotion.component.base.eatersnode

  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 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  Feeders tab in the component UI 
 24  """ 
 25   
 26  import gettext 
 27  import os 
 28  import time 
 29    
 30  import gtk 
 31   
 32  from flumotion.common.format import formatStorage, formatTime, formatTimeStamp 
 33  from flumotion.common.i18n import gettexter 
 34  from flumotion.component.base.baseadminnode import BaseAdminGtkNode 
 35  from flumotion.component.base.statewatcher import StateWatcher 
 36   
 37  _ = gettext.gettext 
 38  __version__ = "$Rev: 7089 $" 
 39  T_ = gettexter() 
 40   
 41   
42 -class EatersAdminGtkNode(BaseAdminGtkNode):
43 gladeFile = os.path.join('flumotion', 'component', 'base', 'eaters.glade') 44
45 - def __init__(self, state, admin):
46 BaseAdminGtkNode.__init__(self, state, admin, title=_("Eaters")) 47 # tree model is a model of id, uiState, StateWatcher 48 # tree model contains eaters 49 self.treemodel = None 50 self.treeview = None 51 self._selected = None # the watcher of the currently selected row 52 self.labels = {} 53 self._lastConnect = 0 54 self._lastDisconnect = 0
55
56 - def select(self, watcher):
57 if self._selected: 58 self._selected.hide() 59 if watcher: 60 self._selected = watcher 61 self._selected.show() 62 else: 63 self._selected = None
64
65 - def _setEaterFD(self, state, value):
66 if value is None: 67 self._table_connected.hide() 68 self._table_disconnected.show() 69 else: 70 self._table_disconnected.hide() 71 self._table_connected.show()
72
73 - def _setEaterName(self, state, value):
74 self.labels['eater-name'].set_markup(_('Eater <b>%s</b>') % value)
75
76 - def _setEaterBytesReadCurrent(self, state, value):
77 txt = value and (formatStorage(value) + _('Byte')) or '' 78 self.labels['bytes-read-current'].set_text(txt) 79 self._updateConnectionTime() 80 self._updateDisconnectionTime()
81
82 - def _setEaterConnectionItem(self, state, key, value):
83 if key == 'feed-id': 84 self.labels['eating-from'].set_text(str(value)) 85 # timestamps 86 elif key == 'count-timestamp-discont': 87 self.labels['timestamp-discont-count-current'].set_text(str(value)) 88 if value > 0: 89 self._expander_discont_current.show() 90 elif key == 'time-timestamp-discont': 91 text = formatTimeStamp(time.localtime(value)) 92 self.labels['timestamp-discont-time-current'].set_text(text) 93 if value is not None: 94 self._vbox_timestamp_discont_current.show() 95 elif key == 'last-timestamp-discont': 96 text = formatTime(value, fractional=9) 97 self.labels['timestamp-discont-last-current'].set_text(text) 98 if value > 0.0: 99 self._vbox_timestamp_discont_current.show() 100 elif key == 'total-timestamp-discont': 101 text = formatTime(value, fractional=9) 102 self.labels['timestamp-discont-total-current'].set_text(text) 103 if value > 0.0: 104 self._vbox_timestamp_discont_current.show() 105 elif key == 'timestamp-timestamp-discont': 106 if value is None: 107 return 108 text = formatTime(value, fractional=9) 109 self.labels['timestamp-discont-timestamp-current'].set_text(text) 110 # offsets 111 elif key == 'count-offset-discont': 112 self.labels['offset-discont-count-current'].set_text(str(value)) 113 if value > 0: 114 self._expander_discont_current.show() 115 elif key == 'time-offset-discont': 116 text = formatTimeStamp(time.localtime(value)) 117 self.labels['offset-discont-time-current'].set_text(text) 118 if value is not None: 119 self._vbox_offset_discont_current.show() 120 elif key == 'last-offset-discont': 121 text = _("%d units") % value 122 self.labels['offset-discont-last-current'].set_text(text) 123 if value > 0: 124 self._vbox_offset_discont_current.show() 125 elif key == 'total-offset-discont': 126 text = _("%d units") % value 127 self.labels['offset-discont-total-current'].set_text(text) 128 if value > 0: 129 self._vbox_offset_discont_current.show() 130 elif key == 'offset-offset-discont': 131 if value is None: 132 return 133 text = _("%d units") % value 134 self.labels['offset-discont-offset-current'].set_text(text) 135 if value > 0: 136 self._vbox_offset_discont_current.show()
137
138 - def _setEaterCountTimestampDiscont(self, state, value):
139 if value is None: 140 return 141 self.labels['timestamp-discont-count-total'].set_text(str(value)) 142 if value > 0.0: 143 self._expander_discont_total.show()
144
145 - def _setEaterTotalTimestampDiscont(self, state, value):
146 if value is None: 147 return 148 text = formatTime(value, fractional=9) 149 self.labels['timestamp-discont-total'].set_text(text) 150 if value > 0.0: 151 self._vbox_timestamp_discont_total.show()
152
153 - def _setEaterCountOffsetDiscont(self, state, value):
154 if value is None: 155 return 156 self.labels['offset-discont-count-total'].set_text(str(value)) 157 if value != 0: 158 self._expander_discont_total.show()
159
160 - def _setEaterTotalOffsetDiscont(self, state, value):
161 if value is None: 162 return 163 text = _("%d units") % value 164 self.labels['offset-discont-total'].set_text(text) 165 if value != 0: 166 self._vbox_offset_discont_total.show()
167
168 - def _setEaterLastConnect(self, state, value):
169 if value: 170 text = formatTimeStamp(time.localtime(value)) 171 self.labels['connected-since'].set_text(text) 172 self._table_connected.show() 173 self._table_disconnected.hide() 174 self._lastConnect = value 175 self._updateConnectionTime()
176
177 - def _setEaterTotalConnections(self, state, value):
178 self.labels['connections-total'].set_text(str(value))
179 180 # when we initially get the uiState, connection is an already set dict 181 # this makes sure we handle getting that dict initially
182 - def _setEaterConnection(self, state, value):
183 # can be called with None value due to StateWatcher 184 if value is None: 185 return 186 for k, v in value.items(): 187 self._setEaterConnectionItem(state, k, v)
188 189 # FIXME: add a timeout to update this ?
190 - def _updateConnectionTime(self):
191 if self._lastConnect: 192 text = formatTime(time.time() - self._lastConnect) 193 self.labels['connection-time'].set_text(text)
194 195 # FIXME: add a timeout to update this ?
196 - def _updateDisconnectionTime(self):
197 if self._lastDisconnect: 198 text = formatTime(time.time() - self._lastDisconnect) 199 self.labels['disconnection-time'].set_text(text)
200
201 - def addEater(self, uiState, state):
202 """ 203 @param uiState: the component's uiState 204 @param state: the eater's uiState 205 """ 206 eaterId = state.get('eater-alias') 207 i = self.treemodel.append(None) 208 self.treemodel.set(i, 0, eaterId, 1, state) 209 w = StateWatcher(state, 210 { 211 'fd': self._setEaterFD, 212 'eater-alias': self._setEaterName, 213 'last-connect': self._setEaterLastConnect, 214 'count-timestamp-discont': self._setEaterCountTimestampDiscont, 215 'total-timestamp-discont': self._setEaterTotalTimestampDiscont, 216 'count-offset-discont': self._setEaterCountOffsetDiscont, 217 'total-offset-discont': self._setEaterTotalOffsetDiscont, 218 'total-connections': self._setEaterTotalConnections, 219 # need to have a setter for connection to be able to show 220 # it initially 221 'connection': self._setEaterConnection, 222 }, 223 {}, 224 {}, 225 setitemers={ 226 'connection': self._setEaterConnectionItem, 227 }, 228 delitemers={ 229 } 230 ) 231 self.treemodel.set(i, 2, w)
232
233 - def setUIState(self, state):
234 # will only be called when we have a widget tree 235 BaseAdminGtkNode.setUIState(self, state) 236 #self.widget.show_all() 237 for eater in state.get('eaters'): 238 self.addEater(state, eater)
239
240 - def haveWidgetTree(self):
241 self.labels = {} 242 self.widget = self.wtree.get_widget('eaters-widget') 243 self.treeview = self.wtree.get_widget('treeview-eaters') 244 # tree model is a model of id, uiState, StateWatcher 245 self.treemodel = gtk.TreeStore(str, object, object) 246 self.treeview.set_model(self.treemodel) 247 col = gtk.TreeViewColumn('Eater', gtk.CellRendererText(), 248 text=0) 249 self.treeview.append_column(col) 250 sel = self.treeview.get_selection() 251 sel.set_mode(gtk.SELECTION_SINGLE) 252 253 # get to know and set labels 254 def set_label(name): 255 self.labels[name] = self.wtree.get_widget('label-' + name) 256 if self.labels[name] is None: 257 raise KeyError(name) 258 # zeroes out all value labels 259 self.labels[name].set_text('')
260 261 for name in ( 262 'eater-name', 'connected-since', 'connection-time', 263 'eating-from', 'timestamp-discont-timestamp-current', 264 'offset-discont-offset-current', 265 'timestamp-discont-count-current', 'offset-discont-count-current', 266 'timestamp-discont-total-current', 'offset-discont-total-current', 267 'timestamp-discont-last-current', 'offset-discont-last-current', 268 'timestamp-discont-time-current', 'offset-discont-time-current', 269 'timestamp-discont-count-total', 'offset-discont-count-total', 270 'timestamp-discont-total', 'offset-discont-total', 271 'connections-total', 272 ): 273 set_label(name) 274 275 # handle selection changes on the tree widget 276 def sel_changed(sel): 277 model, i = sel.get_selected() 278 self.select(i and model.get_value(i, 2)) 279 self.wtree.get_widget('box-right').show()
280 281 sel.connect('changed', sel_changed) 282 283 # manage visibility of parts of the widget 284 self._table_connected = self.wtree.get_widget('table-current-connected') 285 self._table_disconnected = self.wtree.get_widget( 286 'table-current-disconnected') 287 self._table_eater = self.wtree.get_widget('table-eater') 288 self._expander_discont_current = self.wtree.get_widget( 289 'expander-discont-current') 290 self._vbox_timestamp_discont_current = self.wtree.get_widget( 291 'vbox-timestamp-discont-current') 292 self._vbox_offset_discont_current = self.wtree.get_widget( 293 'vbox-offset-discont-current') 294 295 self._expander_discont_total = self.wtree.get_widget( 296 'expander-discont-total') 297 self._vbox_timestamp_discont_total = self.wtree.get_widget( 298 'vbox-timestamp-discont-total') 299 self._vbox_offset_discont_total = self.wtree.get_widget( 300 'vbox-offset-discont-total') 301 # 302 # show the tree view always 303 self.wtree.get_widget('scrolledwindow').show_all() 304 305 # hide the specifics of the eater 306 self._expander_discont_current.hide() 307 self._table_connected.hide() 308 self._table_disconnected.hide() 309 self._expander_discont_total.hide() 310 311 # show the right box only when an eater is selected 312 self.wtree.get_widget('box-right').hide() 313 314 # FIXME: do not show all; 315 # hide bytes fed and buffers dropped until something is selected 316 # see #575 317 self.widget.show() 318 return self.widget 319