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_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.cpp463
-rw-r--r--src/libs/installer/component.h12
-rw-r--r--src/libs/installer/component_p.cpp177
-rw-r--r--src/libs/installer/component_p.h20
-rw-r--r--src/libs/installer/componentmodel.cpp450
-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/createshortcutoperation.cpp12
-rw-r--r--src/libs/installer/downloadarchivesjob.cpp16
-rw-r--r--src/libs/installer/elevatedexecuteoperation.cpp7
-rw-r--r--src/libs/installer/errors.h5
-rw-r--r--src/libs/installer/fileutils.cpp42
-rw-r--r--src/libs/installer/fileutils.h3
-rw-r--r--src/libs/installer/fsengineclient.cpp22
-rw-r--r--src/libs/installer/fsengineserver.cpp14
-rw-r--r--src/libs/installer/getrepositoriesmetainfojob.cpp11
-rw-r--r--src/libs/installer/getrepositorymetainfojob.cpp32
-rw-r--r--src/libs/installer/globals.cpp47
-rw-r--r--src/libs/installer/globals.h54
-rw-r--r--src/libs/installer/init.cpp91
-rw-r--r--src/libs/installer/installer.pro20
-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.h6
-rw-r--r--src/libs/installer/messageboxhandler.cpp167
-rw-r--r--src/libs/installer/messageboxhandler.h4
-rw-r--r--src/libs/installer/packagemanagercore.cpp858
-rw-r--r--src/libs/installer/packagemanagercore.h6
-rw-r--r--src/libs/installer/packagemanagercore_p.cpp42
-rw-r--r--src/libs/installer/packagemanagercore_p.h42
-rw-r--r--src/libs/installer/packagemanagercoredata.cpp2
-rw-r--r--src/libs/installer/packagemanagergui.cpp341
-rw-r--r--src/libs/installer/packagemanagergui.h13
-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.cpp24
-rw-r--r--src/libs/installer/productkeycheck.h10
-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.cpp32
-rw-r--r--src/libs/installer/qprocesswrapper.h1
-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.cpp77
-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.cpp408
-rw-r--r--src/libs/installer/scriptengine.h88
-rw-r--r--src/libs/installer/settings.cpp124
-rw-r--r--src/libs/installer/settings.h8
-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
68 files changed, 3142 insertions, 1563 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_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 c5168dcb8..c6562f333 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..ffc4ea904 100644
--- a/src/libs/installer/component.cpp
+++ b/src/libs/installer/component.cpp
@@ -39,13 +39,14 @@
**
**************************************************************************/
#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 <kdupdaterupdatesourcesinfo.h>
@@ -75,11 +76,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 +268,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, QString::number(0));
+ setValue(scUncompressedSize, QString::number(0));
setValue(scRemoteVersion, package.data(scRemoteVersion).toString());
setValue(scInheritVersion, package.data(scInheritVersion).toString());
setValue(scDependencies, package.data(scDependencies).toString());
@@ -181,14 +302,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 +348,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 +362,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 +389,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 +433,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 +476,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()));
- }
-
- 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);
+ ScriptEngine *scriptEngine = d->m_core->scriptEngine();
- QScriptValue comp = d->scriptEngine()->evaluate(QLatin1String("Component"), fileName);
- if (!d->scriptEngine()->hasUncaughtException()) {
- d->m_scriptComponent = comp;
- d->m_scriptComponent.construct();
- }
+ // 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()));
- //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,46 +504,14 @@ 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)
{
@@ -456,7 +523,7 @@ void Component::loadTranslations(const QDir &directory, const QStringList &qms)
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 +531,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 +547,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, MessageBoxHandler::currentBestSuitParent());
+ 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 +577,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 +588,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 +598,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 +615,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 +625,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 +647,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 +671,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 +692,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 +707,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 +745,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 +758,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 +770,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 +794,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 +811,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 +833,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 +844,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 +854,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 +875,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
@@ -865,10 +987,9 @@ Operation *Component::createOperation(const QString &operation, const QStringLis
}
/*!
- 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 +1004,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 +1022,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 +1040,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 +1060,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 +1068,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 +1084,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 +1104,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 +1141,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 +1167,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 +1184,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 +1217,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 +1234,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 +1252,8 @@ bool Component::isDefault() const
}
/*!
+ \qmlmethod boolean Component::isInstalled()
+
Determines if the component is installed.
*/
bool Component::isInstalled() const
@@ -1100,6 +1262,8 @@ bool Component::isInstalled() const
}
/*!
+ \qmlmethod boolean Component::installationRequested()
+
Determines if the user wants to install the component
*/
bool Component::installationRequested() const
@@ -1108,6 +1272,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 +1282,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 +1292,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 +1303,8 @@ bool Component::componentChangeRequested()
/*!
+ \qmlmethod void Component::setUninstalled()
+
Sets the component state to uninstalled.
*/
void Component::setUninstalled()
@@ -1141,6 +1313,8 @@ void Component::setUninstalled()
}
/*!
+ \qmlmethod boolean Component::isUninstalled()
+
Determines if the component is uninstalled.
*/
bool Component::isUninstalled() const
@@ -1149,6 +1323,8 @@ bool Component::isUninstalled() const
}
/*!
+ \qmlmethod boolean Component::uninstallationRequested()
+
Determines if the user wants to uninstall the component.
*/
bool Component::uninstallationRequested() const
@@ -1159,10 +1335,11 @@ bool Component::uninstallationRequested() const
}
/*!
- \property Component::fromOnlineRepository
+ \qmlmethod boolean Component::isFromOnlineRepository()
+
+ Determines whether this component has been loaded from an online repository.
- Determines whether this component has been loaded from an online repository. Get this property's
- value by using %isFromOnlineRepository. \sa addDownloadableArchive
+ \sa addDownloadableArchive, fromOnlineRepository
*/
bool Component::isFromOnlineRepository() const
{
diff --git a/src/libs/installer/component.h b/src/libs/installer/component.h
index 1c8712145..bf5ef4d18 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,10 +227,6 @@ 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);
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..1f81ffd4d 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;
};
@@ -125,10 +113,8 @@ public:
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..f65611ffe 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,218 @@ 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_initialCheckedState.clear();
+ m_currentCheckedState.clear();
+ m_modelState = DefaultChecked;
+
+ // 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_currentCheckedState = m_initialCheckedState;
+ updateAndEmitModelState(); // update the internal state
+}
+
+
+// -- private
+
+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;
}
- m_currentCheckedSet += m_initialCheckedSet;
- if (m_core->runMode() == QInstaller::AllMode)
- select(Qt::Unchecked);
+ if (unchecked().count() == 0 && partially().count() == 0) {
+ m_modelState |= ComponentModel::AllChecked;
+ m_modelState &= ~ComponentModel::PartiallyChecked;
+ }
- foreach (const QString &name, m_currentCheckedSet)
- setData(indexFromComponentName(name), Qt::Checked, Qt::CheckStateRole);
+ 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;
+ 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/createshortcutoperation.cpp b/src/libs/installer/createshortcutoperation.cpp
index 62f7cfa82..2f2696fcd 100644
--- a/src/libs/installer/createshortcutoperation.cpp
+++ b/src/libs/installer/createshortcutoperation.cpp
@@ -107,8 +107,9 @@ static QString takeWorkingDirArgument(QStringList &args)
static bool createLink(const QString &fileName, const QString &linkName, QString workingDir,
QString arguments = QString())
{
- bool success = QFile::link(fileName, linkName);
#ifdef Q_OS_WIN
+ bool success = QFile::link(fileName, linkName);
+
if (!success)
return success;
@@ -131,7 +132,7 @@ static bool createLink(const QString &fileName, const QString &linkName, QString
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 +146,16 @@ 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)
+
+ return true;
#endif
- return success;
}
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..2e1d050a2 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;
}
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/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..62e3cf871 100644
--- a/src/libs/installer/fsengineclient.cpp
+++ b/src/libs/installer/fsengineclient.cpp
@@ -169,9 +169,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 +588,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 +753,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
{
diff --git a/src/libs/installer/fsengineserver.cpp b/src/libs/installer/fsengineserver.cpp
index 991681b95..b17e1ae0a 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:
@@ -448,6 +448,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..99b7e4340 100644
--- a/src/libs/installer/getrepositoriesmetainfojob.cpp
+++ b/src/libs/installer/getrepositoriesmetainfojob.cpp
@@ -43,7 +43,6 @@
#include "getrepositorymetainfojob.h"
#include "packagemanagercore_p.h"
-#include "qinstallerglobal.h"
#include <QtCore/QDebug>
@@ -54,11 +53,11 @@ using namespace QInstaller;
// -- GetRepositoriesMetaInfoJob
GetRepositoriesMetaInfoJob::GetRepositoriesMetaInfoJob(PackageManagerCorePrivate *corePrivate)
- : KDJob(corePrivate),
- m_canceled(false),
- m_silentRetries(3),
- m_haveIgnoredError(false),
- m_corePrivate(corePrivate)
+ : KDJob(corePrivate)
+ , m_canceled(false)
+ , m_silentRetries(3)
+ , m_haveIgnoredError(false)
+ , m_corePrivate(corePrivate)
{
setCapabilities(Cancelable);
}
diff --git a/src/libs/installer/getrepositorymetainfojob.cpp b/src/libs/installer/getrepositorymetainfojob.cpp
index b0386c223..6913a63e5 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;
@@ -121,13 +112,13 @@ 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)
+ : KDJob(parent)
+ , m_canceled(false)
+ , m_silentRetries(4)
+ , m_retriesLeft(m_silentRetries)
+ , m_downloader(0)
+ , m_waitForDone(false)
+ , m_corePrivate(corePrivate)
{
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);
@@ -379,7 +373,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 =
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/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..ab28aa72b 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,9 @@ HEADERS += packagemanagercore.h \
link.h \
createlinkoperation.h \
packagemanagercoredata.h \
- applyproductkeyoperation.h
+ registerqtincreatorqnxoperation.h \
+ applyproductkeyoperation.h \
+ globals.h
SOURCES += packagemanagercore.cpp \
packagemanagercore_p.cpp \
@@ -117,10 +124,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 +138,6 @@ HEADERS += packagemanagercore.h \
replaceoperation.cpp \
linereplaceoperation.cpp \
registertoolchainoperation.cpp \
- registerqtvqnxoperation.cpp \
setqtcreatorvalueoperation.cpp \
addqtcreatorarrayvalueoperation.cpp \
copydirectoryoperation.cpp \
@@ -173,7 +181,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 +199,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/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.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..99e3087e7 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,273 @@
# 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::setRootComponents(list<Component> components)
+
+ Triggered with the list of new root components (for example after an online update).
+*/
+
+/*!
+ \qmlsignal QInstaller::startAllComponentsReset()
+
+ Triggered when the list of components starts to get updated.
+
+ \sa finishAllComponentsReset
+*/
+
+/*!
+ \qmlsignal QInstaller::finishAllComponentsReset()
+
+ Triggered when the list of components has been updated.
+
+ \sa startAllComponentsReset
+*/
+
+/*!
+ \qmlsignal QInstaller::startUpdaterComponentsReset()
+
+ Triggered when components start to get updated during a remote update.
+*/
+
+/*!
+ \qmlsignal QInstaller::finishUpdaterComponentsReset()
+
+ Triggered when components have been updated during a remote update.
+*/
+
+/*!
+ \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 +371,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 +394,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) {
@@ -330,6 +430,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 +440,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 +507,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 +524,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 +636,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 +659,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 +693,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 +715,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 +733,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 +775,6 @@ void PackageManagerCore::setCreateLocalRepositoryFromBinary(bool create)
sCreateLocalRepositoryFromBinary = create;
}
-RunMode PackageManagerCore::runMode() const
-{
- return isUpdater() ? UpdaterMode : AllMode;
-}
-
bool PackageManagerCore::fetchLocalPackagesTree()
{
d->setStatus(Running);
@@ -705,8 +869,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,7 +889,7 @@ bool PackageManagerCore::fetchRemotePackagesTree()
return false;
bool success = false;
- if (runMode() == AllMode)
+ if (!isUpdater())
success = fetchAllPackages(packages, installedPackages);
else {
success = fetchUpdaterPackages(packages, installedPackages);
@@ -739,9 +903,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 +924,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 +943,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 +959,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 +972,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 +991,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 +1007,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 +1024,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 +1056,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 +1100,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 +1150,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 +1186,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 +1225,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 +1266,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,7 +1310,7 @@ 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"));
@@ -1100,7 +1320,7 @@ ComponentModel *PackageManagerCore::defaultComponentModel() const
ComponentModel *PackageManagerCore::updaterComponentModel() const
{
- QMutexLocker _(&sModelMutex);
+ QMutexLocker _(globalModelMutex());
if (!d->m_updaterModel) {
d->m_updaterModel = componentModel(const_cast<PackageManagerCore*> (this),
QLatin1String("UpdaterComponentsModel"));
@@ -1114,7 +1334,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 +1352,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 +1364,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 +1375,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 +1413,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 +1446,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 +1492,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.
+
+ \b{Unix:} The started process will run in its own session and act
+ like a daemon.
- \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{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 +1529,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 +1555,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 +1580,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 +1609,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 +1643,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 +1666,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 +1679,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 +1692,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 +1706,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 +1764,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 +1772,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 +1835,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 +1847,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 +1927,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 +1937,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 +1947,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 +1957,8 @@ bool PackageManagerCore::runPackageUpdater()
}
/*!
- \internal
+ \qmlmethod void QInstaller::languageChanged()
+
Calls languangeChanged on all components.
*/
void PackageManagerCore::languageChanged()
@@ -1646,7 +2018,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 +2026,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 +2083,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 +2103,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;
@@ -1775,7 +2146,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 +2174,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;
@@ -1851,14 +2222,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
@@ -1976,7 +2351,8 @@ ComponentModel *PackageManagerCore::componentModel(PackageManagerCore *core, con
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..712a5174c 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;
@@ -121,7 +122,6 @@ public:
bool fetchRemotePackagesTree();
bool run();
- RunMode runMode() const;
void reset(const QHash<QString, QString> &params);
Q_INVOKABLE void setDependsOnLocalInstallerBinary();
@@ -174,7 +174,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;
@@ -297,7 +300,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..652ecb88a 100644
--- a/src/libs/installer/packagemanagercore_p.cpp
+++ b/src/libs/installer/packagemanagercore_p.cpp
@@ -43,10 +43,12 @@
#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 "messageboxhandler.h"
#include "packagemanagercore.h"
#include "progresscoordinator.h"
@@ -58,7 +60,6 @@
#include "kdupdaterfiledownloaderfactory.h"
#include "kdupdaterupdatesourcesinfo.h"
#include "kdupdaterupdateoperationfactory.h"
-#include "kdupdaterupdatefinder.h"
#include <productkeycheck.h>
@@ -201,6 +202,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 +210,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 +220,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 +237,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 +263,7 @@ PackageManagerCorePrivate::~PackageManagerCorePrivate()
m_FSEngineClientHandler->setActive(false);
delete m_updateFinder;
+ delete m_scriptEngine;
delete m_proxyFactory;
delete m_defaultModel;
@@ -384,6 +390,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 +435,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 +466,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 +570,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);
}
}
@@ -775,7 +788,7 @@ void PackageManagerCorePrivate::writeMaintenanceConfigFiles()
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);
@@ -2008,7 +2021,7 @@ void PackageManagerCorePrivate::runUndoOperations(const OperationList &undoOpera
if (!componentName.isEmpty()) {
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 +2054,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 +2297,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);
}
diff --git a/src/libs/installer/packagemanagercore_p.h b/src/libs/installer/packagemanagercore_p.h
index 9d4a6abab..11ed23230 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);
@@ -241,6 +262,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..efc83f520 100644
--- a/src/libs/installer/packagemanagercoredata.cpp
+++ b/src/libs/installer/packagemanagercoredata.cpp
@@ -90,6 +90,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 +98,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..dddec8aae 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()
@@ -350,58 +345,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 +358,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;
+ try {
+ QScriptValue returnValue = m_core->scriptEngine()->callScriptMethod(
+ d->m_controlScriptContext, methodName);
- method.call(d->m_controlScript);
-
- 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 +400,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 +410,6 @@ void PackageManagerGui::showEvent(QShowEvent *event)
}
}
}
-#endif
QWizard::showEvent(event);
QMetaObject::invokeMethod(this, "dependsOnLocalInstallerBinary", Qt::QueuedConnection);
}
@@ -692,6 +629,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 +639,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 +725,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 +764,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 +825,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 +954,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 +979,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(onCheckStateChanged(QInstaller::ComponentModel::ModelState)));
+ connect(m_updaterModel, SIGNAL(checkStateChanged(QInstaller::ComponentModel::ModelState)), this,
+ SLOT(onCheckStateChanged(QInstaller::ComponentModel::ModelState)));
QHBoxLayout *hlayout = new QHBoxLayout;
hlayout->addWidget(m_treeView, 3);
@@ -1099,18 +1008,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 +1026,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));
@@ -1139,10 +1044,10 @@ 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)));
+ SLOT(currentCheckedChanged(QModelIndex)));
+ disconnect(m_treeView->selectionModel(), SIGNAL(currentChanged(QModelIndex, QModelIndex)),
+ this, SLOT(currentSelectedChanged(QModelIndex)));
}
m_currentModel = m_core->isUpdater() ? m_updaterModel : m_allModel;
@@ -1165,62 +1070,69 @@ public:
hasChildren = m_currentModel->hasChildren(m_currentModel->index(row, 0));
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)));
+ SLOT(currentCheckedChanged(QModelIndex)));
+ connect(m_treeView->selectionModel(), SIGNAL(currentChanged(QModelIndex, QModelIndex)),
+ this, SLOT(currentSelectedChanged(QModelIndex)));
m_treeView->setCurrentIndex(m_currentModel->index(0, 0));
}
public slots:
- void currentChanged(const QModelIndex &current)
+ void currentCheckedChanged(const QModelIndex &current)
+ {
+ if (m_treeView->selectionModel()->currentIndex() == current)
+ currentSelectedChanged(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->checkState() != Qt::Unchecked) && (component->updateUncompressedSize() > 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);
+ }
+
+ void onCheckStateChanged(QInstaller::ComponentModel::ModelState state)
+ {
+ q->setModified(state != ComponentModel::DefaultChecked);
+
+ // 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;
- m_checkAll->setEnabled(true);
- m_uncheckAll->setEnabled(true);
+ // 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);
}
public:
@@ -1248,10 +1160,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 +1184,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 +1242,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() != ComponentModel::DefaultChecked;
}
@@ -1341,20 +1252,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 +1275,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 +1309,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 +1325,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 +1335,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 +1358,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 +1371,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"));
@@ -1561,10 +1460,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 +1509,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 +1519,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 +1688,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 +1731,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 +1808,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);
@@ -2012,11 +1902,13 @@ 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);
}
@@ -2026,10 +1918,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..37e5d6852 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;
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..fe1fd10af 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,7 @@ QString ProductKeyCheck::maintainanceToolDetailErrorNotice()
}
// to filter none valid licenses
-bool ProductKeyCheck::isValidLicense(const QString &/*fileName*/)
+bool ProductKeyCheck::isValidLicenseTextFile(const QString &/*fileName*/)
{
return true;
}
diff --git a/src/libs/installer/productkeycheck.h b/src/libs/installer/productkeycheck.h
index 1ecffc3d2..d472d9288 100644
--- a/src/libs/installer/productkeycheck.h
+++ b/src/libs/installer/productkeycheck.h
@@ -34,6 +34,11 @@
#include <QString>
#include <QHash>
+#include <QPointer>
+
+namespace QInstaller{
+ class PackageManagerCore;
+}
class ProductKeyCheckPrivate;
@@ -41,7 +46,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 +58,7 @@ public:
bool applyKey(const QStringList &arguments);
// to filter none valid licenses
- bool isValidLicense(const QString &fileName);
+ bool isValidLicenseTextFile(const QString &fileName);
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..416ca9f4c 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()
@@ -352,7 +352,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 +371,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 +381,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 +389,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..15e6f1fba 100644
--- a/src/libs/installer/qprocesswrapper.h
+++ b/src/libs/installer/qprocesswrapper.h
@@ -100,6 +100,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..25924811a 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;
}
@@ -169,7 +176,24 @@ bool QtPatchOperation::performOperation()
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 +204,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();
@@ -239,13 +274,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..9ff8ae75e
--- /dev/null
+++ b/src/libs/installer/scriptengine.cpp
@@ -0,0 +1,408 @@
+/**************************************************************************
+**
+** 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);
+
+ 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..8ef248db8 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");
@@ -136,40 +138,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 +205,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;
Settings s;
s.d->m_data.insert(scPrefix, prefix);
@@ -260,22 +226,15 @@ 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 == 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 +252,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 +307,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 +319,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 +363,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 +536,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();
diff --git a/src/libs/installer/settings.h b/src/libs/installer/settings.h
index fcea7cb55..277264f79 100644
--- a/src/libs/installer/settings.h
+++ b/src/libs/installer/settings.h
@@ -93,13 +93,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 +140,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;
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();