From 3053efe754bfac6f0d7faa07bbcece3ebfd30270 Mon Sep 17 00:00:00 2001 From: Katja Marttila Date: Mon, 22 Oct 2018 14:10:15 +0300 Subject: Refactor component selection page Component selection page has a lot of widgets compared to other pages so moved the implementation to own file. Also fixed the following issues in component selection page: 1. Fixed crash when there were no categories and QBsp button was pressed 2. QBsp button opened multiple dialogs if next/back buttons were pressed 3. Made progressbar use the entire vertical space Change-Id: I30cf1599ecb06a633719622427855a57696d5987 Reviewed-by: Jani Heikkinen --- src/libs/installer/componentselectionpage_p.cpp | 454 ++++++++++++++++++++++++ src/libs/installer/componentselectionpage_p.h | 108 ++++++ src/libs/installer/installer.pro | 6 +- src/libs/installer/packagemanagergui.cpp | 451 +---------------------- src/libs/installer/packagemanagergui.h | 6 +- 5 files changed, 573 insertions(+), 452 deletions(-) create mode 100644 src/libs/installer/componentselectionpage_p.cpp create mode 100644 src/libs/installer/componentselectionpage_p.h diff --git a/src/libs/installer/componentselectionpage_p.cpp b/src/libs/installer/componentselectionpage_p.cpp new file mode 100644 index 000000000..22c478beb --- /dev/null +++ b/src/libs/installer/componentselectionpage_p.cpp @@ -0,0 +1,454 @@ +/************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Installer Framework. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +**************************************************************************/ + +#include "componentselectionpage_p.h" + +#include "packagemanagergui.h" +#include "componentmodel.h" +#include "settings.h" +#include "component.h" +#include "fileutils.h" +#include "messageboxhandler.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace QInstaller { + +ComponentSelectionPagePrivate::ComponentSelectionPagePrivate(ComponentSelectionPage *qq, PackageManagerCore *core) + : q(qq) + , m_core(core) + , m_treeView(new QTreeView(q)) + , m_allModel(m_core->defaultComponentModel()) + , m_updaterModel(m_core->updaterComponentModel()) + , m_currentModel(m_allModel) + , m_allowCompressedRepositoryInstall(false) + , m_categoryWidget(Q_NULLPTR) +{ + m_treeView->setObjectName(QLatin1String("ComponentsTreeView")); + + connect(m_allModel, SIGNAL(checkStateChanged(QInstaller::ComponentModel::ModelState)), this, + SLOT(onModelStateChanged(QInstaller::ComponentModel::ModelState))); + connect(m_updaterModel, SIGNAL(checkStateChanged(QInstaller::ComponentModel::ModelState)), + this, SLOT(onModelStateChanged(QInstaller::ComponentModel::ModelState))); + + m_descriptionVLayout = new QVBoxLayout; + m_descriptionVLayout->setObjectName(QLatin1String("DescriptionLayout")); + + m_descriptionLabel = new QLabel(q); + m_descriptionLabel->setWordWrap(true); + m_descriptionLabel->setObjectName(QLatin1String("ComponentDescriptionLabel")); + m_descriptionVLayout->addWidget(m_descriptionLabel); + + m_sizeLabel = new QLabel(q); + m_sizeLabel->setWordWrap(true); + m_sizeLabel->setObjectName(QLatin1String("ComponentSizeLabel")); + m_descriptionVLayout->addWidget(m_sizeLabel); + m_descriptionVLayout->addSpacerItem(new QSpacerItem(1, 1, QSizePolicy::MinimumExpanding, + QSizePolicy::MinimumExpanding)); + + m_treeViewVLayout = new QVBoxLayout; + m_treeViewVLayout->setObjectName(QLatin1String("TreeviewLayout")); + + QHBoxLayout *buttonHLayout = new QHBoxLayout; + m_checkDefault = new QPushButton; + connect(m_checkDefault, &QAbstractButton::clicked, + this, &ComponentSelectionPagePrivate::selectDefault); + if (m_core->isInstaller()) { + m_checkDefault->setObjectName(QLatin1String("SelectDefaultComponentsButton")); + m_checkDefault->setShortcut(QKeySequence(ComponentSelectionPage::tr("Alt+A", + "select default components"))); + m_checkDefault->setText(ComponentSelectionPage::tr("Def&ault")); + } else { + m_checkDefault->setEnabled(false); + m_checkDefault->setObjectName(QLatin1String("ResetComponentsButton")); + m_checkDefault->setShortcut(QKeySequence(ComponentSelectionPage::tr("Alt+R", + "reset to already installed components"))); + m_checkDefault->setText(ComponentSelectionPage::tr("&Reset")); + } + buttonHLayout->addWidget(m_checkDefault); + + m_checkAll = new QPushButton; + connect(m_checkAll, &QAbstractButton::clicked, + this, &ComponentSelectionPagePrivate::selectAll); + m_checkAll->setObjectName(QLatin1String("SelectAllComponentsButton")); + m_checkAll->setShortcut(QKeySequence(ComponentSelectionPage::tr("Alt+S", + "select all components"))); + m_checkAll->setText(ComponentSelectionPage::tr("&Select All")); + buttonHLayout->addWidget(m_checkAll); + + m_uncheckAll = new QPushButton; + connect(m_uncheckAll, &QAbstractButton::clicked, + this, &ComponentSelectionPagePrivate::deselectAll); + m_uncheckAll->setObjectName(QLatin1String("DeselectAllComponentsButton")); + m_uncheckAll->setShortcut(QKeySequence(ComponentSelectionPage::tr("Alt+D", + "deselect all components"))); + m_uncheckAll->setText(ComponentSelectionPage::tr("&Deselect All")); + buttonHLayout->addWidget(m_uncheckAll); + + m_treeViewVLayout->addLayout(buttonHLayout); + + m_metadataProgressLabel = new QLabel(); + m_metadataProgressLabel->hide(); + m_treeViewVLayout->addWidget(m_metadataProgressLabel); + + m_progressBar = new QProgressBar(); + m_progressBar->setRange(0, 0); + m_progressBar->hide(); + m_progressBar->setObjectName(QLatin1String("CompressedInstallProgressBar")); + m_treeViewVLayout->addWidget(m_progressBar); + + connect(m_core, SIGNAL(metaJobProgress(int)), this, SLOT(onProgressChanged(int))); + connect(m_core, SIGNAL(metaJobInfoMessage(QString)), this, SLOT(setMessage(QString))); + connect(m_core, &PackageManagerCore::metaJobTotalProgress, this, + &ComponentSelectionPagePrivate::setTotalProgress); + + m_treeViewVLayout->addWidget(m_treeView, 3); + + m_mainHLayout = new QHBoxLayout(q); + m_mainHLayout->addLayout(m_treeViewVLayout, 3); + m_mainHLayout->addLayout(m_descriptionVLayout, 2); + +#ifdef INSTALLCOMPRESSED + allowCompressedRepositoryInstall(); +#endif +} + +ComponentSelectionPagePrivate::~ComponentSelectionPagePrivate() +{ + +} + +void ComponentSelectionPagePrivate::allowCompressedRepositoryInstall() +{ + m_allowCompressedRepositoryInstall = true; +} + +void ComponentSelectionPagePrivate::showCompressedRepositoryButton() +{ + QWizard *wizard = qobject_cast(m_core->guiObject()); + if (wizard && !(wizard->options() & QWizard::HaveCustomButton2) && m_allowCompressedRepositoryInstall) { + wizard->setOption(QWizard::HaveCustomButton2, true); + wizard->setButtonText(QWizard::CustomButton2, + ComponentSelectionPage::tr("&Browse QBSP files")); + connect(wizard, &QWizard::customButtonClicked, + this, &ComponentSelectionPagePrivate::customButtonClicked); + q->gui()->updateButtonLayout(); + } +} + +void ComponentSelectionPagePrivate::hideCompressedRepositoryButton() +{ + QWizard *wizard = qobject_cast(m_core->guiObject()); + if (wizard && (wizard->options() & QWizard::HaveCustomButton2)) { + wizard->setOption(QWizard::HaveCustomButton2, false); + disconnect(wizard, &QWizard::customButtonClicked, + this, &ComponentSelectionPagePrivate::customButtonClicked); + q->gui()->updateButtonLayout(); + } +} + +void ComponentSelectionPagePrivate::setupCategoryLayout() +{ + if (m_categoryWidget) + return; + m_categoryWidget = new QWidget(); + QVBoxLayout *vLayout = new QVBoxLayout; + m_categoryWidget->setLayout(vLayout); + m_categoryGroupBox = new QGroupBox(q); + m_categoryGroupBox->setTitle(m_core->settings().repositoryCategoryDisplayName()); + m_categoryGroupBox->setObjectName(QLatin1String("CategoryGroupBox")); + QVBoxLayout *categoryLayout = new QVBoxLayout(m_categoryGroupBox); + QPushButton *fetchCategoryButton = new QPushButton(tr("Fetch")); + fetchCategoryButton->setObjectName(QLatin1String("FetchCategoryButton")); + connect(fetchCategoryButton, &QPushButton::clicked, this, + &ComponentSelectionPagePrivate::fetchRepositoryCategories); + + foreach (RepositoryCategory repository, m_core->settings().repositoryCategories()) { + QCheckBox *checkBox = new QCheckBox; + checkBox->setObjectName(repository.displayname()); + connect(checkBox, &QCheckBox::stateChanged, this, + &ComponentSelectionPagePrivate::checkboxStateChanged); + checkBox->setText(repository.displayname()); + categoryLayout->addWidget(checkBox); + } + + vLayout->addWidget(m_categoryGroupBox); + vLayout->addWidget(fetchCategoryButton); + vLayout->addStretch(); + m_mainHLayout->insertWidget(0, m_categoryWidget); +} + +void ComponentSelectionPagePrivate::updateTreeView() +{ + m_checkDefault->setVisible(m_core->isInstaller() || m_core->isPackageManager()); + if (m_treeView->selectionModel()) { + disconnect(m_treeView->selectionModel(), &QItemSelectionModel::currentChanged, + this, &ComponentSelectionPagePrivate::currentSelectedChanged); + } + + m_currentModel = m_core->isUpdater() ? m_updaterModel : m_allModel; + m_treeView->setModel(m_currentModel); + m_treeView->setExpanded(m_currentModel->index(0, 0), true); + foreach (Component *component, m_core->components(PackageManagerCore::ComponentType::All)) { + if (component->isExpandedByDefault()) { + const QModelIndex index = m_currentModel->indexFromComponentName(component->name()); + m_treeView->setExpanded(index, true); + } + } + + const bool installActionColumnVisible = m_core->settings().installActionColumnVisible(); + if (!installActionColumnVisible) + m_treeView->hideColumn(ComponentModelHelper::ActionColumn); + + m_treeView->header()->setSectionResizeMode( + ComponentModelHelper::NameColumn, QHeaderView::ResizeToContents); + if (m_core->isInstaller()) { + m_treeView->setHeaderHidden(true); + 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); + } + + 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(), &QItemSelectionModel::currentChanged, + this, &ComponentSelectionPagePrivate::currentSelectedChanged); + + m_treeView->setCurrentIndex(m_currentModel->index(0, 0)); +} + +void ComponentSelectionPagePrivate::currentSelectedChanged(const QModelIndex ¤t) +{ + if (!current.isValid()) + return; + + m_sizeLabel->setText(QString()); + m_descriptionLabel->setText(m_currentModel->data(m_currentModel->index(current.row(), + ComponentModelHelper::NameColumn, current.parent()), Qt::ToolTipRole).toString()); + + Component *component = m_currentModel->componentFromIndex(current); + if ((m_core->isUninstaller()) || (!component)) + return; + + if (component->isSelected() && (component->value(scUncompressedSizeSum).toLongLong() > 0)) { + m_sizeLabel->setText(ComponentSelectionPage::tr("This component " + "will occupy approximately %1 on your hard disk drive.") + .arg(humanReadableSize(component->value(scUncompressedSizeSum).toLongLong()))); + } +} + +void ComponentSelectionPagePrivate::selectAll() +{ + m_currentModel->setCheckedState(ComponentModel::AllChecked); +} + +void ComponentSelectionPagePrivate::deselectAll() +{ + m_currentModel->setCheckedState(ComponentModel::AllUnchecked); +} + +void ComponentSelectionPagePrivate::checkboxStateChanged() +{ + QList checkboxes = m_categoryGroupBox->findChildren(); + bool enableFetchButton = false; + foreach (QCheckBox *checkbox, checkboxes) { + if (checkbox->isChecked()) { + enableFetchButton = true; + break; + } + } +} + +void ComponentSelectionPagePrivate::enableRepositoryCategory(int index, bool enable) { + RepositoryCategory repoCategory = m_core->settings().repositoryCategories().toList().at(index); + RepositoryCategory replacement = repoCategory; + replacement.setEnabled(enable); + QSet tmpRepoCategories = m_core->settings().repositoryCategories(); + if (tmpRepoCategories.contains(repoCategory)) { + tmpRepoCategories.remove(repoCategory); + tmpRepoCategories.insert(replacement); + m_core->settings().addRepositoryCategories(tmpRepoCategories); + } +} + +void ComponentSelectionPagePrivate::updateWidgetVisibility(bool show) +{ + if (show) { + QSpacerItem *verticalSpacer2 = new QSpacerItem(0, 0, QSizePolicy::Minimum, + QSizePolicy::Expanding); + m_treeViewVLayout->addSpacerItem(verticalSpacer2); + m_mainHLayout->removeItem(m_descriptionVLayout); + } else { + QSpacerItem *item = m_treeViewVLayout->spacerItem(); + m_treeViewVLayout->removeItem(item); + m_mainHLayout->addLayout(m_descriptionVLayout, 2); + } + if (m_categoryWidget) + m_categoryWidget->setDisabled(show); + m_progressBar->setVisible(show); + m_metadataProgressLabel->setVisible(show); + + m_treeView->setVisible(!show); + m_checkDefault->setVisible(!show); + m_checkAll->setVisible(!show); + m_uncheckAll->setVisible(!show); + m_descriptionLabel->setVisible(!show); + m_sizeLabel->setVisible(!show); + QPushButton *const b = qobject_cast(q->gui()->button(QWizard::NextButton)); + b->setEnabled(!show); + + if (QAbstractButton *bspButton = q->gui()->button(QWizard::CustomButton2)) + bspButton->setEnabled(!show); +} + +void ComponentSelectionPagePrivate::fetchRepositoryCategories() +{ + updateWidgetVisibility(true); + + QCheckBox *checkbox; + QList checkboxes = m_categoryGroupBox->findChildren(); + for (int i = 0; i < checkboxes.count(); i++) { + checkbox = checkboxes.at(i); + enableRepositoryCategory(i, checkbox->isChecked()); + } + + if (!m_core->fetchRemotePackagesTree()) { + MessageBoxHandler::critical(MessageBoxHandler::currentBestSuitParent(), + QLatin1String("FailToFetchPackages"), tr("Error"), m_core->error()); + } + updateWidgetVisibility(false); +} + +void ComponentSelectionPagePrivate::customButtonClicked(int which) +{ + if (QWizard::WizardButton(which) == QWizard::CustomButton2) { + QString defaultDownloadDirectory = + QStandardPaths::writableLocation(QStandardPaths::DownloadLocation); + QStringList fileNames = QFileDialog::getOpenFileNames(NULL, + ComponentSelectionPage::tr("Open File"),defaultDownloadDirectory, + QLatin1String("QBSP or 7z Files (*.qbsp *.7z)")); + + QSet set; + foreach (QString fileName, fileNames) { + Repository repository = Repository::fromUserInput(fileName, true); + repository.setEnabled(true); + set.insert(repository); + } + if (set.count() > 0) { + updateWidgetVisibility(true); + m_core->settings().addTemporaryRepositories(set, false); + if (!m_core->fetchCompressedPackagesTree()) { + MessageBoxHandler::critical(MessageBoxHandler::currentBestSuitParent(), + QLatin1String("FailToFetchPackages"), tr("Error"), m_core->error()); + } + } + updateWidgetVisibility(false); + } +} + +/*! + Updates the value of \a progress on the progress bar. +*/ +void ComponentSelectionPagePrivate::onProgressChanged(int progress) +{ + m_progressBar->setValue(progress); +} + +/*! + Displays the message \a msg on the page. +*/ +void ComponentSelectionPagePrivate::setMessage(const QString &msg) +{ + QWizardPage *page = q->gui()->currentPage(); + if (m_metadataProgressLabel && page && page->objectName() == QLatin1String("ComponentSelectionPage")) + m_metadataProgressLabel->setText(msg); +} + +void ComponentSelectionPagePrivate::setTotalProgress(int totalProgress) +{ + if (m_progressBar) + m_progressBar->setRange(0, totalProgress); +} + +void ComponentSelectionPagePrivate::selectDefault() +{ + m_currentModel->setCheckedState(ComponentModel::DefaultChecked); +} + +void ComponentSelectionPagePrivate::onModelStateChanged(QInstaller::ComponentModel::ModelState state) +{ + q->setModified(state.testFlag(ComponentModel::DefaultChecked) == false); + // If all components in the checked list are only checkable when run without forced + // installation, set ComponentModel::AllUnchecked as well, as we cannot uncheck anything. + // Helps to keep the UI correct. + if ((!m_core->noForceInstallation()) + && (m_currentModel->checked() == m_currentModel->uncheckable())) { + state |= ComponentModel::AllUnchecked; + } + // enable the button if the corresponding flag is not set + m_checkAll->setEnabled(state.testFlag(ComponentModel::AllChecked) == false); + m_uncheckAll->setEnabled(state.testFlag(ComponentModel::AllUnchecked) == false); + m_checkDefault->setEnabled(state.testFlag(ComponentModel::DefaultChecked) == false); + + // update the current selected node (important to reflect possible sub-node changes) + if (m_treeView->selectionModel()) + currentSelectedChanged(m_treeView->selectionModel()->currentIndex()); +} + +} // namespace QInstaller diff --git a/src/libs/installer/componentselectionpage_p.h b/src/libs/installer/componentselectionpage_p.h new file mode 100644 index 000000000..bc1e6ed7a --- /dev/null +++ b/src/libs/installer/componentselectionpage_p.h @@ -0,0 +1,108 @@ +/************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Installer Framework. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +**************************************************************************/ + +#ifndef COMPONENTSELECTIONPAGE_P_H +#define COMPONENTSELECTIONPAGE_P_H + +#include +#include + +#include "componentmodel.h" +#include "packagemanagergui.h" + +class QTreeView; +class QLabel; +class QPushButton; +class QGroupBox; +class QListWidgetItem; +class QProgressBar; +class QVBoxLayout; +class QHBoxLayout; + +namespace QInstaller { + +class PackageManagerCore; +class ComponentModel; +class ComponentSelectionPage; + +class ComponentSelectionPagePrivate : public QObject +{ + Q_OBJECT + friend class ComponentSelectionPage; + Q_DISABLE_COPY(ComponentSelectionPagePrivate) + +public: + explicit ComponentSelectionPagePrivate(ComponentSelectionPage *qq, PackageManagerCore *core); + ~ComponentSelectionPagePrivate(); + + void allowCompressedRepositoryInstall(); + void showCompressedRepositoryButton(); + void hideCompressedRepositoryButton(); + void setupCategoryLayout(); + void updateTreeView(); + +public slots: + void currentSelectedChanged(const QModelIndex ¤t); + void selectAll(); + void deselectAll(); + void checkboxStateChanged(); + void enableRepositoryCategory(int index, bool enable); + void updateWidgetVisibility(bool show); + void fetchRepositoryCategories(); + void customButtonClicked(int which); + void onProgressChanged(int progress); + void setMessage(const QString &msg); + void setTotalProgress(int totalProgress); + void selectDefault(); + void onModelStateChanged(QInstaller::ComponentModel::ModelState state); + +private: + ComponentSelectionPage *q; + PackageManagerCore *m_core; + QTreeView *m_treeView; + QLabel *m_sizeLabel; + QLabel *m_descriptionLabel; + QVBoxLayout *m_descriptionVLayout; + QPushButton *m_checkAll; + QPushButton *m_uncheckAll; + QPushButton *m_checkDefault; + QWidget *m_categoryWidget; + QGroupBox *m_categoryGroupBox; + QLabel *m_metadataProgressLabel; + QProgressBar *m_progressBar; + QHBoxLayout *m_mainHLayout; + QVBoxLayout *m_treeViewVLayout; + bool m_allowCompressedRepositoryInstall; + ComponentModel *m_allModel; + ComponentModel *m_updaterModel; + ComponentModel *m_currentModel; +}; + +} // namespace QInstaller + +#endif // COMPONENTSELECTIONPAGE_P_H diff --git a/src/libs/installer/installer.pro b/src/libs/installer/installer.pro index bdca7e0f3..a6dfbde50 100644 --- a/src/libs/installer/installer.pro +++ b/src/libs/installer/installer.pro @@ -132,7 +132,8 @@ HEADERS += packagemanagercore.h \ lib7z_create.h \ lib7z_extract.h \ lib7z_list.h \ - repositorycategory.h + repositorycategory.h \ + componentselectionpage_p.h SOURCES += packagemanagercore.cpp \ packagemanagercore_p.cpp \ @@ -208,7 +209,8 @@ SOURCES += packagemanagercore.cpp \ keepaliveobject.cpp \ systeminfo.cpp \ packagesource.cpp \ - repositorycategory.cpp + repositorycategory.cpp \ + componentselectionpage_p.cpp FORMS += proxycredentialsdialog.ui \ serverauthenticationdialog.ui diff --git a/src/libs/installer/packagemanagergui.cpp b/src/libs/installer/packagemanagergui.cpp index 8961e3a19..a7a0aa45e 100644 --- a/src/libs/installer/packagemanagergui.cpp +++ b/src/libs/installer/packagemanagergui.cpp @@ -40,6 +40,7 @@ #include "scriptengine.h" #include "productkeycheck.h" #include "repositorycategory.h" +#include "componentselectionpage_p.h" #include "sysinfo.h" @@ -57,7 +58,6 @@ #include #include #include -#include #include #include #include @@ -68,7 +68,7 @@ #include #include #include -#include + #include #include #include @@ -1849,444 +1849,6 @@ void LicenseAgreementPage::updateUi() } - -// -- ComponentSelectionPage::Private - -class ComponentSelectionPage::Private : public QObject -{ - Q_OBJECT - -public: - Private(ComponentSelectionPage *qq, PackageManagerCore *core) - : q(qq) - , m_core(core) - , m_treeView(new QTreeView(q)) - , m_allModel(m_core->defaultComponentModel()) - , m_updaterModel(m_core->updaterComponentModel()) - , m_currentModel(m_allModel) - , m_compressedButtonVisible(false) - , m_allowCompressedRepositoryInstall(false) - , m_categoryLayoutVisible(false) - { - m_treeView->setObjectName(QLatin1String("ComponentsTreeView")); - - connect(m_allModel, SIGNAL(checkStateChanged(QInstaller::ComponentModel::ModelState)), this, - SLOT(onModelStateChanged(QInstaller::ComponentModel::ModelState))); - connect(m_updaterModel, SIGNAL(checkStateChanged(QInstaller::ComponentModel::ModelState)), - this, SLOT(onModelStateChanged(QInstaller::ComponentModel::ModelState))); - - m_descriptionVLayout = new QVBoxLayout; - m_descriptionVLayout->setObjectName(QLatin1String("DescriptionLayout")); - - m_descriptionLabel = new QLabel(q); - m_descriptionLabel->setWordWrap(true); - m_descriptionLabel->setObjectName(QLatin1String("ComponentDescriptionLabel")); - m_descriptionVLayout->addWidget(m_descriptionLabel); - - m_sizeLabel = new QLabel(q); - m_sizeLabel->setWordWrap(true); - m_sizeLabel->setObjectName(QLatin1String("ComponentSizeLabel")); - m_descriptionVLayout->addWidget(m_sizeLabel); - m_descriptionVLayout->addSpacerItem(new QSpacerItem(1, 1, QSizePolicy::MinimumExpanding, - QSizePolicy::MinimumExpanding)); - - m_mainHLayout = new QHBoxLayout; - - m_treeViewVLayout = new QVBoxLayout; - m_treeViewVLayout->setObjectName(QLatin1String("TreeviewLayout")); - - m_bspLabel = new QLabel(); - m_bspLabel->hide(); - m_treeViewVLayout->addWidget(m_bspLabel); - - m_progressBar = new QProgressBar(); - m_progressBar->setRange(0, 0); - m_progressBar->hide(); - m_progressBar->setObjectName(QLatin1String("CompressedInstallProgressBar")); - m_treeViewVLayout->addWidget(m_progressBar); - - connect(m_core, SIGNAL(metaJobProgress(int)), this, SLOT(onProgressChanged(int))); - connect(m_core, SIGNAL(metaJobInfoMessage(QString)), this, SLOT(setMessage(QString))); - connect(m_core, &PackageManagerCore::metaJobTotalProgress, this, - &ComponentSelectionPage::Private::setTotalProgress); - - m_buttonHLayout = new QHBoxLayout; - m_checkDefault = new QPushButton; - connect(m_checkDefault, &QAbstractButton::clicked, - this, &ComponentSelectionPage::Private::selectDefault); - if (m_core->isInstaller()) { - m_checkDefault->setObjectName(QLatin1String("SelectDefaultComponentsButton")); - m_checkDefault->setShortcut(QKeySequence(ComponentSelectionPage::tr("Alt+A", - "select default components"))); - m_checkDefault->setText(ComponentSelectionPage::tr("Def&ault")); - } else { - m_checkDefault->setEnabled(false); - m_checkDefault->setObjectName(QLatin1String("ResetComponentsButton")); - m_checkDefault->setShortcut(QKeySequence(ComponentSelectionPage::tr("Alt+R", - "reset to already installed components"))); - m_checkDefault->setText(ComponentSelectionPage::tr("&Reset")); - } - m_buttonHLayout->addWidget(m_checkDefault); - - m_checkAll = new QPushButton; - connect(m_checkAll, &QAbstractButton::clicked, - this, &ComponentSelectionPage::Private::selectAll); - m_checkAll->setObjectName(QLatin1String("SelectAllComponentsButton")); - m_checkAll->setShortcut(QKeySequence(ComponentSelectionPage::tr("Alt+S", - "select all components"))); - m_checkAll->setText(ComponentSelectionPage::tr("&Select All")); - m_buttonHLayout->addWidget(m_checkAll); - - m_uncheckAll = new QPushButton; - connect(m_uncheckAll, &QAbstractButton::clicked, - this, &ComponentSelectionPage::Private::deselectAll); - m_uncheckAll->setObjectName(QLatin1String("DeselectAllComponentsButton")); - m_uncheckAll->setShortcut(QKeySequence(ComponentSelectionPage::tr("Alt+D", - "deselect all components"))); - m_uncheckAll->setText(ComponentSelectionPage::tr("&Deselect All")); - m_buttonHLayout->addWidget(m_uncheckAll); - - m_treeViewVLayout->addLayout(m_buttonHLayout); - m_treeViewVLayout->addWidget(m_treeView, 3); - - m_mainHLayout->addLayout(m_treeViewVLayout, 3); - m_mainHLayout->addLayout(m_descriptionVLayout, 2); - QVBoxLayout *layout = new QVBoxLayout(q); - layout->addLayout(m_mainHLayout, 1); - -#ifdef INSTALLCOMPRESSED - allowCompressedRepositoryInstall(); -#endif - } - - void allowCompressedRepositoryInstall() - { - m_allowCompressedRepositoryInstall = true; - } - - void showCompressedRepositoryButton() - { - if (m_compressedButtonVisible || !m_allowCompressedRepositoryInstall) { - return; - } - connect(m_core, SIGNAL(metaJobProgress(int)), this, SLOT(onProgressChanged(int))); - connect(m_core, SIGNAL(metaJobInfoMessage(QString)), this, SLOT(setMessage(QString))); - - QWizard *wizard = qobject_cast(m_core->guiObject()); - if (wizard) { - wizard->setOption(QWizard::HaveCustomButton2, true); - wizard->setButtonText(QWizard::CustomButton2, - ComponentSelectionPage::tr("&Browse QBSP files")); - connect(wizard, &QWizard::customButtonClicked, - this, &ComponentSelectionPage::Private::selectCompressedPackage); - q->gui()->updateButtonLayout(); - } - m_compressedButtonVisible = true; - } - - void setupCategoryLayout() - { - if (m_categoryLayoutVisible) - return; - QVBoxLayout *vLayout = new QVBoxLayout; - m_categoryVLayout = new QVBoxLayout; - m_categoryGroupBox = new QGroupBox(q); - m_categoryGroupBox->setTitle(m_core->settings().repositoryCategoryDisplayName()); - m_categoryGroupBox->setObjectName(QLatin1String("CategoryGroupBox")); - QVBoxLayout *categoryLayout = new QVBoxLayout(m_categoryGroupBox); - m_fetchCategoryButton = new QPushButton(tr("Fetch")); - m_fetchCategoryButton->setObjectName(QLatin1String("FetchCategoryButton")); - connect(m_fetchCategoryButton, &QPushButton::clicked, this, - &ComponentSelectionPage::Private::fetchRepositoryCategories); - - foreach (RepositoryCategory repository, m_core->settings().repositoryCategories()) { - QCheckBox *checkBox = new QCheckBox; - checkBox->setObjectName(repository.displayname()); - connect(checkBox, &QCheckBox::stateChanged, this, - &ComponentSelectionPage::Private::checkboxStateChanged); - checkBox->setText(repository.displayname()); - categoryLayout->addWidget(checkBox); - } - m_categoryVLayout->insertWidget(0, m_categoryGroupBox); - - m_metadataProgressLabel = new QLabel(q); - m_categoryVLayout->addWidget(m_metadataProgressLabel); - vLayout->addWidget(m_categoryGroupBox); - vLayout->addWidget(m_fetchCategoryButton); - vLayout->addStretch(); - m_mainHLayout->insertLayout(0, vLayout); - m_categoryLayoutVisible = true; - } - - void updateTreeView() - { - m_checkDefault->setVisible(m_core->isInstaller() || m_core->isPackageManager()); - if (m_treeView->selectionModel()) { - disconnect(m_treeView->selectionModel(), &QItemSelectionModel::currentChanged, - this, &ComponentSelectionPage::Private::currentSelectedChanged); - } - - m_currentModel = m_core->isUpdater() ? m_updaterModel : m_allModel; - m_treeView->setModel(m_currentModel); - m_treeView->setExpanded(m_currentModel->index(0, 0), true); - foreach (Component *component, m_core->components(PackageManagerCore::ComponentType::All)) { - if (component->isExpandedByDefault()) { - const QModelIndex index = m_currentModel->indexFromComponentName(component->name()); - m_treeView->setExpanded(index, true); - } - } - - const bool installActionColumnVisible = m_core->settings().installActionColumnVisible(); - if (!installActionColumnVisible) - m_treeView->hideColumn(ComponentModelHelper::ActionColumn); - - m_treeView->header()->setSectionResizeMode( - ComponentModelHelper::NameColumn, QHeaderView::ResizeToContents); - if (m_core->isInstaller()) { - m_treeView->setHeaderHidden(true); - 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); - } - - 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(), &QItemSelectionModel::currentChanged, - this, &ComponentSelectionPage::Private::currentSelectedChanged); - - m_treeView->setCurrentIndex(m_currentModel->index(0, 0)); - } - -public slots: - void currentSelectedChanged(const QModelIndex ¤t) - { - if (!current.isValid()) - return; - - m_sizeLabel->setText(QString()); - m_descriptionLabel->setText(m_currentModel->data(m_currentModel->index(current.row(), - ComponentModelHelper::NameColumn, current.parent()), Qt::ToolTipRole).toString()); - - Component *component = m_currentModel->componentFromIndex(current); - if ((m_core->isUninstaller()) || (!component)) - return; - - if (component->isSelected() && (component->value(scUncompressedSizeSum).toLongLong() > 0)) { - m_sizeLabel->setText(ComponentSelectionPage::tr("This component " - "will occupy approximately %1 on your hard disk drive.") - .arg(humanReadableSize(component->value(scUncompressedSizeSum).toLongLong()))); - } - } - - void selectAll() - { - m_currentModel->setCheckedState(ComponentModel::AllChecked); - } - - void deselectAll() - { - m_currentModel->setCheckedState(ComponentModel::AllUnchecked); - } - - void checkboxStateChanged() - { - QList checkboxes = m_categoryGroupBox->findChildren(); - bool enableFetchButton = false; - foreach (QCheckBox *checkbox, checkboxes) { - if (checkbox->isChecked()) { - enableFetchButton = true; - break; - } - } - } - - void enableRepositoryCategory(int index, bool enable) { - RepositoryCategory repoCategory = m_core->settings().repositoryCategories().toList().at(index); - RepositoryCategory replacement = repoCategory; - replacement.setEnabled(enable); - QSet tmpRepoCategories = m_core->settings().repositoryCategories(); - if (tmpRepoCategories.contains(repoCategory)) { - tmpRepoCategories.remove(repoCategory); - tmpRepoCategories.insert(replacement); - m_core->settings().addRepositoryCategories(tmpRepoCategories); - } - } - - void updateWidgetVisibility(bool show) - { - if (show) { - QSpacerItem *verticalSpacer2 = new QSpacerItem(0, 0, QSizePolicy::Minimum, - QSizePolicy::Expanding); - m_treeViewVLayout->addSpacerItem(verticalSpacer2); - } else { - QSpacerItem *item = m_treeViewVLayout->spacerItem(); - m_treeViewVLayout->removeItem(item); - } - m_fetchCategoryButton->setDisabled(show); - m_progressBar->setVisible(show); - m_bspLabel->setVisible(show); - m_categoryGroupBox->setDisabled(show); - - m_treeView->setVisible(!show); - m_checkDefault->setVisible(!show); - m_checkAll->setVisible(!show); - m_uncheckAll->setVisible(!show); - m_descriptionLabel->setVisible(!show); - QPushButton *const b = qobject_cast(q->gui()->button(QWizard::NextButton)); - b->setEnabled(!show); - - if (QAbstractButton *bspButton = q->gui()->button(QWizard::CustomButton2)) - bspButton->setEnabled(!show); - } - - void fetchRepositoryCategories() - { - updateWidgetVisibility(true); - - QCheckBox *checkbox; - QList checkboxes = m_categoryGroupBox->findChildren(); - for (int i = 0; i < checkboxes.count(); i++) { - checkbox = checkboxes.at(i); - enableRepositoryCategory(i, checkbox->isChecked()); - } - - if (!m_core->fetchRemotePackagesTree()) { - m_metadataProgressLabel->setText(m_core->error()); - } else { - updateTreeView(); - m_metadataProgressLabel->setText(QLatin1String()); - } - updateWidgetVisibility(false); - } - - void selectCompressedPackage() - { - QString defaultDownloadDirectory = - QStandardPaths::writableLocation(QStandardPaths::DownloadLocation); - QStringList fileNames = QFileDialog::getOpenFileNames(NULL, - ComponentSelectionPage::tr("Open File"),defaultDownloadDirectory, - QLatin1String("QBSP or 7z Files (*.qbsp *.7z)")); - - QSet set; - foreach (QString fileName, fileNames) { - Repository repository = Repository::fromUserInput(fileName, true); - repository.setEnabled(true); - set.insert(repository); - } - if (set.count() > 0) { - updateWidgetVisibility(true); - m_core->settings().addTemporaryRepositories(set, false); - if (!m_core->fetchCompressedPackagesTree()) { - setMessage(m_core->error()); - } - else { - updateTreeView(); - setMessage(ComponentSelectionPage::tr("To install new "\ - "compressed repository, browse the repositories from your computer")); - } - } - updateWidgetVisibility(false); - } - - /*! - Updates the value of \a progress on the progress bar. - */ - void onProgressChanged(int progress) - { - m_progressBar->setValue(progress); - } - - /*! - Displays the message \a msg on the page. - */ - void setMessage(const QString &msg) - { - QWizardPage *page = q->gui()->currentPage(); - if (m_bspLabel && page && page->objectName() == QLatin1String("ComponentSelectionPage")) - m_bspLabel->setText(msg); - } - - void setTotalProgress(int totalProgress) - { - if (m_progressBar) - m_progressBar->setRange(0, totalProgress); - } - - void selectDefault() - { - m_currentModel->setCheckedState(ComponentModel::DefaultChecked); - } - - void onModelStateChanged(QInstaller::ComponentModel::ModelState state) - { - q->setModified(state.testFlag(ComponentModel::DefaultChecked) == false); - // If all components in the checked list are only checkable when run without forced - // installation, set ComponentModel::AllUnchecked as well, as we cannot uncheck anything. - // Helps to keep the UI correct. - if ((!m_core->noForceInstallation()) - && (m_currentModel->checked() == m_currentModel->uncheckable())) { - state |= ComponentModel::AllUnchecked; - } - // enable the button if the corresponding flag is not set - m_checkAll->setEnabled(state.testFlag(ComponentModel::AllChecked) == false); - m_uncheckAll->setEnabled(state.testFlag(ComponentModel::AllUnchecked) == false); - m_checkDefault->setEnabled(state.testFlag(ComponentModel::DefaultChecked) == false); - - // update the current selected node (important to reflect possible sub-node changes) - if (m_treeView->selectionModel()) - currentSelectedChanged(m_treeView->selectionModel()->currentIndex()); - } - -public: - ComponentSelectionPage *q; - 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; - QPushButton *m_installCompressButton; - QGroupBox *m_categoryGroupBox; - QPushButton *m_fetchCategoryButton; - QLabel *m_bspLabel; - QLabel *m_metadataProgressLabel; - QProgressBar *m_progressBar; - QVBoxLayout *m_descriptionVLayout; - QHBoxLayout *m_mainHLayout; - QVBoxLayout *m_treeViewVLayout; - QVBoxLayout *m_categoryVLayout; - QHBoxLayout *m_buttonHLayout; - bool m_compressedButtonVisible; - bool m_allowCompressedRepositoryInstall; - bool m_categoryLayoutVisible; -}; - - // -- ComponentSelectionPage /*! @@ -2301,7 +1863,7 @@ public: */ ComponentSelectionPage::ComponentSelectionPage(PackageManagerCore *core) : PackageManagerPage(core) - , d(new Private(this, core)) + , d(new ComponentSelectionPagePrivate(this, core)) { setPixmap(QWizard::WatermarkPixmap, QPixmap()); setObjectName(QLatin1String("ComponentSelectionPage")); @@ -2348,12 +1910,7 @@ void ComponentSelectionPage::entering() void ComponentSelectionPage::leaving() { - QWizard *wizard = qobject_cast(d->m_core->guiObject()); - if (wizard && (gui()->options() & QWizard::HaveCustomButton2)) { - wizard->setOption(QWizard::HaveCustomButton2, false); - gui()->updateButtonLayout(); - d->m_compressedButtonVisible = false; - } + d->hideCompressedRepositoryButton(); } /*! diff --git a/src/libs/installer/packagemanagergui.h b/src/libs/installer/packagemanagergui.h index d67bc9bd9..59ea6572e 100644 --- a/src/libs/installer/packagemanagergui.h +++ b/src/libs/installer/packagemanagergui.h @@ -57,7 +57,7 @@ namespace QInstaller { class PackageManagerCore; class PackageManagerPage; class PerformInstallationForm; - +class ComponentSelectionPagePrivate; // -- PackageManagerGui @@ -321,8 +321,8 @@ private Q_SLOTS: void setModified(bool modified); private: - class Private; - Private *d; + friend class ComponentSelectionPagePrivate; + ComponentSelectionPagePrivate *const d; }; -- cgit v1.2.3