From 05249bc1337473abcb3076be9f20c82e14211d5a Mon Sep 17 00:00:00 2001 From: Manuel Nickschas Date: Wed, 30 Aug 2017 23:43:45 +0200 Subject: [PATCH] Fix layout issues in CoreConfigWizard; cleanup Qt has trouble layouting widgets dynamically added to wizard pages, so switch to using QStackedWidget for storage and authenticator settings. Add size policies as needed and explicitly set the size of all pages to fit the largest one to ensure that the wizard is large enough. While we're at it, clean up related code a bit. Closes GH-170. --- src/qtui/coreconfigwizard.cpp | 137 +++++++++++------- src/qtui/coreconfigwizard.h | 11 +- src/qtui/ui/coreconfigwizardadminuserpage.ui | 7 +- ...configwizardauthenticationselectionpage.ui | 57 ++++---- .../coreconfigwizardstorageselectionpage.ui | 54 +++---- src/qtui/ui/coreconfigwizardsyncpage.ui | 28 ++-- 6 files changed, 171 insertions(+), 123 deletions(-) diff --git a/src/qtui/coreconfigwizard.cpp b/src/qtui/coreconfigwizard.cpp index 18133f07..4324c45f 100644 --- a/src/qtui/coreconfigwizard.cpp +++ b/src/qtui/coreconfigwizard.cpp @@ -20,6 +20,7 @@ #include #include +#include #include #include #include @@ -31,8 +32,21 @@ namespace { +QGroupBox *createDescriptionBox(const QString &description) +{ + auto box = new QGroupBox; + auto layout = new QVBoxLayout(box); + auto label = new QLabel(description, box); + label->setWordWrap(true); + layout->addWidget(label); + layout->setAlignment(label, Qt::AlignTop); + box->setTitle(QCoreApplication::translate("CoreConfigWizard", "Description")); + return box; +} + + template -void createFieldWidgets(QGroupBox *fieldBox, const std::vector &fieldInfos) +QGroupBox *createFieldBox(const QString &title, const std::vector &fieldInfos) { // Create a config UI based on the field types sent from the backend // We make some assumptions here (like integer range and password field names) that may not @@ -40,7 +54,10 @@ void createFieldWidgets(QGroupBox *fieldBox, const std::vector &field // provide specialized config widgets for those (which may be a good idea anyway, e.g. if we // think about client-side translations...) - QFormLayout *formLayout = new QFormLayout; + QGroupBox *fieldBox = new QGroupBox; + fieldBox->setTitle(title); + + QFormLayout *formLayout = new QFormLayout(fieldBox); for (auto &&fieldInfo : fieldInfos) { QWidget *widget {nullptr}; switch (std::get<2>(fieldInfo).type()) { @@ -65,7 +82,7 @@ void createFieldWidgets(QGroupBox *fieldBox, const std::vector &field formLayout->addRow(std::get<1>(fieldInfo) + ":", widget); } } - fieldBox->setLayout(formLayout); + return fieldBox; } @@ -125,11 +142,8 @@ CoreConfigWizard::CoreConfigWizard(CoreConnection *connection, const QVariantLis syncRelayPage = new CoreConfigWizardPages::SyncRelayPage(this); connect(syncRelayPage, SIGNAL(startOver()), this, SLOT(startOver())); setPage(SyncRelayPage, syncRelayPage); - //setPage(Page_StorageDetails, new StorageDetailsPage()); - //setPage(Page_Conclusion, new ConclusionPage(storageProviders)); setStartId(IntroPage); - //setStartId(StorageSelectionPage); #ifndef Q_OS_MAC setWizardStyle(ModernStyle); @@ -141,7 +155,6 @@ CoreConfigWizard::CoreConfigWizard(CoreConnection *connection, const QVariantLis setOption(HaveFinishButtonOnEarlyPages, false); setOption(NoCancelButton, true); setOption(IndependentPages, true); - //setOption(ExtendedWatermarkPixmap, true); setModal(true); @@ -150,17 +163,28 @@ CoreConfigWizard::CoreConfigWizard(CoreConnection *connection, const QVariantLis connect(connection, SIGNAL(coreSetupSuccess()), SLOT(coreSetupSuccess())); connect(connection, SIGNAL(coreSetupFailed(QString)), SLOT(coreSetupFailed(QString))); - //connect(connection, SIGNAL(loginSuccess()), SLOT(loginSuccess())); connect(connection, SIGNAL(synchronized()), SLOT(syncFinished())); connect(this, SIGNAL(rejected()), connection, SLOT(disconnectFromCore())); + + + // Resize all pages to the size hint of the largest one, so the wizard is large enough + QSize maxSize; + for (int id : pageIds()) { + auto p = page(id); + p->adjustSize(); + maxSize = maxSize.expandedTo(p->sizeHint()); + } + for (int id : pageIds()) { + page(id)->setFixedSize(maxSize); + } } void CoreConfigWizard::prepareCoreSetup(const QString &backend, const QVariantMap &properties, const QString &authenticator, const QVariantMap &authProperties) { // Prevent the user from changing any settings he already specified... - foreach(int idx, visitedPages()) - page(idx)->setEnabled(false); + for (auto &&idx : visitedPages()) + page(idx)->setEnabled(false); // FIXME? We need to be able to set up older cores that don't have auth backend support. // So if the core doesn't support that feature, don't pass those parameters. @@ -201,15 +225,6 @@ void CoreConfigWizard::startOver() } -void CoreConfigWizard::loginSuccess() -{ - syncPage->setStatus(tr("Your are now logged into your freshly configured Quassel Core!
" - "Please remember to configure your identities and networks now.")); - syncPage->setComplete(true); - syncPage->setFinalPage(true); -} - - void CoreConfigWizard::syncFinished() { accept(); @@ -289,13 +304,30 @@ AuthenticationSelectionPage::AuthenticationSelectionPage(const QVariantList &aut } props.remove("SetupData"); - _authProperties.emplace_back(props); + _authProperties.emplace_back(std::move(props)); _authFields.emplace_back(std::move(fields)); - // Create entry in authenticator selector - ui.backendList->addItem(props["DisplayName"].toString(), props["BackendId"].toString()); + // Create widgets + ui.backendList->addItem(_authProperties.back()["DisplayName"].toString(), _authProperties.back()["BackendId"].toString()); + ui.descriptionStack->addWidget(createDescriptionBox(_authProperties.back()["Description"].toString())); + ui.authSettingsStack->addWidget(createFieldBox(tr("Authentication Settings"), _authFields.back())); } + // Do some trickery to make the page large enough + setSizePolicy({QSizePolicy::Fixed, QSizePolicy::Fixed}); + + QSizePolicy sp{QSizePolicy::MinimumExpanding, QSizePolicy::Fixed}; +#if QT_VERSION >= 0x050200 + sp.setRetainSizeWhenHidden(true); +#else + ui.authSettingsStack->setVisible(true); // ugly hack that will show an empty box, but we'll deprecate Qt4 soon anyway +#endif + ui.descriptionStack->setSizePolicy(sp); + ui.authSettingsStack->setSizePolicy(sp); + + ui.descriptionStack->adjustSize(); + ui.authSettingsStack->adjustSize(); + ui.backendList->setCurrentIndex(0); } @@ -324,25 +356,16 @@ QString AuthenticationSelectionPage::authenticator() const QVariantMap AuthenticationSelectionPage::authProperties() const { - return propertiesFromFieldWidgets(_fieldBox, _authFields[ui.backendList->currentIndex()]); + return propertiesFromFieldWidgets(qobject_cast(ui.authSettingsStack->currentWidget()), + _authFields[ui.backendList->currentIndex()]); } void AuthenticationSelectionPage::on_backendList_currentIndexChanged(int index) { - ui.description->setText(_authProperties[index]["Description"].toString()); - - if (_fieldBox) { - layout()->removeWidget(_fieldBox); - _fieldBox->deleteLater(); - _fieldBox = nullptr; - } - if (!_authFields[index].empty()) { - _fieldBox = new QGroupBox(this); - _fieldBox->setTitle(tr("Authentication Settings")); - createFieldWidgets(_fieldBox, _authFields[index]); - static_cast(layout())->insertWidget(layout()->indexOf(ui.descriptionBox) + 1, _fieldBox); - } + ui.descriptionStack->setCurrentIndex(index); + ui.authSettingsStack->setCurrentIndex(index); + ui.authSettingsStack->setVisible(!_authFields[index].empty()); } /*** Storage Selection Page ***/ @@ -387,13 +410,30 @@ StorageSelectionPage::StorageSelectionPage(const QVariantList &backendInfos, QWi // Legacy cores (prior to 0.13) don't send the BackendId property if (!props.contains("BackendId")) props["BackendId"] = props["DisplayName"]; - _backendProperties.emplace_back(props); + _backendProperties.emplace_back(std::move(props)); _backendFields.emplace_back(std::move(fields)); - // Create entry in backend selector - ui.backendList->addItem(props["DisplayName"].toString(), props["BackendId"].toString()); + // Create widgets + ui.backendList->addItem(_backendProperties.back()["DisplayName"].toString(), _backendProperties.back()["BackendId"].toString()); + ui.descriptionStack->addWidget(createDescriptionBox(_backendProperties.back()["Description"].toString())); + ui.storageSettingsStack->addWidget(createFieldBox(tr("Storage Settings"), _backendFields.back())); } + // Do some trickery to make the page large enough + setSizePolicy({QSizePolicy::Fixed, QSizePolicy::Fixed}); + + QSizePolicy sp{QSizePolicy::MinimumExpanding, QSizePolicy::Fixed}; +#if QT_VERSION >= 0x050200 + sp.setRetainSizeWhenHidden(true); +#else + ui.storageSettingsStack->setVisible(true); // ugly hack that will show an empty box, but we'll deprecate Qt4 soon anyway +#endif + ui.descriptionStack->setSizePolicy(sp); + ui.storageSettingsStack->setSizePolicy(sp); + + ui.descriptionStack->adjustSize(); + ui.storageSettingsStack->adjustSize(); + ui.backendList->setCurrentIndex(defaultIndex); } @@ -422,25 +462,16 @@ QString StorageSelectionPage::backend() const QVariantMap StorageSelectionPage::backendProperties() const { - return propertiesFromFieldWidgets(_fieldBox, _backendFields[ui.backendList->currentIndex()]); + return propertiesFromFieldWidgets(qobject_cast(ui.storageSettingsStack->currentWidget()), + _backendFields[ui.backendList->currentIndex()]); } void StorageSelectionPage::on_backendList_currentIndexChanged(int index) { - ui.description->setText(_backendProperties[index]["Description"].toString()); - - if (_fieldBox) { - layout()->removeWidget(_fieldBox); - _fieldBox->deleteLater(); - _fieldBox = nullptr; - } - if (!_backendFields[index].empty()) { - _fieldBox = new QGroupBox(this); - _fieldBox->setTitle(tr("Storage Settings")); - createFieldWidgets(_fieldBox, _backendFields[index]); - static_cast(layout())->insertWidget(layout()->indexOf(ui.descriptionBox) + 1, _fieldBox); - } + ui.descriptionStack->setCurrentIndex(index); + ui.storageSettingsStack->setCurrentIndex(index); + ui.storageSettingsStack->setVisible(!_backendFields[index].empty()); } diff --git a/src/qtui/coreconfigwizard.h b/src/qtui/coreconfigwizard.h index 5b09a872..6f2f7114 100644 --- a/src/qtui/coreconfigwizard.h +++ b/src/qtui/coreconfigwizard.h @@ -35,8 +35,10 @@ class CoreConnection; namespace CoreConfigWizardPages { + class SyncPage; class SyncRelayPage; + }; class CoreConfigWizard : public QWizard @@ -64,7 +66,6 @@ signals: void loginToCore(const QString &user, const QString &password, bool rememberPassword); public slots: - void loginSuccess(); void syncFinished(); private slots: @@ -82,6 +83,7 @@ private: namespace CoreConfigWizardPages { + class IntroPage : public QWizardPage { Q_OBJECT @@ -106,7 +108,7 @@ private: Ui::CoreConfigWizardAdminUserPage ui; }; -// Authentication selection before storage selection. + class AuthenticationSelectionPage : public QWizardPage { Q_OBJECT @@ -124,11 +126,11 @@ private slots: private: Ui::CoreConfigWizardAuthenticationSelectionPage ui; - QGroupBox *_fieldBox {nullptr}; std::vector _authProperties; std::vector> _authFields; }; + class StorageSelectionPage : public QWizardPage { Q_OBJECT @@ -146,11 +148,11 @@ private slots: private: Ui::CoreConfigWizardStorageSelectionPage ui; - QGroupBox *_fieldBox {nullptr}; std::vector _backendProperties; std::vector> _backendFields; }; + class SyncPage : public QWizardPage { Q_OBJECT @@ -194,4 +196,5 @@ signals: private: Mode mode; }; + } diff --git a/src/qtui/ui/coreconfigwizardadminuserpage.ui b/src/qtui/ui/coreconfigwizardadminuserpage.ui index e55859fa..5f8cca2f 100644 --- a/src/qtui/ui/coreconfigwizardadminuserpage.ui +++ b/src/qtui/ui/coreconfigwizardadminuserpage.ui @@ -6,8 +6,8 @@ 0 0 - 429 - 273 + 505 + 289 @@ -16,6 +16,9 @@ + + QLayout::SetMinimumSize + diff --git a/src/qtui/ui/coreconfigwizardauthenticationselectionpage.ui b/src/qtui/ui/coreconfigwizardauthenticationselectionpage.ui index d00c8f05..fca2a0ca 100644 --- a/src/qtui/ui/coreconfigwizardauthenticationselectionpage.ui +++ b/src/qtui/ui/coreconfigwizardauthenticationselectionpage.ui @@ -6,16 +6,19 @@ 0 0 - 310 - 168 + 377 + 160 Form - + + + QLayout::SetMinAndMaxSize + @@ -43,8 +46,8 @@ - 40 - 20 + 0 + 0 @@ -52,25 +55,29 @@ - - - Description + + + + 0 + 0 + + + + -1 + + + + + + + + 0 + 0 + + + + -1 - - - - - Foobar - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop - - - true - - - - @@ -80,8 +87,8 @@ - 20 - 40 + 0 + 0 diff --git a/src/qtui/ui/coreconfigwizardstorageselectionpage.ui b/src/qtui/ui/coreconfigwizardstorageselectionpage.ui index 6e718376..c9862cb0 100644 --- a/src/qtui/ui/coreconfigwizardstorageselectionpage.ui +++ b/src/qtui/ui/coreconfigwizardstorageselectionpage.ui @@ -6,14 +6,14 @@ 0 0 - 310 - 168 + 402 + 148 Form - + @@ -43,8 +43,8 @@ - 40 - 20 + 0 + 0 @@ -52,25 +52,29 @@ - - - Description + + + + 0 + 0 + + + + -1 + + + + + + + + 0 + 0 + + + + -1 - - - - - Foobar - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop - - - true - - - - @@ -80,8 +84,8 @@ - 20 - 40 + 0 + 0 diff --git a/src/qtui/ui/coreconfigwizardsyncpage.ui b/src/qtui/ui/coreconfigwizardsyncpage.ui index 9894e97b..39d8818e 100644 --- a/src/qtui/ui/coreconfigwizardsyncpage.ui +++ b/src/qtui/ui/coreconfigwizardsyncpage.ui @@ -7,7 +7,7 @@ 0 0 400 - 300 + 252 @@ -104,19 +104,6 @@ - - - - Qt::Vertical - - - - 20 - 40 - - - - @@ -130,6 +117,19 @@ + + + + Qt::Vertical + + + + 0 + 0 + + + + -- 2.20.1