From: Manuel Nickschas Date: Mon, 14 May 2007 21:48:56 +0000 (+0000) Subject: Merged changes from branch "sput" r62:66 back into trunk. X-Git-Tag: 0.1.0~243 X-Git-Url: https://git.quassel-irc.org/?p=quassel.git;a=commitdiff_plain;h=ddc5208315db8ca9ca19f6a59ee7caefe631ffc7 Merged changes from branch "sput" r62:66 back into trunk. This adds a rudimentarily working db-based backlog as well as a completely revamped message handling. It should also get rid of the nasty crash we had in rev 61. --- diff --git a/CMakeLists.txt b/CMakeLists.txt index 92043db9..ce3267e0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,7 +24,7 @@ IF(NOT BUILD_MONO AND NOT BUILD_CORE AND NOT BUILD_GUI) MESSAGE(FATAL_ERROR "\nYou have not selected which parts of Quassel I should build. Aborting.\nRun 'cmake -DBUILD=', where contains one or more of 'core', 'gui' or 'monolithic', or 'all' to build everything.\n") ENDIF(NOT BUILD_MONO AND NOT BUILD_CORE AND NOT BUILD_GUI) -#SET(CMAKE_BUILD_TYPE Debug) +SET(CMAKE_BUILD_TYPE Debug) # Define files SET(quassel_mono_SRCS main/main_mono.cpp) diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt index 484f994c..c7adb956 100644 --- a/core/CMakeLists.txt +++ b/core/CMakeLists.txt @@ -1,6 +1,6 @@ -SET(core_SRCS core.cpp coreproxy.cpp server.cpp) +SET(core_SRCS core.cpp coreproxy.cpp server.cpp backlog.cpp) SET(core_HDRS ) -SET(core_MOCS core.h coreproxy.h server.h) +SET(core_MOCS core.h coreproxy.h server.h backlog.h) QT4_WRAP_CPP(_MOC ${core_MOCS}) ADD_LIBRARY(core ${_MOC} ${core_SRCS} ${core_HDRS}) diff --git a/core/backlog.cpp b/core/backlog.cpp new file mode 100644 index 00000000..51e1d6b2 --- /dev/null +++ b/core/backlog.cpp @@ -0,0 +1,333 @@ +/*************************************************************************** + * 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 "backlog.h" +#include "util.h" + +#define DBVERSION 1 + +Backlog::Backlog() { + + +} + + +Backlog::~Backlog() { + logDb.close(); + + // FIXME Old stuff + foreach(QDataStream *s, logStreams) { + delete s; + } + foreach(QFile *f, logFiles) { + if(f->isOpen()) f->close(); + delete f; + } +} + + +void Backlog::init(QString _user) { + user = _user; + QDir backlogDir = QDir(Global::quasselDir); + 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()); + backlogEnabled = false; + return; + } + } + QString backlogFile = Global::quasselDir + "/quassel-backlog.sqlite"; + logDb = QSqlDatabase::addDatabase("QSQLITE", user); + 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()); + backlogEnabled = false; return; + } + + if(!logDb.transaction()) qWarning(tr("Database driver does not support transactions. This might lead to a corrupt database!").toAscii()); + QString tname = QString("'Backlog$%1$'").arg(user); + QSqlQuery query(logDb); + /* DEBUG */ + //query.exec(QString("DROP TABLE %1").arg(tname)); // DEBUG + //query.exec(QString("DROP TABLE 'Senders$%1$'").arg(user)); + //query.exec(QString("DROP TABLE 'Buffers$%1$'").arg(user)); + /* END DEBUG */ + query.exec(QString("CREATE TABLE IF NOT EXISTS %1 (" + "MsgId INTEGER PRIMARY KEY AUTOINCREMENT," + "Time INTEGER," + "BufferId INTEGER," + "Type INTEGER," + "Flags INTEGER," + "SenderId INTEGER," + "Text BLOB" + ")").arg(tname)); + query.exec(QString("INSERT OR REPLACE INTO %1 (MsgId, SenderId, Text) VALUES (0, '$VERSION$', %2)").arg(tname).arg(DBVERSION)); + query.exec(QString("CREATE TABLE IF NOT EXISTS 'Senders$%1$' (SenderId INTEGER PRIMARY KEY AUTOINCREMENT, Sender BLOB)").arg(user)); + query.exec(QString("CREATE TABLE IF NOT EXISTS 'Buffers$%1$' (BufferId INTEGER PRIMARY KEY AUTOINCREMENT, GroupId INTEGER, Network BLOB, Buffer BLOB)").arg(user)); + if(query.lastError().isValid()) { + qWarning(tr("Could not create backlog table: %1").arg(query.lastError().text()).toAscii()); + qWarning(tr("Disabling logging...").toAscii()); + logDb.rollback(); + backlogEnabled = false; return; + } + // Find the next free uid numbers + query.exec(QString("SELECT MsgId FROM %1 ORDER BY MsgId DESC LIMIT 1").arg(tname)); + query.first(); + if(query.value(0).isValid()) nextMsgId = query.value(0).toUInt() + 1; + else { + qWarning(tr("Something is wrong with the backlog database! %1").arg(query.lastError().text()).toAscii()); + nextMsgId = 1; + } + query.exec(QString("SELECT BufferId FROM 'Buffers$%1$' ORDER BY BufferId DESC LIMIT 1").arg(user)); + if(query.first()) { + if(query.value(0).isValid()) nextBufferId = query.value(0).toUInt() + 1; + else { + qWarning(tr("Something is wrong with the backlog database! %1").arg(query.lastError().text()).toAscii()); + nextBufferId = 0; + } + } else nextBufferId = 0; + query.exec(QString("SELECT SenderId FROM 'Senders$%1$' ORDER BY SenderId DESC LIMIT 1").arg(user)); + if(query.first()) { + if(query.value(0).isValid()) nextSenderId = query.value(0).toUInt() + 1; + else { + qWarning(tr("Something is wrong with the backlog database! %1").arg(query.lastError().text()).toAscii()); + nextSenderId = 0; + } + } else nextSenderId = 0; + logDb.commit(); + backlogEnabled = true; +} + +uint Backlog::logMessage(Message msg) { + if(!backlogEnabled) return 0; + bool ok; + logDb.transaction(); + QSqlQuery query(logDb); + QString s = msg.sender; s.replace('\'', "''"); QByteArray bs = s.toUtf8().toHex(); + QString t = msg.text; t.replace('\'', "''"); + // Let's do some space-saving optimizations... + query.exec(QString("SELECT SenderId FROM 'Senders$%1$' WHERE Sender == X'%2'").arg(user).arg(bs.constData())); + int suid; + if(!query.first()) { + query.exec(QString("INSERT INTO 'Senders$%1$' (SenderId, Sender) VALUES (%2, X'%3')").arg(user).arg(nextSenderId).arg(bs.constData())); + suid = nextSenderId; + } else suid = query.value(0).toInt(); + query.exec(QString("INSERT INTO 'Backlog$%1$' (MsgId, Time, BufferId, Type, Flags, SenderId, Text) VALUES (%2, %3, %4, %5, %6, %7, X'%8')").arg(user) + .arg(nextMsgId).arg(msg.timeStamp.toTime_t()).arg(msg.buffer.uid()).arg(msg.type).arg(msg.flags).arg(suid).arg(t.toUtf8().toHex().constData())); + + if(query.lastError().isValid()) { + qWarning(tr("Database error while logging: %1").arg(query.lastError().text()).toAscii()); + logDb.rollback(); + return 0; + } + + nextMsgId++; + if(suid == nextSenderId) nextSenderId++; + logDb.commit(); + return nextMsgId - 1; +} + +// TODO: optimize by keeping free IDs in memory? What about deleted IDs? Nickchanges for queries? +BufferId Backlog::getBufferId(QString net, QString buf) { + if(!backlogEnabled) { + return BufferId(0, net, buf); + } + QByteArray n = net.toUtf8().toHex(); + QByteArray b = buf.toUtf8().toHex(); + logDb.transaction(); + QSqlQuery query(logDb); + int uid = -1; + query.exec(QString("SELECT BufferId FROM 'Buffers$%1$' WHERE Network == X'%2' AND Buffer == X'%3'").arg(user).arg(n.constData()).arg(b.constData())); + if(!query.first()) { + // TODO: joined buffers/queries + query.exec(QString("INSERT INTO 'Buffers$%1$' (BufferId, GroupId, Network, Buffer) VALUES (%2, %2, X'%3', X'%4')").arg(user).arg(nextBufferId).arg(n.constData()).arg(b.constData())); + uid = nextBufferId++; + } else uid = query.value(0).toInt(); + logDb.commit(); + return BufferId(uid, net, buf, uid); // FIXME (joined buffers) +} + +QList Backlog::requestBuffers(QDateTime since) { + QList result; + QSqlQuery query(logDb); + if(!since.isValid()) { + query.exec(QString("SELECT BufferId, GroupId, Network, Buffer FROM 'Buffers$%1$'").arg(user)); + } else { + query.exec(QString("SELECT DISTINCT 'Buffers$%1$'.BufferId, GroupId, Network, Buffer FROM 'Buffers$%1$' NATURAL JOIN 'Backlog$%1$' " + "WHERE Time >= %2").arg(user).arg(since.toTime_t())); + } + while(query.next()) { + result.append(BufferId(query.value(0).toUInt(), QString::fromUtf8(query.value(2).toByteArray()), QString::fromUtf8(query.value(3).toByteArray()), query.value(1).toUInt())); + } + return result; +} + +QList Backlog::requestMsgs(BufferId id, int lastlines, int offset) { + QList result; + QSqlQuery query(logDb); + QString limit; + if(lastlines > 0) limit = QString("LIMIT %1").arg(lastlines); + query.exec(QString("SELECT MsgId, Time, Type, Flags, Sender, Text FROM 'Senders$%1$' NATURAL JOIN 'Backlog$%1$' " + "WHERE BufferId IN (SELECT BufferId FROM 'Buffers$%1$' WHERE GroupId == %2) ORDER BY MsgId DESC %3").arg(user).arg(id.groupId()).arg(limit)); + while(query.next()) { + if(offset >= 0 && query.value(0).toInt() >= offset) continue; + Message msg(QDateTime::fromTime_t(query.value(1).toInt()), id, (Message::Type)query.value(2).toUInt(), QString::fromUtf8(query.value(5).toByteArray()), + QString::fromUtf8(query.value(4).toByteArray()), query.value(3).toUInt()); + msg.msgId = query.value(0).toUInt(); + result.append(msg); + } + return result; +} + + +// OBSOLETE +// This is kept here for importing the old file-based backlog. + +void Backlog::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; nextBufferId = 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 Backlog::initBackLogOld() { + 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); + BufferId id; + if((f & Message::PrivMsg) && !(f & Message::Self)) { + id = getBufferId(net, sender); + } else { + id = getBufferId(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; +} + + +/** Log a core message (emitted via a displayMsg() signal) to the backlog file. + * If a file for the current day does not exist, one will be created. Otherwise, messages will be appended. + * The file header is the string defined by BACKLOG_STRING, followed by a quint8 specifying the format + * version (BACKLOG_FORMAT). The rest is simply serialized Message objects. + */ +void Backlog::logMessageOld(QString net, Message msg) { + backLog[net].append(msg); + if(!logFileDirs.contains(net)) { + QDir dir(backLogDir.absolutePath() + "/" + net); + if(!dir.exists()) { + qWarning(QString("Creating backlog directory \"%1\"...").arg(dir.absolutePath()).toAscii()); + if(!dir.mkpath(dir.absolutePath())) { + qWarning(QString("Could not create backlog directory!").toAscii()); + return; + } + } + logFileDirs[net] = dir; + Q_ASSERT(!logFiles.contains(net) && !logStreams.contains(net)); + if(!logFiles.contains(net)) logFiles[net] = new QFile(); + if(!logStreams.contains(net)) logStreams[net] = new QDataStream(); + } + if(!logFileDates[net].isValid() || logFileDates[net] < QDate::currentDate()) { + if(logFiles[net]->isOpen()) logFiles[net]->close(); + logFileDates[net] = QDate::currentDate(); + } + if(!logFiles[net]->isOpen()) { + logFiles[net]->setFileName(QString("%1/%2").arg(logFileDirs[net].absolutePath()) + .arg(logFileDates[net].toString("'quassel-backlog-'yyyy-MM-dd'.bin'"))); + if(!logFiles[net]->open(QIODevice::WriteOnly|QIODevice::Append|QIODevice::Unbuffered)) { + qWarning(QString("Could not open \"%1\" for writing: %2") + .arg(logFiles[net]->fileName()).arg(logFiles[net]->errorString()).toAscii()); + return; + } + logStreams[net]->setDevice(logFiles[net]); logStreams[net]->setVersion(QDataStream::Qt_4_2); + if(!logFiles[net]->size()) *logStreams[net] << BACKLOG_STRING << (quint8)BACKLOG_FORMAT; + } + *logStreams[net] << msg; +} + + diff --git a/core/backlog.h b/core/backlog.h new file mode 100644 index 00000000..709125ad --- /dev/null +++ b/core/backlog.h @@ -0,0 +1,82 @@ +/*************************************************************************** + * 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 _BACKLOG_H_ +#define _BACKLOG_H_ + +#include +#include + +#include "global.h" +#include "message.h" + +// TODO: is this threadsafe? should it be? +class Backlog : public QObject { + Q_OBJECT + + public: + Backlog(); + ~Backlog(); + + void init(QString user); + void setDefaultSettings(int lines = -1, QDateTime time = QDateTime()); + void setSettings(QString network, QString buffer, int lines = -1, QDateTime time = QDateTime()); + + BufferId getBufferId(QString network, QString buffer); + uint logMessage(Message msg); + + QList requestMsgs(BufferId, int lastlines = -1, int offset = -1); + QList requestMsgs(BufferId, QDateTime since, int offset = -1); + //QList requestMsgRange(BufferId, int first, int last); + + QList requestBuffers(QDateTime since = QDateTime()); + + public slots: + void importOldBacklog(); + + private: + QString user; + bool backlogEnabled; + QSqlDatabase logDb; + + uint nextMsgId, nextBufferId, nextSenderId; + + QTimer cleanupTimer; + + void cleanup(); + + // Old stuff, just for importing old file-based data + void initBackLogOld(); + void logMessageOld(QString net, Message); + + bool backLogEnabledOld; + QDir backLogDir; + QHash > backLog; + //QHash netIdx; + QHash logFiles; + QHash logStreams; + QHash logFileDates; + QHash logFileDirs; + +}; + + + +#endif diff --git a/core/core.cpp b/core/core.cpp index 5bed7add..07e0c73e 100644 --- a/core/core.cpp +++ b/core/core.cpp @@ -32,9 +32,12 @@ Core::Core() { connect(coreProxy, SIGNAL(requestServerStates()), this, SIGNAL(serverStateRequested())); connect(coreProxy, SIGNAL(gsRequestConnect(QStringList)), this, SLOT(connectToIrc(QStringList))); - connect(coreProxy, SIGNAL(gsUserInput(QString, QString, QString)), this, SIGNAL(msgFromGUI(QString, QString, QString))); - connect(this, SIGNAL(displayMsg(QString, Message)), coreProxy, SLOT(csDisplayMsg(QString, Message))); + connect(coreProxy, SIGNAL(gsUserInput(BufferId, QString)), this, SLOT(msgFromGUI(BufferId, QString))); + connect(coreProxy, SIGNAL(gsImportBacklog()), &backlog, SLOT(importOldBacklog())); + connect(coreProxy, SIGNAL(gsRequestBacklog(BufferId, QVariant, QVariant)), this, SLOT(sendBacklog(BufferId, QVariant, QVariant))); + connect(this, SIGNAL(displayMsg(Message)), coreProxy, SLOT(csDisplayMsg(Message))); connect(this, SIGNAL(displayStatusMsg(QString, QString)), coreProxy, SLOT(csDisplayStatusMsg(QString, QString))); + connect(this, SIGNAL(backlogData(BufferId, QList, bool)), coreProxy, SLOT(csBacklogData(BufferId, QList, bool))); // Read global settings from config file QSettings s; @@ -43,7 +46,7 @@ Core::Core() { foreach(key, s.childKeys()) { global->updateData(key, s.value(key)); } - initBackLogOld(); + backlog.init("Default"); // FIXME global->updateData("CoreReady", true); // Now that we are in sync, we can connect signals to automatically store further updates. // I don't think we care if global data changed locally or if it was updated by a client. @@ -56,14 +59,6 @@ Core::~Core() { //foreach(Server *s, servers) { // delete s; //} - foreach(QDataStream *s, logStreams) { - delete s; - } - foreach(QFile *f, logFiles) { - if(f->isOpen()) f->close(); - delete f; - } - logDb.close(); } void Core::globalDataUpdated(QString key) { @@ -83,11 +78,11 @@ void Core::connectToIrc(QStringList networks) { connect(this, SIGNAL(disconnectFromIrc(QString)), server, SLOT(disconnectFromIrc(QString))); connect(this, SIGNAL(msgFromGUI(QString, QString, QString)), server, SLOT(userInput(QString, QString, QString))); connect(server, SIGNAL(serverState(QString, VarMap)), coreProxy, SLOT(csServerState(QString, VarMap))); - connect(server, SIGNAL(displayMsg(Message)), this, SLOT(recvMessageFromServer(Message))); + //connect(server, SIGNAL(displayMsg(Message)), this, SLOT(recvMessageFromServer(Message))); + connect(server, SIGNAL(displayMsg(Message::Type, QString, QString, QString, quint8)), this, SLOT(recvMessageFromServer(Message::Type, QString, QString, QString, quint8))); connect(server, SIGNAL(displayStatusMsg(QString)), this, SLOT(recvStatusMsgFromServer(QString))); connect(server, SIGNAL(modeSet(QString, QString, QString)), coreProxy, SLOT(csModeSet(QString, QString, QString))); connect(server, SIGNAL(topicSet(QString, QString, QString)), coreProxy, SLOT(csTopicSet(QString, QString, QString))); - connect(server, SIGNAL(setNicks(QString, QString, QStringList)), coreProxy, SLOT(csSetNicks(QString, QString, QStringList))); connect(server, SIGNAL(nickAdded(QString, QString, VarMap)), coreProxy, SLOT(csNickAdded(QString, QString, VarMap))); connect(server, SIGNAL(nickRenamed(QString, QString, QString)), coreProxy, SLOT(csNickRenamed(QString, QString, QString))); connect(server, SIGNAL(nickRemoved(QString, QString)), coreProxy, SLOT(csNickRemoved(QString, QString))); @@ -111,14 +106,34 @@ void Core::serverDisconnected(QString net) { coreProxy->csServerDisconnected(net); } +void Core::msgFromGUI(BufferId bufid, QString msg) { + emit msgFromGUI(bufid.network(), bufid.buffer(), msg); +} + // ALL messages coming pass through these functions before going to the GUI. // So this is the perfect place for storing the backlog and log stuff. + +void Core::recvMessageFromServer(Message::Type type, QString target, QString text, QString sender, quint8 flags) { + Server *s = qobject_cast(this->sender()); + Q_ASSERT(s); + BufferId buf; + if((flags & Message::PrivMsg) && !(flags & Message::Self)) { + buf = backlog.getBufferId(s->getNetwork(), nickFromMask(sender)); + } else { + buf = backlog.getBufferId(s->getNetwork(), target); + } + Message msg(buf, type, text, sender, flags); + msg.msgId = backlog.logMessage(msg); + emit displayMsg(msg); +} +/* void Core::recvMessageFromServer(Message msg) { Server *s = qobject_cast(sender()); Q_ASSERT(s); - logMessageOld(s->getNetwork(), msg); + logMessage(s->getNetwork(), msg); emit displayMsg(s->getNetwork(), msg); } +*/ void Core::recvStatusMsgFromServer(QString msg) { Server *s = qobject_cast(sender()); @@ -126,154 +141,30 @@ void Core::recvStatusMsgFromServer(QString msg) { emit displayStatusMsg(s->getNetwork(), msg); } -void Core::initBackLog() { - QDir backLogDir = QDir(Global::quasselDir); - 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()); - backLogEnabled = false; - return; - } - } - QString backLogFile = Global::quasselDir + "/quassel-backlog.sqlite"; - logDb = QSqlDatabase::addDatabase("QSQLITE", "backlog"); - 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()); - } - // TODO store database version - QSqlQuery query = logDb.exec("CREATE TABLE IF NOT EXISTS backlog (" - "Time INTEGER, User TEXT, Network TEXT, Buffer TEXT, Message BLOB" - ");"); - if(query.lastError().isValid()) { - qWarning(tr("Could not create backlog table: %1").arg(query.lastError().text()).toAscii()); - qWarning(tr("Disabling logging...").toAscii()); - backLogEnabled = false; - return; - } - - backLogEnabled = true; +QList Core::getBuffers() { + return backlog.requestBuffers(); } -// file name scheme: quassel-backlog-2006-29-10.bin -void Core::initBackLogOld() { - 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()); - backLogEnabled = 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()) { - Message m; - in >> m; - backLog[net].append(m); - } - f.close(); - } - } - backLogEnabled = true; -} +void Core::sendBacklog(BufferId id, QVariant v1, QVariant v2) { + QList log; + QList msglist; + if(v1.type() == QVariant::DateTime) { + -void Core::logMessage(QString net, Message msg) { - if(!backLogEnabled) return; - QString buf; - if(msg.flags & Message::PrivMsg) { - // query - if(msg.flags & Message::Self) buf = msg.target; - else buf = nickFromMask(msg.sender); } else { - buf = msg.target; - } - QSqlQuery query = logDb.exec(QString("INSERT INTO backlog Time, User, Network, Buffer, Message " - "VALUES %1, %2, %3, %4, %5;") - .arg(msg.timeStamp.toTime_t()).arg("Default").arg(net).arg(buf).arg(msg.text)); - if(query.lastError().isValid()) { - qWarning(tr("Error while logging to database: %1").arg(query.lastError().text()).toAscii()); + msglist = backlog.requestMsgs(id, v1.toInt(), v2.toInt()); } -} - - -/** Log a core message (emitted via a displayMsg() signal) to the backlog file. - * If a file for the current day does not exist, one will be created. Otherwise, messages will be appended. - * The file header is the string defined by BACKLOG_STRING, followed by a quint8 specifying the format - * version (BACKLOG_FORMAT). The rest is simply serialized Message objects. - */ -void Core::logMessageOld(QString net, Message msg) { - backLog[net].append(msg); - if(!logFileDirs.contains(net)) { - QDir dir(backLogDir.absolutePath() + "/" + net); - if(!dir.exists()) { - qWarning(QString("Creating backlog directory \"%1\"...").arg(dir.absolutePath()).toAscii()); - if(!dir.mkpath(dir.absolutePath())) { - qWarning(QString("Could not create backlog directory!").toAscii()); - return; - } + // Send messages out in smaller packages - we don't want to make the signal data too large! + for(int i = 0; i < msglist.count(); i++) { + log.append(QVariant::fromValue(msglist[i])); + if(log.count() >= 5) { + emit backlogData(id, log, i >= msglist.count() - 1); + log.clear(); } - logFileDirs[net] = dir; - Q_ASSERT(!logFiles.contains(net) && !logStreams.contains(net)); - if(!logFiles.contains(net)) logFiles[net] = new QFile(); - if(!logStreams.contains(net)) logStreams[net] = new QDataStream(); - } - if(!logFileDates[net].isValid() || logFileDates[net] < QDate::currentDate()) { - if(logFiles[net]->isOpen()) logFiles[net]->close(); - logFileDates[net] = QDate::currentDate(); } - if(!logFiles[net]->isOpen()) { - logFiles[net]->setFileName(QString("%1/%2").arg(logFileDirs[net].absolutePath()) - .arg(logFileDates[net].toString("'quassel-backlog-'yyyy-MM-dd'.bin'"))); - if(!logFiles[net]->open(QIODevice::WriteOnly|QIODevice::Append|QIODevice::Unbuffered)) { - qWarning(QString("Could not open \"%1\" for writing: %2") - .arg(logFiles[net]->fileName()).arg(logFiles[net]->errorString()).toAscii()); - return; - } - logStreams[net]->setDevice(logFiles[net]); logStreams[net]->setVersion(QDataStream::Qt_4_2); - if(!logFiles[net]->size()) *logStreams[net] << BACKLOG_STRING << (quint8)BACKLOG_FORMAT; - } - *logStreams[net] << msg; + if(log.count() > 0) emit backlogData(id, log, true); } + Core *core = 0; diff --git a/core/core.h b/core/core.h index 64178258..c5d266c6 100644 --- a/core/core.h +++ b/core/core.h @@ -27,6 +27,8 @@ #include #include "server.h" +#include "backlog.h" +#include "global.h" class Core : public QObject { Q_OBJECT @@ -35,45 +37,52 @@ class Core : public QObject { Core(); ~Core(); - QHash > getBackLog() { return backLog; }; + QHash > getBackLog() { return QHash >()/*backLog*/; }; // FIXME + QList getBuffers(); public slots: void connectToIrc(QStringList); + void sendBacklog(BufferId, QVariant, QVariant); + void msgFromGUI(BufferId, QString message); signals: - void msgFromGUI(QString network, QString channel, QString message); - void displayMsg(QString network, Message message); + void msgFromGUI(QString net, QString buf, QString message); + void displayMsg(Message message); void displayStatusMsg(QString, QString); void connectToIrc(QString net); void disconnectFromIrc(QString net); void serverStateRequested(); + void backlogData(BufferId, QList, bool done); + private slots: //void serverStatesRequested(); void globalDataUpdated(QString); void recvStatusMsgFromServer(QString msg); - void recvMessageFromServer(Message msg); + //void recvMessageFromServer(Message msg); + void recvMessageFromServer(Message::Type, QString target, QString text, QString sender = "", quint8 flags = Message::None); void serverDisconnected(QString net); private: + Backlog backlog; QDir backLogDir; bool backLogEnabled; QHash servers; - QHash > backLog; + //QHash > backLog; //QHash netIdx; - QHash logFiles; - QHash logStreams; - QHash logFileDates; - QHash logFileDirs; + //QHash logFiles; + //QHash logStreams; + //QHash logFileDates; + //QHash logFileDirs; - QSqlDatabase logDb; + //QSqlDatabase logDb; //uint getNetIdx(QString net); - void initBackLog(); - void initBackLogOld(); - void logMessage(QString, Message); - void logMessageOld(QString, Message); + //void initBackLog(); + //void initBackLogOld(); + //void logMessage(QString, Message); + //void logMessageOld(QString, Message); }; diff --git a/core/coreproxy.cpp b/core/coreproxy.cpp index 11fdf95b..a09a4f52 100644 --- a/core/coreproxy.cpp +++ b/core/coreproxy.cpp @@ -88,6 +88,7 @@ void CoreProxy::processClientInit(QTcpSocket *socket, const QVariant &v) { coreData[key] = global->getData(key); } reply["CoreData"] = coreData; + /* VarMap bl; QHash > log = core->getBackLog(); foreach(QString net, log.keys()) { @@ -97,6 +98,10 @@ void CoreProxy::processClientInit(QTcpSocket *socket, const QVariant &v) { bl[net] = buf; } reply["CoreBackLog"] = bl; + */ + QList bufs; + foreach(BufferId id, core->getBuffers()) { bufs.append(QVariant::fromValue(id)); } + reply["CoreBuffers"] = bufs; QList sigdata; sigdata.append(CS_CORE_STATE); sigdata.append(QVariant(reply)); sigdata.append(QVariant()); sigdata.append(QVariant()); writeDataToDevice(socket, QVariant(sigdata)); @@ -133,8 +138,10 @@ void CoreProxy::recv(GUISignal sig, QVariant arg1, QVariant arg2, QVariant arg3) //qDebug() << "[CORE] Received signal" << sig << ":" << arg1<(), arg2.toString()); break; case GS_REQUEST_CONNECT: emit gsRequestConnect(arg1.toStringList()); break; + case GS_IMPORT_BACKLOG: emit gsImportBacklog(); break; + case GS_REQUEST_BACKLOG: emit gsRequestBacklog(arg1.value(), arg2, arg3); break; default: qWarning() << "Unknown signal in CoreProxy::recv: " << sig; } } diff --git a/core/coreproxy.h b/core/coreproxy.h index 8aecb18f..44ccdf99 100644 --- a/core/coreproxy.h +++ b/core/coreproxy.h @@ -44,22 +44,24 @@ class CoreProxy : public QObject { inline void csServerConnected(QString net) { send(CS_SERVER_CONNECTED, net); } inline void csServerDisconnected(QString net) { send(CS_SERVER_DISCONNECTED, net); } inline void csServerState(QString net, VarMap data) { send(CS_SERVER_STATE, net, data); } - inline void csDisplayMsg(QString net, Message msg) { send(CS_DISPLAY_MSG, net, QVariant::fromValue(msg)); } + inline void csDisplayMsg(Message msg) { send(CS_DISPLAY_MSG, QVariant::fromValue(msg)); } inline void csDisplayStatusMsg(QString net, QString msg) { send(CS_DISPLAY_STATUS_MSG, net, msg); } inline void csModeSet(QString net, QString target, QString mode) { send(CS_MODE_SET, net, target, mode); } inline void csTopicSet(QString net, QString buf, QString topic) { send(CS_TOPIC_SET, net, buf, topic); } - inline void csSetNicks(QString net, QString buf, QStringList nicks) { send(CS_SET_NICKS, net, buf, nicks); } inline void csNickAdded(QString net, QString nick, VarMap props) { send(CS_NICK_ADDED, net, nick, props); } inline void csNickRemoved(QString net, QString nick) { send(CS_NICK_REMOVED, net, nick); } inline void csNickRenamed(QString net, QString oldn, QString newn) { send(CS_NICK_RENAMED, net, oldn, newn); } inline void csNickUpdated(QString net, QString nick, VarMap props) { send(CS_NICK_UPDATED, net, nick, props); } inline void csOwnNickSet(QString net, QString nick) { send(CS_OWN_NICK_SET, net, nick); } inline void csQueryRequested(QString net, QString nick) { send(CS_QUERY_REQUESTED, net, nick); } + inline void csBacklogData(BufferId id, QList msg, bool done) { send(CS_BACKLOG_DATA, QVariant::fromValue(id), msg, done); } signals: void gsPutGlobalData(QString, QVariant); - void gsUserInput(QString, QString, QString); + void gsUserInput(BufferId, QString); void gsRequestConnect(QStringList networks); + void gsImportBacklog(); + void gsRequestBacklog(BufferId, QVariant, QVariant); void requestServerStates(); diff --git a/core/server.cpp b/core/server.cpp index cc97fde0..d9ebdc93 100644 --- a/core/server.cpp +++ b/core/server.cpp @@ -90,7 +90,7 @@ void Server::socketError( QAbstractSocket::SocketError err ) { void Server::socketConnected( ) { emit connected(network); - putRawLine(QString("NICK :%1").arg(identity["NickList"].toStringList()[0])); + putRawLine(QString("NICK :%1").arg(identity["NickList"].toStringList()[0])); // FIXME: try more nicks if error occurs putRawLine(QString("USER %1 8 * :%2").arg(identity["Ident"].toString()).arg(identity["RealName"].toString())); } @@ -201,7 +201,7 @@ void Server::handleServerMsg(QString msg) { defaultServerHandler(cmd, prefix, params); } } catch(Exception e) { - emit displayMsg(Message::error("", e.msg())); + emit displayMsg(Message::Error, "", e.msg()); } } @@ -213,24 +213,24 @@ void Server::defaultServerHandler(QString cmd, QString prefix, QStringList param switch(num) { // Welcome, status, info messages. Just display these. case 2: case 3: case 4: case 5: case 251: case 252: case 253: case 254: case 255: case 372: case 375: - emit displayMsg(Message::server("", params.join(" "), prefix)); + emit displayMsg(Message::Server, "", params.join(" "), prefix); break; // Server error messages without param, just display them case 409: case 411: case 412: case 422: case 424: case 431: case 445: case 446: case 451: case 462: case 463: case 464: case 465: case 466: case 472: case 481: case 483: case 485: case 491: case 501: case 502: - emit displayMsg(Message::error("", params.join(" "), prefix)); + emit displayMsg(Message::Error, "", params.join(" "), prefix); break; // Server error messages, display them in red. First param will be appended. case 401: case 402: case 403: case 404: case 406: case 408: case 415: case 421: case 432: case 442: { QString p = params.takeFirst(); - emit displayMsg(Message::error("", params.join(" ") + " " + p, prefix)); + emit displayMsg(Message::Error, "", params.join(" ") + " " + p, prefix); break; } // Server error messages which will be displayed with a colon between the first param and the rest case 413: case 414: case 423: case 436: case 441: case 444: case 461: case 467: case 471: case 473: case 474: case 475: case 476: case 477: case 478: case 482: { QString p = params.takeFirst(); - emit displayMsg(Message::error("", p + ": " + params.join(" "))); + emit displayMsg(Message::Error, "", p + ": " + params.join(" ")); break; } // Ignore these commands. @@ -239,11 +239,11 @@ void Server::defaultServerHandler(QString cmd, QString prefix, QStringList param // Everything else will be marked in red, so we can add them somewhere. default: - emit displayMsg(Message::error("", cmd + " " + params.join(" "), prefix)); + emit displayMsg(Message::Error, "", cmd + " " + params.join(" "), prefix); } //qDebug() << prefix <<":"< 2) msg = QString("%1 %2").arg(msg).arg(params[2]); - emit displayMsg(Message::kick(params[0], msg, prefix)); + emit displayMsg(Message::Kick, params[0], msg, prefix); if(chans.count() > 0) { n["Channels"] = chans; nicks[nick] = n; @@ -496,12 +498,12 @@ void Server::handleServerMode(QString prefix, QStringList params) { m++; } } - emit displayMsg(Message::mode(params[0], params.join(" "), prefix)); + emit displayMsg(Message::Mode, params[0], params.join(" "), prefix); } else { //Q_ASSERT(nicks.contains(params[0])); //VarMap n = nicks[params[0]].toMap(); //QString mode = n["Mode"].toString(); - emit displayMsg(Message::mode("", params.join(" "))); + emit displayMsg(Message::Mode, "", params.join(" ")); } } @@ -512,8 +514,8 @@ void Server::handleServerNick(QString prefix, QStringList params) { nicks[newnick] = v; VarMap chans = v["Channels"].toMap(); foreach(QString c, chans.keys()) { - if(oldnick != ownNick) { emit displayMsg(Message::nick(c, newnick, prefix)); } - else { emit displayMsg(Message::nick(c, newnick, newnick)); } + if(oldnick != ownNick) { emit displayMsg(Message::Nick, c, newnick, prefix); } + else { emit displayMsg(Message::Nick, c, newnick, newnick); } } emit nickRenamed(network, oldnick, newnick); if(oldnick == ownNick) { @@ -524,8 +526,8 @@ void Server::handleServerNick(QString prefix, QStringList params) { void Server::handleServerNotice(QString prefix, QStringList params) { //Message msg(Message::Notice, params[1], prefix); - if(currentServer.isEmpty() || prefix == currentServer) emit displayMsg(Message::server("", params[1], prefix)); - else emit displayMsg(Message::notice("", params[1], prefix)); + if(currentServer.isEmpty() || prefix == currentServer) emit displayMsg(Message::Server, "", params[1], prefix); + else emit displayMsg(Message::Notice, "", params[1], prefix); } void Server::handleServerPart(QString prefix, QStringList params) { @@ -537,7 +539,7 @@ void Server::handleServerPart(QString prefix, QStringList params) { chans.remove(params[0]); QString msg; if(params.count() > 1) msg = params[1]; - emit displayMsg(Message::part(params[0], msg, prefix)); + emit displayMsg(Message::Part, params[0], msg, prefix); if(chans.count() > 0) { n["Channels"] = chans; nicks[nick] = n; @@ -559,13 +561,13 @@ void Server::handleServerPing(QString prefix, QStringList params) { void Server::handleServerPrivmsg(QString prefix, QStringList params) { updateNickFromMask(prefix); Q_ASSERT(params.count() >= 2); - if(params.count()<2) emit displayMsg(Message::plain(params[0], "", prefix)); + if(params.count()<2) emit displayMsg(Message::Plain, params[0], "", prefix); else { if(params[0] == ownNick) { - emit displayMsg(Message::plain("", params[1], prefix, Message::PrivMsg)); + emit displayMsg(Message::Plain, "", params[1], prefix, Message::PrivMsg); } else { Q_ASSERT(isChannelName(params[0])); // should be channel! - emit displayMsg(Message::plain(params[0], params[1], prefix)); + emit displayMsg(Message::Plain, params[0], params[1], prefix); } } } @@ -575,7 +577,7 @@ void Server::handleServerQuit(QString prefix, QStringList params) { Q_ASSERT(nicks.contains(nick)); VarMap chans = nicks[nick]["Channels"].toMap(); foreach(QString c, chans.keys()) { - emit displayMsg(Message::quit(c, params[0], prefix)); + emit displayMsg(Message::Quit, c, params[0], prefix); } nicks.remove(nick); emit nickRemoved(network, nick); @@ -586,7 +588,7 @@ void Server::handleServerTopic(QString prefix, QStringList params) { Q_ASSERT(nicks.contains(nick)); topics[params[0]] = params[1]; emit topicSet(network, params[0], params[1]); - emit displayMsg(Message::server(params[0], tr("%1 has changed topic for %2 to: \"%3\"").arg(nick).arg(params[0]).arg(params[1]))); + emit displayMsg(Message::Server, params[0], tr("%1 has changed topic for %2 to: \"%3\"").arg(nick).arg(params[0]).arg(params[1])); } /* RPL_WELCOME */ @@ -599,7 +601,7 @@ void Server::handleServer001(QString prefix, QStringList params) { nicks[ownNick] = n; emit ownNickSet(network, ownNick); emit nickAdded(network, ownNick, VarMap()); - emit displayMsg(Message::server("", params[0], prefix)); + emit displayMsg(Message::Server, "", params[0], prefix); // send performlist QStringList performList = networkSettings["Perform"].toString().split( "\n" ); int count = performList.count(); @@ -641,20 +643,20 @@ void Server::handleServer005(QString prefix, QStringList params) { void Server::handleServer331(QString prefix, QStringList params) { topics[params[0]] = ""; emit topicSet(network, params[0], ""); - emit displayMsg(Message::server(params[0], tr("No topic is set for %1.").arg(params[0]))); + emit displayMsg(Message::Server, params[0], tr("No topic is set for %1.").arg(params[0])); } /* RPL_TOPIC */ void Server::handleServer332(QString prefix, QStringList params) { topics[params[0]] = params[1]; emit topicSet(network, params[0], params[1]); - emit displayMsg(Message::server(params[0], tr("Topic for %1 is \"%2\"").arg(params[0]).arg(params[1]))); + emit displayMsg(Message::Server, params[0], tr("Topic for %1 is \"%2\"").arg(params[0]).arg(params[1])); } /* Topic set by... */ void Server::handleServer333(QString prefix, QStringList params) { - emit displayMsg(Message::server(params[0], - tr("Topic set by %1 on %2").arg(params[1]).arg(QDateTime::fromTime_t(params[2].toUInt()).toString()))); + emit displayMsg(Message::Server, params[0], + tr("Topic set by %1 on %2").arg(params[1]).arg(QDateTime::fromTime_t(params[2].toUInt()).toString())); } /* RPL_NAMREPLY */ @@ -692,7 +694,7 @@ void Server::handleServer353(QString prefix, QStringList params) { /* RPL_NICKNAMEINUSER */ void Server::handleServer433(QString prefix, QStringList params) { QString errnick = params[0]; - emit displayMsg(Message::error("", tr("Nick %1 is already taken").arg(errnick))); + emit displayMsg(Message::Error, "", tr("Nick %1 is already taken").arg(errnick)); // if there is a problem while connecting to the server -> we handle it // TODO rely on another source... if(currentServer.isEmpty()) { @@ -701,7 +703,7 @@ void Server::handleServer433(QString prefix, QStringList params) { if (desiredNicks.size() > nextNick) { putCmd("NICK", QStringList(desiredNicks[nextNick])); } else { - emit displayMsg(Message::error("", "All nicks in nicklist taken... use: /nick to continue")); + emit displayMsg(Message::Error, "", "All nicks in nicklist taken... use: /nick to continue"); } } } diff --git a/core/server.h b/core/server.h index b2fb2304..0117b631 100644 --- a/core/server.h +++ b/core/server.h @@ -65,7 +65,8 @@ class Server : public QThread { void serverState(QString net, VarMap data); void recvRawServerMsg(QString); void displayStatusMsg(QString); - void displayMsg(Message msg); + //void displayMsg(Message msg); + void displayMsg(Message::Type, QString target, QString text, QString sender = "", quint8 flags = Message::None); void connected(QString network); void disconnected(QString network); @@ -75,7 +76,6 @@ class Server : public QThread { void nickUpdated(QString network, QString nick, VarMap props); void modeSet(QString network, QString target, QString mode); void topicSet(QString network, QString buffer, QString topic); - void setNicks(QString network, QString buffer, QStringList nicks); void ownNickSet(QString network, QString newNick); void queryRequested(QString network, QString nick); diff --git a/gui/buffer.cpp b/gui/buffer.cpp index 7c92ac66..ec45141b 100644 --- a/gui/buffer.cpp +++ b/gui/buffer.cpp @@ -23,12 +23,21 @@ #include "chatwidget.h" #include "bufferwidget.h" +/* Buffer::Buffer(QString netname, QString bufname) { - _networkName = netname; - _bufferName = bufname; + Buffer(BufferId(0, netname, bufname)); + + +} +*/ + +Buffer::Buffer(BufferId bufid) { + id = bufid; + _networkName = bufid.network(); + _bufferName = bufid.buffer(); - if(bufname.isEmpty()) type = ServerBuffer; - else if(isChannelName(bufname)) type = ChannelBuffer; + if(_bufferName.isEmpty()) type = ServerBuffer; + else if(isChannelName(_bufferName)) type = ChannelBuffer; else type = QueryBuffer; active = false; @@ -65,6 +74,7 @@ void Buffer::setActive(bool a) { } } +/* void Buffer::displayMsg(Message msg) { contents()->append(msg); emit msgDisplayed(msg); @@ -73,10 +83,21 @@ void Buffer::displayMsg(Message msg) { void Buffer::prependMessages(QList msgs) { _contents = msgs + _contents; } +*/ + +void Buffer::appendChatLine(ChatLine *line) { + lines.append(line); + emit chatLineAppended(line); +} + +void Buffer::prependChatLine(ChatLine *line) { + lines.prepend(line); + emit chatLinePrepended(line); +} void Buffer::processUserInput(QString msg) { // TODO User Input processing (plugins) -> well, this goes through MainWin into Core for processing... so... - emit userInput(networkName(), bufferName(), msg); + emit userInput(id, msg); } void Buffer::setTopic(QString t) { diff --git a/gui/buffer.h b/gui/buffer.h index 09f7e029..7738ebe1 100644 --- a/gui/buffer.h +++ b/gui/buffer.h @@ -24,10 +24,12 @@ #include #include +#include "chatwidget.h" #include "global.h" #include "message.h" class ChatWidget; +class ChatLine; class ChatWidgetContents; class BufferWidget; struct BufferState; @@ -41,7 +43,8 @@ class Buffer : public QObject { Q_OBJECT public: - Buffer(QString network, QString buffer); + //Buffer(QString network, QString buffer); + Buffer(BufferId); ~Buffer(); static void init(); @@ -51,14 +54,17 @@ class Buffer : public QObject { QString networkName() { return _networkName; } QString bufferName() { return _bufferName; } - QList *contents() { return &_contents; } + BufferId bufferId() { return id; } + QList contents() { return lines; } VarMap nickList() { return nicks; } QString topic() { return _topic; } QString ownNick() { return _ownNick; } signals: - void userInput(QString, QString, QString); - void msgDisplayed(Message); + void userInput(BufferId, QString); + //void msgDisplayed(Message); + void chatLineAppended(ChatLine *); + void chatLinePrepended(ChatLine *); void nickListChanged(VarMap nicks); void topicSet(QString topic); void ownNickSet(QString ownNick); @@ -67,8 +73,11 @@ class Buffer : public QObject { public slots: void setActive(bool active = true); - void displayMsg(Message); - void prependMessages(QList); // for backlog + //void displayMsg(Message); + //void prependMessages(QList); // for backlog + void appendChatLine(ChatLine *); + void prependChatLine(ChatLine *); + //void prependChatLines(QList); //void recvStatusMsg(QString msg); void setTopic(QString); //void setNicks(QStringList); @@ -81,6 +90,7 @@ class Buffer : public QObject { void processUserInput(QString); private: + BufferId id; bool active; Type type; @@ -90,7 +100,8 @@ class Buffer : public QObject { QString _networkName, _bufferName; BufferState *state; - QList _contents; + //QList _contents; + QList lines; }; diff --git a/gui/bufferwidget.cpp b/gui/bufferwidget.cpp index 8185cbcf..d3de0536 100644 --- a/gui/bufferwidget.cpp +++ b/gui/bufferwidget.cpp @@ -42,8 +42,8 @@ BufferWidget::BufferWidget(QWidget *parent) : QWidget(parent) { void BufferWidget::init() { //layoutThread = new LayoutThread(); - layoutThread = ::layoutThread; - connect(layoutThread, SIGNAL(taskProcessed(LayoutTask)), this, SLOT(messagesLayouted(LayoutTask))); + //layoutThread = ::layoutThread; + //connect(layoutThread, SIGNAL(taskProcessed(LayoutTask)), this, SLOT(messagesLayouted(LayoutTask))); //layoutThread->start(); //while(!layoutThread->isRunning()) {}; } @@ -51,7 +51,7 @@ void BufferWidget::init() { BufferWidget::~BufferWidget() { //emit aboutToClose(); //layoutThread->wait(10000); - delete layoutThread; + //delete layoutThread; foreach(BufferState *s, states.values()) { delete s; } @@ -89,14 +89,9 @@ void BufferWidget::setBuffer(Buffer *buf) { states[buf] = s; state = s; state->chatWidget->init(networkName, bufferName); - // FIXME: layout and cache all incoming messages... maybe do this in buffer? - QList *l = buf->contents(); - state->chatWidget->appendMsgList(l); - if(chatLineCache.contains(buf)) { - state->chatWidget->prependChatLines(chatLineCache[buf]); - buf->prependMessages(msgCache[buf]); - } - connect(buf, SIGNAL(msgDisplayed(Message)), state->chatWidget, SLOT(appendMsg(Message))); + state->chatWidget->setContents(buf->contents()); + connect(buf, SIGNAL(chatLineAppended(ChatLine *)), state->chatWidget, SLOT(appendChatLine(ChatLine *))); + connect(buf, SIGNAL(chatLinePrepended(ChatLine *)), state->chatWidget, SLOT(prependChatLine(ChatLine *))); connect(buf, SIGNAL(topicSet(QString)), this, SLOT(setTopic(QString))); connect(buf, SIGNAL(ownNickSet(QString)), this, SLOT(setOwnNick(QString))); ui.stackedWidget->addWidget(s->page); @@ -117,6 +112,7 @@ void BufferWidget::setBuffer(Buffer *buf) { updateTitle(); } +/* void BufferWidget::prependMessages(Buffer *buf, QList messages) { LayoutTask task; task.messages = messages; @@ -136,6 +132,7 @@ void BufferWidget::messagesLayouted(LayoutTask task) { chatLineCache[task.buffer] = task.lines + chatLineCache[task.buffer]; } } +*/ void BufferWidget::saveState() { foreach(Buffer *buf, states.keys()) { diff --git a/gui/bufferwidget.h b/gui/bufferwidget.h index 94ff0bc3..fb68a484 100644 --- a/gui/bufferwidget.h +++ b/gui/bufferwidget.h @@ -51,7 +51,7 @@ class BufferWidget : public QWidget { void userInput(QString msg); void aboutToClose(); - void layoutMessages(LayoutTask); + //void layoutMessages(LayoutTask); void nickListUpdated(QStringList l); protected: @@ -59,7 +59,7 @@ class BufferWidget : public QWidget { public slots: void setBuffer(Buffer *); void saveState(); - void prependMessages(Buffer *, QList); // for backlog processing + //void prependMessages(Buffer *, QList); // for backlog processing protected: void resizeEvent ( QResizeEvent * event ); @@ -76,7 +76,7 @@ class BufferWidget : public QWidget { void setTopic(QString topic); void setActive(bool act = true); - void messagesLayouted(LayoutTask); + //void messagesLayouted(LayoutTask); private: @@ -92,9 +92,9 @@ class BufferWidget : public QWidget { QString networkName; QString bufferName; - LayoutThread *layoutThread; - QHash > chatLineCache; - QHash > msgCache; + //LayoutThread *layoutThread; + //QHash > chatLineCache; + //QHash > msgCache; }; struct BufferState { diff --git a/gui/chatwidget.cpp b/gui/chatwidget.cpp index a3ab3add..9bd4fc98 100644 --- a/gui/chatwidget.cpp +++ b/gui/chatwidget.cpp @@ -65,9 +65,9 @@ void ChatWidget::init(QString netname, QString bufname) { ChatWidget::~ChatWidget() { //qDebug() << "destroying chatwidget" << bufferName; - foreach(ChatLine *l, lines) { - delete l; - } + //foreach(ChatLine *l, lines) { + // delete l; + //} } QSize ChatWidget::sizeHint() const { @@ -140,6 +140,21 @@ void ChatWidget::clear() { //contents->clear(); } +void ChatWidget::prependChatLine(ChatLine *line) { + qreal h = line->layout(tsWidth, senderWidth, textWidth); + for(int i = 1; i < ycoords.count(); i++) ycoords[i] += h; + ycoords.insert(1, h); + lines.prepend(line); + height += h; + // Fix all variables containing line numbers + dragStartLine ++; + curLine ++; + selectionStart ++; selectionEnd ++; + adjustScrollBar(); + verticalScrollBar()->setValue(verticalScrollBar()->value() + (int)h); + viewport()->update(); +} + void ChatWidget::prependChatLines(QList clist) { QList tmpy; tmpy.append(0); qreal h = 0; @@ -152,11 +167,11 @@ void ChatWidget::prependChatLines(QList clist) { ycoords = tmpy + ycoords; lines = clist + lines; height += h; - /* Fix all variables containing line numbers */ + // Fix all variables containing line numbers int i = clist.count(); dragStartLine += i; curLine += i; - selectionStart += i; selectionEnd += i; selectionEnd += i; + selectionStart += i; selectionEnd += i; //? selectionEnd += i; //if(bottomLine >= 0) bottomLine += i; adjustScrollBar(); //verticalScrollBar()->setPageStep(viewport()->height()); @@ -166,8 +181,8 @@ void ChatWidget::prependChatLines(QList clist) { viewport()->update(); } -void ChatWidget::appendMsg(Message msg) { - ChatLine *line = new ChatLine(msg, networkName, bufferName); + +void ChatWidget::appendChatLine(ChatLine *line) { qreal h = line->layout(tsWidth, senderWidth, textWidth); ycoords.append(h + ycoords[ycoords.count() - 1]); height += h; @@ -178,9 +193,8 @@ void ChatWidget::appendMsg(Message msg) { viewport()->update(); } -void ChatWidget::appendMsgList(QList *list) { - foreach(Message msg, *list) { - ChatLine *line = new ChatLine(msg, networkName, bufferName); +void ChatWidget::appendChatLines(QList list) { + foreach(ChatLine *line, list) { qreal h = line->layout(tsWidth, senderWidth, textWidth); ycoords.append(h + ycoords[ycoords.count() - 1]); height += h; @@ -192,6 +206,14 @@ void ChatWidget::appendMsgList(QList *list) { viewport()->update(); } +void ChatWidget::setContents(QList list) { + ycoords.clear(); + ycoords.append(0); + height = 0; + lines.clear(); + appendChatLines(list); +} + //!\brief Computes the different x position vars for given tsWidth and senderWidth. void ChatWidget::computePositions() { senderX = tsWidth + Style::sepTsSender(); @@ -492,13 +514,13 @@ QString ChatWidget::selectionToString() { if(selectionMode == LinesSelected) { QString result; for(int l = selectionStart; l <= selectionEnd; l++) { - result += QString("[%1] %2 %3\n").arg(lines[l]->getTimeStamp().toLocalTime().toString("hh:mm:ss")) - .arg(lines[l]->getSender()).arg(lines[l]->getText()); + result += QString("[%1] %2 %3\n").arg(lines[l]->timeStamp().toLocalTime().toString("hh:mm:ss")) + .arg(lines[l]->sender()).arg(lines[l]->text()); } return result; } // selectionMode == TextSelected - return lines[selectionLine]->getText().mid(selectionStart, selectionEnd - selectionStart); + return lines[selectionLine]->text().mid(selectionStart, selectionEnd - selectionStart); } /************************************************************************************/ @@ -509,14 +531,13 @@ QString ChatWidget::selectionToString() { * \param net The network name * \param buf The buffer name */ -ChatLine::ChatLine(Message m, QString net, QString buf) : QObject() { +ChatLine::ChatLine(Message m) : QObject() { hght = 0; - networkName = net; - bufferName = buf; + //networkName = m.buffer.network(); + //bufferName = m.buffer.buffer(); msg = m; selectionMode = None; formatMsg(msg); - } ChatLine::~ChatLine() { @@ -528,6 +549,8 @@ void ChatLine::formatMsg(Message msg) { QString host = hostFromMask(msg.sender); QString nick = nickFromMask(msg.sender); QString text = Style::mircToInternal(msg.text); + QString networkName = msg.buffer.network(); + QString bufferName = msg.buffer.buffer(); QString c = tr("%DT[%1]").arg(msg.timeStamp.toLocalTime().toString("hh:mm:ss")); QString s, t; @@ -649,15 +672,23 @@ void ChatLine::setSelection(SelectionMode mode, int start, int end) { } } -QDateTime ChatLine::getTimeStamp() { +uint ChatLine::msgId() { + return msg.buffer.uid(); +} + +BufferId ChatLine::bufferId() { + return msg.buffer; +} + +QDateTime ChatLine::timeStamp() { return msg.timeStamp; } -QString ChatLine::getSender() { +QString ChatLine::sender() { return senderFormatted.text; } -QString ChatLine::getText() { +QString ChatLine::text() { return textFormatted.text; } @@ -879,50 +910,3 @@ void ChatLine::draw(QPainter *p, const QPointF &pos) { /******************************************************************************************************************/ -LayoutThread::LayoutThread() : QThread() { - mutex.lock(); - abort = false; - mutex.unlock(); - -} - -LayoutThread::~LayoutThread() { - mutex.lock(); - abort = true; - mutex.unlock(); - condition.wakeOne(); - wait(); -} - -void LayoutThread::processTask(LayoutTask task) { - if(!isRunning()) start(); - Q_ASSERT(isRunning()); - mutex.lock(); - queue.append(task); - condition.wakeOne(); - mutex.unlock(); -} - -void LayoutThread::run() { - forever { - mutex.lock(); - if(!queue.count()) { - condition.wait(&mutex); - } - if(abort) { - mutex.unlock(); return; - } - Q_ASSERT(queue.count()); //qDebug() << "process"; - LayoutTask task = queue.takeFirst(); - mutex.unlock(); - /* - foreach(Message msg, task.messages) { - //qDebug() << msg.text; - ChatLine *line = new ChatLine(msg, task.net, task.buf); - task.lines.append(line); - } - emit taskProcessed(task); - */ - //msleep(500); - } -} diff --git a/gui/chatwidget.h b/gui/chatwidget.h index 16418242..2fdd8957 100644 --- a/gui/chatwidget.h +++ b/gui/chatwidget.h @@ -52,9 +52,11 @@ class ChatWidget : public QAbstractScrollArea { public slots: void clear(); + void prependChatLine(ChatLine *); + void appendChatLine(ChatLine *); void prependChatLines(QList); - void appendMsg(Message); - void appendMsgList(QList *); + void appendChatLines(QList); + void setContents(QList); protected: virtual void resizeEvent(QResizeEvent *event); @@ -133,7 +135,7 @@ class ChatLine : public QObject { Q_OBJECT public: - ChatLine(Message message, QString networkName, QString bufferName); + ChatLine(Message message); ~ChatLine(); qreal layout(qreal tsWidth, qreal nickWidth, qreal textWidth); @@ -143,9 +145,11 @@ class ChatLine : public QObject { enum SelectionMode { None, Partial, Full }; void setSelection(SelectionMode, int start = 0, int end = 0); - QDateTime getTimeStamp(); - QString getSender(); - QString getText(); + QDateTime timeStamp(); + QString sender(); + QString text(); + uint msgId(); + BufferId bufferId(); bool isUrl(int pos); QUrl getUrl(int pos); @@ -155,7 +159,6 @@ class ChatLine : public QObject { private: qreal hght; Message msg; - QString networkName, bufferName; qreal tsWidth, senderWidth, textWidth; Style::FormattedString tsFormatted, senderFormatted, textFormatted; @@ -193,6 +196,7 @@ class ChatLine : public QObject { QList calcFormatRanges(const Style::FormattedString &, QTextLayout::FormatRange additional = QTextLayout::FormatRange()); }; +/* struct LayoutTask { QList messages; Buffer *buffer; @@ -223,5 +227,6 @@ class LayoutThread : public QThread { bool abort; }; +*/ #endif diff --git a/gui/guiproxy.cpp b/gui/guiproxy.cpp index 3c3c0b37..717f1bc9 100644 --- a/gui/guiproxy.cpp +++ b/gui/guiproxy.cpp @@ -33,17 +33,17 @@ void GUIProxy::recv(CoreSignal sig, QVariant arg1, QVariant arg2, QVariant arg3) case CS_SERVER_DISCONNECTED: emit csServerDisconnected(arg1.toString()); break; case CS_UPDATE_GLOBAL_DATA: emit csUpdateGlobalData(arg1.toString(), arg2); break; //case CS_GLOBAL_DATA_CHANGED: emit csGlobalDataChanged(arg1.toString()); break; - case CS_DISPLAY_MSG: emit csDisplayMsg(arg1.toString(), arg2.value()); break; + case CS_DISPLAY_MSG: emit csDisplayMsg(arg1.value()); break; case CS_DISPLAY_STATUS_MSG: emit csDisplayStatusMsg(arg1.toString(), arg2.toString()); break; case CS_MODE_SET: emit csModeSet(arg1.toString(), arg2.toString(), arg3.toString()); break; case CS_TOPIC_SET: emit csTopicSet(arg1.toString(), arg2.toString(), arg3.toString()); break; - case CS_SET_NICKS: emit csSetNicks(arg1.toString(), arg2.toString(), arg3.toStringList()); break; case CS_NICK_ADDED: emit csNickAdded(arg1.toString(), arg2.toString(), arg3.toMap()); break; case CS_NICK_REMOVED: emit csNickRemoved(arg1.toString(), arg2.toString()); break; case CS_NICK_RENAMED: emit csNickRenamed(arg1.toString(), arg2.toString(), arg3.toString()); break; case CS_NICK_UPDATED: emit csNickUpdated(arg1.toString(), arg2.toString(), arg3.toMap()); break; case CS_OWN_NICK_SET: emit csOwnNickSet(arg1.toString(), arg2.toString()); break; case CS_QUERY_REQUESTED: emit csQueryRequested(arg1.toString(), arg2.toString()); break; + case CS_BACKLOG_DATA: emit csBacklogData(arg1.value(), arg2.toList(), arg3.toBool()); break; default: qWarning() << "Unknown signal in GUIProxy::recv: " << sig; } diff --git a/gui/guiproxy.h b/gui/guiproxy.h index e07599b3..7fe0c18d 100644 --- a/gui/guiproxy.h +++ b/gui/guiproxy.h @@ -41,8 +41,10 @@ class GUIProxy : public QObject { GUIProxy(); public slots: - inline void gsUserInput(QString net, QString buf, QString msg) { send(GS_USER_INPUT, net, buf, msg); } + inline void gsUserInput(BufferId id, QString msg) { send(GS_USER_INPUT, QVariant::fromValue(id), msg); } inline void gsRequestConnect(QStringList networks) { send(GS_REQUEST_CONNECT, networks); } + inline void gsImportBacklog() { send(GS_IMPORT_BACKLOG); } + inline void gsRequestBacklog(BufferId id, QVariant v1, QVariant v2) { send(GS_REQUEST_BACKLOG, QVariant::fromValue(id), v1, v2); } void connectToCore(QString host, quint16 port); void disconnectFromCore(); @@ -52,19 +54,21 @@ class GUIProxy : public QObject { void csServerState(QString, QVariant); void csServerConnected(QString); void csServerDisconnected(QString); - void csDisplayMsg(QString, Message); + void csDisplayMsg(Message); void csDisplayStatusMsg(QString, QString); void csUpdateGlobalData(QString key, QVariant data); void csGlobalDataChanged(QString key); void csModeSet(QString, QString, QString); void csTopicSet(QString, QString, QString); - void csSetNicks(QString, QString, QStringList); void csNickAdded(QString, QString, VarMap); void csNickRemoved(QString, QString); void csNickRenamed(QString, QString, QString); void csNickUpdated(QString, QString, VarMap); void csOwnNickSet(QString, QString); void csQueryRequested(QString, QString); + void csBacklogData(BufferId, QList, bool); + + void csGeneric(int, QVariant, QVariant); void coreConnected(); void coreDisconnected(); diff --git a/gui/mainwin.cpp b/gui/mainwin.cpp index 75b53e8f..84835ad8 100644 --- a/gui/mainwin.cpp +++ b/gui/mainwin.cpp @@ -42,9 +42,14 @@ MainWin::MainWin() : QMainWindow() { //widget = 0; qDebug() << "Available DB drivers: " << QSqlDatabase::drivers (); setWindowTitle("Quassel IRC"); + //setWindowTitle("Κυασελ Εγαρζη"); setWindowIcon(QIcon(":/qirc-icon.png")); setWindowIconText("Quassel IRC"); + layoutTimer = new QTimer(this); + layoutTimer->setInterval(0); + layoutTimer->setSingleShot(false); + connect(layoutTimer, SIGNAL(timeout()), this, SLOT(layoutMsg())); //workspace = new QWorkspace(this); //setCentralWidget(workspace); statusBar()->showMessage(tr("Waiting for core...")); @@ -55,20 +60,21 @@ void MainWin::init() { connect(guiProxy, SIGNAL(csServerState(QString, QVariant)), this, SLOT(recvNetworkState(QString, QVariant))); connect(guiProxy, SIGNAL(csServerConnected(QString)), this, SLOT(networkConnected(QString))); connect(guiProxy, SIGNAL(csServerDisconnected(QString)), this, SLOT(networkDisconnected(QString))); - connect(guiProxy, SIGNAL(csDisplayMsg(QString, Message)), this, SLOT(recvMessage(QString, Message))); + connect(guiProxy, SIGNAL(csDisplayMsg(Message)), this, SLOT(recvMessage(Message))); connect(guiProxy, SIGNAL(csDisplayStatusMsg(QString, QString)), this, SLOT(recvStatusMsg(QString, QString))); connect(guiProxy, SIGNAL(csTopicSet(QString, QString, QString)), this, SLOT(setTopic(QString, QString, QString))); - connect(guiProxy, SIGNAL(csSetNicks(QString, QString, QStringList)), this, SLOT(setNicks(QString, QString, QStringList))); connect(guiProxy, SIGNAL(csNickAdded(QString, QString, VarMap)), this, SLOT(addNick(QString, QString, VarMap))); connect(guiProxy, SIGNAL(csNickRemoved(QString, QString)), this, SLOT(removeNick(QString, QString))); connect(guiProxy, SIGNAL(csNickRenamed(QString, QString, QString)), this, SLOT(renameNick(QString, QString, QString))); connect(guiProxy, SIGNAL(csNickUpdated(QString, QString, VarMap)), this, SLOT(updateNick(QString, QString, VarMap))); connect(guiProxy, SIGNAL(csOwnNickSet(QString, QString)), this, SLOT(setOwnNick(QString, QString))); - connect(this, SIGNAL(sendInput( QString, QString, QString )), guiProxy, SLOT(gsUserInput(QString, QString, QString))); + connect(guiProxy, SIGNAL(csBacklogData(BufferId, QList, bool)), this, SLOT(recvBacklogData(BufferId, QList, bool))); + connect(this, SIGNAL(sendInput(BufferId, QString)), guiProxy, SLOT(gsUserInput(BufferId, QString))); + connect(this, SIGNAL(requestBacklog(BufferId, QVariant, QVariant)), guiProxy, SLOT(gsRequestBacklog(BufferId, QVariant, QVariant))); - layoutThread = new LayoutThread(); - layoutThread->start(); - while(!layoutThread->isRunning()) {}; + //layoutThread = new LayoutThread(); + //layoutThread->start(); + //while(!layoutThread->isRunning()) {}; ui.bufferWidget->init(); show(); @@ -98,6 +104,7 @@ void MainWin::init() { // replay backlog // FIXME do this right + /* QHash > hash; Buffer *b; @@ -122,21 +129,20 @@ void MainWin::init() { foreach(Buffer *buf, hash.keys()) { ui.bufferWidget->prependMessages(buf, hash.take(buf)); } +*/ -/* - foreach(QString key, buffers.keys()) { - foreach(Buffer *b, buffers[key].values()) { - QWidget *widget = b->showWidget(this); - workspace->addWindow(widget); - widget->show(); - } + /* make lookups by id faster */ + foreach(BufferId id, coreBuffers) { + bufferIds[id.uid()] = id; // make lookups by id faster + getBuffer(id); // create all buffers, so we see them in the network views + emit requestBacklog(id, -1, -1); // TODO: use custom settings for backlog request } -*/ s.beginGroup("Buffers"); QString net = s.value("CurrentNetwork", "").toString(); QString buf = s.value("CurrentBuffer", "").toString(); s.endGroup(); + /* if(!net.isEmpty()) { if(buffers.contains(net)) { if(buffers[net].contains(buf)) { @@ -146,15 +152,17 @@ void MainWin::init() { } } } + */ } MainWin::~MainWin() { - typedef QHash BufHash; - foreach(BufHash h, buffers.values()) { - foreach(Buffer *b, h.values()) { - delete b; - } - } + //typedef QHash BufHash; + //foreach(BufHash h, buffers.values()) { + // foreach(Buffer *b, h.values()) { + // delete b; + // } + //} + foreach(Buffer *buf, buffers.values()) delete buf; } /* This is implemented in settingspages.cpp */ @@ -170,6 +178,9 @@ void MainWin::setupMenus() { connect(ui.actionSettingsDlg, SIGNAL(triggered()), this, SLOT(showSettingsDlg())); //ui.actionSettingsDlg->setEnabled(false); connect(ui.actionAboutQt, SIGNAL(triggered()), QApplication::instance(), SLOT(aboutQt())); + // for debugging + connect(ui.actionImportBacklog, SIGNAL(triggered()), this, SLOT(importBacklog())); + connect(this, SIGNAL(importOldBacklog()), guiProxy, SLOT(gsImportBacklog())); } void MainWin::setupViews() { @@ -194,13 +205,13 @@ void MainWin::registerNetView(NetworkView *view) { connect(this, SIGNAL(bufferUpdated(Buffer *)), view, SLOT(bufferUpdated(Buffer *))); connect(this, SIGNAL(bufferDestroyed(Buffer *)), view, SLOT(bufferDestroyed(Buffer *))); connect(view, SIGNAL(bufferSelected(Buffer *)), this, SLOT(showBuffer(Buffer *))); - QList bufs; - typedef QHash bufhash; - QList foo = buffers.values(); - foreach(bufhash h, foo) { - bufs += h.values(); - } - view->setBuffers(bufs); + //QList bufs; + //typedef QHash bufhash; + //QList foo = buffers.values(); + //foreach(bufhash h, foo) { + // bufs += h.values(); + //} + view->setBuffers(buffers.values()); view->setAllowedAreas(Qt::RightDockWidgetArea|Qt::LeftDockWidgetArea); netViews.append(view); ui.menuViews->addAction(view->toggleViewAction()); @@ -229,7 +240,7 @@ void MainWin::closeEvent(QCloseEvent *event) s.setValue("MainWinState", saveState()); s.endGroup(); s.beginGroup("Buffers"); - s.setValue("CurrentNetwork", currentNetwork); + //s.setValue("CurrentNetwork", currentNetwork); s.setValue("CurrentBuffer", currentBuffer); s.endGroup(); delete systray; @@ -239,12 +250,13 @@ void MainWin::closeEvent(QCloseEvent *event) //} } -void MainWin::showBuffer(QString net, QString buf) { - showBuffer(getBuffer(net, buf)); +void MainWin::showBuffer(BufferId id) { + showBuffer(getBuffer(id)); } void MainWin::showBuffer(Buffer *b) { - currentBuffer = b->bufferName(); currentNetwork = b->networkName(); + //currentBuffer = b->bufferName(); currentNetwork = b->networkName(); + currentBuffer = b->bufferId().groupId(); //emit bufferSelected(b); //qApp->processEvents(); ui.bufferWidget->setBuffer(b); @@ -253,44 +265,60 @@ void MainWin::showBuffer(Buffer *b) { void MainWin::networkConnected(QString net) { connected[net] = true; - Buffer *b = getBuffer(net, ""); + BufferId id = getStatusBufferId(net); + Buffer *b = getBuffer(id); b->setActive(true); - b->displayMsg(Message::server("", tr("Connected."))); + //b->displayMsg(Message(id, Message::Server, tr("Connected."))); FIXME // TODO buffersUpdated(); } void MainWin::networkDisconnected(QString net) { //getBuffer(net, "")->setActive(false); - foreach(QString buf, buffers[net].keys()) { - Buffer *b = getBuffer(net, buf); - b->displayMsg(Message::server(buf, tr("Server disconnected."))); + foreach(BufferId id, buffers.keys()) { + if(id.network() != net) continue; + Buffer *b = getBuffer(id); + //b->displayMsg(Message(id, Message::Server, tr("Server disconnected."))); FIXME b->setActive(false); - } connected[net] = false; } -Buffer * MainWin::getBuffer(QString net, QString buf) { - if(!buffers[net].contains(buf)) { - Buffer *b = new Buffer(net, buf); - b->setOwnNick(ownNick[net]); - connect(b, SIGNAL(userInput(QString, QString, QString)), this, SLOT(userInput(QString, QString, QString))); +BufferId MainWin::getBufferId(QString net, QString buf) { + foreach(BufferId id, buffers.keys()) { + if(id.network() == net && id.buffer() == buf) return id; + } + Q_ASSERT(false); + return BufferId(); +} + +BufferId MainWin::getStatusBufferId(QString net) { + return getBufferId(net, ""); +} + + +Buffer * MainWin::getBuffer(BufferId id) { + if(!buffers.contains(id)) { + Buffer *b = new Buffer(id); + b->setOwnNick(ownNick[id.network()]); + connect(b, SIGNAL(userInput(BufferId, QString)), this, SLOT(userInput(BufferId, QString))); connect(b, SIGNAL(bufferUpdated(Buffer *)), this, SIGNAL(bufferUpdated(Buffer *))); connect(b, SIGNAL(bufferDestroyed(Buffer *)), this, SIGNAL(bufferDestroyed(Buffer *))); - buffers[net][buf] = b; + buffers[id] = b; emit bufferUpdated(b); } - return buffers[net][buf]; + return buffers[id]; } void MainWin::recvNetworkState(QString net, QVariant state) { connected[net] = true; setOwnNick(net, state.toMap()["OwnNick"].toString()); - getBuffer(net, "")->setActive(true); + getBuffer(getStatusBufferId(net))->setActive(true); VarMap t = state.toMap()["Topics"].toMap(); VarMap n = state.toMap()["Nicks"].toMap(); - foreach(QString buf, t.keys()) { - getBuffer(net, buf)->setActive(true); + foreach(QVariant v, t.keys()) { + QString buf = v.toString(); + BufferId id = getBufferId(net, buf); + getBuffer(id)->setActive(true); setTopic(net, buf, t[buf].toString()); } foreach(QString nick, n.keys()) { @@ -298,7 +326,8 @@ void MainWin::recvNetworkState(QString net, QVariant state) { } } -void MainWin::recvMessage(QString net, Message msg) { +void MainWin::recvMessage(Message msg) { + /* Buffer *b; if(msg.flags & Message::PrivMsg) { // query @@ -307,21 +336,41 @@ void MainWin::recvMessage(QString net, Message msg) { } else { b = getBuffer(net, msg.target); } - b->displayMsg(msg); + */ + Buffer *b = getBuffer(msg.buffer); + //b->displayMsg(msg); + b->appendChatLine(new ChatLine(msg)); } void MainWin::recvStatusMsg(QString net, QString msg) { - recvMessage(net, Message::server("", QString("[STATUS] %1").arg(msg))); + //recvMessage(net, Message::server("", QString("[STATUS] %1").arg(msg))); + +} + +void MainWin::recvBacklogData(BufferId id, QList msgs, bool done) { + foreach(QVariant v, msgs) { + layoutQueue.append(v.value()); + } + if(!layoutTimer->isActive()) layoutTimer->start(); +} + +void MainWin::layoutMsg() { + if(layoutQueue.count()) { + ChatLine *line = new ChatLine(layoutQueue.takeFirst()); + getBuffer(line->bufferId())->prependChatLine(line); + } + if(!layoutQueue.count()) layoutTimer->stop(); } -void MainWin::userInput(QString net, QString buf, QString msg) { - emit sendInput(net, buf, msg); +void MainWin::userInput(BufferId id, QString msg) { + emit sendInput(id, msg); } void MainWin::setTopic(QString net, QString buf, QString topic) { - if(!connected[net]) return; - Buffer *b = getBuffer(net, buf); + BufferId id = getBufferId(net, buf); + if(!connected[id.network()]) return; + Buffer *b = getBuffer(id); b->setTopic(topic); //if(!b->isActive()) { // b->setActive(true); @@ -329,17 +378,13 @@ void MainWin::setTopic(QString net, QString buf, QString topic) { //} } -void MainWin::setNicks(QString net, QString buf, QStringList nicks) { - Q_ASSERT(false); -} - void MainWin::addNick(QString net, QString nick, VarMap props) { if(!connected[net]) return; nicks[net][nick] = props; VarMap chans = props["Channels"].toMap(); QStringList c = chans.keys(); foreach(QString bufname, c) { - getBuffer(net, bufname)->addNick(nick, props); + getBuffer(getBufferId(net, bufname))->addNick(nick, props); } } @@ -347,7 +392,7 @@ void MainWin::renameNick(QString net, QString oldnick, QString newnick) { if(!connected[net]) return; QStringList chans = nicks[net][oldnick]["Channels"].toMap().keys(); foreach(QString c, chans) { - getBuffer(net, c)->renameNick(oldnick, newnick); + getBuffer(getBufferId(net, c))->renameNick(oldnick, newnick); } nicks[net][newnick] = nicks[net].take(oldnick); } @@ -357,11 +402,11 @@ void MainWin::updateNick(QString net, QString nick, VarMap props) { QStringList oldchans = nicks[net][nick]["Channels"].toMap().keys(); QStringList newchans = props["Channels"].toMap().keys(); foreach(QString c, newchans) { - if(oldchans.contains(c)) getBuffer(net, c)->updateNick(nick, props); - else getBuffer(net, c)->addNick(nick, props); + if(oldchans.contains(c)) getBuffer(getBufferId(net, c))->updateNick(nick, props); + else getBuffer(getBufferId(net, c))->addNick(nick, props); } foreach(QString c, oldchans) { - if(!newchans.contains(c)) getBuffer(net, c)->removeNick(nick); + if(!newchans.contains(c)) getBuffer(getBufferId(net, c))->removeNick(nick); } nicks[net][nick] = props; } @@ -370,7 +415,7 @@ void MainWin::removeNick(QString net, QString nick) { if(!connected[net]) return; VarMap chans = nicks[net][nick]["Channels"].toMap(); foreach(QString bufname, chans.keys()) { - getBuffer(net, bufname)->removeNick(nick); + getBuffer(getBufferId(net, bufname))->removeNick(nick); } nicks[net].remove(nick); } @@ -378,8 +423,17 @@ void MainWin::removeNick(QString net, QString nick) { void MainWin::setOwnNick(QString net, QString nick) { if(!connected[net]) return; ownNick[net] = nick; - foreach(Buffer *b, buffers[net].values()) { - b->setOwnNick(nick); + foreach(BufferId id, buffers.keys()) { + if(id.network() == net) { + buffers[id]->setOwnNick(nick); + } } } +void MainWin::importBacklog() { + if(QMessageBox::warning(this, "Import old backlog?", "Do you want to import your old file-based backlog into new the backlog database?
" + "This will permanently delete the contents of your database!", + QMessageBox::Yes|QMessageBox::No) == QMessageBox::Yes) { + emit importOldBacklog(); + } +} diff --git a/gui/mainwin.h b/gui/mainwin.h index ff3596ec..0ce3c72b 100644 --- a/gui/mainwin.h +++ b/gui/mainwin.h @@ -56,33 +56,39 @@ class MainWin : public QMainWindow { void closeEvent(QCloseEvent *event); signals: - void sendInput(QString network, QString buffer, QString message); + void sendInput(BufferId, QString message); void bufferSelected(Buffer *); void bufferUpdated(Buffer *); void bufferDestroyed(Buffer *); void backlogReceived(Buffer *, QList); + void requestBacklog(BufferId, QVariant, QVariant); + + void importOldBacklog(); private slots: - void userInput(QString, QString, QString); + void userInput(BufferId, QString); void networkConnected(QString); void networkDisconnected(QString); void recvNetworkState(QString, QVariant); - void recvMessage(QString network, Message message); + void recvMessage(Message message); void recvStatusMsg(QString network, QString message); - void setTopic(QString, QString, QString); - void setNicks(QString, QString, QStringList); + void setTopic(QString net, QString buf, QString); void addNick(QString net, QString nick, VarMap props); void removeNick(QString net, QString nick); void renameNick(QString net, QString oldnick, QString newnick); void updateNick(QString net, QString nick, VarMap props); void setOwnNick(QString net, QString nick); + void recvBacklogData(BufferId, QList, bool); void showServerList(); void showSettingsDlg(); - void showBuffer(QString net, QString buf); + void showBuffer(BufferId); void showBuffer(Buffer *); + void importBacklog(); + void layoutMsg(); + private: Ui::MainWin ui; @@ -90,7 +96,10 @@ class MainWin : public QMainWindow { void setupViews(); void setupSettingsDlg(); void syncToCore(); // implemented in main_mono.cpp or main_gui.cpp - Buffer * getBuffer(QString net, QString buf); + //Buffer * getBuffer(QString net, QString buf); + Buffer *getBuffer(BufferId); + BufferId getStatusBufferId(QString net); + BufferId getBufferId(QString net, QString buf); //void buffersUpdated(); QSystemTrayIcon *systray; @@ -102,14 +111,21 @@ class MainWin : public QMainWindow { CoreConnectDlg *coreConnectDlg; SettingsDlg *settingsDlg; - QString currentNetwork, currentBuffer; - QHash > buffers; + //QString currentNetwork, currentBuffer; + //QHash > buffers; + uint currentBuffer; + QHash buffers; + QHash bufferIds; QHash > nicks; QHash connected; QHash ownNick; - QHash > coreBackLog; + //QHash > coreBackLog; + QList coreBuffers; QList netViews; + + QTimer *layoutTimer; + QList layoutQueue; }; #endif diff --git a/gui/ui/bufferwidget.ui b/gui/ui/bufferwidget.ui index 9cb2da08..777b0ea2 100644 --- a/gui/ui/bufferwidget.ui +++ b/gui/ui/bufferwidget.ui @@ -10,9 +10,7 @@ - - 7 - 7 + 5 0 @@ -30,20 +28,38 @@ YourNickname #quassel Network: The Topic - - 0 - 6 + + 0 + + + 0 + + + 0 + + + 0 + - - 0 - 6 + + 0 + + + 0 + + + 0 + + + 0 + @@ -63,9 +79,7 @@ Qt::NonModal - - 0 - 0 + 0 0 @@ -83,9 +97,7 @@ - - 7 - 5 + 0 0 @@ -95,12 +107,21 @@ - - 0 - 6 + + 0 + + + 0 + + + 0 + + + 0 + @@ -110,12 +131,21 @@ QFrame::Plain - - 9 - 6 + + 9 + + + 9 + + + 9 + + + 9 + @@ -127,13 +157,13 @@ <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Trebuchet MS'; font-size:11pt; font-weight:400; font-style:normal; text-decoration:none;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:60pt; color:#000055">Quassel IRC</span></p></body></html> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:60pt; color:#000055" align="center">Quassel IRC</span></p></body></html> true - Qt::AlignCenter + Qt::AlignCenter|Qt::AlignHorizontal_Mask|Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter|Qt::AlignVertical_Mask @@ -146,12 +176,21 @@ p, li { white-space: pre-wrap; } - - 0 - 6 + + 0 + + + 0 + + + 0 + + + 0 + @@ -162,9 +201,7 @@ p, li { white-space: pre-wrap; } - - 3 - 0 + 0 0 diff --git a/gui/ui/mainwin.ui b/gui/ui/mainwin.ui index 9e25be8d..ea93b308 100644 --- a/gui/ui/mainwin.ui +++ b/gui/ui/mainwin.ui @@ -14,20 +14,27 @@ - - 7 - 7 + 0 0 - - 9 - 6 + + 9 + + + 9 + + + 9 + + + 9 + @@ -82,10 +89,17 @@ + + + Debug + + + + @@ -172,6 +186,11 @@ About Quassel IRC... + + + Import Backlog + + diff --git a/main/global.cpp b/main/global.cpp index 4121806f..3317cfda 100644 --- a/main/global.cpp +++ b/main/global.cpp @@ -22,6 +22,7 @@ #include "logger.h" #include "core.h" #include "message.h" +#include "util.h" #include #include @@ -33,6 +34,9 @@ Global::Global() { qInstallMsgHandler(messageHandler); qRegisterMetaType("Message"); qRegisterMetaTypeStreamOperators("Message"); + qRegisterMetaType("BufferId"); + qRegisterMetaTypeStreamOperators("BufferId"); + //initIconMap(); } @@ -94,6 +98,35 @@ void Global::initIconMap() { */ } +/**************************************************************************************/ + + + +BufferId::BufferId(uint _id, QString _net, QString _buf, uint _gid) : id(_id), gid(_gid), net(_net), buf(_buf) { + + +} + +QString BufferId::buffer() { + if(isChannelName(buf)) return buf; + else return nickFromMask(buf); +} + +QDataStream &operator<<(QDataStream &out, const BufferId &bufferId) { + out << bufferId.id << bufferId.gid << bufferId.net.toUtf8() << bufferId.buf.toUtf8(); +} + +QDataStream &operator>>(QDataStream &in, BufferId &bufferId) { + QByteArray n, b; + BufferId i; + in >> bufferId.id >> bufferId.gid >> n >> b; + bufferId.net = QString::fromUtf8(n); + bufferId.buf = QString::fromUtf8(b); +} + +uint qHash(const BufferId &bid) { + return qHash(bid.id); +} /** * Retrieves an icon determined by its symbolic name. The mapping shall later diff --git a/main/global.h b/main/global.h index 1c366611..8787eea3 100644 --- a/main/global.h +++ b/main/global.h @@ -93,4 +93,35 @@ class Exception { }; +class BufferId { + public: + BufferId() { id = gid = 0; } // FIXME + BufferId(uint uid, QString net, QString buf, uint gid = 0); + + inline uint uid() { return id; } + inline uint groupId() { return gid; } + inline QString network() { return net; } + QString buffer(); // nickfrommask? + + void setGroupId(uint _gid) { gid = _gid; } + + inline bool operator==(const BufferId &other) const { return id == other.id; } + private: + uint id; + uint gid; + QString net; + QString buf; + + friend uint qHash(const BufferId &); + friend QDataStream &operator<<(QDataStream &out, const BufferId &bufferId); + friend QDataStream &operator>>(QDataStream &in, BufferId &bufferId); +}; + +QDataStream &operator<<(QDataStream &out, const BufferId &bufferId); +QDataStream &operator>>(QDataStream &in, BufferId &bufferId); + +Q_DECLARE_METATYPE(BufferId); + +uint qHash(const BufferId &); + #endif diff --git a/main/main_gui.cpp b/main/main_gui.cpp index 2d9c4e78..f48f615c 100644 --- a/main/main_gui.cpp +++ b/main/main_gui.cpp @@ -38,8 +38,6 @@ int main(int argc, char **argv) { QApplication::setApplicationName("Quassel IRC"); QApplication::setOrganizationName("The Quassel Team"); - qRegisterMetaType("LayoutTask"); - Global::runMode = Global::GUIOnly; Global::quasselDir = QDir::homePath() + "/.quassel"; @@ -76,6 +74,7 @@ void MainWin::syncToCore() { //qApp->quit(); exit(1); } + /* foreach(QString net, state["CoreBackLog"].toMap().keys()) { QByteArray logbuf = state["CoreBackLog"].toMap()[net].toByteArray(); QDataStream in(&logbuf, QIODevice::ReadOnly); in.setVersion(QDataStream::Qt_4_2); @@ -85,6 +84,9 @@ void MainWin::syncToCore() { } qDebug() << net << coreBackLog[net].count(); } + */ + coreBuffers.clear(); + foreach(QVariant v, state["CoreBuffers"].toList()) { coreBuffers.append(v.value()); } } GUIProxy::GUIProxy() { diff --git a/main/main_mono.cpp b/main/main_mono.cpp index 584c2207..87360c63 100644 --- a/main/main_mono.cpp +++ b/main/main_mono.cpp @@ -38,8 +38,6 @@ int main(int argc, char **argv) { QApplication::setApplicationName("Quassel IRC"); QApplication::setOrganizationName("The Quassel Team"); - qRegisterMetaType("LayoutTask"); - Global::runMode = Global::Monolithic; Global::quasselDir = QDir::homePath() + "/.quassel"; @@ -66,7 +64,7 @@ int main(int argc, char **argv) { void MainWin::syncToCore() { Q_ASSERT(global->getData("CoreReady").toBool()); - coreBackLog = core->getBackLog(); + coreBuffers = core->getBuffers(); // NOTE: We don't need to request server states, because in the monolithic version there can't be // any servers connected at this stage... } diff --git a/main/message.cpp b/main/message.cpp index 6d1e7a8a..e564b84f 100644 --- a/main/message.cpp +++ b/main/message.cpp @@ -21,6 +21,7 @@ #include "message.h" #include +/* Message Message::plain(QString _target, QString _text, QString _sender, quint8 _flags) { return Message(_target, Plain, _text, _sender, _flags); } @@ -72,10 +73,15 @@ Message Message::info(QString _target, QString _text, QString _sender, quint8 _f Message Message::error(QString _target, QString _text, QString _sender, quint8 _flags) { return Message(_target, Error, _text, _sender, _flags); } +*/ QDataStream &operator<<(QDataStream &out, const Message &msg) { + /* out << (quint32)msg.timeStamp.toTime_t() << (quint8)msg.type << (quint8)msg.flags << msg.target.toUtf8() << msg.sender.toUtf8() << msg.text.toUtf8(); + */ + out << (quint32)msg.timeStamp.toTime_t() << (quint8)msg.type << (quint8)msg.flags + << msg.buffer << msg.sender.toUtf8() << msg.text.toUtf8(); return out; } @@ -83,11 +89,12 @@ QDataStream &operator>>(QDataStream &in, Message &msg) { quint8 t, f; quint32 ts; QByteArray s, m, targ; - in >> ts >> t >> f >> targ >> s >> m; + BufferId buf; + in >> ts >> t >> f >> buf >> s >> m; msg.type = (Message::Type)t; msg.flags = (quint8)f; msg.timeStamp = QDateTime::fromTime_t(ts); - msg.target = QString::fromUtf8(targ); + //msg.target = QString::fromUtf8(targ); msg.sender = QString::fromUtf8(s); msg.text = QString::fromUtf8(m); return in; diff --git a/main/message.h b/main/message.h index 2426a0c8..8ce0cfef 100644 --- a/main/message.h +++ b/main/message.h @@ -22,6 +22,7 @@ #define _MESSAGE_H_ #include +#include "global.h" struct Message { @@ -29,16 +30,25 @@ struct Message { enum Type { Plain, Notice, Action, Nick, Mode, Join, Part, Quit, Kick, Kill, Server, Info, Error }; enum Flags { None = 0, Self = 1, PrivMsg = 2, Highlight = 4 }; + uint msgId; Type type; quint8 flags; QString target; QString sender; QString text; QDateTime timeStamp; + BufferId buffer; - Message(QString _target = "", Type _type = Plain, QString _text = "", QString _sender = "", quint8 _flags = None) + Message(QString _target, Type _type = Plain, QString _text = "", QString _sender = "", quint8 _flags = None) : target(_target), text(_text), sender(_sender), type(_type), flags(_flags) { timeStamp = QDateTime::currentDateTime().toUTC(); } + Message(BufferId _buffer = BufferId(), Type _type = Plain, QString _text = "", QString _sender = "", quint8 _flags = None) + : buffer(_buffer), text(_text), sender(_sender), type(_type), flags(_flags) { timeStamp = QDateTime::currentDateTime().toUTC(); } + + Message(QDateTime _ts, BufferId _buffer = BufferId(), Type _type = Plain, QString _text = "", QString _sender = "", quint8 _flags = None) + : timeStamp(_ts), buffer(_buffer), text(_text), sender(_sender), type(_type), flags(_flags) {} + +/* static Message plain(QString _target, QString _text, QString _sender = "", quint8 _flags = None); static Message notice(QString _target, QString _text, QString _sender = "", quint8 _flags = None); static Message action(QString _target, QString _text, QString _sender = "", quint8 _flags = None); @@ -52,6 +62,7 @@ struct Message { static Message server(QString _target, QString _text, QString _sender = "", quint8 _flags = None); static Message info(QString _target, QString _text, QString _sender = "", quint8 _flags = None); static Message error(QString _target, QString _text, QString _sender = "", quint8 _flags = None); +*/ }; QDataStream &operator<<(QDataStream &out, const Message &msg); diff --git a/main/proxy_common.h b/main/proxy_common.h index 8ca9afb2..ab2b7d37 100644 --- a/main/proxy_common.h +++ b/main/proxy_common.h @@ -21,14 +21,15 @@ #ifndef _PROXY_COMMON_H_ #define _PROXY_COMMON_H_ -enum GUISignal { GS_CLIENT_INIT, GS_USER_INPUT, GS_REQUEST_CONNECT, GS_UPDATE_GLOBAL_DATA, +enum GUISignal { GS_CLIENT_INIT, GS_USER_INPUT, GS_REQUEST_CONNECT, GS_UPDATE_GLOBAL_DATA, GS_IMPORT_BACKLOG, + GS_REQUEST_BACKLOG }; enum CoreSignal { CS_CORE_STATE, CS_SERVER_CONNECTED, CS_SERVER_DISCONNECTED, CS_SERVER_STATE, CS_DISPLAY_MSG, CS_DISPLAY_STATUS_MSG, CS_UPDATE_GLOBAL_DATA, CS_MODE_SET, CS_TOPIC_SET, CS_SET_NICKS, CS_NICK_ADDED, CS_NICK_REMOVED, CS_NICK_RENAMED, CS_NICK_UPDATED, - CS_OWN_NICK_SET, CS_QUERY_REQUESTED + CS_OWN_NICK_SET, CS_QUERY_REQUESTED, CS_BACKLOG_DATA };