Package flumotion :: Package component :: Package consumers :: Package disker :: Module admin_gtk
[hide private]

Source Code for Module flumotion.component.consumers.disker.admin_gtk

  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  import os 
 23  import gettext 
 24  import time 
 25   
 26  import gtk 
 27   
 28  from flumotion.common import errors, format 
 29   
 30  from flumotion.component.base.admin_gtk import BaseAdminGtk 
 31  from flumotion.component.base.baseadminnode import BaseAdminGtkNode 
 32   
 33  from flumotion.common.eventcalendar import LOCAL, UTC 
 34   
 35  _ = gettext.gettext 
 36   
 37  __version__ = "$Rev: 8205 $" 
 38   
 39  ( 
 40      COLUMN_TSTAMP, 
 41      COLUMN_FILENAME, 
 42      COLUMN_CREATED, 
 43      COLUMN_SIZE, 
 44      COLUMN_LOCATION, 
 45  ) = range(5) 
 46   
 47  from kiwi.ui import objectlist 
 48   
 49   
50 -class Point:
51
52 - def __init__(self, when, which, what):
53 """ 54 @param when: a naive datetime representing UTC 55 @type when: L{datetime.datetime} 56 @type which: str 57 @type what: str 58 """ 59 self.when = when 60 # when is in UTC, but show it in local timezone instead 61 when = when.replace(tzinfo=UTC).astimezone(LOCAL) 62 63 self.whenLocal = format.formatTimeStamp(when.timetuple()) 64 self.which = which 65 self.what = what
66 67
68 -class PointList(objectlist.ObjectList):
69
70 - def __init__(self, parent, uiState):
71 objectlist.ObjectList.__init__(self, [ 72 objectlist.Column("whenLocal", title=_("When")), 73 objectlist.Column("which", title=_("Which")), 74 objectlist.Column("what", title=_("What")), 75 ]) 76 self._parent = parent 77 self.setUIState(uiState)
78
79 - def setUIState(self, uiState):
80 self._uiState = uiState 81 self.clear() 82 for pointTuple in uiState.get('next-points'): 83 self.appendTuple(pointTuple)
84
85 - def appendTuple(self, pointTuple):
86 point = Point(*pointTuple) 87 self.append(point)
88
89 - def removeTuple(self, pointTuple):
90 for point in self: 91 if (point.when, point.which, point.what) == pointTuple: 92 self.remove(point)
93 94
95 -class FilenameNode(BaseAdminGtkNode):
96 gladeFile = os.path.join('flumotion', 'component', 'consumers', 97 'disker', 'disker.glade') 98 99 currentFilenameLabel = None 100 currentFilenamePendingText = None 101 stopbutton = None 102 hasIcal = False 103
104 - def haveWidgetTree(self):
105 self.labels = {} 106 self.widget = self.wtree.get_widget('filename-widget') 107 self.currentFilenameLabel = self.wtree.get_widget('label-current') 108 if self.currentFilenamePendingText: 109 self.currentFilenameLabel.set_text(self.currentFilenamePendingText) 110 newbutton = self.wtree.get_widget('button-new') 111 newbutton.connect('clicked', self.cb_changefile_button_clicked) 112 self.stopbutton = self.wtree.get_widget('button-stop') 113 self.stopbutton.connect('clicked', self.cb_stop_button_clicked) 114 if self.hasIcal: 115 self.addScheduleWidget() 116 self.addNextPointsWidget()
117
118 - def cb_changefile_button_clicked(self, button):
119 d = self.callRemote("changeFilename") 120 d.addErrback(self.changeFilenameErrback)
121
122 - def changeFilenameErrback(self, failure):
123 self.warning("Failure %s changing filename: %s" % ( 124 failure.type, failure.getErrorMessage())) 125 return None
126
127 - def cb_stop_button_clicked(self, button):
128 d = self.callRemote("stopRecording") 129 d.addErrback(self.stopRecordingErrback)
130
131 - def stopRecordingErrback(self, failure):
132 self.warning("Failure %s stopping recording: %s" % ( 133 failure.type, failure.getErrorMessage())) 134 return None
135
136 - def setUIState(self, state):
137 BaseAdminGtkNode.setUIState(self, state) 138 self.stateSet(state, 'filename', state.get('filename')) 139 self.stateSet(state, 'recording', state.get('recording')) 140 self.stateSet(state, 'can-schedule', state.get('can-schedule'))
141
142 - def stateSet(self, state, key, value):
143 if key == 'filename': 144 if self.currentFilenameLabel: 145 self.currentFilenameLabel.set_text(value or '<waiting>') 146 else: 147 self.currentFilenamePendingText = value 148 if key == 'recording': 149 if not value: 150 if self.currentFilenameLabel: 151 self.currentFilenameLabel.set_text('None') 152 else: 153 self.currentFilenamePendingText = "None" 154 if self.stopbutton: 155 self.stopbutton.set_sensitive(value) 156 if key == 'can-schedule' and value: 157 self.hasIcal = True 158 if self.widget: 159 self.addScheduleWidget() 160 self.addNextPointsWidget()
161
162 - def stateAppend(self, state, key, value):
163 if key == 'next-points': 164 self._pointList.appendTuple(value)
165
166 - def stateRemove(self, state, key, value):
167 if key == 'next-points': 168 self._pointList.removeTuple(value)
169
170 - def addScheduleWidget(self):
171 self.filechooser = gtk.FileChooserButton("Upload a schedule") 172 self.filechooser.set_local_only(True) 173 self.filechooser.set_action(gtk.FILE_CHOOSER_ACTION_OPEN) 174 filefilter = gtk.FileFilter() 175 filefilter.add_pattern("*.ics") 176 filefilter.set_name("vCalendar files") 177 self.filechooser.add_filter(filefilter) 178 self.filechooser.show() 179 scheduleButton = gtk.Button("Schedule recordings") 180 scheduleButton.show() 181 scheduleButton.connect("clicked", self.cb_schedule_recordings) 182 self.widget.attach(scheduleButton, 0, 1, 1, 2, 183 xoptions=0, yoptions=0, xpadding=6, ypadding=6) 184 self.widget.attach(self.filechooser, 1, 2, 1, 2, 185 xoptions = gtk.EXPAND|gtk.FILL, yoptions=0, xpadding=6, ypadding=6)
186
187 - def addNextPointsWidget(self):
188 self._pointList = PointList(self.widget, self.uiState) 189 self.widget.attach(self._pointList, 0, 2, 3, 4, 190 xoptions=gtk.FILL, yoptions=gtk.FILL | gtk.EXPAND, 191 xpadding=6, ypadding=6) 192 self._pointList.show()
193
194 - def cb_schedule_recordings(self, widget):
195 filename = self.filechooser.get_filename() 196 self.debug("filename is %r, uri %r, %r", filename, 197 self.filechooser.get_uri(), self.filechooser) 198 if filename: 199 icsStr = open(filename, "rb").read() 200 d = self.callRemote("scheduleRecordings", icsStr) 201 d.addErrback(self.scheduleRecordingsErrback) 202 else: 203 self.warning("No filename selected")
204
205 - def scheduleRecordingsErrback(self, failure):
206 self.warning("Failure %s scheduling recordings: %s" % ( 207 failure.type, failure.getErrorMessage())) 208 return None
209 210
211 -class StatusNode(BaseAdminGtkNode):
212 gladeFile = os.path.join('flumotion', 'component', 'consumers', 213 'disker', 'status.glade') 214 215 _iters = {} 216
217 - def haveWidgetTree(self):
218 219 def cb_getUIState(state): 220 values = state.get('filelist') 221 self.store.clear() 222 for item in values: 223 self._append(item) 224 if self.rotateTypeLabel: 225 self.rotateTypeLabel.set_text("Rotation: %s" % \ 226 state.get('rotate-type')) 227 self._setCurrentLabel(state) 228 self._setDiskLabel(state)
229 230 self.widget = self.wtree.get_widget('status-widget') 231 self.diskFreeLabel = self.wtree.get_widget('label-free') 232 self.rotateTypeLabel = self.wtree.get_widget('label-rotation') 233 self.currentFilenameLabel = self.wtree.get_widget('label-current') 234 self._buildFilelist() 235 d = self.callRemote("getUIState") 236 d.addCallback(cb_getUIState)
237
238 - def _buildFilelist(self):
239 240 def getGtkColumn(title, text, visible=True, clickable=True): 241 col = gtk.TreeViewColumn(title, 242 gtk.CellRendererText(), 243 text=text) 244 col.set_property('visible', visible) 245 col.set_property('clickable', clickable) 246 col.set_sort_column_id(text) 247 return col
248 249 self.store = gtk.ListStore(str, str, str, str, str) 250 # Sort by time created (default) 251 self.store.set_sort_column_id(0, gtk.SORT_DESCENDING) 252 self.tree = self.wtree.get_widget('treeview-filelist') 253 self.tree.append_column(getGtkColumn('tstamp', 254 COLUMN_TSTAMP, 255 visible=False, 256 clickable=False)) 257 self.tree.append_column(getGtkColumn('Filename', 258 COLUMN_FILENAME)) 259 self.tree.append_column(getGtkColumn('Time created', 260 COLUMN_CREATED)) 261 self.tree.append_column(getGtkColumn('Size in bytes', 262 COLUMN_SIZE)) 263 self.tree.append_column(getGtkColumn('Location', 264 COLUMN_LOCATION)) 265 self.tree.set_rules_hint(True) 266 self.tree.set_model(self.store) 267
268 - def _append(self, item):
269 created = format.formatTimeStamp(time.localtime(item[0])) 270 self._iters[item[0]] = self.store.append([str(item[0]), 271 os.path.basename( 272 str(item[1])), 273 created, 274 str(item[2]), 275 str(item[1])])
276
277 - def _setDiskLabel(self, state):
278 if self.diskFreeLabel: 279 df = state.get('disk-free') 280 if df != None: 281 self.diskFreeLabel.set_text( 282 "Available Disk Space: %s" % df)
283
284 - def _setCurrentLabel(self, state):
285 if self.currentFilenameLabel: 286 self.currentFilenameLabel.set_text("Current filename: %s" % \ 287 state.get("filename"))
288
289 - def stateSet(self, state, key, value):
290 if key == "disk-free": 291 self._setDiskLabel(state) 292 if key == "filename": 293 self._setCurrentLabel(state)
294
295 - def stateAppend(self, state, key, value):
296 if key == 'filelist': 297 self._append(value)
298
299 - def stateRemove(self, state, key, value):
300 if key == 'filelist': 301 iter = self._iters[value[0]] 302 if iter: 303 self.store.remove(iter) 304 self._iters.pop(value[0])
305 306
307 -class DiskerAdminGtk(BaseAdminGtk):
308
309 - def setup(self):
310 filename = FilenameNode(self.state, self.admin, _("Filename")) 311 self.nodes['Filename'] = filename 312 313 status = StatusNode(self.state, self.admin, title=_("Status")) 314 self.nodes['status'] = status 315 316 return BaseAdminGtk.setup(self)
317 318 GUIClass = DiskerAdminGtk 319