From 97d674034551438238c568e8b42efb08e1ba7354 Mon Sep 17 00:00:00 2001 From: Marco Genise Date: Mon, 5 Nov 2007 20:48:46 +0000 Subject: [PATCH] Ok, the long awaited config wizard is here (at least in a very basic state). There are some quicky & dirty hacks to be able to test some functionality, which will be removed/replaced later. --- src/client/client.cpp | 13 +- src/client/client.h | 4 + src/common/global.cpp | 1 - src/common/global.h | 1 - src/common/main.cpp | 1 - src/core/core.cpp | 150 +++++++++++++++++--- src/core/core.h | 11 +- src/core/core.pri | 4 +- src/core/coresession.cpp | 1 - src/core/coresettings.cpp | 59 ++++++++ src/core/coresettings.h | 48 +++++++ src/core/sqlitestorage.cpp | 270 ++++++++++++++++++++---------------- src/core/sqlitestorage.h | 19 +-- src/core/storage.cpp | 96 ------------- src/core/storage.h | 46 ++---- src/qtui/configwizard.cpp | 202 +++++++++++++++++++++++++++ src/qtui/configwizard.h | 120 ++++++++++++++++ src/qtui/coreconnectdlg.cpp | 24 ++++ src/qtui/coreconnectdlg.h | 4 +- src/qtui/qtui.pri | 7 +- 20 files changed, 780 insertions(+), 301 deletions(-) create mode 100644 src/core/coresettings.cpp create mode 100644 src/core/coresettings.h create mode 100644 src/qtui/configwizard.cpp create mode 100644 src/qtui/configwizard.h diff --git a/src/client/client.cpp b/src/client/client.cpp index 2500b273..28df0877 100644 --- a/src/client/client.cpp +++ b/src/client/client.cpp @@ -247,6 +247,10 @@ void Client::disconnectFromCore() { } } +void Client::setCoreConfiguration(const QVariantMap &settings) { + writeDataToDevice(socket, settings); +} + void Client::coreSocketConnected() { connect(this, SIGNAL(recvPartialItem(uint, uint)), this, SIGNAL(coreConnectionProgress(uint, uint))); emit coreConnectionMsg(tr("Synchronizing to core...")); @@ -415,7 +419,14 @@ void Client::coreHasData() { QVariant item; if(readDataFromDevice(socket, blockSize, item)) { emit recvPartialItem(1,1); - recvCoreState(item); + QVariantMap msg = item.toMap(); + if (!msg["StartWizard"].toBool()) { + recvCoreState(msg["Reply"]); + } else { + qWarning("Core not configured!"); + qDebug() << "Available storage providers: " << msg["StorageProviders"].toStringList(); + emit showConfigWizard(msg); + } blockSize = 0; return; } diff --git a/src/client/client.h b/src/client/client.h index 349b5ab2..f3ac138e 100644 --- a/src/client/client.h +++ b/src/client/client.h @@ -89,6 +89,8 @@ signals: void coreConnectionError(QString errorMsg); void coreConnectionMsg(const QString &msg); void coreConnectionProgress(uint part, uint total); + + void showConfigWizard(const QVariantMap &coredata); void connected(); void disconnected(); @@ -102,6 +104,8 @@ public slots: //void connectToLocalCore(); void connectToCore(const QVariantMap &); void disconnectFromCore(); + + void setCoreConfiguration(const QVariantMap &settings); private slots: void recvCoreState(const QVariant &state); diff --git a/src/common/global.cpp b/src/common/global.cpp index cdb33765..954e52b2 100644 --- a/src/common/global.cpp +++ b/src/common/global.cpp @@ -60,4 +60,3 @@ void Global::initIconMap() { //} Global::RunMode Global::runMode; -QString Global::quasselDir; diff --git a/src/common/global.h b/src/common/global.h index 6da6103c..33d52f4c 100644 --- a/src/common/global.h +++ b/src/common/global.h @@ -44,7 +44,6 @@ typedef uint NetworkId; namespace Global { enum RunMode { Monolithic, ClientOnly, CoreOnly }; extern RunMode runMode; - extern QString quasselDir; } struct Exception { diff --git a/src/common/main.cpp b/src/common/main.cpp index fc5c0f7f..3ca8e34d 100644 --- a/src/common/main.cpp +++ b/src/common/main.cpp @@ -85,7 +85,6 @@ int main(int argc, char **argv) { QCoreApplication::setApplicationName("Quassel IRC"); QCoreApplication::setOrganizationName("Quassel IRC Development Team"); - Global::quasselDir = QDir::homePath() + "/.quassel"; #ifndef BUILD_QTUI Core::instance(); // create and init the core #endif diff --git a/src/core/core.cpp b/src/core/core.cpp index 7b576618..9bd36fbe 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -20,9 +20,13 @@ #include "core.h" #include "coresession.h" +#include "coresettings.h" #include "sqlitestorage.h" #include "util.h" +#include +#include + Core *Core::instanceptr = 0; Core *Core::instance() { @@ -38,22 +42,54 @@ void Core::destroy() { } Core::Core() { + storage = NULL; } void Core::init() { - if(!SqliteStorage::isAvailable()) { - qFatal("Sqlite is currently required! Please make sure your Qt library has sqlite support enabled."); + CoreSettings s; + configured = false; + + QVariantMap dbSettings = s.databaseSettings().toMap(); + QString hname = dbSettings["Type"].toString().toLower(); + hname[0] = hname[0].toUpper(); + hname = "initStorage" + hname; + if (!QMetaObject::invokeMethod(this, hname.toAscii(), Q_RETURN_ARG(bool, configured), Q_ARG(QVariantMap, dbSettings), Q_ARG(bool, false))) { + qWarning("No database backend configured."); } - //SqliteStorage::init(); - storage = new SqliteStorage(); + + if (!configured) { + qWarning("Core is currently not configured!"); + } + connect(&server, SIGNAL(newConnection()), this, SLOT(incomingConnection())); - startListening(); // FIXME make configurable + startListening(s.port()); guiUser = 0; } +bool Core::initStorageSqlite(QVariantMap dbSettings, bool setup) { + if (!SqliteStorage::isAvailable()) { + qFatal("Sqlite is currently required! Please make sure your Qt library has sqlite support enabled."); + } + if (storage) { + qDebug() << "Deleting old storage object."; + delete storage; + storage = NULL; + } + + storage = new SqliteStorage(); + if (setup && !storage->setup(dbSettings)) { + return false; + } + + return storage->init(dbSettings); +} + Core::~Core() { qDeleteAll(sessions); - delete storage; + if (storage) { + delete storage; + storage = NULL; + } } CoreSession *Core::session(UserId uid) { @@ -76,7 +112,6 @@ CoreSession *Core::createSession(UserId uid) { return sess; } - bool Core::startListening(uint port) { if(!server.listen(QHostAddress::Any, port)) { qWarning(QString(QString("Could not open GUI client port %1: %2").arg(port).arg(server.errorString())).toAscii()); @@ -93,12 +128,18 @@ void Core::stopListening() { void Core::incomingConnection() { // TODO implement SSL - // TODO While - QTcpSocket *socket = server.nextPendingConnection(); - connect(socket, SIGNAL(disconnected()), this, SLOT(clientDisconnected())); - connect(socket, SIGNAL(readyRead()), this, SLOT(clientHasData())); - blockSizes.insert(socket, (quint32)0); - qDebug() << "Client connected from " << socket->peerAddress().toString(); + while (server.hasPendingConnections()) { + QTcpSocket *socket = server.nextPendingConnection(); + connect(socket, SIGNAL(disconnected()), this, SLOT(clientDisconnected())); + connect(socket, SIGNAL(readyRead()), this, SLOT(clientHasData())); + blockSizes.insert(socket, (quint32)0); + qDebug() << "Client connected from " << socket->peerAddress().toString(); + + if (!configured) { + server.close(); + qDebug() << "Closing server for basic setup."; + } + } } void Core::clientHasData() { @@ -109,7 +150,15 @@ void Core::clientHasData() { if(readDataFromDevice(socket, bsize, item)) { // we need to auth the client try { - processClientInit(socket, item); + QVariantMap msg = item.toMap(); + if (msg["GuiProtocol"].toUInt() != GUI_PROTOCOL) { + throw Exception("GUI client version mismatch"); + } + if (configured) { + processClientInit(socket, msg); + } else { + processCoreSetup(socket, msg); + } } catch(Storage::AuthError) { qWarning() << "Authentification error!"; // FIXME: send auth error to client socket->close(); @@ -124,10 +173,17 @@ void Core::clientHasData() { } // FIXME: no longer called, since connection handling is now in SignalProxy +// No, it is called as long as core is not configured. (kaffeedoktor) void Core::clientDisconnected() { QTcpSocket *socket = dynamic_cast(sender()); blockSizes.remove(socket); qDebug() << "Client disconnected."; + + // make server listen again if still not configured + if (!configured) { + startListening(); + } + // TODO remove unneeded sessions - if necessary/possible... } @@ -144,21 +200,58 @@ void Core::disconnectLocalClient() { instance()->guiUser = 0; } -void Core::processClientInit(QTcpSocket *socket, const QVariant &v) { - QVariantMap msg = v.toMap(); - if(msg["GuiProtocol"].toUInt() != GUI_PROTOCOL) { - //qWarning() << "Client version mismatch."; - throw Exception("GUI client version mismatch"); - } - // Auth - UserId uid = storage->validateUser(msg["User"].toString(), msg["Password"].toString()); // throws exception if this failed - QVariant reply = initSession(uid); +void Core::processClientInit(QTcpSocket *socket, const QVariantMap &msg) { + // Auth + QVariantMap reply; + UserId uid = storage->validateUser(msg["User"].toString(), msg["Password"].toString()); // throws exception if this failed + reply["StartWizard"] = false; + reply["Reply"] = initSession(uid); disconnect(socket, 0, this, 0); sessions[uid]->addClient(socket); qDebug() << "Client initialized successfully."; writeDataToDevice(socket, reply); } +void Core::processCoreSetup(QTcpSocket *socket, QVariantMap &msg) { + if(msg["HasSettings"].toBool()) { + QVariantMap auth; + auth["User"] = msg["User"]; + auth["Password"] = msg["Password"]; + msg.remove("User"); + msg.remove("Password"); + qDebug() << "Initializing storage provider" << msg["Type"].toString(); + QString hname = msg["Type"].toString().toLower(); + hname[0] = hname[0].toUpper(); + hname = "initStorage" + hname; + if (!QMetaObject::invokeMethod(this, hname.toAscii(), Q_RETURN_ARG(bool, configured), Q_ARG(QVariantMap, msg), Q_ARG(bool, true))) { + qWarning("No database backend configured."); + } + if (!configured) { + // notify client to start wizard again + qWarning("Core is currently not configured!"); + QVariantMap reply; + reply["StartWizard"] = true; + reply["StorageProviders"] = availableStorageProviders(); + writeDataToDevice(socket, reply); + } else { + // write coresettings + CoreSettings s; + s.setDatabaseSettings(msg); + // write admin user to database & make the core listen again to connections + storage->addUser(auth["User"].toString(), auth["Password"].toString()); + startListening(); + // continue the normal procedure + processClientInit(socket, auth); + } + } else { + // notify client to start wizard + QVariantMap reply; + reply["StartWizard"] = true; + reply["StorageProviders"] = availableStorageProviders(); + writeDataToDevice(socket, reply); + } +} + QVariant Core::initSession(UserId uid) { // Find or create session for validated user CoreSession *sess; @@ -170,3 +263,14 @@ QVariant Core::initSession(UserId uid) { reply["SessionState"] = sess->sessionState(); return reply; } + +QStringList Core::availableStorageProviders() { + QStringList storageProviders; + if (SqliteStorage::isAvailable()) { + storageProviders.append(SqliteStorage::displayName()); + } + // TODO: temporary + storageProviders.append("MySQL"); + + return storageProviders; +} diff --git a/src/core/core.h b/src/core/core.h index 5e73b7c8..602f7bf4 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -52,12 +52,14 @@ class Core : public QObject { void clientHasData(); void clientDisconnected(); + bool initStorageSqlite(QVariantMap dbSettings, bool setup); + private: Core(); ~Core(); void init(); static Core *instanceptr; - + //! Initiate a session for the user with the given credentials if one does not already exist. /** This function is called during the init process for a new client. If there is no session for the * given user, one is created. @@ -65,7 +67,10 @@ class Core : public QObject { * \return A QVariant containing the session data, e.g. global data and buffers */ QVariant initSession(UserId userId); - void processClientInit(QTcpSocket *socket, const QVariant &v); + void processClientInit(QTcpSocket *socket, const QVariantMap &msg); + void processCoreSetup(QTcpSocket *socket, QVariantMap &msg); + + QStringList availableStorageProviders(); UserId guiUser; QHash sessions; @@ -73,6 +78,8 @@ class Core : public QObject { QTcpServer server; // TODO: implement SSL QHash blockSizes; + + bool configured; }; #endif diff --git a/src/core/core.pri b/src/core/core.pri index 7f6c68f9..13e537dc 100644 --- a/src/core/core.pri +++ b/src/core/core.pri @@ -1,4 +1,4 @@ DEPMOD = common QT_MOD = core network sql -SRCS = core.cpp coresession.cpp server.cpp sqlitestorage.cpp storage.cpp basichandler.cpp ircserverhandler.cpp userinputhandler.cpp ctcphandler.cpp -HDRS = core.h coresession.h server.h sqlitestorage.h storage.h basichandler.h ircserverhandler.h userinputhandler.h ctcphandler.h +SRCS = core.cpp coresession.cpp coresettings.cpp server.cpp sqlitestorage.cpp storage.cpp basichandler.cpp ircserverhandler.cpp userinputhandler.cpp ctcphandler.cpp +HDRS = core.h coresession.h coresettings.h server.h sqlitestorage.h storage.h basichandler.h ircserverhandler.h userinputhandler.h ctcphandler.h diff --git a/src/core/coresession.cpp b/src/core/coresession.cpp index 0cec934e..0accebbf 100644 --- a/src/core/coresession.cpp +++ b/src/core/coresession.cpp @@ -52,7 +52,6 @@ CoreSession::CoreSession(UserId uid, Storage *_storage, QObject *parent) p->attachSlot(SIGNAL(requestNetworkStates()), this, SLOT(serverStateRequested())); p->attachSlot(SIGNAL(requestConnect(QString)), this, SLOT(connectToNetwork(QString))); p->attachSlot(SIGNAL(sendInput(BufferInfo, QString)), this, SLOT(msgFromGui(BufferInfo, QString))); - p->attachSlot(SIGNAL(importOldBacklog()), storage, SLOT(importOldBacklog())); p->attachSlot(SIGNAL(requestBacklog(BufferInfo, QVariant, QVariant)), this, SLOT(sendBacklog(BufferInfo, QVariant, QVariant))); p->attachSignal(this, SIGNAL(displayMsg(Message))); p->attachSignal(this, SIGNAL(displayStatusMsg(QString, QString))); diff --git a/src/core/coresettings.cpp b/src/core/coresettings.cpp new file mode 100644 index 00000000..579713a0 --- /dev/null +++ b/src/core/coresettings.cpp @@ -0,0 +1,59 @@ +/*************************************************************************** + * Copyright (C) 2005-07 by The Quassel IRC Development Team * + * devel@quassel-irc.org * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include "coresettings.h" + +#include + +CoreSettings::CoreSettings() : Settings("Core") { +} + +CoreSettings::~CoreSettings() { +} + +void CoreSettings::setDatabaseSettings(const QVariant &data) { + setLocalValue("DatabaseSettings", data); +} + +QVariant CoreSettings::databaseSettings(const QVariant &def) { + return localValue("DatabaseSettings", def); +} + +void CoreSettings::setPort(const uint &port) { + setLocalValue("Port", port); +} + +uint CoreSettings::port(const uint &def) { + return localValue("Port", def).toUInt(); +} + +QStringList CoreSettings::sessionKeys() { + Q_ASSERT(false); + return QStringList(); +} + +void CoreSettings::setSessionValue(const QString &key, const QVariant &data) { + Q_ASSERT(false); +} + +QVariant CoreSettings::sessionValue(const QString &key, const QVariant &def) { + Q_ASSERT(false); + return QVariant(); +} diff --git a/src/core/coresettings.h b/src/core/coresettings.h new file mode 100644 index 00000000..8c19d732 --- /dev/null +++ b/src/core/coresettings.h @@ -0,0 +1,48 @@ +/*************************************************************************** + * Copyright (C) 2005-07 by The Quassel IRC Development Team * + * devel@quassel-irc.org * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#ifndef CORESETTINGS_H_ +#define CORESETTINGS_H_ + +#include "settings.h" +#include "global.h" + +class CoreSettings : public Settings { + Q_OBJECT + + public: + virtual ~CoreSettings(); + CoreSettings(); + + void setDatabaseSettings(const QVariant &data); + QVariant databaseSettings(const QVariant &def = QVariant()); + + void setPort(const uint &port); + uint port(const uint &def = DEFAULT_PORT); + + private: + //virtual QStringList allSessionKeys() = 0; + virtual QStringList sessionKeys(); + + virtual void setSessionValue(const QString &key, const QVariant &data); + virtual QVariant sessionValue(const QString &key, const QVariant &def = QVariant()); +}; + +#endif /*CORESETTINGS_H_*/ diff --git a/src/core/sqlitestorage.cpp b/src/core/sqlitestorage.cpp index ffd28728..fcb0700d 100644 --- a/src/core/sqlitestorage.cpp +++ b/src/core/sqlitestorage.cpp @@ -23,17 +23,135 @@ #include SqliteStorage::SqliteStorage() { - // TODO I don't think that this path is failsafe for windows users :) - QString backlogFile = Global::quasselDir + "/quassel-storage.sqlite"; - logDb = QSqlDatabase::addDatabase("QSQLITE"); - logDb.setDatabaseName(backlogFile); - bool ok = logDb.open(); - - if(!ok) { - qWarning(tr("Could not open backlog database: %1").arg(logDb.lastError().text()).toAscii()); - qWarning(tr("Disabling logging...").toAscii()); - Q_ASSERT(ok); - return; + logMessageQuery = NULL; + addSenderQuery = NULL; + getLastMessageIdQuery = NULL; + requestMsgsQuery = NULL; + requestMsgsOffsetQuery = NULL; + requestMsgsSinceQuery = NULL; + requestMsgsSinceOffsetQuery = NULL; + requestMsgRangeQuery = NULL; + createNetworkQuery = NULL; + createBufferQuery = NULL; + getBufferInfoQuery = NULL; +} + +SqliteStorage::~SqliteStorage() { + if (logMessageQuery) delete logMessageQuery; + if (addSenderQuery) delete addSenderQuery; + if (getLastMessageIdQuery) delete getLastMessageIdQuery; + if (requestMsgsQuery) delete requestMsgsQuery; + if (requestMsgsOffsetQuery) delete requestMsgsOffsetQuery; + if (requestMsgsSinceQuery) delete requestMsgsSinceQuery; + if (requestMsgsSinceOffsetQuery) delete requestMsgsSinceOffsetQuery; + if (requestMsgRangeQuery) delete requestMsgRangeQuery; + if (createNetworkQuery) delete createNetworkQuery; + if (createBufferQuery) delete createBufferQuery; + if (getBufferInfoQuery) delete getBufferInfoQuery; + + logDb.close(); +} + +bool SqliteStorage::isAvailable() { + if(!QSqlDatabase::isDriverAvailable("QSQLITE")) return false; + return true; +} + +QString SqliteStorage::displayName() { + return QString("SQlite"); +} + +bool SqliteStorage::setup(const QVariantMap &settings) { + bool ok; + // this extra scope is needed to be able to remove the database connection later + { + logDb = QSqlDatabase::addDatabase("QSQLITE", "quassel_setup"); + logDb.setDatabaseName(SqliteStorage::backlogFile(true)); + bool ok = logDb.open(); + + if (!ok) { + qWarning(tr("Could not open backlog database: %1").arg(logDb.lastError().text()).toAscii()); + } else { + logDb.exec("CREATE TABLE quasseluser (" + "userid INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT," + "username TEXT UNIQUE NOT NULL," + "password BLOB NOT NULL)"); + + logDb.exec("CREATE TABLE sender (" + "senderid INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT," + "sender TEXT UNIQUE NOT NULL)"); + + logDb.exec("CREATE TABLE network (" + "networkid INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT," + "userid INTEGER NOT NULL," + "networkname TEXT NOT NULL," + "UNIQUE (userid, networkname))"); + + logDb.exec("CREATE TABLE buffergroup (" + "groupid INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT," + "userid INTEGER NOT NULL," + "displayname TEXT)"); + + logDb.exec("CREATE TABLE buffer (" + "bufferid INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT," + "userid INTEGER NOT NULL," + "groupid INTEGER," + "networkid INTEGER NOT NULL," + "buffername TEXT NOT NULL)"); + + logDb.exec("CREATE UNIQUE INDEX buffer_idx " + "ON buffer(userid, networkid, buffername)"); + + logDb.exec("CREATE TABLE backlog (" + "messageid INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT," + "time INTEGER NOT NULL," + "bufferid INTEGER NOT NULL," + "type INTEGER NOT NULL," + "flags INTEGER NOT NULL," + "senderid INTEGER NOT NULL," + "message TEXT)"); + + logDb.exec("CREATE TABLE coreinfo (" + "updateid INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT," + "version INTEGER NOT NULL)"); + + logDb.exec("INSERT INTO coreinfo (version) VALUES (0)"); + + // something fucked up -> no logging possible + // FIXME logDb.lastError is reset whenever exec is called + if(logDb.lastError().isValid()) { + qWarning(tr("Could not create backlog table: %1").arg(logDb.lastError().text()).toAscii()); + qWarning(tr("Disabling logging...").toAscii()); + Q_ASSERT(false); // quassel does require logging + ok = false; + } + + logDb.close(); + } + } + + QSqlDatabase::removeDatabase("quassel_setup"); + return ok; +} + +bool SqliteStorage::init(const QVariantMap &settings) { + bool ok; + // i need the extra scope to be able to remove the database connection + { + logDb = QSqlDatabase::database("quassel_connection", false); + if (!logDb.isValid()) { + logDb = QSqlDatabase::addDatabase("QSQLITE", "quassel_connection"); + } + logDb.setDatabaseName(SqliteStorage::backlogFile()); + ok = logDb.open(); + if (!ok) { + qWarning(tr("Could not open backlog database: %1").arg(logDb.lastError().text()).toAscii()); + } + } + + if (!ok) { + //QSqlDatabase::removeDatabase("quassel_connection"); + return false; } // check if the db schema is up to date @@ -43,7 +161,8 @@ SqliteStorage::SqliteStorage() { //checkVersion(query.value(0)); qDebug() << "Sqlite is ready. Quassel Schema Version:" << query.value(0).toUInt(); } else { - initDb(); + qWarning("Sqlite is not ready!"); + return false; } // we will need those pretty often... so let's speed things up: @@ -105,93 +224,10 @@ SqliteStorage::SqliteStorage() { "WHERE (buffer.bufferid = :bufferid OR buffer.groupid = (SELECT groupid FROM buffer WHERE bufferid = :bufferid2)) AND " "backlog.messageid >= :firstmsg AND backlog.messageid <= :lastmsg " "ORDER BY messageid DESC "); - -} - -SqliteStorage::~SqliteStorage() { - //logDb.close(); - delete logMessageQuery; - delete addSenderQuery; - delete getLastMessageIdQuery; - delete requestMsgsQuery; - delete requestMsgsOffsetQuery; - delete requestMsgsSinceQuery; - delete requestMsgsSinceOffsetQuery; - delete requestMsgRangeQuery; - delete createNetworkQuery; - delete createBufferQuery; - delete getBufferInfoQuery; - logDb.close(); -} - - -void SqliteStorage::initDb() { - logDb.exec("CREATE TABLE quasseluser (" - "userid INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT," - "username TEXT UNIQUE NOT NULL," - "password BLOB NOT NULL)"); - - logDb.exec("CREATE TABLE sender (" - "senderid INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT," - "sender TEXT UNIQUE NOT NULL)"); - logDb.exec("CREATE TABLE network (" - "networkid INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT," - "userid INTEGER NOT NULL," - "networkname TEXT NOT NULL," - "UNIQUE (userid, networkname))"); - - logDb.exec("CREATE TABLE buffergroup (" - "groupid INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT," - "userid INTEGER NOT NULL," - "displayname TEXT)"); - - logDb.exec("CREATE TABLE buffer (" - "bufferid INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT," - "userid INTEGER NOT NULL," - "groupid INTEGER," - "networkid INTEGER NOT NULL," - "buffername TEXT NOT NULL)"); - - logDb.exec("CREATE UNIQUE INDEX buffer_idx " - "ON buffer(userid, networkid, buffername)"); - - logDb.exec("CREATE TABLE backlog (" - "messageid INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT," - "time INTEGER NOT NULL," - "bufferid INTEGER NOT NULL," - "type INTEGER NOT NULL," - "flags INTEGER NOT NULL," - "senderid INTEGER NOT NULL," - "message TEXT)"); - - logDb.exec("CREATE TABLE coreinfo (" - "updateid INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT," - "version INTEGER NOT NULL)"); - - logDb.exec("INSERT INTO coreinfo (version) VALUES (0)"); - - - // something fucked up -> no logging possible - // FIXME logDb.lastError is reset whenever exec is called - if(logDb.lastError().isValid()) { - qWarning(tr("Could not create backlog table: %1").arg(logDb.lastError().text()).toAscii()); - qWarning(tr("Disabling logging...").toAscii()); - Q_ASSERT(false); // quassel does require logging - } - - addUser("Default", "password"); -} - -bool SqliteStorage::isAvailable() { - if(!QSqlDatabase::isDriverAvailable("QSQLITE")) return false; return true; } -QString SqliteStorage::displayName() { - return QString("SqliteStorage"); -} - UserId SqliteStorage::addUser(const QString &user, const QString &password) { QByteArray cryptopass = QCryptographicHash::hash(password.toUtf8(), QCryptographicHash::Sha1); cryptopass = cryptopass.toHex(); @@ -483,36 +519,24 @@ QList SqliteStorage::requestMsgRange(BufferInfo buffer, int first, int return messagelist; } -void SqliteStorage::importOldBacklog() { - QSqlQuery query(logDb); - int user; - query.prepare("SELECT MIN(userid) FROM quasseluser"); - query.exec(); - if(!query.first()) { - qDebug() << "create a user first!"; - } else { - user = query.value(0).toUInt(); +QString SqliteStorage::backlogFile(bool createPath) { + // kinda ugly, but I currently see no other way to do that +#ifdef _WINDOWS + QString quasselDir = QDir::homePath() + qgetenv("APPDATA") + "\\quassel\\"; +#else + QString quasselDir = QDir::homePath() + "/.quassel/"; +#endif + + if (createPath) { + QDir *qDir = new QDir(quasselDir); + if (!qDir->exists(quasselDir)) { + qDir->mkpath(quasselDir); + } + delete qDir; } - query.prepare("DELETE FROM backlog WHERE bufferid IN (SELECT DISTINCT bufferid FROM buffer WHERE userid = :userid"); - query.bindValue(":userid", user); - query.exec(); - query.prepare("DELETE FROM buffer WHERE userid = :userid"); - query.bindValue(":userid", user); - query.exec(); - query.prepare("DELETE FROM buffergroup WHERE userid = :userid"); - query.bindValue(":userid", user); - query.exec(); - query.prepare("DELETE FROM network WHERE userid = :userid"); - query.bindValue(":userid", user); - query.exec(); - logDb.commit(); - qDebug() << "All userdata has been deleted"; - qDebug() << "importing old backlog files..."; - initBackLogOld(user); - logDb.commit(); - return; -} + return quasselDir + "quassel-storage.sqlite"; +} bool SqliteStorage::watchQuery(QSqlQuery *query) { if(query->lastError().isValid()) { diff --git a/src/core/sqlitestorage.h b/src/core/sqlitestorage.h index 74efe5ab..ca56cabf 100644 --- a/src/core/sqlitestorage.h +++ b/src/core/sqlitestorage.h @@ -34,12 +34,12 @@ class SqliteStorage : public Storage { SqliteStorage(); virtual ~SqliteStorage(); - static void init(); - /* General */ static bool isAvailable(); static QString displayName(); + virtual bool setup(const QVariantMap &settings = QVariantMap()); + virtual bool init(const QVariantMap &settings = QVariantMap()); // TODO: Add functions for configuring the backlog handling, i.e. defining auto-cleanup settings etc @@ -65,23 +65,19 @@ class SqliteStorage : public Storage { virtual QList requestMsgs(BufferInfo buffer, QDateTime since, int offset = -1); virtual QList requestMsgRange(BufferInfo buffer, int first, int last); - public slots: - //! This is just for importing the old file-based backlog */ - /** This slot needs to be implemented in the storage backends. - * It should first prepare (delete?) the database, then call initBackLogOld(UserId id). - * If the importing was successful, backLogEnabledOld will be true afterwards. - */ - void importOldBacklog(); - signals: void bufferInfoUpdated(BufferInfo); protected: private: - void initDb(); + static QString backlogFile(bool createPath = false); + void createBuffer(UserId user, const QString &network, const QString &buffer); bool watchQuery(QSqlQuery *query); + + QSqlDatabase logDb; + QSqlQuery *logMessageQuery; QSqlQuery *addSenderQuery; QSqlQuery *getLastMessageIdQuery; @@ -95,5 +91,4 @@ class SqliteStorage : public Storage { QSqlQuery *getBufferInfoQuery; }; - #endif diff --git a/src/core/storage.cpp b/src/core/storage.cpp index e7dcea54..4df74027 100644 --- a/src/core/storage.cpp +++ b/src/core/storage.cpp @@ -19,99 +19,3 @@ ***************************************************************************/ #include "storage.h" - - -// OBSOLETE -// This is kept here for importing the old file-based backlog. - -/* This is a sample! - -void Storage::importOldBacklog() { - qDebug() << "Deleting backlog database..."; - logDb.exec(QString("DELETE FROM 'Backlog$%1$' WHERE SenderId != '$VERSION$'").arg(user)); - logDb.exec(QString("DELETE FROM 'Senders$%1$'").arg(user)); - logDb.exec(QString("DELETE FROM 'Buffers$%1$'").arg(user)); - nextMsgId = 1; nextBufferInfo = 1; nextSenderId = 1; - qDebug() << "Importing old backlog files..."; - initBackLogOld(); - if(!backLogEnabledOld) return; - logDb.exec("VACUUM"); - qDebug() << "Backlog successfully imported, you have to restart Quassel now!"; - exit(0); - -} -*/ - -// file name scheme: quassel-backlog-2006-29-10.bin -void Storage::initBackLogOld(UserId uid) { - backLogDir = QDir(Global::quasselDir + "/backlog"); - if(!backLogDir.exists()) { - qWarning(QString("Creating backlog directory \"%1\"...").arg(backLogDir.absolutePath()).toAscii()); - if(!backLogDir.mkpath(backLogDir.absolutePath())) { - qWarning(QString("Could not create backlog directory! Disabling logging...").toAscii()); - backLogEnabledOld = false; - return; - } - } - backLogDir.refresh(); - //if(!backLogDir.isReadable()) { - // qWarning(QString("Cannot read directory \"%1\". Disabling logging...").arg(backLogDir.absolutePath()).toAscii()); - // backLogEnabled = false; - // return; - //} - QStringList networks = backLogDir.entryList(QDir::Dirs|QDir::NoDotAndDotDot|QDir::Readable, QDir::Name); - foreach(QString net, networks) { - QDir dir(backLogDir.absolutePath() + "/" + net); - if(!dir.exists()) { - qWarning(QString("Could not change to directory \"%1\"!").arg(dir.absolutePath()).toAscii()); - continue; - } - QStringList logs = dir.entryList(QStringList("quassel-backlog-*.bin"), QDir::Files|QDir::Readable, QDir::Name); - foreach(QString name, logs) { - QFile f(dir.absolutePath() + "/" + name); - if(!f.open(QIODevice::ReadOnly)) { - qWarning(QString("Could not open \"%1\" for reading!").arg(f.fileName()).toAscii()); - continue; - } - QDataStream in(&f); - in.setVersion(QDataStream::Qt_4_2); - QByteArray verstring; quint8 vernum; in >> verstring >> vernum; - if(verstring != BACKLOG_STRING) { - qWarning(QString("\"%1\" is not a Quassel backlog file!").arg(f.fileName()).toAscii()); - f.close(); continue; - } - if(vernum != BACKLOG_FORMAT) { - qWarning(QString("\"%1\": Version mismatch!").arg(f.fileName()).toAscii()); - f.close(); continue; - } - qDebug() << "Reading backlog from" << f.fileName(); - logFileDates[net] = QDate::fromString(f.fileName(), - QString("'%1/quassel-backlog-'yyyy-MM-dd'.bin'").arg(dir.absolutePath())); - if(!logFileDates[net].isValid()) { - qWarning(QString("\"%1\" has an invalid file name!").arg(f.fileName()).toAscii()); - } - while(!in.atEnd()) { - quint8 t, f; - quint32 ts; - QByteArray s, m, targ; - in >> ts >> t >> f >> targ >> s >> m; - QString target = QString::fromUtf8(targ); - QString sender = QString::fromUtf8(s); - QString text = QString::fromUtf8(m); - BufferInfo id; - if((f & Message::PrivMsg) && !(f & Message::Self)) { - id = getBufferInfo(uid, net, sender); - } else { - id = getBufferInfo(uid, net, target); - } - Message msg(QDateTime::fromTime_t(ts), id, (Message::Type)t, text, sender, f); - //backLog[net].append(m); - logMessage(msg); - } - f.close(); - } - } - backLogEnabledOld = true; -} - - diff --git a/src/core/storage.h b/src/core/storage.h index f493721c..f98b75b7 100644 --- a/src/core/storage.h +++ b/src/core/storage.h @@ -33,16 +33,6 @@ class Storage : public QObject { Storage() {}; virtual ~Storage() {}; - //! Initialize the static parts of the storage class - /** This is called by the core before any other method of the storage backend is used. - * This should be used to perform any static initialization that might be necessary. - * DO NOT use this for creating database connection or similar stuff, since init() might be - * called even if the storage backend is never be actually used (because no user selected it). - * For anything like this, the constructor (which is called if and when we actually create an instance - * of the storage backend) is the right place. - */ - static void init() {}; - /* General */ //! Check if the storage type is available. @@ -56,6 +46,19 @@ class Storage : public QObject { /** \return A string that can be used by the GUI to describe the storage backend */ static QString displayName() { return ""; } + //! Setup the storage provider. + /** This prepares the storage provider (e.g. create tables, etc.) for use within Quassel. + * \param settings Hostname, port, username, password, ... + * \return True if and only if the storage provider was initialized successfully. + */ + virtual bool setup(const QVariantMap &settings = QVariantMap()) { return false; } + + //! Initialize the storage provider + /** \param settings Hostname, port, username, password, ... + * \return True if and only if the storage provider was initialized successfully. + */ + virtual bool init(const QVariantMap &settings = QVariantMap()) = 0; + // TODO: Add functions for configuring the backlog handling, i.e. defining auto-cleanup settings etc /* User handling */ @@ -152,14 +155,6 @@ class Storage : public QObject { */ virtual QList requestMsgRange(BufferInfo buffer, int first, int last) = 0; - public slots: - //! This is just for importing the old file-based backlog */ - /** This slot needs to be implemented in the storage backends. - * It should first prepare (delete?) the database, then call initBackLogOld(UserId id). - * If the importing was successful, backLogEnabledOld will be true afterwards. - */ - virtual void importOldBacklog() = 0; - signals: //! Sent when a new BufferInfo is created, or an existing one changed somehow. void bufferInfoUpdated(BufferInfo); @@ -173,21 +168,6 @@ class Storage : public QObject { public: /* Exceptions */ struct AuthError : public Exception {}; - - protected: - // Old stuff, just for importing old file-based data - void initBackLogOld(UserId id); - - QSqlDatabase logDb; // FIXME this does not belong in the base class! - - bool backLogEnabledOld; - QDir backLogDir; - QHash > backLog; - QHash logFiles; - QHash logStreams; - QHash logFileDates; - QHash logFileDirs; - }; diff --git a/src/qtui/configwizard.cpp b/src/qtui/configwizard.cpp new file mode 100644 index 00000000..6dc444f7 --- /dev/null +++ b/src/qtui/configwizard.cpp @@ -0,0 +1,202 @@ +/*************************************************************************** + * Copyright (C) 2005-07 by The Quassel Team * + * devel@quassel-irc.org * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include + +#include "configwizard.h" + +ConfigWizard::ConfigWizard(const QStringList &storageProviders, QWidget *parent) : QWizard(parent) { + setPage(Page_Intro, new IntroPage()); + setPage(Page_AdminUser, new AdminUserPage()); + setPage(Page_StorageSelection, new StorageSelectionPage(storageProviders)); + setPage(Page_StorageDetails, new StorageDetailsPage()); + setPage(Page_Conclusion, new ConclusionPage(storageProviders)); + + setStartId(Page_Intro); + +#ifndef Q_WS_MAC + setWizardStyle(ModernStyle); +#endif + + setOption(HaveHelpButton, false); + setOption(NoBackButtonOnStartPage, true); + setOption(HaveNextButtonOnLastPage, false); + setOption(HaveFinishButtonOnEarlyPages, false); + setOption(NoCancelButton, true); + + setWindowTitle(tr("Core Configuration Wizard")); +} + + +IntroPage::IntroPage(QWidget *parent) : QWizardPage(parent) { + setTitle(tr("Introduction")); + + label = new QLabel(tr("This wizard will guide you through the setup process for your shiny new Quassel IRC Client.")); + label->setWordWrap(true); + + QVBoxLayout *layout = new QVBoxLayout(); + layout->addWidget(label); + setLayout(layout); +} + +int IntroPage::nextId() const { + return ConfigWizard::Page_AdminUser; +} + + +AdminUserPage::AdminUserPage(QWidget *parent) : QWizardPage(parent) { + setTitle(tr("Setup Admin User")); + setSubTitle(tr("Please enter credentials for the admin user.")); + + nameLabel = new QLabel(tr("Name:")); + nameEdit = new QLineEdit(); + nameLabel->setBuddy(nameEdit); + + passwordLabel = new QLabel(tr("Password:")); + passwordEdit = new QLineEdit(); + passwordEdit->setEchoMode(QLineEdit::Password); + passwordLabel->setBuddy(passwordLabel); + + registerField("adminuser.name*", nameEdit); + registerField("adminuser.password*", passwordEdit); + + QGridLayout *layout = new QGridLayout(); + layout->addWidget(nameLabel, 0, 0); + layout->addWidget(nameEdit, 0, 1); + layout->addWidget(passwordLabel, 1, 0); + layout->addWidget(passwordEdit, 1, 1); + setLayout(layout); +} + +int AdminUserPage::nextId() const { + return ConfigWizard::Page_StorageSelection; +} + + +StorageSelectionPage::StorageSelectionPage(const QStringList &storageProviders, QWidget *parent) : QWizardPage(parent) { + setTitle(tr("Select Storage Provider")); + setSubTitle(tr("Please select the storage provider you want to use.")); + + storageSelection = new QComboBox(); + storageSelection->addItems(storageProviders); + + registerField("storage.provider", storageSelection); + + QVBoxLayout *layout = new QVBoxLayout(); + layout->addWidget(storageSelection); + setLayout(layout); +} + +int StorageSelectionPage::nextId() const { + QString selection = storageSelection->currentText(); + if (!selection.compare("Sqlite", Qt::CaseInsensitive)) { + return ConfigWizard::Page_Conclusion; + } else { + return ConfigWizard::Page_StorageDetails; + } +} + + +StorageDetailsPage::StorageDetailsPage(QWidget *parent) : QWizardPage(parent) { + setTitle(tr("Setup Storage Provider")); + setSubTitle(tr("Please enter credentials for the selected storage provider.")); + + hostLabel = new QLabel(tr("Host:")); + hostEdit = new QLineEdit(); + hostLabel->setBuddy(hostEdit); + + portLabel = new QLabel(tr("Port:")); + portEdit = new QLineEdit(); + QIntValidator *portValidator = new QIntValidator(0, 65535, this); + portEdit->setValidator(portValidator); + portLabel->setBuddy(portEdit); + + databaseLabel = new QLabel(tr("Database:")); + databaseEdit = new QLineEdit(); + databaseLabel->setBuddy(databaseEdit); + + userLabel = new QLabel(tr("User:")); + userEdit = new QLineEdit(); + userLabel->setBuddy(userEdit); + + passwordLabel = new QLabel(tr("Password:")); + passwordEdit = new QLineEdit(); + passwordEdit->setEchoMode(QLineEdit::Password); + passwordLabel->setBuddy(passwordLabel); + + registerField("storage.host*", hostEdit); + registerField("storage.port*", portEdit); + registerField("storage.database*", databaseEdit); + registerField("storage.user*", userEdit); + registerField("storage.password*", passwordEdit); + + QGridLayout *layout = new QGridLayout(); + layout->addWidget(hostLabel, 0, 0); + layout->addWidget(hostEdit, 0, 1); + layout->addWidget(portLabel, 1, 0); + layout->addWidget(portEdit, 1, 1); + layout->addWidget(databaseLabel, 2, 0); + layout->addWidget(databaseEdit, 2, 1); + layout->addWidget(userLabel, 3, 0); + layout->addWidget(userEdit, 3, 1); + layout->addWidget(passwordLabel, 4, 0); + layout->addWidget(passwordEdit, 4, 1); + setLayout(layout); +} + +int StorageDetailsPage::nextId() const { + return ConfigWizard::Page_Conclusion; +} + + +ConclusionPage::ConclusionPage(const QStringList &storageProviders, QWidget *parent) : QWizardPage(parent) { + setTitle(tr("Conclusion")); + setSubTitle(tr("You chose the following configuration:")); + + this->storageProviders = storageProviders; + + adminuser = new QLabel(); + storage = new QLabel(); + storage->setWordWrap(true); + + QVBoxLayout *layout = new QVBoxLayout(); + layout->addWidget(adminuser); + layout->addWidget(storage); + setLayout(layout); +} + +int ConclusionPage::nextId() const { + return -1; +} + +void ConclusionPage::initializePage() { + QString adminuserText = "Admin User: " + field("adminuser.name").toString(); + adminuser->setText(adminuserText); + + QString storageText = "Selected Storage Provider: "; + QString sp = storageProviders.value(field("storage.provider").toInt()); + if (!sp.compare("Sqlite", Qt::CaseInsensitive)) { + storageText.append(sp); + } else { + storageText += sp + "\nHost: " + field("storage.host").toString() + "\nPort: " + field("storage.port").toString() + "\nDatabase: " + field("storage.database").toString() + "\nUser: " + field("storage.user").toString(); + } + storage->setText(storageText); +} + diff --git a/src/qtui/configwizard.h b/src/qtui/configwizard.h new file mode 100644 index 00000000..c6e83c9c --- /dev/null +++ b/src/qtui/configwizard.h @@ -0,0 +1,120 @@ +/*************************************************************************** + * Copyright (C) 2005-07 by The Quassel Team * + * devel@quassel-irc.org * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#ifndef CONFIGWIZARD_H_ +#define CONFIGWIZARD_H_ + +#include + +class QLabel; +class QLineEdit; +class QComboBox; + +class ConfigWizard : public QWizard { + Q_OBJECT + + public: + enum { + Page_Intro, + Page_AdminUser, + Page_StorageSelection, + Page_StorageDetails, + Page_Conclusion + }; + + ConfigWizard(const QStringList &storageProviders, QWidget *parent = NULL); +}; + +class IntroPage : public QWizardPage { + Q_OBJECT + + public: + IntroPage(QWidget *parent = NULL); + + int nextId() const; + + private: + QLabel *label; +}; + +class AdminUserPage : public QWizardPage { + Q_OBJECT + + public: + AdminUserPage(QWidget *parent = NULL); + + int nextId() const; + + private: + QLabel *nameLabel; + QLineEdit *nameEdit; + QLabel *passwordLabel; + QLineEdit *passwordEdit; +}; + +class StorageSelectionPage : public QWizardPage { + Q_OBJECT + + public: + StorageSelectionPage(const QStringList &storageProviders, QWidget *parent = NULL); + + int nextId() const; + + private: + QComboBox *storageSelection; +}; + +class StorageDetailsPage : public QWizardPage { + Q_OBJECT + + public: + StorageDetailsPage(QWidget *parent = NULL); + + int nextId() const; + + private: + QLabel *hostLabel; + QLineEdit *hostEdit; + QLabel *portLabel; + QLineEdit *portEdit; + QLabel *databaseLabel; + QLineEdit *databaseEdit; + QLabel *userLabel; + QLineEdit *userEdit; + QLabel *passwordLabel; + QLineEdit *passwordEdit; +}; + +class ConclusionPage : public QWizardPage { + Q_OBJECT + + public: + ConclusionPage(const QStringList &storageProviders, QWidget *parent = NULL); + + void initializePage(); + int nextId() const; + + private: + QLabel *adminuser; + QLabel *storage; + QStringList storageProviders; +}; + +#endif /*CONFIGWIZARD_H_*/ diff --git a/src/qtui/coreconnectdlg.cpp b/src/qtui/coreconnectdlg.cpp index d2c8d06d..2f51fddf 100644 --- a/src/qtui/coreconnectdlg.cpp +++ b/src/qtui/coreconnectdlg.cpp @@ -23,6 +23,7 @@ #include "global.h" #include "client.h" #include "clientsettings.h" +#include "configwizard.h" CoreConnectDlg::CoreConnectDlg(QWidget *parent, bool /*doAutoConnect*/) : QDialog(parent) { ui.setupUi(this); //qDebug() << "new dlg"; @@ -54,6 +55,8 @@ CoreConnectDlg::CoreConnectDlg(QWidget *parent, bool /*doAutoConnect*/) : QDialo connect(Client::instance(), SIGNAL(coreConnectionProgress(uint, uint)), this, SLOT(updateProgressBar(uint, uint))); connect(Client::instance(), SIGNAL(coreConnectionError(QString)), this, SLOT(coreConnectionError(QString))); connect(Client::instance(), SIGNAL(connected()), this, SLOT(coreConnected())); + + connect(Client::instance(), SIGNAL(showConfigWizard(const QVariantMap &)), this, SLOT(showConfigWizard(const QVariantMap &))); AccountSettings s; ui.accountList->addItems(s.knownAccounts()); @@ -310,3 +313,24 @@ void CoreConnectDlg::recvCoreState(QVariant state) { QVariant CoreConnectDlg::getCoreState() { return coreState; } + +void CoreConnectDlg::showConfigWizard(const QVariantMap &coredata) { + QStringList storageProviders = coredata["StorageProviders"].toStringList(); + ConfigWizard *wizard = new ConfigWizard(storageProviders, this); + wizard->exec(); + QVariantMap reply; + reply["GuiProtocol"] = GUI_PROTOCOL; + reply["HasSettings"] = true; + reply["User"] = wizard->field("adminuser.name").toString(); + reply["Password"] = wizard->field("adminuser.password").toString(); + QString sp = storageProviders.value(wizard->field("storage.provider").toInt()); + reply["Type"] = sp; + if (sp.compare("Sqlite", Qt::CaseInsensitive)) { + reply["Host"] = wizard->field("storage.host").toString(); + reply["Port"] = wizard->field("storage.port").toString(); + reply["Database"] = wizard->field("storage.database").toString(); + reply["User"] = wizard->field("storage.user").toString(); + reply["Password"] = wizard->field("storage.password").toString(); + } + Client::instance()->setCoreConfiguration(reply); +} diff --git a/src/qtui/coreconnectdlg.h b/src/qtui/coreconnectdlg.h index 9f988a3f..3d8574f1 100644 --- a/src/qtui/coreconnectdlg.h +++ b/src/qtui/coreconnectdlg.h @@ -33,7 +33,7 @@ class CoreConnectDlg: public QDialog { QVariant getCoreState(); bool willDoInternalAutoConnect(); - + public slots: void doAutoConnect(); @@ -54,6 +54,8 @@ class CoreConnectDlg: public QDialog { //void coreConnectionProgress(uint partial, uint total); void updateProgressBar(uint partial, uint total); void recvCoreState(QVariant); + + void showConfigWizard(const QVariantMap &coredata); private: Ui::CoreConnectDlg ui; diff --git a/src/qtui/qtui.pri b/src/qtui/qtui.pri index 73cfc07b..48c90754 100644 --- a/src/qtui/qtui.pri +++ b/src/qtui/qtui.pri @@ -2,13 +2,12 @@ DEPMOD = uisupport common client QT_MOD = core gui network SRCS += bufferview.cpp bufferviewfilter.cpp bufferwidget.cpp channelwidgetinput.cpp chatline-old.cpp \ - chatwidget.cpp coreconnectdlg.cpp \ - guisettings.cpp identities.cpp mainwin.cpp qtui.cpp qtuistyle.cpp serverlist.cpp settingsdlg.cpp tabcompleter.cpp topicwidget.cpp + chatwidget.cpp coreconnectdlg.cpp configwizard.cpp \ + guisettings.cpp identities.cpp mainwin.cpp qtui.cpp qtuistyle.cpp serverlist.cpp settingsdlg.cpp tabcompleter.cpp topicwidget.cpp -HDRS += bufferview.h bufferviewfilter.h bufferwidget.h channelwidgetinput.h chatline-old.h chatwidget.h \ +HDRS += bufferview.h bufferviewfilter.h bufferwidget.h channelwidgetinput.h chatline-old.h chatwidget.h configwizard.h \ coreconnectdlg.h guisettings.h identities.h mainwin.h qtui.h qtuistyle.h serverlist.h settingsdlg.h settingspage.h tabcompleter.h topicwidget.h - FORMNAMES = identitiesdlg.ui identitieseditdlg.ui networkeditdlg.ui mainwin.ui nickeditdlg.ui serverlistdlg.ui \ servereditdlg.ui coreconnectdlg.ui bufferviewwidget.ui bufferwidget.ui settingsdlg.ui \ buffermgmtpage.ui connectionpage.ui usermgmtpage.ui topicwidget.ui -- 2.20.1