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.
#include <QDebug>
#include <QAbstractButton>
#include <QDebug>
#include <QAbstractButton>
+#include <QCoreApplication>
#include <QFormLayout>
#include <QIcon>
#include <QSpinBox>
#include <QFormLayout>
#include <QIcon>
#include <QSpinBox>
+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<typename FieldInfo>
template<typename FieldInfo>
-void createFieldWidgets(QGroupBox *fieldBox, const std::vector<FieldInfo> &fieldInfos)
+QGroupBox *createFieldBox(const QString &title, const std::vector<FieldInfo> &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
{
// 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
// provide specialized config widgets for those (which may be a good idea anyway, e.g. if we
// think about client-side translations...)
// 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()) {
for (auto &&fieldInfo : fieldInfos) {
QWidget *widget {nullptr};
switch (std::get<2>(fieldInfo).type()) {
formLayout->addRow(std::get<1>(fieldInfo) + ":", widget);
}
}
formLayout->addRow(std::get<1>(fieldInfo) + ":", widget);
}
}
- fieldBox->setLayout(formLayout);
syncRelayPage = new CoreConfigWizardPages::SyncRelayPage(this);
connect(syncRelayPage, SIGNAL(startOver()), this, SLOT(startOver()));
setPage(SyncRelayPage, syncRelayPage);
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(StorageSelectionPage);
#ifndef Q_OS_MAC
setWizardStyle(ModernStyle);
#ifndef Q_OS_MAC
setWizardStyle(ModernStyle);
setOption(HaveFinishButtonOnEarlyPages, false);
setOption(NoCancelButton, true);
setOption(IndependentPages, true);
setOption(HaveFinishButtonOnEarlyPages, false);
setOption(NoCancelButton, true);
setOption(IndependentPages, true);
- //setOption(ExtendedWatermarkPixmap, true);
connect(connection, SIGNAL(coreSetupSuccess()), SLOT(coreSetupSuccess()));
connect(connection, SIGNAL(coreSetupFailed(QString)), SLOT(coreSetupFailed(QString)));
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()));
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...
}
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.
// 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.
-void CoreConfigWizard::loginSuccess()
-{
- syncPage->setStatus(tr("Your are now logged into your freshly configured Quassel Core!<br>"
- "Please remember to configure your identities and networks now."));
- syncPage->setComplete(true);
- syncPage->setFinalPage(true);
-}
-
-
void CoreConfigWizard::syncFinished()
{
accept();
void CoreConfigWizard::syncFinished()
{
accept();
}
props.remove("SetupData");
}
props.remove("SetupData");
- _authProperties.emplace_back(props);
+ _authProperties.emplace_back(std::move(props));
_authFields.emplace_back(std::move(fields));
_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);
}
ui.backendList->setCurrentIndex(0);
}
QVariantMap AuthenticationSelectionPage::authProperties() const
{
QVariantMap AuthenticationSelectionPage::authProperties() const
{
- return propertiesFromFieldWidgets(_fieldBox, _authFields[ui.backendList->currentIndex()]);
+ return propertiesFromFieldWidgets(qobject_cast<QGroupBox *>(ui.authSettingsStack->currentWidget()),
+ _authFields[ui.backendList->currentIndex()]);
}
void AuthenticationSelectionPage::on_backendList_currentIndexChanged(int index)
{
}
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<QVBoxLayout *>(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 ***/
}
/*** Storage Selection Page ***/
// Legacy cores (prior to 0.13) don't send the BackendId property
if (!props.contains("BackendId"))
props["BackendId"] = props["DisplayName"];
// 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));
_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);
}
ui.backendList->setCurrentIndex(defaultIndex);
}
QVariantMap StorageSelectionPage::backendProperties() const
{
QVariantMap StorageSelectionPage::backendProperties() const
{
- return propertiesFromFieldWidgets(_fieldBox, _backendFields[ui.backendList->currentIndex()]);
+ return propertiesFromFieldWidgets(qobject_cast<QGroupBox *>(ui.storageSettingsStack->currentWidget()),
+ _backendFields[ui.backendList->currentIndex()]);
}
void StorageSelectionPage::on_backendList_currentIndexChanged(int index)
{
}
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<QVBoxLayout *>(layout())->insertWidget(layout()->indexOf(ui.descriptionBox) + 1, _fieldBox);
- }
+ ui.descriptionStack->setCurrentIndex(index);
+ ui.storageSettingsStack->setCurrentIndex(index);
+ ui.storageSettingsStack->setVisible(!_backendFields[index].empty());
class CoreConnection;
namespace CoreConfigWizardPages {
class CoreConnection;
namespace CoreConfigWizardPages {
class SyncPage;
class SyncRelayPage;
class SyncPage;
class SyncRelayPage;
};
class CoreConfigWizard : public QWizard
};
class CoreConfigWizard : public QWizard
void loginToCore(const QString &user, const QString &password, bool rememberPassword);
public slots:
void loginToCore(const QString &user, const QString &password, bool rememberPassword);
public slots:
void syncFinished();
private slots:
void syncFinished();
private slots:
namespace CoreConfigWizardPages {
namespace CoreConfigWizardPages {
class IntroPage : public QWizardPage
{
Q_OBJECT
class IntroPage : public QWizardPage
{
Q_OBJECT
Ui::CoreConfigWizardAdminUserPage ui;
};
Ui::CoreConfigWizardAdminUserPage ui;
};
-// Authentication selection before storage selection.
class AuthenticationSelectionPage : public QWizardPage
{
Q_OBJECT
class AuthenticationSelectionPage : public QWizardPage
{
Q_OBJECT
private:
Ui::CoreConfigWizardAuthenticationSelectionPage ui;
private:
Ui::CoreConfigWizardAuthenticationSelectionPage ui;
- QGroupBox *_fieldBox {nullptr};
std::vector<QVariantMap> _authProperties;
std::vector<std::vector<FieldInfo>> _authFields;
};
std::vector<QVariantMap> _authProperties;
std::vector<std::vector<FieldInfo>> _authFields;
};
class StorageSelectionPage : public QWizardPage
{
Q_OBJECT
class StorageSelectionPage : public QWizardPage
{
Q_OBJECT
private:
Ui::CoreConfigWizardStorageSelectionPage ui;
private:
Ui::CoreConfigWizardStorageSelectionPage ui;
- QGroupBox *_fieldBox {nullptr};
std::vector<QVariantMap> _backendProperties;
std::vector<std::vector<FieldInfo>> _backendFields;
};
std::vector<QVariantMap> _backendProperties;
std::vector<std::vector<FieldInfo>> _backendFields;
};
class SyncPage : public QWizardPage
{
Q_OBJECT
class SyncPage : public QWizardPage
{
Q_OBJECT
- <width>429</width>
- <height>273</height>
+ <width>505</width>
+ <height>289</height>
</rect>
</property>
<property name="windowTitle">
</rect>
</property>
<property name="windowTitle">
<layout class="QVBoxLayout">
<item>
<layout class="QGridLayout">
<layout class="QVBoxLayout">
<item>
<layout class="QGridLayout">
+ <property name="sizeConstraint">
+ <enum>QLayout::SetMinimumSize</enum>
+ </property>
<item row="0" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<item row="0" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
- <width>310</width>
- <height>168</height>
+ <width>377</width>
+ <height>160</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
- <layout class="QVBoxLayout">
+ <layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout">
<item>
<layout class="QHBoxLayout">
+ <property name="sizeConstraint">
+ <enum>QLayout::SetMinAndMaxSize</enum>
+ </property>
<item>
<widget class="QLabel" name="label">
<property name="text">
<item>
<widget class="QLabel" name="label">
<property name="text">
</property>
<property name="sizeHint" stdset="0">
<size>
</property>
<property name="sizeHint" stdset="0">
<size>
- <width>40</width>
- <height>20</height>
+ <width>0</width>
+ <height>0</height>
</size>
</property>
</spacer>
</size>
</property>
</spacer>
- <widget class="QGroupBox" name="descriptionBox">
- <property name="title">
- <string>Description</string>
+ <widget class="QStackedWidget" name="descriptionStack">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="currentIndex">
+ <number>-1</number>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QStackedWidget" name="authSettingsStack">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="currentIndex">
+ <number>-1</number>
- <layout class="QVBoxLayout">
- <item>
- <widget class="QLabel" name="description">
- <property name="text">
- <string notr="true">Foobar</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
- </property>
- <property name="wordWrap">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- </layout>
</property>
<property name="sizeHint" stdset="0">
<size>
</property>
<property name="sizeHint" stdset="0">
<size>
- <width>20</width>
- <height>40</height>
+ <width>0</width>
+ <height>0</height>
</size>
</property>
</spacer>
</size>
</property>
</spacer>
- <width>310</width>
- <height>168</height>
+ <width>402</width>
+ <height>148</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
- <layout class="QVBoxLayout">
+ <layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout">
<item>
<item>
<layout class="QHBoxLayout">
<item>
</property>
<property name="sizeHint" stdset="0">
<size>
</property>
<property name="sizeHint" stdset="0">
<size>
- <width>40</width>
- <height>20</height>
+ <width>0</width>
+ <height>0</height>
</size>
</property>
</spacer>
</size>
</property>
</spacer>
- <widget class="QGroupBox" name="descriptionBox">
- <property name="title">
- <string>Description</string>
+ <widget class="QStackedWidget" name="descriptionStack">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="currentIndex">
+ <number>-1</number>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QStackedWidget" name="storageSettingsStack">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="currentIndex">
+ <number>-1</number>
- <layout class="QVBoxLayout">
- <item>
- <widget class="QLabel" name="description">
- <property name="text">
- <string notr="true">Foobar</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
- </property>
- <property name="wordWrap">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- </layout>
</property>
<property name="sizeHint" stdset="0">
<size>
</property>
<property name="sizeHint" stdset="0">
<size>
- <width>20</width>
- <height>40</height>
+ <width>0</width>
+ <height>0</height>
</size>
</property>
</spacer>
</size>
</property>
</spacer>
<x>0</x>
<y>0</y>
<width>400</width>
<x>0</x>
<y>0</y>
<width>400</width>
</rect>
</property>
<property name="windowTitle">
</rect>
</property>
<property name="windowTitle">
</layout>
</widget>
</item>
</layout>
</widget>
</item>
- <item>
- <spacer>
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>40</height>
- </size>
- </property>
- </spacer>
- </item>
<item>
<widget class="QLabel" name="status">
<property name="text">
<item>
<widget class="QLabel" name="status">
<property name="text">
</property>
</widget>
</item>
</property>
</widget>
</item>
+ <item>
+ <spacer>
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
</layout>
</widget>
<resources/>
</layout>
</widget>
<resources/>