diff options
author | kh1 <karsten.heimrich@nokia.com> | 2012-08-21 16:29:45 +0200 |
---|---|---|
committer | Karsten Heimrich <karsten.heimrich@nokia.com> | 2012-08-21 16:30:37 +0200 |
commit | 6d7dbad2de546f2a0a39e21bcfe7afc0fc55ac91 (patch) | |
tree | a9383bb1d1d668c69786290abaf81d3ea662be94 | |
parent | b22a0e8e6d1b3114fc37acad7e96b6b3564a8e19 (diff) |
Create a new folder for S40.
Share as much files as possible, also add a basic version for the
new component selection page. It does compile, still no guarantee
to function in any way.
Change-Id: Ib10303041876d7ae7b7bb4a741989c131997a3b2
Reviewed-by: Karsten Heimrich <karsten.heimrich@nokia.com>
-rw-r--r-- | src/s40/componentviewpage.cpp | 407 | ||||
-rw-r--r-- | src/s40/componentviewpage.h | 124 | ||||
-rw-r--r-- | src/s40/installerbasecommons.cpp | 549 | ||||
-rw-r--r-- | src/s40/installerbasecommons.h | 147 | ||||
-rw-r--r-- | src/s40/s40.pro | 105 | ||||
-rw-r--r-- | src/src.pro | 2 |
6 files changed, 1333 insertions, 1 deletions
diff --git a/src/s40/componentviewpage.cpp b/src/s40/componentviewpage.cpp new file mode 100644 index 000000000..74dc576b6 --- /dev/null +++ b/src/s40/componentviewpage.cpp @@ -0,0 +1,407 @@ +/************************************************************************** +** +** This file is part of Installer Framework +** +** Copyright (c) 2010-2012 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** +** 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. +** +** Other Usage +** +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ +#include "componentviewpage.h" + +#include <component.h> +#include <componentmodel.h> +#include <messageboxhandler.h> +#include <packagemanagercore.h> +#include <settings.h> + +#include <QtCore/QDir> +#include <QtCore/QFileInfo> +#include <QtCore/QTimer> + +#include <QtGui/QLabel> +#include <QtGui/QPushButton> +#include <QtGui/QTreeView> +#include <QtGui/QHeaderView> +#include <QtGui/QProgressBar> +#include <QtGui/QRadioButton> +#include <QtGui/QStackedWidget> +#include <QtGui/QVBoxLayout> + +using namespace QInstaller; + +// -- ComponentViewPage + +ComponentViewPage::ComponentViewPage(QInstaller::PackageManagerCore *core) + : QInstaller::PackageManagerPage(core) + , m_updatesFetched(false) + , m_allPackagesFetched(false) + , m_core(core) + , m_treeView(new QTreeView(this)) + , m_allModel(m_core->defaultComponentModel()) + , m_updaterModel(m_core->updaterComponentModel()) + , m_currentModel(m_allModel) +{ + + setPixmap(QWizard::LogoPixmap, logoPixmap()); + setPixmap(QWizard::WatermarkPixmap, QPixmap()); + setObjectName(QLatin1String("ComponentViewPage")); + setTitle(titleForPage(QLatin1String("ComponentViewPage"), tr("Select Components"))); + + + + m_treeView->setObjectName(QLatin1String("ComponentsTreeView")); + + connect(m_allModel, SIGNAL(defaultCheckStateChanged(bool)), this, SLOT(setModified(bool))); + connect(m_updaterModel, SIGNAL(defaultCheckStateChanged(bool)), this, SLOT(setModified(bool))); + + m_descriptionLabel = new QLabel(this); + m_descriptionLabel->setWordWrap(true); + m_descriptionLabel->setObjectName(QLatin1String("ComponentDescriptionLabel")); + + m_sizeLabel = new QLabel(this); + m_sizeLabel->setWordWrap(true); + m_sizeLabel->setObjectName(QLatin1String("ComponentSizeLabel")); + + m_checkDefault = new QPushButton; + connect(m_checkDefault, SIGNAL(clicked()), this, SLOT(selectDefault())); + connect(m_allModel, SIGNAL(defaultCheckStateChanged(bool)), m_checkDefault, SLOT(setEnabled(bool))); + const QVariantHash hash = elementsForPage(QLatin1String("ComponentViewPage")); + if (m_core->isInstaller()) { + m_checkDefault->setObjectName(QLatin1String("SelectDefaultComponentsButton")); + m_checkDefault->setShortcut(QKeySequence(ComponentViewPage::tr("Alt+A", "select default components"))); + m_checkDefault->setText(hash.value(QLatin1String("SelectDefaultComponentsButton"), ComponentViewPage::tr("Def&ault")) + .toString()); + } else { + m_checkDefault->setEnabled(false); + m_checkDefault->setObjectName(QLatin1String("ResetComponentsButton")); + m_checkDefault->setShortcut(QKeySequence(ComponentViewPage::tr("Alt+R", "reset to already installed components"))); + m_checkDefault->setText(hash.value(QLatin1String("ResetComponentsButton"), ComponentViewPage::tr("&Reset")).toString()); + } + + m_checkAll = new QPushButton; + connect(m_checkAll, SIGNAL(clicked()), this, SLOT(selectAll())); + m_checkAll->setObjectName(QLatin1String("SelectAllComponentsButton")); + m_checkAll->setShortcut(QKeySequence(ComponentViewPage::tr("Alt+S", "select all components"))); + m_checkAll->setText(hash.value(QLatin1String("SelectAllComponentsButton"), ComponentViewPage::tr("&Select All")).toString()); + + m_uncheckAll = new QPushButton; + connect(m_uncheckAll, SIGNAL(clicked()), this, SLOT(deselectAll())); + m_uncheckAll->setObjectName(QLatin1String("DeselectAllComponentsButton")); + m_uncheckAll->setShortcut(QKeySequence(ComponentViewPage::tr("Alt+D", "deselect all components"))); + m_uncheckAll->setText(hash.value(QLatin1String("DeselectAllComponentsButton"), ComponentViewPage::tr("&Deselect All")) + .toString()); + + m_progressBar = new QProgressBar(this); + m_progressBar->setRange(0, 0); + + m_errorLabel = new QLabel(this); + m_errorLabel->setWordWrap(true); + + gui()->showSettingsButton(true); + + connect(core, SIGNAL(metaJobInfoMessage(QString)), this, SLOT(setMessage(QString))); + connect(core, SIGNAL(coreNetworkSettingsChanged()), this, SLOT(onCoreNetworkSettingsChanged())); +} + +void ComponentViewPage::currentChanged(const QModelIndex ¤t) +{ + // if there is not selection or the current selected node didn't change, return + if (!current.isValid() || current != m_treeView->selectionModel()->currentIndex()) + return; + + m_descriptionLabel->setText(m_currentModel->data(m_currentModel->index(current.row(), + ComponentModelHelper::NameColumn, current.parent()), Qt::ToolTipRole).toString()); + + m_sizeLabel->clear(); + if (!m_core->isUninstaller()) { + Component *component = m_currentModel->componentFromIndex(current); + if (component && component->updateUncompressedSize() > 0) { + const QVariantHash hash = elementsForPage(QLatin1String("ComponentViewPage")); + m_sizeLabel->setText(hash.value(QLatin1String("ComponentSizeLabel"), + ComponentViewPage::tr("This component will occupy approximately %1 on your hard disk drive.")).toString() + .arg(m_currentModel->data(m_currentModel->index(current.row(), + ComponentModelHelper::UncompressedSizeColumn, current.parent())).toString())); + } + } +} + +ComponentViewPage::~ComponentViewPage() +{ +} + + +// TODO: all *select* function ignore the fact that components can be selected inside the tree view as +// well, which will result in e.g. a disabled button state as long as "ALL" components not +// unchecked again. +void ComponentViewPage::selectAll() +{ + m_currentModel->selectAll(); + + m_checkAll->setEnabled(false); + m_uncheckAll->setEnabled(true); +} + +void ComponentViewPage::deselectAll() +{ + m_currentModel->deselectAll(); + + m_checkAll->setEnabled(true); + m_uncheckAll->setEnabled(false); +} + +void ComponentViewPage::selectDefault() +{ + m_currentModel->selectDefault(); + + m_checkAll->setEnabled(true); + m_uncheckAll->setEnabled(true); +} + +/*! + Selects the component with /a id in the component tree. +*/ +void ComponentViewPage::selectComponent(const QString &id) +{ + const QModelIndex &idx = m_currentModel->indexFromComponentName(id); + if (idx.isValid()) + m_currentModel->setData(idx, Qt::Checked, Qt::CheckStateRole); +} + +/*! + Deselects the component with /a id in the component tree. +*/ +void ComponentViewPage::deselectComponent(const QString &id) +{ + const QModelIndex &idx = m_currentModel->indexFromComponentName(id); + if (idx.isValid()) + m_currentModel->setData(idx, Qt::Unchecked, Qt::CheckStateRole); +} + + +void ComponentViewPage::updateTreeView() +{ + m_checkDefault->setVisible(m_core->isInstaller() || m_core->isPackageManager()); + if (m_treeView->selectionModel()) { + disconnect(m_treeView->selectionModel(), SIGNAL(currentChanged(QModelIndex, QModelIndex)), + this, SLOT(currentChanged(QModelIndex))); + disconnect(m_currentModel, SIGNAL(checkStateChanged(QModelIndex)), this, + SLOT(currentChanged(QModelIndex))); + } + + m_currentModel = m_core->isUpdater() ? m_updaterModel : m_allModel; + m_treeView->setModel(m_currentModel); + m_treeView->setExpanded(m_currentModel->index(0, 0), true); + + if (m_core->isInstaller()) { + m_treeView->setHeaderHidden(true); + for (int i = 1; i < m_currentModel->columnCount(); ++i) + m_treeView->hideColumn(i); + } else { + m_treeView->header()->setStretchLastSection(true); + for (int i = 0; i < m_currentModel->columnCount(); ++i) + m_treeView->resizeColumnToContents(i); + } + + bool hasChildren = false; + const int rowCount = m_currentModel->rowCount(); + for (int row = 0; row < rowCount && !hasChildren; ++row) + hasChildren = m_currentModel->hasChildren(m_currentModel->index(row, 0)); + m_treeView->setRootIsDecorated(hasChildren); + + connect(m_treeView->selectionModel(), SIGNAL(currentChanged(QModelIndex, QModelIndex)), + this, SLOT(currentChanged(QModelIndex))); + connect(m_currentModel, SIGNAL(checkStateChanged(QModelIndex)), this, + SLOT(currentChanged(QModelIndex))); + + m_treeView->setCurrentIndex(m_currentModel->index(0, 0)); +} + + +bool ComponentViewPage::validatePage() +{ + PackageManagerCore *core = packageManagerCore(); + + setComplete(false); + gui()->setSettingsButtonEnabled(false); + + const bool maintanence = core->isUpdater() || core->isPackageManager(); + if (maintanence) { + showAll(); + } else { + showMetaInfoUdate(); + } + + // fetch updater packages + if (core->isUpdater()) { + if (!m_updatesFetched) { + m_updatesFetched = core->fetchRemotePackagesTree(); + if (!m_updatesFetched) + setErrorMessage(core->error()); + } + + callControlScript(QLatin1String("UpdaterSelectedCallback")); + + if (m_updatesFetched) { + if (core->updaterComponents().count() <= 0) + setErrorMessage(QLatin1String("<b>") + tr("No updates available.") + QLatin1String("</b>")); + else + setComplete(true); + } + } + + // fetch common packages + if (core->isInstaller() || core->isPackageManager()) { + bool localPackagesTreeFetched = false; + if (!m_allPackagesFetched) { + // first try to fetch the server side packages tree + m_allPackagesFetched = core->fetchRemotePackagesTree(); + if (!m_allPackagesFetched) { + QString error = core->error(); + if (core->isPackageManager()) { + // if that fails and we're in maintenance mode, try to fetch local installed tree + localPackagesTreeFetched = core->fetchLocalPackagesTree(); + if (localPackagesTreeFetched) { + // if that succeeded, adjust error message + error = QLatin1String("<font color=\"red\">") + error + tr(" Only local package " + "management available.") + QLatin1String("</font>"); + } + } + setErrorMessage(error); + } + } + + callControlScript(QLatin1String("PackageManagerSelectedCallback")); + + if (m_allPackagesFetched | localPackagesTreeFetched) + setComplete(true); + } + + if (maintanence) { + showMaintenanceTools(); + } else { + hideAll(); + } + gui()->setSettingsButtonEnabled(true); + + return isComplete(); +} + +void ComponentViewPage::showAll() +{ + showWidgets(true); +} + +void ComponentViewPage::hideAll() +{ + showWidgets(false); +} + +void ComponentViewPage::showMetaInfoUdate() +{ + showWidgets(false); + m_label->setVisible(true); + m_progressBar->setVisible(true); +} + +void ComponentViewPage::showMaintenanceTools() +{ + showWidgets(true); + m_label->setVisible(false); + m_progressBar->setVisible(false); +} + +// -- public slots + +void ComponentViewPage::setMessage(const QString &msg) +{ + m_label->setText(msg); +} + +void ComponentViewPage::setErrorMessage(const QString &error) +{ + QPalette palette; + const PackageManagerCore::Status s = packageManagerCore()->status(); + if (s == PackageManagerCore::Failure || s == PackageManagerCore::Failure) { + palette.setColor(QPalette::WindowText, Qt::red); + } else { + palette.setColor(QPalette::WindowText, palette.color(QPalette::WindowText)); + } + + m_errorLabel->setText(error); + m_errorLabel->setPalette(palette); +} + +void ComponentViewPage::callControlScript(const QString &callback) +{ + // Initialize the gui. Needs to be done after check repositories as only then the ui can handle + // hide of pages depending on the components. + gui()->init(); + gui()->callControlScriptMethod(callback); +} + +void ComponentViewPage::onCoreNetworkSettingsChanged() +{ + // force a repaint of the ui as after the settings dialog has been closed and the wizard has been + // restarted, the "Next" button looks still disabled. TODO: figure out why this happens at all! + gui()->repaint(); + + m_updatesFetched = false; + m_allPackagesFetched = false; +} + +// -- private + +void ComponentViewPage::entering() +{ + setComplete(true); + showWidgets(false); + setMessage(QString()); + setErrorMessage(QString()); + setButtonText(QWizard::CancelButton, tr("Quit")); + + PackageManagerCore *core = packageManagerCore(); + if (core->isUninstaller() ||core->isUpdater() || core->isPackageManager()) { + showMaintenanceTools(); + } +} + +void ComponentViewPage::setModified(bool modified) +{ + setComplete(modified); +} + +void ComponentViewPage::leaving() +{ + // TODO: force repaint on next page, keeps unpainted after fetch + QTimer::singleShot(100, gui()->page(nextId()), SLOT(repaint())); + setButtonText(QWizard::CancelButton, gui()->defaultButtonText(QWizard::CancelButton)); +} + +void ComponentViewPage::showWidgets(bool show) +{ + m_label->setVisible(show); + m_progressBar->setVisible(show); +} diff --git a/src/s40/componentviewpage.h b/src/s40/componentviewpage.h new file mode 100644 index 000000000..5d4db7553 --- /dev/null +++ b/src/s40/componentviewpage.h @@ -0,0 +1,124 @@ +/************************************************************************** +** +** This file is part of Installer Framework +** +** Copyright (c) 2010-2012 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** +** 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. +** +** Other Usage +** +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#ifndef COMPONENTVIEWPAGE_H +#define COMPONENTVIEWPAGE_H + +#include <packagemanagergui.h> + +QT_BEGIN_NAMESPACE +class QLabel; +class QString; +class QProgressBar; +class QModelIndex; +class QTreeView; +QT_END_NAMESPACE + + +namespace QInstaller { + class ComponentModel; + +class ComponentViewPage : public QInstaller::PackageManagerPage +{ + Q_OBJECT + +public: + explicit ComponentViewPage(QInstaller::PackageManagerCore *core); + ~ComponentViewPage(); + + bool validatePage(); + + void showAll(); + void hideAll(); + void showMetaInfoUdate(); + void showMaintenanceTools(); + void updateTreeView(); + +public slots: + void onCoreNetworkSettingsChanged(); + void setMessage(const QString &msg); + void setErrorMessage(const QString &error); + + +public slots: + void currentChanged(const QModelIndex ¤t); + + void selectAll(); + void deselectAll(); + void selectDefault(); + void selectComponent(const QString &id); + void deselectComponent(const QString &id); + +signals: + void packageManagerCoreTypeChanged(); + + + bool isComplete() const; + + +protected: + void entering(); + +private Q_SLOTS: + void setModified(bool modified); + +private: + void leaving(); + + void showWidgets(bool show); + void callControlScript(const QString &callback); + +private: + bool m_updatesFetched; + bool m_updatesCompleted; + bool m_allPackagesFetched; + + QLabel *m_label; + QLabel *m_errorLabel; + QProgressBar *m_progressBar; + + + PackageManagerCore *m_core; + QTreeView *m_treeView; + ComponentModel *m_allModel; + ComponentModel *m_updaterModel; + ComponentModel *m_currentModel; + QLabel *m_sizeLabel; + QLabel *m_descriptionLabel; + QPushButton *m_checkAll; + QPushButton *m_uncheckAll; + QPushButton *m_checkDefault; + +}; +} //namespace QInstaller + +#endif // COMPONENTVIEWPAGE_H diff --git a/src/s40/installerbasecommons.cpp b/src/s40/installerbasecommons.cpp new file mode 100644 index 000000000..1a3a08b36 --- /dev/null +++ b/src/s40/installerbasecommons.cpp @@ -0,0 +1,549 @@ +/************************************************************************** +** +** This file is part of Installer Framework +** +** Copyright (c) 2010-2012 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** +** 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. +** +** Other Usage +** +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ +#include "installerbasecommons.h" + +#include <component.h> +#include <messageboxhandler.h> +#include <packagemanagercore.h> +#include <settings.h> + +#include <QtCore/QDir> +#include <QtCore/QFileInfo> +#include <QtCore/QTimer> + +#include <QtGui/QLabel> +#include <QtGui/QProgressBar> +#include <QtGui/QRadioButton> +#include <QtGui/QStackedWidget> +#include <QtGui/QVBoxLayout> + +using namespace QInstaller; + + +// -- IntroductionPageImpl + +IntroductionPageImpl::IntroductionPageImpl(QInstaller::PackageManagerCore *core) + : QInstaller::IntroductionPage(core) + , m_updatesFetched(false) + , m_allPackagesFetched(false) +{ + QWidget *widget = new QWidget(this); + QVBoxLayout *layout = new QVBoxLayout(widget); + + m_packageManager = new QRadioButton(tr("Package manager"), this); + layout->addWidget(m_packageManager); + m_packageManager->setChecked(core->isPackageManager()); + connect(m_packageManager, SIGNAL(toggled(bool)), this, SLOT(setPackageManager(bool))); + + m_updateComponents = new QRadioButton(tr("Update components"), this); + layout->addWidget(m_updateComponents); + m_updateComponents->setChecked(core->isUpdater()); + connect(m_updateComponents, SIGNAL(toggled(bool)), this, SLOT(setUpdater(bool))); + + m_removeAllComponents = new QRadioButton(tr("Remove all components"), this); + layout->addWidget(m_removeAllComponents); + m_removeAllComponents->setChecked(core->isUninstaller()); + connect(m_removeAllComponents, SIGNAL(toggled(bool)), this, SLOT(setUninstaller(bool))); + connect(m_removeAllComponents, SIGNAL(toggled(bool)), core, SLOT(setCompleteUninstallation(bool))); + + layout->addItem(new QSpacerItem(1, 1, QSizePolicy::Minimum, QSizePolicy::Expanding)); + + m_label = new QLabel(this); + m_label->setWordWrap(true); + m_label->setText(tr("Retrieving information from remote installation sources...")); + layout->addWidget(m_label); + + m_progressBar = new QProgressBar(this); + m_progressBar->setRange(0, 0); + layout->addWidget(m_progressBar); + + layout->addItem(new QSpacerItem(1, 1, QSizePolicy::Minimum, QSizePolicy::Expanding)); + + m_errorLabel = new QLabel(this); + m_errorLabel->setWordWrap(true); + layout->addWidget(m_errorLabel); + + widget->setLayout(layout); + setWidget(widget); + + core->setCompleteUninstallation(core->isUninstaller()); + + connect(core, SIGNAL(metaJobInfoMessage(QString)), this, SLOT(setMessage(QString))); + connect(core, SIGNAL(coreNetworkSettingsChanged()), this, SLOT(onCoreNetworkSettingsChanged())); +} + +int IntroductionPageImpl::nextId() const +{ + if (packageManagerCore()->isUninstaller()) + return PackageManagerCore::ReadyForInstallation; + + if (packageManagerCore()->isUpdater() || packageManagerCore()->isPackageManager()) + return PackageManagerCore::ComponentSelection; + + return QInstaller::IntroductionPage::nextId(); +} + +bool IntroductionPageImpl::validatePage() +{ + PackageManagerCore *core = packageManagerCore(); + if (core->isUninstaller()) + return true; + + setComplete(false); + gui()->setSettingsButtonEnabled(false); + + const bool maintanence = core->isUpdater() || core->isPackageManager(); + if (maintanence) { + showAll(); + setMaintenanceToolsEnabled(false); + } else { + showMetaInfoUdate(); + } + + // fetch updater packages + if (core->isUpdater()) { + if (!m_updatesFetched) { + m_updatesFetched = core->fetchRemotePackagesTree(); + if (!m_updatesFetched) + setErrorMessage(core->error()); + } + + callControlScript(QLatin1String("UpdaterSelectedCallback")); + + if (m_updatesFetched) { + if (core->updaterComponents().count() <= 0) + setErrorMessage(QLatin1String("<b>") + tr("No updates available.") + QLatin1String("</b>")); + else + setComplete(true); + } + } + + // fetch common packages + if (core->isInstaller() || core->isPackageManager()) { + bool localPackagesTreeFetched = false; + if (!m_allPackagesFetched) { + // first try to fetch the server side packages tree + m_allPackagesFetched = core->fetchRemotePackagesTree(); + if (!m_allPackagesFetched) { + QString error = core->error(); + if (core->isPackageManager()) { + // if that fails and we're in maintenance mode, try to fetch local installed tree + localPackagesTreeFetched = core->fetchLocalPackagesTree(); + if (localPackagesTreeFetched) { + // if that succeeded, adjust error message + error = QLatin1String("<font color=\"red\">") + error + tr(" Only local package " + "management available.") + QLatin1String("</font>"); + } + } + setErrorMessage(error); + } + } + + callControlScript(QLatin1String("PackageManagerSelectedCallback")); + + if (m_allPackagesFetched | localPackagesTreeFetched) + setComplete(true); + } + + if (maintanence) { + showMaintenanceTools(); + setMaintenanceToolsEnabled(true); + } else { + hideAll(); + } + gui()->setSettingsButtonEnabled(true); + + return isComplete(); +} + +void IntroductionPageImpl::showAll() +{ + showWidgets(true); +} + +void IntroductionPageImpl::hideAll() +{ + showWidgets(false); +} + +void IntroductionPageImpl::showMetaInfoUdate() +{ + showWidgets(false); + m_label->setVisible(true); + m_progressBar->setVisible(true); +} + +void IntroductionPageImpl::showMaintenanceTools() +{ + showWidgets(true); + m_label->setVisible(false); + m_progressBar->setVisible(false); +} + +void IntroductionPageImpl::setMaintenanceToolsEnabled(bool enable) +{ + m_packageManager->setEnabled(enable); + m_updateComponents->setEnabled(enable); + m_removeAllComponents->setEnabled(enable); +} + +// -- public slots + +void IntroductionPageImpl::setMessage(const QString &msg) +{ + m_label->setText(msg); +} + +void IntroductionPageImpl::setErrorMessage(const QString &error) +{ + QPalette palette; + const PackageManagerCore::Status s = packageManagerCore()->status(); + if (s == PackageManagerCore::Failure || s == PackageManagerCore::Failure) { + palette.setColor(QPalette::WindowText, Qt::red); + } else { + palette.setColor(QPalette::WindowText, palette.color(QPalette::WindowText)); + } + + m_errorLabel->setText(error); + m_errorLabel->setPalette(palette); +} + +void IntroductionPageImpl::callControlScript(const QString &callback) +{ + // Initialize the gui. Needs to be done after check repositories as only then the ui can handle + // hide of pages depending on the components. + gui()->init(); + gui()->callControlScriptMethod(callback); +} + +// -- private slots + +void IntroductionPageImpl::setUpdater(bool value) +{ + if (value) { + entering(); + gui()->showSettingsButton(true); + packageManagerCore()->setUpdater(); + emit packageManagerCoreTypeChanged(); + } +} + +void IntroductionPageImpl::setUninstaller(bool value) +{ + if (value) { + entering(); + gui()->showSettingsButton(false); + packageManagerCore()->setUninstaller(); + emit packageManagerCoreTypeChanged(); + } +} + +void IntroductionPageImpl::setPackageManager(bool value) +{ + if (value) { + entering(); + gui()->showSettingsButton(true); + packageManagerCore()->setPackageManager(); + emit packageManagerCoreTypeChanged(); + } +} + +void IntroductionPageImpl::onCoreNetworkSettingsChanged() +{ + // force a repaint of the ui as after the settings dialog has been closed and the wizard has been + // restarted, the "Next" button looks still disabled. TODO: figure out why this happens at all! + gui()->repaint(); + + m_updatesFetched = false; + m_allPackagesFetched = false; +} + +// -- private + +void IntroductionPageImpl::entering() +{ + setComplete(true); + showWidgets(false); + setMessage(QString()); + setErrorMessage(QString()); + setButtonText(QWizard::CancelButton, tr("Quit")); + + PackageManagerCore *core = packageManagerCore(); + if (core->isUninstaller() ||core->isUpdater() || core->isPackageManager()) { + showMaintenanceTools(); + setMaintenanceToolsEnabled(true); + } +} + +void IntroductionPageImpl::leaving() +{ + // TODO: force repaint on next page, keeps unpainted after fetch + QTimer::singleShot(100, gui()->page(nextId()), SLOT(repaint())); + setButtonText(QWizard::CancelButton, gui()->defaultButtonText(QWizard::CancelButton)); +} + +void IntroductionPageImpl::showWidgets(bool show) +{ + m_label->setVisible(show); + m_progressBar->setVisible(show); + m_packageManager->setVisible(show); + m_updateComponents->setVisible(show); + m_removeAllComponents->setVisible(show); +} + + +// -- TargetDirectoryPageImpl + +/*! + A custom target directory selection based due to the no-space restriction... +*/ +TargetDirectoryPageImpl::TargetDirectoryPageImpl(PackageManagerCore *core) + : TargetDirectoryPage(core) +{ + QPalette palette; + palette.setColor(QPalette::WindowText, Qt::red); + + m_warningLabel = new QLabel(this); + m_warningLabel->setPalette(palette); + + insertWidget(m_warningLabel, QLatin1String("MessageLabel"), 2); +} + +QString TargetDirectoryPageImpl::targetDirWarning() const +{ + if (targetDir().isEmpty()) { + return TargetDirectoryPageImpl::tr("The installation path cannot be empty, please specify a valid " + "folder."); + } + + if (QDir(targetDir()).isRelative()) { + return TargetDirectoryPageImpl::tr("The installation path cannot be relative, please specify an " + "absolute path."); + } + + QString dir = targetDir(); +#ifdef Q_OS_WIN + // remove e.g. "c:" + dir = dir.mid(2); +#endif + // check if there are not allowed characters in the target path + if (dir.contains(QRegExp(QLatin1String("[!@#$%^&*: ,;]")))) { + return TargetDirectoryPageImpl::tr("The installation path must not contain !@#$%^&*:,; or spaces, " + "please specify a valid folder."); + } + + return QString(); +} + +bool TargetDirectoryPageImpl::isComplete() const +{ + m_warningLabel->setText(targetDirWarning()); + return m_warningLabel->text().isEmpty(); +} + +bool TargetDirectoryPageImpl::askQuestion(const QString &identifier, const QString &message) +{ + QMessageBox::StandardButton bt = + MessageBoxHandler::warning(MessageBoxHandler::currentBestSuitParent(), identifier, + TargetDirectoryPageImpl::tr("Warning"), message, QMessageBox::Yes | QMessageBox::No); + QTimer::singleShot(100, wizard()->page(nextId()), SLOT(repaint())); + + return bt == QMessageBox::Yes; +} + +bool TargetDirectoryPageImpl::failWithError(const QString &identifier, const QString &message) +{ + MessageBoxHandler::critical(MessageBoxHandler::currentBestSuitParent(), identifier, + TargetDirectoryPageImpl::tr("Error"), message); + QTimer::singleShot(100, wizard()->page(nextId()), SLOT(repaint())); + + return false; +} + +bool TargetDirectoryPageImpl::validatePage() +{ + if (!isVisible()) + return true; + + const QString remove = packageManagerCore()->value(QLatin1String("RemoveTargetDir")); + if (!QVariant(remove).toBool()) + return true; + + const QString targetDir = this->targetDir(); + if (!packageManagerCore()->settings().allowNonAsciiCharacters()) { + for (int i = 0; i < targetDir.length(); ++i) { + if (targetDir.at(i).unicode() & 0xff80) { + return failWithError(QLatin1String("NonAsciiTarget"), tr("The path or installation directory " + "contains non ASCII characters. This is currently not supported! Please choose a different " + "path or installation directory.")); + } + } + } + + const QDir dir(targetDir); + // the directory exists and is empty... + if (dir.exists() && dir.entryList(QDir::AllEntries | QDir::NoDotAndDotDot).isEmpty()) + return true; + + const QFileInfo fi(targetDir); + if (fi.isDir()) { + if (dir == QDir::root() || dir == QDir::home()) { + return failWithError(QLatin1String("ForbiddenTargetDirectory"), tr("As the install directory " + "is completely deleted installing in %1 is forbidden.").arg(QDir::rootPath())); + } + + QString fileName = packageManagerCore()->settings().uninstallerName(); +#if defined(Q_OS_MAC) + if (QFileInfo(QCoreApplication::applicationDirPath() + QLatin1String("/../..")).isBundle()) + fileName += QLatin1String(".app/Contents/MacOS/") + fileName; +#elif defined(Q_OS_WIN) + fileName += QLatin1String(".exe"); +#endif + + QFileInfo fi2(targetDir + QDir::separator() + fileName); + if (fi2.exists()) { + return askQuestion(QLatin1String("OverwriteTargetDirectory"), + TargetDirectoryPageImpl::tr("The folder you selected exists already and contains an " + "installation.\nDo you want to overwrite it?")); + } + + return askQuestion(QLatin1String("OverwriteTargetDirectory"), + tr("You have selected an existing, non-empty folder for installation.\nNote that it will be " + "completely wiped on uninstallation of this application.\nIt is not advisable to install into " + "this folder as installation might fail.\nDo you want to continue?")); + } else if (fi.isFile() || fi.isSymLink()) { + return failWithError(QLatin1String("WrongTargetDirectory"), tr("You have selected an existing file " + "or symlink, please choose a different target for installation.")); + } + return true; +} + + +// -- InstallerGui + +InstallerGui::InstallerGui(PackageManagerCore *core) + : PackageManagerGui(core, 0) +{ + setPage(PackageManagerCore::Introduction, new IntroductionPageImpl(core)); + setPage(PackageManagerCore::TargetDirectory, new TargetDirectoryPageImpl(core)); + setPage(PackageManagerCore::ComponentSelection, new ComponentSelectionPage(core)); + setPage(PackageManagerCore::LicenseCheck, new LicenseAgreementPage(core)); +#ifdef Q_OS_WIN + setPage(PackageManagerCore::StartMenuSelection, new StartMenuDirectoryPage(core)); +#endif + setPage(PackageManagerCore::ReadyForInstallation, new ReadyForInstallationPage(core)); + setPage(PackageManagerCore::PerformInstallation, new PerformInstallationPage(core)); + setPage(PackageManagerCore::InstallationFinished, new FinishedPage(core)); + + bool ok = false; + const int startPage = core->value(QLatin1String("GuiStartPage")).toInt(&ok); + if (ok) + setStartId(startPage); +} + +void InstallerGui::init() +{ +} + +int InstallerGui::nextId() const +{ + const int next = QWizard::nextId(); + if (next == PackageManagerCore::LicenseCheck) { + PackageManagerCore *const core = packageManagerCore(); + const int nextNextId = pageIds().value(pageIds().indexOf(next)+ 1, -1); + if (!core->isInstaller()) + return nextNextId; + + core->calculateComponentsToInstall(); + foreach (Component* component, core->orderedComponentsToInstall()) { + if (!component->licenses().isEmpty()) + return next; + } + return nextNextId; + } + return next; +} + + +// -- MaintenanceGui + +MaintenanceGui::MaintenanceGui(PackageManagerCore *core) + : PackageManagerGui(core, 0) +{ + IntroductionPageImpl *intro = new IntroductionPageImpl(core); + connect(intro, SIGNAL(packageManagerCoreTypeChanged()), this, SLOT(updateRestartPage())); + + setPage(PackageManagerCore::Introduction, intro); + setPage(PackageManagerCore::ComponentSelection, new ComponentSelectionPage(core)); + setPage(PackageManagerCore::LicenseCheck, new LicenseAgreementPage(core)); + setPage(PackageManagerCore::ReadyForInstallation, new ReadyForInstallationPage(core)); + setPage(PackageManagerCore::PerformInstallation, new PerformInstallationPage(core)); + setPage(PackageManagerCore::InstallationFinished, new FinishedPage(core)); + + RestartPage *p = new RestartPage(core); + connect(p, SIGNAL(restart()), this, SIGNAL(gotRestarted())); + setPage(PackageManagerCore::InstallationFinished + 1, p); + + if (core->isUninstaller()) + wizardPageVisibilityChangeRequested(false, PackageManagerCore::InstallationFinished + 1); +} + +void MaintenanceGui::init() +{ +} + +int MaintenanceGui::nextId() const +{ + const int next = QWizard::nextId(); + if (next == PackageManagerCore::LicenseCheck) { + PackageManagerCore *const core = packageManagerCore(); + const int nextNextId = pageIds().value(pageIds().indexOf(next)+ 1, -1); + if (!core->isPackageManager() && !core->isUpdater()) + return nextNextId; + + core->calculateComponentsToInstall(); + foreach (Component* component, core->orderedComponentsToInstall()) { + if (component->isInstalled()) + continue; + if (!component->licenses().isEmpty()) + return next; + } + return nextNextId; + } + return next; +} + +void MaintenanceGui::updateRestartPage() +{ + wizardPageVisibilityChangeRequested((packageManagerCore()->isUninstaller() ? false : true), + PackageManagerCore::InstallationFinished + 1); +} diff --git a/src/s40/installerbasecommons.h b/src/s40/installerbasecommons.h new file mode 100644 index 000000000..f0f0c3d95 --- /dev/null +++ b/src/s40/installerbasecommons.h @@ -0,0 +1,147 @@ +/************************************************************************** +** +** This file is part of Installer Framework +** +** Copyright (c) 2010-2012 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** +** 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. +** +** Other Usage +** +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#ifndef INSTALLERBASECOMMONS_H +#define INSTALLERBASECOMMONS_H + +#include <packagemanagergui.h> + +QT_BEGIN_NAMESPACE +class QLabel; +class QString; +class QProgressBar; +QT_END_NAMESPACE + + +// -- IntroductionPageImpl + +class IntroductionPageImpl : public QInstaller::IntroductionPage +{ + Q_OBJECT + +public: + explicit IntroductionPageImpl(QInstaller::PackageManagerCore *core); + + int nextId() const; + bool validatePage(); + + void showAll(); + void hideAll(); + void showMetaInfoUdate(); + void showMaintenanceTools(); + void setMaintenanceToolsEnabled(bool enable); + +public Q_SLOTS: + void onCoreNetworkSettingsChanged(); + void setMessage(const QString &msg); + void setErrorMessage(const QString &error); + +Q_SIGNALS: + void packageManagerCoreTypeChanged(); + +private Q_SLOTS: + void setUpdater(bool value); + void setUninstaller(bool value); + void setPackageManager(bool value); + +private: + void entering(); + void leaving(); + + void showWidgets(bool show); + void callControlScript(const QString &callback); + +private: + bool m_updatesFetched; + bool m_updatesCompleted; + bool m_allPackagesFetched; + + QLabel *m_label; + QLabel *m_errorLabel; + QProgressBar *m_progressBar; + QRadioButton *m_packageManager; + QRadioButton *m_updateComponents; + QRadioButton *m_removeAllComponents; +}; + + +// --TargetDirectoryPageImpl + +class TargetDirectoryPageImpl : public QInstaller::TargetDirectoryPage +{ + Q_OBJECT + +public: + explicit TargetDirectoryPageImpl(QInstaller::PackageManagerCore *core); + + QString targetDirWarning() const; + bool isComplete() const; + bool askQuestion(const QString &identifier, const QString &message); + bool failWithError(const QString &identifier, const QString &message); + bool validatePage(); + +private: + QLabel *m_warningLabel; +}; + + +// -- InstallerGui + +class InstallerGui : public QInstaller::PackageManagerGui +{ + Q_OBJECT + +public: + explicit InstallerGui(QInstaller::PackageManagerCore *core); + + virtual void init(); + virtual int nextId() const; +}; + + +// -- MaintenanceGui + +class MaintenanceGui : public QInstaller::PackageManagerGui +{ + Q_OBJECT + +public: + explicit MaintenanceGui(QInstaller::PackageManagerCore *core); + + virtual void init(); + virtual int nextId() const; + +private Q_SLOTS: + void updateRestartPage(); +}; + +#endif // INSTALLERBASECOMMONS_H diff --git a/src/s40/s40.pro b/src/s40/s40.pro new file mode 100644 index 000000000..0f85fbc7f --- /dev/null +++ b/src/s40/s40.pro @@ -0,0 +1,105 @@ +TEMPLATE = app +DEPENDPATH += . .. ../sdk +INCLUDEPATH += . .. ../sdk +TARGET = installerbase + +include(../../installerfw.pri) + +QT += network script + +CONFIG -= app_bundle +DESTDIR = $$IFW_APP_PATH + +if (exists($$LRELEASE)) { + QT_LANGUAGES = qt_de + IB_LANGUAGES = de_de en_us + defineReplace(prependAll) { + for(a,$$1):result += $$2$${a}$$3 + return($$result) + } + + defineTest(testFiles) { + for(file, $$1) { + !exists($$file):return(false) + } + return(true) + } + + SUCCESS = false + IB_TRANSLATIONS = $$prependAll(IB_LANGUAGES, $$PWD/translations/,.ts) + QT_TRANSLATIONS = $$prependAll(QT_LANGUAGES, $$[QT_INSTALL_TRANSLATIONS]/,.ts) + + if (!testFiles(QT_TRANSLATIONS)) { + QT_COMPILED_TRANSLATIONS = $$prependAll(QT_LANGUAGES, $$[QT_INSTALL_TRANSLATIONS]/,.qm) + if (testFiles(QT_COMPILED_TRANSLATIONS)) { + SUCCESS = true + copyqm.input = QT_COMPILED_TRANSLATIONS + copyqm.output = $$PWD/translations/${QMAKE_FILE_BASE}.qm + unix:copyqm.commands = $$QMAKE_COPY ${QMAKE_FILE_IN} ${QMAKE_FILE_OUT} + win32:copyqm.commands = $$QMAKE_COPY \"${QMAKE_FILE_IN}\" \"${QMAKE_FILE_OUT}\" + copyqm.name = COPY ${QMAKE_FILE_IN} + copyqm.CONFIG += no_link target_predeps + QMAKE_EXTRA_COMPILERS += copyqm + } + } else { + SUCCESS = true + IB_TRANSLATIONS += $$QT_TRANSLATIONS + } + + if (contains(SUCCESS, true)) { + updateqm.input = IB_TRANSLATIONS + updateqm.output = $$PWD/translations/${QMAKE_FILE_BASE}.qm + updateqm.commands = $$LRELEASE ${QMAKE_FILE_IN} -qm ${QMAKE_FILE_OUT} + updateqm.name = LRELEASE ${QMAKE_FILE_IN} + updateqm.CONFIG += no_link target_predeps + QMAKE_EXTRA_COMPILERS += updateqm + + if (exists($$RCC)) { + RESOURCE_IB_TRANSLATIONS = $$prependAll(IB_LANGUAGES, $$PWD/translations/,.qm) + RESOURCE_QT_TRANSLATIONS = $$prependAll(QT_LANGUAGES, $$PWD/translations/,.qm) + RESOURCE = $$PWD/installerbase.qrc + runrcc.input = RESOURCE + runrcc.output = $$PWD/qrc_installerbase.cpp + runrcc.commands = $$RCC -name ${QMAKE_FILE_BASE} ${QMAKE_FILE_IN} -o ${QMAKE_FILE_OUT} + runrcc.name = RCC ${QMAKE_FILE_IN} + runrcc.CONFIG += no_link explicit_dependencies + runrcc.depends = $$RESOURCE_IB_TRANSLATIONS $$RESOURCE_QT_TRANSLATIONS + runrcc.variable_out = SOURCES + QMAKE_EXTRA_COMPILERS += runrcc + } + } +} + +# the following stuff get's shared with the original installer base + +HEADERS_SHARED = ../sdk/installerbase_p.h \ + ../sdk/tabcontroller.h \ + ../sdk/settingsdialog.h \ + +SOURCE_SHARED = ../sdk/installerbase.cpp \ + ../sdk/installerbase_p.cpp \ + ../sdk/tabcontroller.cpp \ + ../sdk/settingsdialog.cpp + +FORMS += ../sdk/settingsdialog.ui + +# things specifically for s40 + +HEADERS += $$HEADERS_SHARED \ + installerbasecommons.h \ + componentviewpage.h + +SOURCES = $$SOURCE_SHARED \ + installerbasecommons.cpp \ + componentviewpage.cpp + +win32:RC_FILE = ../sdk/installerbase.rc +win32-msvc2005 { + CONFIG += embed_manifest_exe #msvc2008 is doing this automatically +} + +embed_manifest_exe:win32-msvc2005 { + # The default configuration embed_manifest_exe overrides the manifest file + # already embedded via RC_FILE. Vs2008 already have the necessary manifest entry + QMAKE_POST_LINK += $$quote(mt.exe -updateresource:$$IFW_APP_PATH/$${TARGET}.exe -manifest \"$${IFW_SOURCE_TREE}\\src\\s40\\$${TARGET}.exe.manifest\") +} diff --git a/src/src.pro b/src/src.pro index 92ee0cf9b..828b364f9 100644 --- a/src/src.pro +++ b/src/src.pro @@ -1,4 +1,4 @@ CONFIG += ordered TEMPLATE = subdirs -SUBDIRS += libs sdk +SUBDIRS += libs s40 TRANSLATIONS += sdk/translations/de_de.ts sdk/translations/en_us.ts |