Last update of gforge repository
[tablet-suite] / src / backup / pcsrestorebackupui.py
1 # Authors: Amaury Medeiros and Paulo Ouriques
2 # Software License: GPL
3
4 from PyQt4.QtCore import *
5 from PyQt4.QtGui import *
6
7 from functools import partial 
8
9 from ui.pcsuiutils import *
10 from ui.tsuigeneralmethods import *
11
12 from style.styleTabletSuite import *
13
14 from backup.pcsbackupmanager import PcsBackupManager, DEVICES_POINT, USER_HOST
15 from backup.pcspcbackupmanager import PcsPcBackupManager
16 from backup.pcsdevicebackupmanager import PcsDeviceBackupManager
17 from pcsbackuplistui import PCSBackupListUi
18 from pcsprogressdialog import PcsProgressDialog
19 from pcsrestoredialog import PcsRestoreDialog
20 from pcsbackuputils import *
21
22
23 class PcsRestoreBackupUi(QDialog):
24     
25     def __init__(self, deviceInfo, windowManager, parent = None):
26         super(PcsRestoreBackupUi, self).__init__(parent)
27         self.deviceInfo = deviceInfo
28         
29         self.windowManager = windowManager
30         self.pcBackupManager = PcsPcBackupManager()
31         self.deviceBackupManager = PcsDeviceBackupManager(self.deviceInfo)
32         self.deviceListView = PCSBackupListUi(self.deviceBackupManager)
33         
34         self._buttonRestoreI = QPushButton("Restore")
35         self.connect (self._buttonRestoreI, SIGNAL("clicked()"), self._openRestoreBackup)
36         self._buttonRestoreII = QPushButton("Restore")
37         self.connect (self._buttonRestoreII, SIGNAL("clicked()"), self._openRestoreBackup)
38         self._buttonView = QPushButton("View")
39         self.connect (self._buttonView, SIGNAL("clicked()"), self._doViewBackup)
40         self._buttonUpdate = QPushButton("Update")
41         self.connect (self._buttonUpdate, SIGNAL("clicked()"), self._doUpdateList)
42         
43         self.pcListView = PCSBackupListUi(self.pcBackupManager)
44         
45         self.setWindowTitle("%s Restore Backup" % APPLICATION_NAME)
46         self.setFixedSize(WINDOW_WIDTH, WINDOW_HEIGHT)
47         self.vLayout = QVBoxLayout()
48         
49         self._insertLayout()
50     
51     def _createCenterLayout(self):
52         self.deviceListView.updateBackupList()
53         tab = QTabBar()
54         tab.setObjectName("restoreTabs")
55         self.tabBar = QTabWidget()
56         self.tabBar.setTabBar(tab)
57         self.tabBar.setAttribute(Qt.WA_NoSystemBackground)
58         self.tabBar.setObjectName("tabBar")
59         self.tabBar.addTab(self._createPcListViewWidget(), "PC Backups")
60         self.tabBar.addTab(self._createDeviceListViewWidget(), "Device Backups")
61         self.connect(self.tabBar, SIGNAL("currentChanged(int)"), 
62                      self._updateButtonsState)
63         
64         layout = QVBoxLayout()
65         layout.addWidget(self.tabBar)
66         
67         return layout
68     
69     def _createButtons(self, pcFlag = False):
70         buttonBox = QHBoxLayout()
71         self._buttonRestoreI.setStyleSheet(DEFAULT_BUTTON_STYLE)
72         self._buttonRestoreI.setDisabled(True)
73         self._buttonRestoreII.setStyleSheet(DEFAULT_BUTTON_STYLE)
74         self._buttonRestoreII.setDisabled(True)
75         self._buttonView.setStyleSheet(DEFAULT_BUTTON_STYLE)
76         self._buttonView.setDisabled(True)
77         self._buttonUpdate.setStyleSheet(DEFAULT_BUTTON_STYLE)
78         self._buttonUpdate.setDisabled(True)
79         
80         
81         if pcFlag:
82             buttonBox.addWidget(self._buttonRestoreI)
83             buttonBox.addWidget(self._buttonView)
84         else:
85             buttonBox.addWidget(self._buttonRestoreII)
86             buttonBox.addWidget(self._buttonUpdate)
87         
88         return buttonBox
89     
90     def _createPcListViewWidget(self):
91         self.pcListView.setObjectName("ListView")
92         pcListViewSelectionModel = self.pcListView.selectionModel()
93         self.connect(pcListViewSelectionModel, 
94                      SIGNAL("selectionChanged(QItemSelection, QItemSelection)"),
95                      self._updateButtonsState)
96         
97         self.pcListView.updateBackupList()
98         
99         panel = QWidget()
100         panel.setAttribute(Qt.WA_NoSystemBackground)
101         panel.setObjectName("DeviceListPanel")
102         vLay = QVBoxLayout()
103         
104         vLay.addWidget(self.pcListView)
105         vLay.addLayout(self._createButtons(True))
106         panel.setLayout(vLay)
107         
108         return panel
109     
110     def _createDeviceListViewWidget(self):
111         self.deviceListView.setObjectName("ListView")
112         deviceListViewSelectionModel = self.deviceListView.selectionModel()
113         self.connect(deviceListViewSelectionModel, 
114                      SIGNAL("selectionChanged(QItemSelection, QItemSelection)"), 
115                      self._updateButtonsState)
116         
117         self.deviceListView.updateBackupList()
118         
119         panel = QWidget()
120         panel.setAttribute(Qt.WA_NoSystemBackground)
121         panel.setObjectName("DeviceListPanel")
122         vLay = QVBoxLayout()
123         
124         vLay.addWidget(self.deviceListView)
125         vLay.addLayout(self._createButtons())
126         panel.setLayout(vLay)
127         
128         return panel
129         
130         
131     def _insertLayout(self):
132         
133         self.vLayout.setMargin(0)
134         self.wayLayout = self._wayLayout()
135         buttonLayout = self._menuButtons()
136         spc = QSpacerItem(0, 6)
137         self.vLayout.addItem(spc)
138         self.vLayout.addLayout(buttonLayout, Qt.AlignTop)
139         spc = QSpacerItem(0, 5)
140         self.vLayout.addItem(spc)
141         self.vLayout.addLayout(self.wayLayout, Qt.AlignLeft)
142         spc = QSpacerItem(0, 3)
143         self.vLayout.addItem(spc)
144         self.vLayout.addLayout(self._createCenterLayout(), Qt.AlignVCenter)
145         
146         self.vLayout.addLayout(self._createInformationsLabel(), Qt.AlignVCenter)
147         spc = QSpacerItem(0, 8)
148         self.vLayout.addItem(spc)
149         self.setLayout(self.vLayout)
150
151     def _menuButtons(self):
152         infList = [("New Backup", SMALL_ICON_NEW_BACKUP_STYLE, self._newBackupDialog), 
153                    ("Manage Backup", SMALL_ICON_MANAGER_BACKUP_STYLE, self._manageDialog),
154                    ("Restore Backup", SMALL_ICON_RESTORE_BACKUP_STYLE_SELECTED)]
155         
156         buttonsLayout = QHBoxLayout()
157         for i in range(3):
158             but = QPushButton(infList[i][0])
159             but.setStyleSheet(infList[i][1])
160             if i <> 2:
161                 buttonsLayout.addWidget(but, Qt.AlignLeft)
162                 self.connect(but, SIGNAL("clicked()"), infList[i][2])
163             else:
164                 buttonsLayout.addWidget(but)
165         return buttonsLayout    
166     
167     def _wayLayout(self):
168         self.barLayout = QHBoxLayout()
169         self.barLayout.setMargin(0)
170         spc = QSpacerItem(8, 0)
171         self.barLayout.addItem(spc)
172         main = QLabel("<font style='color: #333333'; size=2>Main</font>")
173         restore = QLabel("<font style='color: #FFFFFF'; size=2> Restore backups</font>")
174         spc = QSpacerItem(2, 0)
175         widgetList = [main, self._arrow(), restore]
176         
177         for widget in widgetList:
178             self.barLayout.addWidget(widget, Qt.AlignLeft)
179             self.barLayout.addItem(spc)
180                     
181         self.barLayout.addItem(QSpacerItem(300, 0))
182         return self.barLayout
183     
184     def _manageDialog(self):
185         if(self.deviceInfo and self.deviceInfo.ip != None):
186             backupManager = self.windowManager.getBackupManager()
187             centralize(backupManager)
188             backupManager.setGeometry(self.geometry())
189             backupManager.show()
190             self.close()
191         else:
192             self._showNoDeviceFoundMessage()
193     
194     def _newBackupDialog(self):
195         if(self.deviceInfo and self.deviceInfo.ip != None):
196             newBackup = self.windowManager.getNewBackup()
197             centralize(newBackup)
198             newBackup.setGeometry(self.geometry())
199             newBackup.show()
200             self.close()
201         else:
202             self._showNoDeviceFoundMessage()
203     
204     def _showNoDeviceFoundMessage(self):
205         inf = QMessageBox(self)
206         inf.setWindowTitle("Connect a device.")
207         inf.setText("No devices were found.")
208         inf.show()
209     
210     def _arrow(self):
211         label = QLabel()
212         label.setPixmap(QPixmap(BLACK_ARROW))
213         return label
214         
215     def _createInformationsLabel(self):
216         hLay = QHBoxLayout()
217         
218         self.infLabel = QLabel("<font style='color:"\
219                              "#333333'; size=2>"\
220                              "Select the backup you wish to restore.</font>")
221         iconAlert = QLabel()
222         iconAlert.setPixmap(QPixmap(ICON_ALERT))
223         spc = QSpacerItem(15, 0)
224         hLay.addItem(spc)
225         hLay.addWidget(iconAlert)
226         hLay.addWidget(self.infLabel, Qt.AlignLeft)
227         
228         return hLay
229
230     def _updateButtonsState(self, index):
231         list = self._currentBackupList()
232         selectionModel = list.selectionModel()
233         indexList = selectionModel.selectedRows()
234         
235         self._buttonUpdate.setEnabled(True)
236         if len(indexList) <> 1:
237             self._buttonView.setDisabled(True)
238             self._buttonRestoreI.setDisabled(True)
239             self._buttonRestoreII.setDisabled(True)
240         else:
241             self._buttonView.setEnabled(True)
242             self._buttonRestoreI.setEnabled(True)
243             self._buttonRestoreII.setEnabled(True)
244
245     def _currentBackupList(self):
246         if self.tabBar.currentIndex() == 0:
247             return self.pcListView
248         else:
249             return self.deviceListView
250     
251     def _doUpdateList(self):
252         self._currentBackupList().updateBackupList()
253         self._updateButtonsState(0)
254         
255     def doRestoreBackup(self, categories):
256         if self._currentBackupList() == self.pcListView:
257             manager = self.pcBackupManager
258         else:
259             manager = self.deviceBackupManager
260             
261         self.restoreBackupThread = RestoreBackupThread(self, manager, categories)
262         self.restoreBackupThread.start()
263         self._runRestoreProgress()
264         self.connect(self.restoreBackupThread, SIGNAL("restoreProgress"), 
265                      self._updateCategoriesAndProgress)
266         self.connect(self.restoreBackupThread, SIGNAL("restoreDone"), 
267                      self._onRestodeDone)
268         self.connect(self.restoreBackupThread, SIGNAL("openFileError"),
269                      self._onOpenFileError)
270
271     def _openRestoreBackup(self):
272         backup = self._currentBackupList().getSelectedBackup()
273         if self._currentBackupList() == self.pcListView:
274             self.pcBackupManager.loadBackups()
275             backupInfo = self.pcBackupManager.getBackupInfo(str(backup))
276         else:
277             self.deviceBackupManager.loadBackups()
278             backupInfo = self.deviceBackupManager.getBackupInfo(str(backup))
279             
280         host_ip = self.deviceInfo.ip
281         devicePath = os.path.join(DEVICES_POINT, "%s" % host_ip)
282         mountPath = os.path.join(devicePath, "Root" )
283         mountDevice(USER_HOST, host_ip, mountPath)
284         list = getBackupCategories(backupInfo)
285         unmountDevice(mountPath)
286         
287         self.restoreDialog = PcsRestoreDialog(self.deviceInfo, list, self)
288         self.connect(self.restoreDialog.buttonCancel, SIGNAL("clicked()"),
289                      self.restoreDialog.close)
290         
291         self.connect(self.restoreDialog.buttonOk, SIGNAL("clicked()"),
292                      self._doRestoreAndCloseDialog)
293         self.restoreDialog.exec_()
294         
295     
296     def _doRestoreAndCloseDialog(self):
297         categories = self.restoreDialog.getCategories()
298         self.restoreDialog.close()
299         self.doRestoreBackup(categories)
300         
301     def _doRestoreBackup(self, categories):
302         selectedBackups = self._currentBackupList().getSelectedBackupList()
303         if self._currentBackupList() == self.pcListView:
304             self.pcBackupManager.loadBackups()
305             for backup in selectedBackups:
306                 backupInfo = self.pcBackupManager.getBackupInfo(str(backup))
307                 ip = self.deviceBackupManager._deviceInfo.ip
308                 self.emit(SIGNAL("restoreStarted"))
309                 result = self.pcBackupManager.startBackupRestore(backupInfo, ip,
310                                                        categories)
311                 if result == False or result == 0:
312                     return result
313         else:
314             self.deviceBackupManager.loadBackups()
315             for backup in selectedBackups:
316                 backupInfo = self.deviceBackupManager.getBackupInfo(str(backup))
317                 self.emit(SIGNAL("restoreStarted"))
318                 result = self.deviceBackupManager.startBackupRestore(backupInfo, 
319                                                           categories)
320                 if result == False or result == 0:
321                     return result
322         return True
323
324     def showRestoreMessage(self, done):
325         if done != 0:
326             self._progressDialog.cancel()  
327             ip = self.deviceBackupManager._deviceInfo.ip
328             if done:
329                 doneMessage = "Restore done. Your device will be rebooted now"
330                 showMessageBox(doneMessage, "Restore successfully Done")
331                 rebootDevice(ip)
332             else:
333                 showMessageBox("An error occurred while restoring backup",
334                                  "Restore error")
335               
336     def _doViewBackup(self):
337         list = self._currentBackupList()
338         backupManager = list.getBackupManager()
339         backupName = (str(list.getSelectedBackup())).strip()
340         if backupName == None:
341             return False
342         
343         dialog = QDialog(self, Qt.FramelessWindowHint)
344         dialog.setObjectName("viewDialog")
345         dialog.setFixedSize(WINDOW_WIDTH, WINDOW_HEIGHT)
346         dialog.setWindowTitle("Backup Files")
347         dialog.setWindowIcon(QIcon(BACKUP_IMAGE))
348         
349         layout = QVBoxLayout()
350         layout.setMargin(10)
351         listWidget = QListWidget()
352         listWidget.setObjectName("viewList")
353         listWidget.setDragDropMode(QAbstractItemView.NoDragDrop)
354
355         backupContentList = backupManager.listBackupContent(backupName)
356         if not backupContentList:
357             showMessageBox("Could not open backup files", "Error")
358             return False
359         for backupContent in backupContentList:
360             backup_button = QListWidgetItem()
361             backup_button.setText(backupContent)
362             listWidget.addItem(backup_button)
363         
364         okButton = QPushButton("OK")
365         okButton.setStyleSheet(SMALL_DEFAULT_BUTTON_STYLE)
366         visible = partial(dialog.setVisible, False)
367         self.connect(okButton, SIGNAL("clicked()"), visible)
368         hLay = QHBoxLayout()
369         hLay.addItem(QSpacerItem(200,0))
370         hLay.addWidget(okButton)
371         layout.addWidget(listWidget)
372         layout.addLayout(hLay)
373         dialog.setLayout(layout)
374         dialog.show()
375     
376     def _runRestoreProgress(self):
377         self._progressDialog = PcsProgressDialog(self)
378         self._progressDialog.setAction("restore")
379         self.connect(self._progressDialog.cancelButton, SIGNAL("clicked()"),
380                       self._onRestoreCancel)
381         
382         self._progressDialog.show()
383     
384     def _updateCategoriesAndProgress(self, information):
385         progress, category, self.numberOfFiles, self.totalSize = information
386         
387         self._progressDialog.setProgress(progress)
388         self._progressDialog.setCategory(category)
389     
390     def _onRestodeDone(self):
391         self._progressDialog.updateInfo(self.totalSize, self.numberOfFiles)
392         self._progressDialog.progressDone()
393     
394     def _onRestoreCancel(self):
395         self._progressDialog.progressCanceled()
396         if self._currentBackupList() == self.pcListView:
397             self.pcBackupManager.setRestoreInProgress(False)
398         else:
399             self.deviceBackupManager.setRestoreInProgress(False)
400             
401     def _onOpenFileError(self):
402         self._progressDialog.close()
403         showMessageBox(OPEN_FILE_ERROR, OPEN_FILE_ERROR_TITLE)
404     
405 class RestoreBackupThread(QThread):
406     def __init__(self, restoreBackup, manager,  categories):
407         QThread.__init__(self)
408         self.restoreBackup = restoreBackup
409         self.categories = categories
410         self.connect(manager, SIGNAL("restoreProgress"), self._reEmitSignal)
411     
412     def _reEmitSignal(self, informations):
413         self.emit(SIGNAL("restoreProgress"), informations)
414
415     def run(self):
416         try:
417             done = self.restoreBackup._doRestoreBackup(self.categories)
418         except IOError:
419             self.emit(SIGNAL("openFileError"))
420             return
421         self.emit(SIGNAL("restoreDone"))
422