1 /***************************************************************************
2 * Copyright (C) 2005-2016 by the Quassel Project *
3 * devel@quassel-irc.org *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) version 3. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
19 ***************************************************************************/
22 #include <QAbstractButton>
23 #include <QFormLayout>
27 #include "coreconfigwizard.h"
28 #include "coreconnection.h"
30 CoreConfigWizard::CoreConfigWizard(CoreConnection *connection, const QList<QVariant> &backends, const QList<QVariant> &authenticators, QWidget *parent)
32 _connection(connection)
35 setAttribute(Qt::WA_DeleteOnClose);
37 foreach(const QVariant &v, backends)
38 _backends[v.toMap()["DisplayName"].toString()] = v;
40 foreach(const QVariant &v, authenticators)
41 _authenticators[v.toMap()["DisplayName"].toString()] = v;
43 setPage(IntroPage, new CoreConfigWizardPages::IntroPage(this));
44 setPage(AdminUserPage, new CoreConfigWizardPages::AdminUserPage(this));
45 setPage(AuthenticationSelectionPage, new CoreConfigWizardPages::AuthenticationSelectionPage(_authenticators, this));
46 setPage(StorageSelectionPage, new CoreConfigWizardPages::StorageSelectionPage(_backends, this));
47 syncPage = new CoreConfigWizardPages::SyncPage(this);
48 connect(syncPage, SIGNAL(setupCore(const QString &, const QVariantMap &, const QString &, const QVariantMap &)),
49 SLOT(prepareCoreSetup(const QString &, const QVariantMap &, const QString &, const QVariantMap &)));
50 setPage(SyncPage, syncPage);
51 syncRelayPage = new CoreConfigWizardPages::SyncRelayPage(this);
52 connect(syncRelayPage, SIGNAL(startOver()), this, SLOT(startOver()));
53 setPage(SyncRelayPage, syncRelayPage);
54 //setPage(Page_StorageDetails, new StorageDetailsPage());
55 //setPage(Page_Conclusion, new ConclusionPage(storageProviders));
57 setStartId(IntroPage);
58 //setStartId(StorageSelectionPage);
61 setWizardStyle(ModernStyle);
64 setOption(HaveHelpButton, false);
65 setOption(NoBackButtonOnStartPage, true);
66 setOption(HaveNextButtonOnLastPage, false);
67 setOption(HaveFinishButtonOnEarlyPages, false);
68 setOption(NoCancelButton, true);
69 setOption(IndependentPages, true);
70 //setOption(ExtendedWatermarkPixmap, true);
74 setWindowTitle(tr("Core Configuration Wizard"));
75 setPixmap(QWizard::LogoPixmap, QIcon::fromTheme("quassel", QIcon(":/icons/quassel.png")).pixmap(48));
77 connect(connection, SIGNAL(coreSetupSuccess()), SLOT(coreSetupSuccess()));
78 connect(connection, SIGNAL(coreSetupFailed(QString)), SLOT(coreSetupFailed(QString)));
79 //connect(connection, SIGNAL(loginSuccess()), SLOT(loginSuccess()));
80 connect(connection, SIGNAL(synchronized()), SLOT(syncFinished()));
81 connect(this, SIGNAL(rejected()), connection, SLOT(disconnectFromCore()));
85 QHash<QString, QVariant> CoreConfigWizard::backends() const
90 QHash<QString, QVariant> CoreConfigWizard::authenticators() const
92 return _authenticators;
95 void CoreConfigWizard::prepareCoreSetup(const QString &backend, const QVariantMap &properties, const QString &authBackend, const QVariantMap &authProperties)
97 // Prevent the user from changing any settings he already specified...
98 foreach(int idx, visitedPages())
99 page(idx)->setEnabled(false);
101 coreConnection()->setupCore(Protocol::SetupData(field("adminUser.user").toString(), field("adminUser.password").toString(), backend, authBackend, properties, authProperties));
105 void CoreConfigWizard::coreSetupSuccess()
107 syncPage->setStatus(tr("Your core has been successfully configured. Logging you in..."));
108 syncPage->setError(false);
109 syncRelayPage->setMode(CoreConfigWizardPages::SyncRelayPage::Error);
110 coreConnection()->loginToCore(field("adminUser.user").toString(), field("adminUser.password").toString(), field("adminUser.rememberPasswd").toBool());
114 void CoreConfigWizard::coreSetupFailed(const QString &error)
116 syncPage->setStatus(tr("Core configuration failed:<br><b>%1</b><br>Press <em>Next</em> to start over.").arg(error));
117 syncPage->setError(true);
118 syncRelayPage->setMode(CoreConfigWizardPages::SyncRelayPage::Error);
119 //foreach(int idx, visitedPages()) page(idx)->setEnabled(true);
120 //setStartId(SyncPage);
125 void CoreConfigWizard::startOver()
127 foreach(int idx, visitedPages()) page(idx)->setEnabled(true);
128 setStartId(CoreConfigWizard::AdminUserPage);
133 void CoreConfigWizard::loginSuccess()
135 syncPage->setStatus(tr("Your are now logged into your freshly configured Quassel Core!<br>"
136 "Please remember to configure your identities and networks now."));
137 syncPage->setComplete(true);
138 syncPage->setFinalPage(true);
142 void CoreConfigWizard::syncFinished()
148 namespace CoreConfigWizardPages {
151 IntroPage::IntroPage(QWidget *parent) : QWizardPage(parent)
154 setTitle(tr("Introduction"));
155 //setSubTitle(tr("foobar"));
156 //setPixmap(QWizard::WatermarkPixmap, QPixmap(":icons/quassel-icon.png"));
160 int IntroPage::nextId() const
162 return CoreConfigWizard::AdminUserPage;
166 /*** Admin User Page ***/
168 AdminUserPage::AdminUserPage(QWidget *parent) : QWizardPage(parent)
171 setTitle(tr("Create Admin User"));
172 setSubTitle(tr("First, we will create a user on the core. This first user will have administrator privileges."));
174 registerField("adminUser.user*", ui.user);
175 registerField("adminUser.password*", ui.password);
176 registerField("adminUser.password2*", ui.password2);
177 registerField("adminUser.rememberPasswd", ui.rememberPasswd);
179 //ui.user->setText("foo");
180 //ui.password->setText("foo");
181 //ui.password2->setText("foo");
185 int AdminUserPage::nextId() const
187 return CoreConfigWizard::AuthenticationSelectionPage;
191 bool AdminUserPage::isComplete() const
193 bool ok = !ui.user->text().isEmpty() && !ui.password->text().isEmpty() && ui.password->text() == ui.password2->text();
197 /*** Authentication Selection Page ***/
199 AuthenticationSelectionPage::AuthenticationSelectionPage(const QHash<QString, QVariant> &backends, QWidget *parent)
200 : QWizardPage(parent),
206 setTitle(tr("Select Authentication Backend"));
207 setSubTitle(tr("Please select a backend for Quassel Core to use for authenticating users."));
210 registerField("authentication.backend", ui.backendList);
212 foreach(QString key, _backends.keys()) {
213 ui.backendList->addItem(_backends[key].toMap()["DisplayName"].toString(), key);
216 on_backendList_currentIndexChanged();
220 int AuthenticationSelectionPage::nextId() const
222 return CoreConfigWizard::StorageSelectionPage;
226 QString AuthenticationSelectionPage::selectedBackend() const
228 return ui.backendList->currentText();
232 QVariantMap AuthenticationSelectionPage::connectionProperties() const
234 QString backend = ui.backendList->itemData(ui.backendList->currentIndex()).toString();
236 QVariantMap properties;
237 QStringList setupKeys = _backends[backend].toMap()["SetupKeys"].toStringList();
238 if (!setupKeys.isEmpty()) {
239 QVariantMap defaults = _backends[backend].toMap()["SetupDefaults"].toMap();
240 foreach(QString key, setupKeys) {
241 QWidget *widget = _connectionBox->findChild<QWidget *>(key);
243 if (defaults.contains(key)) {
246 switch (def.type()) {
249 QSpinBox *spinbox = qobject_cast<QSpinBox *>(widget);
251 def = QVariant(spinbox->value());
256 QLineEdit *lineEdit = qobject_cast<QLineEdit *>(widget);
258 def = QVariant(lineEdit->text());
261 properties[key] = def;
264 qDebug() << properties;
266 // QVariantMap properties = _backends[backend].toMap()["ConnectionProperties"].toMap();
267 // if(!properties.isEmpty() && _connectionBox) {
268 // QVariantMap::iterator propertyIter = properties.begin();
269 // while(propertyIter != properties.constEnd()) {
270 // QWidget *widget = _connectionBox->findChild<QWidget *>(propertyIter.key());
271 // switch(propertyIter.value().type()) {
272 // case QVariant::Int:
274 // QSpinBox *spinbox = qobject_cast<QSpinBox *>(widget);
275 // Q_ASSERT(spinbox);
276 // propertyIter.value() = QVariant(spinbox->value());
281 // QLineEdit *lineEdit = qobject_cast<QLineEdit *>(widget);
282 // Q_ASSERT(lineEdit);
283 // propertyIter.value() = QVariant(lineEdit->text());
293 void AuthenticationSelectionPage::on_backendList_currentIndexChanged()
295 QString backend = ui.backendList->itemData(ui.backendList->currentIndex()).toString();
296 ui.description->setText(_backends[backend].toMap()["Description"].toString());
298 if (_connectionBox) {
299 layout()->removeWidget(_connectionBox);
300 _connectionBox->deleteLater();
304 QStringList setupKeys = _backends[backend].toMap()["SetupKeys"].toStringList();
305 if (!setupKeys.isEmpty()) {
306 QVariantMap defaults = _backends[backend].toMap()["SetupDefaults"].toMap();
307 QGroupBox *propertyBox = new QGroupBox(this);
308 propertyBox->setTitle(tr("Connection Properties"));
309 QFormLayout *formlayout = new QFormLayout;
311 foreach(QString key, setupKeys) {
314 if (defaults.contains(key)) {
317 switch (def.type()) {
320 QSpinBox *spinbox = new QSpinBox(propertyBox);
321 spinbox->setMaximum(64000);
322 spinbox->setValue(def.toInt());
328 QLineEdit *lineEdit = new QLineEdit(def.toString(), propertyBox);
329 if (key.toLower().contains("password")) {
330 lineEdit->setEchoMode(QLineEdit::Password);
335 widget->setObjectName(key);
336 formlayout->addRow(key + ":", widget);
338 propertyBox->setLayout(formlayout);
339 static_cast<QVBoxLayout *>(layout())->insertWidget(layout()->indexOf(ui.descriptionBox) + 1, propertyBox);
340 _connectionBox = propertyBox;
344 /*** Storage Selection Page ***/
346 StorageSelectionPage::StorageSelectionPage(const QHash<QString, QVariant> &backends, QWidget *parent)
347 : QWizardPage(parent),
353 setTitle(tr("Select Storage Backend"));
354 setSubTitle(tr("Please select a database backend for the Quassel Core storage to store the backlog and other data in."));
357 registerField("storage.backend", ui.backendList);
359 int defaultIndex = 0;
360 foreach(QString key, _backends.keys()) {
361 ui.backendList->addItem(_backends[key].toMap()["DisplayName"].toString(), key);
362 if (_backends[key].toMap()["IsDefault"].toBool()) {
363 defaultIndex = ui.backendList->count() - 1;
367 ui.backendList->setCurrentIndex(defaultIndex);
369 on_backendList_currentIndexChanged();
373 int StorageSelectionPage::nextId() const
375 return CoreConfigWizard::SyncPage;
379 QString StorageSelectionPage::selectedBackend() const
381 return ui.backendList->currentText();
385 QVariantMap StorageSelectionPage::connectionProperties() const
387 QString backend = ui.backendList->itemData(ui.backendList->currentIndex()).toString();
389 QVariantMap properties;
390 QStringList setupKeys = _backends[backend].toMap()["SetupKeys"].toStringList();
391 if (!setupKeys.isEmpty()) {
392 QVariantMap defaults = _backends[backend].toMap()["SetupDefaults"].toMap();
393 foreach(QString key, setupKeys) {
394 QWidget *widget = _connectionBox->findChild<QWidget *>(key);
396 if (defaults.contains(key)) {
399 switch (def.type()) {
402 QSpinBox *spinbox = qobject_cast<QSpinBox *>(widget);
404 def = QVariant(spinbox->value());
409 QLineEdit *lineEdit = qobject_cast<QLineEdit *>(widget);
411 def = QVariant(lineEdit->text());
414 properties[key] = def;
417 qDebug() << properties;
419 // QVariantMap properties = _backends[backend].toMap()["ConnectionProperties"].toMap();
420 // if(!properties.isEmpty() && _connectionBox) {
421 // QVariantMap::iterator propertyIter = properties.begin();
422 // while(propertyIter != properties.constEnd()) {
423 // QWidget *widget = _connectionBox->findChild<QWidget *>(propertyIter.key());
424 // switch(propertyIter.value().type()) {
425 // case QVariant::Int:
427 // QSpinBox *spinbox = qobject_cast<QSpinBox *>(widget);
428 // Q_ASSERT(spinbox);
429 // propertyIter.value() = QVariant(spinbox->value());
434 // QLineEdit *lineEdit = qobject_cast<QLineEdit *>(widget);
435 // Q_ASSERT(lineEdit);
436 // propertyIter.value() = QVariant(lineEdit->text());
446 void StorageSelectionPage::on_backendList_currentIndexChanged()
448 QString backend = ui.backendList->itemData(ui.backendList->currentIndex()).toString();
449 ui.description->setText(_backends[backend].toMap()["Description"].toString());
451 if (_connectionBox) {
452 layout()->removeWidget(_connectionBox);
453 _connectionBox->deleteLater();
457 QStringList setupKeys = _backends[backend].toMap()["SetupKeys"].toStringList();
458 if (!setupKeys.isEmpty()) {
459 QVariantMap defaults = _backends[backend].toMap()["SetupDefaults"].toMap();
460 QGroupBox *propertyBox = new QGroupBox(this);
461 propertyBox->setTitle(tr("Connection Properties"));
462 QFormLayout *formlayout = new QFormLayout;
464 foreach(QString key, setupKeys) {
467 if (defaults.contains(key)) {
470 switch (def.type()) {
473 QSpinBox *spinbox = new QSpinBox(propertyBox);
474 spinbox->setMaximum(64000);
475 spinbox->setValue(def.toInt());
481 QLineEdit *lineEdit = new QLineEdit(def.toString(), propertyBox);
482 if (key.toLower().contains("password")) {
483 lineEdit->setEchoMode(QLineEdit::Password);
488 widget->setObjectName(key);
489 formlayout->addRow(key + ":", widget);
491 propertyBox->setLayout(formlayout);
492 static_cast<QVBoxLayout *>(layout())->insertWidget(layout()->indexOf(ui.descriptionBox) + 1, propertyBox);
493 _connectionBox = propertyBox;
500 SyncPage::SyncPage(QWidget *parent) : QWizardPage(parent)
503 setTitle(tr("Storing Your Settings"));
504 setSubTitle(tr("Your settings are now stored in the core, and you will be logged in automatically."));
508 void SyncPage::initializePage()
513 // Fill in sync info about the storage layer.
514 StorageSelectionPage *storagePage = qobject_cast<StorageSelectionPage *>(wizard()->page(CoreConfigWizard::StorageSelectionPage));
515 QString backend = storagePage->selectedBackend();
516 QVariantMap properties = storagePage->connectionProperties();
517 Q_ASSERT(!backend.isEmpty());
518 ui.backend->setText(backend);
520 // Fill in synci nfo about the authentication layer.
521 AuthenticationSelectionPage *authPage = qobject_cast<AuthenticationSelectionPage *>(wizard()->page(CoreConfigWizard::AuthenticationSelectionPage));
522 QString authBackend = authPage->selectedBackend();
523 QVariantMap authProperties = authPage->connectionProperties();
524 Q_ASSERT(!authBackend.isEmpty());
525 ui.authBackend->setText(authBackend);
527 ui.user->setText(wizard()->field("adminUser.user").toString());
529 emit setupCore(backend, properties, authBackend, authProperties);
533 int SyncPage::nextId() const
535 if (!hasError) return -1;
536 return CoreConfigWizard::SyncRelayPage;
540 bool SyncPage::isComplete() const
546 void SyncPage::setStatus(const QString &status)
548 ui.status->setText(status);
552 void SyncPage::setError(bool e)
558 void SyncPage::setComplete(bool c)
565 /*** Sync Relay Page ***/
567 SyncRelayPage::SyncRelayPage(QWidget *parent) : QWizardPage(parent)
573 void SyncRelayPage::setMode(Mode m)
580 void SyncRelayPage::initializePage() {
582 if(mode == Success) {
590 int SyncRelayPage::nextId() const
595 }; /* namespace CoreConfigWizardPages */