summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKatja Marttila <katja.marttila@qt.io>2016-09-20 14:45:24 +0300
committerIikka Eklund <iikka.eklund@qt.io>2016-11-09 07:08:48 +0000
commite7f93217182233383851a25ae21bd950d05b408a (patch)
tree978adb275ec5b3f52a93a610ef5d50d27c6a2479
parent6e5ef08718b7b638b57dda4ef4a7bdbfe8046743 (diff)
allow installing compressed packages
This change introduces new feature to add 7z packages to be installed. Packages must be installer repositories (created with repogen), compressed to 7z file and named as qtbsp or 7z. Selecting compressed package is done either with button in component selection page or with --installCompressedRepository parameter given to installer or to maintenancetool. Button will not be created by default. If you want to show the button either build IFW with DEFINES+=INSTALLCOMPRESSED or enable the button in control script with allowCompressedRepositoryInstall() in ComponentSelectionPageCallback Task-number: QTIFW-886 Change-Id: Ia060092c348991d5195393b7dc154205f8bf92a5 Reviewed-by: Iikka Eklund <iikka.eklund@qt.io>
-rw-r--r--src/libs/installer/metadatajob.cpp155
-rw-r--r--src/libs/installer/metadatajob.h7
-rw-r--r--src/libs/installer/metadatajob_p.h2
-rw-r--r--src/libs/installer/packagemanagercore.cpp45
-rw-r--r--src/libs/installer/packagemanagercore.h7
-rw-r--r--src/libs/installer/packagemanagercore_p.cpp94
-rw-r--r--src/libs/installer/packagemanagercore_p.h7
-rw-r--r--src/libs/installer/packagemanagergui.cpp112
-rw-r--r--src/libs/installer/packagemanagergui.h1
-rw-r--r--src/libs/installer/repository.cpp35
-rw-r--r--src/libs/installer/repository.h7
-rw-r--r--src/libs/kdtools/task.cpp2
-rw-r--r--src/libs/kdtools/updatefinder.cpp11
-rw-r--r--src/libs/kdtools/updatefinder.h4
-rw-r--r--src/sdk/commandlineparser.cpp5
-rw-r--r--src/sdk/constants.h1
-rw-r--r--src/sdk/installerbase.cpp8
17 files changed, 438 insertions, 65 deletions
diff --git a/src/libs/installer/metadatajob.cpp b/src/libs/installer/metadatajob.cpp
index b010209c3..b3301c761 100644
--- a/src/libs/installer/metadatajob.cpp
+++ b/src/libs/installer/metadatajob.cpp
@@ -55,6 +55,7 @@ static QUrl resolveUrl(const FileTaskResult &result, const QString &url)
MetadataJob::MetadataJob(QObject *parent)
: Job(parent)
, m_core(0)
+ , m_addCompressedPackages(false)
{
setCapabilities(Cancelable);
connect(&m_xmlTask, &QFutureWatcherBase::finished, this, &MetadataJob::xmlTaskFinished);
@@ -77,48 +78,142 @@ Repository MetadataJob::repositoryForDirectory(const QString &directory) const
void MetadataJob::doStart()
{
- reset();
if (!m_core) {
emitFinishedWithError(Job::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->isMaintainer()) {
- QList<FileTaskItem> 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());
-
- QString url = repo.url().toString() + QLatin1String("/Updates.xml?");
- if (!m_core->value(scUrlQueryString).isEmpty())
- url += m_core->value(scUrlQueryString) + QLatin1Char('&');
-
- // also append a random string to avoid proxy caches
- FileTaskItem item(url.append(QString::number(qrand() * qrand())));
- item.insert(TaskRole::UserRole, QVariant::fromValue(repo));
- item.insert(TaskRole::Authenticator, QVariant::fromValue(authenticator));
- items.append(item);
+ const ProductKeyCheck *const productKeyCheck = ProductKeyCheck::instance();
+ if (!m_addCompressedPackages) {
+ reset();
+ emit infoMessage(this, tr("Preparing meta information download..."));
+ const bool onlineInstaller = m_core->isInstaller() && !m_core->isOfflineOnly();
+
+ if (onlineInstaller || m_core->isMaintainer()) {
+ QList<FileTaskItem> items;
+ foreach (const Repository &repo, m_core->settings().repositories()) {
+ if (repo.isEnabled() &&
+ productKeyCheck->isValidRepository(repo)) {
+ QAuthenticator authenticator;
+ authenticator.setUser(repo.username());
+ authenticator.setPassword(repo.password());
+
+ if (!repo.isCompressed()) {
+ QString url = repo.url().toString() + QLatin1String("/Updates.xml?");
+ if (!m_core->value(scUrlQueryString).isEmpty())
+ url += m_core->value(scUrlQueryString) + QLatin1Char('&');
+
+ // also append a random string to avoid proxy caches
+ FileTaskItem item(url.append(QString::number(qrand() * qrand())));
+ item.insert(TaskRole::UserRole, QVariant::fromValue(repo));
+ item.insert(TaskRole::Authenticator, QVariant::fromValue(authenticator));
+ items.append(item);
+ }
+ else {
+ qDebug() << "Trying to parse compressed repo as normal repository."\
+ "Check repository syntax.";
+ }
+ }
+ }
+ if (items.count() > 0) {
+ startXMLTask(items);
+ } else {
+ emitFinished();
}
+ } else {
+ emitFinished();
}
- DownloadFileTask *const xmlTask = new DownloadFileTask(items);
- xmlTask->setProxyFactory(m_core->proxyFactory());
- m_xmlTask.setFuture(QtConcurrent::run(&DownloadFileTask::doTask, xmlTask));
} else {
- emitFinished();
+ m_packages.clear();
+ bool repositoriesFound = false;
+ foreach (const Repository &repo, m_core->settings().repositories()) {
+ if (repo.isCompressed() && repo.isEnabled() &&
+ productKeyCheck->isValidRepository(repo)) {
+ repositoriesFound = true;
+ startUnzipRepositoryTask(repo);
+ }
+ }
+ if (!repositoriesFound)
+ emitFinished();
+ else
+ emit infoMessage(this, tr("Unpacking compressed repositories..."));
}
}
+void MetadataJob::startXMLTask(const QList<FileTaskItem> items)
+{
+ DownloadFileTask *const xmlTask = new DownloadFileTask(items);
+ xmlTask->setProxyFactory(m_core->proxyFactory());
+ m_xmlTask.setFuture(QtConcurrent::run(&DownloadFileTask::doTask, xmlTask));
+}
+
void MetadataJob::doCancel()
{
reset();
emitFinishedWithError(Job::Canceled, tr("Meta data download canceled."));
}
+void MetadataJob::startUnzipRepositoryTask(const Repository &repo)
+{
+ QTemporaryDir tempRepoDir(QDir::tempPath() + QLatin1String("/compressedRepo-XXXXXX"));
+ if (!tempRepoDir.isValid()) {
+ qDebug() << "Cannot create unique temporary directory.";
+ return;
+ }
+ tempRepoDir.setAutoRemove(false);
+ m_tempDirDeleter.add(tempRepoDir.path());
+ QString url = repo.url().toLocalFile();
+ UnzipArchiveTask *task = new UnzipArchiveTask(url, tempRepoDir.path());
+ QFutureWatcher<void> *watcher = new QFutureWatcher<void>();
+ m_unzipRepositoryTasks.insert(watcher, qobject_cast<QObject*> (task));
+ connect(watcher, &QFutureWatcherBase::finished, this,
+ &MetadataJob::unzipRepositoryTaskFinished);
+ connect(watcher, &QFutureWatcherBase::progressValueChanged, this,
+ &MetadataJob::progressChanged);
+ watcher->setFuture(QtConcurrent::run(&UnzipArchiveTask::doTask, task));
+}
+
+void MetadataJob::unzipRepositoryTaskFinished()
+{
+ QFutureWatcher<void> *watcher = static_cast<QFutureWatcher<void> *>(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."));
+ }
+
+ QHashIterator<QFutureWatcher<void> *, QObject*> i(m_unzipRepositoryTasks);
+ while (i.hasNext()) {
+ i.next();
+ if (i.key() == watcher) {
+ UnzipArchiveTask *task = qobject_cast<UnzipArchiveTask*> (i.value());
+ QString url = task->target();
+
+ QUrl targetUrl = targetUrl.fromLocalFile(url);
+ Repository repo(targetUrl, false, true);
+ url = repo.url().toString() + QLatin1String("/Updates.xml");
+ FileTaskItem item(url);
+ item.insert(TaskRole::UserRole, QVariant::fromValue(repo));
+ m_unzipRepositoryitems.append(item);
+ }
+ }
+
+ //One can specify many zipped repository items at once. As the repositories are
+ //unzipped one by one, we collect here all items before parsing xml files from those.
+ delete m_unzipRepositoryTasks.value(watcher);
+ m_unzipRepositoryTasks.remove(watcher);
+ delete watcher;
+
+ if (m_unzipRepositoryitems.count() > 0 && m_unzipRepositoryTasks.isEmpty())
+ startXMLTask(m_unzipRepositoryitems);
+}
+
void MetadataJob::xmlTaskFinished()
{
Status status = XmlDownloadFailure;
@@ -291,6 +386,14 @@ void MetadataJob::reset()
foreach (QObject *const object, m_unzipTasks)
object->deleteLater();
m_unzipTasks.clear();
+
+ foreach (QFutureWatcher<void> *const watcher, m_unzipRepositoryTasks.keys()) {
+ watcher->cancel();
+ watcher->deleteLater();
+ }
+ foreach (QObject *const object, m_unzipRepositoryTasks)
+ object->deleteLater();
+ m_unzipRepositoryTasks.clear();
} catch (...) {}
m_tempDirDeleter.releaseAndDeleteAll();
}
diff --git a/src/libs/installer/metadatajob.h b/src/libs/installer/metadatajob.h
index 10fffe172..e59029940 100644
--- a/src/libs/installer/metadatajob.h
+++ b/src/libs/installer/metadatajob.h
@@ -69,6 +69,7 @@ public:
QList<Metadata> metadata() const { return m_metadata.values(); }
Repository repositoryForDirectory(const QString &directory) const;
void setPackageManagerCore(PackageManagerCore *core) { m_core = core; }
+ void addCompressedPackages(bool addCompressPackage) { m_addCompressedPackages = addCompressPackage;}
private slots:
void doStart();
@@ -78,8 +79,11 @@ private slots:
void unzipTaskFinished();
void metadataTaskFinished();
void progressChanged(int progress);
+ void unzipRepositoryTaskFinished();
+ void startXMLTask(const QList<FileTaskItem> items);
private:
+ void startUnzipRepositoryTask(const Repository &repo);
void reset();
Status parseUpdatesXml(const QList<FileTaskResult> &results);
@@ -92,6 +96,9 @@ private:
QFutureWatcher<FileTaskResult> m_xmlTask;
QFutureWatcher<FileTaskResult> m_metadataTask;
QHash<QFutureWatcher<void> *, QObject*> m_unzipTasks;
+ QHash<QFutureWatcher<void> *, QObject*> m_unzipRepositoryTasks;
+ bool m_addCompressedPackages;
+ QList<FileTaskItem> m_unzipRepositoryitems;
};
} // namespace QInstaller
diff --git a/src/libs/installer/metadatajob_p.h b/src/libs/installer/metadatajob_p.h
index a07c7a80f..7839eacb5 100644
--- a/src/libs/installer/metadatajob_p.h
+++ b/src/libs/installer/metadatajob_p.h
@@ -69,7 +69,7 @@ public:
UnzipArchiveTask(const QString &arcive, const QString &target)
: m_archive(arcive), m_targetDir(target)
{}
-
+ QString target() { return m_targetDir; }
void doTask(QFutureInterface<void> &fi)
{
fi.reportStarted();
diff --git a/src/libs/installer/packagemanagercore.cpp b/src/libs/installer/packagemanagercore.cpp
index 731171f61..971ca694d 100644
--- a/src/libs/installer/packagemanagercore.cpp
+++ b/src/libs/installer/packagemanagercore.cpp
@@ -1153,8 +1153,37 @@ PackagesList PackageManagerCore::remotePackages()
}
/*!
+ Checks for compressed packages to install. Returns \c true if newer versions exist
+ and they can be installed.
+*/
+bool PackageManagerCore::fetchCompressedPackagesTree()
+{
+ const LocalPackagesHash installedPackages = d->localInstalledPackages();
+ if (!isInstaller() && status() == Failure)
+ return false;
+
+ if (!d->fetchMetaInformationFromCompressedRepositories())
+ return false;
+
+ if (!d->addUpdateResourcesFromRepositories(true, true)) {
+ return false;
+ }
+
+ PackagesList packages;
+ const PackagesList &compPackages = d->compressedPackages();
+ if (compPackages.isEmpty())
+ return false;
+ packages.append(compPackages);
+ const PackagesList &rPackages = d->remotePackages();
+ packages.append(rPackages);
+
+ return fetchPackagesTree(packages, installedPackages);
+}
+
+
+/*!
Checks for packages to install. Returns \c true if newer versions exist
- and they can be installed and sets the status of the update to \c Success.
+ and they can be installed.
*/
bool PackageManagerCore::fetchRemotePackagesTree()
{
@@ -1177,6 +1206,9 @@ bool PackageManagerCore::fetchRemotePackagesTree()
if (!d->fetchMetaInformationFromRepositories())
return false;
+ if (!d->fetchMetaInformationFromCompressedRepositories())
+ return false;
+
if (!d->addUpdateResourcesFromRepositories(true))
return false;
@@ -1184,6 +1216,11 @@ bool PackageManagerCore::fetchRemotePackagesTree()
if (packages.isEmpty())
return false;
+ return fetchPackagesTree(packages, installedPackages);
+}
+
+bool PackageManagerCore::fetchPackagesTree(const PackagesList &packages, const LocalPackagesHash installedPackages) {
+
bool success = false;
if (!isUpdater()) {
success = fetchAllPackages(packages, installedPackages);
@@ -1366,12 +1403,12 @@ void PackageManagerCore::addUserRepositories(const QStringList &repositories)
\sa {installer::setTemporaryRepositories}{installer.setTemporaryRepositories}
\sa addUserRepositories()
*/
-void PackageManagerCore::setTemporaryRepositories(const QStringList &repositories, bool replace)
+void PackageManagerCore::setTemporaryRepositories(const QStringList &repositories, bool replace,
+ bool compressed)
{
QSet<Repository> repositorySet;
foreach (const QString &repository, repositories)
- repositorySet.insert(Repository::fromUserInput(repository));
-
+ repositorySet.insert(Repository::fromUserInput(repository, compressed));
settings().setTemporaryRepositories(repositorySet, replace);
}
diff --git a/src/libs/installer/packagemanagercore.h b/src/libs/installer/packagemanagercore.h
index eebc33c4b..6b2a42ace 100644
--- a/src/libs/installer/packagemanagercore.h
+++ b/src/libs/installer/packagemanagercore.h
@@ -127,6 +127,7 @@ public:
PackagesList remotePackages();
bool fetchRemotePackagesTree();
+ bool fetchCompressedPackagesTree();
bool run();
void reset(const QHash<QString, QString> &params);
@@ -181,8 +182,8 @@ public:
void setTestChecksum(bool test);
Q_INVOKABLE void addUserRepositories(const QStringList &repositories);
- Q_INVOKABLE void setTemporaryRepositories(const QStringList &repositories, bool replace = false);
-
+ Q_INVOKABLE void setTemporaryRepositories(const QStringList &repositories,
+ bool replace = false, bool compressed = false);
Q_INVOKABLE void autoAcceptMessageBoxes();
Q_INVOKABLE void autoRejectMessageBoxes();
Q_INVOKABLE void setMessageBoxAutomaticAnswer(const QString &identifier, int button);
@@ -340,6 +341,8 @@ private:
ComponentModel *componentModel(PackageManagerCore *core, const QString &objectName) const;
QList<Component *> componentsMarkedForInstallation() const;
+ bool fetchPackagesTree(const PackagesList &packages, const LocalPackagesHash installedPackages);
+
private:
PackageManagerCorePrivate *const d;
friend class PackageManagerCorePrivate;
diff --git a/src/libs/installer/packagemanagercore_p.cpp b/src/libs/installer/packagemanagercore_p.cpp
index b972545ce..58847dfec 100644
--- a/src/libs/installer/packagemanagercore_p.cpp
+++ b/src/libs/installer/packagemanagercore_p.cpp
@@ -185,6 +185,7 @@ static void deferredRename(const QString &oldName, const QString &newName, bool
PackageManagerCorePrivate::PackageManagerCorePrivate(PackageManagerCore *core)
: m_updateFinder(0)
+ , m_compressedFinder(0)
, m_localPackageHub(std::make_shared<LocalPackageHub>())
, m_core(core)
, m_updates(false)
@@ -206,6 +207,7 @@ PackageManagerCorePrivate::PackageManagerCorePrivate(PackageManagerCore *core)
PackageManagerCorePrivate::PackageManagerCorePrivate(PackageManagerCore *core, qint64 magicInstallerMaker,
const QList<OperationBlob> &performedOperations)
: m_updateFinder(0)
+ , m_compressedFinder(0)
, m_localPackageHub(std::make_shared<LocalPackageHub>())
, m_status(PackageManagerCore::Unfinished)
, m_needsHardRestart(false)
@@ -2131,6 +2133,29 @@ PackagesList PackageManagerCorePrivate::remotePackages()
return m_updateFinder->updates();
}
+PackagesList PackageManagerCorePrivate::compressedPackages()
+{
+ if (m_compressedUpdates && m_compressedFinder)
+ return m_compressedFinder->updates();
+ m_compressedUpdates = false;
+ delete m_compressedFinder;
+
+ m_compressedFinder = new KDUpdater::UpdateFinder;
+ m_compressedFinder->setAutoDelete(false);
+ m_compressedFinder->addCompressedPackage(true);
+ m_compressedFinder->setPackageSources(m_compressedPackageSources);
+
+ m_compressedFinder->setLocalPackageHub(m_localPackageHub);
+ m_compressedFinder->run();
+ if (m_compressedFinder->updates().isEmpty()) {
+ setStatus(PackageManagerCore::Failure, tr("Cannot retrieve remote tree %1.")
+ .arg(m_compressedFinder->errorString()));
+ return PackagesList();
+ }
+ m_compressedUpdates = true;
+ return m_compressedFinder->updates();
+}
+
/*!
Returns a hash containing the installed package name and it's associated package information. If
the application is running in installer mode or the local components file could not be parsed, the
@@ -2200,9 +2225,44 @@ bool PackageManagerCorePrivate::fetchMetaInformationFromRepositories()
return m_repoFetched;
}
-bool PackageManagerCorePrivate::addUpdateResourcesFromRepositories(bool parseChecksum)
+bool PackageManagerCorePrivate::fetchMetaInformationFromCompressedRepositories()
+{
+ bool compressedRepoFetched = false;
+
+ m_compressedUpdates = false;
+ m_updateSourcesAdded = false;
+
+ try {
+ //Tell MetadataJob that only compressed packages needed to be fetched and not all.
+ //We cannot do this in general fetch meta method as the compressed packages might be
+ //installed after components tree is generated
+ m_metadataJob.addCompressedPackages(true);
+ m_metadataJob.start();
+ m_metadataJob.waitForFinished();
+ m_metadataJob.addCompressedPackages(false);
+ } catch (Error &error) {
+ setStatus(PackageManagerCore::Failure, tr("Cannot retrieve meta information: %1")
+ .arg(error.message()));
+ return compressedRepoFetched;
+ }
+
+ if (m_metadataJob.error() != Job::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_metadataJob.errorString());
+ return compressedRepoFetched;
+ }
+ }
+
+ compressedRepoFetched = true;
+ return compressedRepoFetched;
+}
+
+bool PackageManagerCorePrivate::addUpdateResourcesFromRepositories(bool parseChecksum, bool compressedRepository)
{
- if (m_updateSourcesAdded)
+ if (!compressedRepository && m_updateSourcesAdded)
return m_updateSourcesAdded;
const QList<Metadata> metadata = m_metadataJob.metadata();
@@ -2210,15 +2270,21 @@ bool PackageManagerCorePrivate::addUpdateResourcesFromRepositories(bool parseChe
m_updateSourcesAdded = true;
return m_updateSourcesAdded;
}
-
- m_packageSources.clear();
- if (isInstaller())
- m_packageSources.insert(PackageSource(QUrl(QLatin1String("resource://metadata/")), 0));
-
- m_updates = false;
- m_updateSourcesAdded = false;
+ if (compressedRepository) {
+ m_compressedPackageSources.clear();
+ }
+ else {
+ m_packageSources.clear();
+ m_updates = false;
+ m_updateSourcesAdded = false;
+ if (isInstaller())
+ m_packageSources.insert(PackageSource(QUrl(QLatin1String("resource://metadata/")), 0));
+ }
foreach (const Metadata &data, metadata) {
+ if (compressedRepository && !data.repository.isCompressed()) {
+ continue;
+ }
if (statusCanceledOrFailed())
return false;
@@ -2251,11 +2317,15 @@ bool PackageManagerCorePrivate::addUpdateResourcesFromRepositories(bool parseChe
if (!checksum.isNull())
m_core->setTestChecksum(checksum.toElement().text().toLower() == scTrue);
}
- m_packageSources.insert(PackageSource(QUrl::fromLocalFile(data.directory), 1));
+ if (compressedRepository)
+ m_compressedPackageSources.insert(PackageSource(QUrl::fromLocalFile(data.directory), 1));
+ else
+ m_packageSources.insert(PackageSource(QUrl::fromLocalFile(data.directory), 1));
+
ProductKeyCheck::instance()->addPackagesFromXml(data.directory + QLatin1String("/Updates.xml"));
}
-
- if (m_packageSources.count() == 0) {
+ if ((compressedRepository && m_compressedPackageSources.count() == 0 ) ||
+ (!compressedRepository && m_packageSources.count() == 0)) {
setStatus(PackageManagerCore::Failure, tr("Cannot find any update source information."));
return false;
}
diff --git a/src/libs/installer/packagemanagercore_p.h b/src/libs/installer/packagemanagercore_p.h
index d78bd3e69..7377feff4 100644
--- a/src/libs/installer/packagemanagercore_p.h
+++ b/src/libs/installer/packagemanagercore_p.h
@@ -175,7 +175,9 @@ signals:
public:
UpdateFinder *m_updateFinder;
+ UpdateFinder *m_compressedFinder;
QSet<PackageSource> m_packageSources;
+ QSet<PackageSource> m_compressedPackageSources;
std::shared_ptr<LocalPackageHub> m_localPackageHub;
QStringList m_filesForDelayedDeletion;
@@ -227,9 +229,11 @@ private:
bool adminRightsGained, bool deleteOperation);
PackagesList remotePackages();
+ PackagesList compressedPackages();
LocalPackagesHash localInstalledPackages();
bool fetchMetaInformationFromRepositories();
- bool addUpdateResourcesFromRepositories(bool parseChecksum);
+ bool fetchMetaInformationFromCompressedRepositories();
+ bool addUpdateResourcesFromRepositories(bool parseChecksum, bool compressedRepository = false);
void processFilesForDelayedDeletion();
private:
@@ -237,6 +241,7 @@ private:
MetadataJob m_metadataJob;
bool m_updates;
+ bool m_compressedUpdates;
bool m_repoFetched;
bool m_updateSourcesAdded;
qint64 m_magicBinaryMarker;
diff --git a/src/libs/installer/packagemanagergui.cpp b/src/libs/installer/packagemanagergui.cpp
index ec558a7ab..18f8849f9 100644
--- a/src/libs/installer/packagemanagergui.cpp
+++ b/src/libs/installer/packagemanagergui.cpp
@@ -75,6 +75,7 @@
#include <QTreeView>
#include <QVBoxLayout>
#include <QShowEvent>
+#include <QFileDialog>
#ifdef Q_OS_WIN
# include <qt_windows.h>
@@ -1858,6 +1859,7 @@ public:
, m_allModel(m_core->defaultComponentModel())
, m_updaterModel(m_core->updaterComponentModel())
, m_currentModel(m_allModel)
+ , m_compressedButtonVisible(false)
{
m_treeView->setObjectName(QLatin1String("ComponentsTreeView"));
@@ -1873,17 +1875,21 @@ public:
m_descriptionLabel->setWordWrap(true);
m_descriptionLabel->setObjectName(QLatin1String("ComponentDescriptionLabel"));
- QVBoxLayout *vlayout = new QVBoxLayout;
- vlayout->addWidget(m_descriptionLabel);
+ m_vlayout = new QVBoxLayout;
+ m_vlayout->setObjectName(QLatin1String("VerticalLayout"));
+ m_vlayout->addWidget(m_descriptionLabel);
m_sizeLabel = new QLabel(q);
m_sizeLabel->setWordWrap(true);
- vlayout->addWidget(m_sizeLabel);
+ m_vlayout->addWidget(m_sizeLabel);
m_sizeLabel->setObjectName(QLatin1String("ComponentSizeLabel"));
- vlayout->addSpacerItem(new QSpacerItem(1, 1, QSizePolicy::MinimumExpanding,
+#ifdef INSTALLCOMPRESSED
+ allowCompressedRepositoryInstall();
+#endif
+ m_vlayout->addSpacerItem(new QSpacerItem(1, 1, QSizePolicy::MinimumExpanding,
QSizePolicy::MinimumExpanding));
- hlayout->addLayout(vlayout, 2);
+ hlayout->addLayout(m_vlayout, 2);
QVBoxLayout *layout = new QVBoxLayout(q);
layout->addLayout(hlayout, 1);
@@ -1929,6 +1935,40 @@ public:
layout->addLayout(hlayout);
}
+ void allowCompressedRepositoryInstall()
+ {
+ if (m_compressedButtonVisible) {
+ return;
+ }
+
+ connect(m_core, SIGNAL(metaJobProgress(int)), this, SLOT(onProgressChanged(int)));
+ connect(m_core, SIGNAL(metaJobInfoMessage(QString)), this, SLOT(setMessage(QString)));
+
+ m_bspLabel = new QLabel(ComponentSelectionPage::tr("To install new "\
+ "compressed repository, browse the repositories from your computer"),q);
+ m_bspLabel->setWordWrap(true);
+ m_bspLabel->setObjectName(QLatin1String("CompressedButtonLabel"));
+
+ m_vlayout->addSpacing(50);
+ m_vlayout->addWidget(m_bspLabel);
+
+
+ m_progressBar = new QProgressBar();
+ m_progressBar->setRange(0, 0);
+ m_progressBar->hide();
+ m_vlayout->addWidget(m_progressBar);
+ m_progressBar->setObjectName(QLatin1String("CompressedInstallProgressBar"));
+
+
+ m_installCompressButton = new QPushButton;
+ connect(m_installCompressButton, &QAbstractButton::clicked,
+ this, &ComponentSelectionPage::Private::selectCompressedPackage);
+ m_installCompressButton->setObjectName(QLatin1String("InstallCompressedPackageButton"));
+ m_installCompressButton->setText(ComponentSelectionPage::tr("&Browse BSP or 7z files..."));
+ m_vlayout->addWidget(m_installCompressButton);
+ m_compressedButtonVisible = true;
+ }
+
void updateTreeView()
{
m_checkDefault->setVisible(m_core->isInstaller() || m_core->isPackageManager());
@@ -2012,6 +2052,58 @@ public slots:
m_currentModel->setCheckedState(ComponentModel::AllUnchecked);
}
+ void selectCompressedPackage()
+ {
+ QString defaultDownloadDirectory =
+ QStandardPaths::writableLocation(QStandardPaths::DownloadLocation);
+ QStringList fileNames = QFileDialog::getOpenFileNames(NULL,
+ ComponentSelectionPage::tr("Open File"),defaultDownloadDirectory,
+ QLatin1String("QtBSP or 7z Files (*.qtbsp *.7z)"));
+
+ QSet<Repository> set;
+ foreach (QString fileName, fileNames) {
+ Repository repository = Repository::fromUserInput(fileName, true);
+ set.insert(repository);
+ }
+ if (set.count() > 0) {
+ m_progressBar->show();
+ m_installCompressButton->setEnabled(false);
+ QPushButton *const b = qobject_cast<QPushButton *>(q->gui()->button(QWizard::NextButton));
+ b->setEnabled(false);
+ m_core->settings().addTemporaryRepositories(set, false);
+ m_core->fetchCompressedPackagesTree();
+ updateTreeView();
+
+ m_progressBar->hide();
+ m_bspLabel->setText(ComponentSelectionPage::tr("To install new "\
+ "compressed repository, browse the repositories from your computer"));
+ m_installCompressButton->setEnabled(true);
+ b->setEnabled(true);
+ }
+ }
+
+ /*!
+ Updates the value of \a progress on the progress bar.
+ */
+ void onProgressChanged(int progress)
+ {
+ m_progressBar->setValue(progress);
+ }
+
+ /*!
+ Displays the message \a msg on the page.
+ */
+ void setMessage(const QString &msg)
+ {
+ if (m_progressBar->isVisible()) {
+ m_bspLabel->setText(msg);
+ }
+ else {
+ m_bspLabel->setText(ComponentSelectionPage::tr("To install new "\
+ "compressed repository, browse the repositories from your computer"));
+ }
+ }
+
void selectDefault()
{
m_currentModel->setCheckedState(ComponentModel::DefaultChecked);
@@ -2049,6 +2141,11 @@ public:
QPushButton *m_checkAll;
QPushButton *m_uncheckAll;
QPushButton *m_checkDefault;
+ QPushButton *m_installCompressButton;
+ QLabel *m_bspLabel;
+ QProgressBar *m_progressBar;
+ QVBoxLayout *m_vlayout;
+ bool m_compressedButtonVisible;
};
@@ -2167,6 +2264,11 @@ void ComponentSelectionPage::deselectComponent(const QString &id)
d->m_currentModel->setData(idx, Qt::Unchecked, Qt::CheckStateRole);
}
+void ComponentSelectionPage::allowCompressedRepositoryInstall()
+{
+ d->allowCompressedRepositoryInstall();
+}
+
void ComponentSelectionPage::setModified(bool modified)
{
setComplete(modified);
diff --git a/src/libs/installer/packagemanagergui.h b/src/libs/installer/packagemanagergui.h
index 2940df052..63d00b941 100644
--- a/src/libs/installer/packagemanagergui.h
+++ b/src/libs/installer/packagemanagergui.h
@@ -314,6 +314,7 @@ public:
Q_INVOKABLE void selectDefault();
Q_INVOKABLE void selectComponent(const QString &id);
Q_INVOKABLE void deselectComponent(const QString &id);
+ Q_INVOKABLE void allowCompressedRepositoryInstall();
protected:
void entering();
diff --git a/src/libs/installer/repository.cpp b/src/libs/installer/repository.cpp
index 9a501fdfe..280ff1c75 100644
--- a/src/libs/installer/repository.cpp
+++ b/src/libs/installer/repository.cpp
@@ -46,6 +46,7 @@ namespace QInstaller {
Repository::Repository()
: m_default(false)
, m_enabled(false)
+ , m_compressed(false)
{
registerMetaType();
}
@@ -60,28 +61,31 @@ Repository::Repository(const Repository &other)
, m_username(other.m_username)
, m_password(other.m_password)
, m_displayname(other.m_displayname)
+ , m_compressed(other.m_compressed)
{
registerMetaType();
}
/*!
- Constructs a new repository by setting its address to \a url and its default state.
+ Constructs a new repository by setting its address to \a url
+ and its default and \a compressed states.
*/
-Repository::Repository(const QUrl &url, bool isDefault)
+Repository::Repository(const QUrl &url, bool isDefault, bool compressed)
: m_url(url)
, m_default(isDefault)
, m_enabled(true)
+ , m_compressed(compressed)
{
registerMetaType();
}
/*!
- Constructs a new repository by setting its address to \a repositoryUrl as string and its
- default state.
+ Constructs a new repository by setting its address to \a repositoryUrl as
+ string and its \a compressed state.
Note: user and password can be inside the \a repositoryUrl string: http://user:password@repository.url
*/
-Repository Repository::fromUserInput(const QString &repositoryUrl)
+Repository Repository::fromUserInput(const QString &repositoryUrl, bool compressed)
{
QUrl url = QUrl::fromUserInput(repositoryUrl);
const QStringList supportedSchemes = KDUpdater::FileDownloaderFactory::supportedSchemes();
@@ -93,7 +97,7 @@ Repository Repository::fromUserInput(const QString &repositoryUrl)
url.setUserName(QString());
url.setPassword(QString());
- Repository repository(url, false);
+ Repository repository(url, false, compressed);
repository.setUsername(userName);
repository.setPassword(password);
return repository;
@@ -200,6 +204,22 @@ void Repository::setDisplayName(const QString &displayname)
}
/*!
+ Returns true if repository is compressed
+*/
+bool Repository::isCompressed() const
+{
+ return m_compressed;
+}
+
+/*!
+ Sets this repository to \a compressed state to know weather the repository
+ needs to be uncompressed before use.
+*/
+void Repository::setCompressed(bool compressed)
+{
+ m_compressed = compressed;
+}
+/*!
Compares the values of this repository to \a other and returns true if they are equal (same server,
default state, enabled state as well as username and password). \sa operator!=()
*/
@@ -232,6 +252,7 @@ const Repository &Repository::operator=(const Repository &other)
m_username = other.m_username;
m_password = other.m_password;
m_displayname = other.m_displayname;
+ m_compressed = other.m_compressed;
return *this;
}
@@ -244,7 +265,7 @@ void Repository::registerMetaType()
QDataStream &operator>>(QDataStream &istream, Repository &repository)
{
- QByteArray url, username, password, displayname;
+ QByteArray url, username, password, displayname, compressed;
istream >> url >> repository.m_default >> repository.m_enabled >> username >> password >> displayname;
repository.setUrl(QUrl::fromEncoded(QByteArray::fromBase64(url)));
repository.setUsername(QString::fromUtf8(QByteArray::fromBase64(username)));
diff --git a/src/libs/installer/repository.h b/src/libs/installer/repository.h
index 96e41d311..785b452fb 100644
--- a/src/libs/installer/repository.h
+++ b/src/libs/installer/repository.h
@@ -46,10 +46,10 @@ class INSTALLER_EXPORT Repository
public:
explicit Repository();
Repository(const Repository &other);
- explicit Repository(const QUrl &url, bool isDefault);
+ explicit Repository(const QUrl &url, bool isDefault, bool compressed = false);
static void registerMetaType();
- static Repository fromUserInput(const QString &repositoryUrl);
+ static Repository fromUserInput(const QString &repositoryUrl, bool compressed = false);
bool isValid() const;
bool isDefault() const;
@@ -69,6 +69,8 @@ public:
QString displayname() const;
void setDisplayName(const QString &displayname);
+ bool isCompressed() const;
+ void setCompressed(bool compressed);
bool operator==(const Repository &other) const;
bool operator!=(const Repository &other) const;
@@ -85,6 +87,7 @@ private:
QString m_username;
QString m_password;
QString m_displayname;
+ bool m_compressed;
};
inline uint qHash(const Repository &repository)
diff --git a/src/libs/kdtools/task.cpp b/src/libs/kdtools/task.cpp
index 14b774ea9..64e999ba2 100644
--- a/src/libs/kdtools/task.cpp
+++ b/src/libs/kdtools/task.cpp
@@ -183,7 +183,7 @@ void Task::run()
return;
}
- if (m_finished || m_stopped) {
+ if (m_stopped) {
qDebug("Trying to start a finished or canceled task");
return;
}
diff --git a/src/libs/kdtools/updatefinder.cpp b/src/libs/kdtools/updatefinder.cpp
index 25e587b17..8553fea2c 100644
--- a/src/libs/kdtools/updatefinder.cpp
+++ b/src/libs/kdtools/updatefinder.cpp
@@ -173,7 +173,8 @@ void UpdateFinder::Private::computeUpdates()
// 1. Downloading Update XML files from all the update sources
// 2. Matching updates with Package XML and figuring out available updates
- clear();
+ if (!q->isCompressedPackage())
+ clear();
cancel = false;
// First do some quick sanity checks on the packages info
@@ -399,7 +400,8 @@ void UpdateFinder::Private::createUpdateObjects(const PackageSource &source,
delete updates.take(name);
// Create and register the update
- updates.insert(name, new Update(source, info));
+ if (!q->isCompressedPackage() || value == Resolution::AddPackage)
+ updates.insert(name, new Update(source, info));
}
}
@@ -439,6 +441,10 @@ UpdateFinder::Private::Resolution UpdateFinder::Private::checkPriorityAndVersion
<< ", Source: " << QFileInfo(source.url.toLocalFile()).fileName() << "'";
return Resolution::RemoveExisting;
}
+ if (q->isCompressedPackage() && match == 0 && source.priority == existingPackage->packageSource().priority) {
+ //Same package with the same priority and version already exists
+ return Resolution::RemoveExisting;
+ }
return Resolution::KeepExisting; // otherwise keep existing
}
return Resolution::AddPackage;
@@ -453,6 +459,7 @@ UpdateFinder::Private::Resolution UpdateFinder::Private::checkPriorityAndVersion
*/
UpdateFinder::UpdateFinder()
: Task(QLatin1String("UpdateFinder"), Stoppable),
+ m_compressedPackage(false),
d(new Private(this))
{
}
diff --git a/src/libs/kdtools/updatefinder.h b/src/libs/kdtools/updatefinder.h
index 1fbebdd9a..ed943789f 100644
--- a/src/libs/kdtools/updatefinder.h
+++ b/src/libs/kdtools/updatefinder.h
@@ -58,7 +58,8 @@ public:
void setLocalPackageHub(std::weak_ptr<LocalPackageHub> hub);
void setPackageSources(const QSet<QInstaller::PackageSource> &sources);
-
+ void addCompressedPackage(bool add) { m_compressedPackage = add; }
+ bool isCompressedPackage() { return m_compressedPackage; }
private:
void doRun();
bool doStop();
@@ -66,6 +67,7 @@ private:
bool doResume();
private:
+ bool m_compressedPackage;
Private *d;
Q_PRIVATE_SLOT(d, void slotDownloadDone())
};
diff --git a/src/sdk/commandlineparser.cpp b/src/sdk/commandlineparser.cpp
index 6da318806..1dc7ca168 100644
--- a/src/sdk/commandlineparser.cpp
+++ b/src/sdk/commandlineparser.cpp
@@ -114,7 +114,10 @@ CommandLineParser::CommandLineParser()
"a value is omitted, the client will use a default instead. Note: The server process is "
"not started by the client application in that case, you need to start it on your own."),
QLatin1String("socketname,key")));
-
+ m_parser.addOption(QCommandLineOption(QLatin1String(CommandLineOptions::InstallCompressedRepository),
+ QLatin1String("Installs QtBSP or 7z file. The QtBSP (Board Support Package) file must be a .7z "
+ "file which contains a valid repository."),
+ QLatin1String("URI,...")));
m_parser.addPositionalArgument(QLatin1String(CommandLineOptions::KeyValue),
QLatin1String("Key Value pair to be set."));
}
diff --git a/src/sdk/constants.h b/src/sdk/constants.h
index a322df09b..763377a08 100644
--- a/src/sdk/constants.h
+++ b/src/sdk/constants.h
@@ -56,6 +56,7 @@ const char AddTmpRepository[] = "addTempRepository";
const char SetTmpRepository[] = "setTempRepository";
const char StartServer[] = "startserver";
const char StartClient[] = "startclient";
+const char InstallCompressedRepository[] = "installCompressedRepository";
} // namespace CommandLineOptions
diff --git a/src/sdk/installerbase.cpp b/src/sdk/installerbase.cpp
index c99a48aa8..ec3a87a8d 100644
--- a/src/sdk/installerbase.cpp
+++ b/src/sdk/installerbase.cpp
@@ -217,6 +217,14 @@ int InstallerBase::run()
m_core->setTemporaryRepositories(repoList, true);
}
+ if (parser.isSet(QLatin1String(CommandLineOptions::InstallCompressedRepository))) {
+ const QStringList repoList = repositories(parser
+ .value(QLatin1String(CommandLineOptions::InstallCompressedRepository)));
+ if (repoList.isEmpty())
+ throw QInstaller::Error(QLatin1String("Empty repository list for option 'installCompressedRepository'."));
+ m_core->setTemporaryRepositories(repoList, false, true);
+ }
+
QInstaller::PackageManagerCore::setNoForceInstallation(parser
.isSet(QLatin1String(CommandLineOptions::NoForceInstallation)));
QInstaller::PackageManagerCore::setCreateLocalRepositoryFromBinary(parser