1 | /*************************************************************************** |
2 | * Copyright (C) 2005-2014 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_OS_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 | coreConnection()->setupCore(Protocol::SetupData(field("adminUser.user" ).toString(), field("adminUser.password" ).toString(), backend, properties)); |
93 | } |
94 | |
95 | |
96 | void CoreConfigWizard::coreSetupSuccess() |
97 | { |
98 | syncPage->setStatus(tr("Your core has been successfully configured. Logging you in..." )); |
99 | syncPage->setError(false); |
100 | syncRelayPage->setMode(CoreConfigWizardPages::SyncRelayPage::Error); |
101 | coreConnection()->loginToCore(field("adminUser.user" ).toString(), field("adminUser.password" ).toString(), field("adminUser.rememberPasswd" ).toBool()); |
102 | } |
103 | |
104 | |
105 | void CoreConfigWizard::coreSetupFailed(const QString &error) |
106 | { |
107 | syncPage->setStatus(tr("Core configuration failed:<br><b>%1</b><br>Press <em>Next</em> to start over." ).arg(error)); |
108 | syncPage->setError(true); |
109 | syncRelayPage->setMode(CoreConfigWizardPages::SyncRelayPage::Error); |
110 | //foreach(int idx, visitedPages()) page(idx)->setEnabled(true); |
111 | //setStartId(SyncPage); |
112 | //restart(); |
113 | } |
114 | |
115 | |
116 | void CoreConfigWizard::startOver() |
117 | { |
118 | foreach(int idx, visitedPages()) page(idx)->setEnabled(true); |
119 | setStartId(CoreConfigWizard::AdminUserPage); |
120 | restart(); |
121 | } |
122 | |
123 | |
124 | void CoreConfigWizard::loginSuccess() |
125 | { |
126 | syncPage->setStatus(tr("Your are now logged into your freshly configured Quassel Core!<br>" |
127 | "Please remember to configure your identities and networks now." )); |
128 | syncPage->setComplete(true); |
129 | syncPage->setFinalPage(true); |
130 | } |
131 | |
132 | |
133 | void CoreConfigWizard::syncFinished() |
134 | { |
135 | accept(); |
136 | } |
137 | |
138 | |
139 | namespace CoreConfigWizardPages { |
140 | /*** Intro Page ***/ |
141 | |
142 | IntroPage::IntroPage(QWidget *parent) : QWizardPage(parent) |
143 | { |
144 | ui.setupUi(this); |
145 | setTitle(tr("Introduction" )); |
146 | //setSubTitle(tr("foobar")); |
147 | //setPixmap(QWizard::WatermarkPixmap, QPixmap(":icons/quassel-icon.png")); |
148 | } |
149 | |
150 | |
151 | int IntroPage::nextId() const |
152 | { |
153 | return CoreConfigWizard::AdminUserPage; |
154 | } |
155 | |
156 | |
157 | /*** Admin User Page ***/ |
158 | |
159 | AdminUserPage::AdminUserPage(QWidget *parent) : QWizardPage(parent) |
160 | { |
161 | ui.setupUi(this); |
162 | setTitle(tr("Create Admin User" )); |
163 | setSubTitle(tr("First, we will create a user on the core. This first user will have administrator privileges." )); |
164 | |
165 | registerField("adminUser.user*" , ui.user); |
166 | registerField("adminUser.password*" , ui.password); |
167 | registerField("adminUser.password2*" , ui.password2); |
168 | registerField("adminUser.rememberPasswd" , ui.rememberPasswd); |
169 | |
170 | //ui.user->setText("foo"); |
171 | //ui.password->setText("foo"); |
172 | //ui.password2->setText("foo"); |
173 | } |
174 | |
175 | |
176 | int AdminUserPage::nextId() const |
177 | { |
178 | return CoreConfigWizard::StorageSelectionPage; |
179 | } |
180 | |
181 | |
182 | bool AdminUserPage::isComplete() const |
183 | { |
184 | bool ok = !ui.user->text().isEmpty() && !ui.password->text().isEmpty() && ui.password->text() == ui.password2->text(); |
185 | return ok; |
186 | } |
187 | |
188 | |
189 | /*** Storage Selection Page ***/ |
190 | |
191 | StorageSelectionPage::StorageSelectionPage(const QHash<QString, QVariant> &backends, QWidget *parent) |
192 | : QWizardPage(parent), |
193 | _connectionBox(0), |
194 | _backends(backends) |
195 | { |
196 | ui.setupUi(this); |
197 | |
198 | setTitle(tr("Select Storage Backend" )); |
199 | setSubTitle(tr("Please select a database backend for the Quassel Core storage to store the backlog and other data in." )); |
200 | setCommitPage(true); |
201 | |
202 | registerField("storage.backend" , ui.backendList); |
203 | |
204 | foreach(QString key, _backends.keys()) { |
205 | ui.backendList->addItem(_backends[key].toMap()["DisplayName" ].toString(), key); |
206 | } |
207 | |
208 | on_backendList_currentIndexChanged(); |
209 | } |
210 | |
211 | |
212 | int StorageSelectionPage::nextId() const |
213 | { |
214 | return CoreConfigWizard::SyncPage; |
215 | } |
216 | |
217 | |
218 | QString StorageSelectionPage::selectedBackend() const |
219 | { |
220 | return ui.backendList->currentText(); |
221 | } |
222 | |
223 | |
224 | QVariantMap StorageSelectionPage::connectionProperties() const |
225 | { |
226 | QString backend = ui.backendList->itemData(ui.backendList->currentIndex()).toString(); |
227 | |
228 | QVariantMap properties; |
229 | QStringList setupKeys = _backends[backend].toMap()["SetupKeys" ].toStringList(); |
230 | if (!setupKeys.isEmpty()) { |
231 | QVariantMap defaults = _backends[backend].toMap()["SetupDefaults" ].toMap(); |
232 | foreach(QString key, setupKeys) { |
233 | QWidget *widget = _connectionBox->findChild<QWidget *>(key); |
234 | QVariant def; |
235 | if (defaults.contains(key)) { |
236 | def = defaults[key]; |
237 | } |
238 | switch (def.type()) { |
239 | case QVariant::Int: |
240 | { |
241 | QSpinBox *spinbox = qobject_cast<QSpinBox *>(widget); |
242 | Q_ASSERT(spinbox); |
243 | def = QVariant(spinbox->value()); |
244 | } |
245 | break; |
246 | default: |
247 | { |
248 | QLineEdit *lineEdit = qobject_cast<QLineEdit *>(widget); |
249 | Q_ASSERT(lineEdit); |
250 | def = QVariant(lineEdit->text()); |
251 | } |
252 | } |
253 | properties[key] = def; |
254 | } |
255 | } |
256 | qDebug() << properties; |
257 | |
258 | // QVariantMap properties = _backends[backend].toMap()["ConnectionProperties"].toMap(); |
259 | // if(!properties.isEmpty() && _connectionBox) { |
260 | // QVariantMap::iterator propertyIter = properties.begin(); |
261 | // while(propertyIter != properties.constEnd()) { |
262 | // QWidget *widget = _connectionBox->findChild<QWidget *>(propertyIter.key()); |
263 | // switch(propertyIter.value().type()) { |
264 | // case QVariant::Int: |
265 | // { |
266 | // QSpinBox *spinbox = qobject_cast<QSpinBox *>(widget); |
267 | // Q_ASSERT(spinbox); |
268 | // propertyIter.value() = QVariant(spinbox->value()); |
269 | // } |
270 | // break; |
271 | // default: |
272 | // { |
273 | // QLineEdit *lineEdit = qobject_cast<QLineEdit *>(widget); |
274 | // Q_ASSERT(lineEdit); |
275 | // propertyIter.value() = QVariant(lineEdit->text()); |
276 | // } |
277 | // } |
278 | // propertyIter++; |
279 | // } |
280 | // } |
281 | return properties; |
282 | } |
283 | |
284 | |
285 | void StorageSelectionPage::on_backendList_currentIndexChanged() |
286 | { |
287 | QString backend = ui.backendList->itemData(ui.backendList->currentIndex()).toString(); |
288 | ui.description->setText(_backends[backend].toMap()["Description" ].toString()); |
289 | |
290 | if (_connectionBox) { |
291 | layout()->removeWidget(_connectionBox); |
292 | _connectionBox->deleteLater(); |
293 | _connectionBox = 0; |
294 | } |
295 | |
296 | QStringList setupKeys = _backends[backend].toMap()["SetupKeys" ].toStringList(); |
297 | if (!setupKeys.isEmpty()) { |
298 | QVariantMap defaults = _backends[backend].toMap()["SetupDefaults" ].toMap(); |
299 | QGroupBox *propertyBox = new QGroupBox(this); |
300 | propertyBox->setTitle(tr("Connection Properties" )); |
301 | QFormLayout *formlayout = new QFormLayout; |
302 | |
303 | foreach(QString key, setupKeys) { |
304 | QWidget *widget = 0; |
305 | QVariant def; |
306 | if (defaults.contains(key)) { |
307 | def = defaults[key]; |
308 | } |
309 | switch (def.type()) { |
310 | case QVariant::Int: |
311 | { |
312 | QSpinBox *spinbox = new QSpinBox(propertyBox); |
313 | spinbox->setMaximum(64000); |
314 | spinbox->setValue(def.toInt()); |
315 | widget = spinbox; |
316 | } |
317 | break; |
318 | default: |
319 | { |
320 | QLineEdit *lineEdit = new QLineEdit(def.toString(), propertyBox); |
321 | if (key.toLower().contains("password" )) { |
322 | lineEdit->setEchoMode(QLineEdit::Password); |
323 | } |
324 | widget = lineEdit; |
325 | } |
326 | } |
327 | widget->setObjectName(key); |
328 | formlayout->addRow(key + ":" , widget); |
329 | } |
330 | propertyBox->setLayout(formlayout); |
331 | static_cast<QVBoxLayout *>(layout())->insertWidget(layout()->indexOf(ui.descriptionBox) + 1, propertyBox); |
332 | _connectionBox = propertyBox; |
333 | } |
334 | } |
335 | |
336 | |
337 | /*** Sync Page ***/ |
338 | |
339 | SyncPage::SyncPage(QWidget *parent) : QWizardPage(parent) |
340 | { |
341 | ui.setupUi(this); |
342 | setTitle(tr("Storing Your Settings" )); |
343 | setSubTitle(tr("Your settings are now stored in the core, and you will be logged in automatically." )); |
344 | } |
345 | |
346 | |
347 | void SyncPage::initializePage() |
348 | { |
349 | complete = false; |
350 | hasError = false; |
351 | |
352 | StorageSelectionPage *storagePage = qobject_cast<StorageSelectionPage *>(wizard()->page(CoreConfigWizard::StorageSelectionPage)); |
353 | QString backend = storagePage->selectedBackend(); |
354 | QVariantMap properties = storagePage->connectionProperties(); |
355 | Q_ASSERT(!backend.isEmpty()); |
356 | ui.user->setText(wizard()->field("adminUser.user" ).toString()); |
357 | ui.backend->setText(backend); |
358 | emit setupCore(backend, properties); |
359 | } |
360 | |
361 | |
362 | int SyncPage::nextId() const |
363 | { |
364 | if (!hasError) return -1; |
365 | return CoreConfigWizard::SyncRelayPage; |
366 | } |
367 | |
368 | |
369 | bool SyncPage::isComplete() const |
370 | { |
371 | return complete; |
372 | } |
373 | |
374 | |
375 | void SyncPage::setStatus(const QString &status) |
376 | { |
377 | ui.status->setText(status); |
378 | } |
379 | |
380 | |
381 | void SyncPage::setError(bool e) |
382 | { |
383 | hasError = e; |
384 | } |
385 | |
386 | |
387 | void SyncPage::setComplete(bool c) |
388 | { |
389 | complete = c; |
390 | completeChanged(); |
391 | } |
392 | |
393 | |
394 | /*** Sync Relay Page ***/ |
395 | |
396 | SyncRelayPage::SyncRelayPage(QWidget *parent) : QWizardPage(parent) |
397 | { |
398 | mode = Success; |
399 | } |
400 | |
401 | |
402 | void SyncRelayPage::setMode(Mode m) |
403 | { |
404 | mode = m; |
405 | } |
406 | |
407 | |
408 | /* |
409 | void SyncRelayPage::initializePage() { |
410 | return; |
411 | if(mode == Success) { |
412 | wizard()->accept(); |
413 | } else { |
414 | emit startOver(); |
415 | } |
416 | } |
417 | */ |
418 | |
419 | int SyncRelayPage::nextId() const |
420 | { |
421 | emit startOver(); |
422 | return 0; |
423 | } |
424 | }; /* namespace CoreConfigWizardPages */ |
425 | |