Initial commit (Vesion 0.1)
[tablet-suite] / src / backup / .svn / text-base / pcsbackupmanagerui.py.svn-base
1 # Software License: GPL
2
3 import os
4 import sys
5
6 from functools import partial
7
8 from PyQt4.QtCore import *
9 from PyQt4.QtGui import *
10
11 from ui.pcsuiutils import *
12 from ui.tsuigeneralmethods import *
13 from ui.pcsapp import PcsApp
14 from backup.pcsbackuputils import *
15
16 from pcsbackuplistui import PCSBackupListUi
17 from pcspcbackupmanager import PcsPcBackupManager
18 from pcsdevicebackupmanager import PcsDeviceBackupManager
19 from pcsprogressdialog import PcsProgressDialog
20 from style.styleTabletSuite import *
21
22 COPY_BUTTON_ID = 0
23 DELETE_BUTTON_ID = 1
24 RENAME_BUTTON_ID = 2
25 VIEW_BUTTON_ID = 3
26 _home_dir = os.path.expanduser("~")
27 _default_dir = _home_dir + "/.pcsuite/Backup"
28
29
30 class PcsBackupManagerUi(QDialog):
31     
32     ''' Class that calls a Backup Pc Suite application
33         with a Table Viewer'''
34
35     def __init__(self, deviceInfo, windowManager, parent=None):
36         QDialog.__init__(self, parent)
37         self.deviceInfo = deviceInfo
38         self.windowManager = windowManager
39         
40         self.setWindowIcon(QIcon(BACKUP_IMAGE))
41         self.setWindowTitle("%s Backup Manager" % APPLICATION_NAME)
42         self.setFixedSize(WINDOW_WIDTH, WINDOW_HEIGHT)
43         self._home_dir = os.path.expanduser("~")
44         self._default_dir = _home_dir + "/.pcsuite/Backup"
45         self.copyPath = self._default_dir
46         self.name_change = None
47         self._setupUi()
48         
49     def _setupUi(self):
50         # Creates the lists
51         self.pcBackupManager = PcsPcBackupManager()
52         self.deviceBackupManager = PcsDeviceBackupManager(self.deviceInfo)
53
54         self.pcListView = PCSBackupListUi(self.pcBackupManager)
55         self.pcListView.setObjectName("ListView")
56         # "Update pc list view"
57         pcListViewSelectionModel = self.pcListView.selectionModel()
58         self.connect(pcListViewSelectionModel, 
59                      SIGNAL("selectionChanged(QItemSelection, QItemSelection)"),
60                      self._updateButtonsState)
61         self.pcListView.updateBackupList()
62         
63         self.deviceListView = PCSBackupListUi(self.deviceBackupManager)
64         self.deviceListView.setObjectName("ListView")
65         deviceListViewSelectionModel = self.deviceListView.selectionModel()
66         self.connect(deviceListViewSelectionModel, 
67                      SIGNAL("selectionChanged(QItemSelection, QItemSelection)"), 
68                      self._updateButtonsState)
69         # "Update device List view"
70         self.deviceListView.updateBackupList()
71         
72         layout = QVBoxLayout()
73         menuLayout = self._menuButtons()
74         layout.addLayout(menuLayout, Qt.AlignTop)
75         wayLayout = self._wayLayout()
76         layout.addLayout(wayLayout, Qt.AlignLeft)
77         layout.addItem(QSpacerItem(0,3))
78         layout.addLayout(self._centerLayout(), Qt.AlignTop)
79
80         layout.addItem(QSpacerItem(0,15))
81         informationLayout = self._createInformationsLabel()
82         layout.addLayout(informationLayout)
83         layout.addItem(QSpacerItem(0,2))
84         self.setLayout(layout)
85     
86     def _centerLayout(self):
87         # Creates the tabs
88         layout = QVBoxLayout()
89         tabLayout = QVBoxLayout()
90         tab = QTabBar()
91         tab.setObjectName("managerTabs")
92         self.tabBar = QTabWidget()
93         self.tabBar.setTabBar(tab)
94         self.tabBar.setAttribute(Qt.WA_NoSystemBackground)
95         self.tabBar.setObjectName("tabBar")
96         self.tabBar.addTab(self.pcListView, "PC Backups")
97         self.tabBar.addTab(self.deviceListView, "Device Backups")
98         self.connect(self.tabBar, SIGNAL("currentChanged(int)"), self._updateButtonsState)
99         tabLayout.addWidget(self.tabBar)
100         layout.addLayout(tabLayout)
101         #Spacer
102         layout.addItem(QSpacerItem(0,5))        
103         # Creates the buttons
104         buttonBox = QHBoxLayout()
105         self._buttonCopy = QPushButton("Copy")
106         self._buttonCopy.setDisabled(True)
107         self._buttonCopy.setStyleSheet(DEFAULT_BUTTON_STYLE)
108         buttonBox.addWidget(self._buttonCopy)
109         self.connect (self._buttonCopy, SIGNAL("clicked()"), self._doCopyBackup)
110         
111         self._buttonDelete = QPushButton("Delete")
112         self._buttonDelete.setDisabled(True)
113         buttonBox.addWidget(self._buttonDelete)
114         self._buttonDelete.setStyleSheet(DEFAULT_BUTTON_STYLE)
115         self.connect (self._buttonDelete, SIGNAL("clicked()"), self._doDeleteBackup)
116         
117         self._buttonRename = QPushButton("Rename")
118         self._buttonRename.setDisabled(True)
119         buttonBox.addWidget(self._buttonRename)
120         self._buttonRename.setStyleSheet(DEFAULT_BUTTON_STYLE)
121         self.connect (self._buttonRename, SIGNAL("clicked()"), self._doRenameBackup)
122         
123         self._buttonView = QPushButton("View")
124         self._buttonView.setDisabled(True)
125         buttonBox.addWidget(self._buttonView)
126         self._buttonView.setStyleSheet(DEFAULT_BUTTON_STYLE)
127         self.connect (self._buttonView, SIGNAL("clicked()"), self._doViewBackup)
128         
129         self._buttonUpdate = QPushButton("Update")
130         self._buttonUpdate.setDisabled(False)
131         self._buttonUpdate.setVisible(False)
132         buttonBox.addWidget(self._buttonUpdate)
133         self._buttonUpdate.setStyleSheet(DEFAULT_BUTTON_STYLE)
134         self.connect (self._buttonUpdate, SIGNAL("clicked()"), self._doUpdateList)
135         
136         layout.addLayout(buttonBox)
137         return layout
138         
139     def _menuButtons(self):
140         infList = [("New Backup", SMALL_ICON_NEW_BACKUP_STYLE, self._newBackupDialog), 
141                    ("Manage Backup", SMALL_ICON_MANAGER_BACKUP_STYLE_SELECTED),
142                    ("Restore Backup", SMALL_ICON_RESTORE_BACKUP_STYLE, self._restoreDialog)]
143         
144         buttonsLayout = QHBoxLayout()
145         for i in range(3):
146             but = QPushButton(infList[i][0])
147             but.setStyleSheet(infList[i][1])
148             if i <> 1:
149                 buttonsLayout.addWidget(but, Qt.AlignLeft)
150                 self.connect(but, SIGNAL("clicked()"), infList[i][2])
151             else:
152                 buttonsLayout.addWidget(but)
153         buttonsLayout.setMargin(0)
154         return buttonsLayout    
155     
156     def _newBackupDialog(self):
157         if(self.deviceInfo and self.deviceInfo.ip != None):
158             newBackup = self.windowManager.getNewBackup()
159             centralize(newBackup)
160             newBackup.setGeometry(self.geometry())
161             newBackup.show()
162             self.close()
163         else:
164             self._showNoDeviceFoundMessage()
165     
166     def _restoreDialog(self):
167         if(self.deviceInfo and self.deviceInfo.ip != None):
168             restoreBackup = self.windowManager.getRestoreBackup()
169             centralize(restoreBackup)
170             restoreBackup.setGeometry(self.geometry())
171             restoreBackup.show()
172             self.close()
173         else:
174             self._showNoDeviceFoundMessage()
175     
176     def _wayLayout(self):
177         self.barLayout = QHBoxLayout()
178         self.barLayout.setMargin(0)
179         spc = QSpacerItem(8, 0)
180         self.barLayout.addItem(spc)
181         main = QLabel("<font style='color: #333333'; size=2>Main</font>")
182         restore = QLabel("<font style='color: #FFFFFF'; size=2> Manage backups</font>")
183         spc = QSpacerItem(2, 0)
184         widgetList = [main, self._arrow(), restore]
185         
186         for widget in widgetList:
187             self.barLayout.addWidget(widget, Qt.AlignLeft)
188             self.barLayout.addItem(spc)
189                     
190         self.barLayout.addItem(QSpacerItem(300, 0))
191         return self.barLayout
192     
193     def _arrow(self):
194         label = QLabel()
195         label.setPixmap(QPixmap(BLACK_ARROW))
196         return label
197     
198     def _createInformationsLabel(self):
199         hLay = QHBoxLayout()
200         
201         self.infLabel = QLabel("<font style='color:"\
202                              "#333333'; size=2>"\
203                              "Select the backup you wish to manipulate.</font>")
204         iconAlert = QLabel()
205         hLay.setMargin(0)
206         iconAlert.setPixmap(QPixmap(ICON_ALERT))
207         spc = QSpacerItem(15, 0)
208         hLay.addItem(spc)
209         hLay.addWidget(iconAlert)
210         hLay.addWidget(self.infLabel, Qt.AlignLeft)
211         
212         return hLay
213     
214     def _doUpdateList(self):
215         self._currentBackupList().updateBackupList()
216         self._updateButtonsState(0)
217     
218     def _execCopyDialogToDevice(self):
219         self._copyDialogToDevice = QDialog(self, Qt.FramelessWindowHint)
220         self._copyDialogToDevice.setObjectName("copyDialogToDevice")
221         
222         self.rb1 = QRadioButton()
223         self.rb1.setText("External Memory Card")
224         self.rb2 = QRadioButton()
225         self.rb2.setText("Internal Memory Card")
226         
227         layout = QVBoxLayout()
228         layout.addWidget(self.rb1)
229         layout.addWidget(self.rb2)
230         
231         buttonCopy = QPushButton("Copy")
232         buttonCopy.setStyleSheet(DEFAULT_BUTTON_STYLE)
233         self.connect(buttonCopy, SIGNAL("clicked()"), self._doCopyToDevice)
234         buttonCancel = QPushButton("Cancel")
235         buttonCancel.setStyleSheet(DEFAULT_BUTTON_STYLE)
236         self.connect(buttonCancel, SIGNAL("clicked()"), self._copyDialogToDevice.close)
237         
238         hlay = QHBoxLayout()
239         hlay.addWidget(buttonCancel)
240         hlay.addWidget(buttonCopy)
241         layout.addLayout(hlay)
242         self._copyDialogToDevice.setLayout(layout)
243         self._copyDialogToDevice.exec_()
244     
245     def _execCopyDialogFromDevice(self):
246         self._copyDialogFromDevice = QDialog(self, Qt.FramelessWindowHint)
247         self._copyDialogFromDevice.setObjectName("copyDialogFromDevice")
248         
249         hLayout = QHBoxLayout()
250         hLayout.setMargin(0)
251         self.textField = QLineEdit(self)
252         buttonOpen = QPushButton()
253         buttonOpen.setObjectName("buttonBrowse")
254         self.connect(buttonOpen, SIGNAL("clicked()"), self._doBrowse)
255         copyPath = str(self._default_dir)
256         self.textField.setReadOnly(True)
257         self.textField.setText(self._default_dir)
258         hLayout.addWidget(self.textField)
259         hLayout.addWidget(buttonOpen)
260         
261         message = QLabel("<font style='color: #333333'; size=2> Backup copy destination: </font>")
262         message.setFixedHeight(15)
263         
264         layout = QVBoxLayout()
265         layout.addWidget(message)
266         layout.addLayout(hLayout)
267         
268         buttonCopy = QPushButton("Copy")
269         buttonCopy.setStyleSheet(DEFAULT_BUTTON_STYLE)
270         self.connect(buttonCopy, SIGNAL("clicked()"), self._doCopyFromDevice)
271         buttonCancel = QPushButton("Cancel")
272         buttonCancel.setStyleSheet(DEFAULT_BUTTON_STYLE)
273         self.connect(buttonCancel, SIGNAL("clicked()"), self._copyDialogFromDevice.close)
274         
275         hlay = QHBoxLayout()
276         hlay.addWidget(buttonCancel)
277         hlay.addWidget(buttonCopy)
278         layout.addLayout(hlay)
279         self._copyDialogFromDevice.setLayout(layout)
280         self._copyDialogFromDevice.exec_()
281     
282     def _doCopyBackup(self):
283         if self.tabBar.currentIndex() == 0:
284             self._execCopyDialogToDevice()
285         else:
286             self._execCopyDialogFromDevice()
287     
288     def doCopy(self, device_ip, backupName, ret, destinationPath):
289         self.copyThread = CopyBackupThread(self, device_ip, backupName, ret, destinationPath)
290         self.copyThread.start()
291         self._runCopyProgress()
292         
293         self.connect(self.copyThread, SIGNAL("openFileError"), self._onOpenFileError)
294         self.connect(self.copyThread, SIGNAL("copyProgress"), self._updateProgress)
295         self.connect(self.copyThread, SIGNAL("copyDone"), self._onCopyDone)
296     
297     def _doCopyToDevice(self):
298         self._copyDialogToDevice.close()
299         ret = 1
300         if self.rb1.isChecked():
301             ret = 0
302         selectedBackupList = self._currentBackupList().getSelectedBackupList()
303         for backup in selectedBackupList: 
304             self.doCopy(self.deviceInfo.ip, str(backup).strip(), ret, "")
305         
306     def _doCopyFromDevice(self):
307         self._copyDialogFromDevice.close()
308         if self.copyPath != "":
309             selectedBackupList = self._currentBackupList().getSelectedBackupList()
310             self.name_change = False
311             for backup in selectedBackupList:
312                 self.pcBackupManager.loadBackups()
313                 self.correct_name = self.pcBackupManager._verify_backup_name(str(backup).strip())
314                 self.doCopy(self.deviceInfo.ip, str(backup).strip(), 0, self.copyPath)
315                 if self.correct_name != backup:
316                     self.name_change = True
317
318     def _showMessageCopyBackupDone(self):
319         if self.name_change == None or not self.name_change:
320             QMessageBox.information(self, "Copy Backup", "Backup(s) copied")
321         else:
322             QMessageBox.information(sopenFileErrorelf, "Copy Backup",
323                                     "Backup copied with name: %s" % self.correct_name)
324         
325     def _doBrowse(self):
326         pathDialog = QFileDialog()
327         prompt = "Select the folder you wish to copy your backup(s):"
328         self.copyPath = pathDialog.getExistingDirectory(self, prompt, self._home_dir)
329         if(self.copyPath != ""):
330             self.textField.setText(self.copyPath)
331
332     def _doRenameBackup(self):
333         res = False
334         (newName, ok) = QInputDialog.getText(self, "Rename Backup", "New Backup Name:",
335                                              QLineEdit.Normal, QString(),  
336                                              Qt.FramelessWindowHint)
337         if ok:
338             if newName:
339                 newName = QString(str(newName).strip())
340             if not newName.isEmpty():
341                 list = self._currentBackupList()
342                 res = list.renameSelectedBackup(newName)
343             if res:
344                 showMessageBox("Backup Renamed", "")
345             else:
346                 showMessageBox("Error while renaming the backup", "")
347
348     def _doDeleteBackup(self):
349         
350         dialog = QMessageBox()
351         dialog.setText("Remove selected backup?")
352         dialog.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
353         dialog.setWindowFlags(Qt.FramelessWindowHint)
354         dialog.setStyleSheet(MESSAGE_BOX_DEFAULT)
355         ret = dialog.exec_()
356         if ret == QMessageBox.Yes:
357             list = self._currentBackupList()
358             list.removeSelectedBackups()
359             showMessageBox("Backup Removed", "")
360
361     def _currentBackupList(self):
362         if self.tabBar.currentIndex() == 0:
363             self._buttonRename.setVisible(True)
364             self._buttonDelete.setVisible(True)
365             self._buttonView.setVisible(True)
366             self._buttonUpdate.setVisible(False)
367             return self.pcListView
368         else:
369             self._buttonUpdate.setVisible(True)
370             self._buttonRename.setVisible(False)
371             self._buttonDelete.setVisible(False)
372             self._buttonView.setVisible(False)
373             return self.deviceListView
374
375     def _updateButtonsState(self, index):
376         list = self._currentBackupList()
377         selectionModel = list.selectionModel()
378         indexList = selectionModel.selectedRows()
379         
380         if len(indexList) != 1:
381             self._buttonRename.setDisabled(True)
382             self._buttonView.setDisabled(True)
383             self._buttonCopy.setDisabled(True)
384         else:
385             self._buttonRename.setEnabled(True)
386             self._buttonView.setEnabled(True)
387             self._buttonCopy.setEnabled(True)
388         
389         if len(indexList) == 0:
390             self._buttonDelete.setDisabled(True)
391 #            self._buttonCopy.setDisabled(True)
392         else:
393             self._buttonDelete.setEnabled(True)
394 #            self._buttonCopy.setEnabled(True)             
395         
396   
397     def _doViewBackup(self):
398         list = self._currentBackupList()
399         backupManager = list.getBackupManager()
400         backupName = (str(list.getSelectedBackup())).strip()
401         if backupName == None:
402             return False
403         
404         dialog = QDialog(self, Qt.FramelessWindowHint)
405         dialog.setObjectName("viewDialog")
406         dialog.setFixedSize(WINDOW_WIDTH, WINDOW_HEIGHT)
407         dialog.setWindowTitle("Backup Files")
408         dialog.setWindowIcon(QIcon(BACKUP_IMAGE))
409         
410         layout = QVBoxLayout()
411         listWidget = QListWidget()
412         listWidget.setObjectName("viewList")
413         listWidget.setDragDropMode(QAbstractItemView.NoDragDrop)
414         
415         try:
416             backupContentList = backupManager.listBackupContent(backupName)
417         except IOError:
418             showMessageBox(self.openFileError, "Error while opening file")
419             return False
420
421         for backupContent in backupContentList:
422             backup_button = QListWidgetItem()
423             backup_button.setText(backupContent)
424             listWidget.addItem(backup_button)
425         
426         okButton = QPushButton("OK")
427         okButton.setStyleSheet(SMALL_DEFAULT_BUTTON_STYLE)
428         visible = partial(dialog.setVisible, False)
429         self.connect(okButton, SIGNAL("clicked()"), visible)
430         hLay = QHBoxLayout()
431         hLay.addItem(QSpacerItem(200,0))
432         hLay.addWidget(okButton)
433         
434         layout.addWidget(listWidget)
435         layout.addLayout(hLay)
436         dialog.setLayout(layout)
437         dialog.show()
438     
439     def _runCopyProgress(self):
440         self._progressDialog = PcsProgressDialog(self)
441         self._progressDialog.setAction("copy")
442         self.connect(self._progressDialog.cancelButton, SIGNAL("clicked()"),
443                       self._onCopyCancel)
444         self._progressDialog.show()
445     
446     def _updateProgress(self, information):
447         progress, self.numberOfFiles, self.totalSize = information
448         self._progressDialog.setProgress(progress)
449     
450     def _onCopyDone(self):
451         self._progressDialog.updateInfo(self.totalSize, self.numberOfFiles)
452         self._progressDialog.progressDone()
453         self.pcListView.updateBackupList()
454     
455     def _onCopyCancel(self):
456         if self.tabBar.currentIndex() == 0:
457             self.pcBackupManager.setCopyInProgress(False)
458         else:
459             self.deviceBackupManager.setCopyInProgress(False)
460         self._progressDialog.progressCanceled()
461         
462     def _onOpenFileError(self):
463         self._progressDialog.close()
464         showMessageBox(OPEN_FILE_ERROR, OPEN_FILE_ERROR_TITLE)
465         
466         
467         
468 class CopyBackupThread(QThread):
469     def __init__(self, manager, deviceIp, backupName, ret, destinationPath ):
470         QThread.__init__(self)
471         self.uiManager = manager
472         self.deviceIp = deviceIp
473         self.backupName = backupName
474         self.memoryCard = ret
475         self.destinationPath = destinationPath
476         self.connect(self.uiManager.pcBackupManager, SIGNAL("copyProgress"), 
477                      self.reEmit)
478         self.connect(self.uiManager.deviceBackupManager, SIGNAL("copyProgress"),
479                       self.reEmit)
480         
481     def reEmit(self, inf):
482         self.emit(SIGNAL("copyProgress"), inf)
483     
484     def run(self):
485         try:
486             if self.uiManager.tabBar.currentIndex() == 0:
487                 manager = self.uiManager.pcBackupManager
488                 manager.copyBackupToDevice(self.deviceIp, self.backupName, 
489                                             self.memoryCard)
490             else:
491                 manager = self.uiManager.deviceBackupManager
492                 manager.copyBackupFromDevice(self.backupName, 
493                                              self.destinationPath)
494         
495         except IOError:
496             self.emit(SIGNAL("openFileError"))
497             return
498         self.emit(SIGNAL("copyDone"))
499         
500         
501         
502