Initial commit (Vesion 0.1)
[tablet-suite] / src / backup / pcsrestorebackupui.py
diff --git a/src/backup/pcsrestorebackupui.py b/src/backup/pcsrestorebackupui.py
new file mode 100644 (file)
index 0000000..dc9733a
--- /dev/null
@@ -0,0 +1,412 @@
+# Authors: Amaury Medeiros and Paulo Ouriques
+# Software License: GPL
+
+from PyQt4.QtCore import *
+from PyQt4.QtGui import *
+
+from functools import partial 
+
+from ui.pcsuiutils import *
+from ui.tsuigeneralmethods import *
+
+from style.styleTabletSuite import *
+
+from backup.pcsbackupmanager import PcsBackupManager, DEVICES_POINT, USER_HOST
+from backup.pcspcbackupmanager import PcsPcBackupManager
+from backup.pcsdevicebackupmanager import PcsDeviceBackupManager
+from pcsbackuplistui import PCSBackupListUi
+from pcsprogressdialog import PcsProgressDialog
+from pcsrestoredialog import PcsRestoreDialog
+from pcsbackuputils import *
+
+
+class PcsRestoreBackupUi(QDialog):
+    
+    def __init__(self, deviceInfo, windowManager, parent = None):
+        super(PcsRestoreBackupUi, self).__init__(parent)
+        self.deviceInfo = deviceInfo
+        
+        self.windowManager = windowManager
+        self.pcBackupManager = PcsPcBackupManager()
+        self.deviceBackupManager = PcsDeviceBackupManager(self.deviceInfo)
+        self.deviceListView = PCSBackupListUi(self.deviceBackupManager)
+        
+        self._buttonRestoreI = QPushButton("Restore")
+        self.connect (self._buttonRestoreI, SIGNAL("clicked()"), self._openRestoreBackup)
+        self._buttonRestoreII = QPushButton("Restore")
+        self.connect (self._buttonRestoreII, SIGNAL("clicked()"), self._openRestoreBackup)
+        self._buttonView = QPushButton("View")
+        self.connect (self._buttonView, SIGNAL("clicked()"), self._doViewBackup)
+        
+        self.pcListView = PCSBackupListUi(self.pcBackupManager)
+        
+        self.setWindowTitle("%s Restore Backup" % APPLICATION_NAME)
+        self.setFixedSize(WINDOW_WIDTH, WINDOW_HEIGHT)
+        self.vLayout = QVBoxLayout()
+        
+        self._insertLayout()
+    
+    def _createCenterLayout(self):
+        self.deviceListView.updateBackupList()
+        tab = QTabBar()
+        tab.setObjectName("restoreTabs")
+        self.tabBar = QTabWidget()
+        self.tabBar.setTabBar(tab)
+        self.tabBar.setAttribute(Qt.WA_NoSystemBackground)
+        self.tabBar.setObjectName("tabBar")
+        self.tabBar.addTab(self._createPcListViewWidget(), "PC Backups")
+        self.tabBar.addTab(self._createDeviceListViewWidget(), "Device Backups")
+        self.connect(self.tabBar, SIGNAL("currentChanged(int)"), 
+                     self._updateButtonsState)
+        
+        layout = QVBoxLayout()
+        layout.addWidget(self.tabBar)
+        
+        return layout
+    
+    def _createButtons(self, pcFlag = False):
+        buttonBox = QHBoxLayout()
+        self._buttonRestoreI.setStyleSheet(DEFAULT_BUTTON_STYLE)
+        self._buttonRestoreI.setDisabled(True)
+        self._buttonRestoreII.setStyleSheet(DEFAULT_BUTTON_STYLE)
+        self._buttonRestoreII.setDisabled(True)
+        self._buttonView.setStyleSheet(DEFAULT_BUTTON_STYLE)
+        self._buttonView.setDisabled(True)
+        
+        if pcFlag:
+            buttonBox.addWidget(self._buttonView)
+            buttonBox.addWidget(self._buttonRestoreI)
+        else:
+            buttonBox.addWidget(self._buttonRestoreII)
+        
+        return buttonBox
+    
+    def _createPcListViewWidget(self):
+        self.pcListView.setObjectName("ListView")
+        pcListViewSelectionModel = self.pcListView.selectionModel()
+        self.connect(pcListViewSelectionModel, 
+                     SIGNAL("selectionChanged(QItemSelection, QItemSelection)"),
+                     self._updateButtonsState)
+        
+        self.pcListView.updateBackupList()
+        
+        panel = QWidget()
+        panel.setAttribute(Qt.WA_NoSystemBackground)
+        panel.setObjectName("DeviceListPanel")
+        vLay = QVBoxLayout()
+        
+        vLay.addWidget(self.pcListView)
+        vLay.addLayout(self._createButtons(True))
+        panel.setLayout(vLay)
+        
+        return panel
+    
+    def _createDeviceListViewWidget(self):
+        self.deviceListView.setObjectName("ListView")
+        deviceListViewSelectionModel = self.deviceListView.selectionModel()
+        self.connect(deviceListViewSelectionModel, 
+                     SIGNAL("selectionChanged(QItemSelection, QItemSelection)"), 
+                     self._updateButtonsState)
+        
+        self.deviceListView.updateBackupList()
+        
+        panel = QWidget()
+        panel.setAttribute(Qt.WA_NoSystemBackground)
+        panel.setObjectName("DeviceListPanel")
+        vLay = QVBoxLayout()
+        
+        vLay.addWidget(self.deviceListView)
+        vLay.addLayout(self._createButtons())
+        panel.setLayout(vLay)
+        
+        return panel
+        
+        
+    def _insertLayout(self):
+        
+        self.vLayout.setMargin(0)
+        self.wayLayout = self._wayLayout()
+        buttonLayout = self._menuButtons()
+        spc = QSpacerItem(0, 6)
+        self.vLayout.addItem(spc)
+        self.vLayout.addLayout(buttonLayout, Qt.AlignTop)
+        spc = QSpacerItem(0, 5)
+        self.vLayout.addItem(spc)
+        self.vLayout.addLayout(self.wayLayout, Qt.AlignLeft)
+        spc = QSpacerItem(0, 3)
+        self.vLayout.addItem(spc)
+        self.vLayout.addLayout(self._createCenterLayout(), Qt.AlignVCenter)
+        
+        self.vLayout.addLayout(self._createInformationsLabel(), Qt.AlignVCenter)
+        spc = QSpacerItem(0, 8)
+        self.vLayout.addItem(spc)
+        self.setLayout(self.vLayout)
+
+    def _menuButtons(self):
+        infList = [("New Backup", SMALL_ICON_NEW_BACKUP_STYLE, self._newBackupDialog), 
+                   ("Manage Backup", SMALL_ICON_MANAGER_BACKUP_STYLE, self._manageDialog),
+                   ("Restore Backup", SMALL_ICON_RESTORE_BACKUP_STYLE_SELECTED)]
+        
+        buttonsLayout = QHBoxLayout()
+        for i in range(3):
+            but = QPushButton(infList[i][0])
+            but.setStyleSheet(infList[i][1])
+            if i <> 2:
+                buttonsLayout.addWidget(but, Qt.AlignLeft)
+                self.connect(but, SIGNAL("clicked()"), infList[i][2])
+            else:
+                buttonsLayout.addWidget(but)
+        return buttonsLayout    
+    
+    def _wayLayout(self):
+        self.barLayout = QHBoxLayout()
+        self.barLayout.setMargin(0)
+        spc = QSpacerItem(8, 0)
+        self.barLayout.addItem(spc)
+        main = QLabel("<font style='color: #333333'; size=2>Main</font>")
+        restore = QLabel("<font style='color: #FFFFFF'; size=2> Restore backups</font>")
+        spc = QSpacerItem(2, 0)
+        widgetList = [main, self._arrow(), restore]
+        
+        for widget in widgetList:
+            self.barLayout.addWidget(widget, Qt.AlignLeft)
+            self.barLayout.addItem(spc)
+                    
+        self.barLayout.addItem(QSpacerItem(300, 0))
+        return self.barLayout
+    
+    def _manageDialog(self):
+        if(self.deviceInfo and self.deviceInfo.ip != None):
+            backupManager = self.windowManager.getBackupManager()
+            centralize(backupManager)
+            backupManager.setGeometry(self.geometry())
+            backupManager.show()
+            self.close()
+        else:
+            self._showNoDeviceFoundMessage()
+    
+    def _newBackupDialog(self):
+        if(self.deviceInfo and self.deviceInfo.ip != None):
+            newBackup = self.windowManager.getNewBackup()
+            centralize(newBackup)
+            newBackup.setGeometry(self.geometry())
+            newBackup.show()
+            self.close()
+        else:
+            self._showNoDeviceFoundMessage()
+    
+    def _showNoDeviceFoundMessage(self):
+        inf = QMessageBox(self)
+        inf.setWindowTitle("Connect a device.")
+        inf.setText("No devices were found.")
+        inf.show()
+    
+    def _arrow(self):
+        label = QLabel()
+        label.setPixmap(QPixmap(BLACK_ARROW))
+        return label
+        
+    def _createInformationsLabel(self):
+        hLay = QHBoxLayout()
+        
+        self.infLabel = QLabel("<font style='color:"\
+                             "#333333'; size=2>"\
+                             "Select the backup you wish to restore.</font>")
+        iconAlert = QLabel()
+        iconAlert.setPixmap(QPixmap(ICON_ALERT))
+        spc = QSpacerItem(15, 0)
+        hLay.addItem(spc)
+        hLay.addWidget(iconAlert)
+        hLay.addWidget(self.infLabel, Qt.AlignLeft)
+        
+        return hLay
+
+    def _updateButtonsState(self, index):
+        list = self._currentBackupList()
+        selectionModel = list.selectionModel()
+        indexList = selectionModel.selectedRows()
+        
+        if len(indexList) <> 1:
+            self._buttonView.setDisabled(True)
+            self._buttonRestoreI.setDisabled(True)
+            self._buttonRestoreII.setDisabled(True)
+        else:
+            self._buttonView.setEnabled(True)
+            self._buttonRestoreI.setEnabled(True)
+            self._buttonRestoreII.setEnabled(True)
+
+    def _currentBackupList(self):
+        if self.tabBar.currentIndex() == 0:
+            return self.pcListView
+        else:
+            return self.deviceListView
+        
+        
+    def doRestoreBackup(self, categories):
+        if self._currentBackupList() == self.pcListView:
+            manager = self.pcBackupManager
+        else:
+            manager = self.deviceBackupManager
+            
+        self.restoreBackupThread = RestoreBackupThread(self, manager, categories)
+        self.restoreBackupThread.start()
+        self._runRestoreProgress()
+        self.connect(self.restoreBackupThread, SIGNAL("restoreProgress"), 
+                     self._updateCategoriesAndProgress)
+        self.connect(self.restoreBackupThread, SIGNAL("restoreDone"), 
+                     self._onRestodeDone)
+        self.connect(self.restoreBackupThread, SIGNAL("openFileError"),
+                     self._onOpenFileError)
+
+    def _openRestoreBackup(self):
+        backup = self._currentBackupList().getSelectedBackup()
+        if self._currentBackupList() == self.pcListView:
+            self.pcBackupManager.loadBackups()
+            backupInfo = self.pcBackupManager.getBackupInfo(str(backup))
+        else:
+            self.deviceBackupManager.loadBackups()
+            backupInfo = self.deviceBackupManager.getBackupInfo(str(backup))
+            
+        host_ip = self.deviceInfo.ip
+        devicePath = os.path.join(DEVICES_POINT, "%s" % host_ip)
+        mountPath = os.path.join(devicePath, "Root" )
+        mountDevice(USER_HOST, host_ip, mountPath)
+        list = getBackupCategories(backupInfo)
+        unmountDevice(mountPath)
+        
+        self.restoreDialog = PcsRestoreDialog(self.deviceInfo, list, self)
+        self.connect(self.restoreDialog.buttonCancel, SIGNAL("clicked()"),
+                     self.restoreDialog.close)
+        
+        self.connect(self.restoreDialog.buttonOk, SIGNAL("clicked()"),
+                     self._doRestoreAndCloseDialog)
+        self.restoreDialog.exec_()
+        
+    
+    def _doRestoreAndCloseDialog(self):
+        categories = self.restoreDialog.getCategories()
+        self.restoreDialog.close()
+        self.doRestoreBackup(categories)
+        
+    def _doRestoreBackup(self, categories):
+        selectedBackups = self._currentBackupList().getSelectedBackupList()
+        if self._currentBackupList() == self.pcListView:
+            self.pcBackupManager.loadBackups()
+            for backup in selectedBackups:
+                backupInfo = self.pcBackupManager.getBackupInfo(str(backup))
+                ip = self.deviceBackupManager._deviceInfo.ip
+                self.emit(SIGNAL("restoreStarted"))
+                result = self.pcBackupManager.startBackupRestore(backupInfo, ip,
+                                                       categories)
+                if result == False or result == 0:
+                    return result
+        else:
+            self.deviceBackupManager.loadBackups()
+            for backup in selectedBackups:
+                backupInfo = self.deviceBackupManager.getBackupInfo(str(backup))
+                self.emit(SIGNAL("restoreStarted"))
+                result = self.deviceBackupManager.startBackupRestore(backupInfo, 
+                                                          categories)
+                if result == False or result == 0:
+                    return result
+        return True
+
+    def showRestoreMessage(self, done):
+        if done != 0:
+            self._progressDialog.cancel()  
+            ip = self.deviceBackupManager._deviceInfo.ip
+            if done:
+                doneMessage = "Restore done. Your device will be rebooted now"
+                showMessageBox(doneMessage, "Restore successfully Done")
+                rebootDevice(ip)
+            else:
+                showMessageBox("An error occurred while restoring backup",
+                                 "Restore error")
+              
+    def _doViewBackup(self):
+        list = self._currentBackupList()
+        backupManager = list.getBackupManager()
+        backupName = (str(list.getSelectedBackup())).strip()
+        if backupName == None:
+            return False
+        
+        dialog = QDialog(self, Qt.FramelessWindowHint)
+        dialog.setObjectName("viewDialog")
+        dialog.setFixedSize(WINDOW_WIDTH, WINDOW_HEIGHT)
+        dialog.setWindowTitle("Backup Files")
+        dialog.setWindowIcon(QIcon(BACKUP_IMAGE))
+        
+        layout = QVBoxLayout()
+        layout.setMargin(10)
+        listWidget = QListWidget()
+        listWidget.setObjectName("viewList")
+        listWidget.setDragDropMode(QAbstractItemView.NoDragDrop)
+
+        backupContentList = backupManager.listBackupContent(backupName)
+        if not backupContentList:
+            showMessageBox("Could not open backup files", "Error")
+            return False
+        for backupContent in backupContentList:
+            backup_button = QListWidgetItem()
+            backup_button.setText(backupContent)
+            listWidget.addItem(backup_button)
+        
+        okButton = QPushButton("OK")
+        okButton.setStyleSheet(SMALL_DEFAULT_BUTTON_STYLE)
+        visible = partial(dialog.setVisible, False)
+        self.connect(okButton, SIGNAL("clicked()"), visible)
+        hLay = QHBoxLayout()
+        hLay.addItem(QSpacerItem(200,0))
+        hLay.addWidget(okButton)
+        layout.addWidget(listWidget)
+        layout.addLayout(hLay)
+        dialog.setLayout(layout)
+        dialog.show()
+    
+    def _runRestoreProgress(self):
+        self._progressDialog = PcsProgressDialog(self)
+        self._progressDialog.setAction("restore")
+        self.connect(self._progressDialog.cancelButton, SIGNAL("clicked()"),
+                      self._onRestoreCancel)
+        
+        self._progressDialog.show()
+    
+    def _updateCategoriesAndProgress(self, information):
+        progress, category, self.numberOfFiles, self.totalSize = information
+        
+        self._progressDialog.setProgress(progress)
+        self._progressDialog.setCategory(category)
+    
+    def _onRestodeDone(self):
+        self._progressDialog.updateInfo(self.totalSize, self.numberOfFiles)
+        self._progressDialog.progressDone()
+    
+    def _onRestoreCancel(self):
+        self._progressDialog.progressCanceled()
+        if self._currentBackupList() == self.pcListView:
+            self.pcBackupManager.setRestoreInProgress(False)
+        else:
+            self.deviceBackupManager.setRestoreInProgress(False)
+            
+    def _onOpenFileError(self):
+        self._progressDialog.close()
+        showMessageBox(OPEN_FILE_ERROR, OPEN_FILE_ERROR_TITLE)
+    
+class RestoreBackupThread(QThread):
+    def __init__(self, restoreBackup, manager,  categories):
+        QThread.__init__(self)
+        self.restoreBackup = restoreBackup
+        self.categories = categories
+        self.connect(manager, SIGNAL("restoreProgress"), self._reEmitSignal)
+    
+    def _reEmitSignal(self, informations):
+        self.emit(SIGNAL("restoreProgress"), informations)
+
+    def run(self):
+        try:
+            done = self.restoreBackup._doRestoreBackup(self.categories)
+        except IOError:
+            self.emit(SIGNAL("openFileError"))
+            return
+        self.emit(SIGNAL("restoreDone"))
+