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