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  Eaters 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: 7162 $" 
 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
183 - def _setEaterConnection(self, state, value):
184 # can be called with None value due to StateWatcher 185 if value is None: 186 return 187 for k, v in value.items(): 188 self._setEaterConnectionItem(state, k, v)
189 190 # FIXME: add a timeout to update this ? 191
192 - def _updateConnectionTime(self):
193 if self._lastConnect: 194 text = formatTime(time.time() - self._lastConnect) 195 self.labels['connection-time'].set_text(text)
196 197 # FIXME: add a timeout to update this ? 198
199 - def _updateDisconnectionTime(self):
200 if self._lastDisconnect: 201 text = formatTime(time.time() - self._lastDisconnect) 202 self.labels['disconnection-time'].set_text(text)
203
204 - def addEater(self, uiState, state):
205 """ 206 @param uiState: the component's uiState 207 @param state: the eater's uiState 208 """ 209 eaterId = state.get('eater-alias') 210 i = self.treemodel.append(None) 211 self.treemodel.set(i, 0, eaterId, 1, state) 212 w = StateWatcher(state, 213 { 214 'fd': self._setEaterFD, 215 'eater-alias': self._setEaterName, 216 'last-connect': self._setEaterLastConnect, 217 'count-timestamp-discont': self._setEaterCountTimestampDiscont, 218 'total-timestamp-discont': self._setEaterTotalTimestampDiscont, 219 'count-offset-discont': self._setEaterCountOffsetDiscont, 220 'total-offset-discont': self._setEaterTotalOffsetDiscont, 221 'total-connections': self._setEaterTotalConnections, 222 # need to have a setter for connection to be able to show 223 # it initially 224 'connection': self._setEaterConnection, 225 }, 226 {}, 227 {}, 228 setitemers={'connection': self._setEaterConnectionItem, 229 }, 230 delitemers={}) 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 255 def set_label(name): 256 self.labels[name] = self.wtree.get_widget('label-' + name) 257 if self.labels[name] is None: 258 raise KeyError(name) 259 # zeroes out all value labels 260 self.labels[name].set_text('')
261 262 for name in ( 263 'eater-name', 'connected-since', 'connection-time', 264 'eating-from', 'timestamp-discont-timestamp-current', 265 'offset-discont-offset-current', 266 'timestamp-discont-count-current', 'offset-discont-count-current', 267 'timestamp-discont-total-current', 'offset-discont-total-current', 268 'timestamp-discont-last-current', 'offset-discont-last-current', 269 'timestamp-discont-time-current', 'offset-discont-time-current', 270 'timestamp-discont-count-total', 'offset-discont-count-total', 271 'timestamp-discont-total', 'offset-discont-total', 272 'connections-total', 273 ): 274 set_label(name) 275 276 # handle selection changes on the tree widget 277 278 def sel_changed(sel): 279 model, i = sel.get_selected() 280 self.select(i and model.get_value(i, 2)) 281 self.wtree.get_widget('box-right').show()
282 283 sel.connect('changed', sel_changed) 284 285 # manage visibility of parts of the widget 286 self._table_connected = self.wtree.get_widget( 287 'table-current-connected') 288 self._table_disconnected = self.wtree.get_widget( 289 'table-current-disconnected') 290 self._table_eater = self.wtree.get_widget('table-eater') 291 self._expander_discont_current = self.wtree.get_widget( 292 'expander-discont-current') 293 self._vbox_timestamp_discont_current = self.wtree.get_widget( 294 'vbox-timestamp-discont-current') 295 self._vbox_offset_discont_current = self.wtree.get_widget( 296 'vbox-offset-discont-current') 297 298 self._expander_discont_total = self.wtree.get_widget( 299 'expander-discont-total') 300 self._vbox_timestamp_discont_total = self.wtree.get_widget( 301 'vbox-timestamp-discont-total') 302 self._vbox_offset_discont_total = self.wtree.get_widget( 303 'vbox-offset-discont-total') 304 # 305 # show the tree view always 306 self.wtree.get_widget('scrolledwindow').show_all() 307 308 # hide the specifics of the eater 309 self._expander_discont_current.hide() 310 self._table_connected.hide() 311 self._table_disconnected.hide() 312 self._expander_discont_total.hide() 313 314 # show the right box only when an eater is selected 315 self.wtree.get_widget('box-right').hide() 316 317 # FIXME: do not show all; 318 # hide bytes fed and buffers dropped until something is selected 319 # see #575 320 self.widget.show() 321 return self.widget 322