From eee37a74faeb5bd36794981b4a5b10144fc244e4 Mon Sep 17 00:00:00 2001 From: kh1 Date: Tue, 28 Jan 2014 15:49:35 +0100 Subject: Slightly faster version of asynchronous metadata download. Change-Id: I63793529eeebfd3ea0a325cabe79d646015dc3bc Reviewed-by: Tim Jenssen --- src/libs/installer/getrepositoriesmetainfojob.cpp | 208 ------------ src/libs/installer/getrepositoriesmetainfojob.h | 105 ------ src/libs/installer/getrepositorymetainfojob.h | 129 -------- src/libs/installer/installer.pro | 11 +- src/libs/installer/metadatajob.cpp | 380 ++++++++++++++++++++++ src/libs/installer/metadatajob.h | 107 ++++++ src/libs/installer/metadatajob_p.h | 120 +++++++ src/libs/installer/packagemanagercore.cpp | 9 +- src/libs/installer/packagemanagercore_p.cpp | 47 ++- src/libs/installer/packagemanagercore_p.h | 5 +- src/sdk/installerbasecommons.cpp | 11 + src/sdk/installerbasecommons.h | 1 + 12 files changed, 654 insertions(+), 479 deletions(-) delete mode 100644 src/libs/installer/getrepositoriesmetainfojob.cpp delete mode 100644 src/libs/installer/getrepositoriesmetainfojob.h delete mode 100644 src/libs/installer/getrepositorymetainfojob.h create mode 100644 src/libs/installer/metadatajob.cpp create mode 100644 src/libs/installer/metadatajob.h create mode 100644 src/libs/installer/metadatajob_p.h diff --git a/src/libs/installer/getrepositoriesmetainfojob.cpp b/src/libs/installer/getrepositoriesmetainfojob.cpp deleted file mode 100644 index 284d690dd..000000000 --- a/src/libs/installer/getrepositoriesmetainfojob.cpp +++ /dev/null @@ -1,208 +0,0 @@ -/************************************************************************** -** -** Copyright (C) 2012-2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the Qt Installer Framework. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -**************************************************************************/ - -#include "getrepositoriesmetainfojob.h" - -#include "getrepositorymetainfojob.h" -#include "productkeycheck.h" -#include "packagemanagercore_p.h" - -#include - -using namespace KDUpdater; -using namespace QInstaller; - - -// -- GetRepositoriesMetaInfoJob - -GetRepositoriesMetaInfoJob::GetRepositoriesMetaInfoJob(PackageManagerCore *core) - : KDJob(core) - , m_canceled(false) - , m_silentRetries(3) - , m_haveIgnoredError(false) - , m_core(core) -{ - setTotalAmount(100); - setCapabilities(Cancelable); -} - -QStringList GetRepositoriesMetaInfoJob::temporaryDirectories() const -{ - return m_repositoryByTemporaryDirectory.keys(); -} - -QStringList GetRepositoriesMetaInfoJob::releaseTemporaryDirectories() const -{ - m_tempDirDeleter.releaseAll(); - return m_repositoryByTemporaryDirectory.keys(); -} - -Repository GetRepositoriesMetaInfoJob::repositoryForTemporaryDirectory(const QString &tmpDir) const -{ - return m_repositoryByTemporaryDirectory.value(tmpDir); -} - -int GetRepositoriesMetaInfoJob::numberOfRetrievedRepositories() const -{ - return m_repositoryByTemporaryDirectory.size(); -} - -int GetRepositoriesMetaInfoJob::silentRetries() const -{ - return m_silentRetries; -} - -void GetRepositoriesMetaInfoJob::setSilentRetries(int retries) -{ - m_silentRetries = retries; -} - -void GetRepositoriesMetaInfoJob::reset() -{ - m_canceled = false; - m_silentRetries = 3; - m_errorString.clear(); - m_haveIgnoredError = false; - - m_repositories.clear(); - m_tempDirDeleter.releaseAndDeleteAll(); - m_repositoryByTemporaryDirectory.clear(); - - setError(KDJob::NoError); - setErrorString(QString()); - setCapabilities(Cancelable); -} - -bool GetRepositoriesMetaInfoJob::isCanceled() const -{ - return m_canceled; -} - -// -- private Q_SLOTS - -void GetRepositoriesMetaInfoJob::doStart() -{ - if ((m_core->isInstaller() && !m_core->isOfflineOnly()) || (m_core->isUpdater() - || m_core->isPackageManager())) { - const ProductKeyCheck *const productKeyCheck = ProductKeyCheck::instance(); - foreach (const Repository &repo, m_core->settings().repositories()) { - if (repo.isEnabled() && productKeyCheck->isValidRepository(repo)) - m_repositories += repo; - } - } - - fetchNextRepo(); -} - -void GetRepositoriesMetaInfoJob::doCancel() -{ - m_canceled = true; - if (m_job) - m_job->cancel(); -} - -void GetRepositoriesMetaInfoJob::fetchNextRepo() -{ - if (m_job) { - m_job->deleteLater(); - m_job = 0; - } - - if (m_canceled) { - emitFinishedWithError(KDJob::Canceled, m_errorString); - return; - } - - if (m_repositories.isEmpty()) { - if (m_haveIgnoredError) - emitFinishedWithError(QInstaller::UserIgnoreError, m_errorString); - else - emitFinished(); - return; - } - - m_job = new GetRepositoryMetaInfoJob(m_core, this); - connect(m_job, SIGNAL(finished(KDJob*)), this, SLOT(jobFinished(KDJob*))); - connect(m_job, SIGNAL(infoMessage(KDJob*, QString)), this, SIGNAL(infoMessage(KDJob*, QString))); - connect(m_job, SIGNAL(progress(KDJob*, quint64, quint64)), this, SIGNAL(progress(KDJob*, - quint64, quint64))); - - m_job->setSilentRetries(silentRetries()); - m_job->setRepository(m_repositories.takeLast()); - m_job->start(); -} - -void GetRepositoriesMetaInfoJob::jobFinished(KDJob *j) -{ - const GetRepositoryMetaInfoJob *const job = qobject_cast(j); - Q_ASSERT(job); - - if (job->error() != KDJob::NoError && !job->temporaryDirectory().isEmpty()) { - try { - removeDirectory(job->temporaryDirectory()); - } catch (...) { - } - } - - if (job->error() == KDJob::Canceled - || (job->error() >= KDJob::UserDefinedError && job->error() < QInstaller::UserIgnoreError)) { - emit infoMessage(j, job->errorString()); - qDebug() << job->errorString(); - emitFinishedWithError(job->error(), job->errorString()); - return; - } - - if (job->error() == QInstaller::UserIgnoreError) { - m_haveIgnoredError = true; - m_errorString = job->errorString(); - } else { - const QString &tmpdir = job->releaseTemporaryDirectory(); - job->m_tempDirDeleter.passAndRelease(m_tempDirDeleter, tmpdir); - m_repositoryByTemporaryDirectory.insert(tmpdir, job->repository()); - } - - if (job->error() == QInstaller::RepositoryUpdatesReceived) { - reset(); - QMetaObject::invokeMethod(this, "doStart", Qt::QueuedConnection); - } else { - QMetaObject::invokeMethod(this, "fetchNextRepo", Qt::QueuedConnection); - } -} diff --git a/src/libs/installer/getrepositoriesmetainfojob.h b/src/libs/installer/getrepositoriesmetainfojob.h deleted file mode 100644 index 2cc53b82a..000000000 --- a/src/libs/installer/getrepositoriesmetainfojob.h +++ /dev/null @@ -1,105 +0,0 @@ -/************************************************************************** -** -** Copyright (C) 2012-2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the Qt Installer Framework. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -**************************************************************************/ -#ifndef GETREPOSITORIESMETAINFOJOB_H -#define GETREPOSITORIESMETAINFOJOB_H - -#include "fileutils.h" -#include "installer_global.h" -#include "repository.h" - -#include "kdjob.h" - -#include -#include -#include -#include - -namespace KDUpdater { - class FileDownloader; -} - -namespace QInstaller { - -class GetRepositoryMetaInfoJob; -class PackageManagerCore; - -class INSTALLER_EXPORT GetRepositoriesMetaInfoJob : public KDJob -{ - Q_OBJECT - -public: - explicit GetRepositoriesMetaInfoJob(PackageManagerCore *core); - - QStringList temporaryDirectories() const; - QStringList releaseTemporaryDirectories() const; - Repository repositoryForTemporaryDirectory(const QString &tmpDir) const; - - int numberOfRetrievedRepositories() const; - - int silentRetries() const; - void setSilentRetries(int retries); - - void reset(); - bool isCanceled() const; - -private Q_SLOTS: - /* reimp */ void doStart(); - /* reimp */ void doCancel(); - - void fetchNextRepo(); - void jobFinished(KDJob*); - -private: - bool m_canceled; - int m_silentRetries; - bool m_haveIgnoredError; - PackageManagerCore *m_core; - - QString m_errorString; - QList m_repositories; - mutable TempDirDeleter m_tempDirDeleter; - QPointer m_job; - QHash m_repositoryByTemporaryDirectory; -}; - -} // namespace QInstaller - -#endif // GETREPOSITORIESMETAINFOJOB_H diff --git a/src/libs/installer/getrepositorymetainfojob.h b/src/libs/installer/getrepositorymetainfojob.h deleted file mode 100644 index 23909a8cd..000000000 --- a/src/libs/installer/getrepositorymetainfojob.h +++ /dev/null @@ -1,129 +0,0 @@ -/************************************************************************** -** -** Copyright (C) 2012-2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the Qt Installer Framework. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -**************************************************************************/ -#ifndef GETREPOSITORYMETAINFOJOB_H -#define GETREPOSITORYMETAINFOJOB_H - -#include "downloadfiletask.h" - -#include "fileutils.h" -#include "installer_global.h" -#include "repository.h" - -#include "kdjob.h" - -#include -#include -#include -#include -#include - -namespace KDUpdater { - class FileDownloader; -} - -namespace QInstaller { - -class GetRepositoriesMetaInfoJob; -class PackageManagerCore; - -class INSTALLER_EXPORT GetRepositoryMetaInfoJob : public KDJob -{ - Q_OBJECT - Q_DISABLE_COPY(GetRepositoryMetaInfoJob) - - class ZipRunnable; - friend class QInstaller::GetRepositoriesMetaInfoJob; - -public: - explicit GetRepositoryMetaInfoJob(PackageManagerCore *core, QObject *parent = 0); - ~GetRepositoryMetaInfoJob(); - - Repository repository() const; - void setRepository(const Repository &r); - - int silentRetries() const; - void setSilentRetries(int retries); - - QString temporaryDirectory() const; - QString releaseTemporaryDirectory() const; - -private: - /* reimp */ void doStart(); - /* reimp */ void doCancel(); - void finished(int error, const QString &errorString = QString()); - bool updateRepositories(QSet *repositories, const QString &username, - const QString &password, const QString &displayname = QString()); - -private Q_SLOTS: - void startUpdatesXmlDownload(); - void updatesXmlDownloadCanceled(); - void updatesXmlDownloadFinished(); - void updatesXmlDownloadError(const QString &error); - - void downloadMetaInfo(); - void metaInfoDownloadFinished(); - void onProgressValueChanged(int progress); - void unzipFinished(bool status, const QString &error); - - void onAuthenticatorChanged(const QAuthenticator &authenticator); - -private: - bool m_canceled; - int m_silentRetries; - int m_retriesLeft; - Repository m_repository; - QStringList m_packageNames; - QStringList m_packageVersions; - QStringList m_packageHash; - KDUpdater::FileDownloader *m_downloader; - QString m_temporaryDirectory; - mutable TempDirDeleter m_tempDirDeleter; - - QThreadPool m_threadPool; - PackageManagerCore *m_core; - - DownloadFileTask m_metaDataTask; - QFutureWatcher *m_watcher; -}; - -} // namespace QInstaller - -#endif // GETREPOSITORYMETAINFOJOB_H diff --git a/src/libs/installer/installer.pro b/src/libs/installer/installer.pro index 766525e17..837196c5f 100644 --- a/src/libs/installer/installer.pro +++ b/src/libs/installer/installer.pro @@ -70,7 +70,6 @@ HEADERS += packagemanagercore.h \ installiconsoperation.h \ selfrestartoperation.h \ settings.h \ - getrepositorymetainfojob.h \ downloadarchivesjob.h \ init.h \ updater.h \ @@ -86,7 +85,6 @@ HEADERS += packagemanagercore.h \ minimumprogressoperation.h \ performinstallationform.h \ messageboxhandler.h \ - getrepositoriesmetainfojob.h \ licenseoperation.h \ component_p.h \ qtcreator_constants.h \ @@ -112,7 +110,9 @@ HEADERS += packagemanagercore.h \ downloadfiletask_p.h \ unziptask.h \ observer.h \ - runextensions.h + runextensions.h \ + metadatajob.h \ + metadatajob_p.h SOURCES += packagemanagercore.cpp \ packagemanagercore_p.cpp \ @@ -144,7 +144,6 @@ HEADERS += packagemanagercore.h \ environmentvariablesoperation.cpp \ installiconsoperation.cpp \ selfrestartoperation.cpp \ - getrepositorymetainfojob.cpp \ downloadarchivesjob.cpp \ init.cpp \ updater.cpp \ @@ -160,7 +159,6 @@ HEADERS += packagemanagercore.h \ minimumprogressoperation.cpp \ performinstallationform.cpp \ messageboxhandler.cpp \ - getrepositoriesmetainfojob.cpp \ licenseoperation.cpp \ component_p.cpp \ qprocesswrapper.cpp \ @@ -182,7 +180,8 @@ HEADERS += packagemanagercore.h \ copyfiletask.cpp \ downloadfiletask.cpp \ unziptask.cpp \ - observer.cpp + observer.cpp \ + metadatajob.cpp RESOURCES += resources/patch_file_lists.qrc \ resources/installer.qrc diff --git a/src/libs/installer/metadatajob.cpp b/src/libs/installer/metadatajob.cpp new file mode 100644 index 000000000..d326b70bd --- /dev/null +++ b/src/libs/installer/metadatajob.cpp @@ -0,0 +1,380 @@ +/************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Installer Framework. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +**************************************************************************/ +#include "metadatajob.h" +#include "errors.h" +#include "messageboxhandler.h" +#include "metadatajob_p.h" +#include "packagemanagercore.h" +#include "productkeycheck.h" +#include "qinstallerglobal.h" +#include "settings.h" + +namespace QInstaller { + +MetadataJob::MetadataJob(QObject *parent) + : KDJob(parent) + , m_core(0) +{ + setCapabilities(Cancelable); + connect(&m_xmlTask, SIGNAL(finished()), this, SLOT(xmlTaskFinished())); + connect(&m_metadataTask, SIGNAL(finished()), this, SLOT(metadataTaskFinished())); + connect(&m_metadataTask, SIGNAL(progressValueChanged(int)), this, SLOT(progressChanged(int))); +} + +MetadataJob::~MetadataJob() +{ + reset(); +} + +Repository MetadataJob::repositoryForDirectory(const QString &directory) const +{ + return m_metadata.value(directory).repository; +} + + +// -- private slots + +void MetadataJob::doStart() +{ + reset(); + if (!m_core) { + emitFinishedWithError(KDJob::Canceled, tr("Missing package manager core engine.")); + return; // We can't do anything here without core, so avoid tons of !m_core checks. + } + + emit infoMessage(this, tr("Preparing meta information download...")); + const bool onlineInstaller = m_core->isInstaller() && !m_core->isOfflineOnly(); + if (onlineInstaller || (m_core->isUpdater() || m_core->isPackageManager())) { + QList items; + const ProductKeyCheck *const productKeyCheck = ProductKeyCheck::instance(); + foreach (const Repository &repo, m_core->settings().repositories()) { + if (repo.isEnabled() && productKeyCheck->isValidRepository(repo)) { + QAuthenticator authenticator; + authenticator.setUser(repo.username()); + authenticator.setPassword(repo.password()); + + // append a random string to avoid proxy caches + FileTaskItem item(repo.url().toString() + QString::fromLatin1("/Updates.xml?") + .append(QString::number(qrand() * qrand()))); + item.insert(TaskRole::UserRole, QVariant::fromValue(repo)); + item.insert(TaskRole::Authenticator, QVariant::fromValue(authenticator)); + items.append(item); + } + } + DownloadFileTask *const xmlTask = new DownloadFileTask(items); + m_xmlTask.setFuture(QtConcurrent::run(&DownloadFileTask::doTask, xmlTask)); + } else { + emitFinished(); + } +} + +void MetadataJob::doCancel() +{ + reset(); + emitFinishedWithError(KDJob::Canceled, tr("Meta data download canceled.")); +} + +void MetadataJob::xmlTaskFinished() +{ + Status status = XmlDownloadFailure; + try { + m_xmlTask.waitForFinished(); + status = parseUpdatesXml(m_xmlTask.future().results()); + } catch (const FileTaskException &e) { + reset(); + emitFinishedWithError(QInstaller::DownloadError, e.message()); + } catch (const QUnhandledException &e) { + reset(); + emitFinishedWithError(QInstaller::DownloadError, QLatin1String(e.what())); + } catch (...) { + reset(); + emitFinishedWithError(QInstaller::DownloadError, tr("Unknown exception during download.")); + } + + if (error() != KDJob::NoError) + return; + + if (status == XmlDownloadSuccess) { + setProcessedAmount(0); + DownloadFileTask *const metadataTask = new DownloadFileTask(m_packages); + m_metadataTask.setFuture(QtConcurrent::run(&DownloadFileTask::doTask, metadataTask)); + emit infoMessage(this, tr("Retrieving meta information from remote repository...")); + } else if (status == XmlDownloadRetry) { + QMetaObject::invokeMethod(this, "doStart", Qt::QueuedConnection); + } else { + reset(); + emitFinishedWithError(QInstaller::DownloadError, tr("Failure to fetch repositories.")); + } +} + +void MetadataJob::unzipTaskFinished() +{ + QFutureWatcher *watcher = static_cast *>(sender()); + try { + watcher->waitForFinished(); // trigger possible exceptions + } catch (const UnzipArchiveException &e) { + reset(); + emitFinishedWithError(QInstaller::ExtractionError, e.message()); + } catch (const QUnhandledException &e) { + reset(); + emitFinishedWithError(QInstaller::DownloadError, QLatin1String(e.what())); + } catch (...) { + reset(); + emitFinishedWithError(QInstaller::DownloadError, tr("Unknown exception during extracting.")); + } + delete m_unzipTasks.value(watcher); + m_unzipTasks.remove(watcher); + delete watcher; + + if (error() != KDJob::NoError) + return; + if (m_unzipTasks.isEmpty()) { + setProcessedAmount(100); + emitFinished(); + } +} + +void MetadataJob::progressChanged(int progress) +{ + setProcessedAmount(progress); +} + +void MetadataJob::metadataTaskFinished() +{ + try { + m_metadataTask.waitForFinished(); + QFuture future = m_metadataTask.future(); + if (future.resultCount() > 0) { + emit infoMessage(this, tr("Extracting meta information...")); + foreach (const FileTaskResult &result, future.results()) { + const FileTaskItem item = result.value(TaskRole::TaskItem).value(); + UnzipArchiveTask *task = new UnzipArchiveTask(result.target(), + item.value(TaskRole::UserRole).toString()); + + QFutureWatcher *watcher = new QFutureWatcher(); + m_unzipTasks.insert(watcher, qobject_cast (task)); + connect(watcher, SIGNAL(finished()), this, SLOT(unzipTaskFinished())); + watcher->setFuture(QtConcurrent::run(&UnzipArchiveTask::doTask, task)); + } + } else { + emitFinished(); + } + } catch (const FileTaskException &e) { + reset(); + emitFinishedWithError(QInstaller::DownloadError, e.message()); + } catch (const QUnhandledException &e) { + reset(); + emitFinishedWithError(QInstaller::DownloadError, QLatin1String(e.what())); + } catch (...) { + reset(); + emitFinishedWithError(QInstaller::DownloadError, tr("Unknown exception during download.")); + } +} + + +// -- private + +void MetadataJob::reset() +{ + m_packages.clear(); + m_metadata.clear(); + + setError(KDJob::NoError); + setErrorString(QString()); + setCapabilities(Cancelable); + + try { + m_xmlTask.cancel(); + m_metadataTask.cancel(); + foreach (QFutureWatcher *const watcher, m_unzipTasks.keys()) + watcher->cancel(); + foreach (QObject *const object, m_unzipTasks) + object->deleteLater(); + } catch (...) {} + m_tempDirDeleter.releaseAndDeleteAll(); +} + +MetadataJob::Status MetadataJob::parseUpdatesXml(const QList &results) +{ + foreach (const FileTaskResult &result, results) { + if (error() != KDJob::NoError) + return XmlDownloadFailure; + + Metadata metadata; + try { + metadata.directory = createTemporaryDirectory(QLatin1String("remoterepo-")); + m_tempDirDeleter.add(metadata.directory); + } catch (const QInstaller::Error &error) { + qDebug() << error.message(); + return XmlDownloadFailure; + } + + QFile file(result.target()); + if (!file.rename(metadata.directory + QLatin1String("/Updates.xml"))) { + qDebug() << "Could not rename target to Updates.xml. Error:" << file.errorString(); + return XmlDownloadFailure; + } + + if (!file.open(QIODevice::ReadOnly)) { + qDebug() << "Could not open Updates.xml for reading. Error:" << file.errorString(); + return XmlDownloadFailure; + } + + QString error; + QDomDocument doc; + if (!doc.setContent(&file, &error)) { + qDebug() << QString::fromLatin1("Could not fetch a valid version of Updates.xml from " + "repository: %1. Error: %2").arg(metadata.repository.displayname(), error); + return XmlDownloadFailure; + } + file.close(); + + const FileTaskItem item = result.value(TaskRole::TaskItem).value(); + metadata.repository = item.value(TaskRole::UserRole).value(); + const bool online = !(metadata.repository.url().scheme()).isEmpty(); + + const QDomElement root = doc.documentElement(); + QDomNodeList children = root.childNodes(); + for (int i = 0; i < children.count(); ++i) { + const QDomElement el = children.at(i).toElement(); + if (!el.isNull() && el.tagName() == QLatin1String("PackageUpdate")) { + const QDomNodeList c2 = el.childNodes(); + QString packageName, packageVersion, packageHash; + for (int j = 0; j < c2.count(); ++j) { + if (c2.at(j).toElement().tagName() == scName) + packageName = c2.at(j).toElement().text(); + else if (c2.at(j).toElement().tagName() == scRemoteVersion) + packageVersion = c2.at(j).toElement().text(); + else if (c2.at(j).toElement().tagName() == QLatin1String("SHA1")) + packageHash = c2.at(j).toElement().text(); + } + const QString repoUrl = metadata.repository.url().toString(); + FileTaskItem item(QString::fromLatin1("%1/%2/%3meta.7z").arg(repoUrl, + packageName, (online ? packageVersion : QString()))); + item.insert(TaskRole::UserRole, metadata.directory); + item.insert(TaskRole::Checksum, packageHash.toLatin1()); + m_packages.append(item); + } + } + m_metadata.insert(metadata.directory, metadata); + + // search for additional repositories that we might need to check + const QDomNode repositoryUpdate = root.firstChildElement(QLatin1String("RepositoryUpdate")); + if (repositoryUpdate.isNull()) + continue; + + QHash > repositoryUpdates; + children = repositoryUpdate.toElement().childNodes(); + for (int i = 0; i < children.count(); ++i) { + const QDomElement el = children.at(i).toElement(); + if (!el.isNull() && el.tagName() == QLatin1String("Repository")) { + const QString action = el.attribute(QLatin1String("action")); + if (action == QLatin1String("add")) { + // add a new repository to the defaults list + Repository repository(el.attribute(QLatin1String("url")), true); + repository.setUsername(el.attribute(QLatin1String("username"))); + repository.setPassword(el.attribute(QLatin1String("password"))); + repository.setDisplayName(el.attribute(QLatin1String("displayname"))); + if (ProductKeyCheck::instance()->isValidRepository(repository)) { + repositoryUpdates.insertMulti(action, qMakePair(repository, Repository())); + qDebug() << "Repository to add:" << repository.displayname(); + } + } else if (action == QLatin1String("remove")) { + // remove possible default repositories using the given server url + Repository repository(el.attribute(QLatin1String("url")), true); + repositoryUpdates.insertMulti(action, qMakePair(repository, Repository())); + + qDebug() << "Repository to remove:" << repository.displayname(); + } else if (action == QLatin1String("replace")) { + // replace possible default repositories using the given server url + Repository oldRepository(el.attribute(QLatin1String("oldUrl")), true); + Repository newRepository(el.attribute(QLatin1String("newUrl")), true); + newRepository.setUsername(el.attribute(QLatin1String("username"))); + newRepository.setPassword(el.attribute(QLatin1String("password"))); + newRepository.setDisplayName(el.attribute(QLatin1String("displayname"))); + + if (ProductKeyCheck::instance()->isValidRepository(newRepository)) { + // store the new repository and the one old it replaces + repositoryUpdates.insertMulti(action, qMakePair(newRepository, oldRepository)); + qDebug() << "Replace repository:" << oldRepository.displayname() << "with:" + << newRepository.displayname(); + } + } else { + qDebug() << "Invalid additional repositories action set in Updates.xml fetched " + "from:" << metadata.repository.displayname() << "Line:" << el.lineNumber(); + } + } + } + + if (!repositoryUpdates.isEmpty()) { + Settings &s = m_core->settings(); + const QSet temporaries = s.temporaryRepositories(); + // in case the temp repository introduced something new, we only want that temporary + if (temporaries.contains(metadata.repository)) { + QSet tmpRepositories; + typedef QPair RepositoryPair; + + QList values = repositoryUpdates.values(QLatin1String("add")); + foreach (const RepositoryPair &value, values) + tmpRepositories.insert(value.first); + + values = repositoryUpdates.values(QLatin1String("replace")); + foreach (const RepositoryPair &value, values) + tmpRepositories.insert(value.first); + + tmpRepositories = tmpRepositories.subtract(temporaries); + if (tmpRepositories.count() > 0) { + s.addTemporaryRepositories(tmpRepositories, true); + QFile::remove(result.target()); + return XmlDownloadRetry; + } + } else if (s.updateDefaultRepositories(repositoryUpdates) == Settings::UpdatesApplied) { + if (m_core->isUpdater() || m_core->isPackageManager()) + m_core->writeMaintenanceConfigFiles(); + QFile::remove(result.target()); + return XmlDownloadRetry; + } + } + } + return XmlDownloadSuccess; +} + +} // namespace QInstaller diff --git a/src/libs/installer/metadatajob.h b/src/libs/installer/metadatajob.h new file mode 100644 index 000000000..a10eb083b --- /dev/null +++ b/src/libs/installer/metadatajob.h @@ -0,0 +1,107 @@ +/************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Installer Framework. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +**************************************************************************/ + +#ifndef METADATAJOB_H +#define METADATAJOB_H + +#include "downloadfiletask.h" +#include "fileutils.h" +#include "kdjob.h" +#include "repository.h" + +#include + +namespace QInstaller { + +class PackageManagerCore; + +struct Metadata +{ + QString directory; + Repository repository; +}; + +class INSTALLER_EXPORT MetadataJob : public KDJob +{ + Q_OBJECT + Q_DISABLE_COPY(MetadataJob) + + enum Status { + XmlDownloadRetry, + XmlDownloadFailure, + XmlDownloadSuccess + }; + +public: + explicit MetadataJob(QObject *parent = 0); + ~MetadataJob(); + + QList metadata() const { return m_metadata.values(); } + Repository repositoryForDirectory(const QString &directory) const; + void setPackageManagerCore(PackageManagerCore *core) { m_core = core; } + +private slots: + void doStart(); + void doCancel(); + + void xmlTaskFinished(); + void unzipTaskFinished(); + void metadataTaskFinished(); + void progressChanged(int progress); + +private: + void reset(); + Status parseUpdatesXml(const QList &results); + +private: + PackageManagerCore *m_core; + + QList m_packages; + TempDirDeleter m_tempDirDeleter; + QHash m_metadata; + QFutureWatcher m_xmlTask; + QFutureWatcher m_metadataTask; + QHash *, QObject*> m_unzipTasks; +}; + +} // namespace QInstaller + +#endif // METADATAJOB_H diff --git a/src/libs/installer/metadatajob_p.h b/src/libs/installer/metadatajob_p.h new file mode 100644 index 000000000..3b1835a3c --- /dev/null +++ b/src/libs/installer/metadatajob_p.h @@ -0,0 +1,120 @@ +/************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Installer Framework. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +**************************************************************************/ + +#ifndef METADATAJOB_P_H +#define METADATAJOB_P_H + +#include "lib7z_facade.h" +#include "metadatajob.h" + +namespace QInstaller{ + +class UnzipArchiveException : public QException +{ +public: + UnzipArchiveException() {} + ~UnzipArchiveException() throw() {} + explicit UnzipArchiveException(const QString &message) + : m_message(message) + {} + + void raise() const { throw *this; } + QString message() const { return m_message; } + UnzipArchiveException *clone() const { return new UnzipArchiveException(*this); } + +private: + QString m_message; +}; + +class UnzipArchiveTask : public AbstractTask +{ + Q_OBJECT + Q_DISABLE_COPY(UnzipArchiveTask) + +public: + UnzipArchiveTask(const QString &arcive, const QString &target) + : m_archive(arcive), m_targetDir(target) + {} + ~UnzipArchiveTask() + { + QFile file(m_archive); + if (!file.remove()) { + qWarning("Could not delete file %s: %s", qPrintable(m_archive), qPrintable(file + .errorString())); + } + } + void doTask(QFutureInterface &fi) + { + fi.reportStarted(); + fi.setExpectedResultCount(1); + + if (fi.isCanceled()) { + fi.reportFinished(); + return; // ignore already canceled + } + + QFile archive(m_archive); + if (archive.open(QIODevice::ReadOnly)) { + try { + Lib7z::extractArchive(&archive, m_targetDir); + } catch (const Lib7z::SevenZipException& e) { + fi.reportException(UnzipArchiveException(MetadataJob::tr("Error while extracting " + "'%1': %2").arg(m_archive, e.message()))); + } catch (...) { + fi.reportException(UnzipArchiveException(MetadataJob::tr("Unknown exception " + "caught while extracting %1.").arg(m_archive))); + } + } else { + fi.reportException(UnzipArchiveException(MetadataJob::tr("Could not open %1 for " + "reading. Error: %2").arg(m_archive, archive.errorString()))); + } + + fi.reportFinished(); + } + +private: + QString m_archive; + QString m_targetDir; +}; + +} // namespace QInstaller + +#endif // METADATAJOB_P_H diff --git a/src/libs/installer/packagemanagercore.cpp b/src/libs/installer/packagemanagercore.cpp index 3c6b40724..43ac03510 100644 --- a/src/libs/installer/packagemanagercore.cpp +++ b/src/libs/installer/packagemanagercore.cpp @@ -49,7 +49,6 @@ #include "errors.h" #include "fsengineclient.h" #include "globals.h" -#include "getrepositoriesmetainfojob.h" #include "messageboxhandler.h" #include "packagemanagerproxyfactory.h" #include "progresscoordinator.h" @@ -465,8 +464,7 @@ void PackageManagerCore::setCompleteUninstallation(bool complete) */ void PackageManagerCore::cancelMetaInfoJob() { - if (d->m_repoMetaInfoJob) - d->m_repoMetaInfoJob->cancel(); + d->m_metadataJob.cancel(); } /*! @@ -2093,8 +2091,9 @@ bool PackageManagerCore::updateComponentData(struct Data &data, Component *compo lastLocalPath = localPath; } - if (d->m_repoMetaInfoJob) { - const Repository &repo = d->m_repoMetaInfoJob->repositoryForTemporaryDirectory(localPath); + + const Repository repo = d->m_metadataJob.repositoryForDirectory(localPath); + if (repo.isValid()) { component->setRepositoryUrl(repo.url()); component->setValue(QLatin1String("username"), repo.username()); component->setValue(QLatin1String("password"), repo.password()); diff --git a/src/libs/installer/packagemanagercore_p.cpp b/src/libs/installer/packagemanagercore_p.cpp index 33565bfd3..9fa193754 100644 --- a/src/libs/installer/packagemanagercore_p.cpp +++ b/src/libs/installer/packagemanagercore_p.cpp @@ -207,7 +207,6 @@ PackageManagerCorePrivate::PackageManagerCorePrivate(PackageManagerCore *core) , m_updaterApplication(new DummyConfigurationInterface) , m_FSEngineClientHandler(0) , m_core(core) - , m_repoMetaInfoJob(0) , m_updates(false) , m_repoFetched(false) , m_updateSourcesAdded(false) @@ -235,7 +234,6 @@ PackageManagerCorePrivate::PackageManagerCorePrivate(PackageManagerCore *core, q , m_performedOperationsOld(performedOperations) , m_dependsOnLocalInstallerBinary(false) , m_core(core) - , m_repoMetaInfoJob(0) , m_updates(false) , m_repoFetched(false) , m_updateSourcesAdded(false) @@ -650,14 +648,13 @@ void PackageManagerCorePrivate::initialize(const QHash ¶ms m_updaterApplication.updateSourcesInfo()->setModified(false); } - if (!m_repoMetaInfoJob) { - m_repoMetaInfoJob = new GetRepositoriesMetaInfoJob(m_core); - m_repoMetaInfoJob->setAutoDelete(false); - connect(m_repoMetaInfoJob, SIGNAL(infoMessage(KDJob*, QString)), this, - SLOT(infoMessage(KDJob*, QString))); - connect(m_repoMetaInfoJob, SIGNAL(progress(KDJob *, quint64, quint64)), this, - SLOT(infoProgress(KDJob *, quint64, quint64))); - } + m_metadataJob.disconnect(); + m_metadataJob.setAutoDelete(false); + m_metadataJob.setPackageManagerCore(m_core); + connect(&m_metadataJob, SIGNAL(infoMessage(KDJob*, QString)), this, + SLOT(infoMessage(KDJob*, QString))); + connect(&m_metadataJob, SIGNAL(progress(KDJob *, quint64, quint64)), this, + SLOT(infoProgress(KDJob *, quint64, quint64))); KDUpdater::FileDownloaderFactory::instance().setProxyFactory(m_core->proxyFactory()); } @@ -2174,21 +2171,21 @@ bool PackageManagerCorePrivate::fetchMetaInformationFromRepositories() m_repoFetched = false; m_updateSourcesAdded = false; - m_repoMetaInfoJob->reset(); try { - m_repoMetaInfoJob->start(); - m_repoMetaInfoJob->waitForFinished(); + m_metadataJob.start(); + m_metadataJob.waitForFinished(); } catch (Error &error) { - setStatus(PackageManagerCore::Failure, tr("Could not retrieve meta information: %1").arg(error.message())); + setStatus(PackageManagerCore::Failure, tr("Could not retrieve meta information: %1") + .arg(error.message())); return m_repoFetched; } - if (m_repoMetaInfoJob->isCanceled() || m_repoMetaInfoJob->error() != KDJob::NoError) { - switch (m_repoMetaInfoJob->error()) { + if (m_metadataJob.error() != KDJob::NoError) { + switch (m_metadataJob.error()) { case QInstaller::UserIgnoreError: break; // we can simply ignore this error, the user knows about it default: - setStatus(PackageManagerCore::Failure, m_repoMetaInfoJob->errorString()); + setStatus(PackageManagerCore::Failure, m_metadataJob.errorString()); return m_repoFetched; } } @@ -2202,7 +2199,8 @@ bool PackageManagerCorePrivate::addUpdateResourcesFromRepositories(bool parseChe if (m_updateSourcesAdded) return m_updateSourcesAdded; - if (m_repoMetaInfoJob->temporaryDirectories().isEmpty()) { + const QList metadata = m_metadataJob.metadata(); + if (metadata.isEmpty()) { m_updateSourcesAdded = true; return m_updateSourcesAdded; } @@ -2211,7 +2209,8 @@ bool PackageManagerCorePrivate::addUpdateResourcesFromRepositories(bool parseChe m_updaterApplication.updateSourcesInfo()->refresh(); if (isInstaller()) { m_updaterApplication.addUpdateSource(m_data.settings().applicationName(), - m_data.settings().applicationName(), QString(), QUrl(QLatin1String("resource://metadata/")), 0); + m_data.settings().applicationName(), QString(), + QUrl(QLatin1String("resource://metadata/")), 0); m_updaterApplication.updateSourcesInfo()->setModified(false); } @@ -2219,16 +2218,15 @@ bool PackageManagerCorePrivate::addUpdateResourcesFromRepositories(bool parseChe m_updateSourcesAdded = false; const QString &appName = m_data.settings().applicationName(); - const QStringList tempDirs = m_repoMetaInfoJob->temporaryDirectories(); - foreach (const QString &tmpDir, tempDirs) { + foreach (const Metadata &data, metadata) { if (statusCanceledOrFailed()) return false; - if (tmpDir.isEmpty()) + if (data.directory.isEmpty()) continue; if (parseChecksum) { - const QString updatesXmlPath = tmpDir + QLatin1String("/Updates.xml"); + const QString updatesXmlPath = data.directory + QLatin1String("/Updates.xml"); QFile updatesFile(updatesXmlPath); try { openForRead(&updatesFile, updatesFile.fileName()); @@ -2253,7 +2251,8 @@ bool PackageManagerCorePrivate::addUpdateResourcesFromRepositories(bool parseChe if (!checksum.isNull()) m_core->setTestChecksum(checksum.toElement().text().toLower() == scTrue); } - m_updaterApplication.addUpdateSource(appName, appName, QString(), QUrl::fromLocalFile(tmpDir), 1); + m_updaterApplication.addUpdateSource(appName, appName, QString(), + QUrl::fromLocalFile(data.directory), 1); } m_updaterApplication.updateSourcesInfo()->setModified(false); diff --git a/src/libs/installer/packagemanagercore_p.h b/src/libs/installer/packagemanagercore_p.h index 56a6055ea..1d41d9b21 100644 --- a/src/libs/installer/packagemanagercore_p.h +++ b/src/libs/installer/packagemanagercore_p.h @@ -42,7 +42,7 @@ #ifndef PACKAGEMANAGERCORE_P_H #define PACKAGEMANAGERCORE_P_H -#include "getrepositoriesmetainfojob.h" +#include "metadatajob.h" #include "packagemanagercore.h" #include "packagemanagercoredata.h" #include "qinstallerglobal.h" @@ -95,6 +95,7 @@ class PackageManagerCorePrivate : public QObject { Q_OBJECT friend class PackageManagerCore; + Q_DISABLE_COPY(PackageManagerCorePrivate) public: enum OperationType { @@ -261,7 +262,7 @@ private: private: PackageManagerCore *m_core; - GetRepositoriesMetaInfoJob *m_repoMetaInfoJob; + MetadataJob m_metadataJob; bool m_updates; bool m_repoFetched; diff --git a/src/sdk/installerbasecommons.cpp b/src/sdk/installerbasecommons.cpp index 0cf85a0ec..f44cb409e 100644 --- a/src/sdk/installerbasecommons.cpp +++ b/src/sdk/installerbasecommons.cpp @@ -116,6 +116,7 @@ IntroductionPageImpl::IntroductionPageImpl(QInstaller::PackageManagerCore *core) core->setCompleteUninstallation(core->isUninstaller()); + connect(core, SIGNAL(metaJobProgress(int)), this, SLOT(onProgressChanged(int))); connect(core, SIGNAL(metaJobInfoMessage(QString)), this, SLOT(setMessage(QString))); connect(core, SIGNAL(coreNetworkSettingsChanged()), this, SLOT(onCoreNetworkSettingsChanged())); @@ -249,6 +250,12 @@ void IntroductionPageImpl::setMessage(const QString &msg) m_label->setText(msg); } +void IntroductionPageImpl::onProgressChanged(int progress) +{ + m_progressBar->setRange(0, 100); + m_progressBar->setValue(progress); +} + void IntroductionPageImpl::setErrorMessage(const QString &error) { QPalette palette; @@ -335,6 +342,8 @@ void IntroductionPageImpl::entering() setErrorMessage(QString()); setButtonText(QWizard::CancelButton, tr("Quit")); + m_progressBar->setValue(0); + m_progressBar->setRange(0, 0); PackageManagerCore *core = packageManagerCore(); if (core->isUninstaller() ||core->isUpdater() || core->isPackageManager()) { showMaintenanceTools(); @@ -345,6 +354,8 @@ void IntroductionPageImpl::entering() void IntroductionPageImpl::leaving() { + m_progressBar->setValue(0); + m_progressBar->setRange(0, 0); setButtonText(QWizard::CancelButton, gui()->defaultButtonText(QWizard::CancelButton)); } diff --git a/src/sdk/installerbasecommons.h b/src/sdk/installerbasecommons.h index 2bcdce3f2..79330eaf7 100644 --- a/src/sdk/installerbasecommons.h +++ b/src/sdk/installerbasecommons.h @@ -72,6 +72,7 @@ public: public Q_SLOTS: void onCoreNetworkSettingsChanged(); void setMessage(const QString &msg); + void onProgressChanged(int progress); void setErrorMessage(const QString &error); Q_SIGNALS: -- cgit v1.2.3