summaryrefslogtreecommitdiffstats
path: root/src/libs/installer
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/installer')
-rw-r--r--src/libs/installer/addqtcreatorarrayvalueoperation.h6
-rw-r--r--src/libs/installer/adminauthorization_win.cpp40
-rw-r--r--src/libs/installer/adminauthorization_x11.cpp2
-rw-r--r--src/libs/installer/binaryformat.cpp24
-rw-r--r--src/libs/installer/binaryformat.h2
-rw-r--r--src/libs/installer/binaryformatengine.cpp6
-rw-r--r--src/libs/installer/binaryformatenginehandler.cpp4
-rw-r--r--src/libs/installer/component.cpp511
-rw-r--r--src/libs/installer/component.h16
-rw-r--r--src/libs/installer/component_p.cpp177
-rw-r--r--src/libs/installer/component_p.h26
-rw-r--r--src/libs/installer/componentmodel.cpp459
-rw-r--r--src/libs/installer/componentmodel.h51
-rw-r--r--src/libs/installer/constants.h1
-rw-r--r--src/libs/installer/consumeoutputoperation.cpp158
-rw-r--r--src/libs/installer/consumeoutputoperation.h65
-rw-r--r--src/libs/installer/createdesktopentryoperation.cpp2
-rw-r--r--src/libs/installer/createshortcutoperation.cpp59
-rw-r--r--src/libs/installer/downloadarchivesjob.cpp16
-rw-r--r--src/libs/installer/elevatedexecuteoperation.cpp18
-rw-r--r--src/libs/installer/environmentvariablesoperation.cpp4
-rw-r--r--src/libs/installer/errors.h5
-rw-r--r--src/libs/installer/extractarchiveoperation_p.h8
-rw-r--r--src/libs/installer/fileutils.cpp42
-rw-r--r--src/libs/installer/fileutils.h3
-rw-r--r--src/libs/installer/fsengineclient.cpp34
-rw-r--r--src/libs/installer/fsengineserver.cpp16
-rw-r--r--src/libs/installer/getrepositoriesmetainfojob.cpp25
-rw-r--r--src/libs/installer/getrepositoriesmetainfojob.h6
-rw-r--r--src/libs/installer/getrepositorymetainfojob.cpp63
-rw-r--r--src/libs/installer/getrepositorymetainfojob.h6
-rw-r--r--src/libs/installer/globals.cpp47
-rw-r--r--src/libs/installer/globals.h54
-rw-r--r--src/libs/installer/graph.h158
-rw-r--r--src/libs/installer/init.cpp91
-rw-r--r--src/libs/installer/installer.pro21
-rw-r--r--src/libs/installer/installiconsoperation.cpp47
-rw-r--r--src/libs/installer/lib7z_facade.cpp117
-rw-r--r--src/libs/installer/lib7z_facade.h92
-rw-r--r--src/libs/installer/link.h2
-rw-r--r--src/libs/installer/macreplaceinstallnamesoperation.cpp3
-rw-r--r--src/libs/installer/macreplaceinstallnamesoperation.h6
-rw-r--r--src/libs/installer/messageboxhandler.cpp167
-rw-r--r--src/libs/installer/messageboxhandler.h4
-rw-r--r--src/libs/installer/packagemanagercore.cpp914
-rw-r--r--src/libs/installer/packagemanagercore.h16
-rw-r--r--src/libs/installer/packagemanagercore_p.cpp139
-rw-r--r--src/libs/installer/packagemanagercore_p.h43
-rw-r--r--src/libs/installer/packagemanagercoredata.cpp4
-rw-r--r--src/libs/installer/packagemanagergui.cpp380
-rw-r--r--src/libs/installer/packagemanagergui.h14
-rw-r--r--src/libs/installer/packagemanagerproxyfactory.h2
-rw-r--r--src/libs/installer/performinstallationform.cpp12
-rw-r--r--src/libs/installer/performinstallationform.h2
-rw-r--r--src/libs/installer/productkeycheck.cpp31
-rw-r--r--src/libs/installer/productkeycheck.h14
-rw-r--r--src/libs/installer/progresscoordinator.cpp18
-rw-r--r--src/libs/installer/progresscoordinator.h6
-rw-r--r--src/libs/installer/qinstallerglobal.h23
-rw-r--r--src/libs/installer/qprocesswrapper.cpp40
-rw-r--r--src/libs/installer/qprocesswrapper.h2
-rw-r--r--src/libs/installer/qsettingswrapper.cpp30
-rw-r--r--src/libs/installer/qtpatch.cpp57
-rw-r--r--src/libs/installer/qtpatch.h1
-rw-r--r--src/libs/installer/qtpatchoperation.cpp186
-rw-r--r--src/libs/installer/qtpatchoperation.h2
-rw-r--r--src/libs/installer/registerqtincreatorqnxoperation.cpp (renamed from src/libs/installer/registerqtvqnxoperation.cpp)2
-rw-r--r--src/libs/installer/registerqtincreatorqnxoperation.h (renamed from src/libs/installer/registerqtvqnxoperation.h)6
-rw-r--r--src/libs/installer/resources/files-to-patch-linux-emb-arm1
-rw-r--r--src/libs/installer/resources/files-to-patch-windows-emb-arm1
-rw-r--r--src/libs/installer/scriptengine.cpp410
-rw-r--r--src/libs/installer/scriptengine.h88
-rw-r--r--src/libs/installer/settings.cpp160
-rw-r--r--src/libs/installer/settings.h12
-rw-r--r--src/libs/installer/sysinfo_win.cpp224
-rw-r--r--src/libs/installer/utils.cpp34
-rw-r--r--src/libs/installer/utils.h3
77 files changed, 3819 insertions, 1722 deletions
diff --git a/src/libs/installer/addqtcreatorarrayvalueoperation.h b/src/libs/installer/addqtcreatorarrayvalueoperation.h
index 6792b8e88..670dccff8 100644
--- a/src/libs/installer/addqtcreatorarrayvalueoperation.h
+++ b/src/libs/installer/addqtcreatorarrayvalueoperation.h
@@ -39,8 +39,8 @@
**
**************************************************************************/
-#ifndef ADDQTCREATORVALUEOPERATION_H
-#define ADDQTCREATORVALUEOPERATION_H
+#ifndef ADDQTCREATORARRAYVALUEOPERATION_H
+#define ADDQTCREATORARRAYVALUEOPERATION_H
#include "qinstallerglobal.h"
@@ -60,4 +60,4 @@ public:
} // namespace QInstaller
-#endif // ADDQTCREATORVALUEOPERATION_H
+#endif // ADDQTCREATORARRAYVALUEOPERATION_H
diff --git a/src/libs/installer/adminauthorization_win.cpp b/src/libs/installer/adminauthorization_win.cpp
index 20420cef0..03003b21a 100644
--- a/src/libs/installer/adminauthorization_win.cpp
+++ b/src/libs/installer/adminauthorization_win.cpp
@@ -49,6 +49,9 @@
# ifndef _WIN32_WINNT
# define _WIN32_WINNT 0x0501
# endif
+# ifndef SEE_MASK_NOASYNC
+# define SEE_MASK_NOASYNC 0x00000100
+# endif
#endif
#include <windows.h>
@@ -99,6 +102,31 @@ bool AdminAuthorization::hasAdminRights()
return isInAdminGroup;
}
+//copied from qsystemerror.cpp in Qt
+static QString windowsErrorString(int errorCode)
+{
+ QString ret;
+ wchar_t *string = 0;
+ FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL,
+ errorCode,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPWSTR)&string,
+ 0,
+ NULL);
+ ret = QString::fromWCharArray(string);
+ LocalFree((HLOCAL)string);
+
+ if (ret.isEmpty() && errorCode == ERROR_MOD_NOT_FOUND)
+ ret = QString::fromLatin1("The specified module could not be found.");
+
+ ret.append(QLatin1String(" (0x"));
+ ret.append(QString::number(uint(errorCode), 16).rightJustified(8, QLatin1Char('0')));
+ ret.append(QLatin1String(")"));
+
+ return ret;
+}
+
bool AdminAuthorization::execute(QWidget *, const QString &program, const QStringList &arguments)
{
DeCoInitializer _;
@@ -112,10 +140,16 @@ bool AdminAuthorization::execute(QWidget *, const QString &program, const QStrin
shellExecuteInfo.lpFile = (wchar_t *)file.utf16();
shellExecuteInfo.cbSize = sizeof(SHELLEXECUTEINFOW);
shellExecuteInfo.lpParameters = (wchar_t *)args.utf16();
+ shellExecuteInfo.fMask = SEE_MASK_NOASYNC;
qDebug() << QString::fromLatin1("Starting elevated process %1 with arguments: %2.").arg(file, args);
- ShellExecuteExW(&shellExecuteInfo);
- qDebug() << "Finished starting elevated process.";
- return GetLastError() == ERROR_SUCCESS;
+ if (ShellExecuteExW(&shellExecuteInfo)) {
+ qDebug() << "Finished starting elevated process.";
+ return true;
+ } else {
+ qWarning() << QString::fromLatin1("Error while starting elevated process: %1, "
+ "Error: %2").arg(program, windowsErrorString(GetLastError()));
+ }
+ return false;
}
diff --git a/src/libs/installer/adminauthorization_x11.cpp b/src/libs/installer/adminauthorization_x11.cpp
index 71a66cd83..6d5a52357 100644
--- a/src/libs/installer/adminauthorization_x11.cpp
+++ b/src/libs/installer/adminauthorization_x11.cpp
@@ -194,7 +194,7 @@ bool AdminAuthorization::execute(QWidget *parent, const QString &program, const
const QString line = QString::fromLatin1(buf, bytes);
if (re.indexIn(line) != -1) {
const QString password = getPassword(parent);
- if (password == QString()) {
+ if (password.isEmpty()) {
QByteArray pwd = password.toLatin1();
for (int i = 0; i < 3; ++i) {
::write(masterFD, pwd.data(), pwd.length());
diff --git a/src/libs/installer/binaryformat.cpp b/src/libs/installer/binaryformat.cpp
index 61429b019..1d257a1b4 100644
--- a/src/libs/installer/binaryformat.cpp
+++ b/src/libs/installer/binaryformat.cpp
@@ -256,18 +256,18 @@ qint64 QInstaller::findMagicCookie(QFile *in, quint64 magicCookie)
pre-zipped and gets delivered as it is. If it's a directory, it gets zipped by Archive.
*/
Archive::Archive(const QString &path)
- : m_device(0),
- m_isTempFile(false),
- m_path(path),
- m_name(QFileInfo(path).fileName().toUtf8())
+ : m_device(0)
+ , m_isTempFile(false)
+ , m_path(path)
+ , m_name(QFileInfo(path).fileName().toUtf8())
{
}
Archive::Archive(const QByteArray &identifier, const QByteArray &data)
- : m_device(0),
- m_isTempFile(true),
- m_path(generateTemporaryFileName()),
- m_name(identifier)
+ : m_device(0)
+ , m_isTempFile(true)
+ , m_path(generateTemporaryFileName())
+ , m_name(identifier)
{
QFile file(m_path);
file.open(QIODevice::WriteOnly);
@@ -278,10 +278,10 @@ Archive::Archive(const QByteArray &identifier, const QByteArray &data)
Creates an archive identified by \a identifier providing a data \a segment within a \a device.
*/
Archive::Archive(const QByteArray &identifier, const QSharedPointer<QFile> &device, const Range<qint64> &segment)
- : m_device(device),
- m_segment(segment),
- m_isTempFile(false),
- m_name(identifier)
+ : m_device(device)
+ , m_segment(segment)
+ , m_isTempFile(false)
+ , m_name(identifier)
{
}
diff --git a/src/libs/installer/binaryformat.h b/src/libs/installer/binaryformat.h
index 49be60a06..d255ea8a9 100644
--- a/src/libs/installer/binaryformat.h
+++ b/src/libs/installer/binaryformat.h
@@ -203,7 +203,7 @@ class INSTALLER_EXPORT BinaryContentPrivate : public QSharedData
{
public:
BinaryContentPrivate();
- BinaryContentPrivate(const QString &path);
+ explicit BinaryContentPrivate(const QString &path);
BinaryContentPrivate(const BinaryContentPrivate &other);
~BinaryContentPrivate();
diff --git a/src/libs/installer/binaryformatengine.cpp b/src/libs/installer/binaryformatengine.cpp
index e2fd00b82..416e8ca56 100644
--- a/src/libs/installer/binaryformatengine.cpp
+++ b/src/libs/installer/binaryformatengine.cpp
@@ -49,9 +49,9 @@ class StringListIterator : public QAbstractFileEngineIterator
{
public:
StringListIterator( const QStringList &list, QDir::Filters filters, const QStringList &nameFilters)
- : QAbstractFileEngineIterator(filters, nameFilters),
- list(list),
- index(-1)
+ : QAbstractFileEngineIterator(filters, nameFilters)
+ , list(list)
+ , index(-1)
{
}
diff --git a/src/libs/installer/binaryformatenginehandler.cpp b/src/libs/installer/binaryformatenginehandler.cpp
index e6bf7864f..d872ed229 100644
--- a/src/libs/installer/binaryformatenginehandler.cpp
+++ b/src/libs/installer/binaryformatenginehandler.cpp
@@ -69,8 +69,8 @@ BinaryFormatEngineHandler::BinaryFormatEngineHandler(const ComponentIndex &index
}
BinaryFormatEngineHandler::BinaryFormatEngineHandler(const BinaryFormatEngineHandler &other)
- : QAbstractFileEngineHandler(),
- d(new Private(other.d->index))
+ : QAbstractFileEngineHandler()
+ , d(new Private(other.d->index))
{
s_instance = this;
}
diff --git a/src/libs/installer/component.cpp b/src/libs/installer/component.cpp
index f9e809565..ed815d18a 100644
--- a/src/libs/installer/component.cpp
+++ b/src/libs/installer/component.cpp
@@ -39,14 +39,16 @@
**
**************************************************************************/
#include "component.h"
+#include "scriptengine.h"
#include "errors.h"
#include "fileutils.h"
#include "fsengineclient.h"
+#include "globals.h"
#include "lib7z_facade.h"
-#include "packagemanagercore.h"
-#include "qinstallerglobal.h"
#include "messageboxhandler.h"
+#include "packagemanagercore.h"
+#include "settings.h"
#include <kdupdaterupdatesourcesinfo.h>
#include <kdupdaterupdateoperationfactory.h>
@@ -75,11 +77,132 @@ static const QLatin1String scCurrentState("CurrentState");
static const QLatin1String scForcedInstallation("ForcedInstallation");
/*!
- \class QInstaller::Component
- Component describes a component within the installer.
+ \qmltype Component
+ \inqmlmodule scripting
+
+ \brief Represents an installer component in Qt Script.
+
+ The object represents the component an install script belongs to. It is accessible through the
+ global \c component variable:
+
+ \code
+ function Component()
+ {
+ print("component: " + component.displayName);
+ }
+ \endcode
+*/
+
+/*!
+ \qmlproperty string Component::name
+
+ Returns the name of the component as set in the \c <Name> tag of the package
+ information file.
+*/
+
+/*!
+ \qmlproperty string Component::displayName
+
+ Returns the name of the component as shown in the user interface.
+*/
+
+/*!
+ \qmlproperty boolean Component::selected
+
+ Indicates whether the component is currently selected.
+*/
+
+/*!
+ \qmlproperty boolean Component::autoCreateOperations
+
+ Specifies whether some standard operations for the component should be
+ automatically created when the installation starts. The default is \c true.
+*/
+
+/*!
+ \qmlproperty stringlist Component::archives
+
+ Returns the list of archive URL's (prefixed with \c installer://) registered
+ for the component.
+
+ \sa addDownloadableArchive, removeDownloadableArchive
+*/
+
+/*!
+ \qmlproperty stringlist Component::dependencies
+
+ This read-only property contains components this component depends on.
+*/
+
+/*!
+ \qmlproperty stringlist Component::autoDependencies
+
+ Returns the value of the \c <AutoDependsOn> tag in the package information file.
+*/
+
+/*!
+ \qmlproperty boolean Component::fromOnlineRepository
+
+ Returns whether this component has been loaded from an online repository.
+
+ \sa isFromOnlineRepository
+*/
+
+/*!
+ \qmlproperty url Component::repositoryUrl
+
+ Returns the repository URL the component is downloaded from.
+ When this component is not downloaded from an online repository, returns an empty #QUrl.
+
+*/
+
+/*!
+ \qmlproperty boolean Component::default
+
+ This read-only property indicates if the component is a default one.
+
+ \note Always \c false for virtual components.
+
+ \sa isDefault
*/
/*!
+ \qmlproperty boolean Component::installed
+
+ This read-only property returns if the component is installed.
+
+ \sa isInstalled
+*/
+
+/*!
+ \qmlproperty boolean Component::enabled
+
+ Indicates whether the component is currently enabled. The property is both readable and writable.
+*/
+
+/*!
+ \qmlsignal Component::loaded()
+
+ Emitted when the component has been loaded.
+*/
+
+
+/*!
+ \qmlsignal Component::selectedChanged(boolean isSelected)
+
+ Emitted when the component selection has changed to \a isSelected.
+*/
+
+/*!
+ \qmlsignal Component::valueChanged(string key, string value)
+
+ Emitted when the variable with name \a key has changed to \a value.
+
+ \sa setValue
+*/
+
+
+/*!
Constructor. Creates a new Component inside of \a installer.
*/
Component::Component(PackageManagerCore *core)
@@ -146,15 +269,14 @@ void Component::loadDataFromPackage(const LocalPackage &package)
void Component::loadDataFromPackage(const Package &package)
{
Q_ASSERT(&package);
- Q_ASSERT(!package.name().isEmpty());
setValue(scName, package.data(scName).toString());
setValue(scDisplayName, package.data(scDisplayName).toString());
setValue(scDescription, package.data(scDescription).toString());
setValue(scDefault, package.data(scDefault).toString());
setValue(scAutoDependOn, package.data(scAutoDependOn).toString());
- setValue(scCompressedSize, QString::number(package.compressedSize()));
- setValue(scUncompressedSize, QString::number(package.uncompressedSize()));
+ 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());
@@ -181,14 +303,14 @@ void Component::loadDataFromPackage(const Package &package)
setCheckState(Qt::Checked);
}
- setLocalTempPath(QInstaller::pathFromUrl(package.sourceInfo().url));
- const QStringList uis = package.data(QLatin1String("UserInterfaces")).toString().split(scCommaRegExp,
- QString::SkipEmptyParts);
+ setLocalTempPath(QInstaller::pathFromUrl(package.sourceInfoUrl()));
+ const QStringList uis = package.data(QLatin1String("UserInterfaces")).toString()
+ .split(QInstaller::commaRegExp(), QString::SkipEmptyParts);
if (!uis.isEmpty())
loadUserInterfaces(QDir(QString::fromLatin1("%1/%2").arg(localTempPath(), name())), uis);
- const QStringList qms = package.data(QLatin1String("Translations")).toString().split(scCommaRegExp,
- QString::SkipEmptyParts);
+ const QStringList qms = package.data(QLatin1String("Translations")).toString()
+ .split(QInstaller::commaRegExp(), QString::SkipEmptyParts);
if (!qms.isEmpty())
loadTranslations(QDir(QString::fromLatin1("%1/%2").arg(localTempPath(), name())), qms);
@@ -227,9 +349,11 @@ QHash<QString,QString> Component::variables() const
}
/*!
+ \qmlmethod string Component::value(string key, string value = "")
+
Returns the value of variable name \a key. If \a key is not known yet, \a defaultValue is returned.
Note: If a component is virtual and you ask for the component value with key "Default", it will always
- return false.
+ return \c false.
*/
QString Component::value(const QString &key, const QString &defaultValue) const
{
@@ -239,6 +363,8 @@ QString Component::value(const QString &key, const QString &defaultValue) const
}
/*!
+ \qmlmethod void Component::setValue(string key, string value)
+
Sets the value of the variable with \a key to \a value.
*/
void Component::setValue(const QString &key, const QString &value)
@@ -264,8 +390,8 @@ PackageManagerCore *Component::packageManagerCore() const
}
/*!
- Returns the parent of this component. If this component is com.nokia.sdk.qt, its
- parent is com.nokia.sdk, as far as this exists.
+ Returns the parent of this component. If this component is org.qt-project.sdk.qt, its
+ parent is org.qt-project.sdk, as far as this exists.
*/
Component *Component::parentComponent() const
{
@@ -308,23 +434,22 @@ void Component::removeComponent(Component *component)
}
/*!
- Returns a list of child components. If \a recursive is set to true, the returned list
- contains not only the direct children, but all ancestors. Note: The returned list does include ALL
- children, non virtual components as well as virtual components.
+ Returns a list of child components. If \a kind is set to DirectChildrenOnly, the returned list contains
+ only the direct children, if set to Descendants it will also include all descendants of the components
+ children. Note: The returned list does include ALL children, non virtual components as well as virtual
+ components.
*/
-QList<Component*> Component::childComponents(bool recursive, RunMode runMode) const
+QList<Component *> Component::childComponents(Kind kind) const
{
- QList<Component*> result;
- if (runMode == UpdaterMode)
- return result;
+ if (d->m_core->isUpdater())
+ return QList<Component*>();
- if (!recursive)
- return d->m_allChildComponents;
+ QList<Component *> result = d->m_allChildComponents;
+ if (kind == DirectChildrenOnly)
+ return result;
- foreach (Component *component, d->m_allChildComponents) {
- result.append(component);
- result += component->childComponents(true, runMode);
- }
+ foreach (Component *component, d->m_allChildComponents)
+ result += component->childComponents(kind);
return result;
}
@@ -352,50 +477,25 @@ void Component::loadComponentScript()
}
/*!
- Loads the script at \a fileName into this component's script engine. The installer and all its
+ Loads the script at \a fileName into ScriptEngine. The installer and all its
components as well as other useful stuff are being exported into the script.
Read \link componentscripting Component Scripting \endlink for details.
- \throws Error when either the script at \a fileName couldn't be opened, or the QScriptEngine
+ Throws an error when either the script at \a fileName couldn't be opened, or the QScriptEngine
couldn't evaluate the script.
*/
void Component::loadComponentScript(const QString &fileName)
{
- QFile file(fileName);
- if (!file.open(QIODevice::ReadOnly)) {
- throw Error(tr("Could not open the requested script file at %1: %2.").arg(fileName, file.errorString()));
- }
+ ScriptEngine *scriptEngine = d->m_core->scriptEngine();
- d->scriptEngine()->evaluate(QLatin1String(file.readAll()), fileName);
- if (d->scriptEngine()->hasUncaughtException()) {
- throw Error(tr("Exception while loading the component script: %1")
- .arg(uncaughtExceptionString(d->scriptEngine()/*, QFileInfo(file).absoluteFilePath()*/)));
- }
-
- const QList<Component*> components = d->m_core->availableComponents();
- QScriptValue comps = d->scriptEngine()->newArray(components.count());
- for (int i = 0; i < components.count(); ++i)
- comps.setProperty(i, d->scriptEngine()->newQObject(components[i]));
-
- d->scriptEngine()->globalObject().property(QLatin1String("installer"))
- .setProperty(QLatin1String("components"), comps);
+ // introduce the component object as javascript value and call the name to check that it
+ // was successful
+ QString scriptInjection(QString::fromLatin1(
+ "var component = installer.componentByName('%1'); component.name;").arg(name()));
- QScriptValue comp = d->scriptEngine()->evaluate(QLatin1String("Component"), fileName);
- if (!d->scriptEngine()->hasUncaughtException()) {
- d->m_scriptComponent = comp;
- d->m_scriptComponent.construct();
- }
-
- //evaluate("Component") and construct can have an exception
- if (d->scriptEngine()->hasUncaughtException()) {
- throw Error(tr("Exception while loading the component script: %1")
- .arg(uncaughtExceptionString(d->scriptEngine(), QFileInfo(file).absoluteFilePath())));
- }
+ d->m_scriptContext = scriptEngine->loadInConext(QLatin1String("Component"), fileName, scriptInjection);
emit loaded();
languageChanged();
-
- //Solves a freeze seen on updater/ package manger restart.
- QCoreApplication::processEvents();
}
/*!
@@ -405,58 +505,38 @@ void Component::loadComponentScript(const QString &fileName)
*/
void Component::languageChanged()
{
- callScriptMethod(QLatin1String("retranslateUi"));
-}
-
-/*!
- Tries to call the method with \a name within the script and returns the result. If the method
- doesn't exist, an invalid result is returned. If the method has an uncaught exception, its
- string representation is thrown as an Error exception.
-
- \note The method is not called, if the current script context is the same method, to avoid
- infinite recursion.
-*/
-QScriptValue Component::callScriptMethod(const QString &methodName, const QScriptValueList &arguments) const
-{
- if (!d->m_unexistingScriptMethods.value(methodName, true))
- return QScriptValue();
-
- // don't allow such a recursion
- if (d->scriptEngine()->currentContext()->backtrace().first().startsWith(methodName))
- return QScriptValue();
-
- QScriptValue method = d->m_scriptComponent.property(QString::fromLatin1("prototype"))
- .property(methodName);
- if (!method.isValid()) // this marks the method to be called not any longer
- d->m_unexistingScriptMethods[methodName] = false;
-
- const QScriptValue result = method.call(d->m_scriptComponent, arguments);
- if (!result.isValid())
- return result;
-
- if (d->scriptEngine()->hasUncaughtException())
- throw Error(uncaughtExceptionString(d->scriptEngine()/*, name()*/));
-
- return result;
+ d->m_core->scriptEngine()->callScriptMethod(d->m_scriptContext, QLatin1String("retranslateUi"));
}
/*!
Loads the translations matching the name filters \a qms inside \a directory. Only translations
with a \link QFileInfo::baseName() baseName \endlink matching the current locales \link
QLocale::name() name \endlink are loaded.
- Read \ref componenttranslation for details.
+ Read \l componenttranslation for details.
*/
void Component::loadTranslations(const QDir &directory, const QStringList &qms)
{
QDirIterator it(directory.path(), qms, QDir::Files);
+ const QStringList translations = d->m_core->settings().translations();
+ const QString uiLanguage = QLocale().uiLanguages().value(0, QLatin1String("en_us"))
+ .replace(QLatin1Char('-'), QLatin1Char('_'));
while (it.hasNext()) {
const QString filename = it.next();
- if (QFileInfo(filename).baseName().toLower() != QLocale().name().toLower())
- continue;
+ const QString basename = QFileInfo(filename).baseName();
+ if (!uiLanguage.startsWith(QFileInfo(filename).baseName(), Qt::CaseInsensitive))
+ continue; // do not load the file if it does not match the UI language
+
+ if (!translations.isEmpty()) {
+ bool found = false;
+ foreach (const QString &translation, translations)
+ found |= translation.startsWith(basename, Qt::CaseInsensitive);
+ if (!found) // don't load the file if it does match the UI language but is not allowed to be used
+ continue;
+ }
QScopedPointer<QTranslator> translator(new QTranslator(this));
if (!translator->load(filename))
- throw Error(tr("Could not open the requested translation file at %1").arg(filename));
+ throw Error(tr("Could not open the requested translation file '%1'.").arg(filename));
qApp->installTranslator(translator.take());
}
}
@@ -464,7 +544,7 @@ void Component::loadTranslations(const QDir &directory, const QStringList &qms)
/*!
Loads the user interface files matching the name filters \a uis inside \a directory. The loaded
interface can be accessed via userInterfaces by using the class name set in the ui file.
- Read \ref componentuserinterfaces for details.
+ Read \l componentuserinterfaces for details.
*/
void Component::loadUserInterfaces(const QDir &directory, const QStringList &uis)
{
@@ -480,15 +560,23 @@ void Component::loadUserInterfaces(const QDir &directory, const QStringList &uis
while (it.hasNext()) {
QFile file(it.next());
if (!file.open(QIODevice::ReadOnly)) {
- throw Error(tr("Could not open the requested UI file at %1: %2").arg(it.fileName(),
+ throw Error(tr("Could not open the requested UI file '%1'. Error: %2").arg(it.fileName(),
file.errorString()));
}
static QUiLoader loader;
loader.setTranslationEnabled(true);
loader.setLanguageChangeEnabled(true);
- QWidget *const w = loader.load(&file, MessageBoxHandler::currentBestSuitParent());
- d->m_userInterfaces.insert(w->objectName(), w);
+ QWidget *const widget = loader.load(&file, 0);
+ if (!widget) {
+ throw Error(tr("Could not load the requested UI file '%1'. Error: %2").arg(it.fileName(),
+#if QT_VERSION < 0x050000
+ tr("An error has occurred while reading the UI file.")));
+#else
+ loader.errorString()));
+#endif
+ }
+ d->m_userInterfaces.insert(widget->objectName(), widget);
}
}
@@ -502,7 +590,7 @@ void Component::loadLicenses(const QString &directory, const QHash<QString, QVar
for (it = licenseHash.begin(); it != licenseHash.end(); ++it) {
const QString &fileName = it.value().toString();
- if (!ProductKeyCheck::instance()->isValidLicense(fileName))
+ if (!ProductKeyCheck::instance(d->m_core)->isValidLicenseTextFile(fileName))
continue;
QFileInfo fileInfo(fileName);
@@ -513,7 +601,7 @@ void Component::loadLicenses(const QString &directory, const QHash<QString, QVar
qDebug("Unable to open translated license file. Using untranslated fallback.");
file.setFileName(directory + fileName);
if (!file.open(QIODevice::ReadOnly)) {
- throw Error(tr("Could not open the requested license file at %1: %2").arg(fileName,
+ throw Error(tr("Could not open the requested license file '%1'. Error: %2").arg(fileName,
file.errorString()));
}
}
@@ -523,8 +611,11 @@ void Component::loadLicenses(const QString &directory, const QHash<QString, QVar
}
}
+
/*!
- Contains a list of all user interface class names known to this component.
+ \qmlproperty stringlist Component::userInterfaces
+
+ Returns a list of all user interface class names known to this component.
*/
QStringList Component::userInterfaces() const
{
@@ -537,6 +628,8 @@ QHash<QString, QPair<QString, QString> > Component::licenses() const
}
/*!
+ \qmlmethod QWidget Component::userInterface(string name)
+
Returns the QWidget created for \a name or 0 if the widget already has been deleted or cannot be found.
*/
QWidget *Component::userInterface(const QString &name) const
@@ -545,9 +638,11 @@ QWidget *Component::userInterface(const QString &name) const
}
/*!
+ \qmlmethod void Component::createOperationsForPath(string path)
+
Creates all operations needed to install this component's \a path. \a path is a full qualified
- filename including the component's name. This methods gets called from
- Component::createOperationsForArchive. You can override this method by providing a method with
+ filename including the component's name. This method gets called from
+ Component::createOperationsForArchive. You can override it by providing a method with
the same name in the component script.
\note RSA signature files are omitted by this method.
@@ -565,8 +660,10 @@ void Component::createOperationsForPath(const QString &path)
return;
// the script can override this method
- if (callScriptMethod(QLatin1String("createOperationsForPath"), QScriptValueList() << path).isValid())
+ if (d->m_core->scriptEngine()->callScriptMethod(d->m_scriptContext,
+ QLatin1String("createOperationsForPath"), QScriptValueList() << path).isValid()) {
return;
+ }
QString target;
static const QString prefix = QString::fromLatin1("installer://");
@@ -587,6 +684,8 @@ void Component::createOperationsForPath(const QString &path)
}
/*!
+ \qmlmethod void Component::createOperationsForArchive(string archive)
+
Creates all operations needed to install this component's \a archive. This method gets called
from Component::createOperations. You can override this method by providing a method with the
same name in the component script.
@@ -606,8 +705,10 @@ void Component::createOperationsForArchive(const QString &archive)
return;
// the script can override this method
- if (callScriptMethod(QLatin1String("createOperationsForArchive"), QScriptValueList() << archive).isValid())
+ if (d->m_core->scriptEngine()->callScriptMethod(d->m_scriptContext,
+ QLatin1String("createOperationsForArchive"), QScriptValueList() << archive).isValid()) {
return;
+ }
const bool isZip = Lib7z::isSupportedArchive(archive);
@@ -619,15 +720,34 @@ void Component::createOperationsForArchive(const QString &archive)
}
}
+/*!
+ \qmlmethod void Component::beginInstallation()
+
+ Starts the component installation.
+ You can override this method by providing a method with the same name in the component script.
+
+ \code
+ Component.prototype.beginInstallation = function()
+ {
+ // call default implementation
+ component.beginInstallation();
+ // ...
+ }
+ \endcode
+
+*/
void Component::beginInstallation()
{
// the script can override this method
- if (callScriptMethod(QLatin1String("beginInstallation")).isValid()) {
+ if (d->m_core->scriptEngine()->callScriptMethod(d->m_scriptContext,
+ QLatin1String("beginInstallation")).isValid()) {
return;
}
}
/*!
+ \qmlmethod void Component::createOperations()
+
Creates all operations needed to install this component.
You can override this method by providing a method with the same name in the component script.
@@ -638,7 +758,8 @@ void Component::beginInstallation()
void Component::createOperations()
{
// the script can override this method
- if (callScriptMethod(QLatin1String("createOperations")).isValid()) {
+ if (d->m_core->scriptEngine()->callScriptMethod(d->m_scriptContext,
+ QLatin1String("createOperations")).isValid()) {
d->m_operationsCreated = true;
return;
}
@@ -650,8 +771,10 @@ void Component::createOperations()
}
/*!
+ \qmlmethod void Component::registerPathForUninstallation(string path, boolean wipe = false)
+
Registers the file or directory at \a path for being removed when this component gets uninstalled.
- In case of a directory, this will be recursive. If \a wipe is set to true, the directory will
+ In case of a directory, this will be recursive. If \a wipe is set to \c true, the directory will
also be deleted if it contains changes done by the user after installation.
*/
void Component::registerPathForUninstallation(const QString &path, bool wipe)
@@ -660,6 +783,8 @@ void Component::registerPathForUninstallation(const QString &path, bool wipe)
}
/*!
+ \qmlmethod QList<QPair<string, boolean> > Component::pathesForUninstallation()
+
Returns the list of paths previously registered for uninstallation with
#registerPathForUninstallation.
*/
@@ -682,11 +807,13 @@ QStringList Component::archives() const
}
/*!
+ \qmlmethod void Component::addDownloadableArchive(string path)
+
Adds the archive \a path to this component. This can only be called when this component was
downloaded from an online repository. When adding \a path, it will be downloaded from the
repository when the installation starts.
- Read \ref sec_repogen for details. \sa fromOnlineRepository
+ \sa removeDownloadableArchive, fromOnlineRepository, archives
*/
void Component::addDownloadableArchive(const QString &path)
{
@@ -697,10 +824,12 @@ void Component::addDownloadableArchive(const QString &path)
}
/*!
+ \qmlmethod void Component::removeDownloadableArchive(string path)
+
Removes the archive \a path previously added via addDownloadableArchive from this component.
This can only be called when this component was downloaded from an online repository.
- Read \ref sec_repogen for details.
+ \sa addDownloadableArchive, fromOnlineRepository, archives
*/
void Component::removeDownloadableArchive(const QString &path)
{
@@ -717,7 +846,9 @@ QStringList Component::downloadableArchives() const
}
/*!
- Adds a request for quitting the process @p process before installing/updating/uninstalling the
+ \qmlmethod void Component::addStopProcessForUpdateRequest(string process)
+
+ Adds a request for quitting the process \a process before installing/updating/uninstalling the
component.
*/
void Component::addStopProcessForUpdateRequest(const QString &process)
@@ -726,7 +857,9 @@ void Component::addStopProcessForUpdateRequest(const QString &process)
}
/*!
- Removes the request for quitting the process @p process again.
+ \qmlmethod void Component::removeStopProcessForUpdateRequest(string process)
+
+ Removes the request for quitting the process \a process again.
*/
void Component::removeStopProcessForUpdateRequest(const QString &process)
{
@@ -734,7 +867,9 @@ void Component::removeStopProcessForUpdateRequest(const QString &process)
}
/*!
- Convenience: Add/remove request depending on @p requested (add if @p true, remove if @p false).
+ \qmlmethod void Component::setStopProcessForUpdateRequest(string process, boolean requested)
+
+ Convenience: Add/remove request depending on \a requested (add if \c true, remove if \c false).
*/
void Component::setStopProcessForUpdateRequest(const QString &process, bool requested)
{
@@ -753,7 +888,7 @@ QStringList Component::stopProcessForUpdateRequests() const
}
/*!
- Returns the operations needed to install this component. If autoCreateOperations is true,
+ Returns the operations needed to install this component. If autoCreateOperations is \c true,
createOperations is called, if no operations have been auto-created yet.
*/
OperationList Component::operations() const
@@ -812,7 +947,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)
@@ -839,36 +974,35 @@ 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));
-
- op->setArguments(d->m_core->replaceVariables(parameters));
+ if (operation->name() == QLatin1String("Delete"))
+ operation->setValue(QLatin1String("performUndo"), false);
+ operation->setValue(QLatin1String("installer"), qVariantFromValue(d->m_core));
- return op;
+ operation->setArguments(d->m_core->replaceVariables(parameters));
+ operation->setValue(QLatin1String("component"), name());
+ return operation;
}
/*!
- Creates and adds an installation operation for \a operation. Add any number of \a parameter1,
- \a parameter2, \a parameter3, \a parameter4, \a parameter5 and \a parameter6. The contents of
- the parameters get variables like "@TargetDir@" replaced with their values, if contained.
- \sa installeroperations
+ \qmlmethod boolean Component::addOperation(string operation, string parameter1 = "", string parameter2 = "", ..., string parameter10 = "")
+
+ Convenience method for calling addOperation(string, stringlist) with up to 10 arguments.
*/
bool Component::addOperation(const QString &operation, const QString &parameter1, const QString &parameter2,
const QString &parameter3, const QString &parameter4, const QString &parameter5, const QString &parameter6,
@@ -883,6 +1017,13 @@ bool Component::addOperation(const QString &operation, const QString &parameter1
return false;
}
+/*!
+ \qmlmethod boolean Component::addOperation(string operation, stringlist parameters)
+
+ Creates and adds an installation operation for \a operation. Add any number of parameters.
+ The contents of the parameters get variables like "@TargetDir@" replaced with their values,
+ if contained.
+*/
bool Component::addOperation(const QString &operation, const QStringList &parameters)
{
if (Operation *op = createOperation(operation, parameters)) {
@@ -894,11 +1035,9 @@ bool Component::addOperation(const QString &operation, const QStringList &parame
}
/*!
- Creates and adds an installation operation for \a operation. Add any number of \a parameter1,
- \a parameter2, \a parameter3, \a parameter4, \a parameter5 and \a parameter6. The contents of
- the parameters get variables like "@TargetDir@" replaced with their values, if contained.
- \a operation is executed with elevated rights.
- \sa installeroperations
+ \qmlmethod boolean Component::addElevatedOperation(string operation, string parameter1 = "", string parameter2 = "", ..., string parameter10 = "")
+
+ Convenience method for calling addElevatedOperation(string, stringlist) with up to 10 arguments.
*/
bool Component::addElevatedOperation(const QString &operation, const QString &parameter1,
const QString &parameter2, const QString &parameter3, const QString &parameter4, const QString &parameter5,
@@ -914,6 +1053,14 @@ bool Component::addElevatedOperation(const QString &operation, const QString &pa
return false;
}
+/*!
+ \qmlmethod boolean Component::addElevatedOperation(string operation, stringlist parameters)
+
+ Creates and adds an installation operation for \a operation. Add any number of parameters.
+ The contents of the parameters get variables like "@TargetDir@" replaced with their values,
+ if contained. \a operation is executed with elevated rights.
+
+*/
bool Component::addElevatedOperation(const QString &operation, const QStringList &parameters)
{
if (Operation *op = createOperation(operation, parameters)) {
@@ -926,7 +1073,7 @@ bool Component::addElevatedOperation(const QString &operation, const QStringList
/*!
Specifies whether operations should be automatically created when the installation starts. This
- would be done by calling #createOperations. If you set this to false, it's completely up to the
+ would be done by calling #createOperations. If you set this to \c false, it is completely up to the
component's script to create all operations.
*/
bool Component::autoCreateOperations() const
@@ -934,6 +1081,11 @@ bool Component::autoCreateOperations() const
return d->m_autoCreateOperations;
}
+/*!
+ \qmlmethod void Component::setAutoCreateOperations(boolean autoCreateOperations)
+
+ Setter for the \l autoCreateOperations property.
+ */
void Component::setAutoCreateOperations(bool autoCreateOperations)
{
d->m_autoCreateOperations = autoCreateOperations;
@@ -945,9 +1097,7 @@ bool Component::isVirtual() const
}
/*!
- \property Component::selected
- Specifies whether this component is selected for installation. Get this property's value by using
- %isSelected(), and set it using %setSelected().
+ Specifies whether this component is selected for installation.
*/
bool Component::isSelected() const
{
@@ -967,19 +1117,31 @@ void Component::setValidatorCallbackName(const QString &name)
bool Component::validatePage()
{
if (!validatorCallbackName.isEmpty())
- return callScriptMethod(validatorCallbackName).toBool();
+ return d->m_core->scriptEngine()->callScriptMethod(d->m_scriptContext, validatorCallbackName).toBool();
return true;
}
/*!
+ \qmlmethod void Component::setSelected(boolean selected)
+
Marks the component for installation. Emits the selectedChanged() signal if the check state changes.
+
+ \note This method does not do anything and is deprecated since 1.3.
*/
void Component::setSelected(bool selected)
{
Q_UNUSED(selected)
- qDebug() << Q_FUNC_INFO << QString::fromLatin1("on \"%1\" is deprecated!!!").arg(d->m_componentName);
+ qDebug() << Q_FUNC_INFO << QString::fromLatin1("on '%1' is deprecated.").arg(d->m_componentName);
}
+/*!
+ \qmlmethod void Component::addDependency(string newDependency)
+
+ Adds a new component \a newDependency to the list of dependencies.
+
+ \sa dependencies
+*/
+
void Component::addDependency(const QString &newDependency)
{
QString oldDependencies = d->m_vars.value(scDependencies);
@@ -992,22 +1154,24 @@ void Component::addDependency(const QString &newDependency)
/*!
Contains this component dependencies.
- Read \ref componentdependencies for details.
+ Read \l componentdependencies for details.
*/
QStringList Component::dependencies() const
{
- return d->m_vars.value(scDependencies).split(scCommaRegExp, QString::SkipEmptyParts);
+ return d->m_vars.value(scDependencies).split(QInstaller::commaRegExp(), QString::SkipEmptyParts);
}
QStringList Component::autoDependencies() const
{
QStringList autoDependencyStringList =
- d->m_vars.value(scAutoDependOn).split(scCommaRegExp, QString::SkipEmptyParts);
+ d->m_vars.value(scAutoDependOn).split(QInstaller::commaRegExp(), QString::SkipEmptyParts);
autoDependencyStringList.removeAll(QLatin1String("script"));
return autoDependencyStringList;
}
/*!
+ \qmlmethod void Component::setInstalled()
+
Set's the components state to installed.
*/
void Component::setInstalled()
@@ -1016,8 +1180,10 @@ void Component::setInstalled()
}
/*!
- Determines if the component comes as an auto dependency. Returns true if the component needs to be
- installed.
+ \qmlmethod boolean Component::isAutoDependOn(QSet<string> componentsToInstall)
+
+ Determines if the component comes as an auto dependency. Returns \c true if the component needs
+ to be installed.
*/
bool Component::isAutoDependOn(const QSet<QString> &componentsToInstall) const
{
@@ -1031,7 +1197,8 @@ bool Component::isAutoDependOn(const QSet<QString> &componentsToInstall) const
if (autoDependOnList.first().compare(QLatin1String("script"), Qt::CaseInsensitive) == 0) {
QScriptValue valueFromScript;
try {
- valueFromScript = callScriptMethod(QLatin1String("isAutoDependOn"));
+ valueFromScript = d->m_core->scriptEngine()->callScriptMethod(d->m_scriptContext,
+ QLatin1String("isAutoDependOn"));
} catch (const Error &error) {
MessageBoxHandler::critical(MessageBoxHandler::currentBestSuitParent(),
QLatin1String("isAutoDependOnError"), tr("Can't resolve isAutoDependOn in %1"
@@ -1063,8 +1230,13 @@ bool Component::isAutoDependOn(const QSet<QString> &componentsToInstall) const
}
/*!
- Determines if the component is a default one. Note: if a component is virtual, this function will always
- return false.
+ \qmlmethod boolean Component::isDefault()
+
+ Indicates if the component is a default one.
+
+ \note Always returns \c false for virtual components.
+
+ \sa default
*/
bool Component::isDefault() const
{
@@ -1075,7 +1247,8 @@ bool Component::isDefault() const
if (d->m_vars.value(scDefault).compare(QLatin1String("script"), Qt::CaseInsensitive) == 0) {
QScriptValue valueFromScript;
try {
- valueFromScript = callScriptMethod(QLatin1String("isDefault"));
+ valueFromScript = d->m_core->scriptEngine()->callScriptMethod(d->m_scriptContext,
+ QLatin1String("isDefault"));
} catch (const Error &error) {
MessageBoxHandler::critical(MessageBoxHandler::currentBestSuitParent(),
QLatin1String("isDefaultError"), tr("Can't resolve isDefault in %1").arg(name()),
@@ -1092,6 +1265,8 @@ bool Component::isDefault() const
}
/*!
+ \qmlmethod boolean Component::isInstalled()
+
Determines if the component is installed.
*/
bool Component::isInstalled() const
@@ -1100,6 +1275,8 @@ bool Component::isInstalled() const
}
/*!
+ \qmlmethod boolean Component::installationRequested()
+
Determines if the user wants to install the component
*/
bool Component::installationRequested() const
@@ -1108,6 +1285,8 @@ bool Component::installationRequested() const
}
/*!
+ \qmlmethod void Component::setUpdateAvailable(boolean isUpdateAvailable)
+
Sets a flag that the core found an update
*/
void Component::setUpdateAvailable(bool isUpdateAvailable)
@@ -1116,6 +1295,8 @@ void Component::setUpdateAvailable(bool isUpdateAvailable)
}
/*!
+ \qmlmethod boolean Component::updateRequested()
+
Determines if the user wants to install the update for this component
*/
bool Component::updateRequested()
@@ -1124,7 +1305,9 @@ bool Component::updateRequested()
}
/*!
- Returns true if that component will be changed (update/installation/uninstallation)
+ \qmlmethod boolean Component::componentChangeRequested()
+
+ Returns \c true if that component will be changed (update/installation/uninstallation).
*/
bool Component::componentChangeRequested()
{
@@ -1133,6 +1316,8 @@ bool Component::componentChangeRequested()
/*!
+ \qmlmethod void Component::setUninstalled()
+
Sets the component state to uninstalled.
*/
void Component::setUninstalled()
@@ -1141,6 +1326,8 @@ void Component::setUninstalled()
}
/*!
+ \qmlmethod boolean Component::isUninstalled()
+
Determines if the component is uninstalled.
*/
bool Component::isUninstalled() const
@@ -1149,6 +1336,8 @@ bool Component::isUninstalled() const
}
/*!
+ \qmlmethod boolean Component::uninstallationRequested()
+
Determines if the user wants to uninstall the component.
*/
bool Component::uninstallationRequested() const
@@ -1159,10 +1348,11 @@ bool Component::uninstallationRequested() const
}
/*!
- \property Component::fromOnlineRepository
+ \qmlmethod boolean Component::isFromOnlineRepository()
- Determines whether this component has been loaded from an online repository. Get this property's
- value by using %isFromOnlineRepository. \sa addDownloadableArchive
+ Determines whether this component has been loaded from an online repository.
+
+ \sa addDownloadableArchive, fromOnlineRepository
*/
bool Component::isFromOnlineRepository() const
{
@@ -1213,6 +1403,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 1c8712145..eefe41ebb 100644
--- a/src/libs/installer/component.h
+++ b/src/libs/installer/component.h
@@ -85,6 +85,12 @@ class INSTALLER_EXPORT Component : public QObject, public QScriptable, public Co
Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled)
public:
+ enum Kind
+ {
+ Descendants = 0x1000, // all descendants of the current component (children, grandchildren, etc.)
+ DirectChildrenOnly = 0x2000 // all child components of the current component
+ };
+
explicit Component(PackageManagerCore *core);
~Component();
@@ -117,7 +123,7 @@ public:
Component *parentComponent() const;
void appendComponent(Component *component);
void removeComponent(Component *component);
- QList<Component*> childComponents(bool recursive, RunMode runMode) const;
+ QList<Component*> childComponents(Component::Kind kind) const;
void loadComponentScript();
@@ -221,23 +227,19 @@ Q_SIGNALS:
void selectedChanged(bool selected);
void valueChanged(const QString &key, const QString &value);
-protected:
- QScriptValue callScriptMethod(const QString &name,
- const QScriptValueList &parameters = QScriptValueList()) const;
-
private Q_SLOTS:
void updateModelData(const QString &key, const QString &value);
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.cpp b/src/libs/installer/component_p.cpp
index 162b62c54..560cd6544 100644
--- a/src/libs/installer/component_p.cpp
+++ b/src/libs/installer/component_p.cpp
@@ -59,17 +59,16 @@ namespace QInstaller {
// -- ComponentPrivate
ComponentPrivate::ComponentPrivate(PackageManagerCore *core, Component *qq)
- : q(qq),
- m_core(core),
- m_parentComponent(0),
- m_licenseOperation(0),
- m_minimumProgressOperation(0),
- m_newlyInstalled (false),
- m_operationsCreated(false),
- m_autoCreateOperations(true),
- m_operationsCreatedSuccessfully(true),
- m_updateIsAvailable(false),
- m_scriptEngine(0)
+ : q(qq)
+ , m_core(core)
+ , m_parentComponent(0)
+ , m_licenseOperation(0)
+ , m_minimumProgressOperation(0)
+ , m_newlyInstalled (false)
+ , m_operationsCreated(false)
+ , m_autoCreateOperations(true)
+ , m_operationsCreatedSuccessfully(true)
+ , m_updateIsAvailable(false)
{
}
@@ -88,111 +87,6 @@ ComponentPrivate::~ComponentPrivate()
delete widget.data();
}
-QScriptEngine *ComponentPrivate::scriptEngine()
-{
- if (m_scriptEngine != 0)
- return m_scriptEngine;
-
-
- m_scriptEngine = new QScriptEngine(q);
-
- // register translation stuff
- m_scriptEngine->installTranslatorFunctions();
-
- // register QMessageBox::StandardButton enum in the script connection
- registerMessageBox(m_scriptEngine);
-
- // register ::WizardPage enum in the script connection
- QScriptValue qinstaller = m_scriptEngine->newArray();
- setProperty(qinstaller, QLatin1String("Introduction"), PackageManagerCore::Introduction);
- setProperty(qinstaller, QLatin1String("LicenseCheck"), PackageManagerCore::LicenseCheck);
- setProperty(qinstaller, QLatin1String("TargetDirectory"), PackageManagerCore::TargetDirectory);
- setProperty(qinstaller, QLatin1String("ComponentSelection"), PackageManagerCore::ComponentSelection);
- setProperty(qinstaller, QLatin1String("StartMenuSelection"), PackageManagerCore::StartMenuSelection);
- setProperty(qinstaller, QLatin1String("ReadyForInstallation"), PackageManagerCore::ReadyForInstallation);
- setProperty(qinstaller, QLatin1String("PerformInstallation"), PackageManagerCore::PerformInstallation);
- setProperty(qinstaller, QLatin1String("InstallationFinished"), PackageManagerCore::InstallationFinished);
- setProperty(qinstaller, QLatin1String("End"), PackageManagerCore::End);
-
- // register ::Status enum in the script connection
- setProperty(qinstaller, QLatin1String("Success"), PackageManagerCore::Success);
- setProperty(qinstaller, QLatin1String("Failure"), PackageManagerCore::Failure);
- setProperty(qinstaller, QLatin1String("Running"), PackageManagerCore::Running);
- setProperty(qinstaller, QLatin1String("Canceled"), PackageManagerCore::Canceled);
-
- // maybe used by old scripts
- setProperty(qinstaller, QLatin1String("InstallerFailed"), PackageManagerCore::Failure);
- setProperty(qinstaller, QLatin1String("InstallerSucceeded"), PackageManagerCore::Success);
- setProperty(qinstaller, QLatin1String("InstallerUnfinished"), PackageManagerCore::Unfinished);
- setProperty(qinstaller, QLatin1String("InstallerCanceledByUser"), PackageManagerCore::Canceled);
-
- QScriptValue installerObject = m_scriptEngine->newQObject(m_core);
- installerObject.setProperty(QLatin1String("componentByName"), m_scriptEngine
- ->newFunction(qInstallerComponentByName, 1));
-
- m_scriptEngine->globalObject().setProperty(QLatin1String("QInstaller"), qinstaller);
- m_scriptEngine->globalObject().setProperty(QLatin1String("installer"), installerObject);
-
- // register QDesktopServices in the script connection
- m_scriptEngine->globalObject().setProperty(QLatin1String("QDesktopServices"), getDesktopServices());
- m_scriptEngine->globalObject().setProperty(QLatin1String("component"), m_scriptEngine->newQObject(q));
-
- QScriptValue fileDialog = m_scriptEngine->newArray();
- fileDialog.setProperty(QLatin1String("getExistingDirectory"),
- m_scriptEngine->newFunction(qFileDialogGetExistingDirectory));
- m_scriptEngine->globalObject().setProperty(QLatin1String("QFileDialog"), fileDialog);
-
- return m_scriptEngine;
-}
-
-void ComponentPrivate::setProperty(QScriptValue &scriptValue, const QString &propertyName, int value)
-{
- scriptValue.setProperty(propertyName, m_scriptEngine->newVariant(value));
-}
-
-// -- private
-
-QScriptValue ComponentPrivate::getDesktopServices()
-{
- QScriptValue desktopServices = m_scriptEngine->newArray();
-#if QT_VERSION < 0x050000
- setProperty(desktopServices, QLatin1String("DesktopLocation"), QDesktopServices::DesktopLocation);
- setProperty(desktopServices, QLatin1String("DesktopLocation"), QDesktopServices::DesktopLocation);
- setProperty(desktopServices, QLatin1String("DocumentsLocation"), QDesktopServices::DocumentsLocation);
- setProperty(desktopServices, QLatin1String("FontsLocation"), QDesktopServices::FontsLocation);
- setProperty(desktopServices, QLatin1String("ApplicationsLocation"), QDesktopServices::ApplicationsLocation);
- setProperty(desktopServices, QLatin1String("MusicLocation"), QDesktopServices::MusicLocation);
- setProperty(desktopServices, QLatin1String("MoviesLocation"), QDesktopServices::MoviesLocation);
- setProperty(desktopServices, QLatin1String("PicturesLocation"), QDesktopServices::PicturesLocation);
- setProperty(desktopServices, QLatin1String("TempLocation"), QDesktopServices::TempLocation);
- setProperty(desktopServices, QLatin1String("HomeLocation"), QDesktopServices::HomeLocation);
- setProperty(desktopServices, QLatin1String("DataLocation"), QDesktopServices::DataLocation);
- setProperty(desktopServices, QLatin1String("CacheLocation"), QDesktopServices::CacheLocation);
-#else
- setProperty(desktopServices, QLatin1String("DesktopLocation"), QStandardPaths::DesktopLocation);
- setProperty(desktopServices, QLatin1String("DesktopLocation"), QStandardPaths::DesktopLocation);
- setProperty(desktopServices, QLatin1String("DocumentsLocation"), QStandardPaths::DocumentsLocation);
- setProperty(desktopServices, QLatin1String("FontsLocation"), QStandardPaths::FontsLocation);
- setProperty(desktopServices, QLatin1String("ApplicationsLocation"), QStandardPaths::ApplicationsLocation);
- setProperty(desktopServices, QLatin1String("MusicLocation"), QStandardPaths::MusicLocation);
- setProperty(desktopServices, QLatin1String("MoviesLocation"), QStandardPaths::MoviesLocation);
- setProperty(desktopServices, QLatin1String("PicturesLocation"), QStandardPaths::PicturesLocation);
- setProperty(desktopServices, QLatin1String("TempLocation"), QStandardPaths::TempLocation);
- setProperty(desktopServices, QLatin1String("HomeLocation"), QStandardPaths::HomeLocation);
- setProperty(desktopServices, QLatin1String("DataLocation"), QStandardPaths::DataLocation);
- setProperty(desktopServices, QLatin1String("CacheLocation"), QStandardPaths::CacheLocation);
-#endif
-
- desktopServices.setProperty(QLatin1String("openUrl"),
- m_scriptEngine->newFunction(qDesktopServicesOpenUrl));
- desktopServices.setProperty(QLatin1String("displayName"),
- m_scriptEngine->newFunction(qDesktopServicesDisplayName));
- desktopServices.setProperty(QLatin1String("storageLocation"),
- m_scriptEngine->newFunction(qDesktopServicesStorageLocation));
- return desktopServices;
-}
-
-
// -- ComponentModelHelper
ComponentModelHelper::ComponentModelHelper()
@@ -202,8 +96,8 @@ ComponentModelHelper::ComponentModelHelper()
}
/*!
- Returns the number of child components. Depending if virtual components are visible or not the count might
- differ from what one will get if calling Component::childComponents(...).count().
+ Returns the number of child components. Depending if virtual components are visible or not,
+ the count might differ from what one will get if calling Component::childComponents(...).count().
*/
int ComponentModelHelper::childCount() const
{
@@ -213,49 +107,38 @@ int ComponentModelHelper::childCount() const
}
/*!
- Returns the index of this component as seen from it's parent.
+ Returns the component at index position in the list. Index must be a valid position in
+ the list (i.e., index >= 0 && index < childCount()). Otherwise it returns 0.
*/
-int ComponentModelHelper::indexInParent() const
+Component *ComponentModelHelper::childAt(int index) const
{
- int index = 0;
- if (Component *parent = m_componentPrivate->m_parentComponent->parentComponent())
- index = parent->childComponents(false, AllMode).indexOf(m_componentPrivate->m_parentComponent);
- return (index >= 0 ? index : 0);
+ if (index < 0 && index >= childCount())
+ return 0;
+
+ if (m_componentPrivate->m_core->virtualComponentsVisible())
+ return m_componentPrivate->m_allChildComponents.value(index, 0);
+ return m_componentPrivate->m_childComponents.value(index, 0);
}
/*!
- Returns all children and whose children depending if virtual components are visible or not.
+ Returns all descendants of this component depending if virtual components are visible or not.
*/
-QList<Component*> ComponentModelHelper::childs() const
+QList<Component*> ComponentModelHelper::childItems() const
{
QList<Component*> *components = &m_componentPrivate->m_childComponents;
if (m_componentPrivate->m_core->virtualComponentsVisible())
components = &m_componentPrivate->m_allChildComponents;
QList<Component*> result;
- foreach (Component *component, *components) {
+ foreach (Component *const component, *components) {
result.append(component);
- result += component->childs();
+ result += component->childItems();
}
return result;
}
/*!
- Returns the component at index position in the list. Index must be a valid position in
- the list (i.e., index >= 0 && index < childCount()). Otherwise it returns 0.
-*/
-Component *ComponentModelHelper::childAt(int index) const
-{
- if (index >= 0 && index < childCount()) {
- if (m_componentPrivate->m_core->virtualComponentsVisible())
- return m_componentPrivate->m_allChildComponents.value(index, 0);
- return m_componentPrivate->m_childComponents.value(index, 0);
- }
- return 0;
-}
-
-/*!
- Determines if the components installations status can be changed. The default value is true.
+ Determines if the installation status of the component can be changed. The default value is true.
*/
bool ComponentModelHelper::isEnabled() const
{
@@ -263,7 +146,7 @@ bool ComponentModelHelper::isEnabled() const
}
/*!
- Enables oder disables ability to change the components installations status.
+ Enables or disables the ability to change the installation status of the components.
*/
void ComponentModelHelper::setEnabled(bool enabled)
{
@@ -271,7 +154,7 @@ void ComponentModelHelper::setEnabled(bool enabled)
}
/*!
- Returns whether the component is tristate; that is, if it's checkable with three separate states.
+ Returns whether the component is tri-state; that is, if it's checkable with three separate states.
The default value is false.
*/
bool ComponentModelHelper::isTristate() const
@@ -280,10 +163,10 @@ bool ComponentModelHelper::isTristate() const
}
/*!
- Sets whether the component is tristate. If tristate is true, the component is checkable with three
+ Sets whether the component is tri-state. If tri-state is true, the component is checkable with three
separate states; otherwise, the component is checkable with two states.
- (Note that this also requires that the component is checkable; see isCheckable().)
+ Note: this also requires that the component is checkable. \sa isCheckable()
*/
void ComponentModelHelper::setTristate(bool tristate)
{
diff --git a/src/libs/installer/component_p.h b/src/libs/installer/component_p.h
index 241888a3f..1da9eee1a 100644
--- a/src/libs/installer/component_p.h
+++ b/src/libs/installer/component_p.h
@@ -47,8 +47,7 @@
#include <QtCore/QPointer>
#include <QtCore/QStringList>
#include <QtCore/QUrl>
-
-#include <QtScript/QScriptEngine>
+#include <QScriptValue>
namespace QInstaller {
@@ -63,10 +62,6 @@ public:
explicit ComponentPrivate(PackageManagerCore *core, Component *qq);
~ComponentPrivate();
- QScriptEngine *scriptEngine();
-
- void setProperty(QScriptValue &scriptValue, const QString &propertyName, int value);
-
PackageManagerCore *m_core;
Component *m_parentComponent;
OperationList m_operations;
@@ -82,25 +77,18 @@ public:
QString m_componentName;
QUrl m_repositoryUrl;
QString m_localTempPath;
- QScriptValue m_scriptComponent;
+ QScriptValue m_scriptContext;
QHash<QString, QString> m_vars;
QList<Component*> m_childComponents;
QList<Component*> m_allChildComponents;
QList<Component*> m_virtualChildComponents;
QStringList m_downloadableArchives;
QStringList m_stopProcessForUpdateRequests;
- QHash<QString, bool> m_unexistingScriptMethods;
QHash<QString, QPointer<QWidget> > m_userInterfaces;
// < display name, < file name, file content > >
QHash<QString, QPair<QString, QString> > m_licenses;
QList<QPair<QString, bool> > m_pathesForUninstallation;
-
-private:
- QScriptValue getDesktopServices();
-
-private:
- QScriptEngine* m_scriptEngine;
};
@@ -111,24 +99,24 @@ 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
};
explicit ComponentModelHelper();
int childCount() const;
- int indexInParent() const;
-
- QList<Component*> childs() const;
Component* childAt(int index) const;
+ QList<Component*> childItems() const;
bool isEnabled() const;
void setEnabled(bool enabled);
diff --git a/src/libs/installer/componentmodel.cpp b/src/libs/installer/componentmodel.cpp
index a87f59c00..080e84d85 100644
--- a/src/libs/installer/componentmodel.cpp
+++ b/src/libs/installer/componentmodel.cpp
@@ -47,17 +47,18 @@
namespace QInstaller {
/*!
- \fn void defaultCheckStateChanged(bool changed)
+ \fn void checkStateChanged(const QModelIndex &index)
- This signal is emitted whenever the default check state of a model is changed. The \a changed value
- indicates whether the model has it's initial checked state or some components changed it's checked state.
+ This signal is emitted whenever the check state of a component is changed. The \a index value indicates
+ the QModelIndex representation of the component as seen from the model.
*/
/*!
- \fn void checkStateChanged(const QModelIndex &index)
+ \fn void checkStateChanged(QInstaller::ComponentModel::ModelState state)
- This signal is emitted whenever the default check state of a component is changed. The \a index value
- indicates the QModelIndex representation of the component as seen from the model.
+ This signal is emitted whenever the check state of a model is changed after all check state
+ calculations have taken place. The \a state value indicates whether the model has its default checked
+ state, all components are checked/ unchecked or some individual components checked state has changed.
*/
@@ -67,12 +68,10 @@ namespace QInstaller {
ComponentModel::ComponentModel(int columns, PackageManagerCore *core)
: QAbstractItemModel(core)
, m_core(core)
- , m_rootIndex(0)
+ , m_modelState(DefaultChecked)
{
m_headerData.insert(0, columns, QVariant());
-
connect(this, SIGNAL(modelReset()), this, SLOT(slotModelReset()));
- connect(this, SIGNAL(checkStateChanged(QModelIndex)), this, SLOT(slotCheckStateChanged(QModelIndex)));
}
/*!
@@ -83,8 +82,25 @@ ComponentModel::~ComponentModel()
}
/*!
- Returns the number of items under the given \a parent. When the parent is valid it means that rowCount is
- returning the number of items of parent.
+ Returns the item flags for the given \a index.
+
+ The class implementation returns a combination of flags that enables the item (Qt::ItemIsEnabled), allows
+ it to be selected (Qt::ItemIsSelectable) and to be checked (Qt::ItemIsUserCheckable).
+*/
+Qt::ItemFlags ComponentModel::flags(const QModelIndex &index) const
+{
+ if (!index.isValid())
+ return Qt::NoItemFlags;
+
+ if (Component *component = componentFromIndex(index))
+ return component->flags();
+
+ return Qt::ItemFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable);
+}
+
+/*!
+ Returns the number of items under the given \a parent. When the parent is valid it means that rowCount
+ is returning the number of items of parent.
*/
int ComponentModel::rowCount(const QModelIndex &parent) const
{
@@ -160,9 +176,9 @@ QVariant ComponentModel::data(const QModelIndex &index, int role) const
}
/*!
- Sets the \a role data for the item at \a index to \a value. Returns true if successful; otherwise returns
- false. The dataChanged() signal is emitted if the data was successfully set. The checkStateChanged() and
- defaultCheckStateChanged() signal are emitted in addition if the check state of the item is set.
+ Sets the \a role data for the item at \a index to \a value. Returns true if successful;
+ otherwise returns false. The dataChanged() signal is emitted if the data was successfully set.
+ The checkStateChanged() signals are emitted in addition if the check state of the item is set.
*/
bool ComponentModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
@@ -173,14 +189,17 @@ bool ComponentModel::setData(const QModelIndex &index, const QVariant &value, in
if (!component)
return false;
- component->setData(value, role);
-
- emit dataChanged(index, index);
if (role == Qt::CheckStateRole) {
- emit checkStateChanged(index);
- foreach (Component* comp, m_rootComponentList) {
- comp->updateUncompressedSize();
+ ComponentSet nodes = component->childItems().toSet();
+ QSet<QModelIndex> changed = updateCheckedState(nodes << component, Qt::CheckState(value.toInt()));
+ foreach (const QModelIndex &index, changed) {
+ emit dataChanged(index, index);
+ emit checkStateChanged(index);
}
+ updateAndEmitModelState(); // update the internal state
+ } else {
+ component->setData(value, role);
+ emit dataChanged(index, index);
}
return true;
@@ -217,72 +236,69 @@ bool ComponentModel::setHeaderData(int section, Qt::Orientation orientation, con
}
/*!
- Returns the item flags for the given \a index.
-
- The class implementation returns a combination of flags that enables the item (Qt::ItemIsEnabled), allows
- it to be selected (Qt::ItemIsSelectable) and to be checked (Qt::ItemIsUserCheckable).
+ Returns a list of checked components.
*/
-Qt::ItemFlags ComponentModel::flags(const QModelIndex &index) const
+QSet<Component *> ComponentModel::checked() const
{
- if (!index.isValid())
- return Qt::NoItemFlags;
-
- if (Component *component = componentFromIndex(index))
- return component->flags();
+ return m_currentCheckedState[Qt::Checked];
+}
- return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable;
+/*!
+ Returns a list of partially checked components.
+*/
+QSet<Component *> ComponentModel::partially() const
+{
+ return m_currentCheckedState[Qt::PartiallyChecked];
}
/*!
- Returns a pointer to the PackageManagerCore this model belongs to.
+ Returns a list of unchecked components.
*/
-PackageManagerCore *ComponentModel::packageManagerCore() const
+QSet<Component *> ComponentModel::unchecked() const
{
- return m_core;
+ return m_currentCheckedState[Qt::Unchecked];
}
/*!
- Returns true if no changes to the components checked state have been done, otherwise returns false.
+ Returns a list of components whose check state can't be changed. If package manager core is run with no
+ forced installation argument, the list will always be empty.
*/
-bool ComponentModel::defaultCheckState() const
+QSet<Component *> ComponentModel::uncheckable() const
{
- return m_initialCheckedSet == m_currentCheckedSet;
+ return m_uncheckable;
}
/*!
- Returns true if this model has checked components, otherwise returns false.
+ Returns a pointer to the PackageManagerCore this model belongs to.
*/
-bool ComponentModel::hasCheckedComponents() const
+PackageManagerCore *ComponentModel::core() const
{
- return !m_currentCheckedSet.isEmpty();
+ return m_core;
}
/*!
- Returns a list of checked components.
+ Returns the current state check state of the model.
*/
-QList<Component*> ComponentModel::checkedComponents() const
+ComponentModel::ModelState ComponentModel::checkedState() const
{
- QList<Component*> list;
- foreach (const QString &name, m_currentCheckedSet)
- list.append(componentFromIndex(indexFromComponentName(name)));
- return list;
+ return m_modelState;
}
/*!
- Translates between a given component \a name and it's associated QModelIndex. Returns the QModelIndex that
- represents the component or an invalid QModelIndex if the component does not exist in the model.
+ Translates between a given component \a name and its associated QModelIndex. Returns the QModelIndex
+ that represents the component or an invalid QModelIndex if the component does not exist in the model.
*/
QModelIndex ComponentModel::indexFromComponentName(const QString &name) const
{
if (m_indexByNameCache.isEmpty()) {
for (int i = 0; i < m_rootComponentList.count(); ++i)
- updateCache(index(i, 0, QModelIndex()));
+ collectComponents(m_rootComponentList.at(i), index(i, 0, QModelIndex()));
}
return m_indexByNameCache.value(name, QModelIndex());
}
/*!
- Translates between a given QModelIndex \a index and it's associated Component. Returns the Component if
+ Translates between a given QModelIndex \a index and its associated Component. Returns the component if
the index is valid or 0 if an invalid QModelIndex is given.
*/
Component *ComponentModel::componentFromIndex(const QModelIndex &index) const
@@ -292,242 +308,229 @@ Component *ComponentModel::componentFromIndex(const QModelIndex &index) const
return 0;
}
-// -- public slots
-
-/*!
- Invoking this slot results in an checked state for every component the has a visual representation in the
- model. Note that components are not changed if they are not checkable. The checkStateChanged() and
- defaultCheckStateChanged() signal are emitted.
-*/
-void ComponentModel::selectAll()
-{
- m_currentCheckedSet = m_currentCheckedSet.unite(select(Qt::Checked));
- emit defaultCheckStateChanged(m_initialCheckedSet != m_currentCheckedSet);
-}
-/*!
- Invoking this slot results in an unchecked state for every component the has a visual representation in
- the model. Note that components are not changed if they are not checkable. The checkStateChanged() and
- defaultCheckStateChanged() signal are emitted.
-*/
-void ComponentModel::deselectAll()
-{
- m_currentCheckedSet = m_currentCheckedSet.subtract(select(Qt::Unchecked));
- emit defaultCheckStateChanged(m_initialCheckedSet != m_currentCheckedSet);
-}
+// -- public slots
/*!
- Invoking this slot results in an checked state for every component the has a visual representation in the
- model when the model was setup during setRootComponents() or appendRootComponents(). Note that components
- are not changed it they are not checkable. The checkStateChanged() and defaultCheckStateChanged() signal
- are emitted.
-*/
-void ComponentModel::selectDefault()
-{
- m_currentCheckedSet = m_currentCheckedSet.subtract(select(Qt::Unchecked));
- foreach (const QString &name, m_initialCheckedSet)
- setData(indexFromComponentName(name), Qt::Checked, Qt::CheckStateRole);
- emit defaultCheckStateChanged(m_initialCheckedSet != m_currentCheckedSet);
-}
+ Sets the passed \a rootComponents to be the list of currently shown components.
-/*!
- Set's the passed \a rootComponents to be list of currently shown components. The model is repopulated and
- the individual component checked state is used to show the check mark in front of the visual component
- representation. The modelAboutToBeReset() and modelReset() signals are emitted.
+ The model is repopulated and the individual component checked state is used to show the check mark in
+ front of the visual component representation. The modelAboutToBeReset() and modelReset() signals are
+ emitted.
*/
void ComponentModel::setRootComponents(QList<QInstaller::Component*> rootComponents)
{
beginResetModel();
+ m_uncheckable.clear();
m_indexByNameCache.clear();
m_rootComponentList.clear();
- m_initialCheckedSet.clear();
- m_currentCheckedSet.clear();
-
- m_rootIndex = 0;
- m_rootComponentList = rootComponents;
-
+ 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) {
+ if ((!showVirtuals) && component->isVirtual())
+ continue;
+ m_rootComponentList.append(component);
+ }
endResetModel();
}
/*!
- Appends the passed \a rootComponents to the currently shown list of components. The model is repopulated
- and the individual component checked state is used to show the check mark in front of the visual component
- representation. Already changed check states on the previous model are preserved. The modelAboutToBeReset()
- and modelReset() signals are emitted.
+ Sets the check state of every component in the model to be \a state.
+
+ The ComponentModel::PartiallyChecked flag is ignored by this function. Note that components are not
+ changed if they are not checkable. The dataChanged() and checkStateChanged() signals are emitted.
*/
-void ComponentModel::appendRootComponents(QList<QInstaller::Component*> rootComponents)
+void ComponentModel::setCheckedState(QInstaller::ComponentModel::ModelStateFlag state)
{
- beginResetModel();
-
- m_indexByNameCache.clear();
+ QSet<QModelIndex> changed;
+ switch (state) {
+ case AllChecked:
+ changed = updateCheckedState(m_currentCheckedState[Qt::Unchecked], Qt::Checked);
+ break;
+ case AllUnchecked:
+ changed = updateCheckedState(m_currentCheckedState[Qt::Checked], Qt::Unchecked);
+ break;
+ case DefaultChecked:
+ // record all changes, to be able to update the UI properly
+ changed = updateCheckedState(m_currentCheckedState[Qt::Checked], Qt::Unchecked);
+ changed += updateCheckedState(m_initialCheckedState[Qt::Checked], Qt::Checked);
+ break;
+ default:
+ break;
+ }
- m_rootIndex = m_rootComponentList.count() - 1;
- m_rootComponentList += rootComponents;
+ if (changed.isEmpty())
+ return;
- endResetModel();
+ // notify about changes done to the model
+ foreach (const QModelIndex &index, changed) {
+ emit dataChanged(index, index);
+ emit checkStateChanged(index);
+ }
+ updateAndEmitModelState(); // update the internal state
}
+
// -- private slots
void ComponentModel::slotModelReset()
{
- QList<QInstaller::Component*> components = m_rootComponentList;
- if (m_core->runMode() == QInstaller::AllMode) {
- for (int i = m_rootIndex; i < m_rootComponentList.count(); ++i)
- components.append(m_rootComponentList.at(i)->childs());
+ ComponentList components = m_rootComponentList;
+ if (!m_core->isUpdater()) {
+ foreach (Component *const component, m_rootComponentList)
+ components += component->childItems();
+ }
+
+ ComponentSet checked;
+ foreach (Component *const component, components) {
+ if (component->checkState() == Qt::Checked)
+ checked.insert(component);
}
- foreach (Component *child, components) {
- if (child->checkState() == Qt::Checked && !child->isTristate())
- m_initialCheckedSet.insert(child->name());
+ updateCheckedState(checked, Qt::Checked);
+ foreach (Component *const component, components) {
+ if (!component->isCheckable())
+ m_uncheckable.insert(component);
+ m_initialCheckedState[component->checkState()].insert(component);
}
- m_currentCheckedSet += m_initialCheckedSet;
- if (m_core->runMode() == QInstaller::AllMode)
- select(Qt::Unchecked);
+ m_currentCheckedState = m_initialCheckedState;
+ updateAndEmitModelState(); // update the internal state
+}
+
+
+// -- private
- foreach (const QString &name, m_currentCheckedSet)
- setData(indexFromComponentName(name), Qt::Checked, Qt::CheckStateRole);
+void ComponentModel::updateAndEmitModelState()
+{
+ m_modelState = ComponentModel::DefaultChecked;
+ if (m_initialCheckedState != m_currentCheckedState)
+ m_modelState = ComponentModel::PartiallyChecked;
+ if (checked().count() == 0 && partially().count() == 0) {
+ m_modelState |= ComponentModel::AllUnchecked;
+ m_modelState &= ~ComponentModel::PartiallyChecked;
+ }
+
+ if (unchecked().count() == 0 && partially().count() == 0) {
+ m_modelState |= ComponentModel::AllChecked;
+ m_modelState &= ~ComponentModel::PartiallyChecked;
+ }
+
+ emit checkStateChanged(m_modelState);
}
+void ComponentModel::collectComponents(Component *const component, const QModelIndex &parent) const
+{
+ m_indexByNameCache.insert(component->name(), parent);
+ for (int i = 0; i < component->childCount(); ++i)
+ collectComponents(component->childAt(i), index(i, 0, parent));
+}
+
+namespace ComponentModelPrivate {
+
+struct NameGreaterThan
+{
+ bool operator() (const Component *lhs, const Component *rhs) const
+ {
+ return lhs->name() > rhs->name();
+ }
+};
+
static Qt::CheckState verifyPartiallyChecked(Component *component)
{
int checked = 0;
int unchecked = 0;
- int virtualChilds = 0;
const int count = component->childCount();
for (int i = 0; i < count; ++i) {
- Component *const child = component->childAt(i);
- if (!child->isVirtual()) {
- switch (component->childAt(i)->checkState()) {
- case Qt::Checked: {
- ++checked;
- } break;
- case Qt::Unchecked: {
- ++unchecked;
- } break;
- default:
- break;
- }
- } else {
- ++virtualChilds;
+ switch (component->childAt(i)->checkState()) {
+ case Qt::Checked: {
+ ++checked;
+ } break;
+ case Qt::Unchecked: {
+ ++unchecked;
+ } break;
+ default:
+ break;
}
}
- if ((checked + virtualChilds) == count)
+ if (checked == count)
return Qt::Checked;
- if ((unchecked + virtualChilds) == count)
+ if (unchecked == count)
return Qt::Unchecked;
return Qt::PartiallyChecked;
}
-void ComponentModel::slotCheckStateChanged(const QModelIndex &index)
-{
- Component *component = componentFromIndex(index);
- if (!component)
- return;
-
- if (component->checkState() == Qt::Checked && !component->isTristate())
- m_currentCheckedSet.insert(component->name());
- else if (component->checkState() == Qt::Unchecked && !component->isTristate())
- m_currentCheckedSet.remove(component->name());
- emit defaultCheckStateChanged(m_initialCheckedSet != m_currentCheckedSet);
-
- if (component->isVirtual())
- return;
-
- const Qt::CheckState state = component->checkState();
- if (component->isTristate()) {
- if (state == Qt::PartiallyChecked) {
- component->setCheckState(verifyPartiallyChecked(component));
- return;
- }
-
- QModelIndexList notCheckable;
- foreach (Component *child, component->childs()) {
- const QModelIndex &idx = indexFromComponentName(child->name());
- if (child->isCheckable()) {
- if (child->checkState() != state && !child->isVirtual())
- setData(idx, state, Qt::CheckStateRole);
- } else {
- notCheckable.append(idx);
- }
- }
-
- if (state == Qt::Unchecked && !notCheckable.isEmpty()) {
- foreach (const QModelIndex &idx, notCheckable)
- setData(idx, idx.data(Qt::CheckStateRole), Qt::CheckStateRole);
- }
- } else {
- QList<Component*> parents;
- while (0 != component->parentComponent()) {
- parents.append(component->parentComponent());
- component = parents.last();
- }
-
- foreach (Component *parent, parents) {
- if (parent->isCheckable()) {
- const QModelIndex &idx = indexFromComponentName(parent->name());
- if (parent->checkState() == Qt::PartiallyChecked) {
- setData(idx, verifyPartiallyChecked(parent), Qt::CheckStateRole);
- } else {
- setData(idx, Qt::PartiallyChecked, Qt::CheckStateRole);
- }
- }
- }
- }
-}
-
-// -- private
+} // namespace ComponentModelPrivate
-QSet<QString> ComponentModel::select(Qt::CheckState state)
+QSet<QModelIndex> ComponentModel::updateCheckedState(const ComponentSet &components, Qt::CheckState state)
{
- QSet<QString> changed;
- for (int i = 0; i < m_rootComponentList.count(); ++i) {
- QSet<QString> tmp;
- QList<Component*> children = m_rootComponentList.at(i)->childs();
- children.prepend(m_rootComponentList.at(i)); // we need to take the root item into account as well
- foreach (Component *child, children) {
- if (child->isCheckable() && !child->isTristate() && child->checkState() != state) {
- tmp.insert(child->name());
- child->setCheckState(state);
+ // get all parent nodes for the components we're going to update
+ ComponentSet nodes = components;
+ foreach (Component *const component, components) {
+ if (Component *parent = component->parentComponent()) {
+ nodes.insert(parent);
+ while (parent->parentComponent() != 0) {
+ parent = parent->parentComponent();
+ nodes.insert(parent);
}
}
- if (!tmp.isEmpty()) {
- changed += tmp;
- setData(index(i, 0, QModelIndex()), state, Qt::CheckStateRole);
- }
}
- return changed;
-}
-void ComponentModel::updateCache(const QModelIndex &parent) const
-{
- const QModelIndexList &list = collectComponents(parent);
- foreach (const QModelIndex &index, list) {
- if (Component *component = componentFromIndex(index))
- m_indexByNameCache.insert(component->name(), index);
- }
- m_indexByNameCache.insert((static_cast<Component*> (parent.internalPointer()))->name(), parent);
-}
-
-QModelIndexList ComponentModel::collectComponents(const QModelIndex &parent) const
-{
- QModelIndexList list;
- for (int i = 0; i < rowCount(parent) ; ++i) {
- const QModelIndex &next = index(i, 0, parent);
- if (Component *component = componentFromIndex(next)) {
- if (component->childCount() > 0)
- list += collectComponents(next);
+ QSet<QModelIndex> changed;
+ // sort the nodes, so we can start in descending order to check node and tri-state nodes properly
+ ComponentList sortedNodes = nodes.toList();
+ std::sort(sortedNodes.begin(), sortedNodes.end(), ComponentModelPrivate::NameGreaterThan());
+ foreach (Component *const node, sortedNodes) {
+ if (!node->isCheckable())
+ continue;
+
+ Qt::CheckState newState = state;
+ const Qt::CheckState recentState = node->checkState();
+ if (node->isTristate())
+ newState = ComponentModelPrivate::verifyPartiallyChecked(node);
+ if (recentState == newState)
+ continue;
+
+ node->setCheckState(newState);
+ changed.insert(indexFromComponentName(node->name()));
+
+ m_currentCheckedState[Qt::Checked].remove(node);
+ m_currentCheckedState[Qt::Unchecked].remove(node);
+ m_currentCheckedState[Qt::PartiallyChecked].remove(node);
+
+ switch (newState) {
+ case Qt::Checked:
+ m_currentCheckedState[Qt::Checked].insert(node);
+ break;
+ case Qt::Unchecked:
+ m_currentCheckedState[Qt::Unchecked].insert(node);
+ break;
+ case Qt::PartiallyChecked:
+ m_currentCheckedState[Qt::PartiallyChecked].insert(node);
+ break;
}
- list.append(next);
}
- return list;
+
+ // update all nodes uncompressed size
+ foreach (Component *const node, m_rootComponentList)
+ node->updateUncompressedSize(); // this is a recursive call
+ return changed;
}
} // namespace QInstaller
diff --git a/src/libs/installer/componentmodel.h b/src/libs/installer/componentmodel.h
index b43bfc75a..a691906a4 100644
--- a/src/libs/installer/componentmodel.h
+++ b/src/libs/installer/componentmodel.h
@@ -57,11 +57,23 @@ class PackageManagerCore;
class INSTALLER_EXPORT ComponentModel : public QAbstractItemModel
{
Q_OBJECT
+ typedef QSet<Component *> ComponentSet;
+ typedef QList<Component *> ComponentList;
public:
+ enum ModelStateFlag {
+ AllChecked = 0x01,
+ AllUnchecked = 0x02,
+ DefaultChecked = 0x04,
+ PartiallyChecked = 0x08
+ };
+ Q_DECLARE_FLAGS(ModelState, ModelStateFlag);
+
explicit ComponentModel(int columns, PackageManagerCore *core = 0);
~ComponentModel();
+ Qt::ItemFlags flags(const QModelIndex &index) const;
+
int rowCount(const QModelIndex &parent = QModelIndex()) const;
int columnCount(const QModelIndex &parent = QModelIndex()) const;
@@ -75,49 +87,50 @@ public:
bool setHeaderData(int section, Qt::Orientation orientation, const QVariant &value,
int role = Qt::EditRole);
- Qt::ItemFlags flags(const QModelIndex &index) const;
- PackageManagerCore *packageManagerCore() const;
+ QSet<Component *> checked() const;
+ QSet<Component *> partially() const;
+ QSet<Component *> unchecked() const;
+ QSet<Component *> uncheckable() const;
- bool defaultCheckState() const;
- bool hasCheckedComponents() const;
- QList<Component*> checkedComponents() const;
+ PackageManagerCore *core() const;
+ ComponentModel::ModelState checkedState() const;
QModelIndex indexFromComponentName(const QString &name) const;
Component* componentFromIndex(const QModelIndex &index) const;
public Q_SLOTS:
- void selectAll();
- void deselectAll();
- void selectDefault();
-
void setRootComponents(QList<QInstaller::Component*> rootComponents);
- void appendRootComponents(QList<QInstaller::Component*> rootComponents);
+ void setCheckedState(QInstaller::ComponentModel::ModelStateFlag state);
Q_SIGNALS:
- void defaultCheckStateChanged(bool changed);
void checkStateChanged(const QModelIndex &index);
+ void checkStateChanged(QInstaller::ComponentModel::ModelState state);
private Q_SLOTS:
void slotModelReset();
- void slotCheckStateChanged(const QModelIndex &index);
private:
- QSet<QString> select(Qt::CheckState state);
- void updateCache(const QModelIndex &parent) const;
- QModelIndexList collectComponents(const QModelIndex &parent) const;
+ void updateAndEmitModelState();
+ void collectComponents(Component *const component, const QModelIndex &parent) const;
+ QSet<QModelIndex> updateCheckedState(const ComponentSet &components, Qt::CheckState state);
private:
PackageManagerCore *m_core;
- int m_rootIndex;
+ ModelState m_modelState;
+ ComponentSet m_uncheckable;
QVector<QVariant> m_headerData;
- QSet<QString> m_initialCheckedSet;
- QSet<QString> m_currentCheckedSet;
- QList<Component*> m_rootComponentList;
+ ComponentList m_rootComponentList;
+ QHash<Qt::CheckState, ComponentSet> m_initialCheckedState;
+ QHash<Qt::CheckState, ComponentSet> m_currentCheckedState;
mutable QHash<QString, QPersistentModelIndex> m_indexByNameCache;
};
+Q_DECLARE_OPERATORS_FOR_FLAGS(ComponentModel::ModelState);
} // namespace QInstaller
+Q_DECLARE_METATYPE(QInstaller::ComponentModel::ModelState);
+Q_DECLARE_METATYPE(QInstaller::ComponentModel::ModelStateFlag);
+
#endif // COMPONENTMODEL_H
diff --git a/src/libs/installer/constants.h b/src/libs/installer/constants.h
index 3929681a7..7ea73bbb9 100644
--- a/src/libs/installer/constants.h
+++ b/src/libs/installer/constants.h
@@ -80,6 +80,7 @@ static const QLatin1String scSortingPriority("SortingPriority");
static const QLatin1String scTitle("Title");
static const QLatin1String scPublisher("Publisher");
static const QLatin1String scRunProgram("RunProgram");
+static const QLatin1String scRunProgramArguments("RunProgramArguments");
static const QLatin1String scStartMenuDir("StartMenuDir");
static const QLatin1String scRemoveTargetDir("RemoveTargetDir");
static const QLatin1String scRunProgramDescription("RunProgramDescription");
diff --git a/src/libs/installer/consumeoutputoperation.cpp b/src/libs/installer/consumeoutputoperation.cpp
new file mode 100644
index 000000000..2d3bc1ec0
--- /dev/null
+++ b/src/libs/installer/consumeoutputoperation.cpp
@@ -0,0 +1,158 @@
+/**************************************************************************
+**
+** Copyright (C) 2012-2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Installer Framework.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+**************************************************************************/
+
+#include "consumeoutputoperation.h"
+#include "packagemanagercore.h"
+#include "utils.h"
+
+#include <QFile>
+#include <QDir>
+#include <QProcess>
+#include <QDebug>
+
+using namespace QInstaller;
+
+ConsumeOutputOperation::ConsumeOutputOperation()
+{
+ setName(QLatin1String("ConsumeOutput"));
+}
+
+void ConsumeOutputOperation::backup()
+{
+}
+
+bool ConsumeOutputOperation::performOperation()
+{
+ // Arguments:
+ // 1. key where the output will be saved
+ // 2. executable path
+ // 3. argument for the executable
+ // 4. more arguments possible ...
+ if (arguments().count() < 3) {
+ setError(InvalidArguments);
+ setErrorString(tr("Invalid arguments in %0: %1 arguments given, %2 expected%3.").arg(name()).arg(
+ arguments().count()).arg(tr("at least 2"), QLatin1String("(<to be saved installer key name>, "
+ "<executable>, [argument1], [argument2], ...)")));
+ return false;
+ }
+
+ PackageManagerCore *const core = value(QLatin1String("installer")).value<PackageManagerCore*>();
+ if (!core) {
+ setError(UserDefinedError);
+ setErrorString(tr("Needed installer object in %1 operation is empty.").arg(name()));
+ return false;
+ }
+
+ const QString installerKeyName = arguments().at(0);
+ if (installerKeyName.isEmpty()) {
+ setError(UserDefinedError);
+ setErrorString(tr("Can not save the output of %1 to an empty installer key value.").arg(
+ arguments().at(1)));
+ return false;
+ }
+
+ QString executablePath = arguments().at(1);
+#ifdef Q_OS_WIN
+ if (!QFile::exists(executablePath))
+ executablePath = executablePath + QLatin1String(".exe");
+#endif
+
+ const QFileInfo executable(executablePath);
+ if (!executable.exists() || !executable.isExecutable()) {
+ setError(UserDefinedError);
+ setErrorString(tr("File '%1' does not exist or is not an executable binary.").arg(
+ QDir::toNativeSeparators(executable.absoluteFilePath())));
+ return false;
+ }
+
+ QByteArray executableOutput;
+ QProcess process;
+
+
+ const QStringList processArguments = arguments().mid(2);
+ // in some cases it is not runable, because another process is blocking it(filewatcher ...)
+ int waitCount = 0;
+ while (executableOutput.isEmpty() && waitCount < 60) {
+
+ process.start(executable.absoluteFilePath(), processArguments, QIODevice::ReadOnly);
+ if (process.waitForFinished(2000)) {
+ if (process.exitStatus() == QProcess::CrashExit) {
+ setError(UserDefinedError);
+ setErrorString(tr("Running '%1' resulted in a crash.").arg(
+ QDir::toNativeSeparators(executable.absoluteFilePath())));
+ return false;
+ }
+ executableOutput.append(process.readAllStandardOutput());
+ }
+ if (executableOutput.isEmpty()) {
+ ++waitCount;
+ static const int waitTimeInMilliSeconds = 500;
+ uiDetachedWait(waitTimeInMilliSeconds);
+ }
+ if (process.state() > QProcess::NotRunning ) {
+ qWarning() << executable.absoluteFilePath() << "process is still running, need to kill it.";
+ process.kill();
+ }
+
+ }
+ if (executableOutput.isEmpty()) {
+ qWarning() << QString::fromLatin1("Can't get any query output from executable: '%1'").arg(
+ executable.absoluteFilePath());
+ }
+ core->setValue(installerKeyName, QString::fromLatin1(executableOutput));
+ return true;
+}
+
+bool ConsumeOutputOperation::undoOperation()
+{
+ return true;
+}
+
+bool ConsumeOutputOperation::testOperation()
+{
+ return true;
+}
+
+Operation *ConsumeOutputOperation::clone() const
+{
+ return new ConsumeOutputOperation();
+}
+
diff --git a/src/libs/installer/consumeoutputoperation.h b/src/libs/installer/consumeoutputoperation.h
new file mode 100644
index 000000000..f776cf35a
--- /dev/null
+++ b/src/libs/installer/consumeoutputoperation.h
@@ -0,0 +1,65 @@
+/**************************************************************************
+**
+** Copyright (C) 2012-2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Installer Framework.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+**************************************************************************/
+
+#ifndef CONSUMEOUTPUTOPERATION_H
+#define CONSUMEOUTPUTOPERATION_H
+
+#include "qinstallerglobal.h"
+
+namespace QInstaller {
+
+class INSTALLER_EXPORT ConsumeOutputOperation : public Operation
+{
+public:
+ ConsumeOutputOperation();
+
+ void backup();
+ bool performOperation();
+ bool undoOperation();
+ bool testOperation();
+ Operation *clone() const;
+
+private:
+};
+
+} // namespace QInstaller
+
+#endif // CONSUMEOUTPUTOPERATION_H
diff --git a/src/libs/installer/createdesktopentryoperation.cpp b/src/libs/installer/createdesktopentryoperation.cpp
index f7cb30726..cd79bc65d 100644
--- a/src/libs/installer/createdesktopentryoperation.cpp
+++ b/src/libs/installer/createdesktopentryoperation.cpp
@@ -164,7 +164,7 @@ bool CreateDesktopEntryOperation::performOperation()
}
QFile::setPermissions(filename, QFile::ReadOwner | QFile::WriteOwner | QFile::ReadUser | QFile::ReadGroup
- | QFile::ReadOther);
+ | QFile::ReadOther | QFile::ExeOwner | QFile::ExeGroup | QFile::ExeOther);
QTextStream stream(&file);
stream.setCodec("UTF-8");
diff --git a/src/libs/installer/createshortcutoperation.cpp b/src/libs/installer/createshortcutoperation.cpp
index 62f7cfa82..9f9084e05 100644
--- a/src/libs/installer/createshortcutoperation.cpp
+++ b/src/libs/installer/createshortcutoperation.cpp
@@ -79,12 +79,17 @@ struct DeCoInitializer
};
#endif
-struct StartsWithWorkingDirectory
+struct StartsWith
{
- bool operator()(const QString &s)
+ StartsWith(const QString &searchTerm)
+ : m_searchTerm(searchTerm) {}
+
+ bool operator()(const QString &searchString)
{
- return s.startsWith(QLatin1String("workingDirectory="));
+ return searchString.startsWith(m_searchTerm);
}
+
+ QString m_searchTerm;
};
static QString parentDirectory(const QString &current)
@@ -92,23 +97,25 @@ static QString parentDirectory(const QString &current)
return current.mid(0, current.lastIndexOf(QLatin1Char('/')));
}
-static QString takeWorkingDirArgument(QStringList &args)
+static QString takeArgument(const QString argument, QStringList *arguments)
{
- // if the arguments contain an option in the form "workingDirectory=...", find it and consume it
- QStringList::iterator wdiropt = std::find_if (args.begin(), args.end(), StartsWithWorkingDirectory());
- if (wdiropt == args.end())
+ // if the arguments contain an option in the form "argument=...", find it and consume it
+ QStringList::iterator it = std::find_if(arguments->begin(), arguments->end(), StartsWith(argument));
+ if (it == arguments->end())
return QString();
- const QString workingDir = wdiropt->mid(QString::fromLatin1("workingDirectory=").size());
- args.erase(wdiropt);
- return workingDir;
+ const QString value = it->mid(argument.size());
+ arguments->erase(it);
+ return value;
}
static bool createLink(const QString &fileName, const QString &linkName, QString workingDir,
- QString arguments = QString())
+ const QString &arguments = QString(), const QString &iconPath = QString(),
+ const QString &iconId = QString())
{
- bool success = QFile::link(fileName, linkName);
#ifdef Q_OS_WIN
+ bool success = QFile::link(fileName, linkName);
+
if (!success)
return success;
@@ -128,10 +135,12 @@ static bool createLink(const QString &fileName, const QString &linkName, QString
psl->SetWorkingDirectory((wchar_t *)workingDir.utf16());
if (!arguments.isNull())
psl->SetArguments((wchar_t*)arguments.utf16());
+ if (!iconPath.isNull())
+ psl->SetIconLocation((wchar_t*)(iconPath.utf16()), iconId.toInt());
IPersistFile *ppf = NULL;
if (SUCCEEDED(psl->QueryInterface(IID_IPersistFile, (void **)&ppf))) {
- ppf->Save((wchar_t*)QDir::toNativeSeparators(linkName).utf16(), TRUE);
+ ppf->Save((wchar_t*)QDir::toNativeSeparators(linkName).utf16(), true);
ppf->Release();
}
psl->Release();
@@ -145,11 +154,17 @@ static bool createLink(const QString &fileName, const QString &linkName, QString
SHChangeNotify(SHCNE_UPDATEDIR, SHCNF_IDLIST, pidl, 0);
CoTaskMemFree(pidl);
}
+
+ return success;
#else
Q_UNUSED(arguments)
Q_UNUSED(workingDir)
+ Q_UNUSED(fileName)
+ Q_UNUSED(linkName)
+ Q_UNUSED(iconPath)
+ Q_UNUSED(iconId)
+ return true;
#endif
- return success;
}
@@ -177,12 +192,16 @@ void CreateShortcutOperation::backup()
bool CreateShortcutOperation::performOperation()
{
QStringList args = arguments();
- const QString workingDir = takeWorkingDirArgument(args);
+
+ const QString iconId = takeArgument(QString::fromLatin1("iconId="), &args);
+ const QString iconPath = takeArgument(QString::fromLatin1("iconPath="), &args);
+ const QString workingDir = takeArgument(QString::fromLatin1("workingDirectory="), &args);
if (args.count() != 2 && args.count() != 3) {
setError(InvalidArguments);
setErrorString(tr("Invalid arguments in %0: %1 arguments given, %2 expected%3.")
- .arg(name()).arg(arguments().count()).arg(tr("2 or 3"), tr(" (optional: 'workingDirectory=...')")));
+ .arg(name()).arg(arguments().count()).arg(tr("2 or 3"),
+ tr(" (optional: 'workingDirectory=...', 'iconPath=...', 'iconId=...')")));
return false;
}
@@ -190,10 +209,8 @@ bool CreateShortcutOperation::performOperation()
const QString linkLocation = args.at(1);
const QString targetArguments = args.value(2); //used value because it could be not existing
- const QString linkPath = QFileInfo(linkLocation).absolutePath();
-
- const bool linkPathAlreadyExists = QDir(linkPath).exists();
- const bool created = linkPathAlreadyExists || QDir::root().mkpath(linkPath);
+ const QString linkPath = QFileInfo(linkLocation).absolutePath().trimmed();
+ const bool created = QDir(linkPath).exists() || QDir::root().mkpath(linkPath);
if (!created) {
setError(UserDefinedError);
@@ -219,7 +236,7 @@ bool CreateShortcutOperation::performOperation()
return false;
}
- const bool linked = createLink(linkTarget, linkLocation, workingDir, targetArguments);
+ const bool linked = createLink(linkTarget, linkLocation, workingDir, targetArguments, iconPath, iconId);
if (!linked) {
setError(UserDefinedError);
setErrorString(tr("Could not create link %1: %2").arg(QDir::toNativeSeparators(linkLocation),
diff --git a/src/libs/installer/downloadarchivesjob.cpp b/src/libs/installer/downloadarchivesjob.cpp
index 1cfb2ffec..24fba689a 100644
--- a/src/libs/installer/downloadarchivesjob.cpp
+++ b/src/libs/installer/downloadarchivesjob.cpp
@@ -60,14 +60,14 @@ using namespace KDUpdater;
Creates a new DownloadArchivesJob with \a parent.
*/
DownloadArchivesJob::DownloadArchivesJob(PackageManagerCore *core)
- : KDJob(core),
- m_core(core),
- m_downloader(0),
- m_archivesDownloaded(0),
- m_archivesToDownloadCount(0),
- m_canceled(false),
- m_lastFileProgress(0),
- m_progressChangedTimerId(0)
+ : KDJob(core)
+ , m_core(core)
+ , m_downloader(0)
+ , m_archivesDownloaded(0)
+ , m_archivesToDownloadCount(0)
+ , m_canceled(false)
+ , m_lastFileProgress(0)
+ , m_progressChangedTimerId(0)
{
setCapabilities(Cancelable);
}
diff --git a/src/libs/installer/elevatedexecuteoperation.cpp b/src/libs/installer/elevatedexecuteoperation.cpp
index 0aa8c101d..d797f2077 100644
--- a/src/libs/installer/elevatedexecuteoperation.cpp
+++ b/src/libs/installer/elevatedexecuteoperation.cpp
@@ -54,7 +54,9 @@ class ElevatedExecuteOperation::Private
{
public:
explicit Private(ElevatedExecuteOperation *qq)
- : q(qq), process(0), showStandardError(false)
+ : q(qq)
+ , process(0)
+ , showStandardError(false)
{
}
@@ -202,7 +204,8 @@ bool ElevatedExecuteOperation::Private::run(const QStringList &arguments)
if (!success) {
q->setError(UserDefinedError);
//TODO: pass errorString() through the wrapper */
- q->setErrorString(tr("Execution failed: Could not start: \"%1\"").arg(callstr));
+ q->setErrorString(tr("Execution failed: Could not start: \"%1\"(%2)").arg(callstr,
+ process->errorString()));
returnValue = false;
}
@@ -229,6 +232,12 @@ bool ElevatedExecuteOperation::Private::run(const QStringList &arguments)
} else {
q->setErrorString(customErrorMessage);
}
+
+ QByteArray standardErrorOutput = process->readAllStandardError();
+ // in error case it would be useful to see something in verbose output
+ if (!standardErrorOutput.isEmpty())
+ qWarning() << standardErrorOutput;
+
returnValue = false;
}
@@ -257,7 +266,10 @@ void ElevatedExecuteOperation::Private::readProcessOutput()
}
const QByteArray output = process->readAll();
if (!output.isEmpty()) {
- qDebug() << output;
+ if (q->error() == UserDefinedError)
+ qWarning() << output;
+ else
+ qDebug() << output;
emit q->outputTextChanged(QString::fromLocal8Bit(output));
}
}
diff --git a/src/libs/installer/environmentvariablesoperation.cpp b/src/libs/installer/environmentvariablesoperation.cpp
index de2eae899..192272a8d 100644
--- a/src/libs/installer/environmentvariablesoperation.cpp
+++ b/src/libs/installer/environmentvariablesoperation.cpp
@@ -137,10 +137,10 @@ UpdateOperation::Error undoSetting(const QString &regPath,
bool EnvironmentVariableOperation::performOperation()
{
QStringList args = arguments();
- if (args.count() != 2 && args.count() != 3) {
+ if (args.count() < 2 || args.count() > 4) {
setError(InvalidArguments);
setErrorString(tr("Invalid arguments in %0: %1 arguments given, %2 expected%3.")
- .arg(name()).arg(arguments().count()).arg(tr("2 or 3"), QLatin1String("")));
+ .arg(name()).arg(arguments().count()).arg(tr("2 to 4"), QLatin1String("")));
return false;
}
diff --git a/src/libs/installer/errors.h b/src/libs/installer/errors.h
index 7f5cc9071..18b8ead8f 100644
--- a/src/libs/installer/errors.h
+++ b/src/libs/installer/errors.h
@@ -54,7 +54,10 @@ class Error : public std::runtime_error
public:
explicit Error(const QString &message)
: std::runtime_error(message.toStdString())
- , m_message (message) { qDebug() << "create Error-Exception:" << message; }
+ , m_message (message)
+ {
+ qDebug() << "create Error-Exception:" << message;
+ }
virtual ~Error() throw() {}
QString message() const { return m_message; }
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/fileutils.cpp b/src/libs/installer/fileutils.cpp
index ab7ad6df4..9fb782fec 100644
--- a/src/libs/installer/fileutils.cpp
+++ b/src/libs/installer/fileutils.cpp
@@ -53,6 +53,12 @@
#include <errno.h>
+#ifdef Q_OS_UNIX
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#endif
+
using namespace QInstaller;
@@ -304,9 +310,9 @@ class RemoveDirectoryThread : public QThread
{
public:
explicit RemoveDirectoryThread(const QString &path, bool ignoreErrors = false, QObject *parent = 0)
- : QThread(parent),
- p(path),
- ignore(ignoreErrors)
+ : QThread(parent)
+ , p(path)
+ , ignore(ignoreErrors)
{
}
@@ -455,7 +461,7 @@ QString QInstaller::createTemporaryDirectory(const QString &templ)
if (!f.open())
throw Error(QObject::tr("Could not create temporary folder for template %1: %2").arg(t, f.errorString()));
const QString path = f.fileName() + QLatin1String("meta");
- qDebug() << "Creating meta data directory at" << path;
+ qDebug() << "\nCreating meta data directory at" << path;
QInstaller::mkpath(path);
return path;
@@ -469,6 +475,7 @@ QString QInstaller::createTemporaryDirectory(const QString &templ)
# endif
#include <windows.h>
+
QString QInstaller::getShortPathName(const QString &name)
{
if (name.isEmpty())
@@ -607,4 +614,31 @@ void QInstaller::setApplicationIcon(const QString &application, const QString &i
EndUpdateResourceW(updateRes, false);
}
+static quint64 symlinkSizeWin(const QString &path)
+{
+ WIN32_FILE_ATTRIBUTE_DATA fileAttributeData;
+ if (GetFileAttributesEx((wchar_t*)(path.utf16()), GetFileExInfoStandard, &fileAttributeData) == FALSE)
+ return quint64(0);
+
+ LARGE_INTEGER size;
+ size.LowPart = fileAttributeData.nFileSizeLow;
+ size.HighPart = fileAttributeData.nFileSizeHigh;
+ return quint64(size.QuadPart);
+}
+
#endif
+
+quint64 QInstaller::fileSize(const QFileInfo &info)
+{
+ if (!info.isSymLink())
+ return info.size();
+
+#ifndef Q_OS_WIN
+ struct stat buffer;
+ if (lstat(qPrintable(info.absoluteFilePath()), &buffer) != 0)
+ return quint64(0);
+ return quint64(buffer.st_size);
+#else
+ return symlinkSizeWin(info.absoluteFilePath());
+#endif
+}
diff --git a/src/libs/installer/fileutils.h b/src/libs/installer/fileutils.h
index 0450717cb..9bbcec72a 100644
--- a/src/libs/installer/fileutils.h
+++ b/src/libs/installer/fileutils.h
@@ -49,6 +49,7 @@
QT_BEGIN_NAMESPACE
class QByteArray;
+class QFileInfo;
class QIODevice;
class QUrl;
QT_END_NAMESPACE
@@ -120,6 +121,8 @@ private:
void INSTALLER_EXPORT mkdir(const QString &path);
void INSTALLER_EXPORT mkpath(const QString &path);
+ quint64 INSTALLER_EXPORT fileSize(const QFileInfo &info);
+
#ifdef Q_OS_WIN
QString INSTALLER_EXPORT getLongPathName(const QString &name);
QString INSTALLER_EXPORT getShortPathName(const QString &name);
diff --git a/src/libs/installer/fsengineclient.cpp b/src/libs/installer/fsengineclient.cpp
index c9aff560f..abc686fd9 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>
@@ -169,9 +171,9 @@ class FSEngineClientIterator : public QAbstractFileEngineIterator
{
public:
FSEngineClientIterator(QDir::Filters filters, const QStringList &nameFilters, const QStringList &files)
- : QAbstractFileEngineIterator(filters, nameFilters),
- entries(files),
- index(-1)
+ : QAbstractFileEngineIterator(filters, nameFilters)
+ , entries(files)
+ , index(-1)
{
}
@@ -588,13 +590,13 @@ class FSEngineClientHandler::Private
{
public:
Private()
- : mutex(QMutex::Recursive),
- port(0),
- startServerAsAdmin(false),
- serverStarted(false),
- serverStarting(false),
- active(false),
- thread(new StillAliveThread)
+ : mutex(QMutex::Recursive)
+ , port(0)
+ , startServerAsAdmin(false)
+ , serverStarted(false)
+ , serverStarting(false)
+ , active(false)
+ , thread(new StillAliveThread)
{
thread->moveToThread(thread);
}
@@ -753,7 +755,7 @@ void FSEngineClientHandler::setActive(bool active)
}
/*!
- Returns, wheter this FSEngineClientHandler is active or not.
+ Returns true when this FSEngineClientHandler is active.
*/
bool FSEngineClientHandler::isActive() const
{
@@ -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/fsengineserver.cpp b/src/libs/installer/fsengineserver.cpp
index 991681b95..326a2a02a 100644
--- a/src/libs/installer/fsengineserver.cpp
+++ b/src/libs/installer/fsengineserver.cpp
@@ -75,7 +75,7 @@ bool startDetached(const QString &program, const QStringList &args, const QStrin
const QString arguments = QInstaller::createCommandline(program, args);
const bool success = CreateProcess(0, (wchar_t*)arguments.utf16(),
- 0, 0, FALSE, CREATE_UNICODE_ENVIRONMENT | CREATE_NEW_CONSOLE,
+ 0, 0, false, CREATE_UNICODE_ENVIRONMENT | CREATE_NEW_CONSOLE,
0, (wchar_t*)workingDirectory.utf16(),
&startupInfo, &pinfo);
@@ -129,11 +129,11 @@ class FSEngineConnectionThread : public QThread
Q_OBJECT
public:
FSEngineConnectionThread(descriptor_t socketDescriptor, QObject *parent)
- : QThread(parent),
- descriptor(socketDescriptor),
- settings(0),
- process(0),
- signalReceiver(0)
+ : QThread(parent)
+ , descriptor(socketDescriptor)
+ , settings(0)
+ , process(0)
+ , signalReceiver(0)
{}
protected:
@@ -408,6 +408,8 @@ QByteArray FSEngineConnectionThread::handleCommand(const QString &command)
returnStream << process->readAll();
} else if (command == QLatin1String("QProcess::readAllStandardOutput")) {
returnStream << process->readAllStandardOutput();
+ } else if (command == QLatin1String("QProcess::readAllStandardError")) {
+ returnStream << process->readAllStandardError();
} else if (command == QLatin1String("QProcess::startDetached")) {
QString program;
QStringList arguments;
@@ -448,6 +450,8 @@ QByteArray FSEngineConnectionThread::handleCommand(const QString &command)
returnStream << process->waitForStarted(msecs);
} else if (command == QLatin1String("QProcess::workingDirectory")) {
returnStream << process->workingDirectory();
+ } else if (command == QLatin1String("QProcess::errorString")) {
+ returnStream << process->errorString();
} else if (command == QLatin1String("QProcess::write")) {
QByteArray byteArray;
receivedStream >> byteArray;
diff --git a/src/libs/installer/getrepositoriesmetainfojob.cpp b/src/libs/installer/getrepositoriesmetainfojob.cpp
index 996bf4692..c4564e781 100644
--- a/src/libs/installer/getrepositoriesmetainfojob.cpp
+++ b/src/libs/installer/getrepositoriesmetainfojob.cpp
@@ -42,8 +42,8 @@
#include "getrepositoriesmetainfojob.h"
#include "getrepositorymetainfojob.h"
+#include "productkeycheck.h"
#include "packagemanagercore_p.h"
-#include "qinstallerglobal.h"
#include <QtCore/QDebug>
@@ -53,12 +53,12 @@ using namespace QInstaller;
// -- GetRepositoriesMetaInfoJob
-GetRepositoriesMetaInfoJob::GetRepositoriesMetaInfoJob(PackageManagerCorePrivate *corePrivate)
- : KDJob(corePrivate),
- m_canceled(false),
- m_silentRetries(3),
- m_haveIgnoredError(false),
- m_corePrivate(corePrivate)
+GetRepositoriesMetaInfoJob::GetRepositoriesMetaInfoJob(PackageManagerCore *core)
+ : KDJob(core)
+ , m_canceled(false)
+ , m_silentRetries(3)
+ , m_haveIgnoredError(false)
+ , m_core(core)
{
setCapabilities(Cancelable);
}
@@ -119,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;
}
}
@@ -157,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 b0386c223..1c8d07525 100644
--- a/src/libs/installer/getrepositorymetainfojob.cpp
+++ b/src/libs/installer/getrepositorymetainfojob.cpp
@@ -44,22 +44,13 @@
#include "lib7z_facade.h"
#include "messageboxhandler.h"
#include "packagemanagercore_p.h"
-#include "qinstallerglobal.h"
#include "utils.h"
#include "kdupdaterfiledownloader.h"
#include "kdupdaterfiledownloaderfactory.h"
-#include <QtCore/QFile>
-#include <QtCore/QTimer>
-#include <QtCore/QUrl>
+#include <QTimer>
-#include <QMessageBox>
-
-#include <QtNetwork/QAuthenticator>
-
-#include <QtXml/QDomDocument>
-#include <QtXml/QDomElement>
using namespace KDUpdater;
using namespace QInstaller;
@@ -120,14 +111,14 @@ private:
// -- GetRepositoryMetaInfoJob
-GetRepositoryMetaInfoJob::GetRepositoryMetaInfoJob(PackageManagerCorePrivate *corePrivate, QObject *parent)
- : KDJob(parent),
- m_canceled(false),
- m_silentRetries(4),
- m_retriesLeft(m_silentRetries),
- m_downloader(0),
- m_waitForDone(false),
- m_corePrivate(corePrivate)
+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_core(core)
{
setCapabilities(Cancelable);
}
@@ -276,7 +267,10 @@ void GetRepositoryMetaInfoJob::updatesXmlDownloadFinished()
QString err;
QDomDocument doc;
- if (!doc.setContent(&updatesFile, &err)) {
+ const bool success = doc.setContent(&updatesFile, &err);
+ updatesFile.close();
+
+ if (!success) {
const QString msg = tr("Could not fetch a valid version of Updates.xml from repository: %1. "
"Error: %2").arg(m_repository.url().toString(), err);
@@ -337,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;
}
}
}
@@ -379,7 +372,7 @@ void GetRepositoryMetaInfoJob::updatesXmlDownloadError(const QString &err)
{
if (m_retriesLeft <= 0) {
const QString msg = tr("Could not fetch Updates.xml from repository: %1. Error: %2")
- .arg(m_repository.url().toString(), err);
+ .arg(m_repository.displayname(), err);
QMessageBox::StandardButtons buttons = QMessageBox::Retry | QMessageBox::Cancel;
const QMessageBox::StandardButton b =
@@ -544,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/globals.cpp b/src/libs/installer/globals.cpp
new file mode 100644
index 000000000..f0910372d
--- /dev/null
+++ b/src/libs/installer/globals.cpp
@@ -0,0 +1,47 @@
+/**************************************************************************
+**
+** 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$
+**
+**************************************************************************/
+#include "globals.h"
+
+Q_GLOBAL_STATIC_WITH_ARGS(QRegExp, staticCommaRegExp, (QLatin1String("\\b(,|, )\\b")));
+QRegExp QInstaller::commaRegExp()
+{
+ return *staticCommaRegExp();
+}
diff --git a/src/libs/installer/globals.h b/src/libs/installer/globals.h
new file mode 100644
index 000000000..858c856d5
--- /dev/null
+++ b/src/libs/installer/globals.h
@@ -0,0 +1,54 @@
+/**************************************************************************
+**
+** 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 GLOBALS_H
+#define GLOBALS_H
+
+#include "installer_global.h"
+
+#include <QRegExp>
+
+namespace QInstaller {
+
+QRegExp INSTALLER_EXPORT commaRegExp();
+
+} // QInstaller
+
+#endif // GLOBALS_H
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/init.cpp b/src/libs/installer/init.cpp
index 40c396ab4..a8a7f54d8 100644
--- a/src/libs/installer/init.cpp
+++ b/src/libs/installer/init.cpp
@@ -62,18 +62,18 @@
// QtSDK specific
#include "qtpatchoperation.h"
+#include "consumeoutputoperation.h"
#include "setdemospathonqtoperation.h"
#include "setexamplespathonqtoperation.h"
#include "setpluginpathonqtcoreoperation.h"
#include "setimportspathonqtcoreoperation.h"
#include "setpathonqtcoreoperation.h"
-#include "registerqtvqnxoperation.h"
+#include "registerqtincreatorqnxoperation.h"
#include "setqtcreatorvalueoperation.h"
#include "addqtcreatorarrayvalueoperation.h"
#include "registertoolchainoperation.h"
#include "registerdefaultdebuggeroperation.h"
-
#ifdef Q_OS_MAC
# include "macreplaceinstallnamesoperation.h"
#endif // Q_OS_MAC
@@ -83,74 +83,63 @@
#include "kdupdaterupdateoperationfactory.h"
#include "kdupdaterfiledownloaderfactory.h"
-#include <unix/C/7zCrc.h>
+#include "7zCrc.h"
#include <QtPlugin>
#include <iostream>
namespace NArchive {
-namespace NBz2 { void registerArcBZip2(); }
-namespace NGz { void registerArcGZip(); }
-namespace NLzma { namespace NLzmaAr { void registerArcLzma(); } }
-namespace NLzma { namespace NLzma86Ar { void registerArcLzma86(); } }
-namespace NSplit { void registerArcSplit(); }
-namespace NXz { void registerArcxz(); }
-namespace NZ { void registerArcZ(); }
+ namespace NXz {
+ void registerArcxz();
+ }
+ namespace NSplit {
+ void registerArcSplit();
+ }
+ namespace NLzma {
+ namespace NLzmaAr {
+ void registerArcLzma();
+ }
+ namespace NLzma86Ar {
+ void registerArcLzma86();
+ }
+ }
}
void registerArc7z();
-void registerArcCab();
-void registerArcTar();
-void registerArcZip();
-void registerCodecBCJ2();
-void registerCodecBCJ();
void registerCodecBCJ();
-void registerCodecByteSwap();
-void registerCodecBZip2();
-void registerCodecCopy();
-void registerCodecDeflate64();
-void registerCodecDeflate();
-void registerCodecDelta();
-void registerCodecLZMA2();
+void registerCodecBCJ2();
+
void registerCodecLZMA();
-void registerCodecPPMD();
-void registerCodec7zAES();
+void registerCodecLZMA2();
+
+void registerCodecDelta();
+void registerCodecBranch();
+void registerCodecByteSwap();
-using namespace NArchive;
using namespace KDUpdater;
using namespace QInstaller;
static void initArchives()
{
- NBz2::registerArcBZip2();
- NGz::registerArcGZip();
- NLzma::NLzmaAr::registerArcLzma();
- NLzma::NLzma86Ar::registerArcLzma86();
- NSplit::registerArcSplit();
- NXz::registerArcxz();
- NZ::registerArcZ();
+ CrcGenerateTable();
+
registerArc7z();
- registerArcCab();
- registerArcTar();
- registerArcZip();
- registerCodecBCJ2();
- registerCodecBCJ();
registerCodecBCJ();
- registerCodecByteSwap();
- registerCodecBZip2();
- registerCodecCopy();
- registerCodecDeflate64();
- registerCodecDeflate();
- registerCodecDelta();
- registerCodecLZMA2();
+ registerCodecBCJ2();
registerCodecLZMA();
- registerCodecPPMD();
- registerCodec7zAES();
+ registerCodecLZMA2();
- CrcGenerateTable();
+ registerCodecDelta();
+ registerCodecBranch();
+ registerCodecByteSwap();
+
+ NArchive::NXz::registerArcxz();
+ NArchive::NSplit::registerArcSplit();
+ NArchive::NLzma::NLzmaAr::registerArcLzma();
+ NArchive::NLzma::NLzma86Ar::registerArcLzma86();
}
#if defined(QT_STATIC)
@@ -205,8 +194,9 @@ void messageHandler(QtMsgType type, const QMessageLogContext &context, const QSt
{
QByteArray ba = trimAndPrepend(type, msg.toLocal8Bit());
if (type != QtDebugMsg) {
- ba += QByteArray(" (") + context.file + QByteArray(":").append(context.line) + QByteArray(", ")
- + context.function + QByteArray(")");
+ ba += QString(QStringLiteral(" (%1:%2, %3)")).arg(
+ QString::fromLatin1(context.file)).arg(context.line).arg(
+ QString::fromLatin1(context.function)).toLocal8Bit();
}
#endif
@@ -229,8 +219,8 @@ void messageHandler(QtMsgType type, const QMessageLogContext &context, const QSt
void QInstaller::init()
{
-#if defined(QT_STATIC)
::initArchives();
+#if defined(QT_STATIC)
::initResources();
#endif
@@ -254,6 +244,7 @@ void QInstaller::init()
factory.registerUpdateOperation<MinimumProgressOperation>(QLatin1String("MinimumProgress"));
factory.registerUpdateOperation<LicenseOperation>(QLatin1String("License"));
factory.registerUpdateOperation<ApplyProductKeyOperation>(QLatin1String("ApplyProductKey"));
+ factory.registerUpdateOperation<ConsumeOutputOperation>(QLatin1String("ConsumeOutput"));
// QtSDK specific
factory.registerUpdateOperation<RegisterQtInCreatorQNXOperation>(QLatin1String("RegisterQtInCreatorQNX"));
diff --git a/src/libs/installer/installer.pro b/src/libs/installer/installer.pro
index 3308876fb..653b65d6f 100644
--- a/src/libs/installer/installer.pro
+++ b/src/libs/installer/installer.pro
@@ -14,6 +14,10 @@ include(../../../installerfw.pri)
# your files if needed
HEADERS += productkeycheck.h
!isEmpty(PRODUCTKEYCHECK_PRI_FILE) {
+ # use undocumented no_batch config which disable the implicit rules on msvc compilers
+ # this fixes the problem that same cpp files in different directories are overwritting
+ # each other
+ CONFIG += no_batch
include($$PRODUCTKEYCHECK_PRI_FILE)
} else {
SOURCES += productkeycheck.cpp
@@ -44,12 +48,14 @@ HEADERS += packagemanagercore.h \
utils.h \
errors.h \
component.h \
+ scriptengine.h \
componentmodel.h \
qinstallerglobal.h \
qtpatch.h \
persistentsettings.h \
projectexplorer_export.h \
qtpatchoperation.h \
+ consumeoutputoperation.h \
setpathonqtcoreoperation.h \
setdemospathonqtoperation.h \
setexamplespathonqtoperation.h \
@@ -58,7 +64,6 @@ HEADERS += packagemanagercore.h \
replaceoperation.h \
linereplaceoperation.h \
registertoolchainoperation.h \
- registerqtvqnxoperation.h \
setqtcreatorvalueoperation.h \
addqtcreatorarrayvalueoperation.h \
copydirectoryoperation.h \
@@ -104,7 +109,10 @@ HEADERS += packagemanagercore.h \
link.h \
createlinkoperation.h \
packagemanagercoredata.h \
- applyproductkeyoperation.h
+ registerqtincreatorqnxoperation.h \
+ applyproductkeyoperation.h \
+ globals.h \
+ graph.h
SOURCES += packagemanagercore.cpp \
packagemanagercore_p.cpp \
@@ -117,10 +125,12 @@ HEADERS += packagemanagercore.h \
fileutils.cpp \
utils.cpp \
component.cpp \
+ scriptengine.cpp \
componentmodel.cpp \
qtpatch.cpp \
persistentsettings.cpp \
qtpatchoperation.cpp \
+ consumeoutputoperation.cpp \
setpathonqtcoreoperation.cpp \
setdemospathonqtoperation.cpp \
setexamplespathonqtoperation.cpp \
@@ -129,7 +139,6 @@ HEADERS += packagemanagercore.h \
replaceoperation.cpp \
linereplaceoperation.cpp \
registertoolchainoperation.cpp \
- registerqtvqnxoperation.cpp \
setqtcreatorvalueoperation.cpp \
addqtcreatorarrayvalueoperation.cpp \
copydirectoryoperation.cpp \
@@ -173,7 +182,9 @@ HEADERS += packagemanagercore.h \
link.cpp \
createlinkoperation.cpp \
packagemanagercoredata.cpp \
- applyproductkeyoperation.cpp
+ registerqtincreatorqnxoperation.cpp \
+ applyproductkeyoperation.cpp \
+ globals.cpp
RESOURCES += resources/patch_file_lists.qrc \
resources/installer.qrc
@@ -189,7 +200,7 @@ unix:!macx:SOURCES += adminauthorization_x11.cpp
LIBS += -l7z
win32 {
- SOURCES += adminauthorization_win.cpp
+ SOURCES += adminauthorization_win.cpp sysinfo_win.cpp
LIBS += -loleaut32 -luser32 # 7zip
LIBS += -ladvapi32 -lpsapi # kdtools
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/lib7z_facade.cpp b/src/libs/installer/lib7z_facade.cpp
index 3695c0038..a818e9a61 100644
--- a/src/libs/installer/lib7z_facade.cpp
+++ b/src/libs/installer/lib7z_facade.cpp
@@ -1,3 +1,43 @@
+/**************************************************************************
+**
+** Copyright (C) 2012-2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Installer Framework.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+**************************************************************************/
#include "lib7z_facade.h"
#include "errors.h"
@@ -17,12 +57,13 @@
#include "Windows/PropVariant.h"
#include "Windows/PropVariantConversions.h"
-#include <QtCore/QDir>
-#include <QtCore/QFileInfo>
-#include <QtCore/QIODevice>
+#include <QDir>
+#include <QFileInfo>
+#include <QIODevice>
#include <QtCore/QMutexLocker>
-#include <QtCore/QPointer>
-#include <QtCore/QTemporaryFile>
+#include <QPointer>
+#include <QTemporaryFile>
+#include <QReadWriteLock>
#ifdef _MSC_VER
#pragma warning(disable:4297)
@@ -99,9 +140,9 @@ namespace {
*/
struct DirectoryGuard {
explicit DirectoryGuard(const QString &path)
- : m_path(path),
- m_created(false),
- m_released(false)
+ : m_path(path)
+ , m_created(false)
+ , m_released(false)
{
m_path.replace(QLatin1Char('\\'), QLatin1Char('/'));
}
@@ -293,40 +334,39 @@ namespace Lib7z {
class QIODeviceSequentialOutStream : public ISequentialOutStream, public CMyUnknownImp
{
public:
- enum DestructorBehavior{
- CloseAndDeleteIODeviceAtDestructor,
- KeepIODeviceAtItIsAtDestructor
+ enum Behavior {
+ KeepDeviceUntouched,
+ CloseAndDeleteDevice
};
MY_UNKNOWN_IMP
- explicit QIODeviceSequentialOutStream(QIODevice* device, DestructorBehavior behavior);
+ explicit QIODeviceSequentialOutStream(QIODevice* device, Behavior behavior);
~QIODeviceSequentialOutStream();
QString errorString() const;
/* reimp */ STDMETHOD(Write)(const void* data, UInt32 size, UInt32* processedSize);
private:
- QPointer<QIODevice> m_device;
- const DestructorBehavior m_destructorBehavior;
+ Behavior m_behavior;
QString m_errorString;
+ QPointer<QIODevice> m_device;
};
-QIODeviceSequentialOutStream::QIODeviceSequentialOutStream(QIODevice* device, DestructorBehavior behavior)
+QIODeviceSequentialOutStream::QIODeviceSequentialOutStream(QIODevice* device, Behavior behavior)
: ISequentialOutStream()
, CMyUnknownImp()
+ , m_behavior(behavior)
, m_device(device)
- , m_destructorBehavior(behavior)
{
Q_ASSERT(m_device);
- if (!m_device->open(QIODevice::WriteOnly)) {
+ if (!device->isOpen() && !m_device->open(QIODevice::WriteOnly))
m_errorString = m_device->errorString();
- }
}
QIODeviceSequentialOutStream::~QIODeviceSequentialOutStream()
{
- if (m_destructorBehavior == CloseAndDeleteIODeviceAtDestructor) {
+ if (m_behavior == CloseAndDeleteDevice) {
m_device->close();
delete m_device;
m_device = 0;
@@ -724,12 +764,12 @@ class Lib7z::ExtractCallbackImpl : public IArchiveExtractCallback, public CMyUnk
public:
MY_UNKNOWN_IMP
explicit ExtractCallbackImpl(ExtractCallback* qq)
- : q(qq),
- currentIndex(0),
- arc(0),
- total(0),
- completed(0),
- device(0)
+ : q(qq)
+ , currentIndex(0)
+ , arc(0)
+ , total(0)
+ , completed(0)
+ , device(0)
{
}
@@ -751,7 +791,7 @@ public:
*outStream = 0;
if (device != 0) {
QIODeviceSequentialOutStream *qOutStream = new QIODeviceSequentialOutStream(device,
- QIODeviceSequentialOutStream::KeepIODeviceAtItIsAtDestructor);
+ QIODeviceSequentialOutStream::KeepDeviceUntouched);
if (!qOutStream->errorString().isEmpty()) {
Lib7z::setLastError(qOutStream->errorString());
return E_FAIL;
@@ -800,7 +840,7 @@ public:
}
#endif
QIODeviceSequentialOutStream *qOutStream = new QIODeviceSequentialOutStream(
- new QFile(fi.absoluteFilePath()), QIODeviceSequentialOutStream::CloseAndDeleteIODeviceAtDestructor);
+ new QFile(fi.absoluteFilePath()), QIODeviceSequentialOutStream::CloseAndDeleteDevice);
if (!qOutStream->errorString().isEmpty()) {
Lib7z::setLastError(QObject::tr("Could not open file: %1 (%2)").arg(
fi.absoluteFilePath(), qOutStream->errorString()));
@@ -1172,9 +1212,9 @@ class ExtractItemJob::Private
{
public:
Private(ExtractItemJob* qq)
- : q(qq),
- target(0),
- callback(new ExtractCallbackJobImpl(q))
+ : q(qq)
+ , target(0)
+ , callback(new ExtractCallbackJobImpl(q))
{
}
@@ -1361,7 +1401,8 @@ void Lib7z::createArchive(QIODevice* archive, const QStringList &sourcePaths, Up
}
}
-void Lib7z::extractArchive(QIODevice* archive, const File& item, QIODevice* target, ExtractCallback* callback)
+void Lib7z::extractFileFromArchive(QIODevice* archive, const File& item, QIODevice* target,
+ ExtractCallback* callback)
{
assert(archive);
assert(target);
@@ -1398,20 +1439,22 @@ void Lib7z::extractArchive(QIODevice* archive, const File& item, QIODevice* targ
assert(item.path == UString2QString(s).replace(QLatin1Char('\\'), QLatin1Char('/')));
callback->setTarget(target);
- const LONG extractResult = parchive->Extract(&itemIdx, 1, /*testmode=*/1, callback->impl());
+ const LONG extractResult = parchive->Extract(&itemIdx, 1, /*testmode=*/0, callback->impl());
if (extractResult != S_OK)
throw SevenZipException(errorMessageFrom7zResult(extractResult));
} catch (const char *err) {
throw SevenZipException(err);
+ } catch (const Lib7z::SevenZipException& e) {
+ throw e;
} catch (...) {
throw SevenZipException(QObject::tr("Unknown exception caught (%1)")
.arg(QString::fromLatin1(Q_FUNC_INFO)));
}
}
-void Lib7z::extractArchive(QIODevice* archive, const File& item, const QString &targetDirectory,
+void Lib7z::extractFileFromArchive(QIODevice* archive, const File& item, const QString &targetDirectory,
ExtractCallback* callback)
{
assert(archive);
@@ -1428,10 +1471,10 @@ void Lib7z::extractArchive(QIODevice* archive, const File& item, const QString &
throw SevenZipException(QObject::tr("Could not create output file for writing: %1")
.arg(fi.absoluteFilePath()));
}
+ callback->setTarget(&out);
+ extractFileFromArchive(archive, item, &out, callback);
if (item.permissions)
out.setPermissions(item.permissions);
- callback->setTarget(&out);
- extractArchive(archive, item, &out, callback);
outDir.release();
}
@@ -1518,9 +1561,9 @@ void ExtractItemJob::doStart()
if (!d->archive)
throw SevenZipException(tr("Could not list archive: QIODevice not set or already destroyed."));
if (d->target)
- extractArchive(d->archive, d->item, d->target, d->callback);
+ extractFileFromArchive(d->archive, d->item, d->target, d->callback);
else if (!d->item.path.isEmpty())
- extractArchive(d->archive, d->item, d->targetDirectory, d->callback);
+ extractFileFromArchive(d->archive, d->item, d->targetDirectory, d->callback);
else
extractArchive(d->archive, d->targetDirectory, d->callback);
} catch (const SevenZipException& e) {
diff --git a/src/libs/installer/lib7z_facade.h b/src/libs/installer/lib7z_facade.h
index 515d63bba..a783fbd44 100644
--- a/src/libs/installer/lib7z_facade.h
+++ b/src/libs/installer/lib7z_facade.h
@@ -1,17 +1,56 @@
+/**************************************************************************
+**
+** Copyright (C) 2012-2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Installer Framework.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+**************************************************************************/
#ifndef LIB7Z_FACADE_H
#define LIB7Z_FACADE_H
#include "installer_global.h"
+#include <QCoreApplication>
#include <QDateTime>
-#include <QtCore/QCoreApplication>
-#include <QtCore/QFile>
-#include <QtCore/QPoint>
-#include <QtCore/QRunnable>
-#include <QtCore/QString>
-#include <QtCore/QVector>
-#include <QtCore/QVariant>
-#include <QtCore/QReadWriteLock>
+#include <QFile>
+#include <QPoint>
+#include <QRunnable>
+#include <QString>
+#include <QVariant>
+#include <QVector>
#include "Common/MyWindows.h"
@@ -46,7 +85,6 @@ namespace Lib7z {
QFile::Permissions permissions;
QString path;
- QString name;
QDateTime mtime;
quint64 uncompressedSize;
quint64 compressedSize;
@@ -112,20 +150,32 @@ namespace Lib7z {
void deviceDestroyed(QObject*);
};
- /*
- * @throws Lib7z::SevenZipException
- */
- void INSTALLER_EXPORT extractArchive( QIODevice* archive, const File& item, QIODevice* out, ExtractCallback* callback=0 );
+ /*!
+ Extracts the given File \a file from \a archive into output device \a out using the provided extract
+ callback \a callback.
- /*
- * @throws Lib7z::SevenZipException
- */
- void INSTALLER_EXPORT extractArchive( QIODevice* archive, const File& item, const QString& targetDirectory, ExtractCallback* callback=0 );
+ Throws Lib7z::SevenZipException on error.
+ */
+ void INSTALLER_EXPORT extractFileFromArchive(QIODevice* archive, const File& item, QIODevice* out,
+ ExtractCallback* callback=0 );
- /*
- * @throws Lib7z::SevenZipException
- */
- void INSTALLER_EXPORT extractArchive( QIODevice* archive, const QString& targetDirectory, ExtractCallback* callback=0 );
+ /*!
+ Extracts the given File \a file from \a archive into target directory \a targetDirectory using the
+ provided extract callback \a callback. The output filename is deduced from the \a file path name.
+
+ Throws Lib7z::SevenZipException on error.
+ */
+ void INSTALLER_EXPORT extractFileFromArchive(QIODevice* archive, const File& item,
+ const QString& targetDirectory, ExtractCallback* callback = 0);
+
+ /*!
+ Extracts the given \a archive content into target directory \a targetDirectory using the
+ provided extract callback \a callback. The output filenames are deduced from the \a archive content.
+
+ Throws Lib7z::SevenZipException on error.
+ */
+ void INSTALLER_EXPORT extractArchive(QIODevice* archive, const QString& targetDirectory,
+ ExtractCallback* callback = 0);
/*
* @thows Lib7z::SevenZipException
diff --git a/src/libs/installer/link.h b/src/libs/installer/link.h
index fc8d8fee3..e359c8f91 100644
--- a/src/libs/installer/link.h
+++ b/src/libs/installer/link.h
@@ -47,7 +47,7 @@
class Link
{
public:
- Link(const QString &path);
+ explicit Link(const QString &path);
static Link create(const QString &link, const QString &targetPath);
QString targetPath() const;
bool targetExists();
diff --git a/src/libs/installer/macreplaceinstallnamesoperation.cpp b/src/libs/installer/macreplaceinstallnamesoperation.cpp
index a79072481..fa5e6139a 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/macreplaceinstallnamesoperation.h b/src/libs/installer/macreplaceinstallnamesoperation.h
index 635f60054..f4b76de6d 100644
--- a/src/libs/installer/macreplaceinstallnamesoperation.h
+++ b/src/libs/installer/macreplaceinstallnamesoperation.h
@@ -39,8 +39,8 @@
**
**************************************************************************/
-#ifndef MACREPLACEINSTALLNAMEOPERATION_H
-#define MACREPLACEINSTALLNAMEOPERATION_H
+#ifndef MACREPLACEINSTALLNAMESOPERATION_H
+#define MACREPLACEINSTALLNAMESOPERATION_H
#include "qinstallerglobal.h"
@@ -85,4 +85,4 @@ private:
} // namespace QInstaller
-#endif // MACREPLACEINSTALLNAMEOPERATION_H
+#endif // MACREPLACEINSTALLNAMESOPERATION_H
diff --git a/src/libs/installer/messageboxhandler.cpp b/src/libs/installer/messageboxhandler.cpp
index cb9a845ff..69fc62570 100644
--- a/src/libs/installer/messageboxhandler.cpp
+++ b/src/libs/installer/messageboxhandler.cpp
@@ -47,76 +47,90 @@
#include <QDialogButtonBox>
#include <QPushButton>
-#include <QtScript/QScriptEngine>
-#include <QtScript/QScriptValue>
+/*!
+ \qmltype QMessageBox
+ \inqmlmodule scripting
-QScriptValue QInstaller::registerMessageBox(QScriptEngine *scriptEngine)
-{
- // register QMessageBox::StandardButton enum in the script connection
- QScriptValue messageBox = scriptEngine->newQObject(MessageBoxHandler::instance());
- messageBox.setProperty(QLatin1String("Ok"),
- scriptEngine->newVariant(static_cast<int>(QMessageBox::Yes)));
- messageBox.setProperty(QLatin1String("Open"),
- scriptEngine->newVariant(static_cast<int>(QMessageBox::Open)));
- messageBox.setProperty(QLatin1String("Save"),
- scriptEngine->newVariant(static_cast<int>(QMessageBox::Save)));
- messageBox.setProperty(QLatin1String("Cancel"),
- scriptEngine->newVariant(static_cast<int>(QMessageBox::Cancel)));
- messageBox.setProperty(QLatin1String("Close"),
- scriptEngine->newVariant(static_cast<int>(QMessageBox::Close)));
- messageBox.setProperty(QLatin1String("Discard"),
- scriptEngine->newVariant(static_cast<int>(QMessageBox::Discard)));
- messageBox.setProperty(QLatin1String("Apply"),
- scriptEngine->newVariant(static_cast<int>(QMessageBox::Apply)));
- messageBox.setProperty(QLatin1String("Reset"),
- scriptEngine->newVariant(static_cast<int>(QMessageBox::Reset)));
- messageBox.setProperty(QLatin1String("RestoreDefaults"),
- scriptEngine->newVariant(static_cast<int>(QMessageBox::RestoreDefaults)));
- messageBox.setProperty(QLatin1String("Help"),
- scriptEngine->newVariant(static_cast<int>(QMessageBox::Help)));
- messageBox.setProperty(QLatin1String("SaveAll"),
- scriptEngine->newVariant(static_cast<int>(QMessageBox::SaveAll)));
- messageBox.setProperty(QLatin1String("Yes"),
- scriptEngine->newVariant(static_cast<int>(QMessageBox::Yes)));
- messageBox.setProperty(QLatin1String("YesToAll"),
- scriptEngine->newVariant(static_cast<int>(QMessageBox::YesToAll)));
- messageBox.setProperty(QLatin1String("No"),
- scriptEngine->newVariant(static_cast<int>(QMessageBox::No)));
- messageBox.setProperty(QLatin1String("NoToAll"),
- scriptEngine->newVariant(static_cast<int>(QMessageBox::NoToAll)));
- messageBox.setProperty(QLatin1String("Abort"),
- scriptEngine->newVariant(static_cast<int>(QMessageBox::Abort)));
- messageBox.setProperty(QLatin1String("Retry"),
- scriptEngine->newVariant(static_cast<int>(QMessageBox::Retry)));
- messageBox.setProperty(QLatin1String("Ignore"),
- scriptEngine->newVariant(static_cast<int>(QMessageBox::Ignore)));
- messageBox.setProperty(QLatin1String("NoButton"),
- scriptEngine->newVariant(static_cast<int>(QMessageBox::NoButton)));
- scriptEngine->globalObject().setProperty(QLatin1String("QMessageBox"), messageBox);
-
- return messageBox;
-}
+ \brief The QMessageBox type provides a modal dialog for informing the
+ user or asking the user a question and receiving an answer.
-using namespace QInstaller;
-template <typename T>
-static QList<T> reversed(const QList<T> &list)
-{
- qFatal("This seems to be broken, check this!!!!");
- // TODO: Figure out what should happen here. See setDefaultAction(...).
-#if 1
- // Note: This does not what the function name implies???
- QList<T> res = list;
- qCopyBackward(list.begin(), list.end(), res.end());
- return res;
-#else
- // Note: This does what the function name implies, but we need to check if this is what we want.
- QList<T> res = list;
- std::reverse(res.begin(), res.end());
- return res;
-#endif
-}
+ \code
+ var result = QMessageBox.question("quit.question", "Installer", "Do you want to quit the installer?",
+ QMessageBox.Yes | QMessageBox.No);
+ if (result == QMessageBox.Yes) {
+ // ...
+ }
+ \endcode
+
+ \section2 Buttons
+
+ QMessageBox defines a list of common buttons:
+ \list
+ \li QMessageBox.Ok
+ \li QMessageBox.Open
+ \li QMessageBox.Save
+ \li QMessageBox.Cancel
+ \li QMessageBox.Close
+ \li QMessageBox.Discard
+ \li QMessageBox.Apply
+ \li QMessageBox.Reset
+ \li QMessageBox.RestoreDefaults
+ \li QMessageBox.Help
+ \li QMessageBox.SaveAll
+ \li QMessageBox.Yes
+ \li QMessageBox.YesToAll
+ \li QMessageBox.No
+ \li QMessageBox.NoToAll
+ \li QMessageBox.Abort
+ \li QMessageBox.Retry
+ \li QMessageBox.Ignore
+ \li QMessageBox.NoButton
+ \endlist
+
+ \section2 Scripted Installations
+
+ Sometimes it is useful to automatically close message boxes, for example during a scripted
+ installation. This can be achieved by calling
+ Installer::setMessageBoxAutomaticAnswer, Installer::autoAcceptMessageBoxes,
+ Installer::autoRejectMessageBoxes. The \c identifier argument in the method calls
+ allows to identify specific message boxes for this purpose.
+ */
+
+
+/*!
+ \qmlmethod Button QMessageBox::critical(string identifier, string title, string text,
+ Buttons buttons = QMessageBox.Ok, Button button
+ = QMessageBox.NoButton)
+
+ Opens a critical message box with the given \a title and \a text.
+*/
+
+/*!
+ \qmlmethod Button QMessageBox::information(string identifier, string title, string text,
+ Buttons buttons = QMessageBox.Ok, Button button
+ = QMessageBox.NoButton)
+
+ Opens an information message box with the given \a title and \a text.
+*/
+
+/*!
+ \qmlmethod Button QMessageBox::question(string identifier, string title, string text,
+ Buttons buttons = QMessageBox.Yes | QMessageBox.No, Button button
+ = QMessageBox.NoButton)
+
+ Opens a question message box with the given \a title and \a text.
+*/
+
+/*!
+ \qmlmethod Button QMessageBox::warning(string identifier, string title, string text,
+ Buttons buttons = QMessageBox.Ok, Button button
+ = QMessageBox.NoButton)
+
+ Opens a warning message box with the given \a title and \a text.
+*/
+using namespace QInstaller;
// -- MessageBoxHandler
@@ -151,6 +165,19 @@ QWidget *MessageBoxHandler::currentBestSuitParent()
return qApp->activeWindow();
}
+QList<QMessageBox::Button> MessageBoxHandler::orderedButtons()
+{
+ static QList<QMessageBox::Button> buttons;
+ if (!buttons.isEmpty())
+ return buttons;
+ buttons << QMessageBox::YesToAll << QMessageBox::Yes << QMessageBox::Ok << QMessageBox::Apply
+ << QMessageBox::SaveAll << QMessageBox::Save <<QMessageBox::Retry << QMessageBox::Ignore
+ << QMessageBox::Help << QMessageBox::RestoreDefaults << QMessageBox::Reset << QMessageBox::Open
+ << QMessageBox::Cancel << QMessageBox::Close << QMessageBox::Abort << QMessageBox::Discard
+ << QMessageBox::No << QMessageBox::NoToAll;
+ return buttons;
+}
+
void MessageBoxHandler::setDefaultAction(DefaultAction defaultAction)
{
if (m_defaultAction == defaultAction)
@@ -159,17 +186,13 @@ void MessageBoxHandler::setDefaultAction(DefaultAction defaultAction)
m_buttonOrder.clear();
if (m_defaultAction != AskUser) {
- m_buttonOrder << QMessageBox::YesToAll << QMessageBox::Yes << QMessageBox::Ok << QMessageBox::Apply
- << QMessageBox::SaveAll << QMessageBox::Save <<QMessageBox::Retry << QMessageBox::Ignore
- << QMessageBox::Help << QMessageBox::RestoreDefaults << QMessageBox::Reset << QMessageBox::Open
- << QMessageBox::Cancel << QMessageBox::Close << QMessageBox::Abort << QMessageBox::Discard
- << QMessageBox::No << QMessageBox::NoToAll;
+ m_buttonOrder = orderedButtons();
}
if (m_defaultAction == Reject) {
// If we want to reject everything, we need the lowest button. For example, if Cancel is existing it
// could use Cancel, but if Close is existing it will use Close.
- m_buttonOrder = reversed(m_buttonOrder);
+ std::reverse(m_buttonOrder.begin(), m_buttonOrder.end());
}
}
diff --git a/src/libs/installer/messageboxhandler.h b/src/libs/installer/messageboxhandler.h
index b0b0fb6f2..bc3edce3b 100644
--- a/src/libs/installer/messageboxhandler.h
+++ b/src/libs/installer/messageboxhandler.h
@@ -51,8 +51,6 @@
namespace QInstaller {
-QScriptValue registerMessageBox(QScriptEngine *scriptEngine);
-
class INSTALLER_EXPORT MessageBoxHandler : public QObject, private QScriptable
{
Q_OBJECT
@@ -110,6 +108,8 @@ public:
QMessageBox::StandardButtons buttons = QMessageBox::Ok,
QMessageBox::StandardButton button = QMessageBox::NoButton) const;
+ static QList<QMessageBox::Button> orderedButtons();
+
private Q_SLOTS:
//this removes the slot from the script area
virtual void deleteLater() {
diff --git a/src/libs/installer/packagemanagercore.cpp b/src/libs/installer/packagemanagercore.cpp
index cb957f9aa..007354f5d 100644
--- a/src/libs/installer/packagemanagercore.cpp
+++ b/src/libs/installer/packagemanagercore.cpp
@@ -39,6 +39,7 @@
**
**************************************************************************/
#include "packagemanagercore.h"
+#include "packagemanagercore_p.h"
#include "adminauthorization.h"
#include "binaryformat.h"
@@ -47,12 +48,11 @@
#include "downloadarchivesjob.h"
#include "errors.h"
#include "fsengineclient.h"
+#include "globals.h"
#include "getrepositoriesmetainfojob.h"
#include "messageboxhandler.h"
-#include "packagemanagercore_p.h"
#include "packagemanagerproxyfactory.h"
#include "progresscoordinator.h"
-#include "qinstallerglobal.h"
#include "qprocesswrapper.h"
#include "qsettingswrapper.h"
#include "settings.h"
@@ -71,9 +71,6 @@
#include <QDesktopServices>
#include <QFileDialog>
-#include <QtScript/QScriptEngine>
-#include <QtScript/QScriptContext>
-
#include "kdsysinfo.h"
#include "kdupdaterupdateoperationfactory.h"
@@ -85,30 +82,267 @@
# include <QStandardPaths>
#endif
+/*!
+ \qmltype QInstaller
+ \inqmlmodule scripting
+
+ \brief Provides access to the installer from Qt Script.
+
+ Use the \c installer object in the global namespace to access functionality of the installer.
+
+ \section2 Wizard Pages
+
+ The installer has various pre-defined pages that can be used to for example insert pages
+ in a certain place:
+ \list
+ \li QInstaller.Introduction
+ \li QInstaller.TargetDirectory
+ \li QInstaller.ComponentSelection
+ \li QInstaller.LicenseCheck
+ \li QInstaller.StartMenuSelection
+ \li QInstaller.ReadyForInstallation
+ \li QInstaller.PerformInstallation
+ \li QInstaller.InstallationFinished
+ \li QInstaller.End
+ \endlist
+*/
+
+
+/*!
+ \qmlproperty enumeration QInstaller::status
+
+ Status of the installer.
+
+ Possible values are:
+ \list
+ \li QInstaller.Success (deprecated: QInstaller.InstallerSucceeded)
+ \li QInstaller.Failure (deprecated: QInstaller.InstallerFailed)
+ \li QInstaller.Running (deprecated: QInstaller.InstallerFailed)
+ \li QInstaller.Canceled (deprecated: QInstaller.CanceledByUser)
+ \li deprecated: QInstaller.InstallerUnfinished
+ \endlist
+*/
+
+/*!
+ \qmlsignal QInstaller::aboutCalculateComponentsToInstall()
+
+ Emitted before the ordered list of components to install is calculated.
+*/
+
+/*!
+ \qmlsignal QInstaller::componentAdded(Component component)
+
+ Emitted when a new root component has been added.
+
+ \sa rootComponentsAdded, updaterComponentsAdded
+*/
+
+/*!
+ \qmlsignal QInstaller::rootComponentsAdded(list<Component> components)
+
+ Emitted when a new list of root components has been added.
+
+ \sa componentAdded, updaterComponentsAdded
+*/
+
+/*!
+ \qmlsignal QInstaller::updaterComponentsAdded(list<Component> components)
+
+ Emitted when a new list of updater components has been added.
+ \sa componentAdded, rootComponentsAdded
+*/
+
+/*!
+ \qmlsignal QInstaller::componentsAboutToBeCleared()
+
+ Deprecated, and not emitted any more.
+*/
+
+/*!
+ \qmlsignal QInstaller::valueChanged(string key, string value)
+
+ Emitted whenever a value changes.
+
+ \sa setValue
+*/
+
+/*!
+ \qmlsignal QInstaller::statusChanged(Status status)
+
+ Emitted whenever the installer status changes.
+*/
+
+/*!
+ \qmlsignal QInstaller::currentPageChanged(int page)
+
+ Emitted whenever the current page changes.
+*/
+
+/*!
+ \qmlsignal QInstaller::finishButtonClicked()
+
+ Emitted when the user clicks the \uicontrol Finish button of the installer.
+*/
+
+/*!
+ \qmlsignal QInstaller::metaJobInfoMessage(string message)
+
+ Triggered with informative updates of the communication with a remote repository.
+ This is only useful for debugging purposes.
+*/
+
+/*!
+ \qmlsignal QInstaller::startAllComponentsReset()
+
+ Triggered when the list of components starts to get updated.
+
+ \sa finishAllComponentsReset
+*/
+
+/*!
+ \qmlsignal QInstaller::finishAllComponentsReset(list<Component> rootComponents)
+
+ Triggered when the list of new root components has been updated.
+
+ \sa startAllComponentsReset
+*/
+
+/*!
+ \qmlsignal QInstaller::startUpdaterComponentsReset()
+
+ Triggered when components start to get updated during a remote update.
+*/
+
+/*!
+ \qmlsignal QInstaller::finishUpdaterComponentsReset(list<Component> componentsWithUpdates)
+
+ Triggered when the list of available remote updates has been updated.
+*/
+
+/*!
+ \qmlsignal QInstaller::installationStarted()
+
+ Triggered when installation has started.
+
+ \sa installationFinished installationInterrupted
+*/
+
+/*!
+ \qmlsignal QInstaller::installationInterrupted()
+
+ Triggered when installation has been interrupted (cancelled).
+
+ \sa interrupt installationStarted installationFinished
+*/
+
+/*!
+ \qmlsignal QInstaller::installationFinished()
+
+ Triggered when installation has been finished.
+
+ \sa installationStarted installationInterrupted
+*/
+
+/*!
+ \qmlsignal QInstaller::updateFinished()
+
+ Triggered when an update has been finished.
+*/
+
+/*!
+ \qmlsignal QInstaller::uninstallationStarted()
+
+ Triggered when uninstallation has started.
+
+ \sa uninstallationFinished
+*/
+
+/*!
+ \qmlsignal QInstaller::uninstallationFinished()
+
+ Triggered when uninstallation has been finished.
+
+ \sa uninstallationStarted
+*/
+
+/*!
+ \qmlsignal QInstaller::titleMessageChanged(string title)
+
+ Emitted when the text of the installer status (on the PerformInstallation page) changes to
+ \a title.
+*/
+
+/*!
+ \qmlsignal QInstaller::wizardPageInsertionRequested(Widget widget, WizardPage page)
+
+ Emitted when a custom \a widget is about to be inserted into \a page by addWizardPage.
+*/
+
+/*!
+ \qmlsignal QInstaller::wizardPageRemovalRequested(Widget widget)
+
+ Emitted when a \a widget is removed by removeWizardPage.
+*/
+
+/*!
+ \qmlsignal QInstaller::wizardWidgetInsertionRequested(Widget widget, WizardPage page)
+
+ Emitted when a \a widget is inserted into \a page by addWizardPageItem.
+*/
+
+/*!
+ \qmlsignal QInstaller::wizardWidgetRemovalRequested(Widget widget)
+
+ Emitted when a \a widget is removed by removeWizardPageItem.
+*/
+
+/*!
+ \qmlsignal QInstaller::wizardPageVisibilityChangeRequested(bool visible, int page)
+
+ Emitted when the visibility of the page with id \a page changes to \a visible.
+
+ \sa setDefaultPageVisible
+*/
+
+/*!
+ \qmlsignal QInstaller::setValidatorForCustomPageRequested(Componentcomponent, string name,
+ string callbackName)
+
+ Triggered when setValidatorForCustomPage is called.
+*/
+
+/*!
+ \qmlsignal QInstaller::setAutomatedPageSwitchEnabled(bool request)
+
+ Triggered when the automatic switching from PerformInstallation to InstallationFinished page
+ is enabled (\a request = \c true) or disabled (\a request = \c false).
+
+ The automatic switching is disabled automatically when for example the user expands or unexpands
+ the \gui Details section of the PerformInstallation page.
+*/
+
+/*!
+ \qmlsignal QInstaller::coreNetworkSettingsChanged()
+
+ Emitted when the network settings are changed.
+*/
+
+/*!
+ \qmlmethod list<Component> QInstaller::components()
+
+ Returns the list of all components.
+*/
+
using namespace QInstaller;
-static QMutex sModelMutex;
+Q_GLOBAL_STATIC(QMutex, globalModelMutex);
static QFont *sVirtualComponentsFont = 0;
-static QMutex sVirtualComponentsFontMutex;
+Q_GLOBAL_STATIC(QMutex, globalVirtualComponentsFontMutex);
static bool sNoForceInstallation = false;
static bool sVirtualComponentsVisible = false;
static bool sCreateLocalRepositoryFromBinary = false;
-static QScriptValue checkArguments(QScriptContext *context, int amin, int amax)
-{
- if (context->argumentCount() < amin || context->argumentCount() > amax) {
- if (amin != amax) {
- return context->throwError(QObject::tr("Invalid arguments: %1 arguments given, %2 to "
- "%3 expected.").arg(QString::number(context->argumentCount()),
- QString::number(amin), QString::number(amax)));
- }
- return context->throwError(QObject::tr("Invalid arguments: %1 arguments given, %2 expected.")
- .arg(QString::number(context->argumentCount()), QString::number(amin)));
- }
- return QScriptValue();
-}
-
static bool componentMatches(const Component *component, const QString &name,
const QString &version = QString())
{
@@ -131,12 +365,12 @@ Component *PackageManagerCore::subComponentByName(const QInstaller::PackageManag
if (check != 0 && componentMatches(check, name, version))
return check;
- if (installer->runMode() == AllMode) {
+ if (!installer->isUpdater()) {
QList<Component*> rootComponents;
if (check == 0)
rootComponents = installer->rootComponents();
else
- rootComponents = check->childComponents(false, AllMode);
+ rootComponents = check->childComponents(Component::DirectChildrenOnly);
foreach (QInstaller::Component *component, rootComponents) {
Component *const result = subComponentByName(installer, name, version, component);
@@ -154,146 +388,6 @@ Component *PackageManagerCore::subComponentByName(const QInstaller::PackageManag
return 0;
}
-/*!
- Scriptable version of PackageManagerCore::componentByName(QString).
- \sa PackageManagerCore::componentByName
- */
-QScriptValue QInstaller::qInstallerComponentByName(QScriptContext *context, QScriptEngine *engine)
-{
- const QScriptValue check = checkArguments(context, 1, 1);
- if (check.isError())
- return check;
-
- // well... this is our "this" pointer
- PackageManagerCore *const core = dynamic_cast<PackageManagerCore*>(engine->globalObject()
- .property(QLatin1String("installer")).toQObject());
-
- const QString name = context->argument(0).toString();
- return engine->newQObject(core->componentByName(name));
-}
-
-QScriptValue QInstaller::qDesktopServicesOpenUrl(QScriptContext *context, QScriptEngine *engine)
-{
- Q_UNUSED(engine);
- const QScriptValue check = checkArguments(context, 1, 1);
- if (check.isError())
- return check;
- QString url = context->argument(0).toString();
- url.replace(QLatin1String("\\\\"), QLatin1String("/"));
- url.replace(QLatin1String("\\"), QLatin1String("/"));
- return QDesktopServices::openUrl(QUrl::fromUserInput(url));
-}
-
-QScriptValue QInstaller::qDesktopServicesDisplayName(QScriptContext *context, QScriptEngine *engine)
-{
- Q_UNUSED(engine);
- const QScriptValue check = checkArguments(context, 1, 1);
- if (check.isError())
- return check;
-
-#if QT_VERSION < 0x050000
- const QDesktopServices::StandardLocation location =
- static_cast< QDesktopServices::StandardLocation >(context->argument(0).toInt32());
- return QDesktopServices::displayName(location);
-#else
- const QStandardPaths::StandardLocation location =
- static_cast< QStandardPaths::StandardLocation >(context->argument(0).toInt32());
- return QStandardPaths::displayName(location);
-#endif
-}
-
-QScriptValue QInstaller::qDesktopServicesStorageLocation(QScriptContext *context, QScriptEngine *engine)
-{
- Q_UNUSED(engine);
- const QScriptValue check = checkArguments(context, 1, 1);
- if (check.isError())
- return check;
-
-#if QT_VERSION < 0x050000
- const QDesktopServices::StandardLocation location =
- static_cast< QDesktopServices::StandardLocation >(context->argument(0).toInt32());
- return QDesktopServices::storageLocation(location);
-#else
- const QStandardPaths::StandardLocation location =
- static_cast< QStandardPaths::StandardLocation >(context->argument(0).toInt32());
- return QStandardPaths::writableLocation(location);
-#endif
-}
-
-QScriptValue QInstaller::qFileDialogGetExistingDirectory( QScriptContext *context, QScriptEngine *engine )
-{
- Q_UNUSED(engine);
- const QScriptValue check = checkArguments(context, 0, 2);
- if (check.isError())
- return check;
- QString caption;
- QString dir;
- if (context->argumentCount() > 0)
- caption = context->argument(0).toString();
- if (context->argumentCount() > 1)
- dir = context->argument(1).toString();
- return QFileDialog::getExistingDirectory(0, caption, dir);
-}
-
-QString QInstaller::uncaughtExceptionString(QScriptEngine *scriptEngine, const QString &context)
-{
- QString error(QLatin1String("\n\n%1\n\nBacktrace:\n\t%2"));
- if (!context.isEmpty())
- error.prepend(context);
-
- return error.arg(scriptEngine->uncaughtException().toString(), scriptEngine->uncaughtExceptionBacktrace()
- .join(QLatin1String("\n\t")));
-}
-
-
-/*!
- \class QInstaller::PackageManagerCore
- PackageManagerCore forms the core of the installation, update, maintenance and un-installation system.
- */
-
-/*!
- \enum QInstaller::PackageManagerCore::WizardPage
- WizardPage is used to number the different pages known to the Installer GUI.
- */
-
-/*!
- \var QInstaller::PackageManagerCore::Introduction
- I ntroduction page.
- */
-
-/*!
- \var QInstaller::PackageManagerCore::LicenseCheck
- License check page
- */
-/*!
- \var QInstaller::PackageManagerCore::TargetDirectory
- Target directory selection page
- */
-/*!
- \var QInstaller::PackageManagerCore::ComponentSelection
- %Component selection page
- */
-/*!
- \var QInstaller::PackageManagerCore::StartMenuSelection
- Start menu directory selection page - Microsoft Windows only
- */
-/*!
- \var QInstaller::PackageManagerCore::ReadyForInstallation
- "Ready for Installation" page
- */
-/*!
- \var QInstaller::PackageManagerCore::PerformInstallation
- Page shown while performing the installation
- */
-/*!
- \var QInstaller::PackageManagerCore::InstallationFinished
- Page shown when the installation was finished
- */
-/*!
- \var QInstaller::PackageManagerCore::End
- Non-existing page - this value has to be used if you want to insert a page after \a InstallationFinished
- */
-
void PackageManagerCore::writeUninstaller()
{
if (d->m_needToWriteUninstaller) {
@@ -319,6 +413,11 @@ void PackageManagerCore::writeUninstaller()
}
}
+void PackageManagerCore::writeMaintenanceConfigFiles()
+{
+ d->writeMaintenanceConfigFiles();
+}
+
void PackageManagerCore::reset(const QHash<QString, QString> &params)
{
d->m_completeUninstall = false;
@@ -330,6 +429,8 @@ void PackageManagerCore::reset(const QHash<QString, QString> &params)
}
/*!
+ \qmlmethod void QInstaller::setCompleteUninstallation(bool complete)
+
Sets the uninstallation to be \a complete. If \a complete is false, only components deselected
by the user will be uninstalled. This option applies only on uninstallation.
*/
@@ -338,27 +439,60 @@ void PackageManagerCore::setCompleteUninstallation(bool complete)
d->m_completeUninstall = complete;
}
+/*!
+ \qmlmethod void QInstaller::cancelMetaInfoJob()
+
+ Cancels the retrieval of meta information from a remote repository.
+ */
void PackageManagerCore::cancelMetaInfoJob()
{
if (d->m_repoMetaInfoJob)
d->m_repoMetaInfoJob->cancel();
}
+/*!
+ \qmlmethod void QInstaller::componentsToInstallNeedsRecalculation()
+
+ Ensures that component dependencies are re-calculated.
+ */
void PackageManagerCore::componentsToInstallNeedsRecalculation()
{
d->m_componentsToInstallCalculated = false;
}
+/*!
+ \qmlmethod void QInstaller::autoAcceptMessageBoxes()
+
+ Automatically accept all user message boxes.
+
+ \sa autoRejectMessageBoxes, setMessageBoxAutomaticAnswer
+ */
void PackageManagerCore::autoAcceptMessageBoxes()
{
MessageBoxHandler::instance()->setDefaultAction(MessageBoxHandler::Accept);
}
+/*!
+ \qmlmethod void QInstaller::autoRejectMessageBoxes()
+
+ Automatically reject all user message boxes.
+
+ \sa autoAcceptMessageBoxes, setMessageBoxAutomaticAnswer
+ */
void PackageManagerCore::autoRejectMessageBoxes()
{
MessageBoxHandler::instance()->setDefaultAction(MessageBoxHandler::Reject);
}
+/*!
+ \qmlmethod void QInstaller::setMessageBoxAutomaticAnswer(string identifier, int button)
+
+ Automatically close the message box with ID \a identifier as if the user had pressed \a button.
+
+ This can be used for unattended (automatic) installations.
+
+ \sa QMessageBox, autoAcceptMessageBoxes, autoRejectMessageBoxes
+ */
void PackageManagerCore::setMessageBoxAutomaticAnswer(const QString &identifier, int button)
{
MessageBoxHandler::instance()->setAutomaticAnswer(identifier,
@@ -372,6 +506,13 @@ quint64 size(QInstaller::Component *component, const QString &value)
return component->value(value).toLongLong();
}
+/*!
+ \qmlmethod float QInstaller::requiredDiskSpace()
+
+ Returns the estimated amount of disk space in bytes required after installation.
+
+ \sa requiredTemporaryDiskSpace
+ */
quint64 PackageManagerCore::requiredDiskSpace() const
{
quint64 result = 0;
@@ -382,6 +523,13 @@ quint64 PackageManagerCore::requiredDiskSpace() const
return result;
}
+/*!
+ \qmlmethod float QInstaller::requiredTemporaryDiskSpace()
+
+ Returns the estimated required disk space during installation in bytes.
+
+ \sa requiredDiskSpace
+ */
quint64 PackageManagerCore::requiredTemporaryDiskSpace() const
{
quint64 result = 0;
@@ -487,7 +635,7 @@ void PackageManagerCore::rollBackInstallation()
if (!componentName.isEmpty()) {
Component *component = componentByName(componentName);
if (!component)
- component = d->componentsToReplace(runMode()).value(componentName).second;
+ component = d->componentsToReplace().value(componentName).second;
if (component) {
component->setUninstalled();
packages.removePackage(component->name());
@@ -510,12 +658,26 @@ void PackageManagerCore::rollBackInstallation()
packages.writeToDisk();
}
+/*!
+ \qmlmethod boolean Installer::isFileExtensionRegistered(string extension)
+
+ Returns whether a file extension is already registered in the Windows registry. Returns \c false
+ on all other platforms.
+ */
bool PackageManagerCore::isFileExtensionRegistered(const QString &extension) const
{
QSettingsWrapper settings(QLatin1String("HKEY_CLASSES_ROOT"), QSettingsWrapper::NativeFormat);
return settings.value(QString::fromLatin1(".%1/Default").arg(extension)).isValid();
}
+/*!
+ \qmlmethod boolean QInstaller::fileExists(string filePath)
+
+ Returns \c true if the \a filePath exists; otherwise returns \c false.
+
+ \note If the file is a symlink that points to a non existing
+ file, \c false is returned.
+ */
bool PackageManagerCore::fileExists(const QString &filePath) const
{
return QFileInfo(filePath).exists();
@@ -530,6 +692,8 @@ bool PackageManagerCore::fileExists(const QString &filePath) const
PackageManagerCore::PackageManagerCore()
: d(new PackageManagerCorePrivate(this))
{
+ qRegisterMetaType<QInstaller::PackageManagerCore::Status>("QInstaller::PackageManagerCore::Status");
+ qRegisterMetaType<QInstaller::PackageManagerCore::WizardPage>("QInstaller::PackageManagerCore::WizardPage");
}
PackageManagerCore::PackageManagerCore(qint64 magicmaker, const OperationList &performedOperations)
@@ -550,12 +714,16 @@ PackageManagerCore::~PackageManagerCore()
QInstaller::VerboseWriter::instance()->setOutputStream(logFileName);
}
delete d;
+
+ QMutexLocker _(globalVirtualComponentsFontMutex());
+ delete sVirtualComponentsFont;
+ sVirtualComponentsFont = 0;
}
/* static */
QFont PackageManagerCore::virtualComponentsFont()
{
- QMutexLocker _(&sVirtualComponentsFontMutex);
+ QMutexLocker _(globalVirtualComponentsFontMutex());
if (!sVirtualComponentsFont)
sVirtualComponentsFont = new QFont;
return *sVirtualComponentsFont;
@@ -564,7 +732,7 @@ QFont PackageManagerCore::virtualComponentsFont()
/* static */
void PackageManagerCore::setVirtualComponentsFont(const QFont &font)
{
- QMutexLocker _(&sVirtualComponentsFontMutex);
+ QMutexLocker _(globalVirtualComponentsFontMutex());
if (sVirtualComponentsFont)
delete sVirtualComponentsFont;
sVirtualComponentsFont = new QFont(font);
@@ -606,11 +774,6 @@ void PackageManagerCore::setCreateLocalRepositoryFromBinary(bool create)
sCreateLocalRepositoryFromBinary = create;
}
-RunMode PackageManagerCore::runMode() const
-{
- return isUpdater() ? UpdaterMode : AllMode;
-}
-
bool PackageManagerCore::fetchLocalPackagesTree()
{
d->setStatus(Running);
@@ -650,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;
}
@@ -705,8 +867,8 @@ bool PackageManagerCore::fetchRemotePackagesTree()
return false;
}
- if (!ProductKeyCheck::instance()->hasValidKey()) {
- d->setStatus(Failure, ProductKeyCheck::instance()->lastErrorString());
+ if (!ProductKeyCheck::instance(this)->hasValidKey()) {
+ d->setStatus(Failure, ProductKeyCheck::instance(this)->lastErrorString());
return false;
}
@@ -725,9 +887,39 @@ bool PackageManagerCore::fetchRemotePackagesTree()
return false;
bool success = false;
- if (runMode() == AllMode)
+ 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);
}
@@ -739,9 +931,16 @@ bool PackageManagerCore::fetchRemotePackagesTree()
}
/*!
+ \qmlmethod boolean QInstaller::addWizardPage(Component component, string name, int page)
+
Adds the widget with objectName() \a name registered by \a component as a new page
into the installer's GUI wizard. The widget is added before \a page.
- \a page has to be a value of \ref QInstaller::PackageManagerCore::WizardPage "WizardPage".
+
+ See \l{Wizard Pages} for the possible values of \a page.
+
+ Returns \c true if the operation succeeded.
+
+ \sa removeWizardPage, setDefaultPageVisible
*/
bool PackageManagerCore::addWizardPage(Component *component, const QString &name, int page)
{
@@ -753,8 +952,14 @@ bool PackageManagerCore::addWizardPage(Component *component, const QString &name
}
/*!
+ \qmlmethod boolean QInstaller::removeWizardPage(Component component, string name)
+
Removes the widget with objectName() \a name previously added to the installer's wizard
by \a component.
+
+ Returns \c true if the operation succeeded.
+
+ \sa addWizardPage, setDefaultPageVisible, wizardPageRemovalRequested
*/
bool PackageManagerCore::removeWizardPage(Component *component, const QString &name)
{
@@ -766,9 +971,15 @@ bool PackageManagerCore::removeWizardPage(Component *component, const QString &n
}
/*!
+ \qmlmethod boolean QInstaller::setDefaultPageVisible(int page, boolean visible)
+
Sets the visibility of the default page with id \a page to \a visible, i.e.
removes or adds it from/to the wizard. This works only for pages which have been
in the installer when it was started.
+
+ Returns \c true.
+
+ \sa addWizardPage, removeWizardPage
*/
bool PackageManagerCore::setDefaultPageVisible(int page, bool visible)
{
@@ -776,6 +987,12 @@ bool PackageManagerCore::setDefaultPageVisible(int page, bool visible)
return true;
}
+/*!
+ \qmlmethod void QInstaller::setValidatorForCustomPage(Component component, string name,
+ string callbackName)
+
+ \sa setValidatorForCustomPageRequested
+ */
void PackageManagerCore::setValidatorForCustomPage(Component *component, const QString &name,
const QString &callbackName)
{
@@ -783,9 +1000,14 @@ void PackageManagerCore::setValidatorForCustomPage(Component *component, const Q
}
/*!
+ \qmlmethod boolean QInstaller::addWizardPageItem(Component component, string name, int page)
+
Adds the widget with objectName() \a name registered by \a component as an GUI element
into the installer's GUI wizard. The widget is added on \a page.
- \a page has to be a value of \ref QInstaller::PackageManagerCore::WizardPage "WizardPage".
+
+ See \l{Wizard Pages} for the possible values of \a page.
+
+ \sa removeWizardPageItem, wizardWidgetInsertionRequested
*/
bool PackageManagerCore::addWizardPageItem(Component *component, const QString &name, int page)
{
@@ -797,8 +1019,12 @@ bool PackageManagerCore::addWizardPageItem(Component *component, const QString &
}
/*!
+ \qmlmethod boolean QInstaller::removeWizardPageItem(Component component, string name)
+
Removes the widget with objectName() \a name previously added to the installer's wizard
by \a component.
+
+ \sa addWizardPageItem
*/
bool PackageManagerCore::removeWizardPageItem(Component *component, const QString &name)
{
@@ -809,6 +1035,13 @@ bool PackageManagerCore::removeWizardPageItem(Component *component, const QStrin
return false;
}
+/*!
+ \qmlmethod void QInstaller::addUserRepositories(stringlist repositories)
+
+ Registers additional \a repositories.
+
+ \sa setTemporaryRepositories
+ */
void PackageManagerCore::addUserRepositories(const QStringList &repositories)
{
QSet<Repository> repositorySet;
@@ -819,8 +1052,12 @@ void PackageManagerCore::addUserRepositories(const QStringList &repositories)
}
/*!
- Sets additional repository for this instance of the installer or updater.
+ \qmlmethod void QInstaller::setTemporaryRepositories(stringlist repositories, boolean replace)
+
+ Sets additional \a repositories for this instance of the installer or updater.
Will be removed after invoking it again.
+
+ \sa addUserRepositories
*/
void PackageManagerCore::setTemporaryRepositories(const QStringList &repositories, bool replace)
{
@@ -847,6 +1084,11 @@ void PackageManagerCore::setTestChecksum(bool test)
d->m_testChecksum = test;
}
+ScriptEngine *PackageManagerCore::scriptEngine()
+{
+ return d->scriptEngine();
+}
+
/*!
Returns the number of components in the list for installer and package manager mode. Might return 0 in
case the engine has only been run in updater mode or no components have been fetched.
@@ -886,6 +1128,8 @@ void PackageManagerCore::appendRootComponent(Component *component)
}
/*!
+ \qmlmethod int QInstaller::updaterComponentCount()
+
Returns the number of components in the list for updater mode. Might return 0 in case the engine has only
been run in installer or package manager mode or no components have been fetched.
*/
@@ -934,13 +1178,15 @@ QList<Component*> PackageManagerCore::availableComponents() const
QList<Component*> result = d->m_rootComponents;
foreach (QInstaller::Component *component, d->m_rootComponents)
- result += component->childComponents(true, AllMode);
+ result += component->childComponents(Component::Descendants);
return result + d->m_rootDependencyReplacements;
}
/*!
+ \qmlmethod Component QInstaller::componentByName(string name)
+
Returns a component matching \a name. \a name can also contains a version requirement.
- E.g. "com.nokia.sdk.qt" returns any component with that name, "com.nokia.sdk.qt->=4.5" requires
+ E.g. "org.qt-project.sdk.qt" returns any component with that name, "org.qt-project.sdk.qt->=4.5" requires
the returned component to have at least version 4.5.
If no component matches the requirement, 0 is returned.
*/
@@ -968,21 +1214,23 @@ bool PackageManagerCore::calculateComponentsToInstall() const
if (!d->m_componentsToInstallCalculated) {
d->clearComponentsToInstall();
QList<Component*> components;
- if (runMode() == UpdaterMode) {
+ if (isUpdater()) {
foreach (Component *component, updaterComponents()) {
if (component->updateRequested())
components.append(component);
}
- } else if (runMode() == AllMode) {
+ } else if (!isUpdater()) {
// relevant means all components which are not replaced
QList<Component*> relevantComponents = rootComponents();
foreach (QInstaller::Component *component, rootComponents())
- relevantComponents += component->childComponents(true, AllMode);
+ relevantComponents += component->childComponents(Component::Descendants);
foreach (Component *component, relevantComponents) {
// ask for all components which will be installed to get all dependencies
- // even dependencies wich are changed without an increased version
- if (component->installationRequested() || (component->isInstalled() && !component->uninstallationRequested()))
- components.append(component);
+ // even dependencies which are changed without an increased version
+ if (component->installationRequested() || (component->isInstalled()
+ && !component->uninstallationRequested())) {
+ components.append(component);
+ }
}
}
@@ -1005,10 +1253,10 @@ QList<Component*> PackageManagerCore::orderedComponentsToInstall() const
*/
bool PackageManagerCore::calculateComponentsToUninstall() const
{
- if (runMode() == UpdaterMode)
+ if (isUpdater())
return true;
- // hack to avoid removeing needed dependencies
+ // hack to avoid removing needed dependencies
QSet<Component*> componentsToInstall = d->m_orderedComponentsToInstall.toSet();
QList<Component*> components;
@@ -1046,7 +1294,7 @@ QString PackageManagerCore::installReason(Component *component) const
}
/*!
- Returns a list of components that dependend on \a component. The list can be empty. Note: Auto
+ Returns a list of components that depend on \a component. The list can be empty. Note: Auto
installed dependencies are not resolved.
*/
QList<Component*> PackageManagerCore::dependees(const Component *_component) const
@@ -1090,21 +1338,25 @@ QList<Component*> PackageManagerCore::dependencies(const Component *component, Q
ComponentModel *PackageManagerCore::defaultComponentModel() const
{
- QMutexLocker _(&sModelMutex);
+ QMutexLocker _(globalModelMutex());
if (!d->m_defaultModel) {
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;
}
ComponentModel *PackageManagerCore::updaterComponentModel() const
{
- QMutexLocker _(&sModelMutex);
+ QMutexLocker _(globalModelMutex());
if (!d->m_updaterModel) {
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;
}
@@ -1114,7 +1366,11 @@ Settings &PackageManagerCore::settings() const
}
/*!
- This method tries to gain admin rights. On success, it returns true.
+ \qmlmethod boolean QInstaller::gainAdminRights()
+
+ Tries to gain admin rights. On success, it returns \c true.
+
+ \sa dropAdminRights
*/
bool PackageManagerCore::gainAdminRights()
{
@@ -1128,7 +1384,11 @@ bool PackageManagerCore::gainAdminRights()
}
/*!
- This method drops gained admin rights.
+ \qmlmethod void QInstaller::dropAdminRights()
+
+ Drops admin rights gained by gainAdminRights.
+
+ \sa gainAdminRights
*/
void PackageManagerCore::dropAdminRights()
{
@@ -1136,7 +1396,9 @@ void PackageManagerCore::dropAdminRights()
}
/*!
- Return true, if a process with \a name is running. On Windows, the comparison
+ \qmlmethod boolean QInstaller::isProcessRunning(string name)
+
+ Returns true, if a process with \a name is running. On Windows, the comparison
is case-insensitive.
*/
bool PackageManagerCore::isProcessRunning(const QString &name) const
@@ -1145,8 +1407,11 @@ bool PackageManagerCore::isProcessRunning(const QString &name) const
}
/*!
- Return true, if a process with \a absoluteFilePath could be killed or isn't running
- Note: this is implemented in a semi blocking way (to keep the main thread to paint the UI)
+ \qmlmethod boolean QInstaller::killProcess(string absoluteFilePath)
+
+ Returns true, if a process with \a absoluteFilePath could be killed or isn't running
+
+ \note This is implemented in a semi blocking way (to keep the main thread to paint the UI).
*/
bool PackageManagerCore::killProcess(const QString &absoluteFilePath) const
{
@@ -1180,11 +1445,30 @@ bool PackageManagerCore::killProcess(const QString &absoluteFilePath) const
}
+/*!
+ \qmlmethod void QInstaller::setDependsOnLocalInstallerBinary()
+
+ Makes sure the installer runs from a local drive. Otherwise the user will get an
+ appropriate error message.
+
+ \note This only works on Windows.
+
+ \sa localInstallerBinaryUsed
+*/
+
void PackageManagerCore::setDependsOnLocalInstallerBinary()
{
d->m_dependsOnLocalInstallerBinary = true;
}
+/*!
+ \qmlmethod boolean QInstaller::localInstallerBinaryUsed()
+
+ Returns \c false if the installer is run on Windows, and the installer has been started from
+ a remote file system drive. Otherwise returns \c true.
+
+ \sa setDependsOnLocalInstallerBinary
+*/
bool PackageManagerCore::localInstallerBinaryUsed()
{
#ifdef Q_OS_WIN
@@ -1194,14 +1478,20 @@ bool PackageManagerCore::localInstallerBinaryUsed()
}
/*!
- Executes a program.
+ \qmlmethod array QInstaller::execute(string program, stringlist arguments = undefined,
+ string stdin = "")
+
+ Starts the program \a program with the arguments \a arguments in a
+ new process and waits for it to finish.
+
+ \a stdin is sent as standard input to the application.
+
+ Returns an empty array if the program could not be executed, otherwise
+ the output of command as the first item, and the return code as the second.
- \param program The program that should be executed.
- \param arguments Optional list of arguments.
- \param stdIn Optional stdin the program reads.
- \return If the command could not be executed, an empty QList, otherwise the output of the
- command as first item, the return code as second item.
\note On Unix, the output is just the output to stdout, not to stderr.
+
+ \sa executeDetached
*/
QList<QVariant> PackageManagerCore::execute(const QString &program, const QStringList &arguments,
const QString &stdIn) const
@@ -1234,12 +1524,24 @@ QList<QVariant> PackageManagerCore::execute(const QString &program, const QStrin
}
/*!
- Executes a program.
+ \qmlmethod boolean QInstaller::executeDetached(string program, stringlist arguments = undefined,
+ string workingDirectory = "")
+
+ Starts the program \a program with the arguments \a arguments in a
+ new process, and detaches from it. Returns \c true on success;
+ otherwise returns \c false. If the installer exits, the
+ detached process will continue to live.
+
+ \note Arguments that contain spaces are not passed to the
+ process as separate arguments.
- \param program The program that should be executed.
- \param arguments Optional list of arguments.
- \param workingDirectory Optional working directory of the forked process.
- \return If the command could not be executed, an false will be returned
+ \b{Unix:} The started process will run in its own session and act
+ like a daemon.
+
+ \b{Windows:} Arguments that contain spaces are wrapped in quotes.
+ The started process will run as a regular standalone process.
+
+ The process will be started in the directory \a workingDirectory.
*/
bool PackageManagerCore::executeDetached(const QString &program, const QStringList &arguments,
@@ -1259,16 +1561,20 @@ bool PackageManagerCore::executeDetached(const QString &program, const QStringLi
/*!
- Returns an environment variable.
+ \qmlmethod string QInstaller::environmentVariable(string name)
+
+ Returns content of an environment variable \a name. An empty string is returned if the
+ environment variable is not set.
*/
QString PackageManagerCore::environmentVariable(const QString &name) const
{
+ if (name.isEmpty())
+ return QString();
+
#ifdef Q_OS_WIN
- const LPCWSTR n = (LPCWSTR) name.utf16();
- LPTSTR buff = (LPTSTR) malloc(4096 * sizeof(TCHAR));
- DWORD getenvret = GetEnvironmentVariable(n, buff, 4096);
- QString value = getenvret != 0 ? QString::fromUtf16((const unsigned short *) buff) : QString();
- free(buff);
+ static TCHAR buffer[32767];
+ DWORD size = GetEnvironmentVariable(LPCWSTR(name.utf16()), buffer, 32767);
+ QString value = QString::fromUtf16((const unsigned short *) buffer, size);
if (value.isEmpty()) {
static QLatin1String userEnvironmentRegistryPath("HKEY_CURRENT_USER\\Environment");
@@ -1281,14 +1587,14 @@ QString PackageManagerCore::environmentVariable(const QString &name) const
}
return value;
#else
- const char *pPath = name.isEmpty() ? 0 : getenv(name.toLatin1());
- return pPath ? QLatin1String(pPath) : QString();
+ return QString::fromUtf8(qgetenv(name.toLatin1()));
#endif
}
/*!
+ \qmlmethod boolean QInstaller::performOperation(string name, stringlist arguments)
+
Instantly performs an operation \a name with \a arguments.
- \sa Component::addOperation
*/
bool PackageManagerCore::performOperation(const QString &name, const QStringList &arguments)
{
@@ -1306,7 +1612,9 @@ bool PackageManagerCore::performOperation(const QString &name, const QStringList
}
/*!
- Returns true when \a version matches the \a requirement.
+ \qmlmethod boolean QInstaller::versionMatches(string version, string requirement)
+
+ Returns \c true when \a version matches the \a requirement.
\a requirement can be a fixed version number or it can be prefix by the comparators '>', '>=',
'<', '<=' and '='.
*/
@@ -1333,10 +1641,15 @@ bool PackageManagerCore::versionMatches(const QString &version, const QString &r
}
/*!
+ \qmlmethod string QInstaller::findLibrary(string name, stringlist paths = [])
+
Finds a library named \a name in \a paths.
If \a paths is empty, it gets filled with platform dependent default paths.
- The resulting path is stored in \a library.
+ The resulting path is returned.
+
This method can be used by scripts to check external dependencies.
+
+ \sa findPath
*/
QString PackageManagerCore::findLibrary(const QString &name, const QStringList &paths)
{
@@ -1362,9 +1675,14 @@ QString PackageManagerCore::findLibrary(const QString &name, const QStringList &
}
/*!
+ \qmlmethod string QInstaller::findPath(string name, stringlist paths = [])
+
Tries to find a file name \a name in one of \a paths.
- The resulting path is stored in \a path.
+ The resulting path is returned.
+
This method can be used by scripts to check external dependencies.
+
+ \sa findLibrary
*/
QString PackageManagerCore::findPath(const QString &name, const QStringList &paths)
{
@@ -1380,8 +1698,11 @@ QString PackageManagerCore::findPath(const QString &name, const QStringList &pat
}
/*!
+ \qmlmethod void QInstaller::setInstallerBaseBinary(string path)
+
Sets the "installerbase" binary to use when writing the package manager/uninstaller.
Set this if an update to installerbase is available.
+
If not set, the executable segment of the running un/installer will be used.
*/
void PackageManagerCore::setInstallerBaseBinary(const QString &path)
@@ -1390,8 +1711,12 @@ void PackageManagerCore::setInstallerBaseBinary(const QString &path)
}
/*!
+ \qmlmethod string QInstaller::value(string key, string defaultValue = "")
+
Returns the installer value for \a key. If \a key is not known to the system, \a defaultValue is
returned. Additionally, on Windows, \a key can be a registry key.
+
+ \sa setValue, containsValue, valueChanged
*/
QString PackageManagerCore::value(const QString &key, const QString &defaultValue) const
{
@@ -1399,7 +1724,11 @@ QString PackageManagerCore::value(const QString &key, const QString &defaultValu
}
/*!
+ \qmlmethod void QInstaller::setValue(string key, string value)
+
Sets the installer value for \a key to \a value.
+
+ \sa value, containsValue, valueChanged
*/
void PackageManagerCore::setValue(const QString &key, const QString &value)
{
@@ -1409,18 +1738,38 @@ void PackageManagerCore::setValue(const QString &key, const QString &value)
}
/*!
- Returns true, when the installer contains a value for \a key.
+ \qmlmethod boolean QInstaller::containsValue(string key)
+
+ Returns \c true if the installer contains a value for \a key.
+
+ \sa value, setValue, valueChanged
*/
bool PackageManagerCore::containsValue(const QString &key) const
{
return d->m_data.contains(key);
}
+/*!
+ \qmlmethod void QInstaller::setSharedFlag(string key, boolean value)
+
+ Sets a shared flag with name \a key to \a value. This is one option
+ to share information between scripts.
+
+ \sa sharedFlag
+*/
void PackageManagerCore::setSharedFlag(const QString &key, bool value)
{
d->m_sharedFlags.insert(key, value);
}
+/*!
+ \qmlmethod boolean QInstaller::sharedFlag(string key)
+
+ Returns shared flag with name \a key. This is one option
+ to share information between scripts.
+
+ \sa setSharedFlag
+*/
bool PackageManagerCore::sharedFlag(const QString &key) const
{
return d->m_sharedFlags.value(key, false);
@@ -1447,7 +1796,7 @@ QString PackageManagerCore::error() const
}
/*!
- Returns true if at least one complete installation/update was successful, even if the user cancelled the
+ Returns \c true if at least one complete installation/update was successful, even if the user cancelled the
newest installation process.
*/
bool PackageManagerCore::finishedWithSuccess() const
@@ -1455,12 +1804,24 @@ bool PackageManagerCore::finishedWithSuccess() const
return d->m_status == PackageManagerCore::Success || d->m_needToWriteUninstaller;
}
+/*!
+ \qmlmethod void QInstaller::interrupt()
+
+ Cancels an ongoing installation.
+
+ \sa installationInterrupted
+ */
void PackageManagerCore::interrupt()
{
setCanceled();
emit installationInterrupted();
}
+/*!
+ \qmlmethod void QInstaller::setCanceled()
+
+ Cancels the installation.
+ */
void PackageManagerCore::setCanceled()
{
cancelMetaInfoJob();
@@ -1506,7 +1867,11 @@ QString PackageManagerCore::installerBinaryPath() const
}
/*!
- Returns true when this is the installer running.
+ \qmlmethod boolean QInstaller::isInstaller()
+
+ Returns \c true if executed in an install step.
+
+ \sa isUninstaller, isUpdater, isPackageManager
*/
bool PackageManagerCore::isInstaller() const
{
@@ -1514,47 +1879,79 @@ bool PackageManagerCore::isInstaller() const
}
/*!
- Returns true if this is an offline-only installer.
+ \qmlmethod boolean QInstaller::isOfflineOnly()
+
+ Returns \c true if this is an offline-only installer.
*/
bool PackageManagerCore::isOfflineOnly() const
{
return d->isOfflineOnly();
}
+/*!
+ \qmlmethod void QInstaller::setUninstaller()
+
+ Forces an uninstaller context.
+
+ \sa isUninstaller, setUpdater, setPackageManager
+*/
void PackageManagerCore::setUninstaller()
{
d->m_magicBinaryMarker = QInstaller::MagicUninstallerMarker;
}
/*!
- Returns true when this is the uninstaller running.
+ \qmlmethod boolean QInstaller::isUninstaller()
+
+ Returns \c true if the script is executed in an uninstall context.
+
+ \sa setUninstaller, isInstaller, isUpdater, isPackageManager
*/
bool PackageManagerCore::isUninstaller() const
{
return d->isUninstaller();
}
+/*!
+ \qmlmethod void QInstaller::setUpdater()
+
+ Forces an updater context.
+
+ \sa isUpdater, setUninstaller, setPackageManager
+*/
void PackageManagerCore::setUpdater()
{
d->m_magicBinaryMarker = QInstaller::MagicUpdaterMarker;
}
/*!
- Returns true when this is neither an installer nor an uninstaller running.
- Must be an updater, then.
+ \qmlmethod boolean QInstaller::isUpdater()
+
+ Returns \c true if the script is executed in an updater context.
+
+ \sa setUpdater, isInstaller, isUninstaller, isPackageManager
*/
bool PackageManagerCore::isUpdater() const
{
return d->isUpdater();
}
+/*!
+ \qmlmethod void QInstaller::setPackageManager()
+
+ Forces a package manager context.
+*/
void PackageManagerCore::setPackageManager()
{
d->m_magicBinaryMarker = QInstaller::MagicPackageManagerMarker;
}
+
/*!
- Returns true when this is the package manager running.
+ \qmlmethod boolean QInstaller::isPackageManager()
+
+ Returns \c true if the script is executed in a package manager context.
+ \sa setPackageManager, isInstaller, isUninstaller, isUpdater
*/
bool PackageManagerCore::isPackageManager() const
{
@@ -1562,7 +1959,9 @@ bool PackageManagerCore::isPackageManager() const
}
/*!
- Runs the installer. Returns true on success, false otherwise.
+ \qmlmethod boolean QInstaller::runInstaller()
+
+ Runs the installer. Returns \c true on success, \c false otherwise.
*/
bool PackageManagerCore::runInstaller()
{
@@ -1570,7 +1969,9 @@ bool PackageManagerCore::runInstaller()
}
/*!
- Runs the uninstaller. Returns true on success, false otherwise.
+ \qmlmethod boolean QInstaller::runUninstaller()
+
+ Runs the uninstaller. Returns \c true on success, \c false otherwise.
*/
bool PackageManagerCore::runUninstaller()
{
@@ -1578,7 +1979,9 @@ bool PackageManagerCore::runUninstaller()
}
/*!
- Runs the package updater. Returns true on success, false otherwise.
+ \qmlmethod boolean QInstaller::runPackageUpdater()
+
+ Runs the package updater. Returns \c true on success, \c false otherwise.
*/
bool PackageManagerCore::runPackageUpdater()
{
@@ -1586,7 +1989,8 @@ bool PackageManagerCore::runPackageUpdater()
}
/*!
- \internal
+ \qmlmethod void QInstaller::languageChanged()
+
Calls languangeChanged on all components.
*/
void PackageManagerCore::languageChanged()
@@ -1646,7 +2050,7 @@ bool PackageManagerCore::updateComponentData(struct Data &data, Component *compo
// add downloadable archive from xml
const QStringList downloadableArchives = data.package->data(scDownloadableArchives).toString()
- .split(scCommaRegExp, QString::SkipEmptyParts);
+ .split(QInstaller::commaRegExp(), QString::SkipEmptyParts);
if (component->isFromOnlineRepository()) {
foreach (const QString downloadableArchive, downloadableArchives)
@@ -1654,7 +2058,7 @@ bool PackageManagerCore::updateComponentData(struct Data &data, Component *compo
}
const QStringList componentsToReplace = data.package->data(scReplaces).toString()
- .split(scCommaRegExp, QString::SkipEmptyParts);
+ .split(QInstaller::commaRegExp(), QString::SkipEmptyParts);
if (!componentsToReplace.isEmpty()) {
// Store the component (this is a component that replaces others) and all components that
@@ -1711,14 +2115,14 @@ void PackageManagerCore::storeReplacedComponents(QHash<QString, Component *> &co
qWarning() << componentName << "- Does not exist in the repositories anymore.";
continue;
}
- if (!component && !d->componentsToReplace(data.runMode).contains(componentName)) {
+ if (!component && !d->componentsToReplace().contains(componentName)) {
component = new Component(this);
component->setValue(scName, componentName);
} else {
component->loadComponentScript();
- d->replacementDependencyComponents(data.runMode).append(component);
+ d->replacementDependencyComponents().append(component);
}
- d->componentsToReplace(data.runMode).insert(componentName, qMakePair(it.key(), component));
+ d->componentsToReplace().insert(componentName, qMakePair(it.key(), component));
}
}
}
@@ -1731,7 +2135,6 @@ bool PackageManagerCore::fetchAllPackages(const PackagesList &remotes, const Loc
QHash<QString, QInstaller::Component*> components;
Data data;
- data.runMode = AllMode;
data.components = &components;
data.installedPackages = &locals;
@@ -1762,8 +2165,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;
}
@@ -1775,7 +2177,6 @@ bool PackageManagerCore::fetchUpdaterPackages(const PackagesList &remotes, const
QHash<QString, QInstaller::Component *> components;
Data data;
- data.runMode = UpdaterMode;
data.components = &components;
data.installedPackages = &locals;
@@ -1804,7 +2205,8 @@ bool PackageManagerCore::fetchUpdaterPackages(const PackagesList &remotes, const
bool isValidUpdate = locals.contains(name);
if (!isValidUpdate && !replaces.isEmpty()) {
- const QStringList possibleNames = replaces.split(scCommaRegExp, QString::SkipEmptyParts);
+ const QStringList possibleNames = replaces.split(QInstaller::commaRegExp(),
+ QString::SkipEmptyParts);
foreach (const QString &possibleName, possibleNames) {
if (locals.contains(possibleName)) {
isValidUpdate = true;
@@ -1813,7 +2215,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);
@@ -1851,14 +2255,18 @@ bool PackageManagerCore::fetchUpdaterPackages(const PackagesList &remotes, const
try {
if (!components.isEmpty()) {
- // load the scripts and append all components w/o parent to the direct list
+ // append all components w/o parent to the direct list
+ foreach (QInstaller::Component *component, components) {
+ appendUpdaterComponent(component);
+ }
+
+ // after everything is set up, load the scripts
foreach (QInstaller::Component *component, components) {
if (d->statusCanceledOrFailed())
return false;
component->loadComponentScript();
component->setCheckState(Qt::Checked);
- appendUpdaterComponent(component);
}
// after everything is set up, check installed components
@@ -1900,7 +2308,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.
@@ -1909,8 +2317,7 @@ bool PackageManagerCore::fetchUpdaterPackages(const PackagesList &remotes, const
return false;
}
- emit finishUpdaterComponentsReset();
- emit setRootComponents(d->m_updaterComponents);
+ emit finishUpdaterComponentsReset(d->m_updaterComponents);
return true;
}
@@ -1963,7 +2370,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,
@@ -1972,11 +2379,12 @@ 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(defaultCheckStateChanged(bool)), this, SLOT(componentsToInstallNeedsRecalculation()));
+ connect(model, SIGNAL(checkStateChanged(QInstaller::ComponentModel::ModelState)), this,
+ SLOT(componentsToInstallNeedsRecalculation()));
return model;
}
diff --git a/src/libs/installer/packagemanagercore.h b/src/libs/installer/packagemanagercore.h
index 50eb63184..20a3293fa 100644
--- a/src/libs/installer/packagemanagercore.h
+++ b/src/libs/installer/packagemanagercore.h
@@ -57,6 +57,7 @@ namespace QInstaller {
class Component;
class ComponentModel;
+class ScriptEngine;
class PackageManagerCorePrivate;
class Settings;
@@ -81,7 +82,8 @@ public:
Failure = EXIT_FAILURE,
Running,
Canceled,
- Unfinished
+ Unfinished,
+ ForceUpdate
};
Status status() const;
QString error() const;
@@ -121,7 +123,6 @@ public:
bool fetchRemotePackagesTree();
bool run();
- RunMode runMode() const;
void reset(const QHash<QString, QString> &params);
Q_INVOKABLE void setDependsOnLocalInstallerBinary();
@@ -157,6 +158,8 @@ public:
QStringList replaceVariables(const QStringList &str) const;
void writeUninstaller();
+ void writeMaintenanceConfigFiles();
+
QString uninstallerName() const;
QString installerBinaryPath() const;
@@ -174,7 +177,10 @@ public:
Q_INVOKABLE bool fileExists(const QString &filePath) const;
public:
+ ScriptEngine *scriptEngine();
+
// component handling
+
int rootComponentCount() const;
Component *rootComponent(int i) const;
QList<Component*> rootComponents() const;
@@ -268,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();
@@ -297,7 +302,6 @@ Q_SIGNALS:
private:
struct Data {
- RunMode runMode;
Package *package;
QHash<QString, Component*> *components;
const LocalPackagesHash *installedPackages;
diff --git a/src/libs/installer/packagemanagercore_p.cpp b/src/libs/installer/packagemanagercore_p.cpp
index 3cc44a7e5..a840d6d1e 100644
--- a/src/libs/installer/packagemanagercore_p.cpp
+++ b/src/libs/installer/packagemanagercore_p.cpp
@@ -43,10 +43,13 @@
#include "adminauthorization.h"
#include "binaryformat.h"
#include "component.h"
+#include "scriptengine.h"
#include "componentmodel.h"
#include "errors.h"
#include "fileutils.h"
#include "fsengineclient.h"
+#include "globals.h"
+#include "graph.h"
#include "messageboxhandler.h"
#include "packagemanagercore.h"
#include "progresscoordinator.h"
@@ -58,7 +61,6 @@
#include "kdupdaterfiledownloaderfactory.h"
#include "kdupdaterupdatesourcesinfo.h"
#include "kdupdaterupdateoperationfactory.h"
-#include "kdupdaterupdatefinder.h"
#include <productkeycheck.h>
@@ -94,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(", ")));
}
@@ -201,6 +204,7 @@ static void deferredRename(const QString &oldName, const QString &newName, bool
PackageManagerCorePrivate::PackageManagerCorePrivate(PackageManagerCore *core)
: m_updateFinder(0)
+ , m_updaterApplication(new DummyConfigurationInterface)
, m_FSEngineClientHandler(0)
, m_core(core)
, m_repoMetaInfoJob(0)
@@ -208,6 +212,7 @@ PackageManagerCorePrivate::PackageManagerCorePrivate(PackageManagerCore *core)
, m_repoFetched(false)
, m_updateSourcesAdded(false)
, m_componentsToInstallCalculated(false)
+ , m_scriptEngine(0)
, m_proxyFactory(0)
, m_defaultModel(0)
, m_updaterModel(0)
@@ -217,6 +222,7 @@ PackageManagerCorePrivate::PackageManagerCorePrivate(PackageManagerCore *core)
PackageManagerCorePrivate::PackageManagerCorePrivate(PackageManagerCore *core, qint64 magicInstallerMaker,
const OperationList &performedOperations)
: m_updateFinder(0)
+ , m_updaterApplication(new DummyConfigurationInterface)
, m_FSEngineClientHandler(initFSEngineClientHandler())
, m_status(PackageManagerCore::Unfinished)
, m_forceRestart(false)
@@ -233,6 +239,7 @@ PackageManagerCorePrivate::PackageManagerCorePrivate(PackageManagerCore *core, q
, m_updateSourcesAdded(false)
, m_magicBinaryMarker(magicInstallerMaker)
, m_componentsToInstallCalculated(false)
+ , m_scriptEngine(0)
, m_proxyFactory(0)
, m_defaultModel(0)
, m_updaterModel(0)
@@ -258,6 +265,7 @@ PackageManagerCorePrivate::~PackageManagerCorePrivate()
m_FSEngineClientHandler->setActive(false);
delete m_updateFinder;
+ delete m_scriptEngine;
delete m_proxyFactory;
delete m_defaultModel;
@@ -373,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.
@@ -384,6 +392,13 @@ bool PackageManagerCorePrivate::buildComponentTree(QHash<QString, Component*> &c
return true;
}
+ScriptEngine *PackageManagerCorePrivate::scriptEngine()
+{
+ if (!m_scriptEngine)
+ m_scriptEngine = new ScriptEngine(m_core);
+ return m_scriptEngine;
+}
+
void PackageManagerCorePrivate::clearAllComponentLists()
{
qDeleteAll(m_rootComponents);
@@ -422,14 +437,14 @@ void PackageManagerCorePrivate::clearUpdaterComponentLists()
m_componentsToInstallCalculated = false;
}
-QList<Component *> &PackageManagerCorePrivate::replacementDependencyComponents(RunMode mode)
+QList<Component *> &PackageManagerCorePrivate::replacementDependencyComponents()
{
- return mode == AllMode ? m_rootDependencyReplacements : m_updaterDependencyReplacements;
+ return (!isUpdater()) ? m_rootDependencyReplacements : m_updaterDependencyReplacements;
}
-QHash<QString, QPair<Component*, Component*> > &PackageManagerCorePrivate::componentsToReplace(RunMode mode)
+QHash<QString, QPair<Component*, Component*> > &PackageManagerCorePrivate::componentsToReplace()
{
- return mode == AllMode ? m_componentsToReplaceAllMode : m_componentsToReplaceUpdaterMode;
+ return (!isUpdater()) ? m_componentsToReplaceAllMode : m_componentsToReplaceUpdaterMode;
}
void PackageManagerCorePrivate::clearComponentsToInstall()
@@ -453,7 +468,7 @@ bool PackageManagerCorePrivate::appendComponentsToInstall(const QList<Component
relevantComponentForAutoDependOn = m_updaterComponents + m_updaterComponentsDeps;
else {
foreach (QInstaller::Component *component, m_rootComponents)
- relevantComponentForAutoDependOn += component->childComponents(true, AllMode);
+ relevantComponentForAutoDependOn += component->childComponents(Component::Descendants);
}
QList<Component*> notAppendedComponents; // for example components with unresolved dependencies
@@ -557,13 +572,13 @@ QString PackageManagerCorePrivate::installReason(Component *component)
void PackageManagerCorePrivate::initialize(const QHash<QString, QString> &params)
{
- if (!ProductKeyCheck::instance()->hasValidKey()) {
+ if (!ProductKeyCheck::instance(m_core)->hasValidKey()) {
if (m_core->isInstaller()) {
- setStatus(PackageManagerCore::Failure, ProductKeyCheck::instance()->lastErrorString());
+ setStatus(PackageManagerCore::Failure, ProductKeyCheck::instance(m_core)->lastErrorString());
} else {
MessageBoxHandler::warning(MessageBoxHandler::currentBestSuitParent(),
- QLatin1String("ProductKeyCheckError"), ProductKeyCheck::instance()->lastErrorString(),
- ProductKeyCheck::instance()->maintainanceToolDetailErrorNotice(), QMessageBox::Ok);
+ QLatin1String("ProductKeyCheckError"), ProductKeyCheck::instance(m_core)->lastErrorString(),
+ ProductKeyCheck::instance(m_core)->maintainanceToolDetailErrorNotice(), QMessageBox::Ok);
}
}
@@ -617,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)));
@@ -769,13 +784,22 @@ static QSet<Repository> readRepositories(QXmlStreamReader &reader, bool isDefaul
void PackageManagerCorePrivate::writeMaintenanceConfigFiles()
{
+ bool gainedAdminRights = false;
// write current state (variables) to the uninstaller ini file
const QString iniPath = targetDir() + QLatin1Char('/') + m_data.settings().uninstallerIniFile();
+ {
+ QFile tmp(iniPath); // force gaining admin rights in case we haven't done already and we need it
+ if (!tmp.open(QIODevice::ReadWrite) || !tmp.isWritable()) {
+ if (!m_FSEngineClientHandler->isActive()) // check if nobody did it before...
+ gainedAdminRights = m_core->gainAdminRights();
+ }
+ tmp.close();
+ }
QVariantHash variables;
QSettingsWrapper cfg(iniPath, QSettingsWrapper::IniFormat);
foreach (const QString &key, m_data.keys()) {
- if (key != scRunProgramDescription && key != scRunProgram)
+ if (key != scRunProgramDescription && key != scRunProgram && key != scRunProgramArguments)
variables.insert(key, m_data.value(key));
}
cfg.setValue(QLatin1String("Variables"), variables);
@@ -787,6 +811,8 @@ void PackageManagerCorePrivate::writeMaintenanceConfigFiles()
cfg.sync();
if (cfg.status() != QSettingsWrapper::NoError) {
+ if (gainedAdminRights)
+ m_core->dropAdminRights();
const QString reason = cfg.status() == QSettingsWrapper::AccessError ? tr("Access error")
: tr("Format error");
throw Error(tr("Could not write installer configuration to %1: %2").arg(iniPath, reason));
@@ -828,6 +854,9 @@ void PackageManagerCorePrivate::writeMaintenanceConfigFiles()
writer.writeEndElement();
writer.writeEndElement();
}
+
+ if (gainedAdminRights)
+ m_core->dropAdminRights();
}
void PackageManagerCorePrivate::readMaintenanceConfigFiles(const QString &targetDir)
@@ -1301,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
@@ -1584,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)
@@ -1636,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();
}
@@ -1837,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)
@@ -1990,25 +2031,21 @@ 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(m_core->runMode()).value(componentName).second;
+ component = componentsToReplace().value(componentName).second;
if (component) {
component->setUninstalled();
packages.removePackage(component->name());
@@ -2041,7 +2078,6 @@ PackagesList PackageManagerCorePrivate::remotePackages()
m_updateFinder = new KDUpdater::UpdateFinder(&m_updaterApplication);
m_updateFinder->setAutoDelete(false);
- m_updateFinder->setUpdateType(KDUpdater::PackageUpdate | KDUpdater::NewPackage);
m_updateFinder->run();
if (m_updateFinder->updates().isEmpty()) {
@@ -2285,8 +2321,8 @@ bool PackageManagerCorePrivate::appendComponentsToUninstall(const QList<Componen
foreach (Component *c, installedComponents) {
const QString replaces = c->value(scReplaces);
- QStringList possibleNames = replaces.split(scCommaRegExp, QString::SkipEmptyParts);
- possibleNames.append(c->name());
+ const QStringList possibleNames = replaces.split(QInstaller::commaRegExp(),
+ QString::SkipEmptyParts) << c->name();
foreach (const QString &possibleName, possibleNames)
autoDependencies.removeAll(possibleName);
}
@@ -2333,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 9d4a6abab..d5bdc78fd 100644
--- a/src/libs/installer/packagemanagercore_p.h
+++ b/src/libs/installer/packagemanagercore_p.h
@@ -43,18 +43,16 @@
#define PACKAGEMANAGERCORE_P_H
#include "getrepositoriesmetainfojob.h"
-#include "settings.h"
#include "packagemanagercore.h"
#include "packagemanagercoredata.h"
+#include "qinstallerglobal.h"
-#include <kdsysinfo.h>
-#include <kdupdaterapplication.h>
-#include <kdupdaterupdatefinder.h>
+#include "kdsysinfo.h"
+#include "kdupdaterapplication.h"
+#include "kdupdaterfiledownloaderfactory.h"
+#include "kdupdaterupdatefinder.h"
-#include <QtCore/QHash>
-#include <QtCore/QObject>
-#include <QtCore/QPair>
-#include <QtCore/QPointer>
+#include <QObject>
class FSEngineClientHandler;
class KDJob;
@@ -68,9 +66,31 @@ namespace QInstaller {
struct BinaryLayout;
class Component;
+class ScriptEngine;
class ComponentModel;
class TempDirDeleter;
+/*
+ The default configuration interface implementation does call QSettings to save files for later deletion,
+ though according to QSettings there should nothing be written if QSettings is not setup properly (which
+ we do not in our case). Still, caused by a broken QSettings implementation at least on Linux we write an
+ empty config file which resulted in QTIFW-196. To workaround the issue we now use this empty dummy class.
+*/
+class DummyConfigurationInterface : public KDUpdater::ConfigurationInterface
+{
+public:
+ QVariant value(const QString &key) const
+ {
+ Q_UNUSED(key)
+ return QVariant();
+ }
+ void setValue(const QString &key, const QVariant &value)
+ {
+ if (value.isNull())
+ qDebug() << "DummyConfigurationInterface called with key:" << key << "and value:" << value;
+ }
+};
+
class PackageManagerCorePrivate : public QObject
{
Q_OBJECT
@@ -115,10 +135,11 @@ public:
bool buildComponentTree(QHash<QString, Component*> &components, bool loadScript);
+ ScriptEngine *scriptEngine();
void clearAllComponentLists();
void clearUpdaterComponentLists();
- QList<Component*> &replacementDependencyComponents(RunMode mode);
- QHash<QString, QPair<Component*, Component*> > &componentsToReplace(RunMode mode);
+ QList<Component*> &replacementDependencyComponents();
+ QHash<QString, QPair<Component*, Component*> > &componentsToReplace();
void clearComponentsToInstall();
bool appendComponentsToInstall(const QList<Component*> &components);
@@ -146,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);
@@ -241,6 +263,7 @@ private:
qint64 m_magicBinaryMarker;
bool m_componentsToInstallCalculated;
+ ScriptEngine *m_scriptEngine;
// < name (component to replace), < replacement component, component to replace > >
QHash<QString, QPair<Component*, Component*> > m_componentsToReplaceAllMode;
QHash<QString, QPair<Component*, Component*> > m_componentsToReplaceUpdaterMode;
diff --git a/src/libs/installer/packagemanagercoredata.cpp b/src/libs/installer/packagemanagercoredata.cpp
index 7dbdf4e1a..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
@@ -90,6 +92,7 @@ PackageManagerCoreData::PackageManagerCoreData(const QHash<QString, QString> &va
m_variables.insert(scTargetConfigurationFile, m_settings.configurationFileName());
m_variables.insert(QLatin1String("LogoPixmap"), m_settings.logo());
m_variables.insert(QLatin1String("WatermarkPixmap"), m_settings.watermark());
+ m_variables.insert(QLatin1String("BannerPixmap"), m_settings.banner());
const QString description = m_settings.runProgramDescription();
if (!description.isEmpty())
@@ -97,6 +100,7 @@ PackageManagerCoreData::PackageManagerCoreData(const QHash<QString, QString> &va
m_variables.insert(scTargetDir, replaceVariables(m_settings.targetDir()));
m_variables.insert(scRunProgram, replaceVariables(m_settings.runProgram()));
+ m_variables.insert(scRunProgramArguments, replaceVariables(m_settings.runProgramArguments()));
m_variables.insert(scRemoveTargetDir, replaceVariables(m_settings.removeTargetDir()));
}
diff --git a/src/libs/installer/packagemanagergui.cpp b/src/libs/installer/packagemanagergui.cpp
index 1e01e69ff..4ce38a388 100644
--- a/src/libs/installer/packagemanagergui.cpp
+++ b/src/libs/installer/packagemanagergui.cpp
@@ -46,11 +46,11 @@
#include "fileutils.h"
#include "messageboxhandler.h"
#include "packagemanagercore.h"
-#include "qinstallerglobal.h"
#include "progresscoordinator.h"
#include "performinstallationform.h"
#include "settings.h"
#include "utils.h"
+#include "scriptengine.h"
#include "kdsysinfo.h"
@@ -85,8 +85,6 @@
#include <QScrollBar>
#include <QShowEvent>
-#include <QtScript/QScriptEngine>
-
using namespace KDUpdater;
using namespace QInstaller;
@@ -134,6 +132,7 @@ public:
setObjectName(QLatin1String("Dynamic") + widget->objectName());
setPixmap(QWizard::LogoPixmap, logoPixmap());
setPixmap(QWizard::WatermarkPixmap, QPixmap());
+ setPixmap(QWizard::BannerPixmap, QPixmap());
setLayout(new QVBoxLayout);
setSubTitle(QString());
@@ -216,19 +215,13 @@ public:
QHash<int, QWizardPage*> m_defaultPages;
QHash<int, QString> m_defaultButtonText;
- QScriptValue m_controlScript;
- QScriptEngine m_controlScriptEngine;
+ QScriptValue m_controlScriptContext;
QHash<QWizard::WizardButton, QString> m_wizardButtonTypes;
};
// -- PackageManagerGui
-QScriptEngine *PackageManagerGui::controlScriptEngine() const
-{
- return &d->m_controlScriptEngine;
-}
-
/*!
\class QInstaller::PackageManagerGui
Is the "gui" object in a none interactive installation
@@ -244,7 +237,7 @@ PackageManagerGui::PackageManagerGui(PackageManagerCore *core, QWidget *parent)
setWindowTitle(tr("Maintain %1").arg(m_core->value(scTitle)));
#ifndef Q_OS_MAC
- setWindowIcon(QIcon(m_core->settings().icon()));
+ setWindowIcon(QIcon(m_core->settings().installerWindowIcon()));
#else
setPixmap(QWizard::BackgroundPixmap, m_core->settings().background());
#endif
@@ -292,6 +285,8 @@ PackageManagerGui::PackageManagerGui(PackageManagerCore *core, QWidget *parent)
for (int i = QWizard::BackButton; i < QWizard::CustomButton1; ++i)
d->m_defaultButtonText.insert(i, buttonText(QWizard::WizardButton(i)));
+
+ m_core->scriptEngine()->setGuiQObject(this);
}
PackageManagerGui::~PackageManagerGui()
@@ -311,20 +306,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;
}
@@ -350,58 +355,8 @@ void PackageManagerGui::setValidatorForCustomPageRequested(Component *component,
*/
void PackageManagerGui::loadControlScript(const QString &scriptPath)
{
- QFile file(scriptPath);
- if (!file.open(QIODevice::ReadOnly)) {
- throw Error(QObject::tr("Could not open the requested script file at %1: %2")
- .arg(scriptPath, file.errorString()));
- }
-
- QScriptValue installerObject = d->m_controlScriptEngine.newQObject(m_core);
- installerObject.setProperty(QLatin1String("componentByName"), d->m_controlScriptEngine
- .newFunction(qInstallerComponentByName, 1));
-
- d->m_controlScriptEngine.globalObject().setProperty(QLatin1String("installer"),
- installerObject);
- d->m_controlScriptEngine.globalObject().setProperty(QLatin1String("gui"),
- d->m_controlScriptEngine.newQObject(this));
- d->m_controlScriptEngine.globalObject().setProperty(QLatin1String("packagemanagergui"),
- d->m_controlScriptEngine.newQObject(this));
- registerMessageBox(&d->m_controlScriptEngine);
-
-#undef REGISTER_BUTTON
-#define REGISTER_BUTTON(x) buttons.setProperty(QLatin1String(#x), \
- d->m_controlScriptEngine.newVariant(static_cast<int>(QWizard::x)));
-
- QScriptValue buttons = d->m_controlScriptEngine.newArray();
- REGISTER_BUTTON(BackButton)
- REGISTER_BUTTON(NextButton)
- REGISTER_BUTTON(CommitButton)
- REGISTER_BUTTON(FinishButton)
- REGISTER_BUTTON(CancelButton)
- REGISTER_BUTTON(HelpButton)
- REGISTER_BUTTON(CustomButton1)
- REGISTER_BUTTON(CustomButton2)
- REGISTER_BUTTON(CustomButton3)
-
-#undef REGISTER_BUTTON
-
- d->m_controlScriptEngine.globalObject().setProperty(QLatin1String("buttons"), buttons);
-
- d->m_controlScriptEngine.evaluate(QLatin1String(file.readAll()), scriptPath);
- if (d->m_controlScriptEngine.hasUncaughtException()) {
- throw Error(QObject::tr("Exception while loading the control script %1")
- .arg(uncaughtExceptionString(&(d->m_controlScriptEngine)/*, scriptPath*/)));
- }
-
- QScriptValue comp = d->m_controlScriptEngine.evaluate(QLatin1String("Controller"));
- if (d->m_controlScriptEngine.hasUncaughtException()) {
- throw Error(QObject::tr("Exception while loading the control script %1")
- .arg(uncaughtExceptionString(&(d->m_controlScriptEngine)/*, scriptPath*/)));
- }
-
- d->m_controlScript = comp;
- d->m_controlScript.construct();
-
+ d->m_controlScriptContext = m_core->scriptEngine()->loadInConext(
+ QLatin1String("Controller"), scriptPath);
qDebug() << "Loaded control script" << scriptPath;
}
@@ -413,24 +368,18 @@ void PackageManagerGui::slotCurrentPageChanged(int id)
void PackageManagerGui::callControlScriptMethod(const QString &methodName)
{
- if (!d->m_controlScript.isValid())
- return;
-
- QScriptValue method = d->m_controlScript.property(QLatin1String("prototype")).property(methodName);
-
- if (!method.isValid()) {
- qDebug() << "Control script callback" << methodName << "does not exist.";
+ if (!d->m_controlScriptContext.isValid())
return;
- }
-
- qDebug() << "Calling control script callback" << methodName;
-
- method.call(d->m_controlScript);
+ try {
+ QScriptValue returnValue = m_core->scriptEngine()->callScriptMethod(
+ d->m_controlScriptContext, methodName);
- if (d->m_controlScriptEngine.hasUncaughtException()) {
- qCritical()
- << uncaughtExceptionString(&(d->m_controlScriptEngine) /*, QLatin1String("control script")*/);
- // TODO: handle error
+ if (!returnValue.isValid()) {
+ qDebug() << "Control script callback" << methodName << "does not exist.";
+ return;
+ }
+ } catch (const QInstaller::Error &e) {
+ qCritical() << qPrintable(e.message());
}
}
@@ -461,7 +410,6 @@ bool PackageManagerGui::event(QEvent *event)
void PackageManagerGui::showEvent(QShowEvent *event)
{
-#ifndef Q_OS_LINUX
if (!event->spontaneous()) {
foreach (int id, pageIds()) {
const QString subTitle = page(id)->subTitle();
@@ -472,7 +420,6 @@ void PackageManagerGui::showEvent(QShowEvent *event)
}
}
}
-#endif
QWizard::showEvent(event);
QMetaObject::invokeMethod(this, "dependsOnLocalInstallerBinary", Qt::QueuedConnection);
}
@@ -692,6 +639,9 @@ PackageManagerPage::PackageManagerPage(PackageManagerCore *core)
, m_core(core)
, validatorComponent(0)
{
+ setPixmap(QWizard::WatermarkPixmap, watermarkPixmap());
+ setPixmap(QWizard::BannerPixmap, bannerPixmap());
+ setPixmap(QWizard::LogoPixmap, logoPixmap());
}
PackageManagerCore *PackageManagerPage::packageManagerCore() const
@@ -699,44 +649,14 @@ PackageManagerCore *PackageManagerPage::packageManagerCore() const
return m_core;
}
-QVariantHash PackageManagerPage::elementsForPage(const QString &pageName) const
-{
- const QVariant variant = m_core->settings().value(pageName);
-
- QVariantHash hash;
- if (variant.canConvert<QVariantHash>())
- hash = variant.value<QVariantHash>();
- return hash;
-}
-
-QString PackageManagerPage::titleForPage(const QString &pageName, const QString &value) const
-{
- return titleFromHash(m_core->settings().titlesForPage(pageName), value);
-}
-
-QString PackageManagerPage::subTitleForPage(const QString &pageName, const QString &value) const
-{
- return titleFromHash(m_core->settings().subTitlesForPage(pageName), value);
-}
-
-QString PackageManagerPage::titleFromHash(const QVariantHash &hash, const QString &value) const
+QPixmap PackageManagerPage::watermarkPixmap() const
{
- QString defaultValue = hash.value(QLatin1String("Default")).toString();
- if (defaultValue.isEmpty())
- defaultValue = value;
-
- if (m_core->isUpdater())
- return hash.value(QLatin1String("Updater"), defaultValue).toString();
- if (m_core->isInstaller())
- return hash.value(QLatin1String("Installer"), defaultValue).toString();
- if (m_core->isPackageManager())
- return hash.value(QLatin1String("PackageManager"), defaultValue).toString();
- return hash.value(QLatin1String("Uninstaller"), defaultValue).toString();
+ return QPixmap(m_core->value(QLatin1String("WatermarkPixmap")));
}
-QPixmap PackageManagerPage::watermarkPixmap() const
+QPixmap PackageManagerPage::bannerPixmap() const
{
- return QPixmap(m_core->value(QLatin1String("WatermarkPixmap")));
+ return QPixmap(m_core->value(QLatin1String("BannerPixmap")));
}
QPixmap PackageManagerPage::logoPixmap() const
@@ -815,10 +735,13 @@ void PackageManagerPage::setVisible(bool visible)
return;
}
- if (visible)
+ if (visible) {
entering();
- else
+ emit entered();
+ } else {
leaving();
+ emit left();
+ }
}
int PackageManagerPage::nextId() const
@@ -851,16 +774,12 @@ IntroductionPage::IntroductionPage(PackageManagerCore *core)
, m_widget(0)
{
setObjectName(QLatin1String("IntroductionPage"));
- setPixmap(QWizard::WatermarkPixmap, watermarkPixmap());
- setSubTitle(subTitleForPage(QLatin1String("IntroductionPage")));
- setTitle(titleForPage(QLatin1String("IntroductionPage"), tr("Setup - %1")).arg(productName()));
+ setTitle(tr("Setup - %1").arg(productName()));
m_msgLabel = new QLabel(this);
m_msgLabel->setWordWrap(true);
m_msgLabel->setObjectName(QLatin1String("MessageLabel"));
- const QVariantHash hash = elementsForPage(QLatin1String("IntroductionPage"));
- m_msgLabel->setText(hash.value(QLatin1String("MessageLabel"), tr("Welcome to the %1 "
- "Setup Wizard.")).toString().arg(productName()));
+ m_msgLabel->setText(tr("Welcome to the %1 Setup Wizard.").arg(productName()));
QVBoxLayout *layout = new QVBoxLayout(this);
setLayout(layout);
@@ -916,10 +835,9 @@ private:
LicenseAgreementPage::LicenseAgreementPage(PackageManagerCore *core)
: PackageManagerPage(core)
{
- setPixmap(QWizard::LogoPixmap, logoPixmap());
setPixmap(QWizard::WatermarkPixmap, QPixmap());
setObjectName(QLatin1String("LicenseAgreementPage"));
- setTitle(titleForPage(QLatin1String("LicenseAgreementPage"), tr("License Agreement")));
+ setTitle(tr("License Agreement"));
m_licenseListWidget = new QListWidget(this);
m_licenseListWidget->setObjectName(QLatin1String("LicenseListWidget"));
@@ -1046,11 +964,10 @@ void LicenseAgreementPage::updateUi()
rejectButtonText = tr("I do not accept the licenses.");
}
- setSubTitle(subTitleForPage(QLatin1String("LicenseAgreementPage"), subTitleText));
+ setSubTitle(subTitleText);
- const QVariantHash hash = elementsForPage(QLatin1String("LicenseAgreementPage"));
- m_acceptLabel->setText(hash.value(QLatin1String("AcceptLicenseLabel"), acceptButtonText).toString());
- m_rejectLabel->setText(hash.value(QLatin1String("RejectLicenseLabel"), rejectButtonText).toString());
+ m_acceptLabel->setText(acceptButtonText);
+ m_rejectLabel->setText(rejectButtonText);
}
@@ -1072,8 +989,10 @@ public:
{
m_treeView->setObjectName(QLatin1String("ComponentsTreeView"));
- connect(m_allModel, SIGNAL(defaultCheckStateChanged(bool)), q, SLOT(setModified(bool)));
- connect(m_updaterModel, SIGNAL(defaultCheckStateChanged(bool)), q, SLOT(setModified(bool)));
+ connect(m_allModel, SIGNAL(checkStateChanged(QInstaller::ComponentModel::ModelState)), this,
+ SLOT(onModelStateChanged(QInstaller::ComponentModel::ModelState)));
+ connect(m_updaterModel, SIGNAL(checkStateChanged(QInstaller::ComponentModel::ModelState)), this,
+ SLOT(onModelStateChanged(QInstaller::ComponentModel::ModelState)));
QHBoxLayout *hlayout = new QHBoxLayout;
hlayout->addWidget(m_treeView, 3);
@@ -1099,18 +1018,15 @@ public:
m_checkDefault = new QPushButton;
connect(m_checkDefault, SIGNAL(clicked()), this, SLOT(selectDefault()));
- connect(m_allModel, SIGNAL(defaultCheckStateChanged(bool)), m_checkDefault, SLOT(setEnabled(bool)));
- const QVariantHash hash = q->elementsForPage(QLatin1String("ComponentSelectionPage"));
if (m_core->isInstaller()) {
m_checkDefault->setObjectName(QLatin1String("SelectDefaultComponentsButton"));
m_checkDefault->setShortcut(QKeySequence(ComponentSelectionPage::tr("Alt+A", "select default components")));
- m_checkDefault->setText(hash.value(QLatin1String("SelectDefaultComponentsButton"), ComponentSelectionPage::tr("Def&ault"))
- .toString());
+ m_checkDefault->setText(ComponentSelectionPage::tr("Def&ault"));
} else {
m_checkDefault->setEnabled(false);
m_checkDefault->setObjectName(QLatin1String("ResetComponentsButton"));
m_checkDefault->setShortcut(QKeySequence(ComponentSelectionPage::tr("Alt+R", "reset to already installed components")));
- m_checkDefault->setText(hash.value(QLatin1String("ResetComponentsButton"), ComponentSelectionPage::tr("&Reset")).toString());
+ m_checkDefault->setText(ComponentSelectionPage::tr("&Reset"));
}
hlayout = new QHBoxLayout;
hlayout->addWidget(m_checkDefault);
@@ -1120,15 +1036,14 @@ public:
connect(m_checkAll, SIGNAL(clicked()), this, SLOT(selectAll()));
m_checkAll->setObjectName(QLatin1String("SelectAllComponentsButton"));
m_checkAll->setShortcut(QKeySequence(ComponentSelectionPage::tr("Alt+S", "select all components")));
- m_checkAll->setText(hash.value(QLatin1String("SelectAllComponentsButton"), ComponentSelectionPage::tr("&Select All")).toString());
+ m_checkAll->setText(ComponentSelectionPage::tr("&Select All"));
m_uncheckAll = new QPushButton;
hlayout->addWidget(m_uncheckAll);
connect(m_uncheckAll, SIGNAL(clicked()), this, SLOT(deselectAll()));
m_uncheckAll->setObjectName(QLatin1String("DeselectAllComponentsButton"));
m_uncheckAll->setShortcut(QKeySequence(ComponentSelectionPage::tr("Alt+D", "deselect all components")));
- m_uncheckAll->setText(hash.value(QLatin1String("DeselectAllComponentsButton"), ComponentSelectionPage::tr("&Deselect All"))
- .toString());
+ m_uncheckAll->setText(ComponentSelectionPage::tr("&Deselect All"));
hlayout->addSpacerItem(new QSpacerItem(1, 1, QSizePolicy::MinimumExpanding,
QSizePolicy::MinimumExpanding));
@@ -1140,9 +1055,7 @@ public:
m_checkDefault->setVisible(m_core->isInstaller() || m_core->isPackageManager());
if (m_treeView->selectionModel()) {
disconnect(m_treeView->selectionModel(), SIGNAL(currentChanged(QModelIndex, QModelIndex)),
- this, SLOT(currentChanged(QModelIndex)));
- disconnect(m_currentModel, SIGNAL(checkStateChanged(QModelIndex)), this,
- SLOT(currentChanged(QModelIndex)));
+ this, SLOT(currentSelectedChanged(QModelIndex)));
}
m_currentModel = m_core->isUpdater() ? m_updaterModel : m_allModel;
@@ -1166,61 +1079,63 @@ public:
m_treeView->setRootIsDecorated(hasChildren);
connect(m_treeView->selectionModel(), SIGNAL(currentChanged(QModelIndex, QModelIndex)),
- this, SLOT(currentChanged(QModelIndex)));
- connect(m_currentModel, SIGNAL(checkStateChanged(QModelIndex)), this,
- SLOT(currentChanged(QModelIndex)));
+ this, SLOT(currentSelectedChanged(QModelIndex)));
m_treeView->setCurrentIndex(m_currentModel->index(0, 0));
}
public slots:
- void currentChanged(const QModelIndex &current)
+ void currentSelectedChanged(const QModelIndex &current)
{
- // if there is not selection or the current selected node didn't change, return
- if (!current.isValid() || current != m_treeView->selectionModel()->currentIndex())
+ if (!current.isValid())
return;
+ m_sizeLabel->setText(QString());
m_descriptionLabel->setText(m_currentModel->data(m_currentModel->index(current.row(),
ComponentModelHelper::NameColumn, current.parent()), Qt::ToolTipRole).toString());
- m_sizeLabel->clear();
- if (!m_core->isUninstaller()) {
- Component *component = m_currentModel->componentFromIndex(current);
- if (component && component->updateUncompressedSize() > 0) {
- const QVariantHash hash = q->elementsForPage(QLatin1String("ComponentSelectionPage"));
- m_sizeLabel->setText(hash.value(QLatin1String("ComponentSizeLabel"),
- ComponentSelectionPage::tr("This component will occupy approximately %1 on your hard disk drive.")).toString()
- .arg(m_currentModel->data(m_currentModel->index(current.row(),
- ComponentModelHelper::UncompressedSizeColumn, current.parent())).toString()));
- }
+ Component *component = m_currentModel->componentFromIndex(current);
+ if ((m_core->isUninstaller()) || (!component))
+ return;
+
+ 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())));
}
}
- // TODO: all *select* function ignore the fact that components can be selected inside the tree view as
- // well, which will result in e.g. a disabled button state as long as "ALL" components not
- // unchecked again.
void selectAll()
{
- m_currentModel->selectAll();
-
- m_checkAll->setEnabled(false);
- m_uncheckAll->setEnabled(true);
+ m_currentModel->setCheckedState(ComponentModel::AllChecked);
}
void deselectAll()
{
- m_currentModel->deselectAll();
-
- m_checkAll->setEnabled(true);
- m_uncheckAll->setEnabled(false);
+ m_currentModel->setCheckedState(ComponentModel::AllUnchecked);
}
void selectDefault()
{
- m_currentModel->selectDefault();
+ m_currentModel->setCheckedState(ComponentModel::DefaultChecked);
+ }
- m_checkAll->setEnabled(true);
- m_uncheckAll->setEnabled(true);
+ void onModelStateChanged(QInstaller::ComponentModel::ModelState state)
+ {
+ 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()))
+ state |= ComponentModel::AllUnchecked;
+
+ // enable the button if the corresponding flag is not set
+ 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:
@@ -1248,10 +1163,9 @@ ComponentSelectionPage::ComponentSelectionPage(PackageManagerCore *core)
: PackageManagerPage(core)
, d(new Private(this, core))
{
- setPixmap(QWizard::LogoPixmap, logoPixmap());
setPixmap(QWizard::WatermarkPixmap, QPixmap());
setObjectName(QLatin1String("ComponentSelectionPage"));
- setTitle(titleForPage(QLatin1String("ComponentSelectionPage"), tr("Select Components")));
+ setTitle(tr("Select Components"));
}
ComponentSelectionPage::~ComponentSelectionPage()
@@ -1273,7 +1187,7 @@ void ComponentSelectionPage::entering()
if (core->isInstaller()) index = 1;
if (core->isUninstaller()) index = 2;
if (core->isPackageManager()) index = 3;
- setSubTitle(subTitleForPage(QLatin1String("ComponentSelectionPage"), tr(strings[index])));
+ setSubTitle(tr(strings[index]));
d->updateTreeView();
setModified(isComplete());
@@ -1331,8 +1245,8 @@ void ComponentSelectionPage::setModified(bool modified)
bool ComponentSelectionPage::isComplete() const
{
if (packageManagerCore()->isInstaller() || packageManagerCore()->isUpdater())
- return d->m_currentModel->hasCheckedComponents();
- return !d->m_currentModel->defaultCheckState();
+ return d->m_currentModel->checked().count();
+ return d->m_currentModel->checkedState().testFlag(ComponentModel::DefaultChecked) == false;
}
@@ -1341,20 +1255,16 @@ bool ComponentSelectionPage::isComplete() const
TargetDirectoryPage::TargetDirectoryPage(PackageManagerCore *core)
: PackageManagerPage(core)
{
- setPixmap(QWizard::LogoPixmap, logoPixmap());
setPixmap(QWizard::WatermarkPixmap, QPixmap());
setObjectName(QLatin1String("TargetDirectoryPage"));
- setSubTitle(subTitleForPage(QLatin1String("TargetDirectoryPage")));
- setTitle(titleForPage(QLatin1String("TargetDirectoryPage"), tr("Installation Folder")));
+ setTitle(tr("Installation Folder"));
QVBoxLayout *layout = new QVBoxLayout(this);
QLabel *msgLabel = new QLabel(this);
msgLabel->setWordWrap(true);
msgLabel->setObjectName(QLatin1String("MessageLabel"));
- const QVariantHash hash = elementsForPage(QLatin1String("TargetDirectoryPage"));
- msgLabel->setText(hash.value(QLatin1String("MessageLabel"), tr("Please specify the folder "
- "where %1 will be installed.")).toString().arg(productName()));
+ msgLabel->setText(tr("Please specify the folder where %1 will be installed.").arg(productName()));
layout->addWidget(msgLabel);
QHBoxLayout *hlayout = new QHBoxLayout;
@@ -1368,8 +1278,7 @@ TargetDirectoryPage::TargetDirectoryPage(PackageManagerCore *core)
browseButton->setObjectName(QLatin1String("BrowseDirectoryButton"));
connect(browseButton, SIGNAL(clicked()), this, SLOT(dirRequested()));
browseButton->setShortcut(QKeySequence(tr("Alt+R", "browse file system to choose a file")));
- browseButton->setText(hash.value(QLatin1String("BrowseDirectoryButton"), tr("B&rowse..."))
- .toString());
+ browseButton->setText(tr("B&rowse..."));
hlayout->addWidget(browseButton);
layout->addLayout(hlayout);
@@ -1403,12 +1312,10 @@ void TargetDirectoryPage::initializePage()
bool TargetDirectoryPage::validatePage()
{
- const QVariantHash hash = elementsForPage(QLatin1String("TargetDirectoryPage"));
if (targetDir().isEmpty()) {
MessageBoxHandler::critical(MessageBoxHandler::currentBestSuitParent(),
- QLatin1String("EmptyTargetDirectoryMessage"), tr("Error"), hash
- .value(QLatin1String("EmptyTargetDirectoryMessage"), tr("The install directory cannot be "
- "empty, please specify a valid folder.")).toString(), QMessageBox::Ok);
+ QLatin1String("EmptyTargetDirectoryMessage"), tr("Error"), tr("The install directory cannot be "
+ "empty, please specify a valid folder."), QMessageBox::Ok);
return false;
}
@@ -1421,9 +1328,8 @@ bool TargetDirectoryPage::validatePage()
// it exists, but is not empty
if (dir == QDir::root()) {
MessageBoxHandler::critical(MessageBoxHandler::currentBestSuitParent(),
- QLatin1String("ForbiddenTargetDirectoryMessage"), tr("Error"), hash
- .value(QLatin1String("ForbiddenTargetDirectoryMessage"), tr("As the install directory is "
- "completely deleted, installing in %1 is forbidden.")).toString().arg(QDir::rootPath()),
+ QLatin1String("ForbiddenTargetDirectoryMessage"), tr("Error"), tr("As the install directory "
+ "is completely deleted on uninstall, installing in %1 is forbidden.").arg(QDir::rootPath()),
QMessageBox::Ok);
return false;
}
@@ -1432,11 +1338,10 @@ bool TargetDirectoryPage::validatePage()
return true;
return MessageBoxHandler::critical(MessageBoxHandler::currentBestSuitParent(),
- QLatin1String("OverwriteTargetDirectoryMessage"), tr("Warning"), hash
- .value(QLatin1String("OverwriteTargetDirectoryMessage"), tr("You have selected an existing, "
+ QLatin1String("OverwriteTargetDirectoryMessage"), tr("Warning"), tr("You have selected an existing, "
"non-empty folder for installation. Note that it will be completely wiped on uninstallation of "
"this application. It is not advisable to install into this folder as installation might fail. "
- "Do you want to continue?")).toString(), QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes;
+ "Do you want to continue?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes;
}
return true;
}
@@ -1456,9 +1361,7 @@ void TargetDirectoryPage::targetDirSelected()
void TargetDirectoryPage::dirRequested()
{
- const QVariantHash hash = elementsForPage(QLatin1String("TargetDirectoryPage"));
- const QString newDirName = QFileDialog::getExistingDirectory(this, hash
- .value(QLatin1String("SelectInstallationFolderCaption"), tr("Select Installation Folder")).toString(),
+ const QString newDirName = QFileDialog::getExistingDirectory(this, tr("Select Installation Folder"),
targetDir());
if (newDirName.isEmpty() || newDirName == targetDir())
return;
@@ -1471,12 +1374,11 @@ void TargetDirectoryPage::dirRequested()
StartMenuDirectoryPage::StartMenuDirectoryPage(PackageManagerCore *core)
: PackageManagerPage(core)
{
- setPixmap(QWizard::LogoPixmap, logoPixmap());
setPixmap(QWizard::WatermarkPixmap, QPixmap());
setObjectName(QLatin1String("StartMenuDirectoryPage"));
- setTitle(titleForPage(QLatin1String("StartMenuDirectoryPage"), tr("Start Menu shortcuts")));
- setSubTitle(subTitleForPage(QLatin1String("StartMenuDirectoryPage"), tr("Select the Start Menu in which "
- "you would like to create the program's shortcuts. You can also enter a name to create a new folder.")));
+ setTitle(tr("Start Menu shortcuts"));
+ setSubTitle(tr("Select the Start Menu in which you would like to create the program's shortcuts. You can "
+ "also enter a name to create a new folder."));
m_lineEdit = new QLineEdit(this);
m_lineEdit->setObjectName(QLatin1String("LineEdit"));
@@ -1531,12 +1433,12 @@ StartMenuDirectoryPage::StartMenuDirectoryPage(PackageManagerCore *core)
QString StartMenuDirectoryPage::startMenuDir() const
{
- return m_lineEdit->text();
+ return m_lineEdit->text().trimmed();
}
void StartMenuDirectoryPage::setStartMenuDir(const QString &startMenuDir)
{
- m_lineEdit->setText(startMenuDir);
+ m_lineEdit->setText(startMenuDir.trimmed());
}
void StartMenuDirectoryPage::leaving()
@@ -1561,10 +1463,8 @@ ReadyForInstallationPage::ReadyForInstallationPage(PackageManagerCore *core)
: PackageManagerPage(core)
, m_msgLabel(new QLabel)
{
- setPixmap(QWizard::LogoPixmap, logoPixmap());
setPixmap(QWizard::WatermarkPixmap, QPixmap());
setObjectName(QLatin1String("ReadyForInstallationPage"));
- setSubTitle(subTitleForPage(QLatin1String("ReadyForInstallationPage")));
QVBoxLayout *baseLayout = new QVBoxLayout();
baseLayout->setObjectName(QLatin1String("BaseLayout"));
@@ -1612,7 +1512,7 @@ void ReadyForInstallationPage::entering()
m_taskDetailsButton->setVisible(false);
m_taskDetailsBrowser->setVisible(false);
setButtonText(QWizard::CommitButton, tr("U&ninstall"));
- setTitle(titleForPage(objectName(), tr("Ready to Uninstall")));
+ setTitle(tr("Ready to Uninstall"));
m_msgLabel->setText(tr("Setup is now ready to begin removing %1 from your computer.<br>"
"<font color=\"red\">The program directory %2 will be deleted completely</font>, "
"including all content in that directory!")
@@ -1622,12 +1522,12 @@ void ReadyForInstallationPage::entering()
return;
} else if (packageManagerCore()->isPackageManager() || packageManagerCore()->isUpdater()) {
setButtonText(QWizard::CommitButton, tr("U&pdate"));
- setTitle(titleForPage(objectName(), tr("Ready to Update Packages")));
+ setTitle(tr("Ready to Update Packages"));
m_msgLabel->setText(tr("Setup is now ready to begin updating your installation."));
} else {
Q_ASSERT(packageManagerCore()->isInstaller());
setButtonText(QWizard::CommitButton, tr("&Install"));
- setTitle(titleForPage(objectName(), tr("Ready to Install")));
+ setTitle(tr("Ready to Install"));
m_msgLabel->setText(tr("Setup is now ready to begin installing %1 on your computer.")
.arg(productName()));
}
@@ -1791,10 +1691,8 @@ PerformInstallationPage::PerformInstallationPage(PackageManagerCore *core)
: PackageManagerPage(core)
, m_performInstallationForm(new PerformInstallationForm(this))
{
- setPixmap(QWizard::LogoPixmap, logoPixmap());
setPixmap(QWizard::WatermarkPixmap, QPixmap());
setObjectName(QLatin1String("PerformInstallationPage"));
- setSubTitle(subTitleForPage(QLatin1String("PerformInstallationPage")));
m_performInstallationForm->setupUi(this);
@@ -1836,17 +1734,17 @@ void PerformInstallationPage::entering()
if (packageManagerCore()->isUninstaller()) {
setButtonText(QWizard::CommitButton, tr("&Uninstall"));
- setTitle(titleForPage(objectName(), tr("Uninstalling %1")).arg(productName()));
+ setTitle(tr("Uninstalling %1").arg(productName()));
QTimer::singleShot(30, packageManagerCore(), SLOT(runUninstaller()));
} else if (packageManagerCore()->isPackageManager() || packageManagerCore()->isUpdater()) {
setButtonText(QWizard::CommitButton, tr("&Update"));
- setTitle(titleForPage(objectName(), tr("Updating components of %1")).arg(productName()));
+ setTitle(tr("Updating components of %1").arg(productName()));
QTimer::singleShot(30, packageManagerCore(), SLOT(runPackageUpdater()));
} else {
setButtonText(QWizard::CommitButton, tr("&Install"));
- setTitle(titleForPage(objectName(), tr("Installing %1")).arg(productName()));
+ setTitle(tr("Installing %1").arg(productName()));
QTimer::singleShot(30, packageManagerCore(), SLOT(runInstaller()));
}
@@ -1913,21 +1811,16 @@ FinishedPage::FinishedPage(PackageManagerCore *core)
, m_commitButton(0)
{
setObjectName(QLatin1String("FinishedPage"));
- setPixmap(QWizard::WatermarkPixmap, watermarkPixmap());
- setSubTitle(subTitleForPage(QLatin1String("FinishedPage")));
- setTitle(titleForPage(QLatin1String("FinishedPage"), tr("Completing the %1 Wizard")).arg(productName()));
+ setTitle(tr("Completing the %1 Wizard").arg(productName()));
m_msgLabel = new QLabel(this);
m_msgLabel->setWordWrap(true);
m_msgLabel->setObjectName(QLatin1String("MessageLabel"));
- const QVariantHash hash = elementsForPage(QLatin1String("FinishedPage"));
#ifdef Q_OS_MAC
- m_msgLabel->setText(hash.value(QLatin1String("MessageLabel"), tr("Click Done to exit the %1 "
- "Wizard.")).toString().arg(productName()));
+ m_msgLabel->setText(tr("Click Done to exit the %1 Wizard.").arg(productName()));
#else
- m_msgLabel->setText(hash.value(QLatin1String("MessageLabel"), tr("Click Finish to exit the "
- "%1 Wizard.")).toString().arg(productName()));
+ m_msgLabel->setText(tr("Click Finish to exit the %1 Wizard.").arg(productName()));
#endif
m_runItCheckBox = new QCheckBox(this);
@@ -1956,6 +1849,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));
@@ -2012,13 +1912,26 @@ void FinishedPage::leaving()
void FinishedPage::handleFinishClicked()
{
const QString program = packageManagerCore()->replaceVariables(packageManagerCore()->value(scRunProgram));
+ const QStringList args = packageManagerCore()->replaceVariables(
+ packageManagerCore()->value(scRunProgramArguments)).split(QLatin1Char(' '));
if (!m_runItCheckBox->isChecked() || program.isEmpty())
return;
- qDebug() << "starting" << program;
- QProcess::startDetached(program);
+ qDebug() << "starting" << program << args;
+ 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
@@ -2026,10 +1939,7 @@ RestartPage::RestartPage(PackageManagerCore *core)
: PackageManagerPage(core)
{
setObjectName(QLatin1String("RestartPage"));
- setPixmap(QWizard::WatermarkPixmap, watermarkPixmap());
- setSubTitle(subTitleForPage(QLatin1String("RestartPage")));
- setTitle(titleForPage(QLatin1String("RestartPage"), tr("Completing the %1 Setup Wizard"))
- .arg(productName()));
+ setTitle(tr("Completing the %1 Setup Wizard").arg(productName()));
setFinalPage(false);
setCommitPage(false);
diff --git a/src/libs/installer/packagemanagergui.h b/src/libs/installer/packagemanagergui.h
index 5b7bd0615..5c428bf87 100644
--- a/src/libs/installer/packagemanagergui.h
+++ b/src/libs/installer/packagemanagergui.h
@@ -84,8 +84,6 @@ public:
void loadControlScript(const QString& scriptPath);
void callControlScriptMethod(const QString& methodName);
- QScriptEngine *controlScriptEngine() const;
-
Q_INVOKABLE PackageManagerPage* page(int pageId) const;
Q_INVOKABLE QWidget* pageWidgetByObjectName(const QString& name) const;
Q_INVOKABLE QWidget* currentPageWidget() const;
@@ -155,6 +153,7 @@ public:
virtual QPixmap logoPixmap() const;
virtual QString productName() const;
virtual QPixmap watermarkPixmap() const;
+ virtual QPixmap bannerPixmap() const;
virtual bool isComplete() const;
void setComplete(bool complete);
@@ -165,13 +164,12 @@ public:
void setValidatePageComponent(QInstaller::Component *component);
bool validatePage();
+signals:
+ void entered();
+ void left();
protected:
PackageManagerCore *packageManagerCore() const;
- QVariantHash elementsForPage(const QString &pageName) const;
-
- QString titleForPage(const QString &pageName, const QString &value = QString()) const;
- QString subTitleForPage(const QString &pageName, const QString &value = QString()) const;
// Inserts widget into the same layout like a sibling identified
// by its name. Default position is just behind the sibling.
@@ -187,9 +185,6 @@ protected:
bool isConstructing() const { return m_fresh; }
private:
- QString titleFromHash(const QVariantHash &hash, const QString &value = QString()) const;
-
-private:
bool m_fresh;
bool m_complete;
@@ -408,6 +403,7 @@ public:
public Q_SLOTS:
void handleFinishClicked();
+ void cleanupChangedConnects();
protected:
void entering();
diff --git a/src/libs/installer/packagemanagerproxyfactory.h b/src/libs/installer/packagemanagerproxyfactory.h
index 2ddfe7a18..a50605232 100644
--- a/src/libs/installer/packagemanagerproxyfactory.h
+++ b/src/libs/installer/packagemanagerproxyfactory.h
@@ -51,7 +51,7 @@ class PackageManagerCore;
class PackageManagerProxyFactory : public KDUpdater::FileDownloaderProxyFactory
{
public:
- PackageManagerProxyFactory(const PackageManagerCore *const core);
+ explicit PackageManagerProxyFactory(const PackageManagerCore *const core);
PackageManagerProxyFactory *clone() const;
QList<QNetworkProxy> queryProxy(const QNetworkProxyQuery &query = QNetworkProxyQuery());
diff --git a/src/libs/installer/performinstallationform.cpp b/src/libs/installer/performinstallationform.cpp
index fae8eb293..211d8176e 100644
--- a/src/libs/installer/performinstallationform.cpp
+++ b/src/libs/installer/performinstallationform.cpp
@@ -58,12 +58,12 @@ using namespace QInstaller;
// -- PerformInstallationForm
PerformInstallationForm::PerformInstallationForm(QObject *parent)
- : QObject(parent),
- m_progressBar(0),
- m_progressLabel(0),
- m_detailsButton(0),
- m_detailsBrowser(0),
- m_updateTimer(0)
+ : QObject(parent)
+ , m_progressBar(0)
+ , m_progressLabel(0)
+ , m_detailsButton(0)
+ , m_detailsBrowser(0)
+ , m_updateTimer(0)
{
}
diff --git a/src/libs/installer/performinstallationform.h b/src/libs/installer/performinstallationform.h
index f3471ebe2..209afc42d 100644
--- a/src/libs/installer/performinstallationform.h
+++ b/src/libs/installer/performinstallationform.h
@@ -61,7 +61,7 @@ class PerformInstallationForm : public QObject
Q_OBJECT
public:
- PerformInstallationForm(QObject *parent);
+ explicit PerformInstallationForm(QObject *parent);
void setupUi(QWidget *widget);
void setDetailsWidgetVisible(bool visible);
diff --git a/src/libs/installer/productkeycheck.cpp b/src/libs/installer/productkeycheck.cpp
index f975db821..a4af2b6d3 100644
--- a/src/libs/installer/productkeycheck.cpp
+++ b/src/libs/installer/productkeycheck.cpp
@@ -28,12 +28,16 @@
**************************************************************************/
#include <productkeycheck.h>
-
+#include <packagemanagercore.h>
class ProductKeyCheckPrivate
{
+ public:
+ static QPointer<QInstaller::PackageManagerCore> core;
};
+QPointer<QInstaller::PackageManagerCore> ProductKeyCheckPrivate::core = 0;
+
ProductKeyCheck::ProductKeyCheck()
: d(new ProductKeyCheckPrivate())
@@ -45,14 +49,20 @@ ProductKeyCheck::~ProductKeyCheck()
delete d;
}
-ProductKeyCheck *ProductKeyCheck::instance()
+ProductKeyCheck *ProductKeyCheck::instance(QInstaller::PackageManagerCore *core)
+{
+ static ProductKeyCheck instance;
+ if (core)
+ instance.setPackageManagerCore(core);
+ return &instance;
+}
+
+void ProductKeyCheck::setPackageManagerCore(QInstaller::PackageManagerCore *core)
{
- static ProductKeyCheck *instance = 0;
- if (instance == 0)
- instance = new ProductKeyCheck();
- return instance;
+ ProductKeyCheckPrivate::core = core;
}
+
bool ProductKeyCheck::hasValidKey()
{
return true;
@@ -74,7 +84,14 @@ QString ProductKeyCheck::maintainanceToolDetailErrorNotice()
}
// to filter none valid licenses
-bool ProductKeyCheck::isValidLicense(const QString &/*fileName*/)
+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 1ecffc3d2..6d72089e2 100644
--- a/src/libs/installer/productkeycheck.h
+++ b/src/libs/installer/productkeycheck.h
@@ -34,6 +34,12 @@
#include <QString>
#include <QHash>
+#include <QPointer>
+
+namespace QInstaller{
+ class PackageManagerCore;
+ class Repository;
+}
class ProductKeyCheckPrivate;
@@ -41,7 +47,8 @@ class INSTALLER_EXPORT ProductKeyCheck
{
public:
~ProductKeyCheck();
- static ProductKeyCheck *instance();
+ static ProductKeyCheck *instance(QInstaller::PackageManagerCore *core = 0);
+ static void setPackageManagerCore(QInstaller::PackageManagerCore *core);
// was validLicense
bool hasValidKey();
@@ -52,7 +59,10 @@ public:
bool applyKey(const QStringList &arguments);
// to filter none valid licenses
- bool isValidLicense(const QString &fileName);
+ bool isValidLicenseTextFile(const QString &fileName);
+
+ // to filter repositories not matching the license
+ bool isValidRepository(const QInstaller::Repository &repository) const;
private:
ProductKeyCheck();
diff --git a/src/libs/installer/progresscoordinator.cpp b/src/libs/installer/progresscoordinator.cpp
index a0f664357..0850b39d0 100644
--- a/src/libs/installer/progresscoordinator.cpp
+++ b/src/libs/installer/progresscoordinator.cpp
@@ -54,13 +54,13 @@ uint qHash(QPointer<QObject> key)
QT_END_NAMESPACE
ProgressCoordinator::ProgressCoordinator(QObject *parent)
- : QObject(parent),
- m_currentCompletePercentage(0),
- m_currentBasePercentage(0),
- m_manualAddedPercentage(0),
- m_reservedPercentage(0),
- m_undoMode(false),
- m_reachedPercentageBeforeUndo(0)
+ : QObject(parent)
+ , m_currentCompletePercentage(0)
+ , m_currentBasePercentage(0)
+ , m_manualAddedPercentage(0)
+ , m_reservedPercentage(0)
+ , m_undoMode(false)
+ , m_reachedPercentageBeforeUndo(0)
{
// it has to be in the main thread to be able refresh the ui with processEvents
Q_ASSERT(thread() == qApp->thread());
@@ -138,7 +138,7 @@ void ProgressCoordinator::partProgressChanged(double fraction)
}
if (qRound(m_currentCompletePercentage) < qRound(newCurrentCompletePercentage)) {
- qFatal("This should not happen!");
+ qWarning("This should not happen!");
}
m_currentCompletePercentage = newCurrentCompletePercentage;
@@ -171,7 +171,7 @@ void ProgressCoordinator::partProgressChanged(double fraction)
}
if (qRound(m_currentCompletePercentage) > qRound(newCurrentCompletePercentage)) {
- qFatal("This should not happen!");
+ qWarning("This should not happen!");
}
m_currentCompletePercentage = newCurrentCompletePercentage;
diff --git a/src/libs/installer/progresscoordinator.h b/src/libs/installer/progresscoordinator.h
index b1fa0ab67..263b25695 100644
--- a/src/libs/installer/progresscoordinator.h
+++ b/src/libs/installer/progresscoordinator.h
@@ -39,8 +39,8 @@
**
**************************************************************************/
-#ifndef PROGRESSCOORDNINATOR_H
-#define PROGRESSCOORDNINATOR_H
+#ifndef PROGRESSCOORDINATOR_H
+#define PROGRESSCOORDINATOR_H
#include <QtCore/QHash>
#include <QtCore/QObject>
@@ -102,4 +102,4 @@ private:
} //namespace QInstaller
-#endif //PROGRESSCOORDNINATOR_H
+#endif //PROGRESSCOORDINATOR_H
diff --git a/src/libs/installer/qinstallerglobal.h b/src/libs/installer/qinstallerglobal.h
index b7d5d3f3d..427586266 100644
--- a/src/libs/installer/qinstallerglobal.h
+++ b/src/libs/installer/qinstallerglobal.h
@@ -48,23 +48,8 @@
#include <kdupdaterupdateoperation.h>
#include <kdupdaterpackagesinfo.h>
-QT_BEGIN_NAMESPACE
-class QScriptContext;
-class QScriptEngine;
-class QScriptValue;
-QT_END_NAMESPACE
-
-
namespace QInstaller {
-static QRegExp scCommaRegExp(QLatin1String("\\b(,|, )\\b"));
-
-enum INSTALLER_EXPORT RunMode
-{
- AllMode,
- UpdaterMode
-};
-
enum INSTALLER_EXPORT JobError
{
InvalidUrl = 0x24B04,
@@ -86,14 +71,6 @@ typedef QList<QInstaller::Package*> PackagesList;
typedef KDUpdater::PackageInfo LocalPackage;
typedef QHash<QString, LocalPackage> LocalPackagesHash;
-QString INSTALLER_EXPORT uncaughtExceptionString(QScriptEngine *scriptEngine, const QString &context = QString());
-QScriptValue qInstallerComponentByName(QScriptContext *context, QScriptEngine *engine);
-
-QScriptValue qDesktopServicesOpenUrl(QScriptContext *context, QScriptEngine *engine);
-QScriptValue qDesktopServicesDisplayName(QScriptContext *context, QScriptEngine *engine);
-QScriptValue qDesktopServicesStorageLocation(QScriptContext *context, QScriptEngine *engine);
-QScriptValue qFileDialogGetExistingDirectory(QScriptContext *context, QScriptEngine *engine);
-
} // namespace QInstaller
#endif // QINSTALLER_GLOBAL_H
diff --git a/src/libs/installer/qprocesswrapper.cpp b/src/libs/installer/qprocesswrapper.cpp
index 020624425..9544d6682 100644
--- a/src/libs/installer/qprocesswrapper.cpp
+++ b/src/libs/installer/qprocesswrapper.cpp
@@ -54,16 +54,16 @@ class QProcessWrapper::Private
{
public:
Private(QProcessWrapper *qq)
- : q(qq),
- ignoreTimer(false),
- socket(0)
+ : q(qq)
+ , ignoreTimer(false)
+ , socket(0)
{}
bool createSocket()
{
if (!FSEngineClientHandler::instance().isActive())
return false;
- if (socket != 0 && socket->state() == static_cast< int >(QAbstractSocket::ConnectedState))
+ if (socket != 0 && socket->state() == static_cast<int>(QAbstractSocket::ConnectedState))
return true;
if (socket != 0)
delete socket;
@@ -119,8 +119,8 @@ public:
// -- QProcessWrapper
QProcessWrapper::QProcessWrapper(QObject *parent)
- : QObject(parent),
- d(new Private(this))
+ : QObject(parent)
+ , d(new Private(this))
{
connect(&d->process, SIGNAL(bytesWritten(qint64)), SIGNAL(bytesWritten(qint64)));
connect(&d->process, SIGNAL(aboutToClose()), SIGNAL(aboutToClose()));
@@ -293,7 +293,7 @@ int QProcessWrapper::exitCode() const
const Private::TimerBlocker blocker(this);
if (d->createSocket())
return callRemoteMethod<int>(d->stream, QLatin1String("QProcess::exitCode"));
- return static_cast< int>(d->process.exitCode());
+ return static_cast<int>(d->process.exitCode());
}
QProcessWrapper::ExitStatus QProcessWrapper::exitStatus() const
@@ -301,7 +301,7 @@ QProcessWrapper::ExitStatus QProcessWrapper::exitStatus() const
const Private::TimerBlocker blocker(this);
if (d->createSocket())
return callRemoteMethod<QProcessWrapper::ExitStatus>(d->stream, QLatin1String("QProcess::exitStatus"));
- return static_cast< QProcessWrapper::ExitStatus>(d->process.exitStatus());
+ return static_cast<QProcessWrapper::ExitStatus>(d->process.exitStatus());
}
void QProcessWrapper::kill()
@@ -329,6 +329,14 @@ QByteArray QProcessWrapper::readAllStandardOutput()
return d->process.readAllStandardOutput();
}
+QByteArray QProcessWrapper::readAllStandardError()
+{
+ const Private::TimerBlocker blocker(this);
+ if (d->createSocket())
+ return callRemoteMethod<QByteArray>(d->stream, QLatin1String("QProcess::readAllStandardError"));
+ return d->process.readAllStandardError();
+}
+
void QProcessWrapper::start(const QString &param1, const QStringList &param2, QIODevice::OpenMode param3)
{
const Private::TimerBlocker blocker(this);
@@ -352,7 +360,7 @@ QProcessWrapper::ProcessState QProcessWrapper::state() const
const Private::TimerBlocker blocker(this);
if (d->createSocket())
return callRemoteMethod<QProcessWrapper::ProcessState>(d->stream, QLatin1String("QProcess::state"));
- return static_cast< QProcessWrapper::ProcessState>(d->process.state());
+ return static_cast<QProcessWrapper::ProcessState>(d->process.state());
}
void QProcessWrapper::terminate()
@@ -371,7 +379,7 @@ QProcessWrapper::ProcessChannel QProcessWrapper::readChannel() const
return callRemoteMethod<QProcessWrapper::ProcessChannel>(d->stream,
QLatin1String("QProcess::readChannel"));
}
- return static_cast< QProcessWrapper::ProcessChannel>(d->process.readChannel());
+ return static_cast<QProcessWrapper::ProcessChannel>(d->process.readChannel());
}
QProcessWrapper::ProcessChannelMode QProcessWrapper::processChannelMode() const
@@ -381,7 +389,7 @@ QProcessWrapper::ProcessChannelMode QProcessWrapper::processChannelMode() const
return callRemoteMethod<QProcessWrapper::ProcessChannelMode>(d->stream,
QLatin1String("QProcess::processChannelMode"));
}
- return static_cast< QProcessWrapper::ProcessChannelMode>(d->process.processChannelMode());
+ return static_cast<QProcessWrapper::ProcessChannelMode>(d->process.processChannelMode());
}
QString QProcessWrapper::workingDirectory() const
@@ -389,7 +397,15 @@ QString QProcessWrapper::workingDirectory() const
const Private::TimerBlocker blocker(this);
if (d->createSocket())
return callRemoteMethod<QString>(d->stream, QLatin1String("QProcess::workingDirectory"));
- return static_cast< QString>(d->process.workingDirectory());
+ return static_cast<QString>(d->process.workingDirectory());
+}
+
+QString QProcessWrapper::errorString() const
+{
+ const Private::TimerBlocker blocker(this);
+ if (d->createSocket())
+ return callRemoteMethod<QString>(d->stream, QLatin1String("QProcess::errorString"));
+ return static_cast<QString>(d->process.errorString());
}
void QProcessWrapper::setEnvironment(const QStringList &param1)
diff --git a/src/libs/installer/qprocesswrapper.h b/src/libs/installer/qprocesswrapper.h
index c566c3f07..e7caf61f6 100644
--- a/src/libs/installer/qprocesswrapper.h
+++ b/src/libs/installer/qprocesswrapper.h
@@ -84,6 +84,7 @@ public:
void terminate();
QByteArray readAll();
QByteArray readAllStandardOutput();
+ QByteArray readAllStandardError();
void setWorkingDirectory(const QString &dir);
void start(const QString &program);
@@ -100,6 +101,7 @@ public:
bool waitForFinished(int msecs = 30000);
void setEnvironment(const QStringList &environment);
QString workingDirectory() const;
+ QString errorString() const;
qint64 write(const QByteArray &byteArray);
QProcessWrapper::ProcessChannel readChannel() const;
void setReadChannel(QProcessWrapper::ProcessChannel channel);
diff --git a/src/libs/installer/qsettingswrapper.cpp b/src/libs/installer/qsettingswrapper.cpp
index d7cb27828..89f39a14e 100644
--- a/src/libs/installer/qsettingswrapper.cpp
+++ b/src/libs/installer/qsettingswrapper.cpp
@@ -56,38 +56,38 @@ class QSettingsWrapper::Private
{
public:
Private(const QString &organization, const QString &application)
- : native(true),
- settings(organization, application),
- socket(0)
+ : native(true)
+ , settings(organization, application)
+ , socket(0)
{
}
Private(QSettings::Scope scope, const QString &organization, const QString &application)
- : native(true),
- settings(scope, organization, application),
- socket(0)
+ : native(true)
+ , settings(scope, organization, application)
+ , socket(0)
{
}
Private(QSettings::Format format, QSettings::Scope scope, const QString &organization,
const QString &application)
- : native(format == QSettings::NativeFormat),
- settings(format, scope, organization, application),
- socket(0)
+ : native(format == QSettings::NativeFormat)
+ , settings(format, scope, organization, application)
+ , socket(0)
{
}
Private(const QString &fileName, QSettings::Format format)
- : native(format == QSettings::NativeFormat),
- fileName(fileName),
- settings(fileName, format),
- socket(0)
+ : native(format == QSettings::NativeFormat)
+ , fileName(fileName)
+ , settings(fileName, format)
+ , socket(0)
{
}
Private()
- : native(true),
- socket(0)
+ : native(true)
+ , socket(0)
{
}
diff --git a/src/libs/installer/qtpatch.cpp b/src/libs/installer/qtpatch.cpp
index 02795b34b..6581815c2 100644
--- a/src/libs/installer/qtpatch.cpp
+++ b/src/libs/installer/qtpatch.cpp
@@ -40,6 +40,7 @@
**************************************************************************/
#include "qtpatch.h"
+#include "utils.h"
#include <QString>
#include <QStringList>
@@ -52,35 +53,20 @@
#include <QCoreApplication>
#include <QByteArrayMatcher>
-#ifdef Q_OS_WIN
-#include <windows.h> // for Sleep
-#endif
-#ifdef Q_OS_UNIX
-#include <errno.h>
-#include <signal.h>
-#include <time.h>
-#endif
-
-static void sleepCopiedFromQTest(int ms)
+QHash<QString, QByteArray> QtPatch::readQmakeOutput(const QByteArray &data)
{
- if (ms < 0)
- return;
-#ifdef Q_OS_WIN
- Sleep(uint(ms));
-#else
- struct timespec ts = { ms / 1000, (ms % 1000) * 1000 * 1000 };
- nanosleep(&ts, NULL);
-#endif
-}
-
-static void uiDetachedWait(int ms)
-{
- QTime timer;
- timer.start();
- do {
- QCoreApplication::processEvents(QEventLoop::AllEvents, ms);
- sleepCopiedFromQTest(10);
- } while (timer.elapsed() < ms);
+ QHash<QString, QByteArray> qmakeValueHash;
+ QTextStream stream(data, QIODevice::ReadOnly);
+ while (!stream.atEnd()) {
+ const QString line = stream.readLine();
+ const int index = line.indexOf(QLatin1Char(':'));
+ if (index != -1) {
+ QString value = line.mid(index+1);
+ if (value != QLatin1String("**Unknown**") )
+ qmakeValueHash.insert(line.left(index), value.toUtf8());
+ }
+ }
+ return qmakeValueHash;
}
QHash<QString, QByteArray> QtPatch::qmakeValues(const QString &qmakePath, QByteArray *qmakeOutput)
@@ -113,21 +99,12 @@ QHash<QString, QByteArray> QtPatch::qmakeValues(const QString &qmakePath, QByteA
}
QByteArray output = process.readAllStandardOutput();
qmakeOutput->append(output);
- QTextStream stream(&output);
- while (!stream.atEnd()) {
- const QString line = stream.readLine();
- const int index = line.indexOf(QLatin1Char(':'));
- if (index != -1) {
- QString value = line.mid(index+1);
- if (value != QLatin1String("**Unknown**") )
- qmakeValueHash.insert(line.left(index), value.toUtf8());
- }
- }
+ qmakeValueHash = readQmakeOutput(output);
}
if (qmakeValueHash.isEmpty()) {
++waitCount;
static const int waitTimeInMilliSeconds = 500;
- uiDetachedWait(waitTimeInMilliSeconds);
+ QInstaller::uiDetachedWait(waitTimeInMilliSeconds);
}
if (process.state() > QProcess::NotRunning ) {
qDebug() << "qmake process is still running, need to kill it.";
@@ -232,7 +209,7 @@ bool QtPatch::openFileForPatching(QFile *file)
while (!file->open(QFile::ReadWrite) && waitCount < 60) {
++waitCount;
static const int waitTimeInMilliSeconds = 500;
- uiDetachedWait(waitTimeInMilliSeconds);
+ QInstaller::uiDetachedWait(waitTimeInMilliSeconds);
}
return file->openMode() == QFile::ReadWrite;
}
diff --git a/src/libs/installer/qtpatch.h b/src/libs/installer/qtpatch.h
index 5868e6ce2..13c7df84a 100644
--- a/src/libs/installer/qtpatch.h
+++ b/src/libs/installer/qtpatch.h
@@ -50,6 +50,7 @@
namespace QtPatch {
+QHash<QString, QByteArray> INSTALLER_EXPORT readQmakeOutput(const QByteArray &data);
QHash<QString, QByteArray> INSTALLER_EXPORT qmakeValues(const QString &qmakePath, QByteArray *qmakeOutput);
bool INSTALLER_EXPORT patchBinaryFile(const QString &fileName,
diff --git a/src/libs/installer/qtpatchoperation.cpp b/src/libs/installer/qtpatchoperation.cpp
index 9699219ec..e9fbb65c5 100644
--- a/src/libs/installer/qtpatchoperation.cpp
+++ b/src/libs/installer/qtpatchoperation.cpp
@@ -111,7 +111,10 @@ static QHash<QByteArray, QByteArray> generatePatchValueHash(const QByteArray &ne
replaceHash.insert( QByteArray("qt_trnspath=%1").replace("%1", oldValue),
QByteArray("qt_trnspath=%1/translations").replace("%1/", newQtPath + nativeSeperator));
- // This must not be patched. Commenting out to fix QTSDK-429
+ // This must not be patched!
+ // On desktop there should be a correct default path (for example "/etc/xdg"),
+ // but on some other targets you need to use "-sysconfdir </your/default/config/path"
+ // while building Qt to get a correct QT_INSTALL_CONFIGURATION value
// oldValue = qmakeValueHash.value(QLatin1String("QT_INSTALL_CONFIGURATION"));
// replaceMap.insert( QByteArray("qt_stngpath=%1").replace("%1", oldValue),
// QByteArray("qt_stngpath=%1").replace("%1", newQtPath));
@@ -142,6 +145,10 @@ static QHash<QByteArray, QByteArray> generatePatchValueHash(const QByteArray &ne
replaceHash.insert(QByteArray("qt_hdatpath=%1").replace("%1", oldValue),
QByteArray("qt_hdatpath=%1/").replace("%1/", newQtPath));
+ oldValue = qmakeValueHash.value(QLatin1String("QT_HOST_LIBS"));
+ replaceHash.insert(QByteArray("qt_hlibpath=%1").replace("%1", oldValue),
+ QByteArray("qt_hlibpath=%1/lib").replace("%1/", newQtPath + nativeSeperator));
+
return replaceHash;
}
@@ -160,16 +167,34 @@ bool QtPatchOperation::performOperation()
// 1. type
// 2. new/target qtpath
// 3. version if greather Qt4
+ // optional QmakeOutputInstallerKey=<used_installer_value>
// the possible 2 argument case is here to support old syntax
- if (arguments().count() < 2 || arguments().count() > 3) {
+ if (arguments().count() < 2 && arguments().count() > 4) {
setError(InvalidArguments);
setErrorString(tr("Invalid arguments in %0: %1 arguments given, %2 expected%3.")
- .arg(name()).arg(arguments().count()).arg(tr("exactly 3"), QLatin1String("")));
+ .arg(name()).arg(arguments().count()).arg(tr("3 or 4"), QLatin1String("")));
return false;
}
- QString type = arguments().at(0);
+ QStringList args = arguments();
+ QString qmakeOutputInstallerKey;
+ QStringList filteredQmakeOutputInstallerKey = args.filter(QLatin1String("QmakeOutputInstallerKey="),
+ Qt::CaseInsensitive);
+ PackageManagerCore *const core = value(QLatin1String("installer")).value<PackageManagerCore*>();
+ if (!filteredQmakeOutputInstallerKey.isEmpty()) {
+ if (!core) {
+ setError(UserDefinedError);
+ setErrorString(tr("Needed installer object in \"%1\" operation is empty.").arg(name()));
+ return false;
+ }
+ QString qmakeOutputInstallerKeyArgument = filteredQmakeOutputInstallerKey.at(0);
+ qmakeOutputInstallerKey = qmakeOutputInstallerKeyArgument;
+ qmakeOutputInstallerKey.replace(QLatin1String("QmakeOutputInstallerKey="), QString(), Qt::CaseInsensitive);
+ args.removeAll(qmakeOutputInstallerKeyArgument);
+ }
+
+ QString type = args.at(0);
bool isPlatformSupported = type.contains(QLatin1String("linux"), Qt::CaseInsensitive)
|| type.contains(QLatin1String("windows"), Qt::CaseInsensitive)
|| type.contains(QLatin1String("mac"), Qt::CaseInsensitive);
@@ -180,31 +205,42 @@ bool QtPatchOperation::performOperation()
return false;
}
- const QString newQtPathStr = QDir::toNativeSeparators(arguments().at(1));
- const QByteArray newQtPath = newQtPathStr.toUtf8();
+ if (core && !filteredQmakeOutputInstallerKey.isEmpty() && core->value(qmakeOutputInstallerKey).isEmpty()) {
+ setError(UserDefinedError);
+ setErrorString(tr("Could not find the needed QmakeOutputInstallerKey(%1) value on the installer "
+ "object. The ConsumeOutput operation on the valid qmake needs to be called first.").arg(
+ qmakeOutputInstallerKey));
+ return false;
+ }
+ const QString newQtPathStr = QDir::toNativeSeparators(args.at(1));
+ const QByteArray newQtPath = newQtPathStr.toUtf8();
QString qmakePath = QString::fromUtf8(newQtPath) + QLatin1String("/bin/qmake");
#ifdef Q_OS_WIN
qmakePath = qmakePath + QLatin1String(".exe");
#endif
- if (!QFile::exists(qmakePath)) {
- setError(UserDefinedError);
- setErrorString(tr("QMake from the current Qt version \n(%1)is not existing. Please file a bugreport "
- "with this dialog at https://bugreports.qt-project.org.").arg(QDir::toNativeSeparators(qmakePath)));
- return false;
+ QHash<QString, QByteArray> qmakeValueHash;
+ if (core && !core->value(qmakeOutputInstallerKey).isEmpty()) {
+ qmakeValueHash = QtPatch::readQmakeOutput(core->value(qmakeOutputInstallerKey).toLatin1());
+ } else {
+ if (!QFile::exists(qmakePath)) {
+ setError(UserDefinedError);
+ setErrorString(tr("QMake from the current Qt version \n(%1)is not existing. Please file a bugreport "
+ "with this dialog at https://bugreports.qt-project.org.").arg(QDir::toNativeSeparators(qmakePath)));
+ return false;
+ }
+ QByteArray qmakeOutput;
+ qmakeValueHash = QtPatch::qmakeValues(qmakePath, &qmakeOutput);
+ if (qmakeValueHash.isEmpty()) {
+ setError(UserDefinedError);
+ setErrorString(tr("The output of \n%1 -query\nis not parseable. Please file a bugreport with this "
+ "dialog https://bugreports.qt-project.org.\noutput: \"%2\"").arg(QDir::toNativeSeparators(qmakePath),
+ QString::fromUtf8(qmakeOutput)));
+ return false;
+ }
}
- QByteArray qmakeOutput;
- QHash<QString, QByteArray> qmakeValueHash = QtPatch::qmakeValues(qmakePath, &qmakeOutput);
-
- if (qmakeValueHash.isEmpty()) {
- setError(UserDefinedError);
- setErrorString(tr("The output of \n%1 -query\nis not parseable. Please file a bugreport with this "
- "dialog https://bugreports.qt-project.org.\noutput: \"%2\"").arg(QDir::toNativeSeparators(qmakePath),
- QString::fromUtf8(qmakeOutput)));
- return false;
- }
const QByteArray oldQtPath = qmakeValueHash.value(QLatin1String("QT_INSTALL_PREFIX"));
bool oldQtPathFromQMakeIsEmpty = oldQtPath.isEmpty();
@@ -218,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
@@ -239,13 +353,11 @@ bool QtPatchOperation::performOperation()
fileName = QString::fromLatin1(":/files-to-patch-windows");
else if (type == QLatin1String("linux"))
fileName = QString::fromLatin1(":/files-to-patch-linux");
- else if (type == QLatin1String("linux-emb-arm"))
- fileName = QString::fromLatin1(":/files-to-patch-linux-emb-arm");
else if (type == QLatin1String("mac"))
fileName = QString::fromLatin1(":/files-to-patch-macx");
QFile patchFileListFile(fileName);
- QString version = arguments().value(2).toLower();
+ QString version = args.value(2).toLower();
if (!version.isEmpty())
patchFileListFile.setFileName(fileName + QLatin1Char('-') + version);
diff --git a/src/libs/installer/qtpatchoperation.h b/src/libs/installer/qtpatchoperation.h
index f1919f4c6..346466c43 100644
--- a/src/libs/installer/qtpatchoperation.h
+++ b/src/libs/installer/qtpatchoperation.h
@@ -46,7 +46,7 @@
namespace QInstaller {
-class QtPatchOperation : public Operation
+class INSTALLER_EXPORT QtPatchOperation : public Operation
{
public:
QtPatchOperation();
diff --git a/src/libs/installer/registerqtvqnxoperation.cpp b/src/libs/installer/registerqtincreatorqnxoperation.cpp
index b52558145..be99de4c7 100644
--- a/src/libs/installer/registerqtvqnxoperation.cpp
+++ b/src/libs/installer/registerqtincreatorqnxoperation.cpp
@@ -39,7 +39,7 @@
**
**************************************************************************/
-#include "registerqtvqnxoperation.h"
+#include "registerqtincreatorqnxoperation.h"
#include "packagemanagercore.h"
#include "qtcreator_constants.h"
diff --git a/src/libs/installer/registerqtvqnxoperation.h b/src/libs/installer/registerqtincreatorqnxoperation.h
index a5e49656a..5b6a3c9b1 100644
--- a/src/libs/installer/registerqtvqnxoperation.h
+++ b/src/libs/installer/registerqtincreatorqnxoperation.h
@@ -39,8 +39,8 @@
**
**************************************************************************/
-#ifndef REGISTERQTINCREATORVQNXOPERATION_H
-#define REGISTERQTINCREATORVQNXOPERATION_H
+#ifndef REGISTERQTINCREATORQNXOPERATION_H
+#define REGISTERQTINCREATORQNXOPERATION_H
#include "qinstallerglobal.h"
@@ -60,4 +60,4 @@ public:
} // namespace QInstaller
-#endif // REGISTERQTINCREATORVQNXOPERATION_H
+#endif // REGISTERQTINCREATORQNXOPERATION_H
diff --git a/src/libs/installer/resources/files-to-patch-linux-emb-arm b/src/libs/installer/resources/files-to-patch-linux-emb-arm
index a1ba5ccb8..c01fe17a1 100644
--- a/src/libs/installer/resources/files-to-patch-linux-emb-arm
+++ b/src/libs/installer/resources/files-to-patch-linux-emb-arm
@@ -1,5 +1,6 @@
bin/qmake
bin/lrelease
+bin/qdoc
%%
*.la
*.prl
diff --git a/src/libs/installer/resources/files-to-patch-windows-emb-arm b/src/libs/installer/resources/files-to-patch-windows-emb-arm
index 114072689..f0c1c3c73 100644
--- a/src/libs/installer/resources/files-to-patch-windows-emb-arm
+++ b/src/libs/installer/resources/files-to-patch-windows-emb-arm
@@ -1,5 +1,6 @@
bin/qmake.exe
bin/lrelease.exe
+bin/qdoc.exe
%%
*.la
*.prl
diff --git a/src/libs/installer/scriptengine.cpp b/src/libs/installer/scriptengine.cpp
new file mode 100644
index 000000000..b6a8a971a
--- /dev/null
+++ b/src/libs/installer/scriptengine.cpp
@@ -0,0 +1,410 @@
+/**************************************************************************
+**
+** Copyright (C) 2012-2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Installer Framework.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+**************************************************************************/
+#include "scriptengine.h"
+
+#include "component.h"
+#include "packagemanagercore.h"
+#include "messageboxhandler.h"
+#include "errors.h"
+
+#include <QDesktopServices>
+#include <QFileDialog>
+#include <QMetaEnum>
+#include <QWizard>
+
+using namespace QInstaller;
+
+namespace QInstaller {
+
+QString uncaughtExceptionString(const QScriptEngine *scriptEngine, const QString &context)
+{
+ QString error(QLatin1String("\n\n%1\n\nBacktrace:\n\t%2"));
+ if (!context.isEmpty())
+ error.prepend(context);
+
+ return error.arg(scriptEngine->uncaughtException().toString(), scriptEngine->uncaughtExceptionBacktrace()
+ .join(QLatin1String("\n\t")));
+}
+
+/*!
+ Scriptable version of PackageManagerCore::componentByName(QString).
+ \sa PackageManagerCore::componentByName
+ */
+QScriptValue qInstallerComponentByName(QScriptContext *context, QScriptEngine *engine)
+{
+ const QScriptValue check = checkArguments(context, 1, 1);
+ if (check.isError())
+ return check;
+
+ // well... this is our "this" pointer
+ PackageManagerCore *const core = dynamic_cast<PackageManagerCore*>(engine->globalObject()
+ .property(QLatin1String("installer")).toQObject());
+
+ const QString name = context->argument(0).toString();
+ return engine->newQObject(core->componentByName(name));
+}
+
+QScriptValue checkArguments(QScriptContext *context, int minimalArgumentCount, int maximalArgumentCount)
+{
+ if (context->argumentCount() < minimalArgumentCount || context->argumentCount() > maximalArgumentCount) {
+ if (minimalArgumentCount != maximalArgumentCount) {
+ return context->throwError(QObject::tr("Invalid arguments: %1 arguments given, %2 to "
+ "%3 expected.").arg(QString::number(context->argumentCount()),
+ QString::number(minimalArgumentCount), QString::number(maximalArgumentCount)));
+ }
+ return context->throwError(QObject::tr("Invalid arguments: %1 arguments given, %2 expected.")
+ .arg(QString::number(context->argumentCount()), QString::number(minimalArgumentCount)));
+ }
+ return QScriptValue();
+}
+
+QScriptValue qDesktopServicesOpenUrl(QScriptContext *context, QScriptEngine *engine)
+{
+ Q_UNUSED(engine);
+ const QScriptValue check = checkArguments(context, 1, 1);
+ if (check.isError())
+ return check;
+ QString url = context->argument(0).toString();
+ url.replace(QLatin1String("\\\\"), QLatin1String("/"));
+ url.replace(QLatin1String("\\"), QLatin1String("/"));
+ return QDesktopServices::openUrl(QUrl::fromUserInput(url));
+}
+
+QScriptValue qDesktopServicesDisplayName(QScriptContext *context, QScriptEngine *engine)
+{
+ Q_UNUSED(engine);
+ const QScriptValue check = checkArguments(context, 1, 1);
+ if (check.isError())
+ return check;
+
+#if QT_VERSION < 0x050000
+ const QDesktopServices::StandardLocation location =
+ static_cast< QDesktopServices::StandardLocation >(context->argument(0).toInt32());
+ return QDesktopServices::displayName(location);
+#else
+ const QStandardPaths::StandardLocation location =
+ static_cast< QStandardPaths::StandardLocation >(context->argument(0).toInt32());
+ return QStandardPaths::displayName(location);
+#endif
+}
+
+QScriptValue qDesktopServicesStorageLocation(QScriptContext *context, QScriptEngine *engine)
+{
+ Q_UNUSED(engine);
+ const QScriptValue check = checkArguments(context, 1, 1);
+ if (check.isError())
+ return check;
+
+#if QT_VERSION < 0x050000
+ const QDesktopServices::StandardLocation location =
+ static_cast< QDesktopServices::StandardLocation >(context->argument(0).toInt32());
+ return QDesktopServices::storageLocation(location);
+#else
+ const QStandardPaths::StandardLocation location =
+ static_cast< QStandardPaths::StandardLocation >(context->argument(0).toInt32());
+ return QStandardPaths::writableLocation(location);
+#endif
+}
+
+QScriptValue qFileDialogGetExistingDirectory(QScriptContext *context, QScriptEngine *engine)
+{
+ Q_UNUSED(engine);
+ const QScriptValue check = checkArguments(context, 0, 2);
+ if (check.isError())
+ return check;
+ QString caption;
+ QString dir;
+ if (context->argumentCount() > 0)
+ caption = context->argument(0).toString();
+ if (context->argumentCount() > 1)
+ dir = context->argument(1).toString();
+ return QFileDialog::getExistingDirectory(0, caption, dir);
+}
+
+QScriptValue qFileDialogGetOpenFileName(QScriptContext *context, QScriptEngine *engine)
+{
+ Q_UNUSED(engine);
+ const QScriptValue check = checkArguments(context, 0, 2);
+ if (check.isError())
+ return check;
+ QString caption;
+ QString dir;
+ if (context->argumentCount() > 0)
+ caption = context->argument(0).toString();
+ if (context->argumentCount() > 1)
+ dir = context->argument(1).toString();
+ return QFileDialog::getExistingDirectory(0, caption, dir);
+}
+
+} //namespace QInstaller
+
+
+/*!
+ \class QInstaller::ScriptEngine
+ prepare and run the component scripts
+*/
+ScriptEngine::ScriptEngine(PackageManagerCore *core)
+ : QScriptEngine(core)
+ , m_core(core)
+{
+ // register translation stuff
+ installTranslatorFunctions();
+
+ globalObject().setProperty(QLatin1String("QMessageBox"), generateMessageBoxObject());
+ globalObject().setProperty(QLatin1String("QDesktopServices"), generateDesktopServicesObject());
+ globalObject().setProperty(QLatin1String("QInstaller"), generateQInstallerObject());
+
+ QScriptValue installerObject = newQObject(m_core);
+ installerObject.setProperty(QLatin1String("componentByName"), newFunction(qInstallerComponentByName, 1));
+
+ globalObject().setProperty(QLatin1String("installer"), installerObject);
+
+ QScriptValue fileDialog = newArray();
+ fileDialog.setProperty(QLatin1String("getExistingDirectory"),
+ newFunction(qFileDialogGetExistingDirectory));
+ globalObject().setProperty(QLatin1String("QFileDialog"), fileDialog);
+
+ const QList<Component*> components = m_core->availableComponents();
+ QScriptValue scriptComponentsObject = newArray(components.count());
+ for (int i = 0; i < components.count(); ++i)
+ scriptComponentsObject.setProperty(i, newQObject(components[i]));
+
+ globalObject().property(QLatin1String("installer"))
+ .setProperty(QLatin1String("components"), scriptComponentsObject);
+
+ connect(this, SIGNAL(signalHandlerException(QScriptValue)), SLOT(handleException(QScriptValue)));
+}
+
+ScriptEngine::~ScriptEngine()
+{
+}
+
+void ScriptEngine::setGuiQObject(QObject *guiQObject)
+{
+ if (qobject_cast<QWizard*>(guiQObject)) {
+#undef REGISTER_BUTTON
+#define REGISTER_BUTTON(x) buttons.setProperty(QLatin1String(#x), \
+ newVariant(static_cast<int>(QWizard::x)));
+
+ QScriptValue buttons = newArray();
+ REGISTER_BUTTON(BackButton)
+ REGISTER_BUTTON(NextButton)
+ REGISTER_BUTTON(CommitButton)
+ REGISTER_BUTTON(FinishButton)
+ REGISTER_BUTTON(CancelButton)
+ REGISTER_BUTTON(HelpButton)
+ REGISTER_BUTTON(CustomButton1)
+ REGISTER_BUTTON(CustomButton2)
+ REGISTER_BUTTON(CustomButton3)
+
+#undef REGISTER_BUTTON
+ globalObject().setProperty(QLatin1String("buttons"), buttons);
+ }
+ globalObject().setProperty(QLatin1String("gui"), newQObject(guiQObject));
+}
+
+/*!
+ Loads a script into the given \a context at \a fileName inside the ScriptEngine.
+
+ The installer and all its components as well as other useful stuff are being exported into the script.
+ Read \link componentscripting Component Scripting \endlink for details.
+ \throws Error when either the script at \a fileName couldn't be opened, or the QScriptEngine
+ couldn't evaluate the script.
+*/
+QScriptValue ScriptEngine::loadInConext(const QString &context, const QString &fileName,
+ const QString &scriptInjection)
+{
+ QFile file(fileName);
+ if (!file.open(QIODevice::ReadOnly)) {
+ throw Error(tr("Could not open the requested script file at %1: %2.").arg(
+ fileName, file.errorString()));
+ }
+
+ // create inside closure in one line to keep linenumber in the right order
+ // which is used as a debug output in an exception case
+ // scriptContent will be added as the last arg command to prevent wrong
+ // replacements of %1, %2 or %3 inside the scriptContent
+ QString scriptContent = QString::fromLatin1(
+ "(function() { %1 %3 ; return new %2; })();");
+
+ // merging everything together and as last we are adding the file content to prevent wrong
+ // replacements of %1 %2 or %3 inside the javascript code
+ scriptContent = scriptContent.arg(scriptInjection, context, QLatin1String(file.readAll()));
+ QScriptValue scriptContext = evaluate(scriptContent, fileName);
+
+ if (hasUncaughtException()) {
+ throw Error(tr("Exception while loading the component script: '%1'").arg(
+ uncaughtExceptionString(this, QFileInfo(file).absoluteFilePath())));
+ }
+ if (!scriptContext.isValid()) {
+ throw Error(tr("Could not load the component script inside a script context: '%1'").arg(
+ QFileInfo(file).absoluteFilePath()));
+ }
+ return scriptContext;
+}
+
+void ScriptEngine::handleException(const QScriptValue &value)
+{
+ if (!value.engine())
+ return;
+ throw Error(uncaughtExceptionString(this, tr("Fatal error while evaluating a script.")));
+}
+
+/*!
+ Tries to call the method with \a name within the script and returns the result. If the method
+ doesn't exist, an invalid result is returned. If the method has an uncaught exception, its
+ string representation is thrown as an Error exception.
+
+ \note The method is not called, if the current script context is the same method, to avoid
+ infinite recursion.
+*/
+QScriptValue ScriptEngine::callScriptMethod(const QScriptValue &scriptContext,
+ const QString &methodName, const QScriptValueList &arguments) const
+{
+ // don't allow such a recursion
+ if (currentContext()->backtrace().first().startsWith(methodName))
+ return QScriptValue();
+
+ QScriptValue method = scriptContext.property(methodName);
+ // this marks the method to be called not any longer
+ if (!method.isValid())
+ return QScriptValue();
+
+ const QScriptValue result = method.call(scriptContext, arguments);
+ if (!result.isValid())
+ return result;
+
+ if (hasUncaughtException())
+ throw Error(uncaughtExceptionString(this));
+
+ return result;
+}
+
+
+/*!
+ generates QMessageBox::StandardButton enum as an QScriptValue array
+*/
+QScriptValue ScriptEngine::generateMessageBoxObject()
+{
+ // register QMessageBox::StandardButton enum in the script connection
+ QScriptValue messageBox = newQObject(MessageBoxHandler::instance());
+
+ const QMetaObject &messageBoxMetaObject = QMessageBox::staticMetaObject;
+ int index = messageBoxMetaObject.indexOfEnumerator("StandardButtons");
+
+ QMetaEnum metaEnum = messageBoxMetaObject.enumerator(index);
+ for (int i = 0; i < metaEnum.keyCount(); i++) {
+ int enumValue = metaEnum.value(i);
+ if (enumValue < QMessageBox::FirstButton)
+ continue;
+ messageBox.setProperty(QLatin1String(metaEnum.valueToKey(metaEnum.value(i))), newVariant(enumValue));
+ if (enumValue == QMessageBox::LastButton)
+ break;
+ }
+
+ return messageBox;
+}
+
+QScriptValue ScriptEngine::generateDesktopServicesObject()
+{
+ QScriptValue desktopServices = newArray();
+#if QT_VERSION < 0x050000
+ desktopServices.setProperty(QLatin1String("DesktopLocation"), QDesktopServices::DesktopLocation);
+ desktopServices.setProperty(QLatin1String("DesktopLocation"), QDesktopServices::DesktopLocation);
+ desktopServices.setProperty(QLatin1String("DocumentsLocation"), QDesktopServices::DocumentsLocation);
+ desktopServices.setProperty(QLatin1String("FontsLocation"), QDesktopServices::FontsLocation);
+ desktopServices.setProperty(QLatin1String("ApplicationsLocation"), QDesktopServices::ApplicationsLocation);
+ desktopServices.setProperty(QLatin1String("MusicLocation"), QDesktopServices::MusicLocation);
+ desktopServices.setProperty(QLatin1String("MoviesLocation"), QDesktopServices::MoviesLocation);
+ desktopServices.setProperty(QLatin1String("PicturesLocation"), QDesktopServices::PicturesLocation);
+ desktopServices.setProperty(QLatin1String("TempLocation"), QDesktopServices::TempLocation);
+ desktopServices.setProperty(QLatin1String("HomeLocation"), QDesktopServices::HomeLocation);
+ desktopServices.setProperty(QLatin1String("DataLocation"), QDesktopServices::DataLocation);
+ desktopServices.setProperty(QLatin1String("CacheLocation"), QDesktopServices::CacheLocation);
+#else
+ desktopServices.setProperty(QLatin1String("DesktopLocation"), QStandardPaths::DesktopLocation);
+ desktopServices.setProperty(QLatin1String("DesktopLocation"), QStandardPaths::DesktopLocation);
+ desktopServices.setProperty(QLatin1String("DocumentsLocation"), QStandardPaths::DocumentsLocation);
+ desktopServices.setProperty(QLatin1String("FontsLocation"), QStandardPaths::FontsLocation);
+ desktopServices.setProperty(QLatin1String("ApplicationsLocation"), QStandardPaths::ApplicationsLocation);
+ desktopServices.setProperty(QLatin1String("MusicLocation"), QStandardPaths::MusicLocation);
+ desktopServices.setProperty(QLatin1String("MoviesLocation"), QStandardPaths::MoviesLocation);
+ desktopServices.setProperty(QLatin1String("PicturesLocation"), QStandardPaths::PicturesLocation);
+ desktopServices.setProperty(QLatin1String("TempLocation"), QStandardPaths::TempLocation);
+ desktopServices.setProperty(QLatin1String("HomeLocation"), QStandardPaths::HomeLocation);
+ desktopServices.setProperty(QLatin1String("DataLocation"), QStandardPaths::DataLocation);
+ desktopServices.setProperty(QLatin1String("CacheLocation"), QStandardPaths::CacheLocation);
+#endif
+
+ desktopServices.setProperty(QLatin1String("openUrl"),
+ newFunction(qDesktopServicesOpenUrl));
+ desktopServices.setProperty(QLatin1String("displayName"),
+ newFunction(qDesktopServicesDisplayName));
+ desktopServices.setProperty(QLatin1String("storageLocation"),
+ newFunction(qDesktopServicesStorageLocation));
+ return desktopServices;
+}
+
+QScriptValue ScriptEngine::generateQInstallerObject()
+{
+ // register ::WizardPage enum in the script connection
+ QScriptValue qinstaller = newArray();
+ qinstaller.setProperty(QLatin1String("Introduction"), PackageManagerCore::Introduction);
+ qinstaller.setProperty(QLatin1String("LicenseCheck"), PackageManagerCore::LicenseCheck);
+ qinstaller.setProperty(QLatin1String("TargetDirectory"), PackageManagerCore::TargetDirectory);
+ qinstaller.setProperty(QLatin1String("ComponentSelection"), PackageManagerCore::ComponentSelection);
+ qinstaller.setProperty(QLatin1String("StartMenuSelection"), PackageManagerCore::StartMenuSelection);
+ qinstaller.setProperty(QLatin1String("ReadyForInstallation"), PackageManagerCore::ReadyForInstallation);
+ qinstaller.setProperty(QLatin1String("PerformInstallation"), PackageManagerCore::PerformInstallation);
+ qinstaller.setProperty(QLatin1String("InstallationFinished"), PackageManagerCore::InstallationFinished);
+ qinstaller.setProperty(QLatin1String("End"), PackageManagerCore::End);
+
+ // register ::Status enum in the script connection
+ qinstaller.setProperty(QLatin1String("Success"), PackageManagerCore::Success);
+ 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;
+}
+
diff --git a/src/libs/installer/scriptengine.h b/src/libs/installer/scriptengine.h
new file mode 100644
index 000000000..50c50539b
--- /dev/null
+++ b/src/libs/installer/scriptengine.h
@@ -0,0 +1,88 @@
+/**************************************************************************
+**
+** Copyright (C) 2012-2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Installer Framework.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+**************************************************************************/
+
+#ifndef SCRIPTENGINE_H
+#define SCRIPTENGINE_H
+
+#include "qinstallerglobal.h"
+
+#include <QtScript/QScriptEngine>
+
+namespace QInstaller {
+
+QString INSTALLER_EXPORT uncaughtExceptionString(const QScriptEngine *scriptEngine, const QString &context = QString());
+QScriptValue INSTALLER_EXPORT qInstallerComponentByName(QScriptContext *context, QScriptEngine *engine);
+
+QScriptValue INSTALLER_EXPORT qDesktopServicesOpenUrl(QScriptContext *context, QScriptEngine *engine);
+QScriptValue INSTALLER_EXPORT qDesktopServicesDisplayName(QScriptContext *context, QScriptEngine *engine);
+QScriptValue INSTALLER_EXPORT qDesktopServicesStorageLocation(QScriptContext *context, QScriptEngine *engine);
+
+QScriptValue INSTALLER_EXPORT qFileDialogGetExistingDirectory(QScriptContext *context, QScriptEngine *engine);
+QScriptValue INSTALLER_EXPORT qFileDialogGetOpenFileName(QScriptContext *context, QScriptEngine *engine);
+
+QScriptValue INSTALLER_EXPORT checkArguments(QScriptContext *context, int minimalArgumentCount, int maximalArgumentCount);
+
+class PackageManagerCore;
+
+class INSTALLER_EXPORT ScriptEngine : public QScriptEngine
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(ScriptEngine)
+
+public:
+ explicit ScriptEngine(PackageManagerCore *core);
+ ~ScriptEngine();
+ void setGuiQObject(QObject *guiQObject);
+ QScriptValue callScriptMethod(const QScriptValue &scriptContext, const QString &methodName,
+ const QScriptValueList &arguments = QScriptValueList()) const;
+
+ QScriptValue loadInConext(const QString &context, const QString &fileName, const QString &scriptInjection = QString());
+private slots:
+ void handleException(const QScriptValue &value);
+private:
+ QScriptValue generateMessageBoxObject();
+ QScriptValue generateDesktopServicesObject();
+ QScriptValue generateQInstallerObject();
+ PackageManagerCore *m_core;
+};
+}
+
+#endif // SCRIPTENGINE_H
diff --git a/src/libs/installer/settings.cpp b/src/libs/installer/settings.cpp
index a6795598a..d8f409f46 100644
--- a/src/libs/installer/settings.cpp
+++ b/src/libs/installer/settings.cpp
@@ -52,10 +52,12 @@
using namespace QInstaller;
static const QLatin1String scIcon("Icon");
+static const QLatin1String scInstallerApplicationIcon("InstallerApplicationIcon");
+static const QLatin1String scInstallerWindowIcon("InstallerWindowIcon");
static const QLatin1String scLogo("Logo");
-static const QLatin1String scPages("Pages");
static const QLatin1String scPrefix("Prefix");
static const QLatin1String scWatermark("Watermark");
+static const QLatin1String scBanner("Banner");
static const QLatin1String scProductUrl("ProductUrl");
static const QLatin1String scBackground("Background");
static const QLatin1String scAdminTargetDir("AdminTargetDir");
@@ -65,6 +67,7 @@ static const QLatin1String scTmpRepositories("TemporaryRepositories");
static const QLatin1String scUninstallerIniFile("UninstallerIniFile");
static const QLatin1String scRemoteRepositories("RemoteRepositories");
static const QLatin1String scDependsOnLocalInstallerBinary("DependsOnLocalInstallerBinary");
+static const QLatin1String scTranslations("Translations");
static const QLatin1String scFtpProxy("FtpProxy");
static const QLatin1String scHttpProxy("HttpProxy");
@@ -95,6 +98,25 @@ static void raiseError(QXmlStreamReader &reader, const QString &error, Settings:
}
}
+static QStringList readTranslations(QXmlStreamReader &reader, Settings::ParseMode parseMode)
+{
+ QStringList translations;
+ while (reader.readNextStartElement()) {
+ if (reader.name() == QLatin1String("Translation")) {
+ translations.append(reader.readElementText().toLower());
+ } else {
+ raiseError(reader, QString::fromLatin1("Unexpected element '%1'.").arg(reader.name().toString()),
+ parseMode);
+ }
+
+ if (!reader.attributes().isEmpty()) {
+ raiseError(reader, QString::fromLatin1("Unexpected attribute for element '%1'.").arg(reader
+ .name().toString()), parseMode);
+ }
+ }
+ return translations;
+}
+
static QSet<Repository> readRepositories(QXmlStreamReader &reader, bool isDefault, Settings::ParseMode parseMode)
{
QSet<Repository> set;
@@ -136,40 +158,6 @@ static QSet<Repository> readRepositories(QXmlStreamReader &reader, bool isDefaul
return set;
}
-static QVariantHash readTitles(QXmlStreamReader &reader)
-{
- QVariantHash hash;
- while (reader.readNextStartElement())
- hash.insert(reader.name().toString(), reader.readElementText(QXmlStreamReader::SkipChildElements));
- return hash;
-}
-
-static QHash<QString, QVariantHash> readPages(QXmlStreamReader &reader, Settings::ParseMode parseMode)
-{
- QHash<QString, QVariantHash> hash;
- while (reader.readNextStartElement()) {
- if (reader.name() == QLatin1String("Page")) {
- QVariantHash pageElements;
- const QString pageName = reader.attributes().value(QLatin1String("name")).toString();
- if (pageName.isEmpty()) {
- raiseError(reader, QLatin1String("Expected non-empty attribute 'name' for element 'Page'."),
- parseMode);
- }
- while (reader.readNextStartElement()) {
- const QString name = reader.name().toString();
- if (name == QLatin1String("Title") || name == QLatin1String("SubTitle"))
- pageElements.insert(name, readTitles(reader));
- else
- pageElements.insert(name, reader.readElementText(QXmlStreamReader::SkipChildElements));
- }
- hash.insert(pageName, pageElements);
- } else {
- raiseError(reader, QString::fromLatin1("Unexpected element '%1'.").arg(reader.name().toString()),
- parseMode);
- }
- }
- return hash;
-}
// -- Settings::Private
@@ -237,16 +225,14 @@ Settings Settings::fromFileAndPrefix(const QString &path, const QString &prefix,
QStringList elementList;
elementList << scName << scVersion << scTitle << scPublisher << scProductUrl
<< scTargetDir << scAdminTargetDir
- << scIcon << scLogo << scWatermark << scBackground
+ << scIcon << scInstallerApplicationIcon << scInstallerWindowIcon
+ << scLogo << scWatermark << scBanner << scBackground
<< scStartMenuDir << scUninstallerName << scUninstallerIniFile << scRemoveTargetDir
- << scRunProgram << scRunProgramDescription
+ << scRunProgram << scRunProgramArguments << scRunProgramDescription
<< scDependsOnLocalInstallerBinary
<< scAllowSpaceInPath << scAllowNonAsciiCharacters
<< scRepositorySettingsPageVisible << scTargetConfigurationFile
- << scRemoteRepositories << scPages;
-
- QStringList blackList;
- blackList << scRemoteRepositories << scPages;
+ << scRemoteRepositories << scTranslations;
Settings s;
s.d->m_data.insert(scPrefix, prefix);
@@ -260,22 +246,17 @@ Settings Settings::fromFileAndPrefix(const QString &path, const QString &prefix,
parseMode);
}
- if (blackList.contains(name)) {
- if (name == scRemoteRepositories)
- s.addDefaultRepositories(readRepositories(reader, true, parseMode));
+ if (name == scIcon)
+ qWarning() << "Deprecated element 'Icon'.";
- if (name == scPages) {
- qWarning() << "Deprecated element 'Pages'.";
- QHash<QString, QVariantHash> pages = readPages(reader, parseMode);
- const QStringList &keys = pages.keys();
- foreach (const QString &key, keys)
- s.d->m_data.insert(key, pages.value(key));
- }
+ if (s.d->m_data.contains(name))
+ reader.raiseError(QString::fromLatin1("Element '%1' has been defined before.").arg(name));
+
+ if (name == scTranslations) {
+ s.setTranslations(readTranslations(reader, parseMode));
+ } else if (name == scRemoteRepositories) {
+ s.addDefaultRepositories(readRepositories(reader, true, parseMode));
} else {
- if (s.d->m_data.contains(name)) {
- // instead of raising parse mode based error, raise a real error
- reader.raiseError(QString::fromLatin1("Element '%1' has been defined before.").arg(name));
- }
s.d->m_data.insert(name, reader.readElementText(QXmlStreamReader::SkipChildElements));
}
}
@@ -293,6 +274,10 @@ Settings Settings::fromFileAndPrefix(const QString &path, const QString &prefix,
// Add some possible missing values
if (!s.d->m_data.contains(scIcon))
s.d->m_data.insert(scIcon, QLatin1String(":/installer"));
+ if (!s.d->m_data.contains(scInstallerApplicationIcon))
+ s.d->m_data.insert(scInstallerApplicationIcon, s.d->m_data.value(scIcon));
+ if (!s.d->m_data.contains(scInstallerWindowIcon))
+ s.d->m_data.insert(scInstallerWindowIcon, s.d->m_data.value(scIcon).toString() + s.systemIconSuffix());
if (!s.d->m_data.contains(scRemoveTargetDir))
s.d->m_data.insert(scRemoveTargetDir, scTrue);
if (!s.d->m_data.contains(scUninstallerName))
@@ -344,6 +329,11 @@ QString Settings::watermark() const
return d->makeAbsolutePath(d->m_data.value(scWatermark).toString());
}
+QString Settings::banner() const
+{
+ return d->makeAbsolutePath(d->m_data.value(scBanner).toString());
+}
+
QString Settings::background() const
{
return d->makeAbsolutePath(d->m_data.value(scBackground).toString());
@@ -351,15 +341,30 @@ QString Settings::background() const
QString Settings::icon() const
{
- const QString icon = d->makeAbsolutePath(d->m_data.value(scIcon).toString());
+ return d->makeAbsolutePath(d->m_data.value(scIcon).toString() + systemIconSuffix());
+}
+
+QString Settings::installerApplicationIcon() const
+{
+ return d->makeAbsolutePath(d->m_data.value(scInstallerApplicationIcon).toString() + systemIconSuffix());
+}
+
+QString Settings::installerWindowIcon() const
+{
+ return d->makeAbsolutePath(d->m_data.value(scInstallerWindowIcon).toString());
+}
+
+QString Settings::systemIconSuffix() const
+{
#if defined(Q_OS_MAC)
- return icon + QLatin1String(".icns");
+ return QLatin1String(".icns");
#elif defined(Q_OS_WIN)
- return icon + QLatin1String(".ico");
+ return QLatin1String(".ico");
#endif
- return icon + QLatin1String(".png");
+ return QLatin1String(".png");
}
+
QString Settings::removeTargetDir() const
{
return d->m_data.value(scRemoveTargetDir).toString();
@@ -380,6 +385,11 @@ QString Settings::runProgram() const
return d->m_data.value(scRunProgram).toString();
}
+QString Settings::runProgramArguments() const
+{
+ return d->m_data.value(scRunProgramArguments).toString();
+}
+
QString Settings::runProgramDescription() const
{
return d->m_data.value(scRunProgramDescription).toString();
@@ -548,24 +558,6 @@ QVariantList Settings::values(const QString &key, const QVariantList &defaultVal
return list.isEmpty() ? defaultValue : list;
}
-QVariantHash Settings::titlesForPage(const QString &pageName) const
-{
- const QVariantHash hash = d->m_data.value(pageName).toHash();
- const QVariant variant = hash.value(QLatin1String("Title"), QVariant());
- if (!variant.canConvert<QVariantHash>())
- return QVariantHash();
- return variant.value<QVariantHash>();
-}
-
-QVariantHash Settings::subTitlesForPage(const QString &pageName) const
-{
- const QVariantHash hash = d->m_data.value(pageName).toHash();
- const QVariant variant = hash.value(QLatin1String("SubTitle"), QVariant());
- if (!variant.canConvert<QVariantHash>())
- return QVariantHash();
- return variant.value<QVariantHash>();
-}
-
bool Settings::repositorySettingsPageVisible() const
{
return d->m_data.value(scRepositorySettingsPageVisible, true).toBool();
@@ -606,3 +598,17 @@ void Settings::setHttpProxy(const QNetworkProxy &proxy)
{
d->m_data.insert(scHttpProxy, QVariant::fromValue(proxy));
}
+
+QStringList Settings::translations() const
+{
+ const QVariant variant = d->m_data.values(scTranslations);
+ if (variant.canConvert<QStringList>())
+ return variant.value<QStringList>();
+ return QStringList();
+}
+
+void Settings::setTranslations(const QStringList &translations)
+{
+ d->m_data.remove(scTranslations);
+ d->m_data.insert(scTranslations, translations);
+}
diff --git a/src/libs/installer/settings.h b/src/libs/installer/settings.h
index fcea7cb55..85a2ea68e 100644
--- a/src/libs/installer/settings.h
+++ b/src/libs/installer/settings.h
@@ -47,6 +47,7 @@
#include <QtCore/QCoreApplication>
#include <QtCore/QSharedDataPointer>
+#include <QtCore/QStringList>
#include <QtCore/QVariant>
#include <QtNetwork/QNetworkProxy>
@@ -93,13 +94,18 @@ public:
QString publisher() const;
QString url() const;
QString watermark() const;
+ QString banner() const;
QString background() const;
QString icon() const;
+ QString installerApplicationIcon() const;
+ QString installerWindowIcon() const;
+ QString systemIconSuffix() const;
QString applicationName() const;
QString applicationVersion() const;
QString runProgram() const;
+ QString runProgramArguments() const;
QString runProgramDescription() const;
QString startMenuDir() const;
QString targetDir() const;
@@ -135,9 +141,6 @@ public:
QVariant value(const QString &key, const QVariant &defaultValue = QVariant()) const;
QVariantList values(const QString &key, const QVariantList &defaultValue = QVariantList()) const;
- QVariantHash titlesForPage(const QString &pageName) const;
- QVariantHash subTitlesForPage(const QString &pageName) const;
-
bool repositorySettingsPageVisible() const;
Settings::ProxyType proxyType() const;
@@ -149,6 +152,9 @@ public:
QNetworkProxy httpProxy() const;
void setHttpProxy(const QNetworkProxy &proxy);
+ QStringList translations() const;
+ void setTranslations(const QStringList &translations);
+
private:
class Private;
QSharedDataPointer<Private> d;
diff --git a/src/libs/installer/sysinfo_win.cpp b/src/libs/installer/sysinfo_win.cpp
new file mode 100644
index 000000000..618d6cfdb
--- /dev/null
+++ b/src/libs/installer/sysinfo_win.cpp
@@ -0,0 +1,224 @@
+/**************************************************************************
+**
+** 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$
+**
+**************************************************************************/
+
+#include "kdsysinfo.h"
+
+#include "link.h"
+
+#ifdef Q_CC_MINGW
+# ifndef _WIN32_WINNT
+# define _WIN32_WINNT 0x0501
+# endif
+#endif
+
+#include <windows.h>
+#include <psapi.h>
+#include <tlhelp32.h>
+
+#include <winnetwk.h>
+
+#ifndef Q_CC_MINGW
+#pragma comment(lib, "mpr.lib")
+#endif
+
+#include <QDebug>
+#include <QDir>
+#include <QLibrary>
+
+namespace KDUpdater {
+
+VolumeInfo updateVolumeSizeInformation(const VolumeInfo &info)
+{
+ ULARGE_INTEGER bytesTotal;
+ ULARGE_INTEGER freeBytesPerUser;
+
+ VolumeInfo update = info;
+ if (GetDiskFreeSpaceExA(qPrintable(info.volumeDescriptor()), &freeBytesPerUser, &bytesTotal, NULL)) {
+ update.setSize(bytesTotal.QuadPart);
+ update.setAvailableSize(freeBytesPerUser.QuadPart);
+ }
+ return update;
+}
+
+/*!
+ Returns a list of volume info objects that are mounted as network drive shares.
+*/
+QList<VolumeInfo> networkVolumeInfosFromMountPoints()
+{
+ QList<VolumeInfo> volumes;
+ QFileInfoList drives = QDir::drives();
+ foreach (const QFileInfo &drive, drives) {
+ const QString driveLetter = QDir::toNativeSeparators(drive.canonicalPath());
+ const uint driveType = GetDriveTypeA(qPrintable(driveLetter));
+ switch (driveType) {
+ case DRIVE_REMOTE: {
+ char buffer[1024] = "";
+ DWORD bufferLength = 1024;
+ UNIVERSAL_NAME_INFOA *universalNameInfo = (UNIVERSAL_NAME_INFOA*) &buffer;
+ if (WNetGetUniversalNameA(qPrintable(driveLetter), UNIVERSAL_NAME_INFO_LEVEL,
+ LPVOID(universalNameInfo), &bufferLength) == NO_ERROR) {
+ VolumeInfo info;
+ info.setMountPath(driveLetter);
+ info.setVolumeDescriptor(QLatin1String(universalNameInfo->lpUniversalName));
+ volumes.append(info);
+ }
+ } break;
+
+ default:
+ break;
+ }
+ }
+ return volumes;
+}
+
+/*!
+ Returns a list of volume info objects based on the given \a volumeGUID. The function also solves mounted
+ volume folder paths. It does not return any network drive shares.
+*/
+QList<VolumeInfo> localVolumeInfosFromMountPoints(PTCHAR volumeGUID)
+{
+#ifndef UNICODE
+#define fromWCharArray fromLatin1
+#endif
+ QList<VolumeInfo> volumes;
+ DWORD bufferSize;
+ TCHAR volumeNames[MAX_PATH + 1] = { 0 };
+ if (GetVolumePathNamesForVolumeName(volumeGUID, volumeNames, MAX_PATH, &bufferSize)) {
+ QStringList mountedPaths = QString::fromWCharArray(volumeNames, bufferSize).split(QLatin1Char(char(0)),
+ QString::SkipEmptyParts);
+ foreach (const QString &mountedPath, mountedPaths) {
+ VolumeInfo info;
+ info.setMountPath(mountedPath);
+ info.setVolumeDescriptor(QString::fromWCharArray(volumeGUID));
+ volumes.append(info);
+ }
+ }
+ return volumes;
+#ifndef UNICODE
+#undef fromWCharArray
+#endif
+}
+
+QList<VolumeInfo> mountedVolumes()
+{
+ QList<VolumeInfo> tmp;
+ TCHAR volumeGUID[MAX_PATH + 1] = { 0 };
+ HANDLE handle = FindFirstVolume(volumeGUID, MAX_PATH);
+ if (handle != INVALID_HANDLE_VALUE) {
+ tmp += localVolumeInfosFromMountPoints(volumeGUID);
+ while (FindNextVolume(handle, volumeGUID, MAX_PATH)) {
+ tmp += localVolumeInfosFromMountPoints(volumeGUID);
+ }
+ FindVolumeClose(handle);
+ }
+ tmp += networkVolumeInfosFromMountPoints();
+
+ QList<VolumeInfo> volumes;
+ while (!tmp.isEmpty()) // update volume size information
+ volumes.append(updateVolumeSizeInformation(tmp.takeFirst()));
+ return volumes;
+}
+
+bool pathIsOnLocalDevice(const QString &path)
+{
+ if (!QFileInfo(path).exists())
+ return false;
+
+ if (path.startsWith(QLatin1String("\\\\")))
+ return false;
+
+ QDir dir(path);
+ do {
+ if (QFileInfo(dir, QString()).isSymLink()) {
+ QString currentPath = QFileInfo(dir, QString()).absoluteFilePath();
+ return pathIsOnLocalDevice(Link(currentPath).targetPath());
+ }
+ } while (dir.cdUp());
+
+ const UINT DRIVE_REMOTE_TYPE = 4;
+ if (path.contains(QLatin1Char(':'))) {
+ const QLatin1Char nullTermination('\0');
+ // for example "c:\"
+ const QString driveSearchString = path.left(3) + nullTermination;
+ WCHAR wCharDriveSearchArray[4];
+ driveSearchString.toWCharArray(wCharDriveSearchArray);
+ UINT type = GetDriveType(wCharDriveSearchArray);
+ if (type == DRIVE_REMOTE_TYPE)
+ return false;
+ }
+
+ return true;
+}
+
+bool CALLBACK TerminateAppEnum(HWND hwnd, LPARAM lParam)
+{
+ DWORD dwID;
+ GetWindowThreadProcessId(hwnd, &dwID);
+
+ if (dwID == (DWORD)lParam)
+ PostMessage(hwnd, WM_CLOSE, 0, 0);
+ return true;
+}
+
+bool killProcess(const ProcessInfo &process, int msecs)
+{
+ DWORD dwTimeout = msecs;
+ if (msecs == -1)
+ dwTimeout = INFINITE;
+
+ // If we can't open the process with PROCESS_TERMINATE rights, then we give up immediately.
+ HANDLE hProc = OpenProcess(SYNCHRONIZE | PROCESS_TERMINATE, false, process.id);
+ if (hProc == 0)
+ return false;
+
+ // TerminateAppEnum() posts WM_CLOSE to all windows whose PID matches your process's.
+ EnumWindows((WNDENUMPROC)TerminateAppEnum, (LPARAM)process.id);
+
+ // Wait on the handle. If it signals, great. If it times out, then kill it.
+ bool returnValue = false;
+ if (WaitForSingleObject(hProc, dwTimeout) != WAIT_OBJECT_0)
+ returnValue = TerminateProcess(hProc, 0);
+
+ CloseHandle(hProc);
+ return returnValue;
+}
+
+} \ No newline at end of file
diff --git a/src/libs/installer/utils.cpp b/src/libs/installer/utils.cpp
index 1112bcebb..2b5491f62 100644
--- a/src/libs/installer/utils.cpp
+++ b/src/libs/installer/utils.cpp
@@ -45,6 +45,7 @@
#include <QtCore/QDir>
#include <QtCore/QProcessEnvironment>
#include <QtCore/QVector>
+#include <QCoreApplication>
#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE)
# include "qt_windows.h"
@@ -54,6 +55,39 @@
#include <iostream>
#include <sstream>
+
+#ifdef Q_OS_WIN
+#include <windows.h> // for Sleep
+#endif
+#ifdef Q_OS_UNIX
+#include <errno.h>
+#include <signal.h>
+#include <time.h>
+#endif
+
+namespace {
+void sleepCopiedFromQTest(int ms)
+{
+ if (ms < 0)
+ return;
+#ifdef Q_OS_WIN
+ Sleep(uint(ms));
+#else
+ struct timespec ts = { ms / 1000, (ms % 1000) * 1000 * 1000 };
+ nanosleep(&ts, NULL);
+#endif
+}
+}
+void QInstaller::uiDetachedWait(int ms)
+{
+ QTime timer;
+ timer.start();
+ do {
+ QCoreApplication::processEvents(QEventLoop::AllEvents, ms);
+ sleepCopiedFromQTest(10);
+ } while (timer.elapsed() < ms);
+}
+
static bool verb = false;
void QInstaller::setVerbose(bool v)
diff --git a/src/libs/installer/utils.h b/src/libs/installer/utils.h
index 0d21adbee..229dfe95a 100644
--- a/src/libs/installer/utils.h
+++ b/src/libs/installer/utils.h
@@ -57,6 +57,7 @@ class QIODevice;
QT_END_NAMESPACE
namespace QInstaller {
+ void INSTALLER_EXPORT uiDetachedWait(int ms);
QByteArray INSTALLER_EXPORT calculateHash(QIODevice *device, QCryptographicHash::Algorithm algo);
QByteArray INSTALLER_EXPORT calculateHash(const QString &path, QCryptographicHash::Algorithm algo);
@@ -81,7 +82,7 @@ namespace QInstaller {
{
Q_OBJECT
public:
- VerboseWriter(QObject *parent = 0);
+ explicit VerboseWriter(QObject *parent = 0);
~VerboseWriter();
static VerboseWriter *instance();