Fix ALL the license headers!
[quassel.git] / src / qtui / coreconfigwizard.cpp
1 /***************************************************************************
2  *   Copyright (C) 2005-2012 by the Quassel Project                        *
3  *   devel@quassel-irc.org                                                 *
4  *                                                                         *
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.                                           *
9  *                                                                         *
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.                          *
14  *                                                                         *
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  ***************************************************************************/
20
21 #include <QDebug>
22 #include <QAbstractButton>
23 #include <QFormLayout>
24 #include <QSpinBox>
25
26 #include "coreconfigwizard.h"
27 #include "coreconnection.h"
28 #include "iconloader.h"
29
30 CoreConfigWizard::CoreConfigWizard(CoreConnection *connection, const QList<QVariant> &backends, QWidget *parent)
31     : QWizard(parent),
32     _connection(connection)
33 {
34     setModal(true);
35     setAttribute(Qt::WA_DeleteOnClose);
36
37     foreach(const QVariant &v, backends)
38     _backends[v.toMap()["DisplayName"].toString()] = v;
39
40     setPage(IntroPage, new CoreConfigWizardPages::IntroPage(this));
41     setPage(AdminUserPage, new CoreConfigWizardPages::AdminUserPage(this));
42     setPage(StorageSelectionPage, new CoreConfigWizardPages::StorageSelectionPage(_backends, this));
43     syncPage = new CoreConfigWizardPages::SyncPage(this);
44     connect(syncPage, SIGNAL(setupCore(const QString &, const QVariantMap &)), SLOT(prepareCoreSetup(const QString &, const QVariantMap &)));
45     setPage(SyncPage, syncPage);
46     syncRelayPage = new CoreConfigWizardPages::SyncRelayPage(this);
47     connect(syncRelayPage, SIGNAL(startOver()), this, SLOT(startOver()));
48     setPage(SyncRelayPage, syncRelayPage);
49     //setPage(Page_StorageDetails, new StorageDetailsPage());
50     //setPage(Page_Conclusion, new ConclusionPage(storageProviders));
51
52     setStartId(IntroPage);
53     //setStartId(StorageSelectionPage);
54
55 #ifndef Q_WS_MAC
56     setWizardStyle(ModernStyle);
57 #endif
58
59     setOption(HaveHelpButton, false);
60     setOption(NoBackButtonOnStartPage, true);
61     setOption(HaveNextButtonOnLastPage, false);
62     setOption(HaveFinishButtonOnEarlyPages, false);
63     setOption(NoCancelButton, true);
64     setOption(IndependentPages, true);
65     //setOption(ExtendedWatermarkPixmap, true);
66
67     setModal(true);
68
69     setWindowTitle(tr("Core Configuration Wizard"));
70     setPixmap(QWizard::LogoPixmap, DesktopIcon("quassel"));
71
72     connect(connection, SIGNAL(coreSetupSuccess()), SLOT(coreSetupSuccess()));
73     connect(connection, SIGNAL(coreSetupFailed(QString)), SLOT(coreSetupFailed(QString)));
74     //connect(connection, SIGNAL(loginSuccess()), SLOT(loginSuccess()));
75     connect(connection, SIGNAL(synchronized()), SLOT(syncFinished()));
76     connect(this, SIGNAL(rejected()), connection, SLOT(disconnectFromCore()));
77 }
78
79
80 QHash<QString, QVariant> CoreConfigWizard::backends() const
81 {
82     return _backends;
83 }
84
85
86 void CoreConfigWizard::prepareCoreSetup(const QString &backend, const QVariantMap &properties)
87 {
88     // Prevent the user from changing any settings he already specified...
89     foreach(int idx, visitedPages())
90     page(idx)->setEnabled(false);
91
92     QVariantMap foo;
93     foo["AdminUser"] = field("adminUser.user").toString();
94     foo["AdminPasswd"] = field("adminUser.password").toString();
95     foo["Backend"] = backend;
96     foo["ConnectionProperties"] = properties;
97     coreConnection()->doCoreSetup(foo);
98 }
99
100
101 void CoreConfigWizard::coreSetupSuccess()
102 {
103     syncPage->setStatus(tr("Your core has been successfully configured. Logging you in..."));
104     syncPage->setError(false);
105     syncRelayPage->setMode(CoreConfigWizardPages::SyncRelayPage::Error);
106     coreConnection()->loginToCore(field("adminUser.user").toString(), field("adminUser.password").toString(), field("adminUser.rememberPasswd").toBool());
107 }
108
109
110 void CoreConfigWizard::coreSetupFailed(const QString &error)
111 {
112     syncPage->setStatus(tr("Core configuration failed:<br><b>%1</b><br>Press <em>Next</em> to start over.").arg(error));
113     syncPage->setError(true);
114     syncRelayPage->setMode(CoreConfigWizardPages::SyncRelayPage::Error);
115     //foreach(int idx, visitedPages()) page(idx)->setEnabled(true);
116     //setStartId(SyncPage);
117     //restart();
118 }
119
120
121 void CoreConfigWizard::startOver()
122 {
123     foreach(int idx, visitedPages()) page(idx)->setEnabled(true);
124     setStartId(CoreConfigWizard::AdminUserPage);
125     restart();
126 }
127
128
129 void CoreConfigWizard::loginSuccess()
130 {
131     syncPage->setStatus(tr("Your are now logged into your freshly configured Quassel Core!<br>"
132                            "Please remember to configure your identities and networks now."));
133     syncPage->setComplete(true);
134     syncPage->setFinalPage(true);
135 }
136
137
138 void CoreConfigWizard::syncFinished()
139 {
140     accept();
141 }
142
143
144 namespace CoreConfigWizardPages {
145 /*** Intro Page ***/
146
147 IntroPage::IntroPage(QWidget *parent) : QWizardPage(parent)
148 {
149     ui.setupUi(this);
150     setTitle(tr("Introduction"));
151     //setSubTitle(tr("foobar"));
152     //setPixmap(QWizard::WatermarkPixmap, QPixmap(":icons/quassel-icon.png"));
153 }
154
155
156 int IntroPage::nextId() const
157 {
158     return CoreConfigWizard::AdminUserPage;
159 }
160
161
162 /*** Admin User Page ***/
163
164 AdminUserPage::AdminUserPage(QWidget *parent) : QWizardPage(parent)
165 {
166     ui.setupUi(this);
167     setTitle(tr("Create Admin User"));
168     setSubTitle(tr("First, we will create a user on the core. This first user will have administrator privileges."));
169
170     registerField("adminUser.user*", ui.user);
171     registerField("adminUser.password*", ui.password);
172     registerField("adminUser.password2*", ui.password2);
173     registerField("adminUser.rememberPasswd", ui.rememberPasswd);
174
175     //ui.user->setText("foo");
176     //ui.password->setText("foo");
177     //ui.password2->setText("foo");
178 }
179
180
181 int AdminUserPage::nextId() const
182 {
183     return CoreConfigWizard::StorageSelectionPage;
184 }
185
186
187 bool AdminUserPage::isComplete() const
188 {
189     bool ok = !ui.user->text().isEmpty() && !ui.password->text().isEmpty() && ui.password->text() == ui.password2->text();
190     return ok;
191 }
192
193
194 /*** Storage Selection Page ***/
195
196 StorageSelectionPage::StorageSelectionPage(const QHash<QString, QVariant> &backends, QWidget *parent)
197     : QWizardPage(parent),
198     _connectionBox(0),
199     _backends(backends)
200 {
201     ui.setupUi(this);
202
203     setTitle(tr("Select Storage Backend"));
204     setSubTitle(tr("Please select a database backend for the Quassel Core storage to store the backlog and other data in."));
205     setCommitPage(true);
206
207     registerField("storage.backend", ui.backendList);
208
209     foreach(QString key, _backends.keys()) {
210         ui.backendList->addItem(_backends[key].toMap()["DisplayName"].toString(), key);
211     }
212
213     on_backendList_currentIndexChanged();
214 }
215
216
217 int StorageSelectionPage::nextId() const
218 {
219     return CoreConfigWizard::SyncPage;
220 }
221
222
223 QString StorageSelectionPage::selectedBackend() const
224 {
225     return ui.backendList->currentText();
226 }
227
228
229 QVariantMap StorageSelectionPage::connectionProperties() const
230 {
231     QString backend = ui.backendList->itemData(ui.backendList->currentIndex()).toString();
232
233     QVariantMap properties;
234     QStringList setupKeys = _backends[backend].toMap()["SetupKeys"].toStringList();
235     if (!setupKeys.isEmpty()) {
236         QVariantMap defaults = _backends[backend].toMap()["SetupDefaults"].toMap();
237         foreach(QString key, setupKeys) {
238             QWidget *widget = _connectionBox->findChild<QWidget *>(key);
239             QVariant def;
240             if (defaults.contains(key)) {
241                 def = defaults[key];
242             }
243             switch (def.type()) {
244             case QVariant::Int:
245             {
246                 QSpinBox *spinbox = qobject_cast<QSpinBox *>(widget);
247                 Q_ASSERT(spinbox);
248                 def = QVariant(spinbox->value());
249             }
250             break;
251             default:
252             {
253                 QLineEdit *lineEdit = qobject_cast<QLineEdit *>(widget);
254                 Q_ASSERT(lineEdit);
255                 def = QVariant(lineEdit->text());
256             }
257             }
258             properties[key] = def;
259         }
260     }
261     qDebug() << properties;
262
263 //   QVariantMap properties = _backends[backend].toMap()["ConnectionProperties"].toMap();
264 //   if(!properties.isEmpty() && _connectionBox) {
265 //     QVariantMap::iterator propertyIter = properties.begin();
266 //     while(propertyIter != properties.constEnd()) {
267 //       QWidget *widget = _connectionBox->findChild<QWidget *>(propertyIter.key());
268 //       switch(propertyIter.value().type()) {
269 //       case QVariant::Int:
270 //      {
271 //        QSpinBox *spinbox = qobject_cast<QSpinBox *>(widget);
272 //        Q_ASSERT(spinbox);
273 //        propertyIter.value() = QVariant(spinbox->value());
274 //      }
275 //      break;
276 //       default:
277 //      {
278 //        QLineEdit *lineEdit = qobject_cast<QLineEdit *>(widget);
279 //        Q_ASSERT(lineEdit);
280 //        propertyIter.value() = QVariant(lineEdit->text());
281 //      }
282 //       }
283 //       propertyIter++;
284 //     }
285 //   }
286     return properties;
287 }
288
289
290 void StorageSelectionPage::on_backendList_currentIndexChanged()
291 {
292     QString backend = ui.backendList->itemData(ui.backendList->currentIndex()).toString();
293     ui.description->setText(_backends[backend].toMap()["Description"].toString());
294
295     if (_connectionBox) {
296         layout()->removeWidget(_connectionBox);
297         _connectionBox->deleteLater();
298         _connectionBox = 0;
299     }
300
301     QStringList setupKeys = _backends[backend].toMap()["SetupKeys"].toStringList();
302     if (!setupKeys.isEmpty()) {
303         QVariantMap defaults = _backends[backend].toMap()["SetupDefaults"].toMap();
304         QGroupBox *propertyBox = new QGroupBox(this);
305         propertyBox->setTitle(tr("Connection Properties"));
306         QFormLayout *formlayout = new QFormLayout;
307
308         foreach(QString key, setupKeys) {
309             QWidget *widget = 0;
310             QVariant def;
311             if (defaults.contains(key)) {
312                 def = defaults[key];
313             }
314             switch (def.type()) {
315             case QVariant::Int:
316             {
317                 QSpinBox *spinbox = new QSpinBox(propertyBox);
318                 spinbox->setMaximum(64000);
319                 spinbox->setValue(def.toInt());
320                 widget = spinbox;
321             }
322             break;
323             default:
324             {
325                 QLineEdit *lineEdit = new QLineEdit(def.toString(), propertyBox);
326                 if (key.toLower().contains("password")) {
327                     lineEdit->setEchoMode(QLineEdit::Password);
328                 }
329                 widget = lineEdit;
330             }
331             }
332             widget->setObjectName(key);
333             formlayout->addRow(key + ":", widget);
334         }
335         propertyBox->setLayout(formlayout);
336         static_cast<QVBoxLayout *>(layout())->insertWidget(layout()->indexOf(ui.descriptionBox) + 1, propertyBox);
337         _connectionBox = propertyBox;
338     }
339 }
340
341
342 /*** Sync Page ***/
343
344 SyncPage::SyncPage(QWidget *parent) : QWizardPage(parent)
345 {
346     ui.setupUi(this);
347     setTitle(tr("Storing Your Settings"));
348     setSubTitle(tr("Your settings are now stored in the core, and you will be logged in automatically."));
349 }
350
351
352 void SyncPage::initializePage()
353 {
354     complete = false;
355     hasError = false;
356
357     StorageSelectionPage *storagePage = qobject_cast<StorageSelectionPage *>(wizard()->page(CoreConfigWizard::StorageSelectionPage));
358     QString backend = storagePage->selectedBackend();
359     QVariantMap properties = storagePage->connectionProperties();
360     Q_ASSERT(!backend.isEmpty());
361     ui.user->setText(wizard()->field("adminUser.user").toString());
362     ui.backend->setText(backend);
363     emit setupCore(backend, properties);
364 }
365
366
367 int SyncPage::nextId() const
368 {
369     if (!hasError) return -1;
370     return CoreConfigWizard::SyncRelayPage;
371 }
372
373
374 bool SyncPage::isComplete() const
375 {
376     return complete;
377 }
378
379
380 void SyncPage::setStatus(const QString &status)
381 {
382     ui.status->setText(status);
383 }
384
385
386 void SyncPage::setError(bool e)
387 {
388     hasError = e;
389 }
390
391
392 void SyncPage::setComplete(bool c)
393 {
394     complete = c;
395     completeChanged();
396 }
397
398
399 /*** Sync Relay Page ***/
400
401 SyncRelayPage::SyncRelayPage(QWidget *parent) : QWizardPage(parent)
402 {
403     mode = Success;
404 }
405
406
407 void SyncRelayPage::setMode(Mode m)
408 {
409     mode = m;
410 }
411
412
413 /*
414 void SyncRelayPage::initializePage() {
415   return;
416   if(mode == Success) {
417     wizard()->accept();
418   } else {
419     emit startOver();
420   }
421 }
422 */
423
424 int SyncRelayPage::nextId() const
425 {
426     emit startOver();
427     return 0;
428 }
429 };  /* namespace CoreConfigWizardPages */