2011-02-21 16:30:31 +01:00
|
|
|
/**************************************************************************
|
|
|
|
**
|
|
|
|
** This file is part of Qt SDK**
|
|
|
|
**
|
|
|
|
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
|
|
|
|
**
|
|
|
|
** Contact: Nokia Corporation qt-info@nokia.com**
|
|
|
|
**
|
|
|
|
** No Commercial Usage
|
|
|
|
**
|
|
|
|
** This file contains pre-release code and may not be distributed.
|
|
|
|
** You may use this file in accordance with the terms and conditions
|
|
|
|
** contained in the Technology Preview License Agreement accompanying
|
|
|
|
** this package.
|
|
|
|
**
|
|
|
|
** GNU Lesser General Public License Usage
|
|
|
|
**
|
|
|
|
** 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, Nokia gives you certain additional
|
|
|
|
** rights. These rights are described in the Nokia Qt LGPL Exception version
|
|
|
|
** 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|
|
|
**
|
|
|
|
** If you are unsure which license is appropriate for your use, please contact
|
|
|
|
** (qt-info@nokia.com).
|
|
|
|
**
|
|
|
|
**************************************************************************/
|
2011-06-09 11:54:06 +02:00
|
|
|
#include "component.h"
|
2011-02-21 16:30:31 +01:00
|
|
|
|
|
|
|
#include "common/errors.h"
|
2011-03-10 18:36:07 +01:00
|
|
|
#include "common/fileutils.h"
|
2011-03-09 12:45:22 +01:00
|
|
|
#include "common/utils.h"
|
|
|
|
#include "fsengineclient.h"
|
2011-02-21 16:30:31 +01:00
|
|
|
#include "lib7z_facade.h"
|
2011-06-15 12:39:03 +02:00
|
|
|
#include "packagemanagercore.h"
|
2011-03-09 12:45:22 +01:00
|
|
|
#include "qinstallerglobal.h"
|
|
|
|
#include "messageboxhandler.h"
|
2011-02-21 16:30:31 +01:00
|
|
|
|
2011-03-10 18:36:07 +01:00
|
|
|
#include <KDUpdater/UpdateSourcesInfo>
|
2011-02-21 16:30:31 +01:00
|
|
|
#include <KDUpdater/UpdateOperationFactory>
|
|
|
|
|
2011-03-09 12:45:22 +01:00
|
|
|
#include <QtCore/QDirIterator>
|
|
|
|
#include <QtCore/QTranslator>
|
2011-03-23 21:09:14 +01:00
|
|
|
|
|
|
|
#include <QtGui/QApplication>
|
|
|
|
|
2011-03-09 12:45:22 +01:00
|
|
|
#include <QtUiTools/QUiLoader>
|
2011-02-21 16:30:31 +01:00
|
|
|
|
2011-04-01 10:20:07 +02:00
|
|
|
#include <algorithm>
|
|
|
|
|
2011-06-06 17:23:48 +02:00
|
|
|
using namespace QInstaller;
|
2011-04-12 15:32:46 +02:00
|
|
|
|
2011-07-05 13:42:31 +02:00
|
|
|
static const QLatin1String scScript("Script");
|
|
|
|
static const QLatin1String scDefault("Default");
|
2011-07-22 14:35:19 +02:00
|
|
|
static const QLatin1String scAutoDependOn("AutoDependOn");
|
2011-07-05 13:42:31 +02:00
|
|
|
static const QLatin1String scVirtual("Virtual");
|
|
|
|
static const QLatin1String scInstalled("Installed");
|
|
|
|
static const QLatin1String scUpdateText("UpdateText");
|
|
|
|
static const QLatin1String scUninstalled("Uninstalled");
|
|
|
|
static const QLatin1String scCurrentState("CurrentState");
|
|
|
|
static const QLatin1String scForcedInstallation("ForcedInstallation");
|
2011-02-21 16:30:31 +01:00
|
|
|
|
|
|
|
/*!
|
2011-03-09 12:45:22 +01:00
|
|
|
\class QInstaller::Component
|
|
|
|
Component describes a component within the installer.
|
2011-02-21 16:30:31 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
/*!
|
2011-03-09 12:45:22 +01:00
|
|
|
Constructor. Creates a new Component inside of \a installer.
|
2011-02-21 16:30:31 +01:00
|
|
|
*/
|
2011-06-14 16:24:50 +02:00
|
|
|
Component::Component(PackageManagerCore *core)
|
|
|
|
: d(new ComponentPrivate(core, this))
|
2011-02-21 16:30:31 +01:00
|
|
|
{
|
|
|
|
d->init();
|
2011-03-23 22:30:29 +01:00
|
|
|
setPrivate(d);
|
2011-04-01 13:55:31 +02:00
|
|
|
|
|
|
|
connect(this, SIGNAL(valueChanged(QString, QString)), this, SLOT(updateModelData(QString, QString)));
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
2011-03-09 12:45:22 +01:00
|
|
|
Destroys the Component.
|
2011-02-21 16:30:31 +01:00
|
|
|
*/
|
|
|
|
Component::~Component()
|
|
|
|
{
|
2011-03-09 12:45:22 +01:00
|
|
|
if (parentComponent() != 0)
|
2011-07-21 20:05:08 +02:00
|
|
|
d->m_parentComponent->d->m_allChildComponents.removeAll(this);
|
2011-02-21 16:30:31 +01:00
|
|
|
|
2011-07-26 16:33:11 +02:00
|
|
|
//why can we delete all create operations if the component gets destroyed
|
2011-02-21 16:30:31 +01:00
|
|
|
if (!d->m_newlyInstalled)
|
2011-04-13 11:06:16 +02:00
|
|
|
qDeleteAll(d->m_operations);
|
2011-02-21 16:30:31 +01:00
|
|
|
|
2011-07-21 20:05:08 +02:00
|
|
|
qDeleteAll(d->m_allChildComponents);
|
2011-02-21 16:30:31 +01:00
|
|
|
delete d;
|
|
|
|
}
|
|
|
|
|
2011-07-05 13:22:05 +02:00
|
|
|
void Component::loadDataFromPackage(const LocalPackage &package)
|
2011-03-10 18:36:07 +01:00
|
|
|
{
|
2011-07-05 13:22:05 +02:00
|
|
|
setValue(scName, package.name);
|
2011-06-30 14:03:22 +02:00
|
|
|
// pixmap ???
|
2011-07-05 13:22:05 +02:00
|
|
|
setValue(scDisplayName, package.title);
|
|
|
|
setValue(scDescription, package.description);
|
|
|
|
setValue(scVersion, package.version);
|
|
|
|
setValue(scInstalledVersion, package.version);
|
|
|
|
setValue(QLatin1String("LastUpdateDate"), package.lastUpdateDate.toString());
|
|
|
|
setValue(QLatin1String("InstallDate"), package.installDate.toString());
|
|
|
|
setValue(scUncompressedSize, QString::number(package.uncompressedSize));
|
2011-03-11 12:39:45 +01:00
|
|
|
|
2011-03-10 18:36:07 +01:00
|
|
|
QString dependstr = QLatin1String("");
|
2011-07-05 13:22:05 +02:00
|
|
|
foreach (const QString& val, package.dependencies)
|
2011-03-11 12:39:45 +01:00
|
|
|
dependstr += val + QLatin1String(",");
|
|
|
|
|
2011-07-05 13:22:05 +02:00
|
|
|
if (package.dependencies.count() > 0)
|
2011-03-10 18:36:07 +01:00
|
|
|
dependstr.chop(1);
|
2011-06-06 17:23:48 +02:00
|
|
|
setValue(scDependencies, dependstr);
|
2011-03-11 12:39:45 +01:00
|
|
|
|
2011-07-05 13:22:05 +02:00
|
|
|
setValue(scForcedInstallation, package.forcedInstallation ? scTrue : scFalse);
|
|
|
|
if (package.forcedInstallation & !PackageManagerCore::noForceInstallation()) {
|
2011-04-12 11:21:20 +02:00
|
|
|
setEnabled(false);
|
|
|
|
setCheckable(false);
|
|
|
|
setCheckState(Qt::Checked);
|
2011-03-16 10:22:13 +01:00
|
|
|
}
|
2011-07-05 13:22:05 +02:00
|
|
|
setValue(scVirtual, package.virtualComp ? scTrue : scFalse);
|
2011-06-30 14:03:22 +02:00
|
|
|
setValue(scCurrentState, scInstalled);
|
2011-03-10 18:36:07 +01:00
|
|
|
}
|
|
|
|
|
2011-07-05 13:22:05 +02:00
|
|
|
void Component::loadDataFromPackage(const Package &package)
|
2011-03-10 18:36:07 +01:00
|
|
|
{
|
2011-07-05 13:22:05 +02:00
|
|
|
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(scCompressedSize, QString::number(package.compressedSize()));
|
|
|
|
setValue(scUncompressedSize, QString::number(package.uncompressedSize()));
|
|
|
|
setValue(scVersion, package.data(scVersion).toString());
|
|
|
|
setValue(scDependencies, package.data(scDependencies).toString());
|
|
|
|
setValue(scVirtual, package.data(scVirtual).toString());
|
|
|
|
setValue(scSortingPriority, package.data(scSortingPriority).toString());
|
|
|
|
setValue(scInstallPriority, package.data(scInstallPriority).toString());
|
|
|
|
|
|
|
|
setValue(scImportant, package.data(scImportant).toString());
|
|
|
|
setValue(scUpdateText, package.data(scUpdateText).toString());
|
|
|
|
setValue(scNewComponent, package.data(scNewComponent).toString());
|
|
|
|
setValue(scRequiresAdminRights, package.data(scRequiresAdminRights).toString());
|
|
|
|
|
|
|
|
setValue(scScript, package.data(scScript).toString());
|
|
|
|
setValue(scReplaces, package.data(scReplaces).toString());
|
|
|
|
setValue(scReleaseDate, package.data(scReleaseDate).toString());
|
|
|
|
|
|
|
|
QString forced = package.data(scForcedInstallation, scFalse).toString().toLower();
|
2011-06-14 16:24:50 +02:00
|
|
|
if (PackageManagerCore::noForceInstallation())
|
2011-06-06 17:23:48 +02:00
|
|
|
forced = scFalse;
|
|
|
|
setValue(scForcedInstallation, forced);
|
|
|
|
if (forced == scTrue) {
|
2011-04-12 11:21:20 +02:00
|
|
|
setEnabled(false);
|
|
|
|
setCheckable(false);
|
|
|
|
setCheckState(Qt::Checked);
|
|
|
|
}
|
2011-03-10 18:36:07 +01:00
|
|
|
|
2011-07-05 13:22:05 +02:00
|
|
|
setLocalTempPath(QInstaller::pathFromUrl(package.sourceInfo().url));
|
|
|
|
const QStringList uis = package.data(QLatin1String("UserInterfaces")).toString()
|
2011-03-10 18:36:07 +01:00
|
|
|
.split(QString::fromLatin1(","), QString::SkipEmptyParts);
|
2011-03-17 15:13:11 +01:00
|
|
|
if (!uis.isEmpty())
|
|
|
|
loadUserInterfaces(QDir(QString::fromLatin1("%1/%2").arg(localTempPath(), name())), uis);
|
2011-03-10 18:36:07 +01:00
|
|
|
|
2011-07-05 13:22:05 +02:00
|
|
|
const QStringList qms = package.data(QLatin1String("Translations")).toString()
|
2011-03-10 18:36:07 +01:00
|
|
|
.split(QString::fromLatin1(","), QString::SkipEmptyParts);
|
2011-03-17 15:13:11 +01:00
|
|
|
if (!qms.isEmpty())
|
|
|
|
loadTranslations(QDir(QString::fromLatin1("%1/%2").arg(localTempPath(), name())), qms);
|
2011-03-10 18:36:07 +01:00
|
|
|
|
2011-07-05 13:22:05 +02:00
|
|
|
QHash<QString, QVariant> licenseHash = package.data(QLatin1String("Licenses")).toHash();
|
2011-03-17 15:13:11 +01:00
|
|
|
if (!licenseHash.isEmpty())
|
|
|
|
loadLicenses(QString::fromLatin1("%1/%2/").arg(localTempPath(), name()), licenseHash);
|
2011-03-10 18:36:07 +01:00
|
|
|
}
|
|
|
|
|
2011-04-01 12:07:50 +02:00
|
|
|
QString Component::uncompressedSize() const
|
|
|
|
{
|
2011-06-06 17:23:48 +02:00
|
|
|
double size = value(scUncompressedSize).toDouble();
|
2011-06-29 16:08:10 +02:00
|
|
|
if (size < 1000.0)
|
2011-04-01 12:07:50 +02:00
|
|
|
return tr("%L1 Bytes").arg(size);
|
|
|
|
size /= 1024.0;
|
2011-06-29 16:08:10 +02:00
|
|
|
if (size < 1000.0)
|
|
|
|
return tr("%L1 kBytes").arg(size, 0, 'f', 2);
|
2011-04-01 12:07:50 +02:00
|
|
|
size /= 1024.0;
|
2011-06-29 16:08:10 +02:00
|
|
|
if (size < 1000.0)
|
|
|
|
return tr("%L1 MBytes").arg(size, 0, 'f', 2);
|
2011-04-01 12:07:50 +02:00
|
|
|
size /= 1024.0;
|
2011-06-29 16:08:10 +02:00
|
|
|
return tr("%L1 GBytes").arg(size, 0, 'f', 2);
|
2011-04-01 12:07:50 +02:00
|
|
|
}
|
|
|
|
|
2011-02-21 16:30:31 +01:00
|
|
|
void Component::markAsPerformedInstallation()
|
|
|
|
{
|
|
|
|
d->m_newlyInstalled = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
2011-03-09 12:45:22 +01:00
|
|
|
\property Component::removeBeforeUpdate
|
2011-04-21 10:19:02 +02:00
|
|
|
Specifies whether this component gets removed by the installer system before it gets updated. Get this
|
|
|
|
property's value by using %removeBeforeUpdate(), and set it using %setRemoveBeforeUpdate(). The default
|
|
|
|
value is true.
|
2011-03-09 12:45:22 +01:00
|
|
|
*/
|
2011-02-21 16:30:31 +01:00
|
|
|
bool Component::removeBeforeUpdate() const
|
|
|
|
{
|
2011-04-13 11:06:16 +02:00
|
|
|
return d->m_removeBeforeUpdate;
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
|
|
|
|
2011-03-09 12:45:22 +01:00
|
|
|
void Component::setRemoveBeforeUpdate(bool removeBeforeUpdate)
|
2011-02-21 16:30:31 +01:00
|
|
|
{
|
2011-04-13 11:06:16 +02:00
|
|
|
d->m_removeBeforeUpdate = removeBeforeUpdate;
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
QList<Component*> Component::dependees() const
|
|
|
|
{
|
2011-06-14 16:24:50 +02:00
|
|
|
return d->m_core->dependees(this);
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2011-03-09 12:45:22 +01:00
|
|
|
Returns a key/value based hash of all variables set for this component.
|
|
|
|
*/
|
2011-02-21 16:30:31 +01:00
|
|
|
QHash<QString,QString> Component::variables() const
|
|
|
|
{
|
|
|
|
return d->m_vars;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
2011-03-09 12:45:22 +01:00
|
|
|
Returns the value of variable name \a key.
|
|
|
|
If \a key is not known yet, \a defaultValue is returned.
|
|
|
|
*/
|
|
|
|
QString Component::value(const QString &key, const QString &defaultValue) const
|
2011-02-21 16:30:31 +01:00
|
|
|
{
|
|
|
|
return d->m_vars.value(key, defaultValue);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
2011-03-09 12:45:22 +01:00
|
|
|
Sets the value of the variable with \a key to \a value.
|
2011-02-21 16:30:31 +01:00
|
|
|
*/
|
|
|
|
void Component::setValue(const QString &key, const QString &value)
|
|
|
|
{
|
2011-04-12 09:50:34 +02:00
|
|
|
if (d->m_vars.value(key) == value)
|
2011-02-21 16:30:31 +01:00
|
|
|
return;
|
|
|
|
|
2011-06-09 16:47:41 +02:00
|
|
|
if (key == scName)
|
2011-06-06 12:24:50 +02:00
|
|
|
d->m_componentName = value;
|
2011-06-01 18:18:58 +02:00
|
|
|
|
2011-03-09 12:45:22 +01:00
|
|
|
d->m_vars[key] = value;
|
|
|
|
emit valueChanged(key, value);
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
2011-04-21 10:19:02 +02:00
|
|
|
Returns the installer this component belongs to.
|
2011-02-21 16:30:31 +01:00
|
|
|
*/
|
2011-06-14 16:24:50 +02:00
|
|
|
PackageManagerCore *Component::packageManagerCore() const
|
2011-02-21 16:30:31 +01:00
|
|
|
{
|
2011-06-14 16:24:50 +02:00
|
|
|
return d->m_core;
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
2011-03-09 12:45:22 +01:00
|
|
|
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.
|
|
|
|
*/
|
2011-04-13 11:06:16 +02:00
|
|
|
Component* Component::parentComponent() const
|
2011-02-21 16:30:31 +01:00
|
|
|
{
|
2011-04-13 11:06:16 +02:00
|
|
|
return d->m_parentComponent;
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
Appends \a component as a child of this component. If \a component already has a parent,
|
|
|
|
it is removed from the previous parent.
|
2011-03-09 12:45:22 +01:00
|
|
|
*/
|
|
|
|
void Component::appendComponent(Component* component)
|
2011-02-21 16:30:31 +01:00
|
|
|
{
|
2011-06-06 12:41:02 +02:00
|
|
|
if (!component->isVirtual()) {
|
2011-07-21 20:05:08 +02:00
|
|
|
d->m_childComponents.append(component);
|
|
|
|
std::sort(d->m_childComponents.begin(), d->m_childComponents.end(), Component::SortingPriorityLessThan());
|
2011-04-01 10:20:07 +02:00
|
|
|
} else {
|
2011-07-21 20:05:08 +02:00
|
|
|
d->m_virtualChildComponents.append(component);
|
2011-04-01 10:20:07 +02:00
|
|
|
}
|
|
|
|
|
2011-07-21 20:05:08 +02:00
|
|
|
d->m_allChildComponents = d->m_childComponents + d->m_virtualChildComponents;
|
2011-04-01 10:20:07 +02:00
|
|
|
if (Component *parent = component->parentComponent())
|
|
|
|
parent->removeComponent(component);
|
2011-04-13 11:06:16 +02:00
|
|
|
component->d->m_parentComponent = this;
|
2011-07-21 20:05:08 +02:00
|
|
|
setTristate(d->m_childComponents.count() > 0);
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
|
|
|
|
2011-04-01 10:21:34 +02:00
|
|
|
/*!
|
|
|
|
Removes \a component if it is a child of this component. The component object still exists after the
|
|
|
|
function returns. It's up to the caller to delete the passed component.
|
|
|
|
*/
|
|
|
|
void Component::removeComponent(Component *component)
|
|
|
|
{
|
|
|
|
if (component->parentComponent() == this) {
|
2011-04-13 11:06:16 +02:00
|
|
|
component->d->m_parentComponent = 0;
|
2011-07-21 20:05:08 +02:00
|
|
|
d->m_childComponents.removeAll(component);
|
|
|
|
d->m_virtualChildComponents.removeAll(component);
|
|
|
|
d->m_allChildComponents = d->m_childComponents + d->m_virtualChildComponents;
|
2011-04-01 10:21:34 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-02-21 16:30:31 +01:00
|
|
|
/*!
|
2011-03-09 12:45:22 +01:00
|
|
|
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.
|
|
|
|
*/
|
2011-04-12 10:10:52 +02:00
|
|
|
QList<Component*> Component::childComponents(bool recursive, RunMode runMode) const
|
2011-03-09 12:45:22 +01:00
|
|
|
{
|
2011-04-13 11:30:05 +02:00
|
|
|
QList<Component*> result;
|
2011-03-09 12:45:22 +01:00
|
|
|
if (runMode == UpdaterMode)
|
2011-04-13 11:30:05 +02:00
|
|
|
return result;
|
2011-03-09 12:45:22 +01:00
|
|
|
|
|
|
|
if (!recursive)
|
2011-07-21 20:05:08 +02:00
|
|
|
return d->m_allChildComponents;
|
2011-02-21 16:30:31 +01:00
|
|
|
|
2011-07-21 20:05:08 +02:00
|
|
|
foreach (Component *component, d->m_allChildComponents) {
|
2011-03-09 12:45:22 +01:00
|
|
|
result.append(component);
|
2011-04-13 11:30:05 +02:00
|
|
|
result += component->childComponents(true, runMode);
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
2011-03-09 12:45:22 +01:00
|
|
|
Contains this component's name (unique identifier).
|
|
|
|
*/
|
2011-02-21 16:30:31 +01:00
|
|
|
QString Component::name() const
|
|
|
|
{
|
2011-06-06 14:21:12 +02:00
|
|
|
return d->m_componentName;
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
2011-03-09 12:45:22 +01:00
|
|
|
Contains this component's display name (as visible to the user).
|
|
|
|
*/
|
2011-02-21 16:30:31 +01:00
|
|
|
QString Component::displayName() const
|
|
|
|
{
|
2011-06-06 17:23:48 +02:00
|
|
|
return value(scDisplayName);
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
|
|
|
|
2011-03-15 18:17:20 +01:00
|
|
|
void Component::loadComponentScript()
|
|
|
|
{
|
2011-06-06 17:23:48 +02:00
|
|
|
const QString script = value(scScript);
|
2011-03-17 15:13:11 +01:00
|
|
|
if (!localTempPath().isEmpty() && !script.isEmpty())
|
|
|
|
loadComponentScript(QString::fromLatin1("%1/%2/%3").arg(localTempPath(), name(), script));
|
2011-03-15 18:17:20 +01:00
|
|
|
}
|
|
|
|
|
2011-02-21 16:30:31 +01:00
|
|
|
/*!
|
2011-03-09 12:45:22 +01:00
|
|
|
Loads the script at \a fileName into this component's script engine. 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.
|
|
|
|
*/
|
|
|
|
void Component::loadComponentScript(const QString &fileName)
|
|
|
|
{
|
|
|
|
QFile file(fileName);
|
|
|
|
if (!file.open(QIODevice::ReadOnly)) {
|
2011-06-29 13:21:08 +02:00
|
|
|
throw Error(tr("Could not open the requested script file at %1: %2").arg(fileName, file.errorString()));
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
|
|
|
|
2011-04-13 11:06:16 +02:00
|
|
|
d->m_scriptEngine.evaluate(QLatin1String(file.readAll()), fileName);
|
|
|
|
if (d->m_scriptEngine.hasUncaughtException()) {
|
2011-06-29 13:21:08 +02:00
|
|
|
throw Error(tr("Exception while loading the component script %1")
|
2011-04-13 11:06:16 +02:00
|
|
|
.arg(uncaughtExceptionString(&(d->m_scriptEngine)/*, QFileInfo(file).absoluteFilePath()*/)));
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
|
|
|
|
2011-07-21 21:26:29 +02:00
|
|
|
const QList<Component*> components = d->m_core->availableComponents();
|
2011-04-13 11:06:16 +02:00
|
|
|
QScriptValue comps = d->m_scriptEngine.newArray(components.count());
|
2011-03-09 12:45:22 +01:00
|
|
|
for (int i = 0; i < components.count(); ++i)
|
2011-04-13 11:06:16 +02:00
|
|
|
comps.setProperty(i, d->m_scriptEngine.newQObject(components[i]));
|
2011-03-09 12:45:22 +01:00
|
|
|
|
2011-04-13 11:06:16 +02:00
|
|
|
d->m_scriptEngine.globalObject().property(QLatin1String("installer"))
|
2011-03-09 12:45:22 +01:00
|
|
|
.setProperty(QLatin1String("components"), comps);
|
|
|
|
|
2011-04-13 11:06:16 +02:00
|
|
|
QScriptValue comp = d->m_scriptEngine.evaluate(QLatin1String("Component"));
|
|
|
|
if (!d->m_scriptEngine.hasUncaughtException()) {
|
|
|
|
d->m_scriptComponent = comp;
|
|
|
|
d->m_scriptComponent.construct();
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
emit loaded();
|
|
|
|
languageChanged();
|
2011-07-21 20:30:23 +02:00
|
|
|
|
|
|
|
//Solves a freeze seen on updater/ package manger restart.
|
2011-07-12 13:52:38 +02:00
|
|
|
QCoreApplication::processEvents();
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
2011-03-09 12:45:22 +01:00
|
|
|
\internal
|
|
|
|
Calls the script method \link retranslateUi() \endlink, if any. This is done whenever a
|
|
|
|
QTranslator file is being loaded.
|
|
|
|
*/
|
2011-02-21 16:30:31 +01:00
|
|
|
void Component::languageChanged()
|
|
|
|
{
|
2011-03-09 12:45:22 +01:00
|
|
|
callScriptMethod(QLatin1String("retranslateUi"));
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
2011-03-09 12:45:22 +01:00
|
|
|
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.
|
|
|
|
*/
|
2011-06-01 18:18:58 +02:00
|
|
|
QScriptValue Component::callScriptMethod(const QString &methodName, const QScriptValueList& arguments) const
|
2011-03-09 12:45:22 +01:00
|
|
|
{
|
2011-04-13 11:06:16 +02:00
|
|
|
if (!d->m_unexistingScriptMethods.value(methodName, true))
|
2011-02-21 16:30:31 +01:00
|
|
|
return QScriptValue();
|
|
|
|
|
|
|
|
// don't allow such a recursion
|
2011-04-13 11:06:16 +02:00
|
|
|
if (d->m_scriptEngine.currentContext()->backtrace().first().startsWith(methodName))
|
2011-02-21 16:30:31 +01:00
|
|
|
return QScriptValue();
|
|
|
|
|
2011-04-13 11:06:16 +02:00
|
|
|
QScriptValue method = d->m_scriptComponent.property(QString::fromLatin1("prototype"))
|
2011-03-09 12:45:22 +01:00
|
|
|
.property(methodName);
|
|
|
|
if (!method.isValid()) // this marks the method to be called not any longer
|
2011-04-13 11:06:16 +02:00
|
|
|
d->m_unexistingScriptMethods[methodName] = false;
|
2011-02-21 16:30:31 +01:00
|
|
|
|
2011-04-13 11:06:16 +02:00
|
|
|
const QScriptValue result = method.call(d->m_scriptComponent, arguments);
|
2011-03-09 12:45:22 +01:00
|
|
|
if (!result.isValid())
|
2011-02-21 16:30:31 +01:00
|
|
|
return result;
|
|
|
|
|
2011-04-13 11:06:16 +02:00
|
|
|
if (d->m_scriptEngine.hasUncaughtException())
|
|
|
|
throw Error(uncaughtExceptionString(&(d->m_scriptEngine)/*, name()*/));
|
2011-02-21 16:30:31 +01:00
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
2011-03-09 12:45:22 +01:00
|
|
|
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.
|
|
|
|
*/
|
|
|
|
void Component::loadTranslations(const QDir& directory, const QStringList& qms)
|
|
|
|
{
|
|
|
|
QDirIterator it(directory.path(), qms, QDir::Files);
|
|
|
|
while (it.hasNext()) {
|
2011-02-21 16:30:31 +01:00
|
|
|
const QString filename = it.next();
|
2011-03-09 12:45:22 +01:00
|
|
|
if (QFileInfo(filename).baseName().toLower() != QLocale().name().toLower())
|
2011-02-21 16:30:31 +01:00
|
|
|
continue;
|
|
|
|
|
2011-03-09 12:45:22 +01:00
|
|
|
QScopedPointer<QTranslator> translator(new QTranslator(this));
|
|
|
|
if (!translator->load(filename))
|
|
|
|
throw Error(tr("Could not open the requested translation file at %1").arg(filename));
|
|
|
|
qApp->installTranslator(translator.take());
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
2011-03-09 12:45:22 +01:00
|
|
|
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.
|
|
|
|
*/
|
|
|
|
void Component::loadUserInterfaces(const QDir& directory, const QStringList& uis)
|
2011-02-21 16:30:31 +01:00
|
|
|
{
|
2011-03-09 12:45:22 +01:00
|
|
|
if (QApplication::type() == QApplication::Tty)
|
2011-02-21 16:30:31 +01:00
|
|
|
return;
|
|
|
|
|
2011-03-09 12:45:22 +01:00
|
|
|
QDirIterator it(directory.path(), uis, QDir::Files);
|
|
|
|
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(),
|
|
|
|
file.errorString()));
|
|
|
|
}
|
2011-02-21 16:30:31 +01:00
|
|
|
|
|
|
|
static QUiLoader loader;
|
2011-03-09 12:45:22 +01:00
|
|
|
loader.setTranslationEnabled(true);
|
|
|
|
loader.setLanguageChangeEnabled(true);
|
2011-05-04 10:06:05 +02:00
|
|
|
QWidget* const w = loader.load(&file, MessageBoxHandler::currentBestSuitParent());
|
2011-04-13 11:06:16 +02:00
|
|
|
d->m_userInterfaces.insert(w->objectName(), w);
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Component::loadLicenses(const QString &directory, const QHash<QString, QVariant> &licenseHash)
|
|
|
|
{
|
|
|
|
QHash<QString, QVariant>::const_iterator it;
|
|
|
|
for (it = licenseHash.begin(); it != licenseHash.end(); ++it) {
|
|
|
|
const QString &fileName = it.value().toString();
|
|
|
|
QFile file(directory + fileName);
|
2011-03-09 12:45:22 +01:00
|
|
|
if (!file.open(QIODevice::ReadOnly)) {
|
|
|
|
throw Error(tr("Could not open the requested license file at %1: %2").arg(fileName,
|
2011-02-21 16:30:31 +01:00
|
|
|
file.errorString()));
|
|
|
|
}
|
|
|
|
d->m_licenses.insert(it.key(), qMakePair(fileName, QTextStream(&file).readAll()));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
2011-03-09 12:45:22 +01:00
|
|
|
Contains a list of all user interface class names known to this component.
|
|
|
|
*/
|
2011-02-21 16:30:31 +01:00
|
|
|
QStringList Component::userInterfaces() const
|
|
|
|
{
|
2011-04-13 11:06:16 +02:00
|
|
|
return d->m_userInterfaces.keys();
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
QHash<QString, QPair<QString, QString> > Component::licenses() const
|
|
|
|
{
|
|
|
|
return d->m_licenses;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
2011-03-09 12:45:22 +01:00
|
|
|
Returns the QWidget created for class \a name.
|
|
|
|
*/
|
|
|
|
QWidget* Component::userInterface(const QString &name) const
|
2011-02-21 16:30:31 +01:00
|
|
|
{
|
2011-04-13 11:06:16 +02:00
|
|
|
return d->m_userInterfaces.value(name);
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
2011-03-09 12:45:22 +01:00
|
|
|
Creates all operations needed to install this component's \a path. \a path is a full qualified
|
2011-04-21 10:19:02 +02:00
|
|
|
filename including the component's name. This methods gets called from
|
2011-03-09 12:45:22 +01:00
|
|
|
Component::createOperationsForArchive. You can override this method by providing a method with
|
|
|
|
the same name in the component script.
|
|
|
|
|
|
|
|
\note RSA signature files are omitted by this method.
|
|
|
|
\note If you call this method from a script, it won't call the scripts method with the same name.
|
2011-02-21 16:30:31 +01:00
|
|
|
|
2011-04-21 10:19:02 +02:00
|
|
|
The default implementation is recursively creating Copy and Mkdir operations for all files
|
2011-03-09 12:45:22 +01:00
|
|
|
and folders within \a path.
|
|
|
|
*/
|
|
|
|
void Component::createOperationsForPath(const QString &path)
|
2011-02-21 16:30:31 +01:00
|
|
|
{
|
2011-03-09 12:45:22 +01:00
|
|
|
const QFileInfo fi(path);
|
2011-02-21 16:30:31 +01:00
|
|
|
|
|
|
|
// don't copy over a signature
|
2011-03-09 12:45:22 +01:00
|
|
|
if (fi.suffix() == QLatin1String("sig") && QFileInfo(fi.dir(), fi.completeBaseName()).exists())
|
2011-02-21 16:30:31 +01:00
|
|
|
return;
|
|
|
|
|
|
|
|
// the script can override this method
|
2011-03-09 12:45:22 +01:00
|
|
|
if (callScriptMethod(QLatin1String("createOperationsForPath"), QScriptValueList() << path).isValid())
|
2011-02-21 16:30:31 +01:00
|
|
|
return;
|
|
|
|
|
|
|
|
QString target;
|
2011-03-09 12:45:22 +01:00
|
|
|
static const QString zipPrefix = QString::fromLatin1("7z://installer://");
|
|
|
|
// if the path is an archive, remove the archive file name from the target path
|
|
|
|
if (path.startsWith(zipPrefix)) {
|
|
|
|
target = path.mid(zipPrefix.length() + name().length() + 1); // + 1 for the /
|
|
|
|
const int nextSlash = target.indexOf(QLatin1Char('/'));
|
|
|
|
if (nextSlash != -1)
|
|
|
|
target = target.mid(nextSlash);
|
2011-02-21 16:30:31 +01:00
|
|
|
else
|
|
|
|
target.clear();
|
|
|
|
target.prepend(QLatin1String("@TargetDir@"));
|
2011-03-09 12:45:22 +01:00
|
|
|
} else {
|
|
|
|
static const QString prefix = QString::fromLatin1("installer://");
|
|
|
|
target = QString::fromLatin1("@TargetDir@%1").arg(path.mid(prefix.length() + name().length()));
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
2011-03-09 12:45:22 +01:00
|
|
|
|
|
|
|
if (fi.isFile()) {
|
|
|
|
static const QString copy = QString::fromLatin1("Copy");
|
|
|
|
addOperation(copy, fi.filePath(), target);
|
|
|
|
} else if (fi.isDir()) {
|
2011-02-21 16:30:31 +01:00
|
|
|
qApp->processEvents();
|
2011-03-09 12:45:22 +01:00
|
|
|
static const QString mkdir = QString::fromLatin1("Mkdir");
|
|
|
|
addOperation(mkdir, target);
|
2011-02-21 16:30:31 +01:00
|
|
|
|
2011-03-09 12:45:22 +01:00
|
|
|
QDirIterator it(fi.filePath());
|
|
|
|
while (it.hasNext())
|
|
|
|
createOperationsForPath(it.next());
|
|
|
|
}
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
2011-03-09 12:45:22 +01:00
|
|
|
Creates all operations needed to install this component's \a archive. This metods gets called
|
|
|
|
from Component::createOperations. You can override this method by providing a method with the
|
|
|
|
same name in the component script.
|
|
|
|
|
|
|
|
\note If you call this method from a script, it won't call the scripts method with the same name.
|
|
|
|
|
|
|
|
The default implementation calls createOperationsForPath for everything contained in the archive.
|
|
|
|
If \a archive is a compressed archive known to the installer system, an Extract operation is
|
|
|
|
created, instead.
|
|
|
|
*/
|
|
|
|
void Component::createOperationsForArchive(const QString &archive)
|
2011-02-21 16:30:31 +01:00
|
|
|
{
|
|
|
|
// the script can override this method
|
2011-03-09 12:45:22 +01:00
|
|
|
if (callScriptMethod(QLatin1String("createOperationsForArchive"), QScriptValueList() << archive).isValid())
|
2011-02-21 16:30:31 +01:00
|
|
|
return;
|
|
|
|
|
2011-03-09 12:45:22 +01:00
|
|
|
const QFileInfo fi(QString::fromLatin1("installer://%1/%2").arg(name(), archive));
|
|
|
|
const bool isZip = Lib7z::isSupportedArchive(fi.filePath());
|
2011-02-21 16:30:31 +01:00
|
|
|
|
2011-03-09 12:45:22 +01:00
|
|
|
if (isZip) {
|
2011-02-21 16:30:31 +01:00
|
|
|
// archives get completely extracted per default (if the script isn't doing other stuff)
|
2011-03-09 12:45:22 +01:00
|
|
|
addOperation(QLatin1String("Extract"), fi.filePath(), QLatin1String("@TargetDir@"));
|
|
|
|
} else {
|
|
|
|
createOperationsForPath(fi.filePath());
|
|
|
|
}
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
2011-03-09 12:45:22 +01:00
|
|
|
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.
|
|
|
|
|
|
|
|
\note If you call this method from a script, it won't call the scripts method with the same name.
|
|
|
|
|
|
|
|
The default implementation calls createOperationsForArchive for all archives in this component.
|
2011-02-21 16:30:31 +01:00
|
|
|
*/
|
|
|
|
void Component::createOperations()
|
|
|
|
{
|
|
|
|
// the script can override this method
|
2011-03-09 12:45:22 +01:00
|
|
|
if (callScriptMethod(QLatin1String("createOperations")).isValid()) {
|
2011-04-13 11:06:16 +02:00
|
|
|
d->m_operationsCreated = true;
|
2011-02-21 16:30:31 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-03-09 12:45:22 +01:00
|
|
|
foreach (const QString &archive, archives())
|
|
|
|
createOperationsForArchive(archive);
|
2011-02-21 16:30:31 +01:00
|
|
|
|
2011-04-13 11:06:16 +02:00
|
|
|
d->m_operationsCreated = true;
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
2011-03-09 12:45:22 +01:00
|
|
|
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
|
|
|
|
also be deleted if it contains changes done by the user after installation.
|
2011-02-21 16:30:31 +01:00
|
|
|
*/
|
2011-03-09 12:45:22 +01:00
|
|
|
void Component::registerPathForUninstallation(const QString &path, bool wipe)
|
2011-02-21 16:30:31 +01:00
|
|
|
{
|
2011-04-13 11:06:16 +02:00
|
|
|
d->m_pathesForUninstallation.append(qMakePair(path, wipe));
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
2011-04-21 10:19:02 +02:00
|
|
|
Returns the list of paths previously registered for uninstallation with
|
2011-03-09 12:45:22 +01:00
|
|
|
#registerPathForUninstallation.
|
2011-02-21 16:30:31 +01:00
|
|
|
*/
|
2011-03-09 12:45:22 +01:00
|
|
|
QList<QPair<QString, bool> > Component::pathesForUninstallation() const
|
2011-02-21 16:30:31 +01:00
|
|
|
{
|
2011-04-13 11:06:16 +02:00
|
|
|
return d->m_pathesForUninstallation;
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
2011-03-09 12:45:22 +01:00
|
|
|
Contains the names of all archives known to this component. This does not contain archives added
|
|
|
|
with #addDownloadableArchive.
|
|
|
|
*/
|
2011-02-21 16:30:31 +01:00
|
|
|
QStringList Component::archives() const
|
|
|
|
{
|
2011-03-09 12:45:22 +01:00
|
|
|
return QDir(QString::fromLatin1("installer://%1/").arg(name())).entryList();
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
2011-03-09 12:45:22 +01:00
|
|
|
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
|
|
|
|
*/
|
|
|
|
void Component::addDownloadableArchive(const QString &path)
|
|
|
|
{
|
|
|
|
Q_ASSERT(isFromOnlineRepository());
|
|
|
|
|
2011-06-06 17:23:48 +02:00
|
|
|
const QString versionPrefix = value(scVersion);
|
2011-02-21 16:30:31 +01:00
|
|
|
verbose() << "addDownloadable " << path << std::endl;
|
2011-04-13 11:06:16 +02:00
|
|
|
d->m_downloadableArchives.append(versionPrefix + path);
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
2011-03-09 12:45:22 +01:00
|
|
|
|
2011-02-21 16:30:31 +01:00
|
|
|
/*!
|
2011-03-09 12:45:22 +01:00
|
|
|
Removes the archive \a path previously added via addDownloadableArchive from this component.
|
|
|
|
This can oly be called when this component was downloaded from an online repository.
|
|
|
|
|
|
|
|
Read \ref sec_repogen for details.
|
|
|
|
*/
|
|
|
|
void Component::removeDownloadableArchive(const QString &path)
|
2011-02-21 16:30:31 +01:00
|
|
|
{
|
2011-03-09 12:45:22 +01:00
|
|
|
Q_ASSERT(isFromOnlineRepository());
|
2011-04-13 11:06:16 +02:00
|
|
|
d->m_downloadableArchives.removeAll(path);
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
2011-03-09 12:45:22 +01:00
|
|
|
Returns the archives to be downloaded from the online repository before installation.
|
|
|
|
*/
|
2011-02-21 16:30:31 +01:00
|
|
|
QStringList Component::downloadableArchives() const
|
|
|
|
{
|
2011-04-13 11:06:16 +02:00
|
|
|
return d->m_downloadableArchives;
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
2011-03-09 12:45:22 +01:00
|
|
|
Adds a request for quitting the process @p process before installing/updating/uninstalling the
|
|
|
|
component.
|
|
|
|
*/
|
|
|
|
void Component::addStopProcessForUpdateRequest(const QString &process)
|
2011-02-21 16:30:31 +01:00
|
|
|
{
|
2011-04-13 11:06:16 +02:00
|
|
|
d->m_stopProcessForUpdateRequests.append(process);
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
2011-03-09 12:45:22 +01:00
|
|
|
Removes the request for quitting the process @p process again.
|
2011-02-21 16:30:31 +01:00
|
|
|
*/
|
2011-03-09 12:45:22 +01:00
|
|
|
void Component::removeStopProcessForUpdateRequest(const QString &process)
|
2011-02-21 16:30:31 +01:00
|
|
|
{
|
2011-04-13 11:06:16 +02:00
|
|
|
d->m_stopProcessForUpdateRequests.removeAll(process);
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
2011-03-09 12:45:22 +01:00
|
|
|
Convenience: Add/remove request depending on @p requested (add if @p true, remove if @p false).
|
2011-02-21 16:30:31 +01:00
|
|
|
*/
|
2011-03-09 12:45:22 +01:00
|
|
|
void Component::setStopProcessForUpdateRequest(const QString &process, bool requested)
|
2011-02-21 16:30:31 +01:00
|
|
|
{
|
2011-03-09 12:45:22 +01:00
|
|
|
if (requested)
|
|
|
|
addStopProcessForUpdateRequest(process);
|
2011-02-21 16:30:31 +01:00
|
|
|
else
|
2011-03-09 12:45:22 +01:00
|
|
|
removeStopProcessForUpdateRequest(process);
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
2011-03-09 12:45:22 +01:00
|
|
|
The list of processes this component needs to be closed before installing/updating/uninstalling
|
|
|
|
*/
|
2011-02-21 16:30:31 +01:00
|
|
|
QStringList Component::stopProcessForUpdateRequests() const
|
|
|
|
{
|
2011-04-13 11:06:16 +02:00
|
|
|
return d->m_stopProcessForUpdateRequests;
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
2011-03-09 12:45:22 +01:00
|
|
|
Returns the operations needed to install this component. If autoCreateOperations is true,
|
|
|
|
createOperations is called, if no operations have been auto-created yet.
|
|
|
|
*/
|
2011-07-05 10:02:02 +02:00
|
|
|
OperationList Component::operations() const
|
2011-02-21 16:30:31 +01:00
|
|
|
{
|
2011-04-13 11:06:16 +02:00
|
|
|
if (d->m_autoCreateOperations && !d->m_operationsCreated) {
|
2011-03-09 12:45:22 +01:00
|
|
|
const_cast<Component*>(this)->createOperations();
|
2011-02-21 16:30:31 +01:00
|
|
|
|
2011-04-13 11:06:16 +02:00
|
|
|
if (!d->m_minimumProgressOperation) {
|
|
|
|
d->m_minimumProgressOperation = KDUpdater::UpdateOperationFactory::instance()
|
2011-02-21 16:30:31 +01:00
|
|
|
.create(QLatin1String("MinimumProgress"));
|
2011-04-13 11:06:16 +02:00
|
|
|
d->m_operations.append(d->m_minimumProgressOperation);
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!d->m_licenses.isEmpty()) {
|
|
|
|
d->m_licenseOperation = KDUpdater::UpdateOperationFactory::instance()
|
|
|
|
.create(QLatin1String("License"));
|
2011-06-14 16:24:50 +02:00
|
|
|
d->m_licenseOperation->setValue(QLatin1String("installer"), QVariant::fromValue(d->m_core));
|
2011-02-21 16:30:31 +01:00
|
|
|
|
|
|
|
QVariantMap licenses;
|
|
|
|
const QList<QPair<QString, QString> > values = d->m_licenses.values();
|
|
|
|
for (int i = 0; i < values.count(); ++i)
|
|
|
|
licenses.insert(values.at(i).first, values.at(i).second);
|
|
|
|
d->m_licenseOperation->setValue(QLatin1String("licenses"), licenses);
|
2011-04-13 11:06:16 +02:00
|
|
|
d->m_operations.append(d->m_licenseOperation);
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
|
|
|
}
|
2011-04-13 11:06:16 +02:00
|
|
|
return d->m_operations;
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
2011-03-09 12:45:22 +01:00
|
|
|
Adds \a operation to the list of operations needed to install this component.
|
|
|
|
*/
|
2011-07-04 23:40:17 +02:00
|
|
|
void Component::addOperation(Operation *operation)
|
2011-02-21 16:30:31 +01:00
|
|
|
{
|
2011-04-13 11:06:16 +02:00
|
|
|
d->m_operations.append(operation);
|
2011-06-15 15:29:31 +02:00
|
|
|
if (FSEngineClientHandler::instance().isActive())
|
2011-03-09 12:45:22 +01:00
|
|
|
operation->setValue(QLatin1String("admin"), true);
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
2011-03-09 12:45:22 +01:00
|
|
|
Adds \a operation to the list of operations needed to install this component. \a operation
|
|
|
|
is executed with elevated rights.
|
|
|
|
*/
|
2011-07-04 23:40:17 +02:00
|
|
|
void Component::addElevatedOperation(Operation *operation)
|
2011-02-21 16:30:31 +01:00
|
|
|
{
|
2011-03-09 12:45:22 +01:00
|
|
|
addOperation(operation);
|
|
|
|
operation->setValue(QLatin1String("admin"), true);
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
bool Component::operationsCreatedSuccessfully() const
|
|
|
|
{
|
2011-04-13 11:06:16 +02:00
|
|
|
return d->m_operationsCreatedSuccessfully;
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
|
|
|
|
2011-07-04 23:40:17 +02:00
|
|
|
Operation* Component::createOperation(const QString &operation, const QString ¶meter1,
|
|
|
|
const QString ¶meter2, const QString ¶meter3, const QString ¶meter4, const QString ¶meter5,
|
|
|
|
const QString ¶meter6, const QString ¶meter7, const QString ¶meter8, const QString ¶meter9,
|
2011-03-09 12:45:22 +01:00
|
|
|
const QString ¶meter10)
|
|
|
|
{
|
2011-07-04 23:40:17 +02:00
|
|
|
Operation* op = KDUpdater::UpdateOperationFactory::instance().create(operation);
|
2011-03-09 12:45:22 +01:00
|
|
|
if (op == 0) {
|
|
|
|
const QMessageBox::StandardButton button =
|
|
|
|
MessageBoxHandler::critical(MessageBoxHandler::currentBestSuitParent(),
|
2011-07-04 23:40:17 +02:00
|
|
|
QLatin1String("OperationDoesNotExistError"), tr("Error"), tr("Error: Operation %1 does not exist")
|
|
|
|
.arg(operation), QMessageBox::Abort | QMessageBox::Ignore);
|
2011-03-09 12:45:22 +01:00
|
|
|
if (button == QMessageBox::Abort)
|
2011-04-13 11:06:16 +02:00
|
|
|
d->m_operationsCreatedSuccessfully = false;
|
2011-03-09 12:45:22 +01:00
|
|
|
return op;
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
2011-03-09 12:45:22 +01:00
|
|
|
|
|
|
|
if (op->name() == QLatin1String("Delete"))
|
|
|
|
op->setValue(QLatin1String("performUndo"), false);
|
2011-06-14 16:24:50 +02:00
|
|
|
op->setValue(QLatin1String("installer"), qVariantFromValue(d->m_core));
|
2011-03-09 12:45:22 +01:00
|
|
|
|
2011-02-21 16:30:31 +01:00
|
|
|
QStringList arguments;
|
2011-03-09 12:45:22 +01:00
|
|
|
if (!parameter1.isNull())
|
|
|
|
arguments.append(parameter1);
|
|
|
|
if (!parameter2.isNull())
|
|
|
|
arguments.append(parameter2);
|
|
|
|
if (!parameter3.isNull())
|
|
|
|
arguments.append(parameter3);
|
|
|
|
if (!parameter4.isNull())
|
|
|
|
arguments.append(parameter4);
|
|
|
|
if (!parameter5.isNull())
|
|
|
|
arguments.append(parameter5);
|
|
|
|
if (!parameter6.isNull())
|
|
|
|
arguments.append(parameter6);
|
|
|
|
if (!parameter7.isNull())
|
|
|
|
arguments.append(parameter7);
|
|
|
|
if (!parameter8.isNull())
|
|
|
|
arguments.append(parameter8);
|
|
|
|
if (!parameter9.isNull())
|
|
|
|
arguments.append(parameter9);
|
|
|
|
if (!parameter10.isNull())
|
|
|
|
arguments.append(parameter10);
|
2011-06-14 16:24:50 +02:00
|
|
|
op->setArguments(d->m_core->replaceVariables(arguments));
|
2011-03-09 12:45:22 +01:00
|
|
|
|
|
|
|
return op;
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
|
|
|
/*!
|
2011-03-09 12:45:22 +01:00
|
|
|
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
|
|
|
|
*/
|
2011-07-04 23:40:17 +02:00
|
|
|
bool Component::addOperation(const QString &operation, const QString ¶meter1, const QString ¶meter2,
|
|
|
|
const QString ¶meter3, const QString ¶meter4, const QString ¶meter5, const QString ¶meter6,
|
|
|
|
const QString ¶meter7, const QString ¶meter8, const QString ¶meter9, const QString ¶meter10)
|
2011-03-09 12:45:22 +01:00
|
|
|
{
|
2011-07-04 23:40:17 +02:00
|
|
|
if (Operation *op = createOperation(operation, parameter1, parameter2, parameter3, parameter4, parameter5,
|
|
|
|
parameter6, parameter7, parameter8, parameter9, parameter10)) {
|
2011-03-09 12:45:22 +01:00
|
|
|
addOperation(op);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
|
|
|
|
2011-03-09 12:45:22 +01:00
|
|
|
/*!
|
|
|
|
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
|
|
|
|
*/
|
2011-06-14 16:24:50 +02:00
|
|
|
bool Component::addElevatedOperation(const QString &operation, const QString ¶meter1,
|
|
|
|
const QString ¶meter2, const QString ¶meter3, const QString ¶meter4, const QString ¶meter5,
|
|
|
|
const QString ¶meter6, const QString ¶meter7, const QString ¶meter8, const QString ¶meter9,
|
|
|
|
const QString ¶meter10)
|
2011-03-09 12:45:22 +01:00
|
|
|
{
|
2011-07-04 23:40:17 +02:00
|
|
|
if (Operation *op = createOperation(operation, parameter1, parameter2, parameter3, parameter4, parameter5,
|
|
|
|
parameter6, parameter7, parameter8, parameter9, parameter10)) {
|
2011-03-09 12:45:22 +01:00
|
|
|
addElevatedOperation(op);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
2011-02-21 16:30:31 +01:00
|
|
|
|
|
|
|
/*!
|
2011-04-21 10:19:02 +02:00
|
|
|
Specifies whether operations should be automatically created when the installation starts. This
|
2011-03-09 12:45:22 +01:00
|
|
|
would be done by calling #createOperations. If you set this to false, it's completely up to the
|
|
|
|
component's script to create all operations.
|
|
|
|
*/
|
2011-02-21 16:30:31 +01:00
|
|
|
bool Component::autoCreateOperations() const
|
|
|
|
{
|
2011-04-13 11:06:16 +02:00
|
|
|
return d->m_autoCreateOperations;
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
|
|
|
|
2011-03-09 12:45:22 +01:00
|
|
|
void Component::setAutoCreateOperations(bool autoCreateOperations)
|
2011-02-21 16:30:31 +01:00
|
|
|
{
|
2011-04-13 11:06:16 +02:00
|
|
|
d->m_autoCreateOperations = autoCreateOperations;
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
|
|
|
|
2011-06-06 12:41:02 +02:00
|
|
|
bool Component::isVirtual() const
|
|
|
|
{
|
2011-06-09 15:57:31 +02:00
|
|
|
return value(scVirtual, scFalse).toLower() == scTrue;
|
2011-06-06 12:41:02 +02:00
|
|
|
}
|
|
|
|
|
2011-02-21 16:30:31 +01:00
|
|
|
/*!
|
2011-03-09 12:45:22 +01:00
|
|
|
\property Component::selected
|
2011-04-21 10:19:02 +02:00
|
|
|
Specifies whether this component is selected for installation. Get this property's value by using
|
2011-03-09 12:45:22 +01:00
|
|
|
%isSelected(), and set it using %setSelected().
|
|
|
|
*/
|
2011-04-12 12:04:55 +02:00
|
|
|
bool Component::isSelected() const
|
2011-03-09 12:45:22 +01:00
|
|
|
{
|
2011-04-05 17:53:34 +02:00
|
|
|
return checkState() != Qt::Unchecked;
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
|
|
|
|
2011-06-07 12:39:52 +02:00
|
|
|
bool Component::forcedInstallation() const
|
|
|
|
{
|
2011-06-09 15:57:31 +02:00
|
|
|
return value(scForcedInstallation, scFalse).toLower() == scTrue;
|
2011-06-07 12:39:52 +02:00
|
|
|
}
|
|
|
|
|
2011-03-09 12:45:22 +01:00
|
|
|
/*!
|
2011-04-12 12:04:55 +02:00
|
|
|
Marks the component for installation. Emits the selectedChanged() signal if the check state changes.
|
2011-03-09 12:45:22 +01:00
|
|
|
*/
|
2011-04-12 12:04:55 +02:00
|
|
|
void Component::setSelected(bool selected)
|
2011-02-21 16:30:31 +01:00
|
|
|
{
|
2011-06-06 12:24:50 +02:00
|
|
|
Q_UNUSED(selected)
|
|
|
|
verbose() << Q_FUNC_INFO << qPrintable(QString(QLatin1String("on \"%1\" is deprecated!!!")).arg(
|
|
|
|
d->m_componentName)) << std::endl;
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
2011-03-09 12:45:22 +01:00
|
|
|
Contains this component dependencies.
|
|
|
|
Read \ref componentdependencies for details.
|
|
|
|
*/
|
2011-02-21 16:30:31 +01:00
|
|
|
QStringList Component::dependencies() const
|
|
|
|
{
|
2011-07-22 14:35:19 +02:00
|
|
|
return value(scDependencies).split(QLatin1Char(','), QString::SkipEmptyParts);
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
2011-04-12 15:32:46 +02:00
|
|
|
Set's the components state to installed.
|
|
|
|
*/
|
|
|
|
void Component::setInstalled()
|
|
|
|
{
|
2011-06-06 17:23:48 +02:00
|
|
|
setValue(scCurrentState, scInstalled);
|
2011-04-12 15:32:46 +02:00
|
|
|
}
|
|
|
|
|
2011-07-22 14:35:19 +02:00
|
|
|
/*!
|
|
|
|
Determines if the component comes as an auto dependency.
|
|
|
|
*/
|
|
|
|
bool Component::isAutoDependOn() const
|
|
|
|
{
|
|
|
|
// the script can override this method
|
|
|
|
if (value(scAutoDependOn).compare(QLatin1String("script"), Qt::CaseInsensitive) == 0) {
|
|
|
|
const QScriptValue valueFromScript = callScriptMethod(QLatin1String("isAutoDependOn"));
|
|
|
|
if (valueFromScript.isValid()) {
|
|
|
|
return valueFromScript.toBool();
|
|
|
|
}
|
|
|
|
verbose() << "value from script is not valid " << std::endl;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
QStringList autoDependOnDependencyList = value(scAutoDependOn).split(QLatin1Char(','),
|
|
|
|
QString::SkipEmptyParts);
|
|
|
|
if (autoDependOnDependencyList.isEmpty())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
QList<Component*> components = d->m_core->componentsToInstall(AllMode);
|
|
|
|
foreach (Component *component, components) {
|
|
|
|
if (autoDependOnDependencyList.contains(component->name())) {
|
|
|
|
autoDependOnDependencyList.removeAll(component->name());
|
|
|
|
//found all "when" components
|
|
|
|
if (autoDependOnDependencyList.isEmpty())
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2011-06-01 18:18:58 +02:00
|
|
|
/*!
|
|
|
|
Determines if the component is a default one.
|
|
|
|
*/
|
|
|
|
bool Component::isDefault() const
|
|
|
|
{
|
|
|
|
// the script can override this method
|
2011-06-06 17:23:48 +02:00
|
|
|
if (value(scDefault).compare(QLatin1String("script"), Qt::CaseInsensitive) == 0) {
|
2011-06-01 18:18:58 +02:00
|
|
|
const QScriptValue valueFromScript = callScriptMethod(QLatin1String("isDefault"));
|
|
|
|
if (valueFromScript.isValid()) {
|
|
|
|
return valueFromScript.toBool();
|
|
|
|
}
|
|
|
|
verbose() << "value from script is not valid " << std::endl;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2011-06-09 16:47:41 +02:00
|
|
|
return value(scDefault).compare(scTrue, Qt::CaseInsensitive) == 0;
|
2011-06-01 18:18:58 +02:00
|
|
|
}
|
|
|
|
|
2011-04-12 15:32:46 +02:00
|
|
|
/*!
|
|
|
|
Determines if the component is installed.
|
2011-03-09 12:45:22 +01:00
|
|
|
*/
|
2011-02-21 16:30:31 +01:00
|
|
|
bool Component::isInstalled() const
|
|
|
|
{
|
2011-06-06 17:23:48 +02:00
|
|
|
return scInstalled == value(scCurrentState);
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
2011-03-09 12:45:22 +01:00
|
|
|
Determines if the user wants to install the component
|
|
|
|
*/
|
2011-02-21 16:30:31 +01:00
|
|
|
bool Component::installationRequested() const
|
|
|
|
{
|
2011-04-12 12:04:55 +02:00
|
|
|
return !isInstalled() && isSelected();
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
2011-04-12 15:32:46 +02:00
|
|
|
Set's the components state to uninstalled.
|
2011-03-09 12:45:22 +01:00
|
|
|
*/
|
2011-04-12 15:32:46 +02:00
|
|
|
void Component::setUninstalled()
|
2011-02-21 16:30:31 +01:00
|
|
|
{
|
2011-06-06 17:23:48 +02:00
|
|
|
setValue(scCurrentState, scUninstalled);
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
2011-04-12 15:32:46 +02:00
|
|
|
Determines if the component is uninstalled.
|
2011-03-09 12:45:22 +01:00
|
|
|
*/
|
2011-04-12 15:32:46 +02:00
|
|
|
bool Component::isUninstalled() const
|
2011-02-21 16:30:31 +01:00
|
|
|
{
|
2011-06-06 17:23:48 +02:00
|
|
|
return scUninstalled == value(scCurrentState);
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
2011-04-12 15:32:46 +02:00
|
|
|
Determines if the user wants to uninstall the component.
|
2011-03-09 12:45:22 +01:00
|
|
|
*/
|
2011-04-12 15:32:46 +02:00
|
|
|
bool Component::uninstallationRequested() const
|
2011-02-21 16:30:31 +01:00
|
|
|
{
|
2011-04-12 15:32:46 +02:00
|
|
|
return isInstalled() && !isSelected();
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
2011-03-09 12:45:22 +01:00
|
|
|
\property Component::fromOnlineRepository
|
|
|
|
|
2011-04-21 10:19:02 +02:00
|
|
|
Determines whether this component has been loaded from an online repository. Get this property's
|
|
|
|
value by using %isFromOnlineRepository. \sa addDownloadableArchive
|
2011-03-09 12:45:22 +01:00
|
|
|
*/
|
2011-02-21 16:30:31 +01:00
|
|
|
bool Component::isFromOnlineRepository() const
|
|
|
|
{
|
|
|
|
return !repositoryUrl().isEmpty();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
2011-03-09 12:45:22 +01:00
|
|
|
Contains the repository Url this component is downloaded from.
|
|
|
|
When this component is not downloaded from an online repository, returns an empty #QUrl.
|
|
|
|
*/
|
2011-02-21 16:30:31 +01:00
|
|
|
QUrl Component::repositoryUrl() const
|
|
|
|
{
|
2011-04-13 11:06:16 +02:00
|
|
|
return d->m_repositoryUrl;
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
2011-03-09 12:45:22 +01:00
|
|
|
Sets this components #repositoryUrl.
|
2011-02-21 16:30:31 +01:00
|
|
|
*/
|
2011-03-09 12:45:22 +01:00
|
|
|
void Component::setRepositoryUrl(const QUrl& url)
|
2011-02-21 16:30:31 +01:00
|
|
|
{
|
2011-04-13 11:06:16 +02:00
|
|
|
d->m_repositoryUrl = url;
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
2011-03-15 18:17:20 +01:00
|
|
|
|
|
|
|
|
|
|
|
QString Component::localTempPath() const
|
|
|
|
{
|
2011-04-13 11:06:16 +02:00
|
|
|
return d->m_localTempPath;
|
2011-03-15 18:17:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void Component::setLocalTempPath(const QString &tempLocalPath)
|
|
|
|
{
|
2011-04-13 11:06:16 +02:00
|
|
|
d->m_localTempPath = tempLocalPath;
|
2011-03-15 18:17:20 +01:00
|
|
|
}
|
2011-04-01 13:55:31 +02:00
|
|
|
|
|
|
|
void Component::updateModelData(const QString &key, const QString &data)
|
|
|
|
{
|
2011-06-06 17:23:48 +02:00
|
|
|
if (key == scVirtual) {
|
|
|
|
if (data.toLower() == scTrue)
|
2011-06-14 16:24:50 +02:00
|
|
|
setData(d->m_core->virtualComponentsFont(), Qt::FontRole);
|
2011-04-01 13:55:31 +02:00
|
|
|
}
|
|
|
|
|
2011-06-06 17:23:48 +02:00
|
|
|
if (key == scVersion)
|
2011-04-01 13:55:31 +02:00
|
|
|
setData(data, NewVersion);
|
|
|
|
|
2011-06-06 17:23:48 +02:00
|
|
|
if (key == scDisplayName)
|
2011-04-01 13:55:31 +02:00
|
|
|
setData(data, Qt::DisplayRole);
|
|
|
|
|
2011-06-06 17:23:48 +02:00
|
|
|
if (key == scInstalledVersion)
|
2011-04-01 13:55:31 +02:00
|
|
|
setData(data, InstalledVersion);
|
|
|
|
|
2011-06-06 17:23:48 +02:00
|
|
|
if (key == scUncompressedSize)
|
2011-04-01 13:55:31 +02:00
|
|
|
setData(uncompressedSize(), UncompressedSize);
|
|
|
|
|
2011-06-22 12:53:18 +02:00
|
|
|
const QString &updateInfo = value(scUpdateText);
|
|
|
|
if (updateInfo.isEmpty()) {
|
|
|
|
setData(QLatin1String("<html><body>") + value(scDescription) + QLatin1String("</body></html>"),
|
|
|
|
Qt::ToolTipRole);
|
|
|
|
} else {
|
|
|
|
setData(value(scDescription) + QLatin1String("<br><br>Update Info: ") + value(scUpdateText),
|
|
|
|
Qt::ToolTipRole);
|
|
|
|
}
|
2011-04-01 13:55:31 +02:00
|
|
|
}
|