summaryrefslogtreecommitdiffstats
path: root/src/libs/installer/packagemanagergui.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/installer/packagemanagergui.cpp')
-rw-r--r--src/libs/installer/packagemanagergui.cpp424
1 files changed, 279 insertions, 145 deletions
diff --git a/src/libs/installer/packagemanagergui.cpp b/src/libs/installer/packagemanagergui.cpp
index 86c3a2d0c..1f0462eea 100644
--- a/src/libs/installer/packagemanagergui.cpp
+++ b/src/libs/installer/packagemanagergui.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2021 The Qt Company Ltd.
+** Copyright (C) 2024 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -54,6 +54,7 @@
#include <QtCore/QTimer>
#include <QAbstractItemView>
+#include <QAction>
#include <QCheckBox>
#include <QComboBox>
#include <QDesktopServices>
@@ -64,6 +65,8 @@
#include <QLineEdit>
#include <QListWidget>
#include <QListWidgetItem>
+#include <QMenuBar>
+#include <QMenu>
#include <QMessageBox>
#include <QProgressBar>
#include <QPushButton>
@@ -71,18 +74,21 @@
#include <QSplitter>
#include <QStringListModel>
#include <QTextBrowser>
+#include <QFontDatabase>
#include <QVBoxLayout>
#include <QShowEvent>
#include <QFileDialog>
#include <QGroupBox>
-#include <QDesktopWidget>
+#include <QScreen>
#ifdef Q_OS_WIN
# include <qt_windows.h>
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
# include <QWinTaskbarButton>
# include <QWinTaskbarProgress>
#endif
+#endif
using namespace KDUpdater;
using namespace QInstaller;
@@ -125,7 +131,7 @@ public:
return m_widget;
}
- bool isComplete() const Q_DECL_OVERRIDE
+ bool isComplete() const override
{
return m_widget->property("complete").toBool();
}
@@ -206,8 +212,9 @@ Q_DECLARE_METATYPE(DynamicInstallerPage*)
class PackageManagerGui::Private
{
public:
- Private()
- : m_currentId(-1)
+ Private(PackageManagerGui *qq)
+ : q(qq)
+ , m_currentId(-1)
, m_modified(false)
, m_autoSwitchPage(true)
, m_showSettingsButton(false)
@@ -231,6 +238,20 @@ public:
QLatin1String("unknown button"));
}
+ void showSettingsButton(bool show)
+ {
+ if (m_showSettingsButton == show)
+ return;
+ q->setOption(QWizard::HaveCustomButton1, show);
+ q->setButtonText(QWizard::CustomButton1, tr("&Settings"));
+ q->button(QWizard::CustomButton1)->setToolTip(
+ PackageManagerGui::tr("Specify proxy settings and configure repositories for add-on components."));
+
+ q->updateButtonLayout();
+ m_showSettingsButton = show;
+ }
+
+ PackageManagerGui *q;
int m_currentId;
bool m_modified;
bool m_autoSwitchPage;
@@ -279,6 +300,11 @@ public:
*/
/*!
+ \fn void QInstaller::PackageManagerGui::aboutApplicationClicked()
+ \sa {gui::aboutApplicationClicked}{gui.aboutApplicationClicked}
+*/
+
+/*!
\fn void QInstaller::PackageManagerGui::packageManagerCore() const
Returns the package manager core.
@@ -290,7 +316,7 @@ public:
*/
PackageManagerGui::PackageManagerGui(PackageManagerCore *core, QWidget *parent)
: QWizard(parent)
- , d(new Private)
+ , d(new Private(this))
, m_core(core)
{
if (m_core->isInstaller())
@@ -299,7 +325,17 @@ PackageManagerGui::PackageManagerGui(PackageManagerCore *core, QWidget *parent)
setWindowTitle(tr("Maintain %1").arg(m_core->value(scTitle)));
setWindowFlags(windowFlags() &~ Qt::WindowContextHelpButtonHint);
-#ifndef Q_OS_MACOS
+#ifdef Q_OS_MACOS
+ QMenuBar *menuBar = new QMenuBar(this);
+ QMenu *applicationMenu = new QMenu(menuBar);
+ menuBar->addMenu(applicationMenu);
+
+ QAction *aboutAction = new QAction(applicationMenu);
+ aboutAction->setMenuRole(QAction::AboutRole);
+ applicationMenu->addAction(aboutAction);
+
+ connect(aboutAction, &QAction::triggered, this, &PackageManagerGui::aboutApplicationClicked);
+#else
setWindowIcon(QIcon(m_core->settings().installerWindowIcon()));
#endif
if (!m_core->settings().wizardShowPageList()) {
@@ -321,7 +357,7 @@ PackageManagerGui::PackageManagerGui(PackageManagerCore *core, QWidget *parent)
QFile sheet(styleSheetFile);
if (sheet.exists()) {
if (sheet.open(QIODevice::ReadOnly)) {
- setStyleSheet(QString::fromLatin1(sheet.readAll()));
+ qApp->setStyleSheet(QString::fromLatin1(sheet.readAll()));
} else {
qCWarning(QInstaller::lcDeveloperBuild) << "The specified style sheet file "
"can not be opened.";
@@ -334,6 +370,11 @@ PackageManagerGui::PackageManagerGui(PackageManagerCore *core, QWidget *parent)
setOption(QWizard::NoBackButtonOnStartPage);
setOption(QWizard::NoBackButtonOnLastPage);
+#ifdef Q_OS_MACOS
+ setOptions(options() & ~QWizard::NoDefaultButton);
+ if (QPushButton *nextButton = qobject_cast<QPushButton *>(button(QWizard::NextButton)))
+ nextButton->setFocusPolicy(Qt::StrongFocus);
+#endif
if (m_core->settings().wizardShowPageList()) {
QWidget *sideWidget = new QWidget(this);
@@ -349,6 +390,7 @@ PackageManagerGui::PackageManagerGui(PackageManagerCore *core, QWidget *parent)
m_pageListWidget->setFocusPolicy(Qt::NoFocus);
m_pageListWidget->setSelectionMode(QAbstractItemView::NoSelection);
m_pageListWidget->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
+ m_pageListWidget->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
QVBoxLayout *sideWidgetLayout = new QVBoxLayout(sideWidget);
@@ -370,10 +412,13 @@ PackageManagerGui::PackageManagerGui(PackageManagerCore *core, QWidget *parent)
connect(this, &QDialog::rejected, m_core, &PackageManagerCore::setCanceled);
connect(this, &PackageManagerGui::interrupted, m_core, &PackageManagerCore::interrupt);
- // both queued to show the finished page once everything is done
+ // all queued to show the finished page once everything is done
connect(m_core, &PackageManagerCore::installationFinished,
this, &PackageManagerGui::showFinishedPage,
Qt::QueuedConnection);
+ connect(m_core, &PackageManagerCore::offlineGenerationFinished,
+ this, &PackageManagerGui::showFinishedPage,
+ Qt::QueuedConnection);
connect(m_core, &PackageManagerCore::uninstallationFinished,
this, &PackageManagerGui::showFinishedPage,
Qt::QueuedConnection);
@@ -426,7 +471,7 @@ PackageManagerGui::PackageManagerGui(PackageManagerCore *core, QWidget *parent)
*/
void PackageManagerGui::setMaxSize()
{
- QSize size = qApp->desktop()->availableGeometry(this).size();
+ QSize size = this->screen()->availableGeometry().size();
int windowFrameHeight = frameGeometry().height() - geometry().height();
int availableHeight = size.height() - windowFrameHeight;
@@ -469,7 +514,7 @@ void PackageManagerGui::updatePageListWidget()
itemText.replace(regExp2, QLatin1String("\\1 \\2"));
}
QListWidgetItem *item = new QListWidgetItem(itemText, m_pageListWidget);
- item->setSizeHint(QSize(item->sizeHint().width(), 30));
+ item->setSizeHint(QSize(m_pageListWidget->width(), 30));
// Give visual indication about current & non-visited pages
if (id == d->m_currentId) {
@@ -478,7 +523,7 @@ void PackageManagerGui::updatePageListWidget()
item->setFont(currentItemFont);
// Current item should be always visible on the list
m_pageListWidget->scrollToItem(item);
- } else if (id > d->m_currentId) {
+ } else {
item->setFlags(item->flags() & ~Qt::ItemIsEnabled);
}
}
@@ -647,6 +692,22 @@ bool PackageManagerGui::isButtonEnabled(int wb)
}
/*!
+ Sets \a buttonText for button specified by \a buttonId to a installer page \a pageId.
+
+ \note In some pages, installer will change the button text when entering
+ the page. In that case, you need to connect to \c entered() -signal of the
+ page to change the \a buttonText.
+
+ \sa {gui::setWizardPageButtonText}{gui.setWizardPageButtonText}
+*/
+void PackageManagerGui::setWizardPageButtonText(int pageId, int buttonId, const QString &buttonText)
+{
+ PackageManagerPage *const p = qobject_cast<PackageManagerPage*> (page(pageId));
+ if (p)
+ p->setButtonText(static_cast<QWizard::WizardButton>(buttonId), buttonText);
+}
+
+/*!
Sets a validator for the custom page specified by \a name and
\a callbackName requested by \a component.
*/
@@ -945,7 +1006,7 @@ void PackageManagerGui::cancelButtonClicked()
interrupt = true;
question = tr("Do you want to cancel the installation process?");
if (m_core->isUninstaller())
- question = tr("Do you want to cancel the uninstallation process?");
+ question = tr("Do you want to cancel the removal process?");
} else {
question = tr("Do you want to quit the installer application?");
if (m_core->isUninstaller())
@@ -1009,16 +1070,18 @@ void PackageManagerGui::showFinishedPage()
*/
void PackageManagerGui::showSettingsButton(bool show)
{
- if (d->m_showSettingsButton == show)
- return;
-
- d->m_showSettingsButton = show;
- setOption(QWizard::HaveCustomButton1, show);
- setButtonText(QWizard::CustomButton1, tr("Settings"));
- button(QWizard::CustomButton1)->setToolTip(
- PackageManagerGui::tr("Specify proxy settings and configure repositories for add-on components."));
+ m_core->setValue(QLatin1String("ShowSettingsButton"), QString::number(show));
+ d->showSettingsButton(show);
+}
- updateButtonLayout();
+/*!
+ Shows the \uicontrol Settings button if \a request is \c true. If script has
+ set the settings button visibility, this function has no effect.
+*/
+void PackageManagerGui::requestSettingsButtonByInstaller(bool request)
+{
+ if (m_core->value(QLatin1String("ShowSettingsButton")).isEmpty())
+ d->showSettingsButton(request);
}
/*!
@@ -1201,10 +1264,10 @@ void PackageManagerGui::currentPageChanged(int newId)
PackageManagerPage::PackageManagerPage(PackageManagerCore *core)
: m_complete(true)
, m_titleColor(QString())
+ , m_showOnPageList(true)
, m_needsSettingsButton(false)
, m_core(core)
, validatorComponent(nullptr)
- , m_showOnPageList(true)
{
if (!m_core->settings().titleColor().isEmpty())
m_titleColor = m_core->settings().titleColor();
@@ -1268,7 +1331,7 @@ QString PackageManagerPage::productName() const
*/
void PackageManagerPage::setColoredTitle(const QString &title)
{
- setTitle(QString::fromLatin1("<font color=\"%1\">%2</font>").arg(m_titleColor, title));
+ setTitle(QString::fromLatin1("<center><font color=\"%1\">%2</font></center>").arg(m_titleColor, title));
}
/*!
@@ -1276,7 +1339,7 @@ void PackageManagerPage::setColoredTitle(const QString &title)
*/
void PackageManagerPage::setColoredSubTitle(const QString &subTitle)
{
- setSubTitle(QString::fromLatin1("<font color=\"%1\">%2</font>").arg(m_titleColor, subTitle));
+ setSubTitle(QString::fromLatin1("<center><font color=\"%1\">%2</font></center>").arg(m_titleColor, subTitle));
}
/*!
@@ -1333,12 +1396,8 @@ void PackageManagerPage::setComplete(bool complete)
{
m_complete = complete;
if (QWizard *w = wizard()) {
- if (QAbstractButton *cancel = w->button(QWizard::CancelButton)) {
- if (cancel->hasFocus()) {
- if (QAbstractButton *next = w->button(QWizard::NextButton))
- next->setFocus();
- }
- }
+ if (QAbstractButton *nextButton = w->button(QWizard::NextButton))
+ nextButton->setFocus();
}
emit completeChanged();
}
@@ -1412,20 +1471,12 @@ int PackageManagerPage::nextId() const
if (next == PackageManagerCore::LicenseCheck) {
// calculate the page after the license page
const int nextNextId = gui()->pageIds().value(gui()->pageIds().indexOf(next) + 1, -1);
- const PackageManagerCore *const core = packageManagerCore();
+ PackageManagerCore *const core = packageManagerCore();
if (core->isUninstaller())
return nextNextId; // forcibly hide the license page if we run as uninstaller
-
- core->calculateComponentsToInstall();
- foreach (Component* component, core->orderedComponentsToInstall()) {
- if (core->isMaintainer() && component->isInstalled())
- continue; // package manager or updater, hide as long as the component is installed
-
- // The component is about to be installed and provides a license, so the page needs to
- // be shown.
- if (!component->licenses().isEmpty())
- return next;
- }
+ core->recalculateAllComponents();
+ if (core->hasLicenses())
+ return next;
return nextNextId; // no component with a license or all components with license installed
}
return next; // default, show the next page
@@ -1453,6 +1504,8 @@ IntroductionPage::IntroductionPage(PackageManagerCore *core)
: PackageManagerPage(core)
, m_updatesFetched(false)
, m_allPackagesFetched(false)
+ , m_forceUpdate(false)
+ , m_offlineMaintenanceTool(false)
, m_label(nullptr)
, m_msgLabel(nullptr)
, m_errorLabel(nullptr)
@@ -1462,7 +1515,7 @@ IntroductionPage::IntroductionPage(PackageManagerCore *core)
, m_removeAllComponents(nullptr)
{
setObjectName(QLatin1String("IntroductionPage"));
- setColoredTitle(tr("Setup - %1").arg(productName()));
+ setColoredTitle(tr("Welcome"));
QVBoxLayout *layout = new QVBoxLayout(this);
setLayout(layout);
@@ -1470,7 +1523,7 @@ IntroductionPage::IntroductionPage(PackageManagerCore *core)
m_msgLabel = new QLabel(this);
m_msgLabel->setWordWrap(true);
m_msgLabel->setObjectName(QLatin1String("MessageLabel"));
- m_msgLabel->setText(tr("Welcome to the %1 Setup Wizard.").arg(productName()));
+ m_msgLabel->setText(tr("Welcome to the %1 Setup.").arg(productName()));
QWidget *widget = new QWidget(this);
QVBoxLayout *boxLayout = new QVBoxLayout(widget);
@@ -1510,6 +1563,8 @@ IntroductionPage::IntroductionPage(PackageManagerCore *core)
m_errorLabel = new QLabel(this);
m_errorLabel->setWordWrap(true);
+ m_errorLabel->setTextFormat(Qt::RichText);
+ m_errorLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);
boxLayout->addWidget(m_errorLabel);
m_errorLabel->setObjectName(QLatin1String("ErrorLabel"));
@@ -1523,9 +1578,10 @@ IntroductionPage::IntroductionPage(PackageManagerCore *core)
connect(core, &PackageManagerCore::coreNetworkSettingsChanged,
this, &IntroductionPage::onCoreNetworkSettingsChanged);
- m_updateComponents->setEnabled(ProductKeyCheck::instance()->hasValidKey());
+ m_updateComponents->setEnabled(!m_offlineMaintenanceTool && ProductKeyCheck::instance()->hasValidKey());
#ifdef Q_OS_WIN
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
if (QSysInfo::windowsVersion() >= QSysInfo::WV_WINDOWS7) {
m_taskButton = new QWinTaskbarButton(this);
connect(core, &PackageManagerCore::metaJobProgress,
@@ -1534,6 +1590,7 @@ IntroductionPage::IntroductionPage(PackageManagerCore *core)
m_taskButton = nullptr;
}
#endif
+#endif
}
/*!
@@ -1560,9 +1617,11 @@ bool IntroductionPage::validatePage()
return true;
setComplete(false);
+ setErrorMessage(QString());
+
bool isOfflineOnlyInstaller = core->isInstaller() && core->isOfflineOnly();
// If not offline only installer, at least one valid repository needs to be available
- if (!isOfflineOnlyInstaller && !validRepositoriesAvailable()) {
+ if (!isOfflineOnlyInstaller && !core->validRepositoriesAvailable()) {
setErrorMessage(QLatin1String("<font color=\"red\">") + tr("At least one valid and enabled "
"repository required for this action to succeed.") + QLatin1String("</font>"));
return isComplete();
@@ -1577,6 +1636,7 @@ bool IntroductionPage::validatePage()
}
#ifdef Q_OS_WIN
+#if QT_VERSION < QT_VERSION_CHECK(6, 0 ,0)
if (m_taskButton) {
if (!m_taskButton->window()) {
if (QWidget *widget = QApplication::activeWindow())
@@ -1588,6 +1648,7 @@ bool IntroductionPage::validatePage()
m_taskButton->progress()->setVisible(true);
}
#endif
+#endif
// fetch updater packages
if (core->isUpdater()) {
@@ -1607,26 +1668,30 @@ bool IntroductionPage::validatePage()
// 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() && core->status() != PackageManagerCore::ForceUpdate) {
- // 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>");
- }
+ if (core->status() == PackageManagerCore::ForceUpdate) {
+ // replaces the error string from packagemanagercore
+ error = tr("There is an important update available. Please select '%1' first")
+ .arg(m_updateComponents->text().remove(QLatin1Char('&')));
+
+ m_forceUpdate = true;
+ // Don't call these directly. Need to finish the current validation first,
+ // because changing the selection updates the binary marker and resets the
+ // complete -state of the page.
+ QMetaObject::invokeMethod(m_updateComponents, "setChecked",
+ Qt::QueuedConnection, Q_ARG(bool, true));
+ QMetaObject::invokeMethod(this, "setErrorMessage",
+ Qt::QueuedConnection, Q_ARG(QString, error));
}
setErrorMessage(error);
}
}
- if (m_allPackagesFetched || localPackagesTreeFetched)
+ if (m_allPackagesFetched)
setComplete(true);
}
@@ -1639,9 +1704,11 @@ bool IntroductionPage::validatePage()
gui()->setSettingsButtonEnabled(true);
#ifdef Q_OS_WIN
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
if (m_taskButton)
m_taskButton->progress()->setVisible(!isComplete());
#endif
+#endif
return isComplete();
}
@@ -1683,15 +1750,41 @@ void IntroductionPage::showMaintenanceTools()
/*!
Sets \a enable to \c true to enable the options to install, add, and
- uninstall components on the page.
+ uninstall components on the page. For a maintenance tool without any enabled
+ repositories, the package manager and updater stay disabled regardless of
+ the value of \a enable.
*/
void IntroductionPage::setMaintenanceToolsEnabled(bool enable)
{
- m_packageManager->setEnabled(enable);
- m_updateComponents->setEnabled(enable && ProductKeyCheck::instance()->hasValidKey());
+ m_packageManager->setEnabled(enable && !m_offlineMaintenanceTool);
+ m_updateComponents->setEnabled(enable && !m_offlineMaintenanceTool
+ && ProductKeyCheck::instance()->hasValidKey());
m_removeAllComponents->setEnabled(enable);
}
+/*!
+ Enables or disables the options to add or update components based on the
+ value of \a enable. For a maintenance tool without any enabled repositories,
+ the package manager and updater stay disabled regardless of the value of \a enable.
+*/
+void IntroductionPage::setMaintainerToolsEnabled(bool enable)
+{
+ m_packageManager->setEnabled(enable && !m_offlineMaintenanceTool);
+ m_updateComponents->setEnabled(enable && !m_offlineMaintenanceTool
+ && ProductKeyCheck::instance()->hasValidKey());
+}
+
+/*!
+ Resets the internal page state, so that on clicking \uicontrol Next the metadata needs to be
+ fetched again.
+*/
+void IntroductionPage::resetFetchedState()
+{
+ m_updatesFetched = false;
+ m_allPackagesFetched = false;
+ m_forceUpdate = false;
+}
+
// -- public slots
/*!
@@ -1736,29 +1829,15 @@ void IntroductionPage::setErrorMessage(const QString &error)
m_errorLabel->setPalette(palette);
#ifdef Q_OS_WIN
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
if (m_taskButton) {
m_taskButton->progress()->stop();
m_taskButton->progress()->setValue(100);
}
#endif
+#endif
}
-/*!
- Returns \c true if at least one valid and enabled repository is available.
-*/
-bool IntroductionPage::validRepositoriesAvailable() const
-{
- const PackageManagerCore *const core = packageManagerCore();
- bool valid = false;
-
- foreach (const Repository &repo, core->settings().repositories()) {
- if (repo.isEnabled() && repo.isValid()) {
- valid = true;
- break;
- }
- }
- return valid;
-}
// -- private slots
@@ -1766,7 +1845,7 @@ void IntroductionPage::setUpdater(bool value)
{
if (value) {
entering();
- gui()->showSettingsButton(true);
+ gui()->requestSettingsButtonByInstaller(true);
packageManagerCore()->setUpdater();
emit packageManagerCoreTypeChanged();
@@ -1778,7 +1857,7 @@ void IntroductionPage::setUninstaller(bool value)
{
if (value) {
entering();
- gui()->showSettingsButton(false);
+ gui()->requestSettingsButtonByInstaller(true);
packageManagerCore()->setUninstaller();
emit packageManagerCoreTypeChanged();
@@ -1790,7 +1869,7 @@ void IntroductionPage::setPackageManager(bool value)
{
if (value) {
entering();
- gui()->showSettingsButton(true);
+ gui()->requestSettingsButtonByInstaller(true);
packageManagerCore()->setPackageManager();
emit packageManagerCoreTypeChanged();
@@ -1803,6 +1882,8 @@ void IntroductionPage::setPackageManager(bool value)
void IntroductionPage::initializePage()
{
PackageManagerCore *core = packageManagerCore();
+ const bool repositoriesAvailable = core->validRepositoriesAvailable();
+
if (core->isPackageManager()) {
m_packageManager->setChecked(true);
} else if (core->isUpdater()) {
@@ -1811,24 +1892,35 @@ void IntroductionPage::initializePage()
// If we are running maintenance tool and the default uninstaller
// marker is not overridden, set the default checked radio button
// based on if we have valid repositories available.
- if (!core->isUserSetBinaryMarker() && validRepositoriesAvailable()) {
+ if (!core->isUserSetBinaryMarker() && repositoriesAvailable) {
m_packageManager->setChecked(true);
} else {
// No repositories available, default to complete uninstallation.
m_removeAllComponents->setChecked(true);
core->setCompleteUninstallation(true);
}
+ // Disable options that are unusable without repositories
+ m_offlineMaintenanceTool = !repositoriesAvailable;
+ setMaintainerToolsEnabled(repositoriesAvailable);
}
}
/*!
Resets the internal page state, so that on clicking \uicontrol Next the metadata needs to be
- fetched again.
+ fetched again. For maintenance tool, enables or disables options requiring enabled repositories
+ based on the current repository settings.
*/
void IntroductionPage::onCoreNetworkSettingsChanged()
{
- m_updatesFetched = false;
- m_allPackagesFetched = false;
+ resetFetchedState();
+
+ PackageManagerCore *core = packageManagerCore();
+ if (core->isUninstaller() || core->isMaintainer()) {
+ m_offlineMaintenanceTool = !core->validRepositoriesAvailable();
+
+ setMaintainerToolsEnabled(!m_offlineMaintenanceTool);
+ m_removeAllComponents->setChecked(m_offlineMaintenanceTool);
+ }
}
// -- private
@@ -1851,7 +1943,10 @@ void IntroductionPage::entering()
showMaintenanceTools();
setMaintenanceToolsEnabled(true);
}
- setSettingsButtonRequested((!core->isOfflineOnly()) && (!core->isUninstaller()));
+ if (m_forceUpdate)
+ m_packageManager->setEnabled(false);
+
+ setSettingsButtonRequested((!core->isOfflineOnly()));
}
/*!
@@ -1944,6 +2039,7 @@ LicenseAgreementPage::LicenseAgreementPage(PackageManagerCore *core)
m_textBrowser->setReadOnly(true);
m_textBrowser->setOpenLinks(false);
m_textBrowser->setOpenExternalLinks(true);
+ m_textBrowser->setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont));
m_textBrowser->setObjectName(QLatin1String("LicenseTextBrowser"));
connect(m_textBrowser, &QTextBrowser::anchorClicked, this, &LicenseAgreementPage::openLicenseUrl);
@@ -1959,7 +2055,7 @@ LicenseAgreementPage::LicenseAgreementPage(PackageManagerCore *core)
layout->addWidget(licenseSplitter);
m_acceptCheckBox = new QCheckBox(this);
- m_acceptCheckBox->setShortcut(QKeySequence(tr("Alt+A", "agree license")));
+ m_acceptCheckBox->setShortcut(QKeySequence(tr("Alt+A", "Agree license")));
m_acceptCheckBox->setObjectName(QLatin1String("AcceptLicenseCheckBox"));
ClickForwarder *acceptClickForwarder = new ClickForwarder(m_acceptCheckBox);
@@ -1988,7 +2084,6 @@ void LicenseAgreementPage::entering()
m_textBrowser->setHtml(QString());
m_licenseListWidget->setVisible(false);
- packageManagerCore()->calculateComponentsToInstall();
foreach (QInstaller::Component *component, packageManagerCore()->orderedComponentsToInstall())
packageManagerCore()->addLicenseItem(component->licenses());
@@ -2011,7 +2106,7 @@ void LicenseAgreementPage::entering()
*/
bool LicenseAgreementPage::isComplete() const
{
- return m_acceptCheckBox->isChecked();
+ return m_acceptCheckBox->isChecked() && ProductKeyCheck::instance()->hasAcceptedAllLicenses();
}
void LicenseAgreementPage::openLicenseUrl(const QUrl &url)
@@ -2104,7 +2199,7 @@ void ComponentSelectionPage::entering()
QT_TR_NOOP("Please select the components you want to update."),
QT_TR_NOOP("Please select the components you want to install."),
QT_TR_NOOP("Please select the components you want to uninstall."),
- QT_TR_NOOP("Select the components to install. Deselect installed components to uninstall them. Any components already installed will not be updated."),
+ QT_TR_NOOP("Select the components to install. Deselect installed components to uninstall them.<br>Any components already installed will not be updated."),
QT_TR_NOOP("Mandatory components need to be updated first before you can select other components to update.")
};
@@ -2119,18 +2214,16 @@ void ComponentSelectionPage::entering()
d->updateTreeView();
// check component model state so we can enable needed component selection buttons
- if (core->isUpdater())
- d->onModelStateChanged(d->m_currentModel->checkedState());
+ d->onModelStateChanged(d->m_currentModel->checkedState());
setModified(isComplete());
- if (core->settings().repositoryCategories().count() > 0 && !core->isOfflineOnly()
- && !core->isUpdater()) {
- d->showCategoryLayout(true);
- core->settings().setAllowUnstableComponents(true);
- } else {
- d->showCategoryLayout(false);
- }
+ d->showCategoryLayout(core->showRepositoryCategories());
d->showCompressedRepositoryButton();
+ d->showCreateOfflineInstallerButton(true);
+
+ // Reset to default supplement state. The page may set it to OfflineGenerator
+ // which needs to be reset after navigating back to the page.
+ core->resetBinaryMarkerSupplement();
}
/*!
@@ -2140,6 +2233,7 @@ void ComponentSelectionPage::entering()
void ComponentSelectionPage::leaving()
{
d->hideCompressedRepositoryButton();
+ d->showCreateOfflineInstallerButton(false);
}
/*!
@@ -2158,6 +2252,29 @@ void ComponentSelectionPage::showEvent(QShowEvent *event)
}
/*!
+ Called when \c ComponentSelectionPage is validated.
+ Tries to load \c component scripts for components about to be installed.
+ Returns \c true if the script loading succeeded and the next page is shown.
+*/
+bool ComponentSelectionPage::validatePage()
+{
+ PackageManagerCore *core = packageManagerCore();
+ try {
+ core->loadComponentScripts(core->orderedComponentsToInstall(), true);
+ } catch (const Error &error) {
+ // As component script loading failed, there is error in the script and component is
+ // marked as unselected. Recalculate so that unselected component is removed from install.
+ // User is then able to select other components for install.
+ core->clearComponentsToInstallCalculated();
+ core->calculateComponentsToInstall();
+ MessageBoxHandler::critical(MessageBoxHandler::currentBestSuitParent(), QLatin1String("Error"),
+ tr("Error"), error.message());
+ return false;
+ }
+ return true;
+}
+
+/*!
Selects all components in the component tree.
*/
void ComponentSelectionPage::selectAll()
@@ -2200,16 +2317,6 @@ void ComponentSelectionPage::deselectComponent(const QString &id)
}
/*!
- Adds the possibility to install a compressed repository on component selection
- page. A new button which opens a file browser is added for compressed
- repository selection.
-*/
-void ComponentSelectionPage::allowCompressedRepositoryInstall()
-{
- d->allowCompressedRepositoryInstall();
-}
-
-/*!
Adds an additional virtual component with the \a name to be installed.
Returns \c true if the virtual component is found and not installed.
@@ -2222,13 +2329,18 @@ bool ComponentSelectionPage::addVirtualComponentToUninstall(const QString &name)
name, allComponents);
if (component && component->isInstalled() && component->isVirtual()) {
component->setCheckState(Qt::Unchecked);
- core->componentsToInstallNeedsRecalculation();
+ core->recalculateAllComponents();
qCDebug(QInstaller::lcDeveloperBuild) << "Virtual component " << name << " was selected for uninstall by script.";
return true;
}
return false;
}
+void ComponentSelectionPage::setAllowCreateOfflineInstaller(bool allow)
+{
+ d->setAllowCreateOfflineInstaller(allow);
+}
+
void ComponentSelectionPage::setModified(bool modified)
{
setComplete(modified);
@@ -2239,9 +2351,10 @@ void ComponentSelectionPage::setModified(bool modified)
*/
bool ComponentSelectionPage::isComplete() const
{
- if (packageManagerCore()->isInstaller() || packageManagerCore()->isUpdater())
- return d->m_currentModel->checked().count();
- return d->m_currentModel->checkedState().testFlag(ComponentModel::DefaultChecked) == false;
+ if (!d->componentsResolved())
+ return false;
+
+ return d->m_currentModel->componentsSelected();
}
@@ -2303,7 +2416,7 @@ TargetDirectoryPage::TargetDirectoryPage(PackageManagerCore *core)
QPushButton *browseButton = new QPushButton(this);
browseButton->setObjectName(QLatin1String("BrowseDirectoryButton"));
connect(browseButton, &QAbstractButton::clicked, this, &TargetDirectoryPage::dirRequested);
- browseButton->setShortcut(QKeySequence(tr("Alt+R", "browse file system to choose a file")));
+ browseButton->setShortcut(QKeySequence(tr("Alt+R", "Browse file system to choose a file")));
browseButton->setText(tr("B&rowse..."));
browseButton->setToolTip(TargetDirectoryPage::tr("Browse file system to choose the installation directory."));
hlayout->addWidget(browseButton);
@@ -2378,7 +2491,7 @@ bool TargetDirectoryPage::validatePage()
if (!QVariant(remove).toBool())
return true;
- return this->packageManagerCore()->checkTargetDir(targetDir());
+ return this->packageManagerCore()->installationAllowedToDirectory(targetDir());
}
/*!
@@ -2567,7 +2680,7 @@ void ReadyForInstallationPage::entering()
m_taskDetailsBrowser->setVisible(false);
setButtonText(QWizard::CommitButton, tr("U&ninstall"));
setColoredTitle(tr("Ready to Uninstall"));
- m_msgLabel->setText(tr("Setup is now ready to begin removing %1 from your computer.<br>"
+ m_msgLabel->setText(tr("All required information is now available to begin removing %1 from your computer.<br>"
"<font color=\"red\">The program directory %2 will be deleted completely</font>, "
"including all content in that directory!")
.arg(productName(),
@@ -2578,26 +2691,31 @@ void ReadyForInstallationPage::entering()
} else if (packageManagerCore()->isMaintainer()) {
setButtonText(QWizard::CommitButton, tr("U&pdate"));
setColoredTitle(tr("Ready to Update Packages"));
- m_msgLabel->setText(tr("Setup is now ready to begin updating your installation."));
+ m_msgLabel->setText(tr("All required information is now available to begin updating your installation."));
+ } else if (packageManagerCore()->isOfflineGenerator()) {
+ setButtonText(QWizard::CommitButton, tr("Create Offline Installer"));
+ setColoredTitle(tr("Ready to Create Offline Installer"));
+ m_msgLabel->setText(tr("All required information is now available to create an offline installer for selected components."));
} else {
Q_ASSERT(packageManagerCore()->isInstaller());
setButtonText(QWizard::CommitButton, tr("&Install"));
setColoredTitle(tr("Ready to Install"));
- m_msgLabel->setText(tr("Setup is now ready to begin installing %1 on your computer.")
+ m_msgLabel->setText(tr("All required information is now available to begin installing %1 on your computer.")
.arg(productName()));
}
- QString htmlOutput;
- bool componentsOk = packageManagerCore()->calculateComponents(&htmlOutput);
+ bool componentsOk = packageManagerCore()->recalculateAllComponents();
+ const QString htmlOutput = packageManagerCore()->componentResolveReasons();
+
+ qCDebug(QInstaller::lcInstallerInstallLog).noquote() << htmlToString(htmlOutput);
m_taskDetailsBrowser->setHtml(htmlOutput);
m_taskDetailsBrowser->setVisible(!componentsOk || LoggingHandler::instance().isVerbose());
setComplete(componentsOk);
- QString spaceInfo;
- if (packageManagerCore()->checkAvailableSpace(spaceInfo)) {
- m_msgLabel->setText(QString::fromLatin1("%1 %2").arg(m_msgLabel->text(), spaceInfo));
+ if (packageManagerCore()->checkAvailableSpace()) {
+ m_msgLabel->setText(QString::fromLatin1("%1 %2").arg(m_msgLabel->text(), packageManagerCore()->availableSpaceMessage()));
} else {
- m_msgLabel->setText(spaceInfo);
+ m_msgLabel->setText(packageManagerCore()->availableSpaceMessage());
setComplete(false);
}
}
@@ -2617,7 +2735,9 @@ void ReadyForInstallationPage::leaving()
void ReadyForInstallationPage::updatePageListTitle()
{
PackageManagerCore *core = packageManagerCore();
- if (core->isInstaller())
+ if (core->isOfflineGenerator())
+ setPageListTitle(tr("Ready to Create Offline Installer"));
+ else if (core->isInstaller())
setPageListTitle(tr("Ready to Install"));
else if (core->isMaintainer())
setPageListTitle(tr("Ready to Update"));
@@ -2654,7 +2774,7 @@ void ReadyForInstallationPage::updatePageListTitle()
*/
PerformInstallationPage::PerformInstallationPage(PackageManagerCore *core)
: PackageManagerPage(core)
- , m_performInstallationForm(new PerformInstallationForm(this))
+ , m_performInstallationForm(new PerformInstallationForm(core, this))
{
setPixmap(QWizard::WatermarkPixmap, QPixmap());
setObjectName(QLatin1String("PerformInstallationPage"));
@@ -2675,6 +2795,11 @@ PerformInstallationPage::PerformInstallationPage(PackageManagerCore *core)
connect(core, &PackageManagerCore::installationFinished,
this, &PerformInstallationPage::installationFinished);
+ connect(core, &PackageManagerCore::offlineGenerationStarted,
+ this, &PerformInstallationPage::installationStarted);
+ connect(core, &PackageManagerCore::offlineGenerationFinished,
+ this, &PerformInstallationPage::installationFinished);
+
connect(core, &PackageManagerCore::uninstallationStarted,
this, &PerformInstallationPage::uninstallationStarted);
connect(core, &PackageManagerCore::uninstallationFinished,
@@ -2744,6 +2869,11 @@ void PerformInstallationPage::entering()
setColoredTitle(tr("Updating components of %1").arg(productName()));
QTimer::singleShot(30, packageManagerCore(), SLOT(runPackageUpdater()));
+ } else if (packageManagerCore()->isOfflineGenerator()) {
+ setButtonText(QWizard::CommitButton, tr("&Create Offline Installer"));
+ setColoredTitle(tr("Creating Offline Installer for %1").arg(productName()));
+
+ QTimer::singleShot(30, packageManagerCore(), SLOT(runOfflineGenerator()));
} else {
setButtonText(QWizard::CommitButton, tr("&Install"));
setColoredTitle(tr("Installing %1").arg(productName()));
@@ -2768,7 +2898,9 @@ void PerformInstallationPage::leaving()
void PerformInstallationPage::updatePageListTitle()
{
PackageManagerCore *core = packageManagerCore();
- if (core->isInstaller())
+ if (core->isOfflineGenerator())
+ setPageListTitle(tr("Creating Offline Installer"));
+ else if (core->isInstaller())
setPageListTitle(tr("Installing"));
else if (core->isMaintainer())
setPageListTitle(tr("Updating"));
@@ -2792,17 +2924,26 @@ void PerformInstallationPage::setTitleMessage(const QString &title)
*/
void PerformInstallationPage::changeCurrentImage()
{
- const QStringList productImages = packageManagerCore()->settings().productImages();
+ const QMap<QString, QVariant> productImages = packageManagerCore()->settings().productImages();
if (productImages.isEmpty())
return;
- const QString nextImage = (m_currentImage.isEmpty() || m_currentImage == productImages.last())
- ? productImages.first()
- : productImages.at(productImages.indexOf(m_currentImage) + 1);
+ QString nextImage;
+ QString nextUrl;
+ if (m_currentImage.isEmpty() || m_currentImage == productImages.lastKey()) {
+ nextImage = productImages.firstKey();
+ nextUrl = productImages.value(nextImage).toString();
+ } else {
+ QMap<QString, QVariant>::const_iterator i = productImages.constFind(m_currentImage);
+ if (++i != productImages.end()) {
+ nextImage = i.key();
+ nextUrl = i.value().toString();
+ }
+ }
// Do not update the pixmap if there was only one image available
if (nextImage != m_currentImage) {
- m_performInstallationForm->setImageFromFileName(nextImage);
+ m_performInstallationForm->setImageFromFileName(nextImage, nextUrl);
m_currentImage = nextImage;
}
}
@@ -2863,7 +3004,7 @@ FinishedPage::FinishedPage(PackageManagerCore *core)
, m_commitButton(nullptr)
{
setObjectName(QLatin1String("FinishedPage"));
- setColoredTitle(tr("Completing the %1 Wizard").arg(productName()));
+ setColoredTitle(tr("Finished the %1 Setup").arg(productName()));
setPageListTitle(tr("Finished"));
m_msgLabel = new QLabel(this);
@@ -2888,7 +3029,7 @@ FinishedPage::FinishedPage(PackageManagerCore *core)
*/
void FinishedPage::entering()
{
- m_msgLabel->setText(tr("Click %1 to exit the %2 Wizard.")
+ m_msgLabel->setText(tr("Click %1 to exit the %2 Setup.")
.arg(gui()->defaultButtonText(QWizard::FinishButton).remove(QLatin1Char('&')))
.arg(productName()));
@@ -2935,7 +3076,8 @@ void FinishedPage::entering()
connect(m_commitButton, &QAbstractButton::clicked, this, &FinishedPage::handleFinishClicked);
}
- if (packageManagerCore()->status() == PackageManagerCore::Success) {
+ if (packageManagerCore()->status() == PackageManagerCore::Success
+ || packageManagerCore()->status() == PackageManagerCore::EssentialUpdated) {
const QString finishedText = packageManagerCore()->value(QLatin1String("FinishedText"));
if (!finishedText.isEmpty())
m_msgLabel->setText(finishedText);
@@ -2949,7 +3091,7 @@ void FinishedPage::entering()
}
} else {
// TODO: how to handle this using the config.xml
- setColoredTitle(tr("The %1 Wizard failed.").arg(productName()));
+ setColoredTitle(tr("The %1 Setup failed.").arg(productName()));
}
m_runItCheckBox->hide();
@@ -2980,16 +3122,8 @@ void FinishedPage::leaving()
*/
void FinishedPage::handleFinishClicked()
{
- const QString program =
- packageManagerCore()->replaceVariables(packageManagerCore()->value(scRunProgram));
-
- const QStringList args = packageManagerCore()->replaceVariables(packageManagerCore()
- ->values(scRunProgramArguments));
- if (!m_runItCheckBox->isChecked() || program.isEmpty())
- return;
-
- qCDebug(QInstaller::lcInstallerInstallLog) << "starting" << program << args;
- QProcess::startDetached(program, args);
+ if (m_runItCheckBox->isChecked())
+ packageManagerCore()->runProgram();
}
/*!
@@ -3034,7 +3168,7 @@ RestartPage::RestartPage(PackageManagerCore *core)
: PackageManagerPage(core)
{
setObjectName(QLatin1String("RestartPage"));
- setColoredTitle(tr("Completing the %1 Setup Wizard").arg(productName()));
+ setColoredTitle(tr("Finished the %1 Setup").arg(productName()));
// Never show this page on the page list
setShowOnPageList(false);