summaryrefslogtreecommitdiffstats
path: root/src/libs/installer
diff options
context:
space:
mode:
authorTim Jenssen <tim.jenssen@digia.com>2013-08-26 12:24:11 +0200
committerTim Jenssen <tim.jenssen@digia.com>2013-08-26 12:24:11 +0200
commitd8d93f85d6362e8cfb24a076e3df0504cb93957f (patch)
tree898b5580dab6ce76d1fea05a723416bee2feeed6 /src/libs/installer
parentcf7efd742ff29f932beb8f20b8b6e8ed4cac141b (diff)
parentf84cbe8da86dac7daf75cacbb3b68127bdff761a (diff)
Merge remote-tracking branch 'origin/1.4'
Diffstat (limited to 'src/libs/installer')
-rw-r--r--src/libs/installer/binaryformat.cpp8
-rw-r--r--src/libs/installer/component.cpp33
-rw-r--r--src/libs/installer/component.h4
-rw-r--r--src/libs/installer/component_p.h6
-rw-r--r--src/libs/installer/componentmodel.cpp15
-rw-r--r--src/libs/installer/extractarchiveoperation_p.h8
-rw-r--r--src/libs/installer/fsengineclient.cpp12
-rw-r--r--src/libs/installer/getrepositoriesmetainfojob.cpp18
-rw-r--r--src/libs/installer/getrepositoriesmetainfojob.h6
-rw-r--r--src/libs/installer/getrepositorymetainfojob.cpp33
-rw-r--r--src/libs/installer/getrepositorymetainfojob.h6
-rw-r--r--src/libs/installer/graph.h158
-rw-r--r--src/libs/installer/installer.pro3
-rw-r--r--src/libs/installer/installiconsoperation.cpp47
-rw-r--r--src/libs/installer/macreplaceinstallnamesoperation.cpp3
-rw-r--r--src/libs/installer/packagemanagercore.cpp78
-rw-r--r--src/libs/installer/packagemanagercore.h10
-rw-r--r--src/libs/installer/packagemanagercore_p.cpp83
-rw-r--r--src/libs/installer/packagemanagercore_p.h1
-rw-r--r--src/libs/installer/packagemanagercoredata.cpp2
-rw-r--r--src/libs/installer/packagemanagergui.cpp69
-rw-r--r--src/libs/installer/packagemanagergui.h1
-rw-r--r--src/libs/installer/productkeycheck.cpp7
-rw-r--r--src/libs/installer/productkeycheck.h4
-rw-r--r--src/libs/installer/qtpatchoperation.cpp104
-rw-r--r--src/libs/installer/scriptengine.cpp2
26 files changed, 557 insertions, 164 deletions
diff --git a/src/libs/installer/binaryformat.cpp b/src/libs/installer/binaryformat.cpp
index c6562f333..1d257a1b4 100644
--- a/src/libs/installer/binaryformat.cpp
+++ b/src/libs/installer/binaryformat.cpp
@@ -853,7 +853,15 @@ BinaryContent BinaryContent::readAndRegisterFromBinary(const QString &path)
*/
BinaryContent BinaryContent::readFromApplicationFile()
{
+#ifdef Q_OS_MAC
+ // On Mac, data is always in a separate file so that the binary can be signed
+ QDir dataPath(QCoreApplication::applicationFilePath());
+ dataPath.cdUp();
+ dataPath.cd(QLatin1String("Resources"));
+ return BinaryContent::readFromBinary(dataPath.filePath(QLatin1String("installer.dat")));
+#else
return BinaryContent::readFromBinary(QCoreApplication::applicationFilePath());
+#endif
}
/*!
diff --git a/src/libs/installer/component.cpp b/src/libs/installer/component.cpp
index 5889c67ce..0ac69aaf8 100644
--- a/src/libs/installer/component.cpp
+++ b/src/libs/installer/component.cpp
@@ -275,8 +275,8 @@ void Component::loadDataFromPackage(const Package &package)
setValue(scDescription, package.data(scDescription).toString());
setValue(scDefault, package.data(scDefault).toString());
setValue(scAutoDependOn, package.data(scAutoDependOn).toString());
- setValue(scCompressedSize, QString::number(0));
- setValue(scUncompressedSize, QString::number(0));
+ setValue(scCompressedSize, package.data(scCompressedSize).toString());
+ setValue(scUncompressedSize, package.data(scUncompressedSize).toString());
setValue(scRemoteVersion, package.data(scRemoteVersion).toString());
setValue(scInheritVersion, package.data(scInheritVersion).toString());
setValue(scDependencies, package.data(scDependencies).toString());
@@ -948,7 +948,7 @@ bool Component::operationsCreatedSuccessfully() const
return d->m_operationsCreatedSuccessfully;
}
-Operation *Component::createOperation(const QString &operation, const QString &parameter1,
+Operation *Component::createOperation(const QString &operationName, const QString &parameter1,
const QString &parameter2, const QString &parameter3, const QString &parameter4, const QString &parameter5,
const QString &parameter6, const QString &parameter7, const QString &parameter8, const QString &parameter9,
const QString &parameter10)
@@ -975,29 +975,29 @@ Operation *Component::createOperation(const QString &operation, const QString &p
if (!parameter10.isNull())
arguments.append(parameter10);
- return createOperation(operation, arguments);
+ return createOperation(operationName, arguments);
}
-Operation *Component::createOperation(const QString &operation, const QStringList &parameters)
+Operation *Component::createOperation(const QString &operationName, const QStringList &parameters)
{
- Operation *op = KDUpdater::UpdateOperationFactory::instance().create(operation);
- if (op == 0) {
+ Operation *operation = KDUpdater::UpdateOperationFactory::instance().create(operationName);
+ if (operation == 0) {
const QMessageBox::StandardButton button =
MessageBoxHandler::critical(MessageBoxHandler::currentBestSuitParent(),
QLatin1String("OperationDoesNotExistError"), tr("Error"), tr("Error: Operation %1 does not exist")
- .arg(operation), QMessageBox::Abort | QMessageBox::Ignore);
+ .arg(operationName), QMessageBox::Abort | QMessageBox::Ignore);
if (button == QMessageBox::Abort)
d->m_operationsCreatedSuccessfully = false;
- return op;
+ return operation;
}
- if (op->name() == QLatin1String("Delete"))
- op->setValue(QLatin1String("performUndo"), false);
- op->setValue(QLatin1String("installer"), qVariantFromValue(d->m_core));
+ if (operation->name() == QLatin1String("Delete"))
+ operation->setValue(QLatin1String("performUndo"), false);
+ operation->setValue(QLatin1String("installer"), qVariantFromValue(d->m_core));
- op->setArguments(d->m_core->replaceVariables(parameters));
-
- return op;
+ operation->setArguments(d->m_core->replaceVariables(parameters));
+ operation->setValue(QLatin1String("component"), name());
+ return operation;
}
/*!
@@ -1404,6 +1404,9 @@ void Component::updateModelData(const QString &key, const QString &data)
if (key == scDisplayVersion)
setData(data, LocalDisplayVersion);
+ if (key == scReleaseDate)
+ setData(data, ReleaseDate);
+
if (key == scUncompressedSize) {
quint64 size = d->m_vars.value(scUncompressedSizeSum).toLongLong();
setData(humanReadableSize(size), UncompressedSize);
diff --git a/src/libs/installer/component.h b/src/libs/installer/component.h
index bf5ef4d18..eefe41ebb 100644
--- a/src/libs/installer/component.h
+++ b/src/libs/installer/component.h
@@ -233,13 +233,13 @@ private Q_SLOTS:
private:
void setLocalTempPath(const QString &tempPath);
- Operation *createOperation(const QString &operation, const QString &parameter1 = QString(),
+ Operation *createOperation(const QString &operationName, const QString &parameter1 = QString(),
const QString &parameter2 = QString(), const QString &parameter3 = QString(),
const QString &parameter4 = QString(), const QString &parameter5 = QString(),
const QString &parameter6 = QString(), const QString &parameter7 = QString(),
const QString &parameter8 = QString(), const QString &parameter9 = QString(),
const QString &parameter10 = QString());
- Operation *createOperation(const QString &operation, const QStringList &parameters);
+ Operation *createOperation(const QString &operationName, const QStringList &parameters);
private:
QString validatorCallbackName;
diff --git a/src/libs/installer/component_p.h b/src/libs/installer/component_p.h
index 1f81ffd4d..1da9eee1a 100644
--- a/src/libs/installer/component_p.h
+++ b/src/libs/installer/component_p.h
@@ -99,14 +99,16 @@ class INSTALLER_EXPORT ComponentModelHelper
public:
enum Roles {
LocalDisplayVersion = Qt::UserRole + 1,
- RemoteDisplayVersion = LocalDisplayVersion + 1,
- UncompressedSize = RemoteDisplayVersion + 1
+ RemoteDisplayVersion,
+ ReleaseDate,
+ UncompressedSize
};
enum Column {
NameColumn = 0,
InstalledVersionColumn,
NewVersionColumn,
+ ReleaseDateColumn,
UncompressedSizeColumn
};
diff --git a/src/libs/installer/componentmodel.cpp b/src/libs/installer/componentmodel.cpp
index f65611ffe..080e84d85 100644
--- a/src/libs/installer/componentmodel.cpp
+++ b/src/libs/installer/componentmodel.cpp
@@ -324,10 +324,17 @@ void ComponentModel::setRootComponents(QList<QInstaller::Component*> rootCompone
m_uncheckable.clear();
m_indexByNameCache.clear();
- m_initialCheckedState.clear();
- m_currentCheckedState.clear();
+ m_rootComponentList.clear();
m_modelState = DefaultChecked;
+ // Initialize these with an empty set for every possible state, cause we compare the hashes later in
+ // updateAndEmitModelState(). The comparison than might lead to wrong results if one of the checked
+ // states is absent initially.
+ m_initialCheckedState[Qt::Checked] = ComponentSet();
+ m_initialCheckedState[Qt::Unchecked] = ComponentSet();
+ m_initialCheckedState[Qt::PartiallyChecked] = ComponentSet();
+ m_currentCheckedState = m_initialCheckedState; // both should be equal
+
// show virtual components only in case we run as updater or if the core engine is set to show them
const bool showVirtuals = m_core->isUpdater() || m_core->virtualComponentsVisible();
foreach (Component *const component, rootComponents) {
@@ -519,6 +526,10 @@ QSet<QModelIndex> ComponentModel::updateCheckedState(const ComponentSet &compone
break;
}
}
+
+ // update all nodes uncompressed size
+ foreach (Component *const node, m_rootComponentList)
+ node->updateUncompressedSize(); // this is a recursive call
return changed;
}
diff --git a/src/libs/installer/extractarchiveoperation_p.h b/src/libs/installer/extractarchiveoperation_p.h
index 44e75a949..4e0632830 100644
--- a/src/libs/installer/extractarchiveoperation_p.h
+++ b/src/libs/installer/extractarchiveoperation_p.h
@@ -117,9 +117,11 @@ public Q_SLOTS:
case PackageManagerCore::Failure:
state = E_FAIL;
break;
- case PackageManagerCore::Unfinished: // fall through
- case PackageManagerCore::Success:
- case PackageManagerCore::Running:
+ default: // fall through
+ // PackageManagerCore::Unfinished, PackageManagerCore::Success, PackageManagerCore::Running
+ // PackageManagerCore::ForceUpdate
+
+ // already set
//state = S_OK;
break;
}
diff --git a/src/libs/installer/fsengineclient.cpp b/src/libs/installer/fsengineclient.cpp
index 169b1e67b..2a7a8a5bd 100644
--- a/src/libs/installer/fsengineclient.cpp
+++ b/src/libs/installer/fsengineclient.cpp
@@ -44,6 +44,8 @@
#include "adminauthorization.h"
#include "messageboxhandler.h"
+#include <QElapsedTimer>
+
#include <QtCore/QCoreApplication>
#include <QtCore/QMutex>
#include <QtCore/QProcess>
@@ -809,8 +811,14 @@ void FSEngineClientHandler::Private::maybeStartServer()
}
if (serverStarted) {
- QTcpSocket s; // now wait for the socket to arrive
- serverStarted = FSEngineClientHandler::instance().connect(&s);
+ QElapsedTimer t;
+ t.start();
+ while (serverStarting && serverStarted
+ && t.elapsed() < 30000) { // 30 seconds ought to be enough for the app to start
+ QTcpSocket s;
+ if (FSEngineClientHandler::instance().connect(&s))
+ serverStarting = false;
+ }
}
serverStarting = false;
}
diff --git a/src/libs/installer/getrepositoriesmetainfojob.cpp b/src/libs/installer/getrepositoriesmetainfojob.cpp
index 99b7e4340..c4564e781 100644
--- a/src/libs/installer/getrepositoriesmetainfojob.cpp
+++ b/src/libs/installer/getrepositoriesmetainfojob.cpp
@@ -42,6 +42,7 @@
#include "getrepositoriesmetainfojob.h"
#include "getrepositorymetainfojob.h"
+#include "productkeycheck.h"
#include "packagemanagercore_p.h"
#include <QtCore/QDebug>
@@ -52,12 +53,12 @@ using namespace QInstaller;
// -- GetRepositoriesMetaInfoJob
-GetRepositoriesMetaInfoJob::GetRepositoriesMetaInfoJob(PackageManagerCorePrivate *corePrivate)
- : KDJob(corePrivate)
+GetRepositoriesMetaInfoJob::GetRepositoriesMetaInfoJob(PackageManagerCore *core)
+ : KDJob(core)
, m_canceled(false)
, m_silentRetries(3)
, m_haveIgnoredError(false)
- , m_corePrivate(corePrivate)
+ , m_core(core)
{
setCapabilities(Cancelable);
}
@@ -118,10 +119,11 @@ bool GetRepositoriesMetaInfoJob::isCanceled() const
void GetRepositoriesMetaInfoJob::doStart()
{
- if ((m_corePrivate->isInstaller() && !m_corePrivate->isOfflineOnly())
- || (m_corePrivate->isUpdater() || m_corePrivate->isPackageManager())) {
- foreach (const Repository &repo, m_corePrivate->m_data.settings().repositories()) {
- if (repo.isEnabled())
+ if ((m_core->isInstaller() && !m_core->isOfflineOnly()) || (m_core->isUpdater()
+ || m_core->isPackageManager())) {
+ const ProductKeyCheck *const productKeyCheck = ProductKeyCheck::instance(m_core);
+ foreach (const Repository &repo, m_core->settings().repositories()) {
+ if (repo.isEnabled() && productKeyCheck->isValidRepository(repo))
m_repositories += repo;
}
}
@@ -156,7 +158,7 @@ void GetRepositoriesMetaInfoJob::fetchNextRepo()
return;
}
- m_job = new GetRepositoryMetaInfoJob(m_corePrivate, this);
+ 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)));
diff --git a/src/libs/installer/getrepositoriesmetainfojob.h b/src/libs/installer/getrepositoriesmetainfojob.h
index aa381e3a4..2cc53b82a 100644
--- a/src/libs/installer/getrepositoriesmetainfojob.h
+++ b/src/libs/installer/getrepositoriesmetainfojob.h
@@ -59,14 +59,14 @@ namespace KDUpdater {
namespace QInstaller {
class GetRepositoryMetaInfoJob;
-class PackageManagerCorePrivate;
+class PackageManagerCore;
class INSTALLER_EXPORT GetRepositoriesMetaInfoJob : public KDJob
{
Q_OBJECT
public:
- explicit GetRepositoriesMetaInfoJob(PackageManagerCorePrivate *corePrivate);
+ explicit GetRepositoriesMetaInfoJob(PackageManagerCore *core);
QStringList temporaryDirectories() const;
QStringList releaseTemporaryDirectories() const;
@@ -91,7 +91,7 @@ private:
bool m_canceled;
int m_silentRetries;
bool m_haveIgnoredError;
- PackageManagerCorePrivate *m_corePrivate;
+ PackageManagerCore *m_core;
QString m_errorString;
QList<Repository> m_repositories;
diff --git a/src/libs/installer/getrepositorymetainfojob.cpp b/src/libs/installer/getrepositorymetainfojob.cpp
index 6913a63e5..1c8d07525 100644
--- a/src/libs/installer/getrepositorymetainfojob.cpp
+++ b/src/libs/installer/getrepositorymetainfojob.cpp
@@ -111,14 +111,14 @@ private:
// -- GetRepositoryMetaInfoJob
-GetRepositoryMetaInfoJob::GetRepositoryMetaInfoJob(PackageManagerCorePrivate *corePrivate, QObject *parent)
+GetRepositoryMetaInfoJob::GetRepositoryMetaInfoJob(PackageManagerCore *core, QObject *parent)
: KDJob(parent)
, m_canceled(false)
, m_silentRetries(4)
, m_retriesLeft(m_silentRetries)
, m_downloader(0)
, m_waitForDone(false)
- , m_corePrivate(corePrivate)
+ , m_core(core)
{
setCapabilities(Cancelable);
}
@@ -331,12 +331,11 @@ void GetRepositoryMetaInfoJob::updatesXmlDownloadFinished()
}
if (!repositoryUpdates.isEmpty()) {
- if (m_corePrivate->m_data.settings().updateDefaultRepositories(repositoryUpdates)
- == Settings::UpdatesApplied) {
- if (m_corePrivate->isUpdater() || m_corePrivate->isPackageManager())
- m_corePrivate->writeMaintenanceConfigFiles();
- finished(QInstaller::RepositoryUpdatesReceived, tr("Repository updates received."));
- return;
+ if (m_core->settings().updateDefaultRepositories(repositoryUpdates) == Settings::UpdatesApplied) {
+ if (m_core->isUpdater() || m_core->isPackageManager())
+ m_core->writeMaintenanceConfigFiles();
+ finished(QInstaller::RepositoryUpdatesReceived, tr("Repository updates received."));
+ return;
}
}
}
@@ -538,26 +537,26 @@ void GetRepositoryMetaInfoJob::onAuthenticatorChanged(const QAuthenticator &auth
const QString username = authenticator.user();
const QString password = authenticator.password();
if (username != m_repository.username() || password != m_repository.password()) {
- QSet<Repository> repositories = m_corePrivate->m_data.settings().defaultRepositories();
+ QSet<Repository> repositories = m_core->settings().defaultRepositories();
bool reposChanged = updateRepositories(&repositories, username, password);
if (reposChanged)
- m_corePrivate->m_data.settings().setDefaultRepositories(repositories);
+ m_core->settings().setDefaultRepositories(repositories);
- repositories = m_corePrivate->m_data.settings().temporaryRepositories();
+ repositories = m_core->settings().temporaryRepositories();
reposChanged |= updateRepositories(&repositories, username, password);
if (reposChanged) {
- m_corePrivate->m_data.settings().setTemporaryRepositories(repositories,
- m_corePrivate->m_data.settings().hasReplacementRepos());
+ m_core->settings().setTemporaryRepositories(repositories,
+ m_core->settings().hasReplacementRepos());
}
- repositories = m_corePrivate->m_data.settings().userRepositories();
+ repositories = m_core->settings().userRepositories();
reposChanged |= updateRepositories(&repositories, username, password);
if (reposChanged)
- m_corePrivate->m_data.settings().setUserRepositories(repositories);
+ m_core->settings().setUserRepositories(repositories);
if (reposChanged) {
- if (m_corePrivate->isUpdater() || m_corePrivate->isPackageManager())
- m_corePrivate->writeMaintenanceConfigFiles();
+ if (m_core->isUpdater() || m_core->isPackageManager())
+ m_core->writeMaintenanceConfigFiles();
finished(QInstaller::RepositoryUpdatesReceived, tr("Repository updates received."));
}
}
diff --git a/src/libs/installer/getrepositorymetainfojob.h b/src/libs/installer/getrepositorymetainfojob.h
index 8601742a2..803f8b43f 100644
--- a/src/libs/installer/getrepositorymetainfojob.h
+++ b/src/libs/installer/getrepositorymetainfojob.h
@@ -61,7 +61,7 @@ namespace KDUpdater {
namespace QInstaller {
class GetRepositoriesMetaInfoJob;
-class PackageManagerCorePrivate;
+class PackageManagerCore;
class INSTALLER_EXPORT GetRepositoryMetaInfoJob : public KDJob
{
@@ -70,7 +70,7 @@ class INSTALLER_EXPORT GetRepositoryMetaInfoJob : public KDJob
friend class QInstaller::GetRepositoriesMetaInfoJob;
public:
- explicit GetRepositoryMetaInfoJob(PackageManagerCorePrivate *corePrivate, QObject *parent = 0);
+ explicit GetRepositoryMetaInfoJob(PackageManagerCore *core, QObject *parent = 0);
~GetRepositoryMetaInfoJob();
Repository repository() const;
@@ -119,7 +119,7 @@ private:
bool m_waitForDone;
QThreadPool m_threadPool;
- PackageManagerCorePrivate *m_corePrivate;
+ PackageManagerCore *m_core;
};
} // namespace QInstaller
diff --git a/src/libs/installer/graph.h b/src/libs/installer/graph.h
new file mode 100644
index 000000000..59778a440
--- /dev/null
+++ b/src/libs/installer/graph.h
@@ -0,0 +1,158 @@
+/**************************************************************************
+**
+** Copyright (C) 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 GRAPH_H
+#define GRAPH_H
+
+#include <QHash>
+#include <QList>
+#include <QPair>
+#include <QSet>
+
+namespace QInstaller {
+
+template <class T> class Graph
+{
+public:
+ inline Graph() {}
+ explicit Graph(const QList<T> &nodes)
+ {
+ addNodes(nodes);
+ }
+
+ const QList<T> nodes() const
+ {
+ return m_graph.keys();
+ }
+
+ void addNode(const T &node)
+ {
+ m_graph.insert(node, QSet<T>());
+ }
+
+ void addNodes(const QList<T> &nodes)
+ {
+ foreach (const T &node, nodes)
+ addNode(node);
+ }
+
+ QList<T> edges(const T &node) const
+ {
+ return m_graph.value(node).toList();
+ }
+
+ void addEdge(const T &node, const T &edge)
+ {
+ m_graph[node].insert(edge);
+ }
+
+ void addEdges(const T &node, const QList<T> &edges)
+ {
+ foreach (const T &edge, edges)
+ addEdge(node, edge);
+ }
+
+ bool hasCycle() const
+ {
+ return m_hasCycle;
+ }
+
+ QPair<T, T> cycle() const
+ {
+ return m_cycle;
+ }
+
+ QList<T> sort() const
+ {
+ QSet<T> visitedNodes;
+ QList<T> resolvedNodes;
+
+ m_hasCycle = false;
+ m_cycle = qMakePair(T(), T());
+ foreach (const T &node, nodes())
+ visit(node, &resolvedNodes, &visitedNodes);
+ return resolvedNodes;
+ }
+
+ QList<T> sortReverse() const
+ {
+ QList<T> result = sort();
+ std::reverse(result.begin(), result.end());
+ return result;
+ }
+
+private:
+ void visit(const T &node, QList<T> *const resolvedNodes, QSet<T> *const visitedNodes) const
+ {
+ if (m_hasCycle)
+ return;
+
+ // if we visited this node already
+ if (visitedNodes->contains(node)) {
+ // and if the node is already in the ordered list
+ if (resolvedNodes->contains(node))
+ return;
+
+ m_hasCycle = true;
+ m_cycle.second = node;
+ return; // if not yet in the ordered list, we detected a cycle
+ }
+
+ // mark this node as visited
+ visitedNodes->insert(node);
+
+ m_cycle.first = node;
+ // recursively visit all adjacency
+ foreach (const T &adjacency, edges(node))
+ visit(adjacency, resolvedNodes, visitedNodes);
+
+ // append this node the the ordered list
+ resolvedNodes->append(node);
+ }
+
+private:
+ mutable bool m_hasCycle;
+ QHash<T, QSet<T> > m_graph;
+ mutable QPair<T,T> m_cycle;
+};
+
+}
+#endif // GRAPH_H
diff --git a/src/libs/installer/installer.pro b/src/libs/installer/installer.pro
index 5ae0b1afb..a1631c4a3 100644
--- a/src/libs/installer/installer.pro
+++ b/src/libs/installer/installer.pro
@@ -100,7 +100,8 @@ HEADERS += packagemanagercore.h \
createlinkoperation.h \
packagemanagercoredata.h \
applyproductkeyoperation.h \
- globals.h
+ globals.h \
+ graph.h
SOURCES += packagemanagercore.cpp \
packagemanagercore_p.cpp \
diff --git a/src/libs/installer/installiconsoperation.cpp b/src/libs/installer/installiconsoperation.cpp
index f46ab5315..dba6d644b 100644
--- a/src/libs/installer/installiconsoperation.cpp
+++ b/src/libs/installer/installiconsoperation.cpp
@@ -45,6 +45,7 @@
#include <QtCore/QDir>
#include <QtCore/QDirIterator>
+#include <QDebug>
#if QT_VERSION >= 0x040600
# include <QProcessEnvironment>
@@ -121,10 +122,6 @@ InstallIconsOperation::InstallIconsOperation()
InstallIconsOperation::~InstallIconsOperation()
{
const QStringList backupFiles = value(QLatin1String("backupfiles")).toStringList();
- for (QStringList::const_iterator it = backupFiles.begin(); it != backupFiles.end(); it += 2) {
- const QString& backup = *(it + 1);
- deleteFileNowOrLater(backup);
- }
}
void InstallIconsOperation::backup()
@@ -164,8 +161,6 @@ bool InstallIconsOperation::performOperation()
QDirIterator it(sourceDir.path(), QDir::Dirs | QDir::Files | QDir::Hidden | QDir::NoDotAndDotDot,
QDirIterator::Subdirectories);
while (it.hasNext()) {
- qApp->processEvents();
-
const int status = core->status();
if (status == PackageManagerCore::Canceled || status == PackageManagerCore::Failure)
return true;
@@ -194,7 +189,7 @@ bool InstallIconsOperation::performOperation()
if (QFile(target).exists()) {
// first backup...
- const QString backup = generateTemporaryFileName(target + QLatin1String("XXXXXX"));
+ const QString backup = generateTemporaryFileName(target);
QFile bf(target);
if (!bf.copy(backup)) {
setError(UserDefinedError);
@@ -251,12 +246,10 @@ bool InstallIconsOperation::performOperation()
bool InstallIconsOperation::undoOperation()
{
- bool success = true;
-
+ QStringList warningMessages;
// first copy back all files to their origin
const QStringList files = value(QLatin1String("files")).toStringList();
for (QStringList::const_iterator it = files.begin(); it != files.end(); it += 2) {
- qApp->processEvents();
const QString& source = *it;
const QString& target = *(it + 1);
@@ -264,10 +257,11 @@ bool InstallIconsOperation::undoOperation()
// first make sure the "source" path is valid
QDir().mkpath(QFileInfo(source).absolutePath());
- // now copy target to source (feels weird, I know...)
- success = QFile::copy(target, source) && success;
- // and remove target
- success = QFile::remove(target) && success;
+ QFile installedTarget(target);
+ if (installedTarget.exists() && !(installedTarget.copy(source) && installedTarget.remove())) {
+ warningMessages << QString::fromLatin1("Could not move file from '%1' to '%2', error: %3)").arg(
+ target, source, installedTarget.errorString());
+ }
}
// then copy back and remove all backuped files
@@ -278,11 +272,17 @@ bool InstallIconsOperation::undoOperation()
// remove the target
if (QFile::exists(target))
- success = deleteFileNowOrLater(target) && success;
+ deleteFileNowOrLater(target);
// then copy the backup onto the target
- success = QFile::copy(backup, target) && success;
+ if (!QFile::copy(backup, target)) {
+ warningMessages << QString::fromLatin1("Could not restore the backup '%1' to '%2'").arg(
+ backup, target);
+ }
+
// finally remove the backp
- success = deleteFileNowOrLater(backup) && success;
+ if (!deleteFileNowOrLater(backup))
+ warningMessages << QString::fromLatin1("Could not remove the backup '%1'").arg(backup);
+
}
// then remove all directories created by us
@@ -290,10 +290,19 @@ bool InstallIconsOperation::undoOperation()
for (QStringList::const_iterator it = createdDirectories.begin(); it != createdDirectories.end(); ++it) {
const QDir dir(*it);
removeSystemGeneratedFiles(dir.absolutePath());
- success = QDir::root().rmdir(dir.path());
+ if (dir.exists() && !QDir::root().rmdir(dir.path()))
+ warningMessages << QString::fromLatin1("Could not remove directory '%1'").arg(dir.path());
+ }
+
+ if (!warningMessages.isEmpty()) {
+ qWarning() << QString::fromLatin1("Undo of operation '%1' with arguments '%2' had some problems.").arg(
+ name(), arguments().join(QLatin1String(", ")));
+ foreach (const QString &message, warningMessages) {
+ qWarning() << message;
+ }
}
- return success;
+ return true;
}
bool InstallIconsOperation::testOperation()
diff --git a/src/libs/installer/macreplaceinstallnamesoperation.cpp b/src/libs/installer/macreplaceinstallnamesoperation.cpp
index 470c15b37..9ec553358 100644
--- a/src/libs/installer/macreplaceinstallnamesoperation.cpp
+++ b/src/libs/installer/macreplaceinstallnamesoperation.cpp
@@ -198,9 +198,8 @@ void MacReplaceInstallNamesOperation::relocateBinary(const MacBinaryInfo &info,
// change framework ID only if dynamicLibId isn't only the filename, if it has no relative path ("@")
- // and is not existing at the current looking for location
if (!info.dynamicLibId.isEmpty() && (info.dynamicLibId != QFileInfo(info.fileName).fileName())
- && !info.dynamicLibId.contains(QLatin1String("@")) && !QFileInfo(info.dynamicLibId).exists()) {
+ && !info.dynamicLibId.contains(QLatin1String("@"))) {
// error is set inside the execCommand method
if (!execCommand(QLatin1String("install_name_tool"), QStringList(QLatin1String("-id"))
<< info.fileName << info.fileName)) {
diff --git a/src/libs/installer/packagemanagercore.cpp b/src/libs/installer/packagemanagercore.cpp
index 9543aca5e..c617dd239 100644
--- a/src/libs/installer/packagemanagercore.cpp
+++ b/src/libs/installer/packagemanagercore.cpp
@@ -192,12 +192,6 @@
*/
/*!
- \qmlsignal QInstaller::setRootComponents(list<Component> components)
-
- Triggered with the list of new root components (for example after an online update).
-*/
-
-/*!
\qmlsignal QInstaller::startAllComponentsReset()
Triggered when the list of components starts to get updated.
@@ -206,9 +200,9 @@
*/
/*!
- \qmlsignal QInstaller::finishAllComponentsReset()
+ \qmlsignal QInstaller::finishAllComponentsReset(list<Component> rootComponents)
- Triggered when the list of components has been updated.
+ Triggered when the list of new root components has been updated.
\sa startAllComponentsReset
*/
@@ -220,9 +214,9 @@
*/
/*!
- \qmlsignal QInstaller::finishUpdaterComponentsReset()
+ \qmlsignal QInstaller::finishUpdaterComponentsReset(list<Component> componentsWithUpdates)
- Triggered when components have been updated during a remote update.
+ Triggered when the list of available remote updates has been updated.
*/
/*!
@@ -419,6 +413,11 @@ void PackageManagerCore::writeUninstaller()
}
}
+void PackageManagerCore::writeMaintenanceConfigFiles()
+{
+ d->writeMaintenanceConfigFiles();
+}
+
void PackageManagerCore::reset(const QHash<QString, QString> &params)
{
d->m_completeUninstall = false;
@@ -814,9 +813,8 @@ bool PackageManagerCore::fetchLocalPackagesTree()
updateDisplayVersions(scDisplayVersion);
- emit finishAllComponentsReset();
+ emit finishAllComponentsReset(d->m_rootComponents);
d->setStatus(Success);
- emit setRootComponents(d->m_rootComponents);
return true;
}
@@ -889,9 +887,39 @@ bool PackageManagerCore::fetchRemotePackagesTree()
return false;
bool success = false;
- if (!isUpdater())
+ if (!isUpdater()) {
success = fetchAllPackages(packages, installedPackages);
- else {
+ if (success && !d->statusCanceledOrFailed() && isPackageManager()) {
+ foreach (Package *const update, packages) {
+ if (update->data(scEssential, scFalse).toString().toLower() == scTrue) {
+ const QString name = update->data(scName).toString();
+ if (!installedPackages.contains(name)) {
+ success = false;
+ break; // unusual, the maintenance tool should always be available
+ }
+
+ const LocalPackage localPackage = installedPackages.value(name);
+ const QString updateVersion = update->data(scRemoteVersion).toString();
+ if (KDUpdater::compareVersion(updateVersion, localPackage.version) <= 0)
+ break; // remote version equals or is less than the installed maintenance tool
+
+ const QDate updateDate = update->data(scReleaseDate).toDate();
+ if (localPackage.lastUpdateDate >= updateDate)
+ break; // remote release date equals or is less than the installed maintenance tool
+
+ success = false;
+ break; // we found a newer version of the maintenance tool
+ }
+ }
+
+ if (!success && !d->statusCanceledOrFailed()) {
+ updateDisplayVersions(scRemoteDisplayVersion);
+ d->setStatus(ForceUpdate, tr("There is an important update available, please run the "
+ "updater first."));
+ return false;
+ }
+ }
+ } else {
success = fetchUpdaterPackages(packages, installedPackages);
}
@@ -1315,6 +1343,8 @@ ComponentModel *PackageManagerCore::defaultComponentModel() const
d->m_defaultModel = componentModel(const_cast<PackageManagerCore*> (this),
QLatin1String("AllComponentsModel"));
}
+ connect(this, SIGNAL(finishAllComponentsReset(QList<QInstaller::Component*>)), d->m_defaultModel,
+ SLOT(setRootComponents(QList<QInstaller::Component*>)));
return d->m_defaultModel;
}
@@ -1325,6 +1355,8 @@ ComponentModel *PackageManagerCore::updaterComponentModel() const
d->m_updaterModel = componentModel(const_cast<PackageManagerCore*> (this),
QLatin1String("UpdaterComponentsModel"));
}
+ connect(this, SIGNAL(finishUpdaterComponentsReset(QList<QInstaller::Component*>)), d->m_updaterModel,
+ SLOT(setRootComponents(QList<QInstaller::Component*>)));
return d->m_updaterModel;
}
@@ -2141,8 +2173,7 @@ bool PackageManagerCore::fetchAllPackages(const PackagesList &remotes, const Loc
if (!d->buildComponentTree(components, true))
return false;
- emit finishAllComponentsReset();
- emit setRootComponents(d->m_rootComponents);
+ emit finishAllComponentsReset(d->m_rootComponents);
return true;
}
@@ -2192,7 +2223,9 @@ bool PackageManagerCore::fetchUpdaterPackages(const PackagesList &remotes, const
}
}
- if (!isValidUpdate)
+ // break if the update is not valid and if it's not the maintenance tool (we might get an update
+ // for the maintenance tool even if it's not currently installed - possible offline installation)
+ if (!isValidUpdate && (update->data(scEssential, scFalse).toString().toLower() == scFalse))
continue; // Update for not installed package found, skip it.
const LocalPackage &localPackage = locals.value(name);
@@ -2283,7 +2316,7 @@ bool PackageManagerCore::fetchUpdaterPackages(const PackagesList &remotes, const
}
} catch (const Error &error) {
d->clearUpdaterComponentLists();
- emit finishUpdaterComponentsReset();
+ emit finishUpdaterComponentsReset(QList<QInstaller::Component*>());
d->setStatus(Failure, error.message());
// TODO: make sure we remove all message boxes inside the library at some point.
@@ -2292,8 +2325,7 @@ bool PackageManagerCore::fetchUpdaterPackages(const PackagesList &remotes, const
return false;
}
- emit finishUpdaterComponentsReset();
- emit setRootComponents(d->m_updaterComponents);
+ emit finishUpdaterComponentsReset(d->m_updaterComponents);
return true;
}
@@ -2346,7 +2378,7 @@ QString PackageManagerCore::findDisplayVersion(const QString &componentName,
ComponentModel *PackageManagerCore::componentModel(PackageManagerCore *core, const QString &objectName) const
{
- ComponentModel *model = new ComponentModel(4, core);
+ ComponentModel *model = new ComponentModel(5, core);
model->setObjectName(objectName);
model->setHeaderData(ComponentModelHelper::NameColumn, Qt::Horizontal,
@@ -2355,10 +2387,10 @@ ComponentModel *PackageManagerCore::componentModel(PackageManagerCore *core, con
ComponentModel::tr("Installed Version"));
model->setHeaderData(ComponentModelHelper::NewVersionColumn, Qt::Horizontal,
ComponentModel::tr("New Version"));
+ model->setHeaderData(ComponentModelHelper::ReleaseDateColumn, Qt::Horizontal,
+ ComponentModel::tr("Release Date"));
model->setHeaderData(ComponentModelHelper::UncompressedSizeColumn, Qt::Horizontal,
ComponentModel::tr("Size"));
- connect(this, SIGNAL(setRootComponents(QList<QInstaller::Component*>)), model,
- SLOT(setRootComponents(QList<QInstaller::Component*>)));
connect(model, SIGNAL(checkStateChanged(QInstaller::ComponentModel::ModelState)), this,
SLOT(componentsToInstallNeedsRecalculation()));
diff --git a/src/libs/installer/packagemanagercore.h b/src/libs/installer/packagemanagercore.h
index 712a5174c..20a3293fa 100644
--- a/src/libs/installer/packagemanagercore.h
+++ b/src/libs/installer/packagemanagercore.h
@@ -82,7 +82,8 @@ public:
Failure = EXIT_FAILURE,
Running,
Canceled,
- Unfinished
+ Unfinished,
+ ForceUpdate
};
Status status() const;
QString error() const;
@@ -157,6 +158,8 @@ public:
QStringList replaceVariables(const QStringList &str) const;
void writeUninstaller();
+ void writeMaintenanceConfigFiles();
+
QString uninstallerName() const;
QString installerBinaryPath() const;
@@ -271,13 +274,12 @@ Q_SIGNALS:
void finishButtonClicked();
void metaJobInfoMessage(const QString &message);
- void setRootComponents(const QList<QInstaller::Component*> &components);
void startAllComponentsReset();
- void finishAllComponentsReset();
+ void finishAllComponentsReset(const QList<QInstaller::Component*> &rootComponents);
void startUpdaterComponentsReset();
- void finishUpdaterComponentsReset();
+ void finishUpdaterComponentsReset(const QList<QInstaller::Component*> &componentsWithUpdates);
void installationStarted();
void installationInterrupted();
diff --git a/src/libs/installer/packagemanagercore_p.cpp b/src/libs/installer/packagemanagercore_p.cpp
index 1728a85b2..f102d79ed 100644
--- a/src/libs/installer/packagemanagercore_p.cpp
+++ b/src/libs/installer/packagemanagercore_p.cpp
@@ -49,6 +49,7 @@
#include "fileutils.h"
#include "fsengineclient.h"
#include "globals.h"
+#include "graph.h"
#include "messageboxhandler.h"
#include "packagemanagercore.h"
#include "progresscoordinator.h"
@@ -95,7 +96,8 @@ public:
{
if (!m_operation)
return;
- qDebug() << QString::fromLatin1("%1 operation: %2").arg(state, m_operation->name());
+ qDebug() << QString::fromLatin1("%1 %2 operation: %3").arg(state, m_operation->value(
+ QLatin1String("component")).toString(), m_operation->name());
qDebug() << QString::fromLatin1("\t- arguments: %1").arg(m_operation->arguments()
.join(QLatin1String(", ")));
}
@@ -379,7 +381,7 @@ bool PackageManagerCorePrivate::buildComponentTree(QHash<QString, Component*> &c
std::sort(m_rootComponents.begin(), m_rootComponents.end(), Component::SortingPriorityGreaterThan());
} catch (const Error &error) {
clearAllComponentLists();
- emit m_core->finishAllComponentsReset();
+ emit m_core->finishAllComponentsReset(QList<QInstaller::Component*>());
setStatus(PackageManagerCore::Failure, error.message());
// TODO: make sure we remove all message boxes inside the library at some point.
@@ -630,7 +632,7 @@ void PackageManagerCorePrivate::initialize(const QHash<QString, QString> &params
}
if (!m_repoMetaInfoJob) {
- m_repoMetaInfoJob = new GetRepositoriesMetaInfoJob(this);
+ m_repoMetaInfoJob = new GetRepositoriesMetaInfoJob(m_core);
m_repoMetaInfoJob->setAutoDelete(false);
connect(m_repoMetaInfoJob, SIGNAL(infoMessage(KDJob*, QString)), this, SLOT(infoMessage(KDJob*,
QString)));
@@ -1328,9 +1330,15 @@ void PackageManagerCorePrivate::writeUninstaller(OperationList performedOperatio
#endif
}
+ performedOperations = sortOperationsBasedOnComponentDependencies(
+ performedOperations);
+
+ m_core->setValue(QLatin1String("installedOperationAreSorted"), QLatin1String("true"));
+
try {
KDSaveFile file(dataFile + QLatin1String(".new"));
openForWrite(&file, file.fileName());
+
writeUninstallerBinaryData(&file, &input, performedOperations, layout);
appendInt64(&file, MagicCookieDat);
file.setPermissions(file.permissions() | QFile::WriteUser | QFile::ReadGroup
@@ -1611,8 +1619,14 @@ bool PackageManagerCorePrivate::runPackageUpdater()
OperationList nonRevertedOperations;
QHash<QString, Component *> componentsByName;
+ // order the operations in the right component dependency order
+ // next loop will save the needed operations in reverse order for uninstallation
+ OperationList performedOperationsOld = m_performedOperationsOld;
+ if (m_core->value(QLatin1String("installedOperationAreSorted")) != QLatin1String("true"))
+ performedOperationsOld = sortOperationsBasedOnComponentDependencies(m_performedOperationsOld);
+
// build a list of undo operations based on the checked state of the component
- foreach (Operation *operation, m_performedOperationsOld) {
+ foreach (Operation *operation, performedOperationsOld) {
const QString &name = operation->value(QLatin1String("component")).toString();
Component *component = componentsByName.value(name, 0);
if (!component)
@@ -1663,6 +1677,7 @@ bool PackageManagerCorePrivate::runPackageUpdater()
continue;
}
+ // uninstallation should be in reverse order so prepend it here
undoOperations.prepend(operation);
updateAdminRights |= operation->value(QLatin1String("admin")).toBool();
}
@@ -1864,7 +1879,6 @@ void PackageManagerCorePrivate::installComponent(Component *component, double pr
// Remember that the operation was performed, that allows us to undo it if a following operation
// fails or if this operation failed but still needs an undo call to cleanup.
addPerformed(operation);
- operation->setValue(QLatin1String("component"), component->name());
}
if (becameAdmin)
@@ -2017,22 +2031,18 @@ void PackageManagerCorePrivate::runUndoOperations(const OperationList &undoOpera
const QString componentName = undoOperation->value(QLatin1String("component")).toString();
if (!componentName.isEmpty()) {
- while (!ok && !ignoreError && m_core->status() != PackageManagerCore::Canceled) {
- const QMessageBox::StandardButton button =
- MessageBoxHandler::warning(MessageBoxHandler::currentBestSuitParent(),
- QLatin1String("installationErrorWithRetry"), tr("Installer Error"),
- tr("Error during uninstallation process:\n%1").arg(undoOperation->errorString()),
- QMessageBox::Retry | QMessageBox::Ignore, QMessageBox::Retry);
-
- if (button == QMessageBox::Retry) {
- ok = performOperationThreaded(undoOperation, Undo);
- } else if (button == QMessageBox::Ignore) {
- ignoreError = true;
- }
- }
- }
-
- if (!componentName.isEmpty()) {
+ while (!ok && !ignoreError && m_core->status() != PackageManagerCore::Canceled) {
+ const QMessageBox::StandardButton button =
+ MessageBoxHandler::warning(MessageBoxHandler::currentBestSuitParent(),
+ QLatin1String("installationErrorWithRetry"), tr("Installer Error"),
+ tr("Error during uninstallation process:\n%1").arg(undoOperation->errorString()),
+ QMessageBox::Retry | QMessageBox::Ignore, QMessageBox::Retry);
+
+ if (button == QMessageBox::Retry)
+ ok = performOperationThreaded(undoOperation, Undo);
+ else if (button == QMessageBox::Ignore)
+ ignoreError = true;
+ }
Component *component = m_core->componentByName(componentName);
if (!component)
component = componentsToReplace().value(componentName).second;
@@ -2359,6 +2369,37 @@ void PackageManagerCorePrivate::connectOperationCallMethodRequest(Operation *con
}
}
+OperationList PackageManagerCorePrivate::sortOperationsBasedOnComponentDependencies(const OperationList &operationList)
+{
+ OperationList sortedOperations;
+ QHash<QString, OperationList> componentOperationHash;
+
+ // sort component unrelated operations to the beginning
+ foreach (Operation *operation, operationList) {
+ const QString componentName = operation->value(QLatin1String("component")).toString();
+ if (componentName.isEmpty())
+ sortedOperations.append(operation);
+ else {
+ OperationList componentOperationList = componentOperationHash.value(componentName);
+ componentOperationList.append(operation);
+ componentOperationHash.insert(operation->value(QLatin1String("component")).toString(),
+ componentOperationList);
+ }
+ }
+
+ // create the complete component graph
+ Graph<QString> componentGraph;
+ foreach (const Component* componentNode, m_core->availableComponents()) {
+ componentGraph.addNode(componentNode->name());
+ componentGraph.addEdges(componentNode->name(), componentNode->dependencies());
+ }
+
+ foreach (const QString &componentName, componentGraph.sort())
+ sortedOperations.append(componentOperationHash.value(componentName));
+
+ return sortedOperations;
+}
+
void PackageManagerCorePrivate::handleMethodInvocationRequest(const QString &invokableMethodName)
{
QObject *obj = QObject::sender();
diff --git a/src/libs/installer/packagemanagercore_p.h b/src/libs/installer/packagemanagercore_p.h
index 11ed23230..d5bdc78fd 100644
--- a/src/libs/installer/packagemanagercore_p.h
+++ b/src/libs/installer/packagemanagercore_p.h
@@ -167,6 +167,7 @@ public:
int countProgressOperations(const OperationList &operations);
void connectOperationToInstaller(Operation *const operation, double progressOperationPartSize);
void connectOperationCallMethodRequest(Operation *const operation);
+ OperationList sortOperationsBasedOnComponentDependencies(const OperationList &operationList);
Operation *createOwnedOperation(const QString &type);
Operation *takeOwnedOperation(Operation *operation);
diff --git a/src/libs/installer/packagemanagercoredata.cpp b/src/libs/installer/packagemanagercoredata.cpp
index efc83f520..2294a8086 100644
--- a/src/libs/installer/packagemanagercoredata.cpp
+++ b/src/libs/installer/packagemanagercoredata.cpp
@@ -57,6 +57,8 @@ PackageManagerCoreData::PackageManagerCoreData(const QHash<QString, QString> &va
// in a script or...
m_variables.insert(QLatin1String("rootDir"), QDir::rootPath());
m_variables.insert(QLatin1String("homeDir"), QDir::homePath());
+ m_variables.insert(QLatin1String("RootDir"), QDir::rootPath());
+ m_variables.insert(QLatin1String("HomeDir"), QDir::homePath());
m_variables.insert(scTargetConfigurationFile, QLatin1String("components.xml"));
#ifdef Q_OS_WIN
diff --git a/src/libs/installer/packagemanagergui.cpp b/src/libs/installer/packagemanagergui.cpp
index 10caed749..2db2a9e4a 100644
--- a/src/libs/installer/packagemanagergui.cpp
+++ b/src/libs/installer/packagemanagergui.cpp
@@ -299,20 +299,30 @@ QString PackageManagerGui::defaultButtonText(int wizardButton) const
void PackageManagerGui::clickButton(int wb, int delay)
{
- if (QAbstractButton *b = button(static_cast<QWizard::WizardButton>(wb) )) {
+ // transform the FinishButton to CancelButton, because of the needed misuse of the
+ // CancelButton as a FinishButton to have some more control of closing the wizard
+ if (!m_core->isInstaller() && currentId() == PackageManagerCore::InstallationFinished &&
+ wb == QWizard::FinishButton) {
+ wb = QWizard::CancelButton;
+ }
+ if (QAbstractButton *b = button(static_cast<QWizard::WizardButton>(wb) ))
QTimer::singleShot(delay, b, SLOT(click()));
- } else {
+ else
qWarning() << "Button with type: " << d->buttonType(wb) << "not found!";
- }
}
bool PackageManagerGui::isButtonEnabled(int wb)
{
- if (QAbstractButton *b = button(static_cast<QWizard::WizardButton>(wb) )) {
- return b->isEnabled();
- } else {
- qWarning() << "Button with type: " << d->buttonType(wb) << "not found!";
+ // transform the FinishButton to CancelButton, because of the needed misuse of the
+ // CancelButton as a FinishButton to have some more control of closing the wizard
+ if (!m_core->isInstaller() && currentId() == PackageManagerCore::InstallationFinished &&
+ wb == QWizard::FinishButton) {
+ wb = QWizard::CancelButton;
}
+ if (QAbstractButton *b = button(static_cast<QWizard::WizardButton>(wb) ))
+ return b->isEnabled();
+
+ qWarning() << "Button with type: " << d->buttonType(wb) << "not found!";
return false;
}
@@ -970,9 +980,9 @@ public:
m_treeView->setObjectName(QLatin1String("ComponentsTreeView"));
connect(m_allModel, SIGNAL(checkStateChanged(QInstaller::ComponentModel::ModelState)), this,
- SLOT(onCheckStateChanged(QInstaller::ComponentModel::ModelState)));
+ SLOT(onModelStateChanged(QInstaller::ComponentModel::ModelState)));
connect(m_updaterModel, SIGNAL(checkStateChanged(QInstaller::ComponentModel::ModelState)), this,
- SLOT(onCheckStateChanged(QInstaller::ComponentModel::ModelState)));
+ SLOT(onModelStateChanged(QInstaller::ComponentModel::ModelState)));
QHBoxLayout *hlayout = new QHBoxLayout;
hlayout->addWidget(m_treeView, 3);
@@ -1034,8 +1044,6 @@ public:
{
m_checkDefault->setVisible(m_core->isInstaller() || m_core->isPackageManager());
if (m_treeView->selectionModel()) {
- disconnect(m_currentModel, SIGNAL(checkStateChanged(QModelIndex)), this,
- SLOT(currentCheckedChanged(QModelIndex)));
disconnect(m_treeView->selectionModel(), SIGNAL(currentChanged(QModelIndex, QModelIndex)),
this, SLOT(currentSelectedChanged(QModelIndex)));
}
@@ -1060,8 +1068,6 @@ public:
hasChildren = m_currentModel->hasChildren(m_currentModel->index(row, 0));
m_treeView->setRootIsDecorated(hasChildren);
- connect(m_currentModel, SIGNAL(checkStateChanged(QModelIndex)), this,
- SLOT(currentCheckedChanged(QModelIndex)));
connect(m_treeView->selectionModel(), SIGNAL(currentChanged(QModelIndex, QModelIndex)),
this, SLOT(currentSelectedChanged(QModelIndex)));
@@ -1069,12 +1075,6 @@ public:
}
public slots:
- void currentCheckedChanged(const QModelIndex &current)
- {
- if (m_treeView->selectionModel()->currentIndex() == current)
- currentSelectedChanged(current);
- }
-
void currentSelectedChanged(const QModelIndex &current)
{
if (!current.isValid())
@@ -1088,7 +1088,7 @@ public slots:
if ((m_core->isUninstaller()) || (!component))
return;
- if ((component->checkState() != Qt::Unchecked) && (component->updateUncompressedSize() > 0)) {
+ if (component->isSelected() && (component->value(scUncompressedSizeSum).toLongLong() > 0)) {
m_sizeLabel->setText(ComponentSelectionPage::tr("This component "
"will occupy approximately %1 on your hard disk drive.")
.arg(humanReadableSize(component->value(scUncompressedSizeSum).toLongLong())));
@@ -1110,10 +1110,9 @@ public slots:
m_currentModel->setCheckedState(ComponentModel::DefaultChecked);
}
- void onCheckStateChanged(QInstaller::ComponentModel::ModelState state)
+ void onModelStateChanged(QInstaller::ComponentModel::ModelState state)
{
- q->setModified(state != ComponentModel::DefaultChecked);
-
+ q->setModified(state.testFlag(ComponentModel::DefaultChecked) == false);
// If all components in the checked list are only checkable when run without forced installation, set
// ComponentModel::AllUnchecked as well, as we cannot uncheck anything. Helps to keep the UI correct.
if ((!m_core->noForceInstallation()) && (m_currentModel->checked() == m_currentModel->uncheckable()))
@@ -1123,6 +1122,10 @@ public slots:
m_checkAll->setEnabled(state.testFlag(ComponentModel::AllChecked) == false);
m_uncheckAll->setEnabled(state.testFlag(ComponentModel::AllUnchecked) == false);
m_checkDefault->setEnabled(state.testFlag(ComponentModel::DefaultChecked) == false);
+
+ // update the current selected node (important to reflect possible sub-node changes)
+ if (m_treeView->selectionModel())
+ currentSelectedChanged(m_treeView->selectionModel()->currentIndex());
}
public:
@@ -1233,7 +1236,7 @@ bool ComponentSelectionPage::isComplete() const
{
if (packageManagerCore()->isInstaller() || packageManagerCore()->isUpdater())
return d->m_currentModel->checked().count();
- return d->m_currentModel->checkedState() != ComponentModel::DefaultChecked;
+ return d->m_currentModel->checkedState().testFlag(ComponentModel::DefaultChecked) == false;
}
@@ -1836,6 +1839,13 @@ void FinishedPage::entering()
m_commitButton = cancel;
cancel->setEnabled(true);
cancel->setVisible(true);
+ // we don't use the usual FinishButton so we need to connect the misused CancelButton
+ connect(cancel, SIGNAL(clicked()), gui(), SIGNAL(finishButtonClicked()));
+ connect(cancel, SIGNAL(clicked()), packageManagerCore(), SIGNAL(finishButtonClicked()));
+ // for the moment we don't want the rejected signal connected
+ disconnect(gui(), SIGNAL(rejected()), packageManagerCore(), SLOT(setCanceled()));
+
+ connect(gui()->button(QWizard::CommitButton), SIGNAL(clicked()), this, SLOT(cleanupChangedConnects()));
}
setButtonText(QWizard::CommitButton, tr("Restart"));
setButtonText(QWizard::CancelButton, gui()->defaultButtonText(QWizard::FinishButton));
@@ -1901,6 +1911,17 @@ void FinishedPage::handleFinishClicked()
QProcess::startDetached(program, args);
}
+void FinishedPage::cleanupChangedConnects()
+{
+ if (QAbstractButton *cancel = gui()->button(QWizard::CancelButton)) {
+ // remove the workaround connect from entering page
+ disconnect(cancel, SIGNAL(clicked()), gui(), SIGNAL(finishButtonClicked()));
+ disconnect(cancel, SIGNAL(clicked()), packageManagerCore(), SIGNAL(finishButtonClicked()));
+ connect(gui(), SIGNAL(rejected()), packageManagerCore(), SLOT(setCanceled()));
+
+ disconnect(gui()->button(QWizard::CommitButton), SIGNAL(clicked()), this, SLOT(cleanupChangedConnects()));
+ }
+}
// -- RestartPage
diff --git a/src/libs/installer/packagemanagergui.h b/src/libs/installer/packagemanagergui.h
index 37e5d6852..5c428bf87 100644
--- a/src/libs/installer/packagemanagergui.h
+++ b/src/libs/installer/packagemanagergui.h
@@ -403,6 +403,7 @@ public:
public Q_SLOTS:
void handleFinishClicked();
+ void cleanupChangedConnects();
protected:
void entering();
diff --git a/src/libs/installer/productkeycheck.cpp b/src/libs/installer/productkeycheck.cpp
index fe1fd10af..a4af2b6d3 100644
--- a/src/libs/installer/productkeycheck.cpp
+++ b/src/libs/installer/productkeycheck.cpp
@@ -88,3 +88,10 @@ bool ProductKeyCheck::isValidLicenseTextFile(const QString &/*fileName*/)
{
return true;
}
+
+
+bool ProductKeyCheck::isValidRepository(const QInstaller::Repository &repository) const
+{
+ Q_UNUSED(repository)
+ return true;
+} \ No newline at end of file
diff --git a/src/libs/installer/productkeycheck.h b/src/libs/installer/productkeycheck.h
index d472d9288..6d72089e2 100644
--- a/src/libs/installer/productkeycheck.h
+++ b/src/libs/installer/productkeycheck.h
@@ -38,6 +38,7 @@
namespace QInstaller{
class PackageManagerCore;
+ class Repository;
}
class ProductKeyCheckPrivate;
@@ -60,6 +61,9 @@ public:
// to filter none valid licenses
bool isValidLicenseTextFile(const QString &fileName);
+ // to filter repositories not matching the license
+ bool isValidRepository(const QInstaller::Repository &repository) const;
+
private:
ProductKeyCheck();
ProductKeyCheckPrivate *const d;
diff --git a/src/libs/installer/qtpatchoperation.cpp b/src/libs/installer/qtpatchoperation.cpp
index 822d5e3a4..e9fbb65c5 100644
--- a/src/libs/installer/qtpatchoperation.cpp
+++ b/src/libs/installer/qtpatchoperation.cpp
@@ -254,19 +254,97 @@ bool QtPatchOperation::performOperation()
}
#ifdef Q_OS_MAC
- // just try to patch here at the beginning to keep the unpatched qmake if mac install_names_tool fails
- MacReplaceInstallNamesOperation operation;
- operation.setArguments(QStringList()
- //can not use the old path which is wrong in the webkit case
- //<< QString::fromUtf8(oldQtPath)
- << QLatin1String("/lib/Qt") // search string
- << newQtPathStr + QLatin1String("/lib/Qt") //replace string
- << newQtPathStr //where
- );
- if (!operation.performOperation()) {
- setError(operation.error());
- setErrorString(operation.errorString());
- return false;
+ // looking for /lib/Qt wasn't enough for all libs and frameworks,
+ // at the Qt4 case we had for example: /lib/libQtCLucene* and /lib/phonon*
+ // so now we find every possible replace string inside dynlib dependencies
+ // and we reduce it to few as possible search strings
+ QStringList possibleSearchStringList;
+ QDirIterator dirIterator(newQtPathStr + QLatin1String("/lib/"));
+ while (dirIterator.hasNext()) {
+ const QString possibleSearchString = QString(dirIterator.next()).remove(newQtPathStr);
+ const QFileInfo fileInfo = dirIterator.fileInfo();
+ if (fileInfo.isSymLink())
+ continue;
+ if (fileInfo.isDir()) {
+ if (possibleSearchString.endsWith(QLatin1String(".framework")))
+ possibleSearchStringList.append(possibleSearchString);
+ else
+ continue;
+ }
+ if (possibleSearchString.endsWith(QLatin1String(".dylib")))
+ possibleSearchStringList.append(possibleSearchString);
+ }
+
+ // now we have this in possibleSearchStringList at Qt 4.8.6
+// "/lib/libQtCLucene.4.8.6.dylib"
+// "/lib/libQtCLucene_debug.4.8.6.dylib"
+// "/lib/phonon.framework"
+// "/lib/QtCore.framework"
+// "/lib/QtDeclarative.framework"
+// "/lib/QtDesigner.framework"
+// "/lib/QtDesignerComponents.framework"
+// "/lib/QtGui.framework"
+// "/lib/QtHelp.framework"
+// "/lib/QtMultimedia.framework"
+// "/lib/QtNetwork.framework"
+// "/lib/QtOpenGL.framework"
+// "/lib/QtScript.framework"
+// "/lib/QtScriptTools.framework"
+// "/lib/QtSql.framework"
+// "/lib/QtSvg.framework"
+// "/lib/QtTest.framework"
+// "/lib/QtWebKit.framework"
+// "/lib/QtXml.framework"
+// "/lib/QtXmlPatterns.framework"
+
+ // so then we reduce the possible filter strings as much as possible
+ QStringList searchStringList;
+
+ // as the minimal search string use the subdirector lib + one letter from the name
+ int minFilterLength = QString(QLatin1String("/lib/")).length() + 1;
+
+ while (!possibleSearchStringList.isEmpty()) {
+ QString firstSearchString = possibleSearchStringList.first();
+ int filterLength = minFilterLength;
+ int lastFilterCount = 0;
+ QString lastFilterString;
+ // now filter as long as we find something more then 1
+ for (; filterLength < firstSearchString.length(); ++filterLength) {
+ QString filterString(firstSearchString.left(filterLength));
+ QStringList filteredStringList(possibleSearchStringList.filter(filterString));
+ // found a valid filter
+ if (lastFilterCount > filteredStringList.count()) {
+ possibleSearchStringList = QList<QString>::fromSet(possibleSearchStringList.toSet() -
+ possibleSearchStringList.filter(lastFilterString).toSet());
+ searchStringList.append(lastFilterString);
+ break;
+ } else if (lastFilterCount == 1){ //in case there is only one we can use the complete name
+ possibleSearchStringList = QList<QString>::fromSet(possibleSearchStringList.toSet() -
+ possibleSearchStringList.filter(firstSearchString).toSet());
+ searchStringList.append(firstSearchString);
+ break;
+ } else {
+ lastFilterCount = possibleSearchStringList.filter(filterString).count();
+ lastFilterString = filterString;
+ }
+ }
+ }
+
+ // in the tested Qt 4.8.6 case we have searchStringList ("/lib/libQtCLucene", "/lib/Qt", "/lib/phonon")
+ foreach (const QString &searchString, searchStringList) {
+ MacReplaceInstallNamesOperation operation;
+ operation.setArguments(QStringList()
+ //can not use the old path which is wrong in the webkit case
+ //<< QString::fromUtf8(oldQtPath)
+ << searchString
+ << newQtPathStr + searchString //replace string
+ << newQtPathStr //where
+ );
+ if (!operation.performOperation()) {
+ setError(operation.error());
+ setErrorString(operation.errorString());
+ return false;
+ }
}
#endif
diff --git a/src/libs/installer/scriptengine.cpp b/src/libs/installer/scriptengine.cpp
index 75a60dc15..e85ce9671 100644
--- a/src/libs/installer/scriptengine.cpp
+++ b/src/libs/installer/scriptengine.cpp
@@ -407,6 +407,8 @@ QScriptValue ScriptEngine::generateQInstallerObject()
qinstaller.setProperty(QLatin1String("Failure"), PackageManagerCore::Failure);
qinstaller.setProperty(QLatin1String("Running"), PackageManagerCore::Running);
qinstaller.setProperty(QLatin1String("Canceled"), PackageManagerCore::Canceled);
+ qinstaller.setProperty(QLatin1String("Unfinished"), PackageManagerCore::Unfinished);
+ qinstaller.setProperty(QLatin1String("ForceUpdate"), PackageManagerCore::ForceUpdate);
return qinstaller;
}