Ejemplo n.º 1
0
 def downloadVersions(self):
     directory = self.baseUrl.currentText()
     if not directory.endswith('/'):
         directory += '/'
     directory += self.machineType.currentText()
     directory += '/'
     self.directory = directory
     self.loader = HtmlLoader(directory)
     self.status.setText(i18n("Downloading directory listing..."))
     self.progress.setRange(0, 0)
     self.loader.done.connect(self.versionsDownloaded)
Ejemplo n.º 2
0
class LilyPondDownloadDialog(KDialog):
    def __init__(self, info):
        """info is a LilyPondInfoDialog (see settings.py)"""
        KDialog.__init__(self, info)
        self.info = info
        
        # local attributes
        self.job = None
        self.unpackJob = None
        
        self.setButtons(KDialog.ButtonCode(
            KDialog.Help | KDialog.Details | KDialog.Ok | KDialog.Cancel))
        layout = QGridLayout(self.mainWidget())
        
        self.setButtonText(KDialog.Ok, i18n("Install"))
        self.setButtonIcon(KDialog.Ok, KIcon("download"))
        self.setCaption(i18n("Download LilyPond"))
        self.setHelp("download-lilypond")
        
        l = QLabel(i18n(
            "With this tool you can download packaged binary releases "
            "of LilyPond for your operating system."))
        l.setWordWrap(True)
        layout.addWidget(l, 0, 0, 1, 2)
        
        v = self.lilyVersion = QComboBox()
        v.currentIndexChanged.connect(self.selectVersion, Qt.QueuedConnection)
        v.setToolTip(i18n(
            "Select the LilyPond version you want to download."))
        l = QLabel(i18n("Version:"))
        l.setBuddy(v)
        layout.addWidget(l, 1, 0)
        layout.addWidget(v, 1, 1)
        
        d = self.installDest = KUrlRequester()
        d.setMode(KFile.Mode(KFile.Directory | KFile.LocalOnly))
        d.setPath(config().readPathEntry(
            'lilypond install path', os.path.expanduser('~/lilypond_bin/')))
        d.setToolTip(i18n(
            "Select a writable directory you want to install LilyPond to.\n"
            "(A version-numbered directory will be created in this directory.)"))
        l = QLabel(i18n("Install into:"))
        l.setBuddy(d)
        layout.addWidget(l, 2, 0)
        layout.addWidget(d, 2, 1)
        
        s = self.status = QLabel()
        layout.addWidget(s, 3, 0, 1, 2)
        
        p = self.progress = QProgressBar()
        layout.addWidget(p, 4, 0, 1, 2)
        
        details = QGroupBox(i18n("Details"))
        layout.addWidget(details, 5, 0, 1, 2)
        layout = QGridLayout()
        details.setLayout(layout)

        b = self.baseUrl = QComboBox()
        b.setEditable(True)
        b.setToolTip(i18n(
            "The website where LilyPond binaries can be downloaded."))
        b.addItems(['http://download.linuxaudio.org/lilypond/binaries/'])
        b.setCurrentIndex(0)
        
        l = QLabel(i18n("Download from:"))
        l.setBuddy(b)
        layout.addWidget(l, 0, 0)
        layout.addWidget(b, 0, 1)
        
        m = self.machineType = QComboBox()
        items = [
            'linux-x86',
            'linux-64',
            'linux-ppc',
            'freebsd-x86',
            'freebsd-64',
            'darwin-x86',
            'darwin-ppc',
            ]
        m.addItems(items)

        l = QLabel(i18n("Machine type:"))
        l.setBuddy(m)
        layout.addWidget(l, 1, 0)
        layout.addWidget(m, 1, 1)
        
        u = self.packageUrl = KUrlRequester()
        u.setToolTip(i18n(
            "This is the URL to the package that will be downloaded and "
            "installed.\n"
            "You can also browse to other places to select a LilyPond package."))
        l = QLabel(i18n("Package Url:"))
        l.setBuddy(u)
        layout.addWidget(l, 2, 0)
        layout.addWidget(u, 2, 1)
        
        self.setDetailsWidget(details)
        
        # default for machine
        platform, machine = os.uname()[0::4]
        if '64' in machine:
            machine = '64'
        elif '86' in machine:
            machine = 'x86'
        elif 'ower' in machine or 'ppc' in machine:
            machine = 'ppc'
        mtype = platform.lower() + '-' + machine
        if mtype in items:
            m.setCurrentIndex(items.index(mtype))
        else:
            self.setDetailsWidgetVisible(True)
        m.currentIndexChanged.connect(self.downloadVersions)
        self.downloadVersions()
        
    def downloadVersions(self):
        directory = self.baseUrl.currentText()
        if not directory.endswith('/'):
            directory += '/'
        directory += self.machineType.currentText()
        directory += '/'
        self.directory = directory
        self.loader = HtmlLoader(directory)
        self.status.setText(i18n("Downloading directory listing..."))
        self.progress.setRange(0, 0)
        self.loader.done.connect(self.versionsDownloaded)
        
    def versionsDownloaded(self):
        self.progress.setRange(0, 100)
        self.progress.reset()
        self.status.setText('')
        if self.loader.error():
            self.status.setText(i18n(
                "No packages found. You can browse to a package manually."))
            self.setDetailsWidgetVisible(True)
            self.packageUrl.lineEdit().setFocus()
            return
        
        versions = {}
        versionStrings = {}
        for m in re.finditer(r'\bhref="(lilypond-.*?\.sh)"', self.loader.html()):
            fileName = m.group(1)
            m = _version_re.search(fileName)
            if m:
                versionStrings[fileName] = m.group()
                ver, build = m.group(1, 4)
                version = (tuple(map(int, re.findall(r'\d+', ver))), int(build or 0))
                versions[fileName] = version
        
        files = versions.keys()
        files.sort(key=versions.get)
        
        # add the versions
        self.lilyVersion.clear()
        self.items = []
        # determine last stable and development:
        stable, development = False, False
        for f in files[::-1]:
            if versions[f][0][1] & 1:
                if not development:
                    development = True
                    self.items.append(f)
                    self.lilyVersion.addItem(i18n(
                        "Latest Development Version (%1)", versionStrings[f]))
            elif not stable:
                stable = True
                self.items.append(f)
                self.lilyVersion.addItem(i18n(
                    "Latest Stable Version (%1)", versionStrings[f]))
            if stable and development:
                break
        
        for f in files:
            self.lilyVersion.addItem(versionStrings[f])
            self.items.append(f)
        self.lilyVersion.setCurrentIndex(0)

    def selectVersion(self, index):
        self.packageUrl.setUrl(KUrl(self.directory + self.items[index]))

    def done(self, result):
        if result == KDialog.Accepted:
            # Download (OK) clicked
            url = self.packageUrl.url()
            if not url.isEmpty():
                self.enableButtonOk(False)
                # save the install path
                config().writePathEntry('lilypond install path',
                    self.installDest.url().path())
                if url.isLocalFile():
                    self.unpack(url.path())
                else:
                    self.download(url)
        else:
            if self.downloadBusy():
                self.cancelDownload()
            elif not self.unpackBusy():
                KDialog.done(self, result)
    
    def download(self, url):
        """Download the package from given KUrl."""
        self.progress.setRange(0, 100)
        self.status.setText(i18n("Downloading %1...", url.fileName()))
        dest = KGlobal.dirs().saveLocation('tmp')
        self.job = KIO.copy(url, KUrl(dest),
            KIO.JobFlags(KIO.Overwrite | KIO.Resume | KIO.HideProgressInfo))
        QObject.connect(self.job, SIGNAL("percent(KJob*, unsigned long)"), self.slotPercent)
        QObject.connect(self.job, SIGNAL("result(KJob*)"), self.slotResult, Qt.QueuedConnection)
        self.job.start()
        
    def downloadBusy(self):
        return bool(self.job)
    
    def cancelDownload(self):
        self.job.kill()
        self.status.setText(i18n("Download cancelled."))
        self.enableButtonOk(True)
        self.progress.setValue(0)
        
    def slotPercent(self, job, percent):
        self.progress.setValue(percent)
        
    def slotResult(self):
        if self.job.error():
            self.status.setText(i18n("Download failed: %1", self.job.errorString()))
            self.enableButtonOk(True)
        else:
            fileName = self.job.srcUrls()[0].fileName()
            package = os.path.join(self.job.destUrl().path(), fileName)
            self.unpack(package)
        self.job = None

    def unpack(self, package):
        """Unpack the given lilypond .sh archive."""
        fileName = os.path.basename(package)
        ver = version(fileName) or 'unknown' # should not happen
        self.prefix = os.path.join(self.installDest.url().path(), ver)
        self.lilypond = os.path.join(self.prefix, "bin", "lilypond")
        if not os.path.exists(self.prefix):
            os.makedirs(self.prefix)
        elif os.path.exists(self.lilypond):
            result = KMessageBox.questionYesNoCancel(self, i18n(
                "LilyPond %1 seems already to be installed in %2.\n\n"
                "Do you want to use it or to remove and re-install?",
                ver, self.prefix), None,
                KGuiItem(i18n("Use existing LilyPond")),
                KGuiItem(i18n("Remove and re-install")))
            if result == KMessageBox.Yes:
                self.info.lilypond.setText(self.lilypond)
                self.enableButtonOk(True)
                KDialog.done(self, KDialog.Accepted)
                return
            elif result == KMessageBox.No:
                shutil.rmtree(self.prefix, True)
            else: # Cancel
                self.progress.reset()
                self.enableButtonOk(True)
                return
        self.status.setText(i18n("Unpacking %1...", fileName))
        self.progress.setRange(0, 0)
        unpack = self.unpackJob = QProcess()
        unpack.setProcessChannelMode(QProcess.MergedChannels)
        unpack.setWorkingDirectory(self.prefix)
        unpack.finished.connect(self.unpackFinished)
        unpack.error.connect(self.unpackError)
        unpack.start("sh", [package, "--batch", "--prefix", self.prefix])
    
    def unpackBusy(self):
        return bool(self.unpackJob and self.unpackJob.state())
        
    def unpackFinished(self, exitCode, exitStatus):
        self.progress.setRange(0, 100)
        self.progress.reset()
        self.enableButtonOk(True)
        if exitStatus == QProcess.NormalExit and exitCode == 0:
            self.status.setText(i18n("Unpacking finished."))
            self.info.lilypond.setText(self.lilypond)
            KDialog.done(self, KDialog.Accepted)
        else:
            self.status.setText(i18n("Unpacking failed."))
            KMessageBox.error(self, i18n("An error occurred:\n\n%1",
                str(self.unpackJob.readAllStandardOutput())))
        
    def unpackError(self, err):
        self.progress.setRange(0, 100)
        self.progress.reset()
        self.enableButtonOk(True)
        self.status.setText(i18n("Unpacking failed."))
        KMessageBox.error(self, i18n("An error occurred:\n\n%1",
            self.unpackJob.errorString()))