}
}
+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..."));
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;
}
void coreConnectionError(QString errorMsg);
void coreConnectionMsg(const QString &msg);
void coreConnectionProgress(uint part, uint total);
+
+ void showConfigWizard(const QVariantMap &coredata);
void connected();
void disconnected();
//void connectToLocalCore();
void connectToCore(const QVariantMap &);
void disconnectFromCore();
+
+ void setCoreConfiguration(const QVariantMap &settings);
private slots:
void recvCoreState(const QVariant &state);
//}
Global::RunMode Global::runMode;
-QString Global::quasselDir;
namespace Global {
enum RunMode { Monolithic, ClientOnly, CoreOnly };
extern RunMode runMode;
- extern QString quasselDir;
}
struct Exception {
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
#include "core.h"
#include "coresession.h"
+#include "coresettings.h"
#include "sqlitestorage.h"
#include "util.h"
+#include <QMetaObject>
+#include <QMetaMethod>
+
Core *Core::instanceptr = 0;
Core *Core::instance() {
}
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) {
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());
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() {
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();
}
// 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<QTcpSocket*>(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...
}
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;
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;
+}
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.
* \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<UserId, CoreSession *> sessions;
QTcpServer server; // TODO: implement SSL
QHash<QTcpSocket *, quint32> blockSizes;
+
+ bool configured;
};
#endif
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
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)));
--- /dev/null
+/***************************************************************************
+ * 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 <QStringList>
+
+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();
+}
--- /dev/null
+/***************************************************************************
+ * 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_*/
#include <QtSql>
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
//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:
"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();
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()) {
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
virtual QList<Message> requestMsgs(BufferInfo buffer, QDateTime since, int offset = -1);
virtual QList<Message> 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;
QSqlQuery *getBufferInfoQuery;
};
-
#endif
***************************************************************************/
#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;
-}
-
-
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.
/** \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 */
*/
virtual QList<Message> 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);
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<QString, QList<Message> > backLog;
- QHash<QString, QFile *> logFiles;
- QHash<QString, QDataStream *> logStreams;
- QHash<QString, QDate> logFileDates;
- QHash<QString, QDir> logFileDirs;
-
};
--- /dev/null
+/***************************************************************************
+ * 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 <QtGui>
+
+#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);
+}
+
--- /dev/null
+/***************************************************************************
+ * 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 <QWizard>
+
+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_*/
#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";
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());
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);
+}
QVariant getCoreState();
bool willDoInternalAutoConnect();
-
+
public slots:
void doAutoConnect();
//void coreConnectionProgress(uint partial, uint total);
void updateProgressBar(uint partial, uint total);
void recvCoreState(QVariant);
+
+ void showConfigWizard(const QVariantMap &coredata);
private:
Ui::CoreConnectDlg ui;
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