Esempio n. 1
0
class Installer(QObject):
    setProgress = pyqtSignal(int)

    def __init__(self, options, schema, firer):

        QObject.__init__(self)
        if not hasattr(options, 'install_path') or not hasattr(options, 'distrib_path'):
            QMessageBox.warning(firer, u'Error', u'Incorrect options')
            firer.setEnabled(False)
            return

        self.schema = schema

        self.options = options
        self.firer = firer

        self.wizard = QWizard()
        self.wizard.setOptions(QWizard.NoBackButtonOnStartPage | QWizard.NoBackButtonOnLastPage)
        self.wizard.resize(800, 600)
        self.wizard.schema = schema

        self.unwizard = QWizard()
        self.unwizard.setOptions(QWizard.NoBackButtonOnStartPage | QWizard.NoBackButtonOnLastPage)
        self.unwizard.resize(800, 600)
        self.unwizard.schema = schema

        self.pip = self.PreInstallPage(self)
        self.cp = self.CheckPage(self)
        self.ip = self.InstallPage(self)

        self.puip = self.PreUnInstallPage(self)
        self.uip = self.UnInstallPage(self)

        self.wizard.addPage(self.pip)
        self.wizard.addPage(self.cp)
        self.wizard.addPage(self.ip)

        self.unwizard.addPage(self.puip)
        self.unwizard.addPage(self.uip)

    def install(self):
        self.wizard.setModal(True)
        self.wizard.show()

    def uninstall(self):
        self.unwizard.setModal(True)
        self.unwizard.show()

    class PreInstallPage(QWizardPage):
        def __init__(self, parent):
            QWizardPage.__init__(self)
            self.parent = parent

            self.setLayout(QGridLayout())
            self.setTitle('Options')
            self.setSubTitle('Please select destination folder and folder which contains downloaded files.')

            self.path = PathPanel(default=self.parent.options.install_path)
            self.layout().addWidget(QLabel('Installation path:'), 1, 0)
            self.layout().addWidget(self.path, 1, 1)

            self.distrib_path = PathPanel(default=self.parent.options.distrib_path)
            self.layout().addWidget(QLabel('Downloaded files:'), 2, 0)
            self.layout().addWidget(self.distrib_path, 2, 1)

            self.registerField('path', self.path, 'getPath', self.path.path_input.textChanged)
            self.registerField('distrib_path', self.distrib_path, 'getPath', self.distrib_path.path_input.textChanged)

            self.path.updated.connect(self.changed)
            self.distrib_path.updated.connect(self.changed)

        def initializePage(self):
            self.path.setPath(self.parent.options.install_path)
            self.distrib_path.setPath(self.parent.options.distrib_path)

        def changed(self):
            self.completeChanged.emit()

        def isComplete(self):
            return os.path.isdir(self.path.getPath) and os.path.isdir(self.distrib_path.getPath)


    class CheckPage(QWizardPage):
        setProgress = pyqtSignal(int)
        addComponentItem = pyqtSignal(object, str, bool, bool)
        editComponentItem = pyqtSignal(str, str)

        def __init__(self, parent):
            QWizardPage.__init__(self)
            self.parent = parent

            self.setLayout(QGridLayout())
            self.setTitle('Components')
            self.setSubTitle('Please select components which will be extracted to your destination folder.')

            self.status_label = QLabel()
            self.layout().addWidget(self.status_label, 1, 0)

            self.components_list = QListWidget()
            self.progress = QProgressBar()
            self.layout().addWidget(self.progress, 2, 0, 1, 4)
            self.layout().addWidget(self.components_list, 3, 0, 1, 4)

            addcomponent_button = QPushButton(u'Add component')
            addcomponent_button.setEnabled(False)
            self.layout().addWidget(addcomponent_button, 4, 0)

            self.is_done = False

            self.addComponentItem.connect(self.addListItem)
            self.setProgress.connect(self.progress.setValue)

            self.components_list.itemChanged.connect(self.completeChanged.emit)
            self.components_list.itemClicked.connect(self.completeChanged.emit)

            self.registerField('components', self, 'getComponents', self.components_list.itemClicked)

        def initializePage(self):
            self.components = []
            self.distrib_path = str(self.field('distrib_path').toString())
            self.status_label.setText('Search components in %s...' % self.distrib_path)
            self.components_list.clear()
            self.progress.setMaximum(0)
            self.startSearchComponents()

        def startSearchComponents(self):
            self.w = Worker(lambda: self.searchComponent(self.distrib_path))
            self.w.done.connect(self.endSearchComponents)
            self.w.error.connect(self.parent.printError)

            self.w.start()

        def endSearchComponents(self):
            self.status_label.setText('Found components in %s' % self.distrib_path)

            self.is_done = True
            self.completeChanged.emit()

        def isComplete(self):
            self.wizard().components = self.getComponents
            return self.is_done and len(self.getComponents)


        @pyqtProperty(list)
        def getComponents(self):
            components = []
            for item in self.getSelectedItems():
                if item.component.available:
                    components.append(item.component)
            return components

        def getSelectedItems(self):
            list_widget = self.components_list
            items = []
            for i in range(list_widget.count()):
                item = list_widget.item(i)
                if item.checkState() == Qt.Checked:
                    items.append(item)

            return items


        def addListItem(self, component, title, valid=True, checked=True):
            item = QListWidgetItem(title)
            item.component = component
            item.setFlags(item.flags() | Qt.ItemIsUserCheckable)
            if valid:
                pass
            else:
                item.setForeground(QColor('gray'))

            if checked:
                item.setCheckState(Qt.Checked)
            else:
                item.setCheckState(Qt.Unchecked)

            self.components_list.addItem(item)


        def searchComponent(self, distrib_path):

            self.setProgress.emit(0)

            self.progress.setMaximum(len(self.wizard().schema.components.keys()))

            for i, component_name in enumerate(self.wizard().schema.components.keys()):
                component = Component.create(component_name, distrib_path,
                                             self.wizard().schema.components[component_name])
                self.setProgress.emit(i)
                if component is not None:
                    self.addComponentItem.emit(
                        component,
                        component.title,
                        component.available,
                        component.default_install
                    )
                    self.components.append(component)

            self.setProgress.emit(len(self.wizard().schema.components.keys()))

    class InstallPage(QWizardPage):
        setProgress = pyqtSignal(int)
        message = pyqtSignal(str)

        def __init__(self, parent):
            QWizardPage.__init__(self)
            self.parent = parent

            self.setLayout(QGridLayout())
            self.setTitle('Installation')
            self.setSubTitle('All selected components will be extracted.')

            self.layout().addWidget(QLabel(u'Installation progress'), 0, 0)
            self.progress = QProgressBar()
            self.progress.setMaximum(0)
            self.layout().addWidget(self.progress, 1, 0, 1, 2)

            self.log = QTextBrowser()
            self.layout().addWidget(self.log, 2, 0, 1, 2)

            self.setProgress.connect(self.progress.setValue)
            self.message.connect(self.log.append)
            self.is_done = False

        def initializePage(self):
            self.components = self.wizard().components
            self.startInstallation()

        def startInstallation(self):
            self.distrib_path = str(self.field('distrib_path').toString())
            self.path = str(self.field('path').toString())

            self.w = Worker(lambda: self.install(self.distrib_path, self.path))
            self.w.done.connect(self.endInstall)
            self.w.error.connect(self.parent.printError)

            self.w.start()

        def install(self, src, destination):
            self.message.emit(u'Started...')
            self.progress.setMaximum(len(self.components))
            for i, component in enumerate(self.components):
                self.setProgress.emit(i)
                component.install(destination, message=self.message.emit)

            self.generateUninstallList(destination, src, self.components)

        def generateUninstallList(self, install_path, distrib_path, components):
            self.message.emit(u'Generating uninstall list...')

            with open('config/uninstall.yml', 'w') as f:
                l = ''
                for i, component in enumerate(components):
                    file_list = {component.name: component.uninstall_info}
                    l += yaml.dump(file_list, default_flow_style=False, indent=4, allow_unicode=True,
                                   encoding="utf-8")
                f.write(l)
                f.close()

        def endInstall(self):
            self.log.append(u'Finished')
            self.setProgress.emit(len(self.components))
            self.is_done = True
            self.completeChanged.emit()

        def isComplete(self):
            if self.is_done:
                self.wizard().finished.emit(1)
            return self.is_done

    class PreUnInstallPage(QWizardPage):
        setProgress = pyqtSignal(int)
        addComponentItem = pyqtSignal(object, str, bool, bool)
        editComponentItem = pyqtSignal(str, str)

        def __init__(self, parent):
            QWizardPage.__init__(self)
            self.parent = parent

            self.setLayout(QGridLayout())
            self.setTitle('Components')
            self.setSubTitle('This page cant handle manually installed components')

            self.components_list = QListWidget()
            self.progress = QProgressBar()
            self.layout().addWidget(self.progress, 2, 0, 1, 4)
            self.layout().addWidget(self.components_list, 3, 0, 1, 4)

            self.setProgress.connect(self.progress.setValue)

            self.is_done = False

            self.addComponentItem.connect(self.addListItem)
            self.setProgress.connect(self.progress.setValue)

            self.components_list.itemChanged.connect(self.completeChanged.emit)
            self.components_list.itemClicked.connect(self.completeChanged.emit)

        def initializePage(self):
            self.components = []
            self.components_list.clear()
            schema = Config(open('config/uninstall.yml'))
            for component_name in schema.keys():
                component = Component.create(component_name, None, schema[component_name])
                if component is not None:
                    self.addComponentItem.emit(
                        component,
                        component.title,
                        True,
                        component.default_uninstall
                    )
                    self.components.append(component)

            self.is_done = True

        def isComplete(self):
            self.wizard().components = self.getComponents
            return self.is_done and len(self.wizard().components)


        @pyqtProperty(list)
        def getComponents(self):
            components = []
            for item in self.getSelectedItems():
                if item.component.available:
                    components.append(item.component)
            return components

        def getSelectedItems(self):
            list_widget = self.components_list
            items = []
            for i in range(list_widget.count()):
                item = list_widget.item(i)
                if item.checkState() == Qt.Checked:
                    items.append(item)

            return items


        def addListItem(self, component, title, valid=True, checked=True):
            item = QListWidgetItem(title)
            item.component = component
            item.setFlags(item.flags() | Qt.ItemIsUserCheckable)
            if valid:
                pass
            else:
                item.setForeground(QColor('gray'))

            if checked:
                item.setCheckState(Qt.Checked)
            else:
                item.setCheckState(Qt.Unchecked)

            self.components_list.addItem(item)


    class UnInstallPage(QWizardPage):
        setProgress = pyqtSignal(int)
        message = pyqtSignal(str)

        def __init__(self, parent):
            QWizardPage.__init__(self)
            self.parent = parent

            self.setLayout(QGridLayout())
            self.setTitle('Uninstallation')
            self.setSubTitle('All selected components will be removed.')

            self.layout().addWidget(QLabel(u'Uninstallation progress'), 0, 0)
            self.progress = QProgressBar()
            self.progress.setMaximum(0)
            self.layout().addWidget(self.progress, 1, 0, 1, 2)

            self.log = QTextBrowser()
            self.layout().addWidget(self.log, 2, 0, 1, 2)

            self.setProgress.connect(self.progress.setValue)
            self.message.connect(self.log.append)
            self.is_done = False

        def initializePage(self):
            self.components = self.wizard().components
            self.startUninstallation()

        def startUninstallation(self):
            self.path = str(self.parent.options.install_path)

            self.w = Worker(lambda: self.uninstall(self.path, self.components))
            self.w.done.connect(self.endUninstall)
            self.w.error.connect(self.parent.printError)

            self.w.start()

        def uninstall(self, path, components):
            self.message.emit('Start uninstalling...')
            schema = Config(open('config/uninstall.yml'))

            self.progress.setMaximum(len(components))

            component_names = [x.name for x in components]

            i = 0
            for component in components:
                if component.name in component_names:
                    i += 1
                    self.setProgress.emit(i)
                    component.uninstall(schema[component.name], message=self.message.emit)

        def endUninstall(self):
            self.log.append(u'Finished')
            self.is_done = True
            self.completeChanged.emit()

        def isComplete(self):
            if self.is_done:
                self.wizard().finished.emit(1)
            return self.is_done

    def printError(self, e):
        print(e)