summaryrefslogtreecommitdiffstats
path: root/src/libs/installer
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/installer')
-rw-r--r--src/libs/installer/component.cpp12
-rw-r--r--src/libs/installer/component_p.cpp10
-rw-r--r--src/libs/installer/component_p.h19
-rw-r--r--src/libs/installer/componentchecker.cpp73
-rw-r--r--src/libs/installer/componentmodel.cpp79
-rw-r--r--src/libs/installer/createlocalrepositoryoperation.cpp2
-rw-r--r--src/libs/installer/installercalculator.cpp3
-rw-r--r--src/libs/installer/messageboxhandler.cpp2
-rw-r--r--src/libs/installer/observer.cpp19
-rw-r--r--src/libs/installer/packagemanagercore.cpp95
-rw-r--r--src/libs/installer/packagemanagercore.h1
-rw-r--r--src/libs/installer/packagemanagercore_p.cpp27
-rw-r--r--src/libs/installer/packagemanagercoredata.cpp2
-rw-r--r--src/libs/installer/packagemanagergui.cpp118
-rw-r--r--src/libs/installer/packagemanagergui.h33
-rw-r--r--src/libs/installer/remoteobject.h2
-rw-r--r--src/libs/installer/remoteserverconnection.cpp6
-rw-r--r--src/libs/installer/scriptengine.cpp261
-rw-r--r--src/libs/installer/scriptengine.h6
-rw-r--r--src/libs/installer/scriptengine_p.h45
-rw-r--r--src/libs/installer/settings.cpp13
-rw-r--r--src/libs/installer/settings.h4
-rw-r--r--src/libs/installer/uninstallercalculator.cpp6
-rw-r--r--src/libs/installer/utils.cpp2
24 files changed, 577 insertions, 263 deletions
diff --git a/src/libs/installer/component.cpp b/src/libs/installer/component.cpp
index 2d6836ed0..86388cc2e 100644
--- a/src/libs/installer/component.cpp
+++ b/src/libs/installer/component.cpp
@@ -72,7 +72,7 @@ static const QLatin1String scForcedInstallation("ForcedInstallation");
\qmltype component
\inqmlmodule scripting
- \brief The component type represents the current component that the Qt Script belongs to.
+ \brief Represents the current component that the Qt Script belongs to.
A minimal valid script needs to contain a constructor, which can look like this:
@@ -156,7 +156,7 @@ static const QLatin1String scForcedInstallation("ForcedInstallation");
/*!
\qmlproperty stringlist component::autoDependencies
- Returns the value of the \c <AutoDependsOn> tag in the package information file.
+ Returns the value of the \c <AutoDependOn> tag in the package information file.
*/
/*!
@@ -342,8 +342,10 @@ quint64 Component::updateUncompressedSize()
{
quint64 size = 0;
- if (installationRequested() || updateRequested())
+ if (installAction() == ComponentModelHelper::Install
+ || installAction() == ComponentModelHelper::KeepInstalled) {
size = d->m_vars.value(scUncompressedSize).toLongLong();
+ }
foreach (Component* comp, d->m_allChildComponents)
size += comp->updateUncompressedSize();
@@ -534,8 +536,7 @@ void Component::loadTranslations(const QDir &directory, const QStringList &qms)
{
QDirIterator it(directory.path(), qms, QDir::Files);
const QStringList translations = d->m_core->settings().translations();
- const QString uiLanguage = QLocale().uiLanguages().value(0, QLatin1String("en_us"))
- .replace(QLatin1Char('-'), QLatin1Char('_'));
+ const QString uiLanguage = QLocale().uiLanguages().value(0, QLatin1String("en"));
while (it.hasNext()) {
const QString filename = it.next();
const QString basename = QFileInfo(filename).baseName();
@@ -583,6 +584,7 @@ void Component::loadUserInterfaces(const QDir &directory, const QStringList &uis
throw Error(tr("Could not load the requested UI file '%1'. Error: %2").arg(it.fileName(),
loader.errorString()));
}
+ d->scriptEngine()->newQObject(widget);
d->m_userInterfaces.insert(widget->objectName(), widget);
}
}
diff --git a/src/libs/installer/component_p.cpp b/src/libs/installer/component_p.cpp
index 4bcfbf5dc..18ba4b7b5 100644
--- a/src/libs/installer/component_p.cpp
+++ b/src/libs/installer/component_p.cpp
@@ -204,6 +204,16 @@ void ComponentModelHelper::setSelectable(bool selectable)
changeFlags(selectable, Qt::ItemIsSelectable);
}
+ComponentModelHelper::InstallAction ComponentModelHelper::installAction() const
+{
+ return data(ComponentModelHelper::Action).value<ComponentModelHelper::InstallAction>();
+}
+
+void ComponentModelHelper::setInstallAction(ComponentModelHelper::InstallAction action)
+{
+ setData(QVariant::fromValue<ComponentModelHelper::InstallAction>(action), ComponentModelHelper::Action);
+}
+
/*!
Returns the item flags for the component. The item flags determine how the user can interact with the
component.
diff --git a/src/libs/installer/component_p.h b/src/libs/installer/component_p.h
index 15834d1f2..87e067ba4 100644
--- a/src/libs/installer/component_p.h
+++ b/src/libs/installer/component_p.h
@@ -93,18 +93,28 @@ class INSTALLER_EXPORT ComponentModelHelper
{
public:
enum Roles {
- LocalDisplayVersion = Qt::UserRole + 1,
+ Action = Qt::UserRole + 1,
+ LocalDisplayVersion,
RemoteDisplayVersion,
ReleaseDate,
UncompressedSize
};
+ enum InstallAction {
+ Install,
+ Uninstall,
+ KeepInstalled,
+ KeepUninstalled
+ };
+
enum Column {
NameColumn = 0,
+ ActionColumn,
InstalledVersionColumn,
NewVersionColumn,
ReleaseDateColumn,
- UncompressedSizeColumn
+ UncompressedSizeColumn,
+ LastColumn
};
explicit ComponentModelHelper();
@@ -125,6 +135,9 @@ public:
bool isSelectable() const;
void setSelectable(bool selectable);
+ InstallAction installAction() const;
+ void setInstallAction(InstallAction action);
+
Qt::ItemFlags flags() const;
void setFlags(Qt::ItemFlags flags);
@@ -148,4 +161,6 @@ private:
} // namespace QInstaller
+Q_DECLARE_METATYPE(QInstaller::ComponentModelHelper::InstallAction)
+
#endif // COMPONENT_P_H
diff --git a/src/libs/installer/componentchecker.cpp b/src/libs/installer/componentchecker.cpp
index 5f07c74fd..64ce851a0 100644
--- a/src/libs/installer/componentchecker.cpp
+++ b/src/libs/installer/componentchecker.cpp
@@ -48,51 +48,68 @@ QStringList ComponentChecker::checkComponent(Component *component)
const bool defaultPropertyValue = component->variables().value(scDefault).compare(scTrue, Qt::CaseInsensitive) == 0;
if (!component->autoDependencies().isEmpty()) {
if (component->forcedInstallation()) {
- checkResult << tr("Component %1 specifies \"ForcedInstallation\" property "
- "together with \"AutoDependOn\" list. This combination of states "
- "may not work properly."
- ).arg(component->name());
+ checkResult << QString::fromLatin1("Component %1 specifies \"ForcedInstallation\" property "
+ "together with \"AutoDependOn\" list. This combination of states may not work properly.")
+ .arg(component->name());
}
if (defaultPropertyScriptValue) {
- checkResult << tr("Component %1 specifies script value for \"Default\" property "
- "together with \"AutoDependOn\" list. This combination of states "
- "may not work properly."
- ).arg(component->name());
+ checkResult << QString::fromLatin1("Component %1 specifies script value for \"Default\" "
+ "property together with \"AutoDependOn\" list. This combination of states may not "
+ "work properly.").arg(component->name());
}
if (defaultPropertyValue) {
- checkResult << tr("Component %1 specifies \"Default\" property "
- "together with \"AutoDependOn\" list. This combination of states "
- "may not work properly."
- ).arg(component->name());
+ checkResult << QString::fromLatin1("Component %1 specifies \"Default\" property together "
+ "with \"AutoDependOn\" list. This combination of states may not work properly.")
+ .arg(component->name());
}
}
if (component->packageManagerCore()->isInstaller()) {
if (component->isTristate()) {
if (defaultPropertyScriptValue) {
- checkResult << tr("Component %1 specifies script value for \"Default\" property "
- "while not being a leaf node. The \"Default\" property "
- "will get a \"false\" value."
- ).arg(component->name());
+ checkResult << QString::fromLatin1("Component %1 specifies script value for \"Default\" "
+ "property while not being a leaf node. The \"Default\" property will get a "
+ "\"false\" value.").arg(component->name());
}
if (defaultPropertyValue) {
- checkResult << tr("Component %1 specifies \"Default\" property "
- "while not being a leaf node. The \"Default\" property "
- "will get a \"false\" value."
- ).arg(component->name());
+ checkResult << QString::fromLatin1("Component %1 specifies \"Default\" property "
+ "while not being a leaf node. The \"Default\" property will get a \"false\" value.")
+ .arg(component->name());
}
}
if (!component->isCheckable()) {
if (defaultPropertyScriptValue) {
- checkResult << tr("Component %1 specifies script value for \"Default\" property "
- "while being not checkable. The \"Default\" property "
- "will get a \"false\" value."
- ).arg(component->name());
+ checkResult << QString::fromLatin1("Component %1 specifies script value for \"Default\" "
+ "property while being not checkable. The \"Default\" property will get a \"false\" "
+ "value.").arg(component->name());
}
if (defaultPropertyValue) {
- checkResult << tr("Component %1 specifies \"Default\" property "
- "while being not checkable. The \"Default\" property "
- "will get a \"false\" value."
- ).arg(component->name());
+ checkResult << QString::fromLatin1("Component %1 specifies \"Default\" property "
+ "while being not checkable. The \"Default\" property will get a \"false\" value.")
+ .arg(component->name());
+ }
+ }
+ if (component->childCount()) {
+ const QStringList autoDependencies = component->autoDependencies();
+ if (!autoDependencies.isEmpty()) {
+ checkResult << QString::fromLatin1("Component %1 auto depends on other components "
+ "while having children components. This will not work properly.")
+ .arg(component->name());
+ }
+
+ // TODO: search also for components which autodepend on "component"
+ // (something like core->autodependees(component))
+
+ if (!component->dependencies().isEmpty()) {
+ checkResult << QString::fromLatin1("Component %1 depends on other components "
+ "while having children components. This will not work properly.")
+ .arg(component->name());
+ }
+
+ PackageManagerCore *core = component->packageManagerCore();
+ if (!core->dependees(component).isEmpty()) {
+ checkResult << QString::fromLatin1("Other components depend on component %1 "
+ "which has children components. This will not work properly.")
+ .arg(component->name());
}
}
}
diff --git a/src/libs/installer/componentmodel.cpp b/src/libs/installer/componentmodel.cpp
index 4c4bda080..d2537dea0 100644
--- a/src/libs/installer/componentmodel.cpp
+++ b/src/libs/installer/componentmodel.cpp
@@ -36,6 +36,7 @@
#include "component.h"
#include "packagemanagercore.h"
+#include <QIcon>
namespace QInstaller {
@@ -71,6 +72,20 @@ namespace QInstaller {
or unchecked, or some individual component's checked state has changed.
*/
+class IconCache
+{
+public:
+ IconCache() {
+ }
+
+ QIcon icon(ComponentModelHelper::InstallAction action) const {
+ return m_icons.value(action);
+ }
+private:
+ QMap<ComponentModelHelper::InstallAction, QIcon> m_icons;
+};
+
+Q_GLOBAL_STATIC(IconCache, iconCache)
/*!
Constructs an component model with the given number of \a columns and \a core as parent.
@@ -179,6 +194,25 @@ QVariant ComponentModel::data(const QModelIndex &index, int role) const
if (index.column() > 0) {
if (role == Qt::CheckStateRole)
return QVariant();
+ if (index.column() == ComponentModelHelper::ActionColumn) {
+ if (role == Qt::DecorationRole)
+ return iconCache->icon(component->installAction());
+ if (role == Qt::ToolTipRole) {
+ switch (component->installAction()) {
+ case ComponentModelHelper::Install:
+ return tr("Component is marked for installation.");
+ case ComponentModelHelper::Uninstall:
+ return tr("Component is marked for uninstallation.");
+ case ComponentModelHelper::KeepInstalled:
+ return tr("Component is installed.");
+ case ComponentModelHelper::KeepUninstalled:
+ return tr("Component is not installed.");
+ default:
+ return QString();
+ }
+ }
+ return QVariant();
+ }
if (role == Qt::EditRole || role == Qt::DisplayRole || role == Qt::ToolTipRole)
return component->data(Qt::UserRole + index.column());
}
@@ -202,6 +236,8 @@ bool ComponentModel::setData(const QModelIndex &index, const QVariant &value, in
return false;
if (role == Qt::CheckStateRole) {
+ if (index.column() != 0)
+ return false;
ComponentSet nodes = component->childItems().toSet();
Qt::CheckState newValue = Qt::CheckState(value.toInt());
if (newValue == Qt::PartiallyChecked) {
@@ -459,6 +495,15 @@ void ComponentModel::updateAndEmitModelState()
}
emit checkStateChanged(m_modelState);
+
+ foreach (const Component *component, m_rootComponentList) {
+ emit dataChanged(indexFromComponentName(component->name()),
+ indexFromComponentName(component->name()));
+ QList<Component *> children = component->childItems();
+ foreach (const Component *child, children)
+ emit dataChanged(indexFromComponentName(child->name()),
+ indexFromComponentName(child->name()));
+ }
}
void ComponentModel::collectComponents(Component *const component, const QModelIndex &parent) const
@@ -470,15 +515,6 @@ void ComponentModel::collectComponents(Component *const component, const QModelI
namespace ComponentModelPrivate {
-struct NameGreaterThan
-{
- bool operator() (const Component *lhs, const Component *rhs) const
- {
- return lhs->name() > rhs->name();
- }
-};
-
-// call it only for items with childern
static Qt::CheckState verifyPartiallyChecked(Component *component)
{
bool anyChecked = false;
@@ -514,22 +550,19 @@ static Qt::CheckState verifyPartiallyChecked(Component *component)
QSet<QModelIndex> ComponentModel::updateCheckedState(const ComponentSet &components, Qt::CheckState 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);
- }
+ QMap<QString, Component *> sortedNodesMap;
+ foreach (Component *component, components) {
+ while (component && !sortedNodesMap.values(component->name()).contains(component)) {
+ sortedNodesMap.insertMulti(component->name(), component);
+ component = component->parentComponent();
}
}
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) {
+ const ComponentList sortedNodes = sortedNodesMap.values();
+ // we can start in descending order to check node and tri-state nodes properly
+ for (int i = sortedNodes.count(); i > 0; i--) {
+ Component * const node = sortedNodes.at(i - 1);
if (!node->isCheckable())
continue;
@@ -559,10 +592,6 @@ QSet<QModelIndex> ComponentModel::updateCheckedState(const ComponentSet &compone
break;
}
}
-
- // update all nodes uncompressed size
- foreach (Component *const node, m_rootComponentList)
- node->updateUncompressedSize(); // this is a recursive call
return changed;
}
diff --git a/src/libs/installer/createlocalrepositoryoperation.cpp b/src/libs/installer/createlocalrepositoryoperation.cpp
index b2f7232d8..c53cebee6 100644
--- a/src/libs/installer/createlocalrepositoryoperation.cpp
+++ b/src/libs/installer/createlocalrepositoryoperation.cpp
@@ -291,7 +291,7 @@ bool CreateLocalRepositoryOperation::performOperation()
if (!isOpen) // If we reach that point, either the resource was opened already.
resource->close(); // or we did open it and have to close it again.
}
- emit progressChanged(.65f + ((double(i) / double(name.count())) * .25f));
+ emit progressChanged(.65f + ((double(i) / double(names.count())) * .25f));
}
}
diff --git a/src/libs/installer/installercalculator.cpp b/src/libs/installer/installercalculator.cpp
index e4773460d..10f7327db 100644
--- a/src/libs/installer/installercalculator.cpp
+++ b/src/libs/installer/installercalculator.cpp
@@ -101,9 +101,6 @@ QString InstallerCalculator::componentsToInstallError() const
void InstallerCalculator::realAppendToInstallComponents(Component *component)
{
if (!component->isInstalled() || component->updateRequested()) {
- // remove the checkState method if we don't use selected in scripts
- component->setCheckState(Qt::Checked);
-
m_orderedComponentsToInstall.append(component);
m_toInstallComponentIds.insert(component->name());
}
diff --git a/src/libs/installer/messageboxhandler.cpp b/src/libs/installer/messageboxhandler.cpp
index 266558d93..86e28eb39 100644
--- a/src/libs/installer/messageboxhandler.cpp
+++ b/src/libs/installer/messageboxhandler.cpp
@@ -44,7 +44,7 @@
\qmltype QMessageBox
\inqmlmodule scripting
- \brief The QMessageBox type provides a modal dialog for informing the user or asking the user
+ \brief Provides a modal dialog for informing the user or asking the user
a question and receiving an answer.
diff --git a/src/libs/installer/observer.cpp b/src/libs/installer/observer.cpp
index cfb3d3c31..4bc6d6721 100644
--- a/src/libs/installer/observer.cpp
+++ b/src/libs/installer/observer.cpp
@@ -68,14 +68,15 @@ QString FileTaskObserver::progressText() const
if (bytesReceived.endsWith(tmp))
bytesReceived.chop(tmp.length());
- progressText = bytesReceived + tr(" of ") + bytesToReceive;
+ progressText = tr("%1 of %2").arg(bytesReceived).arg(bytesToReceive);
} else {
if (m_bytesTransfered > 0)
- progressText = QInstaller::humanReadableSize(m_bytesTransfered) + tr(" received.");
+ progressText = tr("%1 received.").arg(QInstaller::humanReadableSize(m_bytesTransfered));
}
- progressText += QLatin1String(" (") + QInstaller::humanReadableSize(m_bytesPerSecond) + tr("/sec")
- + QLatin1Char(')');
+ if (!progressText.isEmpty())
+ progressText += QLatin1Char(' ');
+ progressText += tr("(%1/sec)").arg(QInstaller::humanReadableSize(m_bytesPerSecond));
if (m_bytesToTransfer > 0 && m_bytesPerSecond > 0) {
const qint64 time = (m_bytesToTransfer - m_bytesTransfered) / m_bytesPerSecond;
@@ -86,22 +87,22 @@ QString FileTaskObserver::progressText() const
QString days;
if (d > 0)
- days = QString::number(d) + (d < 2 ? tr(" day") : tr(" days")) + QLatin1String(", ");
+ days = tr("%n day(s), ", "", d);
QString hours;
if (h > 0)
- hours = QString::number(h) + (h < 2 ? tr(" hour") : tr(" hours")) + QLatin1String(", ");
+ hours = tr("%n hour(s), ", "", h);
QString minutes;
if (m > 0)
- minutes = QString::number(m) + (m < 2 ? tr(" minute") : tr(" minutes"));
+ minutes = tr("%n minute(s)", "", m);
QString seconds;
if (s >= 0 && minutes.isEmpty()) {
s = (s <= 0 ? 1 : s);
- seconds = QString::number(s) + (s < 2 ? tr(" second") : tr(" seconds"));
+ seconds = tr("%n second(s)", "", s);
}
- progressText += tr(" - ") + days + hours + minutes + seconds + tr(" remaining.");
+ progressText += tr(" - %1%2%3%4 remaining.").arg(days).arg(hours).arg(minutes).arg(seconds);
} else {
progressText += tr(" - unknown time remaining.");
}
diff --git a/src/libs/installer/packagemanagercore.cpp b/src/libs/installer/packagemanagercore.cpp
index 960c2da93..8600dc114 100644
--- a/src/libs/installer/packagemanagercore.cpp
+++ b/src/libs/installer/packagemanagercore.cpp
@@ -83,7 +83,7 @@
\qmltype installer
\inqmlmodule scripting
- \brief The installer type provides access to core functionality of the Qt Installer Framework.
+ \brief Provides access to core functionality of the Qt Installer Framework.
*/
/*!
@@ -424,7 +424,37 @@ void PackageManagerCore::cancelMetaInfoJob()
*/
void PackageManagerCore::componentsToInstallNeedsRecalculation()
{
- d->m_componentsToInstallCalculated = false;
+ d->clearInstallerCalculator();
+ d->clearUninstallerCalculator();
+ QList<Component*> selectedComponentsToInstall = componentsMarkedForInstallation();
+
+ d->m_componentsToInstallCalculated =
+ d->installerCalculator()->appendComponentsToInstall(selectedComponentsToInstall);
+
+ QList<Component *> componentsToInstall = d->installerCalculator()->orderedComponentsToInstall();
+
+ QList<Component *> selectedComponentsToUninstall;
+ foreach (Component *component, components(ComponentType::All)) {
+ if (component->uninstallationRequested() && !selectedComponentsToInstall.contains(component))
+ selectedComponentsToUninstall.append(component);
+ }
+
+ d->uninstallerCalculator()->appendComponentsToUninstall(selectedComponentsToUninstall);
+
+ QSet<Component *> componentsToUninstall = d->uninstallerCalculator()->componentsToUninstall();
+
+ foreach (Component *component, components(ComponentType::Root | ComponentType::Descendants))
+ component->setInstallAction(component->isInstalled()
+ ? ComponentModelHelper::KeepInstalled
+ : ComponentModelHelper::KeepUninstalled);
+ foreach (Component *component, componentsToUninstall)
+ component->setInstallAction(ComponentModelHelper::Uninstall);
+ foreach (Component *component, componentsToInstall)
+ component->setInstallAction(ComponentModelHelper::Install);
+
+ // update all nodes uncompressed size
+ foreach (Component *const component, components(ComponentType::Root))
+ component->updateUncompressedSize(); // this is a recursive call
}
/*!
@@ -468,15 +498,15 @@ void PackageManagerCore::setMessageBoxAutomaticAnswer(const QString &identifier,
quint64 size(QInstaller::Component *component, const QString &value)
{
- if (!component->isSelected() || component->isInstalled())
- return quint64(0);
- return component->value(value).toLongLong();
+ if (component->installAction() == ComponentModelHelper::Install)
+ return component->value(value).toLongLong();
+ return quint64(0);
}
/*!
\qmlmethod float installer::requiredDiskSpace()
- Returns the estimated amount of disk space in bytes required after installation.
+ Returns the additional estimated amount of disk space in bytes required after installation.
\sa requiredTemporaryDiskSpace
*/
@@ -966,7 +996,7 @@ bool PackageManagerCore::fetchRemotePackagesTree()
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.
- See \l{Wizard Pages} for the possible values of \a page.
+ See \l{Controller Scripting} for the possible values of \a page.
Returns \c true if the operation succeeded.
@@ -1035,7 +1065,7 @@ void PackageManagerCore::setValidatorForCustomPage(Component *component, const Q
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.
- See \l{Wizard Pages} for the possible values of \a page.
+ See \l{Controller Scripting} for the possible values of \a page.
\sa removeWizardPageItem, wizardWidgetInsertionRequested
*/
@@ -1235,6 +1265,30 @@ Component *PackageManagerCore::componentByName(const QString &name, const QList<
return 0;
}
+QList<Component *> PackageManagerCore::componentsMarkedForInstallation() const
+{
+ QList<Component*> markedForInstallation;
+ const QList<Component*> relevant = components(ComponentType::Root | ComponentType::Descendants);
+ if (isUpdater()) {
+ foreach (Component *component, relevant) {
+ if (component->updateRequested())
+ markedForInstallation.append(component);
+ }
+ } else {
+ // relevant means all components which are not replaced
+ foreach (Component *component, relevant) {
+ // ask for all components which will be installed to get all dependencies
+ // even dependencies which are changed without an increased version
+ if (component->installationRequested()
+ || (component->isInstalled()
+ && !component->uninstallationRequested())) {
+ markedForInstallation.append(component);
+ }
+ }
+ }
+ return markedForInstallation;
+}
+
/*!
\qmlmethod boolean installer::calculateComponentsToInstall()
@@ -1248,28 +1302,11 @@ bool PackageManagerCore::calculateComponentsToInstall() const
emit aboutCalculateComponentsToInstall();
if (!d->m_componentsToInstallCalculated) {
d->clearInstallerCalculator();
- QList<Component*> componentsToInstall;
- const QList<Component*> relevant = components(ComponentType::Root | ComponentType::Descendants);
- if (isUpdater()) {
- foreach (Component *component, relevant) {
- if (component->updateRequested())
- componentsToInstall.append(component);
- }
- } else if (!isUpdater()) {
- // relevant means all components which are not replaced
- foreach (Component *component, relevant) {
- // ask for all components which will be installed to get all dependencies
- // even dependencies which are changed without an increased version
- if (component->installationRequested() || (component->isInstalled()
- && !component->uninstallationRequested())) {
- componentsToInstall.append(component);
- }
- }
- }
+ QList<Component*> selectedComponentsToInstall = componentsMarkedForInstallation();
d->storeCheckState();
d->m_componentsToInstallCalculated =
- d->installerCalculator()->appendComponentsToInstall(componentsToInstall);
+ d->installerCalculator()->appendComponentsToInstall(selectedComponentsToInstall);
}
emit finishedCalculateComponentsToInstall();
return d->m_componentsToInstallCalculated;
@@ -2441,11 +2478,13 @@ QString PackageManagerCore::findDisplayVersion(const QString &componentName,
ComponentModel *PackageManagerCore::componentModel(PackageManagerCore *core, const QString &objectName) const
{
- ComponentModel *model = new ComponentModel(5, core);
+ ComponentModel *model = new ComponentModel(ComponentModelHelper::LastColumn, core);
model->setObjectName(objectName);
model->setHeaderData(ComponentModelHelper::NameColumn, Qt::Horizontal,
ComponentModel::tr("Component Name"));
+ model->setHeaderData(ComponentModelHelper::ActionColumn, Qt::Horizontal,
+ ComponentModel::tr("Action"));
model->setHeaderData(ComponentModelHelper::InstalledVersionColumn, Qt::Horizontal,
ComponentModel::tr("Installed Version"));
model->setHeaderData(ComponentModelHelper::NewVersionColumn, Qt::Horizontal,
diff --git a/src/libs/installer/packagemanagercore.h b/src/libs/installer/packagemanagercore.h
index df7ac5557..fb16cc29c 100644
--- a/src/libs/installer/packagemanagercore.h
+++ b/src/libs/installer/packagemanagercore.h
@@ -329,6 +329,7 @@ private:
QString findDisplayVersion(const QString &componentName, const QHash<QString, QInstaller::Component*> &components,
const QString& versionKey, QHash<QString, bool> &visited);
ComponentModel *componentModel(PackageManagerCore *core, const QString &objectName) const;
+ QList<Component *> componentsMarkedForInstallation() const;
private:
PackageManagerCorePrivate *const d;
diff --git a/src/libs/installer/packagemanagercore_p.cpp b/src/libs/installer/packagemanagercore_p.cpp
index ba28c6871..7735f280c 100644
--- a/src/libs/installer/packagemanagercore_p.cpp
+++ b/src/libs/installer/packagemanagercore_p.cpp
@@ -78,6 +78,9 @@
#include <qt_windows.h>
#endif
+#define QUOTE_(x) #x
+#define QUOTE(x) QUOTE_(x)
+
namespace QInstaller {
class OperationTracer
@@ -433,17 +436,20 @@ ScriptEngine *PackageManagerCorePrivate::controlScriptEngine() const
void PackageManagerCorePrivate::clearAllComponentLists()
{
- qDeleteAll(m_rootComponents);
+ QList<QInstaller::Component*> toDelete;
+
+ toDelete << m_rootComponents;
m_rootComponents.clear();
m_rootDependencyReplacements.clear();
const QList<QPair<Component*, Component*> > list = m_componentsToReplaceAllMode.values();
for (int i = 0; i < list.count(); ++i)
- delete list.at(i).second;
+ toDelete << list.at(i).second;
m_componentsToReplaceAllMode.clear();
m_componentsToInstallCalculated = false;
+ qDeleteAll(toDelete);
cleanUpComponentEnvironment();
}
@@ -460,8 +466,6 @@ void PackageManagerCorePrivate::clearUpdaterComponentLists()
usedComponents.insert(list.at(i).second);
}
- qDeleteAll(usedComponents);
-
m_updaterComponents.clear();
m_updaterComponentsDeps.clear();
@@ -470,6 +474,7 @@ void PackageManagerCorePrivate::clearUpdaterComponentLists()
m_componentsToReplaceUpdaterMode.clear();
m_componentsToInstallCalculated = false;
+ qDeleteAll(usedComponents);
cleanUpComponentEnvironment();
}
@@ -563,8 +568,7 @@ void PackageManagerCorePrivate::initialize(const QHash<QString, QString> &params
}
if (isInstaller() || packagesInfo.applicationVersion().isEmpty()) {
- // TODO: this seems to be wrong, we should ask for ProductVersion defaulting to applicationVersion...
- packagesInfo.setApplicationVersion(m_data.settings().applicationVersion());
+ packagesInfo.setApplicationVersion(QLatin1String(QUOTE(IFW_REPOSITORY_FORMAT_VERSION)));
}
if (isInstaller()) {
@@ -1475,11 +1479,10 @@ bool PackageManagerCorePrivate::runInstaller()
info.setFileName(componentsXmlPath());
// Clear the packages as we might install into an already existing installation folder.
info.clearPackageInfoList();
- // also update the application name and version, might be set from a script as well
+ // also update the application name, might be set from a script as well
info.setApplicationName(m_data.value(QLatin1String("ProductName"),
m_data.settings().applicationName()).toString());
- info.setApplicationVersion(m_data.value(QLatin1String("ProductVersion"),
- m_data.settings().applicationVersion()).toString());
+ info.setApplicationVersion(QLatin1String(QUOTE(IFW_REPOSITORY_FORMAT_VERSION)));
const int progressOperationCount = countProgressOperations(componentsToInstall)
// add one more operation as we support progress
@@ -1638,7 +1641,9 @@ bool PackageManagerCorePrivate::runPackageUpdater()
} else if (isPackageManager()) {
// We found the component, the component is still checked and the dependency solver did not
// add the component as install dependency, keep it.
- if (component && component->isSelected() && !componentsToInstall.contains(component)) {
+ if (component
+ && component->installAction() == ComponentModelHelper::KeepInstalled
+ && !componentsToInstall.contains(component)) {
nonRevertedOperations.append(operation);
continue;
}
@@ -2088,7 +2093,7 @@ LocalPackagesHash PackageManagerCorePrivate::localInstalledPackages()
if (packagesInfo.applicationName().isEmpty())
packagesInfo.setApplicationName(m_data.settings().applicationName());
if (packagesInfo.applicationVersion().isEmpty())
- packagesInfo.setApplicationVersion(m_data.settings().applicationVersion());
+ packagesInfo.setApplicationVersion(QLatin1String(QUOTE(IFW_REPOSITORY_FORMAT_VERSION)));
}
if (packagesInfo.error() != KDUpdater::PackagesInfo::NoError)
diff --git a/src/libs/installer/packagemanagercoredata.cpp b/src/libs/installer/packagemanagercoredata.cpp
index d8b6d3a28..3acc24a76 100644
--- a/src/libs/installer/packagemanagercoredata.cpp
+++ b/src/libs/installer/packagemanagercoredata.cpp
@@ -108,7 +108,7 @@ PackageManagerCoreData::PackageManagerCoreData(const QHash<QString, QString> &va
// fill the variables defined in the settings
m_variables.insert(QLatin1String("ProductName"), m_settings.applicationName());
- m_variables.insert(QLatin1String("ProductVersion"), m_settings.applicationVersion());
+ m_variables.insert(QLatin1String("ProductVersion"), m_settings.version());
m_variables.insert(scTitle, m_settings.title());
m_variables.insert(scPublisher, m_settings.publisher());
m_variables.insert(QLatin1String("Url"), m_settings.url());
diff --git a/src/libs/installer/packagemanagergui.cpp b/src/libs/installer/packagemanagergui.cpp
index 5b9e7493a..46ba310ba 100644
--- a/src/libs/installer/packagemanagergui.cpp
+++ b/src/libs/installer/packagemanagergui.cpp
@@ -177,7 +177,8 @@ protected:
void addPageAndProperties(ScriptEngine *engine)
{
- engine->addQObjectChildren(this);
+ engine->addToGlobalObject(this);
+ engine->addToGlobalObject(widget());
static const QStringList properties = QStringList() << QStringLiteral("final")
<< QStringLiteral("commit") << QStringLiteral("complete");
@@ -203,7 +204,8 @@ class PackageManagerGui::Private
{
public:
Private()
- : m_modified(false)
+ : m_currentId(-1)
+ , m_modified(false)
, m_autoSwitchPage(true)
, m_showSettingsButton(false)
{
@@ -225,7 +227,7 @@ public:
QLatin1String("unknown button"));
}
-
+ int m_currentId;
bool m_modified;
bool m_autoSwitchPage;
bool m_showSettingsButton;
@@ -281,7 +283,7 @@ PackageManagerGui::PackageManagerGui(PackageManagerCore *core, QWidget *parent)
connect(m_core, SIGNAL(uninstallationFinished()), this, SLOT(showFinishedPage()),
Qt::QueuedConnection);
- connect(this, SIGNAL(currentIdChanged(int)), this, SLOT(executeControlScript(int)));
+ connect(this, SIGNAL(currentIdChanged(int)), this, SLOT(currentPageChanged(int)));
connect(this, SIGNAL(currentIdChanged(int)), m_core, SIGNAL(currentPageChanged(int)));
connect(button(QWizard::FinishButton), SIGNAL(clicked()), this, SIGNAL(finishButtonClicked()));
connect(button(QWizard::FinishButton), SIGNAL(clicked()), m_core, SIGNAL(finishButtonClicked()));
@@ -511,8 +513,8 @@ void PackageManagerGui::wizardPageRemovalRequested(QWidget *widget)
continue;
removePage(pageId);
d->m_defaultPages.remove(pageId);
- packageManagerCore()->controlScriptEngine()->removeQObjectChildren(dynamicPage);
- packageManagerCore()->componentScriptEngine()->removeQObjectChildren(dynamicPage);
+ packageManagerCore()->controlScriptEngine()->removeFromGlobalObject(dynamicPage);
+ packageManagerCore()->componentScriptEngine()->removeFromGlobalObject(dynamicPage);
}
}
@@ -522,8 +524,8 @@ void PackageManagerGui::wizardWidgetInsertionRequested(QWidget *widget,
Q_ASSERT(widget);
if (QWizardPage *const p = QWizard::page(page)) {
p->layout()->addWidget(widget);
- packageManagerCore()->controlScriptEngine()->addQObjectChildren(p);
- packageManagerCore()->componentScriptEngine()->addQObjectChildren(p);
+ packageManagerCore()->controlScriptEngine()->addToGlobalObject(p);
+ packageManagerCore()->componentScriptEngine()->addToGlobalObject(p);
}
}
@@ -531,8 +533,8 @@ void PackageManagerGui::wizardWidgetRemovalRequested(QWidget *widget)
{
Q_ASSERT(widget);
widget->setParent(0);
- packageManagerCore()->controlScriptEngine()->removeQObjectChildren(widget);
- packageManagerCore()->componentScriptEngine()->removeQObjectChildren(widget);
+ packageManagerCore()->controlScriptEngine()->removeFromGlobalObject(widget);
+ packageManagerCore()->componentScriptEngine()->removeFromGlobalObject(widget);
}
void PackageManagerGui::wizardPageVisibilityChangeRequested(bool visible, int p)
@@ -698,26 +700,6 @@ void PackageManagerGui::setSettingsButtonEnabled(bool enabled)
btn->setEnabled(enabled);
}
-/**
- Returns the first descendant of \a parent that has \a objectName as name.
-
- This method is meant to be invoked from script.
- */
-QObject *PackageManagerGui::findChild(QObject *parent, const QString &objectName)
-{
- return parent->findChild<QObject*>(objectName);
-}
-
-/**
- Returns all descendants of \a parent that have \a objectName as name.
-
- This method is meant to be invoked from script.
- */
-QList<QObject *> PackageManagerGui::findChildren(QObject *parent, const QString &objectName)
-{
- return parent->findChildren<QObject*>(objectName);
-}
-
void PackageManagerGui::customButtonClicked(int which)
{
if (QWizard::WizardButton(which) == QWizard::CustomButton1 && d->m_showSettingsButton)
@@ -735,12 +717,29 @@ void PackageManagerGui::dependsOnLocalInstallerBinary()
}
}
+void PackageManagerGui::currentPageChanged(int newId)
+{
+ executeControlScript(newId);
+
+ PackageManagerPage *oldPage = qobject_cast<PackageManagerPage *>(page(d->m_currentId));
+ if (oldPage) {
+ oldPage->leaving();
+ emit oldPage->left();
+ }
+
+ d->m_currentId = newId;
+
+ PackageManagerPage *newPage = qobject_cast<PackageManagerPage *>(page(d->m_currentId));
+ if (newPage) {
+ newPage->entering();
+ emit newPage->entered();
+ }
+}
// -- PackageManagerPage
PackageManagerPage::PackageManagerPage(PackageManagerCore *core)
- : m_fresh(true)
- , m_complete(true)
+ : m_complete(true)
, m_needsSettingsButton(false)
, m_core(core)
, validatorComponent(0)
@@ -840,31 +839,6 @@ QWidget *PackageManagerPage::findWidget(const QString &objectName) const
return findChild<QWidget*> (objectName);
}
-/*!
- \internal
-
- Used to support some kind of initializePage() in the case the wizard has been set
- to QWizard::IndependentPages. If that option has been set, initializePage() would be only
- called once. So we provide entering() and leaving() based on this reimplemented function.
-*/
-void PackageManagerPage::setVisible(bool visible)
-{
- QWizardPage::setVisible(visible);
- if (m_fresh && !visible) {
- // this is only hit once when the page gets added to the wizard
- m_fresh = false;
- return;
- }
-
- if (visible) {
- entering();
- emit entered();
- } else {
- leaving();
- emit left();
- }
-}
-
int PackageManagerPage::nextId() const
{
const int next = QWizardPage::nextId(); // the page to show next
@@ -1488,12 +1462,30 @@ public:
m_treeView->setModel(m_currentModel);
m_treeView->setExpanded(m_currentModel->index(0, 0), true);
+ const bool installActionColumnVisible = false;
+ if (!installActionColumnVisible)
+ m_treeView->hideColumn(ComponentModelHelper::ActionColumn);
+
if (m_core->isInstaller()) {
m_treeView->setHeaderHidden(true);
- for (int i = 1; i < m_currentModel->columnCount(); ++i)
+ for (int i = ComponentModelHelper::InstalledVersionColumn; i < m_currentModel->columnCount(); ++i)
m_treeView->hideColumn(i);
+
+ if (installActionColumnVisible) {
+ m_treeView->header()->setStretchLastSection(false);
+ m_treeView->header()->setSectionResizeMode(
+ ComponentModelHelper::NameColumn, QHeaderView::Stretch);
+ m_treeView->header()->setSectionResizeMode(
+ ComponentModelHelper::ActionColumn, QHeaderView::ResizeToContents);
+ }
} else {
m_treeView->header()->setStretchLastSection(true);
+ if (installActionColumnVisible) {
+ m_treeView->header()->setSectionResizeMode(
+ ComponentModelHelper::NameColumn, QHeaderView::Interactive);
+ m_treeView->header()->setSectionResizeMode(
+ ComponentModelHelper::ActionColumn, QHeaderView::Interactive);
+ }
for (int i = 0; i < m_currentModel->columnCount(); ++i)
m_treeView->resizeColumnToContents(i);
}
@@ -1797,10 +1789,8 @@ bool TargetDirectoryPage::validatePage()
void TargetDirectoryPage::entering()
{
- if (QPushButton *const b = qobject_cast<QPushButton *>(gui()->button(QWizard::NextButton))) {
+ if (QPushButton *const b = qobject_cast<QPushButton *>(gui()->button(QWizard::NextButton)))
b->setDefault(true);
- b->setFocus();
- }
}
void TargetDirectoryPage::leaving()
@@ -2103,7 +2093,7 @@ void ReadyForInstallationPage::entering()
quint64 repositorySize = 0;
const bool createLocalRepository = packageManagerCore()->createLocalRepositoryFromBinary();
- if (createLocalRepository) {
+ if (createLocalRepository && packageManagerCore()->isInstaller()) {
repositorySize = QFile(QCoreApplication::applicationFilePath()).size();
// if we create a local repository, take that space into account as well
required += repositorySize;
@@ -2394,10 +2384,8 @@ void FinishedPage::entering()
} else {
if (packageManagerCore()->isInstaller()) {
m_commitButton = wizard()->button(QWizard::FinishButton);
- if (QPushButton *const b = qobject_cast<QPushButton *>(m_commitButton)) {
+ if (QPushButton *const b = qobject_cast<QPushButton *>(m_commitButton))
b->setDefault(true);
- b->setFocus();
- }
}
gui()->setOption(QWizard::NoCancelButton, true);
diff --git a/src/libs/installer/packagemanagergui.h b/src/libs/installer/packagemanagergui.h
index f99d65593..11848b806 100644
--- a/src/libs/installer/packagemanagergui.h
+++ b/src/libs/installer/packagemanagergui.h
@@ -77,21 +77,18 @@ public:
void loadControlScript(const QString& scriptPath);
void callControlScriptMethod(const QString& methodName);
- Q_INVOKABLE QWidget *pageById(int id) const;
- Q_INVOKABLE QWidget *pageByObjectName(const QString &name) const;
+ QWidget *pageById(int id) const;
+ QWidget *pageByObjectName(const QString &name) const;
- Q_INVOKABLE QWidget* currentPageWidget() const;
- Q_INVOKABLE QWidget* pageWidgetByObjectName(const QString &name) const;
+ QWidget *currentPageWidget() const;
+ QWidget *pageWidgetByObjectName(const QString &name) const;
- Q_INVOKABLE QString defaultButtonText(int wizardButton) const;
- Q_INVOKABLE void clickButton(int wizardButton, int delayInMs = 0);
- Q_INVOKABLE bool isButtonEnabled(int wizardButton);
+ QString defaultButtonText(int wizardButton) const;
+ void clickButton(int wizardButton, int delayInMs = 0);
+ bool isButtonEnabled(int wizardButton);
- Q_INVOKABLE void showSettingsButton(bool show);
- Q_INVOKABLE void setSettingsButtonEnabled(bool enable);
-
- Q_INVOKABLE QObject *findChild(QObject *parent, const QString &objectName);
- Q_INVOKABLE QList<QObject*> findChildren(QObject *parent, const QString &objectName);
+ void showSettingsButton(bool show);
+ void setSettingsButtonEnabled(bool enable);
void updateButtonLayout();
static QWizard::WizardStyle getStyle(const QString &name);
@@ -116,7 +113,6 @@ protected Q_SLOTS:
void wizardWidgetInsertionRequested(QWidget *widget, QInstaller::PackageManagerCore::WizardPage page);
void wizardWidgetRemovalRequested(QWidget *widget);
void wizardPageVisibilityChangeRequested(bool visible, int page);
- void executeControlScript(int pageId);
void setValidatorForCustomPageRequested(QInstaller::Component *component, const QString &name,
const QString &callbackName);
@@ -126,11 +122,13 @@ private Q_SLOTS:
void onLanguageChanged();
void customButtonClicked(int which);
void dependsOnLocalInstallerBinary();
+ void currentPageChanged(int newId);
protected:
bool event(QEvent *event);
void showEvent(QShowEvent *event);
PackageManagerCore *packageManagerCore() const { return m_core; }
+ void executeControlScript(int pageId);
private:
class Private;
@@ -182,22 +180,23 @@ protected:
virtual void insertWidget(QWidget *widget, const QString &siblingName, int offset = 1);
virtual QWidget *findWidget(const QString &objectName) const;
- virtual void setVisible(bool visible); // reimp
virtual int nextId() const; // reimp
+ // Used to support some kind of initializePage() in the case the wizard has been set
+ // to QWizard::IndependentPages. If that option has been set, initializePage() would be only
+ // called once. So we provide entering() and leaving() based on currentPageChanged() signal.
virtual void entering() {} // called on entering
virtual void leaving() {} // called on leaving
- bool isConstructing() const { return m_fresh; }
-
private:
- bool m_fresh;
bool m_complete;
QString m_titleColor;
bool m_needsSettingsButton;
PackageManagerCore *m_core;
QInstaller::Component *validatorComponent;
+
+ friend class PackageManagerGui;
};
diff --git a/src/libs/installer/remoteobject.h b/src/libs/installer/remoteobject.h
index 2b6a3ab71..f47cd1367 100644
--- a/src/libs/installer/remoteobject.h
+++ b/src/libs/installer/remoteobject.h
@@ -97,7 +97,7 @@ public:
while (m_socket->bytesAvailable() < size) {
if (!m_socket->waitForReadyRead(30000)) {
throw Error(tr("Could not read all data after sending command: %1. "
- "Bytes expected: %2, Bytes received: %3. Error: %3").arg(name).arg(size)
+ "Bytes expected: %2, Bytes received: %3. Error: %4").arg(name).arg(size)
.arg(m_socket->bytesAvailable()).arg(m_socket->errorString()));
}
}
diff --git a/src/libs/installer/remoteserverconnection.cpp b/src/libs/installer/remoteserverconnection.cpp
index 0a142c4be..591ca621e 100644
--- a/src/libs/installer/remoteserverconnection.cpp
+++ b/src/libs/installer/remoteserverconnection.cpp
@@ -187,7 +187,7 @@ void RemoteServerConnection::handleQProcess(const QString &command, QDataStream
while (stream.device()->bytesAvailable() < size) {
if (!stream.device()->waitForReadyRead(30000)) {
throw Error(tr("Could not read all data after sending command: %1. "
- "Bytes expected: %2, Bytes received: %3. Error: %3").arg(command).arg(size)
+ "Bytes expected: %2, Bytes received: %3. Error: %4").arg(command).arg(size)
.arg(stream.device()->bytesAvailable()).arg(stream.device()->errorString()));
}
}
@@ -297,7 +297,7 @@ void RemoteServerConnection::handleQSettings(const QString &command, QDataStream
while (stream.device()->bytesAvailable() < size) {
if (!stream.device()->waitForReadyRead(30000)) {
throw Error(tr("Could not read all data after sending command: %1. "
- "Bytes expected: %2, Bytes received: %3. Error: %3").arg(command).arg(size)
+ "Bytes expected: %2, Bytes received: %3. Error: %4").arg(command).arg(size)
.arg(stream.device()->bytesAvailable()).arg(stream.device()->errorString()));
}
}
@@ -388,7 +388,7 @@ void RemoteServerConnection::handleQFSFileEngine(const QString &command, QDataSt
while (stream.device()->bytesAvailable() < size) {
if (!stream.device()->waitForReadyRead(30000)) {
throw Error(tr("Could not read all data after sending command: %1. "
- "Bytes expected: %2, Bytes received: %3. Error: %3").arg(command).arg(size)
+ "Bytes expected: %2, Bytes received: %3. Error: %4").arg(command).arg(size)
.arg(stream.device()->bytesAvailable()).arg(stream.device()->errorString()));
}
}
diff --git a/src/libs/installer/scriptengine.cpp b/src/libs/installer/scriptengine.cpp
index d15357e0d..fb67a1788 100644
--- a/src/libs/installer/scriptengine.cpp
+++ b/src/libs/installer/scriptengine.cpp
@@ -54,7 +54,7 @@ namespace QInstaller {
/*!
\qmltype console
\inqmlmodule scripting
- \brief The console type provides methods for logging and debugging.
+ \brief Provides methods for logging and debugging.
*/
/*!
@@ -82,22 +82,37 @@ namespace QInstaller {
/*!
\qmltype buttons
\inqmlmodule scripting
+
+ \brief Provides buttons that can be used on installer pages.
+
+ You can use a set of standard buttons and some custom buttons on the
+ installer pages. For more information about the buttons used by default on
+ each installer page, see \l {Controller Scripting}.
*/
/*!
\qmlproperty enumeration buttons::QWizard
- \list
- \li buttons.BackButton
- \li buttons.NextButton
- \li buttons.CommitButton
- \li buttons.FinishButton
- \li buttons.CancelButton
- \li buttons.HelpButton
- \li buttons.CustomButton1
- \li buttons.CustomButton2
- \li buttons.CustomButton3
- \endlist
+ Specifies the buttons on an installer page.
+
+ \value buttons.BackButton
+ The \uicontrol Back button (\uicontrol {Go Back} on OS X.)
+ \value buttons.NextButton
+ The \uicontrol Next button (\uicontrol Continue on OS X.)
+ \value buttons.CommitButton
+ The \uicontrol Commit button.
+ \value buttons.FinishButton
+ The \uicontrol Finish button (\uicontrol Done on OS X.)
+ \value buttons.CancelButton
+ The \uicontrol Cancel button.
+ \value buttons.HelpButton
+ The \uicontrol Help button.
+ \value buttons.CustomButton1
+ A custom button.
+ \value buttons.CustomButton2
+ A custom button.
+ \value buttons.CustomButton3
+ A custom button.
*/
/*!
@@ -145,7 +160,7 @@ namespace QInstaller {
\qmltype QInstaller
\inqmlmodule scripting
- \brief The QInstaller type provides access to the installer status and pages from Qt Script.
+ \brief Provides access to the installer status and pages from Qt Script.
*/
/*!
@@ -189,40 +204,139 @@ namespace QInstaller {
*/
/*!
+ \qmlsignal gui::interrupted()
+*/
+
+/*!
+ \qmlsignal gui::languageChanged()
+*/
+
+/*!
+ \qmlsignal gui::finishButtonClicked()
+*/
+
+/*!
+ \qmlsignal gui::gotRestarted()
+*/
+
+/*!
+ \qmlsignal gui::settingsButtonClicked();
+*/
+
+GuiProxy::GuiProxy(ScriptEngine *engine, QObject *parent) :
+ QObject(parent),
+ m_engine(engine),
+ m_gui(0)
+{
+}
+
+void GuiProxy::setPackageManagerGui(PackageManagerGui *gui)
+{
+ if (m_gui) {
+ disconnect(m_gui, &PackageManagerGui::interrupted, this, &GuiProxy::interrupted);
+ disconnect(m_gui, &PackageManagerGui::languageChanged, this, &GuiProxy::languageChanged);
+ disconnect(m_gui, &PackageManagerGui::finishButtonClicked, this, &GuiProxy::finishButtonClicked);
+ disconnect(m_gui, &PackageManagerGui::gotRestarted, this, &GuiProxy::gotRestarted);
+ disconnect(m_gui, &PackageManagerGui::settingsButtonClicked, this, &GuiProxy::settingsButtonClicked);
+ }
+
+ m_gui = gui;
+
+ if (m_gui) {
+ connect(m_gui, &PackageManagerGui::interrupted, this, &GuiProxy::interrupted);
+ connect(m_gui, &PackageManagerGui::languageChanged, this, &GuiProxy::languageChanged);
+ connect(m_gui, &PackageManagerGui::finishButtonClicked, this, &GuiProxy::finishButtonClicked);
+ connect(m_gui, &PackageManagerGui::gotRestarted, this, &GuiProxy::gotRestarted);
+ connect(m_gui, &PackageManagerGui::settingsButtonClicked, this, &GuiProxy::settingsButtonClicked);
+ }
+}
+
+/*!
\qmlmethod object gui::pageById(int id)
*/
+QJSValue GuiProxy::pageById(int id) const
+{
+ if (!m_gui)
+ return QJSValue();
+ return m_engine->newQObject(m_gui->pageById(id));
+}
/*!
\qmlmethod object gui::pageByObjectName(string name)
*/
+QJSValue GuiProxy::pageByObjectName(const QString &name) const
+{
+ if (!m_gui)
+ return QJSValue();
+ return m_engine->newQObject(m_gui->pageByObjectName(name));
+}
/*!
\qmlmethod object gui::currentPageWidget()
*/
+QJSValue GuiProxy::currentPageWidget() const
+{
+ if (!m_gui)
+ return QJSValue();
+ return m_engine->newQObject(m_gui->currentPageWidget());
+}
/*!
\qmlmethod object gui::pageWidgetByObjectName(string name)
*/
+QJSValue GuiProxy::pageWidgetByObjectName(const QString &name) const
+{
+ if (!m_gui)
+ return QJSValue();
+ return m_engine->newQObject(m_gui->pageWidgetByObjectName(name));
+}
/*!
\qmlmethod string gui::defaultButtonText(int wizardButton)
*/
+QString GuiProxy::defaultButtonText(int wizardButton) const
+{
+ if (!m_gui)
+ return QString();
+ return m_gui->defaultButtonText(wizardButton);
+}
/*!
\qmlmethod void gui::clickButton(int wizardButton, int delayInMs)
*/
+void GuiProxy::clickButton(int wizardButton, int delayInMs)
+{
+ if (m_gui)
+ m_gui->clickButton(wizardButton, delayInMs);
+}
/*!
\qmlmethod boolean gui::isButtonEnabled(int wizardButton)
*/
+bool GuiProxy::isButtonEnabled(int wizardButton)
+{
+ if (!m_gui)
+ return false;
+ return m_gui->isButtonEnabled(wizardButton);
+}
/*!
\qmlmethod void gui::showSettingsButton(boolean show)
*/
+void GuiProxy::showSettingsButton(bool show)
+{
+ if (m_gui)
+ m_gui->showSettingsButton(show);
+}
/*!
\qmlmethod void gui::setSettingsButtonEnabled(boolean enable)
*/
+void GuiProxy::setSettingsButtonEnabled(bool enable)
+{
+ if (m_gui)
+ m_gui->setSettingsButtonEnabled(enable);
+}
/*!
\qmlmethod object gui::findChild(object parent, string objectName)
@@ -231,6 +345,10 @@ namespace QInstaller {
\sa QObject::findChild
*/
+QJSValue GuiProxy::findChild(QObject *parent, const QString &objectName)
+{
+ return m_engine->newQObject(parent->findChild<QObject*>(objectName));
+}
/*!
\qmlmethod object[] gui::findChildren(object parent, string objectName)
@@ -239,32 +357,66 @@ namespace QInstaller {
\sa QObject::findChildren
*/
+QList<QJSValue> GuiProxy::findChildren(QObject *parent, const QString &objectName)
+{
+ QList<QJSValue> children;
+ foreach (QObject *child, parent->findChildren<QObject*>(objectName))
+ children.append(m_engine->newQObject(child));
+ return children;
+}
/*!
- \qmlsignal gui::interrupted()
+ \qmlmethod void gui::cancelButtonClicked()
*/
+void GuiProxy::cancelButtonClicked()
+{
+ if (m_gui)
+ m_gui->cancelButtonClicked();
+}
/*!
- \qmlsignal gui::languageChanged()
+ \qmlmethod void gui::reject()
*/
+void GuiProxy::reject()
+{
+ if (m_gui)
+ m_gui->reject();
+}
/*!
- \qmlsignal gui::finishButtonClicked()
+ \qmlmethod void gui::rejectWithoutPrompt()
*/
+void GuiProxy::rejectWithoutPrompt()
+{
+ if (m_gui)
+ m_gui->rejectWithoutPrompt();
+}
/*!
- \qmlsignal gui::gotRestarted()
+ \qmlmethod void gui::showFinishedPage()
*/
+void GuiProxy::showFinishedPage()
+{
+ if (m_gui)
+ m_gui->showFinishedPage();
+}
/*!
- \qmlsignal gui::settingsButtonClicked();
+ \qmlmethod void gui::setModified(boolean value)
*/
+void GuiProxy::setModified(bool value)
+{
+ if (m_gui)
+ m_gui->setModified(value);
+}
+
/*!
Constructs a script engine with \a core as parent.
*/
-ScriptEngine::ScriptEngine(PackageManagerCore *core)
- : QObject(core)
+ScriptEngine::ScriptEngine(PackageManagerCore *core) :
+ QObject(core),
+ m_guiProxy(new GuiProxy(this, this))
{
QJSValue global = m_engine.globalObject();
global.setProperty(QLatin1String("console"), m_engine.newQObject(new ConsoleProxy));
@@ -304,24 +456,45 @@ ScriptEngine::ScriptEngine(PackageManagerCore *core)
} else {
global.setProperty(QLatin1String("installer"), m_engine.newQObject(new QObject));
}
+ global.setProperty(QLatin1String("gui"), m_engine.newQObject(m_guiProxy));
global.property(QLatin1String("installer")).setProperty(QLatin1String("componentByName"),
proxy.property(QLatin1String("componentByName")));
}
+/*!
+ Creates a JavaScript object that wraps the given QObject \a object.
+
+ Signals and slots, properties and children of \a object are
+ available as properties of the created QJSValue. In addition some helper methods and properties
+ are added:
+
+ findChild(), findChildren() recursively search for child objects with the given object name.
+
+ Direct child objects are made accessible as properties under their respective object names.
+ */
QJSValue ScriptEngine::newQObject(QObject *object)
{
- QJSValue obj = m_engine.newQObject(object);
+ QJSValue jsValue = m_engine.newQObject(object);
+ QQmlEngine::setObjectOwnership(object, QQmlEngine::CppOwnership);
// add findChild(), findChildren() methods known from QtScript
QJSValue findChild = m_engine.evaluate(
QLatin1String("(function() { return gui.findChild(this, arguments[0]); })"));
QJSValue findChildren = m_engine.evaluate(
QLatin1String("(function() { return gui.findChildren(this, arguments[0]); })"));
- obj.setProperty(QLatin1String("findChild"), findChild);
- obj.setProperty(QLatin1String("findChildren"), findChildren);
+ jsValue.setProperty(QLatin1String("findChild"), findChild);
+ jsValue.setProperty(QLatin1String("findChildren"), findChildren);
+
+ // add all named children as properties
+ foreach (QObject *const child, object->children()) {
+ if (child->objectName().isEmpty())
+ continue;
+ jsValue.setProperty(child->objectName(), m_engine.newQObject(child));
+ newQObject(child);
+ }
- return obj;
+ return jsValue;
}
QJSValue ScriptEngine::evaluate(const QString &program, const QString &fileName, int lineNumber)
@@ -329,37 +502,24 @@ QJSValue ScriptEngine::evaluate(const QString &program, const QString &fileName,
return m_engine.evaluate(program, fileName, lineNumber);
}
-void ScriptEngine::addQObjectChildren(QObject *root)
+/*!
+ Registers QObject \a object in the engine, and makes it globally accessible under its object name.
+ */
+void ScriptEngine::addToGlobalObject(QObject *object)
{
- if ((!root) || root->objectName().isEmpty())
+ if (!object || object->objectName().isEmpty())
return;
- const QObjectList children = root->children();
- QJSValue jsParent = newQObject(root);
- QQmlEngine::setObjectOwnership(root, QQmlEngine::CppOwnership);
- m_engine.globalObject().setProperty(root->objectName(), jsParent);
-
- foreach (QObject *const child, children) {
- if (child->objectName().isEmpty())
- continue;
- QQmlEngine::setObjectOwnership(child, QQmlEngine::CppOwnership);
- jsParent.setProperty(child->objectName(), m_engine.newQObject(child));
- addQObjectChildren(child);
- }
+ QJSValue value = newQObject(object);
+ globalObject().setProperty(object->objectName(), value);
}
-void ScriptEngine::removeQObjectChildren(QObject *root)
+/*!
+ Removes the \a object name from the global object.
+ */
+void ScriptEngine::removeFromGlobalObject(QObject *object)
{
- if ((!root) || root->objectName().isEmpty())
- return;
-
- const QObjectList children = root->children();
- m_engine.globalObject().deleteProperty(root->objectName());
- foreach (QObject *const child, children) {
- if (child->objectName().isEmpty())
- continue;
- m_engine.globalObject().deleteProperty(child->objectName());
- }
+ globalObject().deleteProperty(object->objectName());
}
/*!
@@ -445,8 +605,7 @@ QJSValue ScriptEngine::callScriptMethod(const QJSValue &scriptContext, const QSt
void ScriptEngine::setGuiQObject(QObject *guiQObject)
{
- QQmlEngine::setObjectOwnership(guiQObject, QQmlEngine::CppOwnership);
- m_engine.globalObject().setProperty(QLatin1String("gui"), m_engine.newQObject(guiQObject));
+ m_guiProxy->setPackageManagerGui(qobject_cast<PackageManagerGui*>(guiQObject));
}
diff --git a/src/libs/installer/scriptengine.h b/src/libs/installer/scriptengine.h
index c4352d4ca..5b8a3a3ec 100644
--- a/src/libs/installer/scriptengine.h
+++ b/src/libs/installer/scriptengine.h
@@ -43,6 +43,7 @@
namespace QInstaller {
class PackageManagerCore;
+class GuiProxy;
class INSTALLER_EXPORT ScriptEngine : public QObject
{
@@ -57,8 +58,8 @@ public:
QJSValue evaluate(const QString &program, const QString &fileName = QString(),
int lineNumber = 1);
- void addQObjectChildren(QObject *root);
- void removeQObjectChildren(QObject *root);
+ void addToGlobalObject(QObject *object);
+ void removeFromGlobalObject(QObject *object);
QJSValue loadInContext(const QString &context, const QString &fileName,
const QString &scriptInjection = QString());
@@ -77,6 +78,7 @@ private:
private:
QJSEngine m_engine;
QHash<QString, QStringList> m_callstack;
+ GuiProxy *m_guiProxy;
};
}
diff --git a/src/libs/installer/scriptengine_p.h b/src/libs/installer/scriptengine_p.h
index d207130d7..696073703 100644
--- a/src/libs/installer/scriptengine_p.h
+++ b/src/libs/installer/scriptengine_p.h
@@ -37,6 +37,7 @@
#include "component.h"
#include "packagemanagercore.h"
+#include "packagemanagergui.h"
#include <QDebug>
#include <QDesktopServices>
@@ -137,6 +138,50 @@ public slots:
};
#endif
+class GuiProxy : public QObject
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(GuiProxy)
+
+public:
+ GuiProxy(ScriptEngine *engine, QObject *parent);
+ void setPackageManagerGui(PackageManagerGui *gui);
+
+ Q_INVOKABLE QJSValue pageById(int id) const;
+ Q_INVOKABLE QJSValue pageByObjectName(const QString &name) const;
+
+ Q_INVOKABLE QJSValue currentPageWidget() const;
+ Q_INVOKABLE QJSValue pageWidgetByObjectName(const QString &name) const;
+
+ Q_INVOKABLE QString defaultButtonText(int wizardButton) const;
+ Q_INVOKABLE void clickButton(int wizardButton, int delayInMs = 0);
+ Q_INVOKABLE bool isButtonEnabled(int wizardButton);
+
+ Q_INVOKABLE void showSettingsButton(bool show);
+ Q_INVOKABLE void setSettingsButtonEnabled(bool enable);
+
+ Q_INVOKABLE QJSValue findChild(QObject *parent, const QString &objectName);
+ Q_INVOKABLE QList<QJSValue> findChildren(QObject *parent, const QString &objectName);
+
+signals:
+ void interrupted();
+ void languageChanged();
+ void finishButtonClicked();
+ void gotRestarted();
+ void settingsButtonClicked();
+
+public slots:
+ void cancelButtonClicked();
+ void reject();
+ void rejectWithoutPrompt();
+ void showFinishedPage();
+ void setModified(bool value);
+
+private:
+ ScriptEngine *m_engine;
+ PackageManagerGui *m_gui;
+};
+
} // namespace QInstaller
Q_DECLARE_METATYPE(QInstaller::ConsoleProxy*)
diff --git a/src/libs/installer/settings.cpp b/src/libs/installer/settings.cpp
index a225d4262..b591eed90 100644
--- a/src/libs/installer/settings.cpp
+++ b/src/libs/installer/settings.cpp
@@ -61,6 +61,7 @@ static const QLatin1String scMaintenanceToolIniFile("MaintenanceToolIniFile");
static const QLatin1String scRemoteRepositories("RemoteRepositories");
static const QLatin1String scDependsOnLocalInstallerBinary("DependsOnLocalInstallerBinary");
static const QLatin1String scTranslations("Translations");
+static const QLatin1String scCreateLocalRepository("CreateLocalRepository");
static const QLatin1String scFtpProxy("FtpProxy");
static const QLatin1String scHttpProxy("HttpProxy");
@@ -255,7 +256,8 @@ Settings Settings::fromFileAndPrefix(const QString &path, const QString &prefix,
<< scAllowSpaceInPath << scAllowNonAsciiCharacters << scWizardStyle << scTitleColor
<< scWizardDefaultWidth << scWizardDefaultHeight
<< scRepositorySettingsPageVisible << scTargetConfigurationFile
- << scRemoteRepositories << scTranslations << QLatin1String(scControlScript);
+ << scRemoteRepositories << scTranslations << QLatin1String(scControlScript)
+ << scCreateLocalRepository;
Settings s;
s.d->m_data.insert(scPrefix, prefix);
@@ -314,6 +316,8 @@ Settings Settings::fromFileAndPrefix(const QString &path, const QString &prefix,
s.d->m_data.insert(scDependsOnLocalInstallerBinary, false);
if (!s.d->m_data.contains(scRepositorySettingsPageVisible))
s.d->m_data.insert(scRepositorySettingsPageVisible, true);
+ if (!s.d->m_data.contains(scCreateLocalRepository))
+ s.d->m_data.insert(scCreateLocalRepository, false);
return s;
}
@@ -333,7 +337,7 @@ QString Settings::applicationName() const
return d->m_data.value(scName).toString();
}
-QString Settings::applicationVersion() const
+QString Settings::version() const
{
return d->m_data.value(scVersion).toString();
}
@@ -463,6 +467,11 @@ QString Settings::configurationFileName() const
return d->m_data.value(scTargetConfigurationFile).toString();
}
+bool Settings::createLocalRepository() const
+{
+ return d->m_data.value(scCreateLocalRepository).toBool();
+}
+
bool Settings::allowSpaceInPath() const
{
return d->m_data.value(scAllowSpaceInPath, false).toBool();
diff --git a/src/libs/installer/settings.h b/src/libs/installer/settings.h
index a9cf08d85..ed60219b1 100644
--- a/src/libs/installer/settings.h
+++ b/src/libs/installer/settings.h
@@ -94,7 +94,7 @@ public:
int wizardDefaultHeight() const;
QString applicationName() const;
- QString applicationVersion() const;
+ QString version() const;
QString runProgram() const;
QStringList runProgramArguments() const;
@@ -111,6 +111,8 @@ public:
QString configurationFileName() const;
+ bool createLocalRepository() const;
+
bool dependsOnLocalInstallerBinary() const;
bool hasReplacementRepos() const;
QSet<Repository> repositories() const;
diff --git a/src/libs/installer/uninstallercalculator.cpp b/src/libs/installer/uninstallercalculator.cpp
index 1b59fd42f..726ee735b 100644
--- a/src/libs/installer/uninstallercalculator.cpp
+++ b/src/libs/installer/uninstallercalculator.cpp
@@ -68,17 +68,11 @@ void UninstallerCalculator::appendComponentToUninstall(Component *component)
foreach (Component *dependee, dependees)
appendComponentToUninstall(dependee);
- component->setCheckState(Qt::Unchecked);
m_componentsToUninstall.insert(component);
}
void UninstallerCalculator::appendComponentsToUninstall(const QList<Component*> &components)
{
- if (components.isEmpty()) {
- qDebug() << "components list is empty in" << Q_FUNC_INFO;
- return;
- }
-
foreach (Component *component, components)
appendComponentToUninstall(component);
diff --git a/src/libs/installer/utils.cpp b/src/libs/installer/utils.cpp
index b8aa46324..2b1eab55c 100644
--- a/src/libs/installer/utils.cpp
+++ b/src/libs/installer/utils.cpp
@@ -390,7 +390,7 @@ QString QInstaller::windowsErrorString(int errorCode)
LocalFree((HLOCAL) string);
if (ret.isEmpty() && errorCode == ERROR_MOD_NOT_FOUND)
- ret = QCoreApplication::tr("QInstaller", "The specified module could not be found.");
+ ret = QCoreApplication::translate("QInstaller", "The specified module could not be found.");
ret.append(QLatin1String(" (0x"));
ret.append(QString::number(uint(errorCode), 16).rightJustified(8, QLatin1Char('0')));