90
90
# continues to get called
93
## Refactored view class for the current files list
96
class CurrentFilesList:
97
# Liststore & treeview for included directories & files
98
__liststoreList = None
100
# List of indexed directories & files
104
# This method refresh the Liststores from the main treeview
107
# @author Carlos Agra
108
#FIXME Esto sirve para ALGOOOOOOO???????????????????????????????????????????????????????????????????
109
def reloadList(self):
113
self.__itemsAdded = []
114
self.__liststoreList.clear()
115
if self.__proxy.hasSection("Lists"):
116
if self.__proxy.hasOption("Lists","whitelist"):
117
__aux=self.__proxy.getWhiteList()
118
__aux2=__aux.split(";")
121
self.__itemsAdded.append(i)
122
info = self.__proxy.getFileInfo(calendar.timegm(time.localtime()),i)
123
itt = self.__liststoreList.append([i,info[5],info[4],info[9]])
127
# @param wTree The wTree containing the XML tree for the Glade file, passed from the MainPage
128
# @param proxy The dbus-proxy used to connect to the HD Lorean backend
129
# The constructor initializes the ListStore and TreeView components, and loads from the given wTree
130
# to avoid reopening the glade file
132
def __init__(self,wTree,proxy):
134
# Liststore & treeview for included directories & files
135
self.__liststoreList = gtk.ListStore(str,str,str,str)
136
self.__treeviewList = gtk.TreeView (self.__liststoreList)
137
## Treeviews initializations
138
# Prepare the renderers
139
textrenderer = gtk.CellRendererText()
140
# Include initializations
141
self.__treeviewList = wTree.get_widget('treeviewList')
142
self.__treeviewList.set_model(self.__liststoreList)
143
self.__treeviewList.set_headers_visible(True)
145
header, col, renderer = 'Name', 0, textrenderer
146
column = gtk.TreeViewColumn(header, renderer, text=col)
147
column.set_sort_column_id(col)
148
column.set_resizable(True)
149
self.__treeviewList.append_column(column)
151
header, col,renderer = 'Modified', 1, textrenderer
152
column = gtk.TreeViewColumn(header, renderer, text=col)
153
column.set_sort_column_id(col)
154
column.set_resizable(True)
155
self.__treeviewList.append_column(column)
157
header, col, renderer = 'Size', 2, textrenderer
158
column = gtk.TreeViewColumn(header, renderer, text=col)
159
column.set_sort_column_id(col)
160
column.set_resizable(True)
161
self.__treeviewList.append_column(column)
162
# Add number of backups
163
header, col, renderer = 'Backups', 3, textrenderer
164
column = gtk.TreeViewColumn(header, renderer, text=col)
165
column.set_sort_column_id(col)
166
column.set_resizable(True)
167
self.__treeviewList.append_column(column)
169
# dictionary: connects the signals with the Main Window functions
170
dic = {"on_moreInfo_clicked" : self.moreInfo}
171
wTree.signal_autoconnect (dic)
173
#reload current files list
177
# @brief Call from more info button
179
# This method calls HDLorean
182
# @author Roberto Cano Fernandez, Carlos Agra
183
def moreInfo (self,widget):
184
#TODO by Carlos: cuando tengamos el archivo o directorio, pasárselo a TempLine para que muestre su info
185
#De momento sólo llama a la ventana que hizo Tabas
187
# Returns a (TreeModel, TreeIter) tuple
188
model,itt = self.__treeviewList.get_selection().get_selected()
189
selection = self.__liststoreList.get_value(itt, 0)
191
app=TempLine.TempLine()
193
#print "There is no folder selected"
196
94
## Dual paned view containing all files recoverable through HD lorean
200
98
class AllFilesList:
202
100
# Paths TreeStore and treeview
101
__pathTreeStore = None
204
102
__pathTreeView = None
105
##@brief Rows expanded.
109
##@brief Path row selected
112
__pathRowSelected = None
113
##@brief Rows selected by the user.
206
117
# For a file, snapshots information ListStore and TreeView
207
backupsListStore = None
208
backupsTreeView = None
118
__backupsListStore = None
119
__backupsTreeView = None
121
##@brief List of paths passed to Preferences constructor to refresh properly.
210
# For inDepth algorithm
125
# For __inDepth algorithm
212
TARGETS = [('MY_TREE_MODEL_ROW', gtk.TARGET_SAME_WIDGET, 0),('text/plain', 0, 1),('TEXT', 0, 2),('STRING', 0, 3),]
213
TARGETS2 = [('MY_TREE_MODEL_ROW', gtk.TARGET_SAME_WIDGET, 0),('text/uri-list', 0, 0),('TEXT', 0, 2),('STRING', 0, 3),]
127
##@brief Type of targets for the drag'n drop.
130
__targets = [('MY_TREE_MODEL_ROW', gtk.TARGET_SAME_WIDGET, 0),('text/plain', 0, 1),('TEXT', 0, 2),('STRING', 0, 3),]
131
__backupsForLabel = None
132
__selectedFileLabel = None
134
##@brief Constructor.
137
# @param wTree The wTree containing the XML tree for the Glade file, passed from the MainPage
138
# @param proxy The dbus-proxy used to connect to the HD Lorean backend
139
# The constructor initializes the ListStore and TreeView components, and loads from the given wTree
140
# to avoid reopening the glade file
141
def __init__(self,wTree,proxy,main):
144
self.refreshTree(wTree,proxy,True)
146
##@brief gets the backupliststore.
149
# @return returns the backupsliststore object
150
# @author Daniel Tabas
151
def getBackupsListStore(self):
152
return self.__backupsListStore
154
##@brief gets the backupstreeview.
157
# @return returns the backupstreeview object
158
# @author Daniel Tabas
159
def getBackupsTreeView(self):
160
return self.__backupsTreeView
214
162
##@brief Populate __dicTree with backward recursivity
217
def processPath(self,path):
165
# @param path path which is being processed.
166
def __processPath(self,path):
218
167
parent, name = os.path.split(path)
220
self.processPath(parent)
169
self.__processPath(parent)
221
170
if path not in self.__dicTree:
222
171
if os.path.isfile(path):
223
self.__dicTree[path] = self.pathTreeStore.append(self.__dicTree[parent],[self.get_icon_pixbuf('STOCK_FILE'),name,path])
225
self.__dicTree[path] = self.pathTreeStore.append(self.__dicTree[parent],[self.get_icon_pixbuf('STOCK_DIRECTORY'),name,path])
172
self.__dicTree[path] = self.__pathTreeStore.append(self.__dicTree[parent],[self.__get_icon_pixbuf('STOCK_FILE'),name,path])
173
elif os.path.isdir(path):
174
self.__dicTree[path] = self.__pathTreeStore.append(self.__dicTree[parent],[self.__get_icon_pixbuf('STOCK_DIRECTORY'),name,path])
176
self.__dicTree[path] = self.__pathTreeStore.append(self.__dicTree[parent],[self.__get_icon_pixbuf('STOCK_SAVE'),name,path])
227
178
if path not in self.__dicTree:
228
179
if os.path.isfile(path):
229
self.__dicTree[path] = self.pathTreeStore.append(None,[self.get_icon_pixbuf('STOCK_FILE'),parent,path])
180
self.__dicTree[path] = self.__pathTreeStore.append(None,[self.__get_icon_pixbuf('STOCK_FILE'),parent,path])
181
elif os.path.isdir(path):
182
self.__dicTree[path] = self.__pathTreeStore.append(None,[self.__get_icon_pixbuf('STOCK_DIRECTORY'),parent,path])
231
self.__dicTree[path] = self.pathTreeStore.append(None,[self.get_icon_pixbuf('STOCK_DIRECTORY'),parent,path])
184
self.__dicTree[path] = self.__pathTreeStore.append(None,[self.__get_icon_pixbuf('STOCK_SAVE'),parent,path])
233
186
##@brief Buid the file tree of monitorized system
236
def inDepth(self,list):
190
def __inDepth(self,list):
237
191
self.__dicTree = {}
238
192
for entry in list:
239
self.processPath(entry[0])
193
self.__processPath(entry[0])
195
##@brief Refresh the treeview of the left.
244
# @param wTree The wTree containing the XML tree for the Glade file, passed from the MainPage
245
# @param proxy The dbus-proxy used to connect to the HD Lorean backend
246
# The constructor initializes the ListStore and TreeView components, and loads from the given wTree
247
# to avoid reopening the glade file
248
def __init__(self,wTree,proxy):
249
self.refreshTree(wTree,proxy,True)
198
# @param wTree The glade object.
199
# @param proxy Dbus proxy to access to backend functions.
200
# @param first Flag to show the function if it's the first time call.
251
201
def refreshTree(self,wTree,proxy,first):
252
self.backupsForLabel = wTree.get_widget("backupsForLabel")
253
self.selectedFileLabel = wTree.get_widget("selectedFileLabel")
202
self.__backupsForLabel = wTree.get_widget("backupsForLabel")
203
self.__selectedFileLabel = wTree.get_widget("selectedFileLabel")
255
self.pathTreeStore = gtk.TreeStore(gtk.gdk.Pixbuf, str,str)
205
self.__pathTreeStore = gtk.TreeStore(gtk.gdk.Pixbuf, str,str)
256
206
self.__pathTreeView = wTree.get_widget("pathTreeView")
257
self.__pathTreeView.set_model(self.pathTreeStore)
207
self.__pathTreeView.set_model(self.__pathTreeStore)
259
self.backupsListStore = gtk.ListStore(str,str,str,str,int,str)
260
self.backupsTreeView = wTree.get_widget("snapshotsTreeView")
261
self.backupsTreeView.set_reorderable(False)
262
self.backupsTreeView.set_model(self.backupsListStore)
209
self.__backupsListStore = gtk.ListStore(str,str,str,str,int,str)
210
self.__backupsTreeView = wTree.get_widget("snapshotsTreeView")
211
self.__backupsTreeView.set_reorderable(False)
212
self.__backupsTreeView.set_model(self.__backupsListStore)
213
self.__backupsTreeView.set_rubber_banding(True)
214
self.__backupsTreeView.get_selection().set_mode(gtk.SELECTION_MULTIPLE)
263
216
#Enable the selection callbacks
264
217
__pathSel = self.__pathTreeView.get_selection()
265
218
__pathSel.connect('changed', self.on_pathTree_selection_changed)
267
__snapshotSel = self.backupsTreeView.get_selection()
220
__snapshotSel = self.__backupsTreeView.get_selection()
268
221
__snapshotSel.connect('changed', self.on_snapshotList_selection_changed)
270
223
#TODO refactor to use TreeViewColumn and append_column
271
224
# create the TreeViewColumn to display the data
273
self.__pathTreeView.enable_model_drag_source( gtk.gdk.BUTTON1_MASK,self.TARGETS,gtk.gdk.ACTION_DEFAULT|gtk.gdk.ACTION_MOVE)
274
self.__pathTreeView.enable_model_drag_dest(self.TARGETS,gtk.gdk.ACTION_DEFAULT)
275
self.__pathTreeView.connect("drag_data_received",self.drag_data_received_data)
276
self.backupsTreeView.enable_model_drag_source( gtk.gdk.BUTTON1_MASK,self.TARGETS2,gtk.gdk.ACTION_DEFAULT|gtk.gdk.ACTION_MOVE)
277
self.backupsTreeView.enable_model_drag_dest(self.TARGETS2,gtk.gdk.ACTION_DEFAULT)
278
self.backupsTreeView.drag_source_set(gtk.gdk.BUTTON1_MASK, [ ( "text/plain", 0, 80 ) ], gtk.gdk.ACTION_COPY)
279
self.backupsTreeView.connect("drag_data_get", self.drag_data_get_data)
280
#FIXME by Karl: aqui es donde se puede estar paqueteando si fallan los iconos
226
self.__pathTreeView.enable_model_drag_source( gtk.gdk.BUTTON1_MASK,self.__targets,gtk.gdk.ACTION_DEFAULT|gtk.gdk.ACTION_MOVE)
227
self.__pathTreeView.enable_model_drag_dest(self.__targets,gtk.gdk.ACTION_DEFAULT)
228
self.__pathTreeView.connect("drag_data_received",self.dragDataReceivedData)
229
self.__pathTreeView.connect("row-expanded",self.rowExpanded)
230
self.__pathTreeView.connect("row-collapsed",self.rowCollapsed)
231
self.__pathTreeView.connect("button-press-event",self.pathPressCb)
232
self.__backupsTreeView.connect("button-press-event",self.buttonPressCb)
281
233
self.__pathCol = gtk.TreeViewColumn('Path')
282
234
render_pixbuf = gtk.CellRendererPixbuf()
283
235
self.__pathCol.pack_start(render_pixbuf, False)
296
248
self.__pathCol.pack_start(self.__pathCell, True)
298
250
# set the cell "text" attribute to column 0 - retrieve text
299
# from that column in pathTreeStore
300
self.__pathCol.add_attribute(self.__pathCell, 'text', 0)
251
# from that column in __pathTreeStore
252
# FIXME by Karl: eliminating Bug #212765 by deleting this instruction. La dejo comentada un tiempo por si acaso
253
#self.__pathCol.add_attribute(self.__pathCell, 'text', 0)
301
254
self.__snapshotsCol = gtk.TreeViewColumn('ID',gtk.CellRendererText(), text=0)
302
self.backupsTreeView.append_column(self.__snapshotsCol)
255
self.__backupsTreeView.append_column(self.__snapshotsCol)
305
258
self.__snapshotsCol = gtk.TreeViewColumn('Date',gtk.CellRendererText(), text=1)
306
self.backupsTreeView.append_column(self.__snapshotsCol)
259
self.__backupsTreeView.append_column(self.__snapshotsCol)
308
261
self.__snapshotsCol = gtk.TreeViewColumn('Size',gtk.CellRendererText(), text=2)
309
self.backupsTreeView.append_column(self.__snapshotsCol)
262
self.__backupsTreeView.append_column(self.__snapshotsCol)
312
265
self.__snapshotsCol = gtk.TreeViewColumn('Operation',gtk.CellRendererText(), text=3)
313
self.backupsTreeView.append_column(self.__snapshotsCol)
266
self.__backupsTreeView.append_column(self.__snapshotsCol)
315
268
self.__proxy = proxy
316
269
rootDir = self.__proxy.getCompleteDirList("/")
317
self.inDepth(rootDir)
270
self.__inDepth(rootDir)
272
self.__selectOldPath()
274
## @brief Callback to the signal press button in the right treeview, in order to popup a menu.
280
# @return returns a boolean, to stop propagating the signal(para que no deseleccione vamos).
281
# @author Daniel Tabas
282
def buttonPressCb(self,widget,event):
283
if event.button == 3:
284
self.__menu1 = gtk.Menu()
285
menuItem = gtk.ImageMenuItem('Restore')
286
img = gtk.image_new_from_stock(gtk.STOCK_UNDO, gtk.ICON_SIZE_MENU)
287
menuItem.set_image(img)
288
menuItem.connect('activate', self.restCb,"Restore")
289
self.__menu1.append(menuItem)
290
menuItem = gtk.ImageMenuItem('Delete')
291
img = gtk.image_new_from_stock(gtk.STOCK_DELETE, gtk.ICON_SIZE_MENU)
292
menuItem.set_image(img)
293
menuItem.connect('activate', self.delCb,"Delete")
294
self.__menu1.append(menuItem)
295
self.__menu1.show_all()
296
self.__menu1.popup(None, None, None, 3, event.time)
299
## @brief Callback to the signal press button in the right treeview, in order to popup a menu.
305
# @return returns a boolean, to stop propagating the signal(para que no deseleccione vamos).
306
# @author Daniel Tabas
307
def pathPressCb(self,widget,event):
308
if event.button == 3:
309
self.__menu1 = gtk.Menu()
310
menuItem = gtk.ImageMenuItem('Make Backup')
311
img = gtk.image_new_from_stock(gtk.STOCK_SAVE, gtk.ICON_SIZE_MENU)
312
menuItem.set_image(img)
313
menuItem.connect('activate', self.backupCb,"Make Backup")
314
self.__menu1.append(menuItem)
315
self.__menu1.show_all()
316
self.__menu1.popup(None, None, None, 3, event.time)
319
## @brief Callback to save menu item
324
# @author Daniel Tabas
325
def backupCb(self,widget, data = None):
327
self.__main.saveBackup(self.__wTree)
329
## @brief Callback to restore menu item
334
# @author Daniel Tabas
335
def restCb(self,widget, data = None):
337
self.__main.restWithoutOver(self.__wTree)
339
## @brief Callback to delete menu item
344
# @author Daniel Tabas
345
def delCb(self,widget, data = None):
347
self.__main.deleteOne(self.__wTree)
350
## @brief Method that re-expand the rows that where expanded before the treeview collapsed
353
# @author Carlos Agra
354
def __expandPaths(self):
355
for i in self.__rowsExpanded:
356
self.__pathTreeView.expand_to_path(i)
358
## @brief Method that re-select the row that was selected before the treeview collapsed
361
# @author Carlos Agra
362
def __selectOldPath(self):
363
if self.__pathRowSelected != None:
364
self.__pathTreeView.get_selection().select_path(self.__pathRowSelected)
319
366
#FIXME by Karl: método copy paste de otra aplicacion, para hacer trastadas con iconos
320
367
## Select an icon from the stock items of gtk
323
370
# @param stock The concrete icon from the stock that we will return
324
def get_icon_pixbuf(self, stock):
371
def __get_icon_pixbuf(self, stock):
325
372
return self.__pathTreeView.render_icon(stock_id=getattr(gtk, stock),
326
373
size=gtk.ICON_SIZE_MENU,
329
## update the listModel containing the snapshots info
376
## @brief update the listModel containing the snapshots info.
332
# @param selected The selected file path, given in a string
334
# For a given path, it checks through the proxy and updates the shown info, activating
378
#For a given path, it checks through the proxy and updates the shown info, activating
335
379
# the label if we have information to show as to provide some feedback.
382
# @param selected The selected file path, given in a string.
336
383
# @author Carlos Agra
337
384
def updateSnapshotModel(self,selected):
338
385
historical = self.__proxy.getHistorical(selected)
339
self.backupsListStore.clear()
386
self.__backupsListStore.clear()
341
self.backupsForLabel.set_sensitive(True)
342
self.selectedFileLabel.set_sensitive(True)
388
self.__backupsForLabel.set_sensitive(True)
389
self.__selectedFileLabel.set_sensitive(True)
344
391
for backup in historical:
345
392
sizeOfBackup = self.convertHumanReadable(backup[4])
346
self.backupsListStore.append([str(id),backup[5],sizeOfBackup,backup[6],backup[-1],backup[1]])
393
self.__backupsListStore.append([str(id),backup[5],sizeOfBackup,backup[6],backup[-1],backup[1]])
349
## convert a given bytes size to human readable size
396
## @brief Convert a given bytes size to human readable size.
352
# @param size The size to convert
399
# @param size The size to convert.
353
400
# @author Carlos Agra
354
401
def convertHumanReadable(self,size):
355
402
size = long(size)
357
409
size = size / 1024.0
363
while size[i] != '.':
366
tam = tam + size [i] + size [i+1]
372
while size[i] != '.':
375
tam = tam + size [i] + size [i+1]
413
while size[i] != '.':
416
tam = tam + size [i] + size [i+1]
379
size = str(size) + ' KB'
422
while size[i] != '.':
425
tam = tam + size [i] + size [i+1]
382
## Callback for a selection changed event in the paths tree
429
## @brief Callback for a selection changed event in the paths tree.
384
431
# When a selection in the treeView is changed, we get the file path and update the snapshots shown for it.
385
434
# @param selection The new GTK selection object
386
435
def on_pathTree_selection_changed(self, selection):
387
436
model, selection_iter = selection.get_selected()
389
self.backupsForLabel.set_sensitive(False)
390
self.selectedFileLabel.set_sensitive(False)
437
self.__backupsForLabel.set_sensitive(False)
438
self.__selectedFileLabel.set_sensitive(False)
392
440
if (selection_iter and model):
393
441
#Something is selected so get the object
394
selected = model.get_value(selection_iter, 1)
442
selected = model.get_value(selection_iter, 2)
395
443
#updated selected info on the right pane
396
self.selectedFileLabel.set_text(selected)
444
self.__selectedFileLabel.set_text(selected)
397
445
selected = model.get_value(selection_iter, 2)
446
self.__nPath = selected
398
447
self.updateSnapshotModel(selected)
448
#We store the selected row to restore it later
449
self.__pathRowSelected = model.get_path(selection_iter)
451
j=len(self.__pathRowSelected)
453
#Converting path to GtkTreePath
455
number = str(self.__pathRowSelected[i])
457
number = number + ":"
458
newPath = newPath + number
460
self.__pathRowSelected = newPath
400
self.selectedFileLabel.set_text("")
462
self.__selectedFileLabel.set_text("")
402
## Callback for a selection changed event in the snapshots tree
404
# When we select a file... (TODO)
405
# @param selection The new GTK selection object
467
## brief Callback for a selection changed event in the snapshots tree.
469
#This function stores the paths of the rows of the liststore which has been
470
#selected by the user.
473
# @param selection The new GTK selection object.
474
# @author Daniel Tabas
406
475
def on_snapshotList_selection_changed(self,selection):
407
model, selection_iter = selection.get_selected()
476
self.__rowsSelected = []
477
self.__rowsSelected = selection.get_selected_rows()[1]
480
## @brief getter for the __rowsSelected atribute
483
# @return It returns a list of paths of the selected rows.
484
# @author Daniel Tabas
485
def getRowsSelected(self):
486
return self.__rowsSelected
488
## @brief Getter of a field of one of the selected rows.
491
# @param row Integer to access to the __rowSelected list.
492
# @param element Field of the row.
493
# @return It returns the field selected of the row.
494
# @author Daniel Tabas
495
def getColumnSelected(self,row,element):
496
return self.__backupsTreeView.get_model().get_value(self.__backupsTreeView.get_model().get_iter(self.__rowsSelected[row]),element)
410
498
## @brief Method called when the drag_data_received event is captured, in order to do some drag & drop.
433
521
l1=lista.replace('\n',"").replace('\t',"")
434
522
self.__proxy.setWhiteList(l1.encode("utf-8","strict"))
437
def drag_data_get_data(self, widget, context, selection, targetType, eventTime):
444
print selection.target
445
## TODO http://www.pygtk.org/docs/pygtk/class-gtkselectiondata.html
447
print selection.get_uris()
448
print selection.get_targets()
449
selection.set(selection.target, 8, str)
452
## Returns the path dragged into the treeview
525
## @brief Method called when a row in the path treeview is expanded, to store the information.
528
# @param treeview treeview in wich we capture row_expanded event
529
# @param iter the iter of the row that is expanded
530
# @param path the path that is expanded
531
# @author Carlos Agra
532
def rowExpanded(self,treeview, iter, path):
537
number = str(path[i])
539
number = number + ":"
540
newPath = newPath + number
542
isInList = self.__rowsExpanded.count(newPath)
544
self.__rowsExpanded.append(newPath)
546
## @brief Method called when a row in the path treeview is Collapsed, to store the information.
549
# @param treeview treeview in wich we capture row_expanded event
550
# @param iter the iter of the row that is expanded
551
# @param path the path that is expanded
552
# @author Carlos Agra
553
def rowCollapsed(self,treeview, iter, path):
558
number = str(path[i])
560
number = number + ":"
561
newPath = newPath + number
563
self.__rowsExpanded.remove(newPath)
565
for item in self.__rowsExpanded:
566
if item.startswith(newPath):
567
itemsToDelete.append(item)
568
for item in itemsToDelete:
569
self.__rowsExpanded.remove(item)
573
## @brief Returns the path dragged into the treeview.
455
576
# @return Returns an string with the path dragged
524
644
"on_imagemenuAbout_activate" : self.about,
525
645
"on_imagemenuHelp_activate" : self.help,
526
646
"on_toolHelp_clicked" : self.help,
527
"on_mainPage_destroy" : self.destroyWind,
528
"on_imagemenuDBLog_activate" : self.dbLog,
647
"on_mainPage_destroy" : self.destroyWind
530
649
#connect class signals using the given dictionary
531
650
self.wTree.signal_autoconnect (dic)
532
651
self.window=self.wTree.get_widget('mainPage')
534
#TODO añadir funcionalidad, aqui se iniciaria la ventana de debug
535
def __handlerUnexpected(self,trace):
536
app=DebugWindow.DebugWindow(trace)
538
def __handlerRefresh(self,a):
653
## @brief Shows information related to HDLorean in a popup
656
# @param messages the list of messages to show, where messages[0] will be the title and the remaining elements the paths modified
657
# @author Carlos Agra
659
def showMessage(self,messages):
660
if pynotify.init("HD Lorean notify"):
661
numMessages=len(messages)
665
while i != numMessages:
666
paths = paths + messages[i]
667
if i != numMessages -1:
670
n = pynotify.Notification(messages[0], paths,gtk.STOCK_INFO)
671
n.attach_to_status_icon(self.__sysTrayIcon)
674
print "there was a problem initializing the pynotify module"
677
## @brief Handler for the unexpected exit signal.
680
# @param trace string with the trace to show in the debug window.
681
# @author Daniel Tabas
682
def __handlerUnexpected(self,trace):
683
strtrace="python ./InitDebug.py " +'"' +str(trace)+'"'
684
tr = strtrace.replace('\n'," linea")
687
## @brief Handler for the refresh signal.
690
# @author Daniel Tabas
691
def __handlerRefresh(self):
539
692
self.__allFilesList.refreshTree(self.wTree,self.__proxy,False)
694
## @brief Function that creates the systray icon.
697
# @author Daniel Tabas
541
698
def __initDaemon(self):
542
699
if self.__daemonStarted==False:
543
700
self.__sysTrayIcon = gtk.StatusIcon()
544
701
#gtk menu of the systray icon
545
702
self.__menu = gtk.Menu()
546
menuItem = gtk.ImageMenuItem(gtk.STOCK_STOP)
547
menuItem.connect('activate', self.stop, self.__sysTrayIcon)
548
self.__menu.append(menuItem)
549
menuItem = gtk.ImageMenuItem(gtk.STOCK_QUIT)
550
menuItem.connect('activate', self.quit_cb, self.__sysTrayIcon)
551
self.__menu.append(menuItem)
552
self.__sysTrayIcon.connect('activate', self.activate_icon_cb, self.__sysTrayIcon)
553
self.__sysTrayIcon.connect('popup-menu', self.popup_menu_cb, self.__menu)
703
menuItem = gtk.ImageMenuItem('Close')
704
img = gtk.image_new_from_stock(gtk.STOCK_QUIT, gtk.ICON_SIZE_MENU)
705
menuItem.set_image(img)
706
menuItem.connect('activate', self.quitCb, self.__sysTrayIcon)
707
self.__menu.append(menuItem)
708
menuItem = gtk.ImageMenuItem('Stop Daemon and Exit')
709
img = gtk.image_new_from_stock(gtk.STOCK_STOP, gtk.ICON_SIZE_MENU)
710
menuItem.set_image(img)
711
menuItem.connect('activate', self.stopCb, self.__sysTrayIcon)
712
self.__menu.append(menuItem)
713
self.__sysTrayIcon.connect('activate', self.activateIconCb, self.__sysTrayIcon)
714
self.__sysTrayIcon.connect('popup-menu', self.popupMenuCb, self.__menu)
554
715
self.__sysTrayIcon.set_from_file("../../share/images/HDLoreanHumo.png")
555
716
self.__sysTrayIcon.set_visible(True)
556
717
self.__sysTrayIcon.set_tooltip("HD Lorean Icon")
557
718
self.__daemonStarted=True
560
# TODO modificar estas funciones
561
#################################################################################
563
def delete_cb(self,widget, event, data = None):
565
data.set_blinking(True)
568
def quit_cb(self,widget, data = None):
720
## @brief handler for the quit menu.
725
# @author Daniel Tabas
726
def quitCb(self,widget, data = None):
570
728
self.close(widget)
572
def stop(self,widget,data = None):
730
## @brief handler for the stop menu.
735
# @author Daniel Tabas
736
def stopCb(self,widget,data = None):
574
738
self.quit(widget)
576
def popup_menu_cb(self,widget, button, time, data = None):
741
## @brief handler for the left button press in the systray icon.
748
# @author Daniel Tabas
749
def popupMenuCb(self,widget, button, time, data = None):
580
753
data.popup(None, None, None, 3, time)
583
def activate_icon_cb(self,widget, data = None):
757
## @brief handler for the stop menu.
762
# @author Daniel Tabas
763
def activateIconCb(self,widget, data = None):
585
765
if not self.window.get_property("visible"):
586
766
self.window.destroy()
601
780
# @return nothing
602
781
# @author Roberto Cano.
603
782
def putPercentage(self,oper, perc):
604
self.wTree.get_widget('mainPageStatus').pop(0)
605
self.wTree.get_widget('mainPageStatus').push(0,"Porcentage of "+oper+" operation is: "+str(perc)+" %.")
607
#Functions of main page, they are calls to the other windows of HD Lorean
609
# @brief Open the DataBase Log Window
611
# This method calls DataBase Log Window
614
# @author Carlos Agra
615
def dbLog (self,widget):
618
# @brief Call from more info button
620
# This method calls HDLorean
623
# @author Roberto Cano Fernandez, Carlos Agra
624
def moreInfo (self,widget):
625
#TODO by Carlos: cuando tengamos el archivo o directorio, pasárselo a TempLine para que muestre su info
626
#De momento sólo llama a la ventana que hizo Tabas
628
# Returns a (TreeModel, TreeIter) tuple
629
model,itt = self.__treeviewList.get_selection().get_selected()
630
selection = self.__liststoreList.get_value(itt, 0)
631
app=TempLine.TempLine(selection)
633
# print "There is no folder selected"
783
if ((oper>=0) or (oper <=100)):
784
self.wTree.get_widget('mainPageStatus').pop(0)
785
self.wTree.get_widget('mainPageStatus').push(0,"Porcentage of "+oper+" operation is: "+str(perc)+" %.")
788
## @brief Close the app.
642
794
def close(self,widget):
643
795
app=Close.Close()
798
## @brief Setter for the ntimespref atribute
801
# @param nTimes integer to set.
802
# @author Daniel Tabas
645
803
def setNTimesPref(self,nTimes):
646
804
self._nTimesPref=nTimes
807
## @brief Init for the preferences window.
651
# @param __nTimesPref Bugfix
811
# @param __nTimesPref Flag to refresh correctly.
812
# @author Carlos Agra
654
813
def preferences(self,widget):
655
# TODO Try for this method, waiting for dbus messages...
656
self.putPercentage("preferencias", 50)
657
814
app=Preferences.Preferences(self.__nTimesPref,self.__allFilesList.get_path())
658
815
self.__allFilesList.set_empty()
659
816
self.__nTimesPref=self.__nTimesPref+1
819
## @brief Function that deletes one o more versions of a file.
824
# @author Carlos Agra, Daniel Tabas
668
825
def deleteOne(self,widget):
669
826
self.wTree.get_widget('mainPageStatus').pop(0)
670
827
self.wTree.get_widget('mainPageStatus').push(0,"Delete One Version")
671
app=DeleteOne.DeleteOne()
828
index = self.__allFilesList.getRowsSelected()
831
for i in range(0,len(index)):
832
init_timestamp = self.__allFilesList.getColumnSelected(i,4)
833
path = self.__allFilesList.getColumnSelected(i,5)
834
tempPath.append(path)
835
finalpath = self.__proxy.deleteVersions(path,init_timestamp,0)
836
self.__allFilesList.updateSnapshotModel(path)
837
self.__allFilesList.refreshTree(self.wTree,self.__proxy,False)
838
self.wTree.get_widget('mainPageStatus').push(0,"Delete OK!")
839
self.showMessage(['HD Lorean','Delete OK of:']+tempPath)
841
self.wTree.get_widget('mainPageStatus').push(0,"Please select one row to be deleted")
843
## @brief Stop the daemon and exit.
679
849
def quit(self,widget):
680
850
#self.__proxy.stopDaemon()
681
851
app=CloseAndStop.CloseAndStop(self.__proxy)
703
873
def restWithoutOver(self,widget):
704
874
#aqui ira la llamada a lo del porcentaje
705
875
# ni guarra de si esto funcionaria asi
706
#FIXME if (ipath is None) or (idir is None) or (itime is None):
707
model,itt = self.__allFilesList.backupsTreeView.get_selection().get_selected()
708
if (model is not None) and (itt is not None):
709
timestamp = self.__allFilesList.backupsListStore.get_value(itt, 4)
710
path = self.__allFilesList.backupsListStore.get_value(itt, 5)
711
dialog = gtk.FileChooserDialog("Recover path", None, gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER,(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, gtk.RESPONSE_OK))
712
dialog.set_current_folder(os.environ['HOME'])
713
# if there's no input path or input directory to restore open the choose dialog (menu button was pressed)
715
if dialog.run() == gtk.RESPONSE_OK:
876
#FIXME if (ipath is None) or (idir is None) or (itime is None):
877
self.wTree.get_widget('mainPageStatus').pop(0)
878
index = self.__allFilesList.getRowsSelected()
880
dialog = gtk.FileChooserDialog("Recover path", None, gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER,(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, gtk.RESPONSE_OK))
881
dialog.set_current_folder(os.environ['HOME'])
882
if dialog.run() == gtk.RESPONSE_OK:
716
883
directory = dialog.get_filename()
718
finalpath = self.__proxy.recoverBackups(timestamp,[path],directory)
719
os.system("xdg-open '"+finalpath+"'")
886
self.wTree.get_widget('mainPageStatus').push(0,"Restore cancelled")
722
887
#directory = None
726
#FIXME finalpath=self.__proxy.recoverBackups(itime,[ipath],idir)
890
for i in range(0,len(index)):
891
self.wTree.get_widget('mainPageStatus').push(0,"Restoring...")
892
timestamp = self.__allFilesList.getColumnSelected(i,4)
893
path = self.__allFilesList.getColumnSelected(i,5)
894
# if there's no input path or input directory to restore open the choose dialog (menu button was pressed)
895
finalpath = self.__proxy.recoverBackups(timestamp,[path],directory)
896
os.system("xdg-open '"+finalpath+"'")
897
self.wTree.get_widget('mainPageStatus').push(0,"Restore OK!")
898
self.showMessage(['HD Lorean','Restore succesful of:',path])
729
899
#return directory
902
self.wTree.get_widget('mainPageStatus').push(0,"Please select a row of the list")
904
#FIXME finalpath=self.__proxy.recoverBackups(itime,[ipath],idir)