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