QT4_WRAP_CPP(_MOC ${client_MOCS})
ADD_LIBRARY(client ${client_SRCS} ${_MOC})
-TARGET_LINK_LIBRARIES(client common)
\ No newline at end of file
+TARGET_LINK_LIBRARIES(client common)
#include "util.h"
-Buffer::Buffer(BufferId bufid) {
- id = bufid;
- _networkName = bufid.network();
- _bufferName = bufid.buffer();
-
- if(_bufferName.isEmpty()) type = ServerBuffer;
- else if(isChannelName(_bufferName)) type = ChannelBuffer;
- else type = QueryBuffer;
+Buffer::Buffer(BufferInfo bufferid, QObject *parent)
+ : QObject(parent),
+ _bufferInfo(bufferid),
+ _active(false)
+{
+ if(bufferid.buffer().isEmpty())
+ _type = ServerBuffer;
+ else if(isChannelName(bufferid.buffer()))
+ _type = ChannelBuffer;
+ else
+ _type = QueryBuffer;
- active = false;
/*
QSettings s;
s.beginGroup(QString("GUI/BufferStates/%1/%2").arg(netname).arg(bufname));
}
Buffer::Type Buffer::bufferType() const {
- return type;
+ return _type;
}
bool Buffer::isActive() const {
- return active;
+ // FIXME determine status by checking for a networkInfo objekt
+ return true;
+}
+
+BufferInfo Buffer::bufferInfo() const {
+ return _bufferInfo;
+}
+
+void Buffer::updateBufferInfo(BufferInfo bufferid) {
+ _bufferInfo = bufferid;
+}
+
+uint Buffer::networkId() const {
+ return bufferInfo().networkId();
}
QString Buffer::networkName() const {
- return _networkName;
+ return bufferInfo().network();
}
QString Buffer::bufferName() const {
- return _bufferName;
+ return bufferInfo().buffer();
}
QString Buffer::displayName() const {
return bufferName();
}
-BufferId Buffer::bufferId() const {
- return id;
-}
-
QList<AbstractUiMsg *> Buffer::contents() const {
- return layoutedMsgs;
+ return layoutedMsgs;
}
QVariantMap Buffer::nickList() const {
- return nicks;
+ // FIXME should return a Map or List of IrcUsers in the future
+ return QVariantMap();
}
QString Buffer::topic() const {
- return _topic;
+ // FIXME check if we got a networkInfo() object
+ return QString();
}
QString Buffer::ownNick() const {
- return _ownNick;
+ // FIXME check if we got a networkInfo() object
+ return QString();
}
bool Buffer::isStatusBuffer() const {
}
void Buffer::setActive(bool a) {
- if(a != active) {
- active = a;
- emit bufferUpdated(this);
- }
+// if(a != active) {
+// active = a;
+// emit bufferUpdated(this);
+// }
}
void Buffer::appendMsg(const Message &msg) {
void Buffer::processUserInput(QString msg) {
// TODO User Input processing (plugins) -> well, this goes through MainWin into Core for processing... so...
- emit userInput(id, msg);
-}
-
-void Buffer::setTopic(QString t) {
- _topic = t;
- emit topicSet(t);
- emit bufferUpdated(this);
-}
-
-void Buffer::addNick(QString nick, QVariantMap props) {
- if(nick == ownNick()) setActive(true);
- nicks[nick] = props;
- emit nickListChanged(nicks);
-}
-
-void Buffer::updateNick(QString nick, QVariantMap props) {
- nicks[nick] = props;
- emit nickListChanged(nicks);
-}
-
-void Buffer::renameNick(QString oldnick, QString newnick) {
- QVariant v = nicks.take(oldnick);
- nicks[newnick] = v;
- emit nickListChanged(nicks);
-}
-
-void Buffer::removeNick(QString nick) {
- if(nick == ownNick()) setActive(false);
- nicks.remove(nick);
- emit nickListChanged(nicks);
-}
-
-void Buffer::setOwnNick(QString nick) {
- _ownNick = nick;
- emit ownNickSet(nick);
-}
+ emit userInput(_bufferInfo, msg);
+}
+
+// no longer needed
+// back reference:
+// void Buffer::setTopic(QString t) {
+// _topic = t;
+// emit topicSet(t);
+// emit bufferUpdated(this);
+// }
+
+// void Buffer::addNick(QString nick, QVariantMap props) {
+// if(nick == ownNick()) setActive(true);
+// nicks[nick] = props;
+// emit nickListChanged(nicks);
+// }
+
+// void Buffer::updateNick(QString nick, QVariantMap props) {
+// nicks[nick] = props;
+// emit nickListChanged(nicks);
+// }
+
+// void Buffer::renameNick(QString oldnick, QString newnick) {
+// QVariant v = nicks.take(oldnick);
+// nicks[newnick] = v;
+// emit nickListChanged(nicks);
+// }
+
+// void Buffer::removeNick(QString nick) {
+// if(nick == ownNick()) setActive(false);
+// nicks.remove(nick);
+// emit nickListChanged(nicks);
+// }
+
+// void Buffer::setOwnNick(QString nick) {
+// _ownNick = nick;
+// emit ownNickSet(nick);
+// }
#ifndef _BUFFER_H_
#define _BUFFER_H_
-#include "global.h"
-
class AbstractUiMsg;
-class Message;
+
struct BufferState;
+#include "message.h"
+#include "bufferinfo.h"
+
+#include <QVariantMap>
+
//!\brief Encapsulates the contents of a single channel, query or server status context.
/** A Buffer maintains a list of existing nicks and their status.
*/
class Buffer : public QObject {
Q_OBJECT
- public:
- Buffer(BufferId);
- ~Buffer();
-
- enum Type { ServerBuffer, ChannelBuffer, QueryBuffer };
-
- enum Activity {
- NoActivity = 0x00,
- OtherActivity = 0x01,
- NewMessage = 0x02,
- Highlight = 0x40
- };
- Q_DECLARE_FLAGS(ActivityLevel, Activity);
-
- Type bufferType() const;
- bool isActive() const;
-
- QString networkName() const;
- QString bufferName() const;
- QString displayName() const;
- BufferId bufferId() const;
- QList<AbstractUiMsg *> contents() const;
- QVariantMap nickList() const;
- QString topic() const;
- QString ownNick() const;
- bool isStatusBuffer() const;
-
- signals:
- void userInput(const BufferId &, QString);
- void nickListChanged(QVariantMap nicks);
- void topicSet(QString topic);
- void ownNickSet(QString ownNick);
- void bufferUpdated(Buffer *);
- void bufferDestroyed(Buffer *);
-
- void msgAppended(AbstractUiMsg *);
- void msgPrepended(AbstractUiMsg *);
- void layoutQueueEmpty();
-
- public slots:
- void setActive(bool active = true);
- void appendMsg(const Message &);
- void prependMsg(const Message &);
- bool layoutMsg();
- void setTopic(QString);
- //void setNicks(QStringList);
- void addNick(QString nick, QVariantMap props);
- void renameNick(QString oldnick, QString newnick);
- void removeNick(QString nick);
- void updateNick(QString nick, QVariantMap props);
- void setOwnNick(QString nick);
-
- void processUserInput(QString);
-
- private:
- BufferId id;
- bool active;
- Type type;
-
- QVariantMap nicks;
- QString _topic;
- QString _ownNick;
- QString _networkName, _bufferName;
- BufferState *state;
-
- QList<Message> layoutQueue;
- QList<AbstractUiMsg *> layoutedMsgs;
+public:
+ Buffer(BufferInfo, QObject *parent = 0);
+ ~Buffer();
+
+ enum Type {
+ ServerBuffer,
+ ChannelBuffer,
+ QueryBuffer
+ };
+
+ enum Activity {
+ NoActivity = 0x00,
+ OtherActivity = 0x01,
+ NewMessage = 0x02,
+ Highlight = 0x40
+ };
+ Q_DECLARE_FLAGS(ActivityLevel, Activity)
+
+ bool isStatusBuffer() const;
+ Type bufferType() const;
+ bool isActive() const;
+
+ BufferInfo bufferInfo() const;
+ void updateBufferInfo(BufferInfo bufferid);
+
+ uint networkId() const;
+
+ QString networkName() const;
+ QString bufferName() const;
+ QString displayName() const;
+
+ QList<AbstractUiMsg *> contents() const;
+
+ QVariantMap nickList() const;
+ QString topic() const;
+ QString ownNick() const;
+
+signals:
+ void userInput(const BufferInfo &, QString);
+ void nickListChanged(QVariantMap nicks);
+ void topicSet(QString topic);
+ void ownNickSet(QString ownNick);
+ void bufferUpdated(Buffer *);
+ void bufferDestroyed(Buffer *);
+
+ void msgAppended(AbstractUiMsg *);
+ void msgPrepended(AbstractUiMsg *);
+ void layoutQueueEmpty();
+
+public slots:
+ void setActive(bool active = true);
+ void appendMsg(const Message &);
+ void prependMsg(const Message &);
+ bool layoutMsg();
+
+ // no longer needed
+// void setTopic(QString);
+// //void setNicks(QStringList);
+// void addNick(QString nick, QVariantMap props);
+// void renameNick(QString oldnick, QString newnick);
+// void removeNick(QString nick);
+// void updateNick(QString nick, QVariantMap props);
+// void setOwnNick(QString nick);
+
+ void processUserInput(QString);
+
+private:
+ BufferInfo _bufferInfo;
+ bool _active;
+ Type _type;
+ BufferState *state;
+
+ QList<Message> layoutQueue;
+ QList<AbstractUiMsg *> layoutedMsgs;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(Buffer::ActivityLevel)
#include <QColor> // FIXME Dependency on QtGui!
-#include "client.h"
#include "buffertreemodel.h"
+
+#include "bufferinfo.h"
+#include "client.h"
#include "signalproxy.h"
/*****************************************
}
uint BufferTreeItem::id() const {
- return buf->bufferId().uid();
+ return buf->bufferInfo().uid();
}
void BufferTreeItem::setActivity(const Buffer::ActivityLevel &level) {
return buf->bufferType();
case BufferTreeModel::BufferActiveRole:
return buf->isActive();
- case BufferTreeModel::BufferIdRole:
- return buf->bufferId().uid();
+ case BufferTreeModel::BufferInfoRole:
+ return buf->bufferInfo().uid();
default:
return QVariant();
}
BufferTreeModel::BufferTreeModel(QObject *parent)
: TreeModel(BufferTreeModel::defaultHeader(), parent)
{
- Client::signalProxy()->attachSignal(this, SIGNAL(fakeUserInput(BufferId, QString)), SIGNAL(sendInput(BufferId, QString)));
+ Client::signalProxy()->attachSignal(this, SIGNAL(fakeUserInput(BufferInfo, QString)), SIGNAL(sendInput(BufferInfo, QString)));
}
QList<QVariant >BufferTreeModel::defaultHeader() {
NetworkTreeItem *networkItem = static_cast<NetworkTreeItem*>(networkItemIndex.internalPointer());
TreeItem *bufferItem;
- if(not(bufferItem = networkItem->childById(buffer->bufferId().uid()))) {
+ if(not(bufferItem = networkItem->childById(buffer->bufferInfo().uid()))) {
int nextRow = networkItem->childCount();
bufferItem = new BufferTreeItem(buffer, networkItem);
QStringList types;
types << "application/Quassel/BufferItem/row"
<< "application/Quassel/BufferItem/network"
- << "application/Quassel/BufferItem/bufferId";
+ << "application/Quassel/BufferItem/bufferInfo";
return types;
}
mimeData->setData("application/Quassel/BufferItem/row", QByteArray::number(index.row()));
mimeData->setData("application/Quassel/BufferItem/network", getBufferByIndex(index)->networkName().toUtf8());
- mimeData->setData("application/Quassel/BufferItem/bufferId", QByteArray::number(getBufferByIndex(index)->bufferId().uid()));
+ mimeData->setData("application/Quassel/BufferItem/bufferInfo", QByteArray::number(getBufferByIndex(index)->bufferInfo().uid()));
return mimeData;
}
if(isBufferIndex(clicked)) {
Buffer *buffer = getBufferByIndex(clicked);
if(!buffer->isStatusBuffer())
- emit fakeUserInput(buffer->bufferId(), QString("/join " + buffer->bufferName()));
+ emit fakeUserInput(buffer->bufferInfo(), QString("/join " + buffer->bufferName()));
}
}
#include <QtCore>
#include "treemodel.h"
+class BufferInfo;
#include "buffer.h"
/*****************************************
BufferTypeRole = Qt::UserRole,
BufferActiveRole,
BufferNameRole,
- BufferIdRole
+ BufferInfoRole
};
BufferTreeModel(QObject *parent = 0);
signals:
void bufferSelected(Buffer *);
void invalidateFilter();
- void fakeUserInput(BufferId, QString);
+ void fakeUserInput(BufferInfo, QString);
void selectionChanged(const QModelIndex &);
private:
#include "client.h"
-#include "buffer.h"
+#include "networkinfo.h"
+#include "ircuser.h"
+#include "ircchannel.h"
+
+#include "message.h"
+
+#include "bufferinfo.h"
#include "buffertreemodel.h"
#include "quasselui.h"
#include "signalproxy.h"
+#include "synchronizer.h"
#include "util.h"
-Client * Client::instanceptr = 0;
-
-bool Client::connectedToCore = false;
-Client::ClientMode Client::clientMode;
-QVariantMap Client::coreConnectionInfo;
-QHash<BufferId, Buffer *> Client::buffers;
-QHash<uint, BufferId> Client::bufferIds;
-QHash<QString, QHash<QString, QVariantMap> > Client::nicks;
-QHash<QString, bool> Client::netConnected;
-QStringList Client::netsAwaitingInit;
-QHash<QString, QString> Client::ownNick;
+QPointer<Client> Client::instanceptr = 0;
+// ==============================
+// public Static Methods
+// ==============================
Client *Client::instance() {
- if(instanceptr) return instanceptr;
- instanceptr = new Client();
+ if(!instanceptr)
+ instanceptr = new Client();
return instanceptr;
}
void Client::destroy() {
delete instanceptr;
- instanceptr = 0;
-}
-
-Client::Client() {
- _signalProxy = new SignalProxy(SignalProxy::Client, 0, this);
-
- connectedToCore = false;
- socket = 0;
}
void Client::init(AbstractUi *ui) {
instance()->init();
}
+QList<NetworkInfo *> Client::networkInfos() {
+ return instance()->_networkInfo.values();
+}
+
+NetworkInfo *Client::networkInfo(uint networkid) {
+ if(instance()->_networkInfo.contains(networkid))
+ return instance()->_networkInfo[networkid];
+ else
+ return 0;
+}
+
+QList<BufferInfo> Client::allBufferInfos() {
+ QList<BufferInfo> bufferids;
+ foreach(Buffer *buffer, buffers()) {
+ bufferids << buffer->bufferInfo();
+ }
+ return bufferids;
+}
+
+QList<Buffer *> Client::buffers() {
+ return instance()->_buffers.values();
+}
+
+Buffer *Client::buffer(uint bufferUid) {
+ if(instance()->_buffers.contains(bufferUid))
+ return instance()->_buffers[bufferUid];
+ else
+ return 0;
+}
+
+Buffer *Client::buffer(BufferInfo id) {
+ Buffer *buff = buffer(id.uid());
+
+ if(!buff) {
+ Client *client = Client::instance();
+ Buffer *buff = new Buffer(id, client);
+
+ connect(buff, SIGNAL(userInput(BufferInfo, QString)),
+ client, SLOT(userInput(BufferInfo, QString)));
+ connect(buff, SIGNAL(bufferUpdated(Buffer *)),
+ client, SIGNAL(bufferUpdated(Buffer *)));
+ connect(buff, SIGNAL(bufferDestroyed(Buffer *)),
+ client, SIGNAL(bufferDestroyed(Buffer *)));
+ connect(buff, SIGNAL(bufferDestroyed(Buffer *)),
+ client, SLOT(removeBuffer(Buffer *)));
+
+ client->_buffers[id.uid()] = buff;
+ emit client->bufferUpdated(buff);
+ }
+
+ return buff;
+}
+
+// FIXME switch to netids!
+// WHEN IS THIS NEEDED ANYHOW!?
+BufferInfo Client::bufferInfo(QString net, QString buf) {
+ foreach(Buffer *buffer_, buffers()) {
+ BufferInfo bufferInfo = buffer_->bufferInfo();
+ if(bufferInfo.network() == net && bufferInfo.buffer() == buf)
+ return bufferInfo;
+ }
+ Q_ASSERT(false); // should never happen!
+ return BufferInfo();
+}
+
+BufferInfo Client::statusBufferInfo(QString net) {
+ return bufferInfo(net, "");
+}
+
+BufferTreeModel *Client::bufferModel() {
+ return instance()->_bufferModel;
+}
+
+SignalProxy *Client::signalProxy() {
+ return instance()->_signalProxy;
+}
+
+// ==============================
+// Constructor / Decon
+// ==============================
+Client::Client(QObject *parent)
+ : QObject(parent),
+ socket(0),
+ _signalProxy(new SignalProxy(SignalProxy::Client, 0, this)),
+ mainUi(0),
+ _bufferModel(0),
+ connectedToCore(false)
+{
+}
+
+Client::~Client() {
+// since we're now the parent of buffers this should be no longer needed
+
+// foreach(Buffer *buf, buffers.values()) delete buf; // this is done by disconnectFromCore()! FIXME?
+// Q_ASSERT(!buffers.count());
+}
+
void Client::init() {
blockSize = 0;
_bufferModel = new BufferTreeModel(this);
- connect(this, SIGNAL(bufferSelected(Buffer *)), _bufferModel, SLOT(selectBuffer(Buffer *)));
- connect(this, SIGNAL(bufferUpdated(Buffer *)), _bufferModel, SLOT(bufferUpdated(Buffer *)));
- connect(this, SIGNAL(bufferActivity(Buffer::ActivityLevel, Buffer *)), _bufferModel, SLOT(bufferActivity(Buffer::ActivityLevel, Buffer *)));
+ connect(this, SIGNAL(bufferSelected(Buffer *)),
+ _bufferModel, SLOT(selectBuffer(Buffer *)));
+ connect(this, SIGNAL(bufferUpdated(Buffer *)),
+ _bufferModel, SLOT(bufferUpdated(Buffer *)));
+ connect(this, SIGNAL(bufferActivity(Buffer::ActivityLevel, Buffer *)),
+ _bufferModel, SLOT(bufferActivity(Buffer::ActivityLevel, Buffer *)));
SignalProxy *p = signalProxy();
- p->attachSignal(this, SIGNAL(sendSessionData(const QString &, const QVariant &)), SIGNAL(clientSessionDataChanged(const QString &, const QVariant &)));
- p->attachSlot(SIGNAL(coreSessionDataChanged(const QString &, const QVariant &)), this, SLOT(recvSessionData(const QString &, const QVariant &)));
- p->attachSlot(SIGNAL(coreState(const QVariant &)), this, SLOT(recvCoreState(const QVariant &)));
- p->attachSlot(SIGNAL(networkState(QString, QVariant)), this, SLOT(recvNetworkState(QString, QVariant)));
- p->attachSlot(SIGNAL(networkConnected(QString)), this, SLOT(networkConnected(QString)));
- p->attachSlot(SIGNAL(networkDisconnected(QString)), this, SLOT(networkDisconnected(QString)));
- p->attachSlot(SIGNAL(displayMsg(const Message &)), this, SLOT(recvMessage(const Message &)));
- p->attachSlot(SIGNAL(displayStatusMsg(QString, QString)), this, SLOT(recvStatusMsg(QString, QString)));
- p->attachSlot(SIGNAL(topicSet(QString, QString, QString)), this, SLOT(setTopic(QString, QString, QString)));
- p->attachSlot(SIGNAL(nickAdded(QString, QString, QVariantMap)), this, SLOT(addNick(QString, QString, QVariantMap)));
- p->attachSlot(SIGNAL(nickRemoved(QString, QString)), this, SLOT(removeNick(QString, QString)));
- p->attachSlot(SIGNAL(nickRenamed(QString, QString, QString)), this, SLOT(renameNick(QString, QString, QString)));
- p->attachSlot(SIGNAL(nickUpdated(QString, QString, QVariantMap)), this, SLOT(updateNick(QString, QString, QVariantMap)));
- p->attachSlot(SIGNAL(ownNickSet(QString, QString)), this, SLOT(setOwnNick(QString, QString)));
- p->attachSlot(SIGNAL(backlogData(BufferId, const QVariantList &, bool)), this, SLOT(recvBacklogData(BufferId, const QVariantList &, bool)));
- p->attachSlot(SIGNAL(bufferIdUpdated(BufferId)), this, SLOT(updateBufferId(BufferId)));
- p->attachSignal(this, SIGNAL(sendInput(BufferId, QString)));
+ p->attachSignal(this, SIGNAL(sendSessionData(const QString &, const QVariant &)),
+ SIGNAL(clientSessionDataChanged(const QString &, const QVariant &)));
+ p->attachSlot(SIGNAL(coreSessionDataChanged(const QString &, const QVariant &)),
+ this, SLOT(recvSessionData(const QString &, const QVariant &)));
+ p->attachSlot(SIGNAL(coreState(const QVariant &)),
+ this, SLOT(recvCoreState(const QVariant &)));
+ p->attachSlot(SIGNAL(networkConnected(uint)),
+ this, SLOT(networkConnected(uint)));
+ p->attachSlot(SIGNAL(networkDisconnected(uint)),
+ this, SLOT(networkDisconnected(uint)));
+ p->attachSlot(SIGNAL(displayMsg(const Message &)),
+ this, SLOT(recvMessage(const Message &)));
+ p->attachSlot(SIGNAL(displayStatusMsg(QString, QString)),
+ this, SLOT(recvStatusMsg(QString, QString)));
+
+
+ p->attachSlot(SIGNAL(backlogData(BufferInfo, const QVariantList &, bool)), this, SLOT(recvBacklogData(BufferInfo, const QVariantList &, bool)));
+ p->attachSlot(SIGNAL(bufferInfoUpdated(BufferInfo)), this, SLOT(updateBufferInfo(BufferInfo)));
+ p->attachSignal(this, SIGNAL(sendInput(BufferInfo, QString)));
p->attachSignal(this, SIGNAL(requestNetworkStates()));
connect(mainUi, SIGNAL(connectToCore(const QVariantMap &)), this, SLOT(connectToCore(const QVariantMap &)));
layoutTimer->setInterval(0);
layoutTimer->setSingleShot(false);
connect(layoutTimer, SIGNAL(timeout()), this, SLOT(layoutMsg()));
-}
-
-Client::~Client() {
- foreach(Buffer *buf, buffers.values()) delete buf; // this is done by disconnectFromCore()! FIXME?
- Q_ASSERT(!buffers.count());
-}
-
-BufferTreeModel *Client::bufferModel() {
- return instance()->_bufferModel;
-}
-SignalProxy *Client::signalProxy() {
- return instance()->_signalProxy;
}
bool Client::isConnected() {
- return connectedToCore;
+ return instance()->connectedToCore;
}
void Client::connectToCore(const QVariantMap &conn) {
// TODO implement SSL
coreConnectionInfo = conn;
+
if(isConnected()) {
emit coreConnectionError(tr("Already connected to Core!"));
return;
}
- if(socket != 0) socket->deleteLater();
+
+ if(socket != 0)
+ socket->deleteLater();
+
if(conn["Host"].toString().isEmpty()) {
clientMode = LocalCore;
socket = new QBuffer(this);
}
void Client::coreSocketDisconnected() {
- connectedToCore = false;
+ instance()->connectedToCore = false;
emit disconnected();
socket->deleteLater();
blockSize = 0;
/* Clear internal data. Hopefully nothing relies on it at this point. */
_bufferModel->clear();
- // Buffers, if deleted, send a signal that causes their removal from buffers and bufferIds.
+ // Buffers, if deleted, send a signal that causes their removal from buffers and bufferInfos.
// So we cannot simply go through the array in a loop (or use qDeleteAll) for deletion...
- while(buffers.count()) { delete buffers.take(buffers.keys()[0]); }
- Q_ASSERT(!buffers.count()); // should be empty now!
- Q_ASSERT(!bufferIds.count());
+ while(!_buffers.empty()) {
+ delete _buffers.take(_buffers.keys()[0]);
+ }
+ Q_ASSERT(_buffers.empty());
+
+ while(!_networkInfo.empty()) {
+ delete _networkInfo.take(_networkInfo.keys()[0]);
+ }
+
coreConnectionInfo.clear();
sessionData.clear();
- nicks.clear();
- netConnected.clear();
- netsAwaitingInit.clear();
- ownNick.clear();
layoutQueue.clear();
layoutTimer->stop();
}
disconnectFromCore();
return;
}
+
QVariantMap sessionState = coreState.toMap()["SessionState"].toMap();
- QVariantMap sessData = sessionState["SessionData"].toMap();
- foreach(QString key, sessData.keys()) {
+ // store sessionData
+ QVariantMap sessData = sessionState["SessionData"].toMap();
+ foreach(QString key, sessData.keys())
recvSessionData(key, sessData[key]);
- }
- QList<QVariant> coreBuffers = sessionState["Buffers"].toList();
+
+ // store Buffer details
+ QVariantList coreBuffers = sessionState["Buffers"].toList();
/* make lookups by id faster */
foreach(QVariant vid, coreBuffers) {
- BufferId id = vid.value<BufferId>();
- bufferIds[id.uid()] = id; // make lookups by id faster
- buffer(id); // create all buffers, so we see them in the network views
+ buffer(vid.value<BufferInfo>()); // create all buffers, so we see them in the network views
+ }
+
+ // create networkInfo objects
+ QVariantList networkids = sessionState["Networks"].toList();
+ foreach(QVariant networkid, networkids) {
+ networkConnected(networkid.toUInt());
}
- netsAwaitingInit = sessionState["Networks"].toStringList();
- connectedToCore = true;
- if(netsAwaitingInit.count()) {
+
+ instance()->connectedToCore = true;
+ updateCoreConnectionProgress();
+}
+
+void Client::updateCoreConnectionProgress() {
+ // we'll do this in three steps:
+ // 1.) networks
+ // 2.) channels
+ // 3.) ircusers
+
+ int numNets = networkInfos().count();
+ int numNetsWaiting = 0;
+
+ int numIrcUsers = 0;
+ int numIrcUsersWaiting = 0;
+
+ int numChannels = 0;
+ int numChannelsWaiting = 0;
+
+ foreach(NetworkInfo *net, networkInfos()) {
+ if(not net->initialized())
+ numNetsWaiting++;
+
+ numIrcUsers += net->ircUsers().count();
+ foreach(IrcUser *user, net->ircUsers()) {
+ if(not user->initialized())
+ numIrcUsersWaiting++;
+ }
+
+ numChannels += net->ircChannels().count();
+ foreach(IrcChannel *channel, net->ircChannels()) {
+ if(not channel->initialized())
+ numChannelsWaiting++;
+ }
+
+ }
+
+ if(numNetsWaiting > 0) {
emit coreConnectionMsg(tr("Requesting network states..."));
- emit coreConnectionProgress(0, netsAwaitingInit.count());
- emit requestNetworkStates();
+ emit coreConnectionProgress(numNets - numNetsWaiting, numNets);
+ return;
}
- else {
- emit coreConnectionProgress(1, 1);
- emit connected();
+
+ if(numIrcUsersWaiting > 0) {
+ emit coreConnectionMsg(tr("Requesting User states..."));
+ emit coreConnectionProgress(numIrcUsers - numIrcUsersWaiting, numIrcUsers);
+ return;
}
+
+ if(numChannelsWaiting > 0) {
+ emit coreConnectionMsg(tr("Requesting Channel states..."));
+ emit coreConnectionProgress(numChannels - numChannelsWaiting, numChannels);
+ return;
+ }
+
+ emit coreConnectionProgress(1,1);
+ emit connected();
}
void Client::recvSessionData(const QString &key, const QVariant &data) {
}
}
-void Client::networkConnected(QString net) {
- Q_ASSERT(!netsAwaitingInit.contains(net));
- netConnected[net] = true;
- BufferId id = statusBufferId(net);
- Buffer *b = buffer(id);
- b->setActive(true);
- //b->displayMsg(Message(id, Message::Server, tr("Connected.")));
- // TODO buffersUpdated();
-}
+void Client::networkConnected(uint netid) {
+ // TODO: create statusBuffer / switch to networkids
+ //BufferInfo id = statusBufferInfo(net);
+ //Buffer *b = buffer(id);
+ //b->setActive(true);
-void Client::networkDisconnected(QString net) {
- foreach(BufferId id, buffers.keys()) {
- if(id.network() != net) continue;
- Buffer *b = buffer(id);
- //b->displayMsg(Message(id, Message::Server, tr("Server disconnected."))); FIXME
- b->setActive(false);
- }
- netConnected[net] = false;
- if(netsAwaitingInit.contains(net)) {
- qDebug() << "Network" << net << "disconnected while not yet initialized!";
- netsAwaitingInit.removeAll(net);
- emit coreConnectionProgress(netConnected.count(), netConnected.count() + netsAwaitingInit.count());
- if(!netsAwaitingInit.count()) emit connected();
- }
+ NetworkInfo *netinfo = new NetworkInfo(netid, signalProxy(), this);
+ connect(netinfo, SIGNAL(initDone()), this, SLOT(updateCoreConnectionProgress()));
+ connect(netinfo, SIGNAL(ircUserInitDone()), this, SLOT(updateCoreConnectionProgress()));
+ connect(netinfo, SIGNAL(ircChannelInitDone()), this, SLOT(updateCoreConnectionProgress()));
+ _networkInfo[netid] = netinfo;
}
-void Client::updateBufferId(BufferId id) {
- bufferIds[id.uid()] = id; // make lookups by id faster
- buffer(id);
-}
+void Client::networkDisconnected(uint networkid) {
+ foreach(Buffer *buffer, buffers()) {
+ if(buffer->bufferInfo().networkId() != networkid)
+ continue;
-BufferId Client::bufferId(QString net, QString buf) {
- foreach(BufferId id, buffers.keys()) {
- if(id.network() == net && id.buffer() == buf) return id;
+ //buffer->displayMsg(Message(bufferid, Message::Server, tr("Server disconnected."))); FIXME
+ buffer->setActive(false);
}
- Q_ASSERT(false); // should never happen!
- return BufferId();
-}
-
-BufferId Client::statusBufferId(QString net) {
- return bufferId(net, "");
-}
-
-
-Buffer * Client::buffer(BufferId id) {
- Client *client = Client::instance();
- if(!buffers.contains(id)) {
- Buffer *b = new Buffer(id);
- b->setOwnNick(ownNick[id.network()]);
- connect(b, SIGNAL(userInput(BufferId, QString)), client, SLOT(userInput(BufferId, QString)));
- connect(b, SIGNAL(bufferUpdated(Buffer *)), client, SIGNAL(bufferUpdated(Buffer *)));
- connect(b, SIGNAL(bufferDestroyed(Buffer *)), client, SIGNAL(bufferDestroyed(Buffer *)));
- connect(b, SIGNAL(bufferDestroyed(Buffer *)), client, SLOT(removeBuffer(Buffer *)));
- buffers[id] = b;
- emit client->bufferUpdated(b);
+
+ Q_ASSERT(networkInfo(networkid));
+ if(!networkInfo(networkid)->initialized()) {
+ qDebug() << "Network" << networkid << "disconnected while not yet initialized!";
+ updateCoreConnectionProgress();
}
- return buffers[id];
}
-QList<BufferId> Client::allBufferIds() {
- return buffers.keys();
+void Client::updateBufferInfo(BufferInfo id) {
+ buffer(id)->updateBufferInfo(id);
}
+
void Client::removeBuffer(Buffer *b) {
- buffers.remove(b->bufferId());
- bufferIds.remove(b->bufferId().uid());
-}
-
-void Client::recvNetworkState(QString net, QVariant state) {
- netsAwaitingInit.removeAll(net);
- netConnected[net] = true;
- setOwnNick(net, state.toMap()["OwnNick"].toString());
- buffer(statusBufferId(net))->setActive(true);
- QVariantMap t = state.toMap()["Topics"].toMap();
- QVariantMap n = state.toMap()["Nicks"].toMap();
- foreach(QVariant v, t.keys()) {
- QString buf = v.toString();
- BufferId id = bufferId(net, buf);
- buffer(id)->setActive(true);
- setTopic(net, buf, t[buf].toString());
- }
- foreach(QString nick, n.keys()) {
- addNick(net, nick, n[nick].toMap());
- }
- emit coreConnectionProgress(netConnected.count(), netConnected.count() + netsAwaitingInit.count());
- if(!netsAwaitingInit.count()) emit connected();
+ _buffers.remove(b->bufferInfo().uid());
}
void Client::recvMessage(const Message &msg) {
void Client::recvStatusMsg(QString /*net*/, QString /*msg*/) {
//recvMessage(net, Message::server("", QString("[STATUS] %1").arg(msg)));
-
}
-void Client::recvBacklogData(BufferId id, QVariantList msgs, bool /*done*/) {
+void Client::recvBacklogData(BufferInfo id, QVariantList msgs, bool /*done*/) {
Buffer *b = buffer(id);
foreach(QVariant v, msgs) {
Message msg = v.value<Message>();
void Client::layoutMsg() {
if(layoutQueue.count()) {
Buffer *b = layoutQueue.takeFirst(); // TODO make this the current buffer
- if(b->layoutMsg()) layoutQueue.append(b); // Buffer has more messages in its queue --> Round Robin
+ if(b->layoutMsg())
+ layoutQueue.append(b); // Buffer has more messages in its queue --> Round Robin
}
- if(!layoutQueue.count()) layoutTimer->stop();
+
+ if(!layoutQueue.count())
+ layoutTimer->stop();
}
AbstractUiMsg *Client::layoutMsg(const Message &msg) {
return instance()->mainUi->layoutMsg(msg);
}
-void Client::userInput(BufferId id, QString msg) {
+void Client::userInput(BufferInfo id, QString msg) {
emit sendInput(id, msg);
}
-void Client::setTopic(QString net, QString buf, QString topic) {
- BufferId id = bufferId(net, buf);
- if(!netConnected[id.network()]) return;
- Buffer *b = buffer(id);
- b->setTopic(topic);
- //if(!b->isActive()) {
- // b->setActive(true);
- // buffersUpdated();
- //}
-}
-
-void Client::addNick(QString net, QString nick, QVariantMap props) {
- if(!netConnected[net]) return;
- nicks[net][nick] = props;
- QVariantMap chans = props["Channels"].toMap();
- QStringList c = chans.keys();
- foreach(QString bufname, c) {
- buffer(bufferId(net, bufname))->addNick(nick, props);
- }
-}
-
-void Client::renameNick(QString net, QString oldnick, QString newnick) {
- if(!netConnected[net]) return;
- QStringList chans = nicks[net][oldnick]["Channels"].toMap().keys();
- foreach(QString c, chans) {
- buffer(bufferId(net, c))->renameNick(oldnick, newnick);
- }
- nicks[net][newnick] = nicks[net].take(oldnick);
-}
-
-void Client::updateNick(QString net, QString nick, QVariantMap props) {
- if(!netConnected[net]) return;
- QStringList oldchans = nicks[net][nick]["Channels"].toMap().keys();
- QStringList newchans = props["Channels"].toMap().keys();
- foreach(QString c, newchans) {
- if(oldchans.contains(c)) buffer(bufferId(net, c))->updateNick(nick, props);
- else buffer(bufferId(net, c))->addNick(nick, props);
- }
- foreach(QString c, oldchans) {
- if(!newchans.contains(c)) buffer(bufferId(net, c))->removeNick(nick);
- }
- nicks[net][nick] = props;
-}
-
-void Client::removeNick(QString net, QString nick) {
- if(!netConnected[net]) return;
- QVariantMap chans = nicks[net][nick]["Channels"].toMap();
- foreach(QString bufname, chans.keys()) {
- buffer(bufferId(net, bufname))->removeNick(nick);
- }
- nicks[net].remove(nick);
-}
-
-void Client::setOwnNick(QString net, QString nick) {
- if(!netConnected[net]) return;
- ownNick[net] = nick;
- foreach(BufferId id, buffers.keys()) {
- if(id.network() == net) {
- buffers[id]->setOwnNick(nick);
- }
- }
-}
-
#include <QList>
#include <QPointer>
-#include "buffer.h"
-#include "message.h"
+#include "buffer.h" // needed for activity lvl
+class BufferInfo;
+class Message;
+
+class NetworkInfo;
class AbstractUi;
+class AbstractUiMsg;
class BufferTreeModel;
-class QtGui;
class SignalProxy;
class QTimer;
+
class Client : public QObject {
Q_OBJECT
- public:
- static Client *instance();
- static void init(AbstractUi *);
- static void destroy();
-
- static QList<BufferId> allBufferIds();
- static Buffer *buffer(BufferId);
- static BufferId statusBufferId(QString net);
- static BufferId bufferId(QString net, QString buf);
-
- static BufferTreeModel *bufferModel();
- static SignalProxy *signalProxy();
-
- static AbstractUiMsg *layoutMsg(const Message &);
-
- static bool isConnected();
-
- static void storeSessionData(const QString &key, const QVariant &data);
- static QVariant retrieveSessionData(const QString &key, const QVariant &def = QVariant());
- static QStringList sessionDataKeys();
-
- enum ClientMode { LocalCore, RemoteCore };
- static ClientMode clientMode;
-
- signals:
- void sendInput(BufferId, QString message);
- void showBuffer(Buffer *);
- void bufferSelected(Buffer *);
- void bufferUpdated(Buffer *);
- void bufferActivity(Buffer::ActivityLevel, Buffer *);
- void bufferDestroyed(Buffer *);
- void backlogReceived(Buffer *, QList<Message>);
- void requestBacklog(BufferId, QVariant, QVariant);
- void requestNetworkStates();
-
- void recvPartialItem(uint avail, uint size);
- void coreConnectionError(QString errorMsg);
- void coreConnectionMsg(const QString &msg);
- void coreConnectionProgress(uint part, uint total);
-
- void connected();
- void disconnected();
-
- void sessionDataChanged(const QString &key);
- void sessionDataChanged(const QString &key, const QVariant &data);
- void sendSessionData(const QString &key, const QVariant &data);
-
- public slots:
- //void selectBuffer(Buffer *);
- //void connectToLocalCore();
- void connectToCore(const QVariantMap &);
- void disconnectFromCore();
-
- private slots:
- void recvCoreState(const QVariant &state);
- void recvSessionData(const QString &key, const QVariant &data);
-
- void coreSocketError(QAbstractSocket::SocketError);
- void coreHasData();
- void coreSocketConnected();
- void coreSocketDisconnected();
- void coreSocketStateChanged(QAbstractSocket::SocketState);
-
- void userInput(BufferId, QString);
- void networkConnected(QString);
- void networkDisconnected(QString);
- void recvNetworkState(QString, QVariant);
- void recvMessage(const Message &message);
- void recvStatusMsg(QString network, QString message);
- void setTopic(QString net, QString buf, QString);
- void addNick(QString net, QString nick, QVariantMap props);
- void removeNick(QString net, QString nick);
- void renameNick(QString net, QString oldnick, QString newnick);
- void updateNick(QString net, QString nick, QVariantMap props);
- void setOwnNick(QString net, QString nick);
- void recvBacklogData(BufferId, QVariantList, bool);
- void updateBufferId(BufferId);
-
- void removeBuffer(Buffer *);
-
- void layoutMsg();
-
- private:
- Client();
- ~Client();
- void init();
- static Client *instanceptr;
-
- void syncToCore(const QVariant &coreState);
- QVariant connectToLocalCore(QString user, QString passwd); // defined in main.cpp
- void disconnectFromLocalCore(); // defined in main.cpp
-
- AbstractUi *mainUi;
- SignalProxy *_signalProxy;
- BufferTreeModel *_bufferModel;
-
- QPointer<QIODevice> socket;
- quint32 blockSize;
-
- static bool connectedToCore;
- static QVariantMap coreConnectionInfo;
- static QHash<BufferId, Buffer *> buffers;
- static QHash<uint, BufferId> bufferIds;
- static QHash<QString, QHash<QString, QVariantMap> > nicks;
- static QHash<QString, bool> netConnected;
- static QStringList netsAwaitingInit;
- static QHash<QString, QString> ownNick;
-
- QTimer *layoutTimer;
- QList<Buffer *> layoutQueue;
-
- QVariantMap sessionData;
+public:
+ static Client *instance();
+ static void destroy();
+ static void init(AbstractUi *);
+
+ static QList<NetworkInfo *> networkInfos();
+ static NetworkInfo *networkInfo(uint networkid);
+
+ static QList<BufferInfo> allBufferInfos();
+ static QList<Buffer *> buffers();
+ static Buffer *buffer(uint bufferUid);
+ static Buffer *buffer(BufferInfo);
+ static BufferInfo statusBufferInfo(QString net);
+ static BufferInfo bufferInfo(QString net, QString buf);
+
+ static BufferTreeModel *bufferModel();
+ static SignalProxy *signalProxy();
+
+ static AbstractUiMsg *layoutMsg(const Message &);
+
+ static bool isConnected();
+
+ static void storeSessionData(const QString &key, const QVariant &data);
+ static QVariant retrieveSessionData(const QString &key, const QVariant &def = QVariant());
+ static QStringList sessionDataKeys();
+
+ enum ClientMode { LocalCore, RemoteCore };
+
+signals:
+ void sendInput(BufferInfo, QString message);
+ void showBuffer(Buffer *);
+ void bufferSelected(Buffer *);
+ void bufferUpdated(Buffer *);
+ void bufferActivity(Buffer::ActivityLevel, Buffer *);
+ void bufferDestroyed(Buffer *);
+ void backlogReceived(Buffer *, QList<Message>);
+ void requestBacklog(BufferInfo, QVariant, QVariant);
+ void requestNetworkStates();
+
+ void recvPartialItem(uint avail, uint size);
+ void coreConnectionError(QString errorMsg);
+ void coreConnectionMsg(const QString &msg);
+ void coreConnectionProgress(uint part, uint total);
+
+ void connected();
+ void disconnected();
+
+ void sessionDataChanged(const QString &key);
+ void sessionDataChanged(const QString &key, const QVariant &data);
+ void sendSessionData(const QString &key, const QVariant &data);
+
+public slots:
+ //void selectBuffer(Buffer *);
+ //void connectToLocalCore();
+ void connectToCore(const QVariantMap &);
+ void disconnectFromCore();
+
+private slots:
+ void recvCoreState(const QVariant &state);
+ void recvSessionData(const QString &key, const QVariant &data);
+
+ void coreSocketError(QAbstractSocket::SocketError);
+ void coreHasData();
+ void coreSocketConnected();
+ void coreSocketDisconnected();
+ void coreSocketStateChanged(QAbstractSocket::SocketState);
+
+ void userInput(BufferInfo, QString);
+
+ void networkConnected(uint);
+ void networkDisconnected(uint);
+
+ void updateCoreConnectionProgress();
+ void recvMessage(const Message &message);
+ void recvStatusMsg(QString network, QString message);
+ void recvBacklogData(BufferInfo, QVariantList, bool);
+ void updateBufferInfo(BufferInfo);
+
+ void removeBuffer(Buffer *);
+
+ void layoutMsg();
+
+private:
+ Client(QObject *parent = 0);
+ virtual ~Client();
+ void init();
+
+ void syncToCore(const QVariant &coreState);
+ QVariant connectToLocalCore(QString user, QString passwd); // defined in main.cpp
+ void disconnectFromLocalCore(); // defined in main.cpp
+
+ static QPointer<Client> instanceptr;
+
+ QPointer<QIODevice> socket;
+ QPointer<SignalProxy> _signalProxy;
+ QPointer<AbstractUi> mainUi;
+ QPointer<BufferTreeModel> _bufferModel;
+
+ ClientMode clientMode;
+
+ quint32 blockSize;
+ bool connectedToCore;
+
+ QVariantMap coreConnectionInfo;
+ QHash<uint, Buffer *> _buffers;
+ QHash<uint, NetworkInfo*> _networkInfo;
+
+ QTimer *layoutTimer;
+ QList<Buffer *> layoutQueue;
+
+ QVariantMap sessionData;
+
+
};
#endif
virtual QString sender() const = 0;
virtual QString text() const = 0;
virtual MsgId msgId() const = 0;
- virtual BufferId bufferId() const = 0;
+ virtual BufferInfo bufferInfo() const = 0;
virtual QDateTime timeStamp() const = 0;
};
-SET(common_SRCS global.cpp logger.cpp message.cpp settings.cpp signalproxy.cpp util.cpp ircuser.cpp)
+SET(common_SRCS global.cpp logger.cpp message.cpp settings.cpp signalproxy.cpp util.cpp synchronizer.cpp networkinfo.cpp ircuser.cpp ircchannel.cpp)
SET(common_HDRS global.h message.h util.h)
-SET(common_MOCS logger.h ircuser.h settings.h signalproxy.h)
+SET(common_MOCS logger.h synchronizer.h networkinfo.h ircuser.h ircchannel.h settings.h signalproxy.h)
QT4_WRAP_CPP(_MOC ${common_MOCS})
ADD_LIBRARY(common ${common_SRCS} ${_MOC})
--- /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 <QString>
+#include <QDataStream>
+#include <QByteArray>
+
+#include "bufferinfo.h"
+
+#include "util.h"
+
+BufferInfo::BufferInfo()
+ : _id(0),
+ _netid(0),
+ _gid(0),
+ _networkName(QString()),
+ _bufferName(QString()) {
+}
+
+BufferInfo::BufferInfo(uint id, uint networkid, uint gid, QString net, QString buf)
+ : _id(id),
+ _netid(networkid),
+ _gid(gid),
+ _networkName(net),
+ _bufferName(buf) {
+}
+
+QString BufferInfo::buffer() const {
+ if(isChannelName(_bufferName))
+ return _bufferName;
+ else
+ return nickFromMask(_bufferName);
+}
+
+QDataStream &operator<<(QDataStream &out, const BufferInfo &bufferInfo) {
+ out << bufferInfo._id << bufferInfo._netid << bufferInfo._gid << bufferInfo._networkName.toUtf8() << bufferInfo._bufferName.toUtf8();
+ return out;
+}
+
+QDataStream &operator>>(QDataStream &in, BufferInfo &bufferInfo) {
+ QByteArray n, b;
+ in >> bufferInfo._id >> bufferInfo._netid >> bufferInfo._gid >> n >> b;
+ bufferInfo._networkName = QString::fromUtf8(n);
+ bufferInfo._bufferName = QString::fromUtf8(b);
+ return in;
+}
+
+uint qHash(const BufferInfo &bufferid) {
+ return qHash(bufferid._id);
+}
+
--- /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 _BUFFERINFO_H_
+#define _BUFFERINFO_H_
+
+#include <QtCore>
+
+class QString;
+class QDataStream;
+
+class BufferInfo {
+public:
+ BufferInfo();
+ BufferInfo(uint id, uint networkid, uint gid = 0, QString net = QString(), QString buf = QString());
+
+ inline uint uid() const { return _id; }
+ inline uint networkId() const { return _netid; }
+ inline uint groupId() const { return _gid; }
+ inline QString network() const { return _networkName; }
+ QString buffer() const;
+
+ void setGroupId(uint gid) { _gid = gid; }
+
+ inline bool operator==(const BufferInfo &other) const { return _id == other._id; }
+
+private:
+ uint _id;
+ uint _netid;
+ uint _gid;
+ QString _networkName; // WILL BE REMOVED
+ QString _bufferName;
+
+ friend uint qHash(const BufferInfo &);
+ friend QDataStream &operator<<(QDataStream &out, const BufferInfo &bufferInfo);
+ friend QDataStream &operator>>(QDataStream &in, BufferInfo &bufferInfo);
+};
+
+QDataStream &operator<<(QDataStream &out, const BufferInfo &bufferInfo);
+QDataStream &operator>>(QDataStream &in, BufferInfo &bufferInfo);
+
+Q_DECLARE_METATYPE(BufferInfo);
+
+uint qHash(const BufferInfo &);
+
+#endif
DEPMOD = contrib/qxt
QT_MOD = network
-SRCS += global.cpp ircuser.cpp logger.cpp message.cpp settings.cpp signalproxy.cpp util.cpp
-HDRS += global.h ircuser.h logger.h message.h settings.h signalproxy.h util.h
+SRCS += global.cpp logger.cpp message.cpp settings.cpp signalproxy.cpp util.cpp synchronizer.cpp networkinfo.cpp ircuser.cpp ircchannel.cpp bufferinfo.cpp
+HDRS += global.h logger.h message.h settings.h signalproxy.h util.h synchronizer.h networkinfo.h ircuser.h ircchannel.h bufferinfo.h
}
*/
-/**************************************************************************************/
-BufferId::BufferId()
- : _id(0),
- _netid(0),
- _gid(0),
- _networkName(QString()),
- _bufferName(QString()) {
-}
-
-BufferId::BufferId(uint id, uint networkid, uint gid, QString net, QString buf)
- : _id(id),
- _netid(networkid),
- _gid(gid),
- _networkName(net),
- _bufferName(buf) {
-}
-
-QString BufferId::buffer() const {
- if(isChannelName(_bufferName))
- return _bufferName;
- else
- return nickFromMask(_bufferName);
-}
-
-QDataStream &operator<<(QDataStream &out, const BufferId &bufferId) {
- out << bufferId._id << bufferId._netid << bufferId._gid << bufferId._networkName.toUtf8() << bufferId._bufferName.toUtf8();
- return out;
-}
-
-QDataStream &operator>>(QDataStream &in, BufferId &bufferId) {
- QByteArray n, b;
- in >> bufferId._id >> bufferId._netid >> bufferId._gid >> n >> b;
- bufferId._networkName = QString::fromUtf8(n);
- bufferId._bufferName = QString::fromUtf8(b);
- return in;
-}
-
-uint qHash(const BufferId &bufferid) {
- return qHash(bufferid._id);
-}
-
/**
* Retrieves an icon determined by its symbolic name. The mapping shall later
* be performed by a theme manager or something like that.
};
-class BufferId {
-public:
- BufferId();
- BufferId(uint _id, uint _networkid, uint _gid = 0, QString _net = QString(), QString _buf = QString());
-
- inline uint uid() const { return _id; }
- inline uint networkId() const { return _netid; }
- inline uint groupId() const { return _gid; }
- inline QString network() const { return _networkName; }
- QString buffer() const;
-
- void setGroupId(uint gid) { _gid = gid; }
-
- inline bool operator==(const BufferId &other) const { return _id == other._id; }
-
-private:
- uint _id;
- uint _netid;
- uint _gid;
- QString _networkName; // WILL BE REMOVED
- QString _bufferName; // IS this actually needed?
-
- 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
--- /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 "ircchannel.h"
+
+#include "networkinfo.h"
+#include "signalproxy.h"
+#include "ircuser.h"
+
+#include <QMapIterator>
+#include <QHashIterator>
+
+#include <QDebug>
+
+
+IrcChannel::IrcChannel(const QString &channelname, NetworkInfo *networkinfo)
+ : QObject(networkinfo),
+ _initialized(false),
+ _name(channelname),
+ _topic(QString()),
+ networkInfo(networkinfo)
+{
+ setObjectName(QString::number(networkInfo->networkId()) + "/" + channelname);
+}
+
+// ====================
+// PUBLIC:
+// ====================
+bool IrcChannel::isKnownUser(IrcUser *ircuser) const {
+ bool isknown = true;
+
+ if(ircuser == 0) {
+ qWarning() << "Channel" << name() << "received IrcUser Nullpointer!";
+ isknown = false;
+ }
+
+ if(!_userModes.contains(ircuser) && ircuser) {
+ qWarning() << "Channel" << name() << "received data for unknown User" << ircuser->nick();
+ isknown = false;
+ }
+
+ return isknown;
+}
+
+bool IrcChannel::isValidChannelUserMode(const QString &mode) const {
+ bool isvalid = true;
+ if(mode.size() > 1) {
+ qWarning() << "Channel" << name() << "received Channel User Mode which is longer then 1 Char:" << mode;
+ isvalid = false;
+ }
+ return isvalid;
+}
+
+bool IrcChannel::initialized() const {
+ return _initialized;
+}
+
+QString IrcChannel::name() const {
+ return _name;
+}
+
+QString IrcChannel::topic() const {
+ return _topic;
+}
+
+QList<IrcUser *> IrcChannel::ircUsers() const {
+ return _userModes.keys();
+}
+
+QString IrcChannel::userMode(IrcUser *ircuser) const {
+ if(_userModes.contains(ircuser))
+ return _userModes[ircuser];
+ else
+ return QString();
+}
+
+QString IrcChannel::userMode(const QString &nick) const {
+ return userMode(networkInfo->ircUser(nick));
+}
+
+// ====================
+// PUBLIC SLOTS:
+// ====================
+void IrcChannel::setTopic(const QString &topic) {
+ _topic = topic;
+ emit topicSet(topic);
+}
+
+void IrcChannel::join(IrcUser *ircuser) {
+ if(!_userModes.contains(ircuser) && ircuser) {
+ _userModes[ircuser] = QString();
+ ircuser->joinChannel(name());
+ // no emit here since the join is propagated by IrcUser
+ }
+}
+
+void IrcChannel::join(const QString &nick) {
+ join(networkInfo->ircUser(nick));
+}
+
+void IrcChannel::part(IrcUser *ircuser) {
+ if(isKnownUser(ircuser)) {
+ _userModes.remove(ircuser);
+ ircuser->partChannel(name());
+ // no emit here since the part is propagated by IrcUser
+ }
+}
+
+void IrcChannel::part(const QString &nick) {
+ part(networkInfo->ircUser(nick));
+}
+
+// SET USER MODE
+void IrcChannel::setUserModes(IrcUser *ircuser, const QString &modes) {
+ if(isKnownUser(ircuser)) {
+ _userModes[ircuser] = modes;
+ emit userModesSet(ircuser->nick(), modes);
+ }
+}
+
+void IrcChannel::setUserModes(const QString &nick, const QString &modes) {
+ setUserModes(networkInfo->ircUser(nick), modes);
+}
+
+// ADD USER MODE
+void IrcChannel::addUserMode(IrcUser *ircuser, const QString &mode) {
+ if(!isKnownUser(ircuser) || !isValidChannelUserMode(mode))
+ return;
+
+ if(!_userModes[ircuser].contains(mode)) {
+ _userModes[ircuser] += mode;
+ emit userModeAdded(ircuser->nick(), mode);
+ }
+
+}
+
+void IrcChannel::addUserMode(const QString &nick, const QString &mode) {
+ addUserMode(networkInfo->ircUser(nick), mode);
+}
+
+
+// REMOVE USER MODE
+void IrcChannel::removeUserMode(IrcUser *ircuser, const QString &mode) {
+ if(!isKnownUser(ircuser) || !isValidChannelUserMode(mode))
+ return;
+
+ if(_userModes[ircuser].contains(mode)) {
+ _userModes[ircuser].remove(mode);
+ emit userModeRemoved(ircuser->nick(), mode);
+ }
+
+}
+
+void IrcChannel::removeUserMode(const QString &nick, const QString &mode) {
+ removeUserMode(networkInfo->ircUser(nick), mode);
+}
+
+// INIT SET USER MODES
+QVariantMap IrcChannel::initUserModes() const {
+ QVariantMap usermodes;
+ QHashIterator<IrcUser *, QString> iter(_userModes);
+ while(iter.hasNext()) {
+ iter.next();
+ usermodes[iter.key()->nick()] = iter.value();
+ }
+ return usermodes;
+}
+
+void IrcChannel::initSetUserModes(const QVariantMap &usermodes) {
+ QMapIterator<QString, QVariant> iter(usermodes);
+ while(iter.hasNext()) {
+ iter.next();
+ setUserModes(iter.key(), iter.value().toString());
+ }
+}
+
+void IrcChannel::ircUserDestroyed() {
+ part(qobject_cast<IrcUser *>(sender()));
+}
+
+void IrcChannel::setInitialized() {
+ _initialized = true;
+ emit initDone();
+}
+
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2005/06 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 _IRCCHANNEL_H_
+#define _IRCCHANNEL_H_
+
+#include <QHash>
+#include <QString>
+#include <QStringList>
+#include <QVariantMap>
+
+class SignalProxy;
+class NetworkInfo;
+class IrcUser;
+
+class IrcChannel : public QObject {
+ Q_OBJECT
+
+ Q_PROPERTY(QString name READ name STORED false)
+ Q_PROPERTY(QString topic READ topic WRITE setTopic STORED false)
+
+public:
+ IrcChannel(const QString &channelname, NetworkInfo *networkInfo);
+
+ bool isKnownUser(IrcUser *ircuser) const;
+ bool isValidChannelUserMode(const QString &mode) const;
+
+ bool initialized() const;
+
+ QString name() const;
+ QString topic() const;
+
+ QList<IrcUser *> ircUsers() const;
+
+ QString userMode(IrcUser *ircuser) const;
+ QString userMode(const QString &nick) const;
+
+
+public slots:
+ void setTopic(const QString &topic);
+
+ void join(IrcUser *ircuser);
+ void join(const QString &nick);
+
+ void part(IrcUser *ircuser);
+ void part(const QString &nick);
+
+ void setUserModes(IrcUser *ircuser, const QString &modes);
+ void setUserModes(const QString &nick, const QString &modes);
+
+ void addUserMode(IrcUser *ircuser, const QString &mode);
+ void addUserMode(const QString &nick, const QString &mode);
+
+ void removeUserMode(IrcUser *ircuser, const QString &mode);
+ void removeUserMode(const QString &nick, const QString &mode);
+
+ // init geters
+ QVariantMap initUserModes() const;
+
+ // init seters
+ void initSetUserModes(const QVariantMap &usermodes);
+
+ void ircUserDestroyed();
+
+ void setInitialized();
+
+signals:
+ void topicSet(QString topic);
+ void userModesSet(QString nick, QString modes);
+ void userModeAdded(QString nick, QString mode);
+ void userModeRemoved(QString nick, QString mode);
+
+ void initDone();
+
+private:
+ bool _initialized;
+ QString _name;
+ QString _topic;
+
+ QHash<IrcUser *, QString> _userModes;
+
+ NetworkInfo *networkInfo;
+};
+
+#endif
#include "ircuser.h"
#include "util.h"
-IrcUser::IrcUser(QObject *parent)
- : QObject(parent) {
+#include "networkinfo.h"
+#include "signalproxy.h"
+#include "ircchannel.h"
+
+#include <QDebug>
+
+IrcUser::IrcUser(const QString &hostmask, NetworkInfo *networkinfo)
+ : QObject(networkinfo),
+ _initialized(false),
+ _nick(nickFromMask(hostmask)),
+ _user(userFromMask(hostmask)),
+ _host(hostFromMask(hostmask)),
+ networkInfo(networkinfo)
+{
+ setObjectName(QString::number(networkInfo->networkId()) + "/" + IrcUser::hostmask());
}
-IrcUser::IrcUser(const QString &hostmask, QObject *parent)
- : QObject(parent),
- nick_(nickFromMask(hostmask)),
- user_(userFromMask(hostmask)),
- host_(hostFromMask(hostmask)) {
+// ====================
+// PUBLIC:
+// ====================
+bool IrcUser::initialized() const {
+ return _initialized;
}
-IrcUser::~IrcUser() {
+QString IrcUser::user() const {
+ return _user;
}
-void IrcUser::setUser(const QString &user) {
- user_ = user;
+QString IrcUser::host() const {
+ return _host;
}
-QString IrcUser::user() const {
- return user_;
+QString IrcUser::nick() const {
+ return _nick;
}
-void IrcUser::setHost(const QString &host) {
- host_ = host;
+QString IrcUser::hostmask() const {
+ return QString("%1!%2@%3").arg(nick()).arg(user()).arg(host());
}
-QString IrcUser::host() const {
- return host_;
+QString IrcUser::userModes() const {
+ return _userModes;
}
-void IrcUser::setNick(const QString &nick) {
- nick_ = nick;
+QStringList IrcUser::channels() const {
+ return _channels.toList();
}
-QString IrcUser::nick() const {
- return nick_;
+void IrcUser::updateObjectName() {
+ setObjectName(QString::number(networkInfo->networkId()) + "/" + hostmask());
+ emit objectNameSet();
+}
+
+// ====================
+// PUBLIC SLOTS:
+// ====================
+void IrcUser::setUser(const QString &user) {
+ if(!user.isEmpty() && _user != user) {
+ _user = user;
+ emit userSet(user);
+
+ setObjectName(hostmask());
+ emit objectNameSet();
+ }
}
-void IrcUser::setUsermodes(const QSet<QString> &usermodes) {
- usermodes_ = usermodes;
+void IrcUser::setHost(const QString &host) {
+ if(!host.isEmpty() && _host != host) {
+ _host = host;
+ emit hostSet(host);
+ updateObjectName();
+ }
}
-QSet<QString> IrcUser::usermodes() const {
- return usermodes_;
+void IrcUser::setNick(const QString &nick) {
+ if(!nick.isEmpty() && nick != _nick) {
+ QString oldnick(_nick);
+ _nick = nick;
+ emit nickSet(nick);
+ updateObjectName();
+ }
}
-void IrcUser::setChannelmode(const QString &channel, const QSet<QString> &channelmode) {
- if(channelmodes_.contains(channel))
- channelmodes_[channel] |= channelmode;
- else
- channelmodes_[channel] = channelmode;
+void IrcUser::updateHostmask(const QString &mask) {
+ if(mask == hostmask())
+ return;
+
+ QString user = userFromMask(mask);
+ QString host = hostFromMask(mask);
+
+ // we only need to check user and hostmask.
+ // nick can't have changed since we're identifying IrcUsers by nick
+
+ // we don't use setUser and setHost here.
+ // though this is unpretty code duplication this saves us one emit objectNameSet()
+ // the second one would be erroneous
+
+ if(!user.isEmpty() && _user != user) {
+ _user = user;
+ }
+
+ if(!host.isEmpty() && _host != host) {
+ _host = host;
+ }
+
+ emit hostmaskUpdated(mask);
+ updateObjectName();
}
-QSet<QString> IrcUser::channelmode(const QString &channel) const {
- if(channelmodes_.contains(channel))
- //throw NoSuchChannelException();
- Q_ASSERT(false); // FIXME: exception disabled for qtopia testing
- else
- return QSet<QString>();
+void IrcUser::joinChannel(const QString &channel) {
+ if(!_channels.contains(channel)) {
+ _channels.insert(channel);
+ networkInfo->newIrcChannel(channel)->join(this);
+ emit channelJoined(channel);
+ }
}
-void IrcUser::updateChannelmode(const QString &channel, const QString &channelmode, bool add) {
- if(add)
- addChannelmode(channel, channelmode);
- else
- removeChannelmode(channel, channelmode);
+void IrcUser::partChannel(const QString &channel) {
+ if(_channels.contains(channel)) {
+ _channels.remove(channel);
+
+ Q_ASSERT(networkInfo->ircChannel(channel));
+ networkInfo->ircChannel(channel)->part(this);
+
+ emit channelParted(channel);
+ }
}
-void IrcUser::addChannelmode(const QString &channel, const QString &channelmode) {
- if(!channelmodes_.contains(channel))
- channelmodes_[channel] = QSet<QString>();
- channelmodes_[channel] << channelmode;
+void IrcUser::setUserModes(const QString &modes) {
+ _userModes = modes;
+ emit userModesSet(modes);
}
-void IrcUser::removeChannelmode(const QString &channel, const QString &channelmode) {
- if(channelmodes_.contains(channel))
- channelmodes_[channel].remove(channelmode);
+void IrcUser::addUserMode(const QString &mode) {
+ if(!_userModes.contains(mode)) {
+ _userModes += mode;
+ emit userModeAdded(mode);
+ }
}
-QStringList IrcUser::channels() const {
- return channelmodes_.keys();
+void IrcUser::removeUserMode(const QString &mode) {
+ if(_userModes.contains(mode)) {
+ _userModes.remove(mode);
+ emit userModeRemoved(mode);
+ }
}
-void IrcUser::joinChannel(const QString &channel) {
- if(!channelmodes_.contains(channel))
- channelmodes_[channel] = QSet<QString>();
+void IrcUser::initSetChannels(const QStringList channels) {
+ foreach(QString channel, channels) {
+ joinChannel(channel);
+ }
}
-void IrcUser::partChannel(const QString &channel) {
- channelmodes_.remove(channel);
+void IrcUser::setInitialized() {
+ _initialized = true;
+ emit initDone();
}
+
#ifndef _IRCUSER_H_
#define _IRCUSER_H_
-#include <QtCore>
-#include <QObject>
-#include <QHash>
#include <QSet>
#include <QString>
#include <QStringList>
+#include <QVariantMap>
-#include "global.h"
+class SignalProxy;
+class NetworkInfo;
+class IrcChannel;
class IrcUser : public QObject {
Q_OBJECT
-// Q_PROPERTY(QString user READ user WRITE setUser)
-// Q_PROPERTY(QString host READ host WRITE setHost)
-// Q_PROPERTY(QString nick READ nick WRITE setNick)
-// Q_PROPERTY(QSet<QString> usermodes READ usermodes WRITE setUsermodes)
-// Q_PROPERTY(QStringList channels READ channels)
+ Q_PROPERTY(QString user READ user WRITE setUser STORED false)
+ Q_PROPERTY(QString host READ host WRITE setHost STORED false)
+ Q_PROPERTY(QString nick READ nick WRITE setNick STORED false)
+
+ Q_PROPERTY(QStringList channels READ channels STORED false)
+ // Q_PROPERTY(QStringList usermodes READ usermodes WRITE setUsermodes)
+
public:
- IrcUser(QObject *parent = 0);
- IrcUser(const QString &hostmask, QObject *parent = 0);
- ~IrcUser();
-
- void setUser(const QString &user);
+ IrcUser(const QString &hostmask, NetworkInfo *networkInfo);
+
+ bool initialized() const;
+
QString user() const;
-
- void setHost(const QString &host);
QString host() const;
-
- void setNick(const QString &nick);
QString nick() const;
-
- void setUsermodes(const QSet<QString> &usermodes);
- QSet<QString> usermodes() const;
-
- void setChannelmode(const QString &channel, const QSet<QString> &channelmode);
- QSet<QString> channelmode(const QString &channel) const;
-
- void updateChannelmode(const QString &channel, const QString &channelmode, bool add=true);
- void addChannelmode(const QString &channel, const QString &channelmode);
- void removeChannelmode(const QString &channel, const QString &channelmode);
+ QString hostmask() const;
+
+ QString userModes() const;
QStringList channels() const;
-
+
+ void updateObjectName();
+
+public slots:
+ void setUser(const QString &user);
+ void setHost(const QString &host);
+ void setNick(const QString &nick);
+ void updateHostmask(const QString &mask);
+
+ void setUserModes(const QString &modes);
+
void joinChannel(const QString &channel);
void partChannel(const QString &channel);
+
+ void addUserMode(const QString &mode);
+ void removeUserMode(const QString &mode);
+
+ // init seters
+ void initSetChannels(const QStringList channels);
+
+ void setInitialized();
+
+signals:
+ void userSet(QString user);
+ void hostSet(QString host);
+ void nickSet(QString newnick);
+ void hostmaskUpdated(QString mask);
+
+ void channelsSet(QStringList channels);
+ void userModesSet(QString modes);
+
+ void channelJoined(QString channel);
+ void channelParted(QString channel);
+
+ void userModeAdded(QString mode);
+ void userModeRemoved(QString mode);
+
+ void objectNameSet();
+// void setUsermodes(const QSet<QString> &usermodes);
+// QSet<QString> usermodes() const;
+
+ void initDone();
+
private:
inline bool operator==(const IrcUser &ircuser2) {
- return (nick_.toLower() == ircuser2.nick().toLower());
+ return (_nick.toLower() == ircuser2.nick().toLower());
}
inline bool operator==(const QString &nickname) {
- return (nick_.toLower() == nickname.toLower());
+ return (_nick.toLower() == nickname.toLower());
}
-
- QString nick_;
- QString user_;
- QString host_;
-
- QHash<QString, QSet<QString> > channelmodes_; //keys: channelnames; values: Set of Channelmodes
- QSet<QString> usermodes_;
-};
-struct IrcUserException : public Exception {};
-struct NoSuchChannelException : public IrcUserException {};
-struct NoSuchNickException : public IrcUserException {};
+ bool _initialized;
+
+ QString _nick;
+ QString _user;
+ QString _host;
+ QSet<QString> _channels;
+ QString _userModes;
+
+ NetworkInfo *networkInfo;
+};
#endif
qRegisterMetaType<QVariant>("QVariant");
qRegisterMetaType<Message>("Message");
- qRegisterMetaType<BufferId>("BufferId");
+ qRegisterMetaType<BufferInfo>("BufferInfo");
qRegisterMetaTypeStreamOperators<QVariant>("QVariant");
qRegisterMetaTypeStreamOperators<Message>("Message");
- qRegisterMetaTypeStreamOperators<BufferId>("BufferId");
+ qRegisterMetaTypeStreamOperators<BufferInfo>("BufferInfo");
#if defined BUILD_CORE
Global::runMode = Global::CoreOnly;
***************************************************************************/
#include "message.h"
+
#include "util.h"
+
#include <QDataStream>
-Message::Message(BufferId __buffer, Type __type, QString __text, QString __sender, quint8 __flags)
+Message::Message(BufferInfo __buffer, Type __type, QString __text, QString __sender, quint8 __flags)
: _buffer(__buffer), _text(__text), _sender(__sender), _type(__type), _flags(__flags) {
_timeStamp = QDateTime::currentDateTime().toUTC();
}
-Message::Message(QDateTime __ts, BufferId __buffer, Type __type, QString __text, QString __sender, quint8 __flags)
+Message::Message(QDateTime __ts, BufferInfo __buffer, Type __type, QString __text, QString __sender, quint8 __flags)
: _timeStamp(__ts), _buffer(__buffer), _text(__text), _sender(__sender), _type(__type), _flags(__flags) {
}
_msgId = _id;
}
-BufferId Message::buffer() const {
+BufferInfo Message::buffer() const {
return _buffer;
}
quint8 t, f;
quint32 ts;
QByteArray s, m;
- BufferId buf;
+ BufferInfo buf;
in >> ts >> t >> f >> buf >> s >> m;
msg._type = (Message::Type)t;
msg._flags = (quint8)f;
#include <QString>
#include <QDateTime>
+#include "bufferinfo.h"
#include "global.h"
class 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 };
- Message(BufferId buffer = BufferId(), Type type = Plain, QString text = "", QString sender = "", quint8 flags = None);
+ Message(BufferInfo buffer = BufferInfo(), Type type = Plain, QString text = "", QString sender = "", quint8 flags = None);
- Message(QDateTime ts, BufferId buffer = BufferId(), Type type = Plain, QString text = "", QString sender = "", quint8 flags = None);
+ Message(QDateTime ts, BufferInfo buffer = BufferInfo(), Type type = Plain, QString text = "", QString sender = "", quint8 flags = None);
MsgId msgId() const;
void setMsgId(MsgId id);
- BufferId buffer() const;
+ BufferInfo buffer() const;
QString text() const;
QString sender() const;
Type type() const;
private:
QDateTime _timeStamp;
MsgId _msgId;
- BufferId _buffer;
+ BufferInfo _buffer;
QString _text;
QString _sender;
Type _type;
--- /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 "networkinfo.h"
+
+#include "signalproxy.h"
+#include "synchronizer.h"
+#include "ircuser.h"
+#include "ircchannel.h"
+
+#include <QDebug>
+
+#include "util.h"
+
+// ====================
+// Public:
+// ====================
+NetworkInfo::NetworkInfo(const uint &networkid, SignalProxy *proxy, QObject *parent)
+ : QObject(parent),
+ _networkId(networkid),
+ _initialized(false),
+ _myNick(QString()),
+ _networkName(QString()),
+ _currentServer(QString()),
+ _prefixes(QString()),
+ _prefixModes(QString())
+{
+ setObjectName(QString::number(networkid));
+ _synchronizer = new Synchronizer(this, proxy);
+}
+
+// I think this is unnecessary since IrcUsers have us as their daddy :)
+// NetworkInfo::~NetworkInfo() {
+// QHashIterator<QString, IrcUser *> ircuser(_ircUsers);
+// while (ircuser.hasNext()) {
+// ircuser.next();
+// delete ircuser.value();
+// }
+// }
+
+uint NetworkInfo::networkId() const {
+ return _networkId;
+}
+
+bool NetworkInfo::initialized() const {
+ return _initialized;
+}
+
+Synchronizer *NetworkInfo::synchronizer() {
+ return _synchronizer;
+}
+
+bool NetworkInfo::isMyNick(const QString &nick) const {
+ return (myNick().toLower() == nick.toLower());
+}
+
+bool NetworkInfo::isMyNick(IrcUser *ircuser) const {
+ return (ircuser->nick().toLower() == myNick());
+}
+
+bool NetworkInfo::isChannelName(const QString &channelname) const {
+ if(channelname.isEmpty())
+ return false;
+
+ if(supports("CHANTYPES"))
+ return support("CHANTYPES").contains(channelname[0]);
+ else
+ return QString("#&!+").contains(channelname[0]);
+}
+
+QString NetworkInfo::prefixToMode(const QString &prefix) {
+ if(prefixes().contains(prefix))
+ return QString(prefixModes()[prefixes().indexOf(prefix)]);
+ else
+ return QString();
+}
+
+QString NetworkInfo::prefixToMode(const QCharRef &prefix) {
+ return prefixToMode(QString(prefix));
+}
+
+QString NetworkInfo::modeToPrefix(const QString &mode) {
+ if(prefixModes().contains(mode))
+ return QString(prefixes()[prefixModes().indexOf(mode)]);
+ else
+ return QString();
+}
+
+QString NetworkInfo::modeToPrefix(const QCharRef &mode) {
+ return modeToPrefix(QString(mode));
+}
+
+QString NetworkInfo::networkName() const {
+ return _networkName;
+}
+
+QString NetworkInfo::currentServer() const {
+ return _currentServer;
+}
+
+QString NetworkInfo::myNick() const {
+ return _myNick;
+}
+
+QStringList NetworkInfo::nicks() const {
+ // we don't use _ircUsers.keys() since the keys may be
+ // not up to date after a nick change
+ QStringList nicks;
+ foreach(IrcUser *ircuser, _ircUsers.values()) {
+ nicks << ircuser->nick();
+ }
+ return nicks;
+}
+
+QStringList NetworkInfo::channels() const {
+ return _ircChannels.keys();
+}
+
+QString NetworkInfo::prefixes() {
+ if(_prefixes.isNull())
+ determinePrefixes();
+
+ return _prefixes;
+}
+
+QString NetworkInfo::prefixModes() {
+ if(_prefixModes.isNull())
+ determinePrefixes();
+
+ return _prefixModes;
+}
+
+bool NetworkInfo::supports(const QString ¶m) const {
+ return _supports.contains(param);
+}
+
+QString NetworkInfo::support(const QString ¶m) const {
+ QString support_ = param.toUpper();
+ if(_supports.contains(support_))
+ return _supports[support_];
+ else
+ return QString();
+}
+
+IrcUser *NetworkInfo::newIrcUser(const QString &hostmask) {
+ QString nick(nickFromMask(hostmask));
+ if(!_ircUsers.contains(nick)) {
+ IrcUser *ircuser = new IrcUser(hostmask, this);
+ new Synchronizer(ircuser, synchronizer()->proxy());
+ connect(ircuser, SIGNAL(nickSet(QString)), this, SLOT(ircUserNickChanged(QString)));
+ connect(ircuser, SIGNAL(initDone()), this, SIGNAL(ircUserInitDone()));
+ connect(ircuser, SIGNAL(destroyed()), this, SLOT(ircUserDestroyed()));
+ _ircUsers[nick] = ircuser;
+ emit ircUserAdded(hostmask);
+ }
+ return _ircUsers[nick];
+}
+
+IrcUser *NetworkInfo::ircUser(const QString &nickname) const {
+ if(_ircUsers.contains(nickname))
+ return _ircUsers[nickname];
+ else
+ return 0;
+}
+
+QList<IrcUser *> NetworkInfo::ircUsers() const {
+ return _ircUsers.values();
+}
+
+IrcChannel *NetworkInfo::newIrcChannel(const QString &channelname) {
+ if(!_ircChannels.contains(channelname)) {
+ IrcChannel *channel = new IrcChannel(channelname, this);
+ new Synchronizer(channel, synchronizer()->proxy());
+ connect(channel, SIGNAL(initDone()), this, SIGNAL(ircChannelInitDone()));
+ connect(channel, SIGNAL(destroyed()), this, SLOT(channelDestroyed()));
+ _ircChannels[channelname] = channel;
+ emit ircChannelAdded(channelname);
+ }
+ return _ircChannels[channelname];
+}
+
+
+IrcChannel *NetworkInfo::ircChannel(const QString &channelname) {
+ if(_ircChannels.contains(channelname))
+ return _ircChannels[channelname];
+ else
+ return 0;
+}
+
+QList<IrcChannel *> NetworkInfo::ircChannels() const {
+ return _ircChannels.values();
+}
+
+// ====================
+// Public Slots:
+// ====================
+void NetworkInfo::setNetworkName(const QString &networkName) {
+ _networkName = networkName;
+ emit networkNameSet(networkName);
+}
+
+void NetworkInfo::setCurrentServer(const QString ¤tServer) {
+ _currentServer = currentServer;
+ emit currentServerSet(currentServer);
+}
+
+void NetworkInfo::setMyNick(const QString &nickname) {
+ _myNick = nickname;
+ emit myNickSet(nickname);
+}
+
+void NetworkInfo::addSupport(const QString ¶m, const QString &value) {
+ if(!_supports.contains(param)) {
+ _supports[param] = value;
+ emit supportAdded(param, value);
+ }
+}
+
+void NetworkInfo::removeSupport(const QString ¶m) {
+ if(_supports.contains(param)) {
+ _supports.remove(param);
+ emit supportRemoved(param);
+ }
+}
+
+QVariantMap NetworkInfo::initSupports() const {
+ QVariantMap supports;
+ QHashIterator<QString, QString> iter(_supports);
+ while(iter.hasNext()) {
+ iter.next();
+ supports[iter.key()] = iter.value();
+ }
+ return supports;
+}
+
+QStringList NetworkInfo::initIrcUsers() const {
+ QStringList hostmasks;
+ foreach(IrcUser *ircuser, ircUsers()) {
+ hostmasks << ircuser->hostmask();
+ }
+ return hostmasks;
+}
+
+QStringList NetworkInfo::initIrcChannels() const {
+ return _ircChannels.keys();
+}
+
+void NetworkInfo::initSetSupports(const QVariantMap &supports) {
+ QMapIterator<QString, QVariant> iter(supports);
+ while(iter.hasNext()) {
+ iter.next();
+ addSupport(iter.key(), iter.value().toString());
+ }
+}
+
+void NetworkInfo::initSetIrcUsers(const QStringList &hostmasks) {
+ if(!_ircUsers.empty())
+ return;
+ foreach(QString hostmask, hostmasks) {
+ newIrcUser(hostmask);
+ }
+}
+
+void NetworkInfo::initSetChannels(const QStringList &channels) {
+ if(!_ircChannels.empty())
+ return;
+ foreach(QString channel, channels)
+ newIrcChannel(channel);
+}
+
+IrcUser *NetworkInfo::updateNickFromMask(const QString &mask) {
+ QString nick(nickFromMask(mask));
+ IrcUser *ircuser;
+
+ if(_ircUsers.contains(nick)) {
+ ircuser = _ircUsers[nick];
+ ircuser->updateHostmask(mask);
+ } else {
+ ircuser = newIrcUser(mask);
+ }
+ return ircuser;
+}
+
+void NetworkInfo::ircUserNickChanged(QString newnick) {
+ QString oldnick = _ircUsers.key(qobject_cast<IrcUser*>(sender()));
+ if(oldnick.isNull())
+ return;
+
+ _ircUsers[newnick] = _ircUsers.take(oldnick);
+
+ if(myNick() == oldnick)
+ setMyNick(newnick);
+}
+
+void NetworkInfo::ircUserDestroyed() {
+ IrcUser *ircuser = qobject_cast<IrcUser *>(sender());
+ QHash<QString, IrcUser*>::iterator i = _ircUsers.begin();
+ while(i != _ircUsers.end()) {
+ if(i.value() == ircuser) {
+ i = _ircUsers.erase(i);
+ } else {
+ i++;
+ }
+ }
+}
+
+void NetworkInfo::channelDestroyed() {
+ IrcChannel *channel = qobject_cast<IrcChannel *>(sender());
+ QHash<QString, IrcChannel*>::iterator i = _ircChannels.begin();
+ while(i != _ircChannels.end()) {
+ if(i.value() == channel) {
+ i = _ircChannels.erase(i);
+ } else {
+ i++;
+ }
+ }
+}
+
+void NetworkInfo::setInitialized() {
+ _initialized = true;
+ emit initDone();
+}
+
+// ====================
+// Private:
+// ====================
+void NetworkInfo::determinePrefixes() {
+ // seems like we have to construct them first
+ QString PREFIX = support("PREFIX");
+
+ if(PREFIX.startsWith("(") && PREFIX.contains(")")) {
+ _prefixes = PREFIX.section(")", 1);
+ _prefixModes = PREFIX.mid(1).section(")", 0, 0);
+ } else {
+ QString defaultPrefixes("@%+");
+ QString defaultPrefixModes("ohv");
+
+ // we just assume that in PREFIX are only prefix chars stored
+ for(int i = 0; i < defaultPrefixes.size(); i++) {
+ if(PREFIX.contains(defaultPrefixes[i])) {
+ _prefixes += defaultPrefixes[i];
+ _prefixModes += defaultPrefixModes[i];
+ }
+ }
+ // check for success
+ if(!_prefixes.isNull())
+ return;
+
+ // well... our assumption was obviously wrong...
+ // check if it's only prefix modes
+ for(int i = 0; i < defaultPrefixes.size(); i++) {
+ if(PREFIX.contains(defaultPrefixModes[i])) {
+ _prefixes += defaultPrefixes[i];
+ _prefixModes += defaultPrefixModes[i];
+ }
+ }
+ // now we've done all we've could...
+ }
+}
+
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2005/06 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 _NETWORKINFO_H_
+#define _NETWORKINFO_H_
+
+#include <QString>
+#include <QStringList>
+#include <QList>
+#include <QHash>
+#include <QVariantMap>
+#include <QPointer>
+
+class SignalProxy;
+class Synchronizer;
+class IrcUser;
+class IrcChannel;
+
+
+class NetworkInfo : public QObject {
+ Q_OBJECT
+
+ Q_PROPERTY(QString networkName READ networkName WRITE setNetworkName STORED false)
+ Q_PROPERTY(QString currentServer READ currentServer WRITE setCurrentServer STORED false)
+ Q_PROPERTY(QString myNick READ myNick WRITE setMyNick STORED false)
+
+public:
+ NetworkInfo(const uint &networkid, SignalProxy *proxy, QObject *parent = 0);
+ // virtual ~NetworkInfo();
+
+ uint networkId() const;
+ bool initialized() const;
+ Synchronizer *synchronizer();
+
+ bool isMyNick(const QString &nick) const;
+ bool isMyNick(IrcUser *ircuser) const;
+
+ bool isChannelName(const QString &channelname) const;
+
+ QString prefixToMode(const QString &prefix);
+ QString prefixToMode(const QCharRef &prefix);
+ QString modeToPrefix(const QString &mode);
+ QString modeToPrefix(const QCharRef &mode);
+
+ QString networkName() const;
+ QString currentServer() const;
+ QString myNick() const;
+ QStringList nicks() const;
+ QStringList channels() const;
+
+ QString prefixes();
+ QString prefixModes();
+
+ bool supports(const QString ¶m) const;
+ QString support(const QString ¶m) const;
+
+ IrcUser *newIrcUser(const QString &hostmask);
+ IrcUser *ircUser(const QString &nickname) const;
+ QList<IrcUser *> ircUsers() const;
+
+ IrcChannel *newIrcChannel(const QString &channelname);
+ IrcChannel *ircChannel(const QString &channelname);
+ QList<IrcChannel *> ircChannels() const;
+
+public slots:
+ void setNetworkName(const QString &networkName);
+ void setCurrentServer(const QString ¤tServer);
+ void setMyNick(const QString &mynick);
+
+ void addSupport(const QString ¶m, const QString &value = QString());
+ void removeSupport(const QString ¶m);
+
+ inline void addIrcUser(const QString &hostmask) { newIrcUser(hostmask); }
+
+ //init geters
+ QVariantMap initSupports() const;
+ QStringList initIrcUsers() const;
+ QStringList initIrcChannels() const;
+
+ //init seters
+ void initSetSupports(const QVariantMap &supports);
+ void initSetIrcUsers(const QStringList &hostmasks);
+ void initSetChannels(const QStringList &channels);
+
+ IrcUser *updateNickFromMask(const QString &mask);
+
+ // these slots are to keep the hashlists of all users and the
+ // channel lists up to date
+ void ircUserNickChanged(QString newnick);
+
+ void ircUserDestroyed();
+ void channelDestroyed();
+
+ void setInitialized();
+
+signals:
+ void networkNameSet(const QString &networkName);
+ void currentServerSet(const QString ¤tServer);
+ void myNickSet(const QString &mynick);
+
+ void supportAdded(const QString ¶m, const QString &value = QString());
+ void supportRemoved(const QString ¶m);
+
+ void ircUserAdded(QString hostmask);
+ void ircChannelAdded(QString channelname);
+
+ void initDone();
+ void ircUserInitDone();
+ void ircChannelInitDone();
+
+private:
+ uint _networkId;
+ bool _initialized;
+
+ QString _myNick;
+ QString _networkName;
+ QString _currentServer;
+
+ QString _prefixes;
+ QString _prefixModes;
+
+ QHash<QString, IrcUser *> _ircUsers; // stores all known nicks for the server
+ QHash<QString, IrcChannel *> _ircChannels; // stores all known channels
+ QHash<QString, QString> _supports; // stores results from RPL_ISUPPORT
+
+ //QVariantMap networkSettings;
+ //QVariantMap identity;
+
+ QPointer<Synchronizer> _synchronizer;
+
+ void determinePrefixes();
+};
+
+#endif
SignalProxy(ProxyType type, QIODevice *device = 0, QObject *parent = 0);
~SignalProxy();
+ ProxyType proxyType() const { return type; }
void attachSignal(QObject* sender, const char* signal, const QByteArray& rpcFunction = QByteArray());
void attachSlot(const QByteArray& rpcFunction, QObject* recv, const char* slot);
--- /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 "synchronizer.h"
+
+#include <QString>
+#include <QRegExp>
+#include <QMetaProperty>
+#include <QMetaMethod>
+
+#include "util.h"
+#include "signalproxy.h"
+
+#include <QByteArray>
+#include <QDebug>
+
+// ====================
+// Public:
+// ====================
+Synchronizer::Synchronizer(QObject *parent, SignalProxy *signalproxy)
+ : QObject(parent),
+ _initialized(false),
+ _signalproxy(signalproxy)
+{
+ attach();
+ if(!getMethodByName("objectNameSet()").isEmpty())
+ connect(parent,SIGNAL(objectNameSet()), this, SLOT(parentChangedName()));
+}
+
+bool Synchronizer::initialized() const {
+ return _initialized;
+}
+
+SignalProxy *Synchronizer::proxy() const {
+ return _signalproxy;
+}
+
+QVariantMap Synchronizer::initData() const {
+ QVariantMap properties;
+
+ // we collect data from properties
+ foreach(QMetaProperty property, parentProperties()) {
+ QString name = QString(property.name());
+ QVariant value = property.read(parent());
+ properties[name] = value;
+ // qDebug() << ">>> SYNC:" << name << value;
+ }
+
+ // ...as well as methods, which have names starting with "init"
+ foreach(QMetaMethod method, parentSlots()) {
+ QString methodname = QString(method.signature()).section("(", 0, 0);
+ if(methodname.startsWith("initSet") ||
+ !methodname.startsWith("init"))
+ continue;
+
+ QVariant value = QVariant(QVariant::nameToType(method.typeName()));
+ QGenericReturnArgument genericvalue = QGenericReturnArgument(method.typeName(), &value);
+ QMetaObject::invokeMethod(parent(), methodname.toAscii(), genericvalue);
+
+ properties[methodBaseName(method)] = value;
+ // qDebug() << ">>> SYNC:" << methodBaseName(method) << value;
+ }
+
+ // properties["Payload"] = QByteArray(10000000, 'a'); // for testing purposes
+ return properties;
+}
+
+void Synchronizer::setInitData(const QVariantMap &properties) {
+ if(initialized())
+ return;
+
+ const QMetaObject *metaobject = parent()->metaObject();
+ QMapIterator<QString, QVariant> iterator(properties);
+ while(iterator.hasNext()) {
+ iterator.next();
+ QString name = iterator.key();
+ int propertyIndex = metaobject->indexOfProperty(name.toAscii());
+ if(propertyIndex == -1) {
+ setInitValue(name, iterator.value());
+ } else {
+ if((metaobject->property(propertyIndex)).isWritable())
+ parent()->setProperty(name.toAscii(), iterator.value());
+ else
+ setInitValue(name, iterator.value());
+ }
+ // qDebug() << "<<< SYNC:" << name << iterator.value();
+ }
+
+ _initialized = true;
+ emit initDone();
+}
+
+// ====================
+// Public Slots
+// ====================
+void Synchronizer::synchronizeClients() const {
+ emit sendInitData(initData());
+}
+
+void Synchronizer::recvInitData(QVariantMap properties) {
+ proxy()->detachObject(this);
+ setInitData(properties);
+}
+
+void Synchronizer::parentChangedName() {
+ proxy()->detachObject(parent());
+ proxy()->detachObject(this);
+ attach();
+ if(proxy()->proxyType() == SignalProxy::Client && initialized())
+ proxy()->detachObject(this);
+}
+
+// ====================
+// Private
+// ====================
+QString Synchronizer::signalPrefix() const {
+ return QString(parent()->metaObject()->className()) + "_" + QString(parent()->objectName()) + "_";
+}
+
+QString Synchronizer::initSignal() const {
+ return QString(metaObject()->className())
+ + "_" + QString(parent()->metaObject()->className())
+ + "_" + QString(parent()->objectName())
+ + "_" + QString(SIGNAL(sendInitData(QVariantMap)));
+}
+
+QString Synchronizer::requestSyncSignal() const {
+ return QString(metaObject()->className())
+ + "_" + QString(parent()->metaObject()->className())
+ + "_" + QString(parent()->objectName())
+ + "_" + QString(SIGNAL(requestSync()));
+}
+
+QString Synchronizer::methodBaseName(const QMetaMethod &method) const {
+ QString methodname = QString(method.signature()).section("(", 0, 0);
+
+ // determine where we have to chop:
+ if(method.methodType() == QMetaMethod::Slot) {
+ // we take evertyhing from the first uppercase char if it's slot
+ methodname = methodname.mid(methodname.indexOf(QRegExp("[A-Z]")));
+ } else {
+ // and if it's a signal we discard everything from the last uppercase char
+ methodname = methodname.left(methodname.lastIndexOf(QRegExp("[A-Z]")));
+ }
+
+ methodname[0] = methodname[0].toUpper();
+
+ return methodname;
+}
+
+bool Synchronizer::methodsMatch(const QMetaMethod &signal, const QMetaMethod &slot) const {
+ // if we don't even have the same basename it's a sure NO
+ if(methodBaseName(signal) != methodBaseName(slot))
+ return false;
+
+ const QMetaObject *metaobject = parent()->metaObject();
+
+ // are the signatures compatible?
+ if(! metaobject->checkConnectArgs(signal.signature(), slot.signature()))
+ return false;
+
+ // we take an educated guess if the signals and slots match
+ QString signalsuffix = QString(signal.signature()).section("(", 0, 0);
+ signalsuffix = signalsuffix.mid(signalsuffix.lastIndexOf(QRegExp("[A-Z]"))).toLower();
+
+ QString slotprefix = QString(slot.signature()).section("(", 0, 0);
+ slotprefix = slotprefix.left(slotprefix.indexOf(QRegExp("[A-Z]"))).toLower();
+
+ uint sizediff;
+ if(signalsuffix.size() < slotprefix.size())
+ sizediff = slotprefix.size() - signalsuffix.size();
+ else
+ sizediff = signalsuffix.size() - slotprefix.size();
+
+ int ratio = editingDistance(slotprefix, signalsuffix) - sizediff;
+
+ return (ratio < 2);
+}
+
+QList<QMetaProperty> Synchronizer::parentProperties() const {
+ QList<QMetaProperty> _properties;
+
+ const QMetaObject *metaobject = parent()->metaObject();
+ for(int i = metaobject->propertyOffset(); i < metaobject->propertyCount(); i++) {
+ _properties << metaobject->property(i);
+ }
+
+ return _properties;
+}
+
+QList<QMetaMethod> Synchronizer::parentSlots() const {
+ QList<QMetaMethod> _slots;
+
+ const QMetaObject *metaobject = parent()->metaObject();
+ for(int i = metaobject->methodOffset(); i < metaobject->methodCount(); i++) {
+ QMetaMethod method = metaobject->method(i);
+ if(method.methodType() == QMetaMethod::Slot)
+ _slots << method;
+ }
+
+ return _slots;
+}
+
+
+QList<QMetaMethod> Synchronizer::parentSignals() const {
+ QList<QMetaMethod> _signals;
+
+ const QMetaObject *metaobject = parent()->metaObject();
+ for(int i = metaobject->methodOffset(); i < metaobject->methodCount(); i++) {
+ QMetaMethod method = metaobject->method(i);
+ if(method.methodType() == QMetaMethod::Signal)
+ _signals << method;
+ }
+
+ return _signals;
+}
+
+QList<QMetaMethod> Synchronizer::getMethodByName(const QString &methodname) {
+ QList<QMetaMethod> _methods;
+
+ const QMetaObject* metaobject = parent()->metaObject();
+ for(int i = metaobject->methodOffset(); i < metaobject->methodCount(); i++) {
+ if(QString(metaobject->method(i).signature()).startsWith(methodname))
+ _methods << metaobject->method(i);
+ }
+
+ return _methods;
+}
+
+void Synchronizer::attach() {
+ if(proxy()->proxyType() == SignalProxy::Server)
+ attachAsMaster();
+ else
+ attachAsSlave();
+}
+
+void Synchronizer::attachAsSlave() {
+ QList<QMetaMethod> signals_ = parentSignals();
+
+ foreach(QMetaMethod slot, parentSlots()) {
+ if(signals_.empty())
+ break;
+
+ for(int i = 0; i < signals_.count(); i++) {
+ QMetaMethod signal = signals_[i];
+ if(!methodsMatch(signal, slot))
+ continue;
+
+ // we could simply put a "1" in front of the normalized signature
+ // but to guarantee future compatibility we construct a dummy signal
+ // and replace the known the fake signature by ours...
+ QString dummySlot = QString(SIGNAL(dummy()));
+ QString proxySignal = signalPrefix() + QString(signal.signature());
+ QString slotsignature = dummySlot.replace("dummy()", QString(slot.signature()));
+
+ // qDebug() << "attachSlot:" << proxySignal << slotsignature;
+ proxy()->attachSlot(proxySignal.toAscii(), parent(), slotsignature.toAscii());
+ signals_.removeAt(i);
+ break;
+ }
+ }
+
+ // and then we connect ourself, so we can receive init data
+ // qDebug() << "attachSlot:" << initSignal() << "recvInitData(QVariantMap)";
+ // qDebug() << "attachSignal:" << "requestSync()" << requestSyncSignal();
+ proxy()->attachSlot(initSignal().toAscii(), this, SLOT(recvInitData(QVariantMap)));
+ proxy()->attachSignal(this, SIGNAL(requestSync()), requestSyncSignal().toAscii());
+
+ if(!getMethodByName("setInitialized()").isEmpty())
+ connect(this, SIGNAL(initDone()), parent(), SLOT(setInitialized()));
+
+ emit requestSync();
+}
+
+void Synchronizer::attachAsMaster() {
+ QList<QMetaMethod> slots_ = parentSlots();
+
+ foreach(QMetaMethod signal, parentSignals()) {
+ if(slots_.isEmpty())
+ break;
+
+ // we don't attach all signals, just the ones that have a maching counterpart
+ for(int i = 0; i < slots_.count(); i++) {
+ QMetaMethod slot = slots_[i];
+ if(!methodsMatch(signal, slot))
+ continue;
+
+ // we could simply put a "2" in front of the normalized signature
+ // but to guarantee future compatibility we construct a dummy signal
+ // and replace the known the fake signature by ours...
+ QString dummySignal = QString(SIGNAL(dummy()));
+ QString proxySignal = signalPrefix() + QString(signal.signature());
+ QString signalsignature = dummySignal.replace("dummy()", QString(signal.signature()));
+
+ // qDebug() << "attachSignal:" << signalsignature << proxySignal;
+ proxy()->attachSignal(parent(), signalsignature.toAscii(), proxySignal.toAscii());
+ slots_.removeAt(i);
+ break;
+ }
+ }
+
+ // and then we connect ourself, so we can initialize slaves
+ // qDebug() << "attachSignal:" << "sendInitData(QVariantMap)" << initSignal();
+ // qDebug() << "attachSlot:" << "synchronizeClients()" << requestSyncSignal();
+ proxy()->attachSignal(this, SIGNAL(sendInitData(QVariantMap)), initSignal().toAscii());
+ proxy()->attachSlot(requestSyncSignal().toAscii(), this, SLOT(synchronizeClients()));
+}
+
+bool Synchronizer::setInitValue(const QString &property, const QVariant &value) {
+ QString handlername = QString("initSet") + property;
+ handlername[7] = handlername[7].toUpper();
+
+ //determine param type
+ QByteArray paramtype;
+ foreach(QMetaMethod method, getMethodByName(handlername)) {
+ if(method.parameterTypes().size() == 1) {
+ paramtype = method.parameterTypes()[0];
+ break;
+ }
+ }
+
+ if(paramtype.isNull())
+ return false;
+
+ QGenericArgument param = QGenericArgument(paramtype, &value);
+ return QMetaObject::invokeMethod(parent(), handlername.toAscii(), param);
+}
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2005/06 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 _SYNCHRONIZER_H_
+#define _SYNCHRONIZER_H_
+
+class SignalProxy;
+
+#include <QObject>;
+#include <QList>;
+#include <QString>;
+#include <QVariantMap>;
+#include <QMetaMethod>;
+#include <QPointer>
+
+class Synchronizer : public QObject {
+ Q_OBJECT
+
+public:
+ Synchronizer(QObject *parent, SignalProxy *signalproxy);
+
+ bool initialized() const;
+ SignalProxy *proxy() const;
+
+ QVariantMap initData() const;
+ void setInitData(const QVariantMap &properties);
+
+public slots:
+ void synchronizeClients() const;
+ void recvInitData(QVariantMap properties);
+ void parentChangedName();
+
+signals:
+ void requestSync() const;
+ void sendInitData(QVariantMap properties) const;
+ void initDone();
+
+private:
+ bool _initialized;
+ QPointer<SignalProxy> _signalproxy;
+
+ QString signalPrefix() const;
+ QString initSignal() const;
+ QString requestSyncSignal() const;
+
+ QString methodBaseName(const QMetaMethod &method) const;
+ bool methodsMatch(const QMetaMethod &signal, const QMetaMethod &slot) const;
+
+ QList<QMetaProperty> parentProperties() const;
+ QList<QMetaMethod> parentSlots() const;
+ QList<QMetaMethod> parentSignals() const;
+
+ QList<QMetaMethod> getMethodByName(const QString &methodname);
+
+ void attach();
+ void attachAsSlave();
+ void attachAsMaster();
+
+ bool setInitValue(const QString &property, const QVariant &value);
+};
+
+#endif
-SET(core_SRCS core.cpp coresession.cpp server.cpp serverinfo.cpp sqlitestorage.cpp storage.cpp)
+SET(core_SRCS core.cpp coresession.cpp server.cpp basichandler.cpp ircserverhandler.cpp userinputhandler.cpp ctcphandler.cpp sqlitestorage.cpp storage.cpp)
SET(core_HDRS )
-SET(core_MOCS core.h coresession.h server.h serverinfo.h sqlitestorage.h storage.h)
+SET(core_MOCS core.h coresession.h server.h basichandler.h ircserverhandler.h userinputhandler.h ctcphandler.h sqlitestorage.h storage.h)
QT4_WRAP_CPP(_MOC ${core_MOCS})
ADD_LIBRARY(core ${core_SRCS} ${_MOC})
--- /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 "basichandler.h"
+
+#include <QMetaMethod>
+
+#include "server.h"
+
+BasicHandler::BasicHandler(Server *parent)
+ : QObject(parent),
+ server(parent) {
+
+ connect(this, SIGNAL(displayMsg(Message::Type, QString, QString, QString, quint8)),
+ server, SIGNAL(displayMsg(Message::Type, QString, QString, QString, quint8)));
+
+ connect(this, SIGNAL(putCmd(QString, QStringList, QString)),
+ server, SLOT(putCmd(QString, QStringList, QString)));
+
+ connect(this, SIGNAL(putRawLine(QString)),
+ server, SLOT(putRawLine(QString)));
+}
+
+QStringList BasicHandler::providesHandlers() const {
+ QStringList handlers;
+ for(int i=0; i < metaObject()->methodCount(); i++) {
+ QString methodSignature(metaObject()->method(i).signature());
+ if(!methodSignature.startsWith("handle"))
+ continue;
+
+ methodSignature = methodSignature.section('(',0,0); // chop the attribute list
+ methodSignature = methodSignature.mid(6); // strip "handle"
+ handlers << methodSignature;
+ }
+ return handlers;
+}
+
+
+void BasicHandler::handle(const QString &member, const QGenericArgument &val0,
+ const QGenericArgument &val1, const QGenericArgument &val2,
+ const QGenericArgument &val3, const QGenericArgument &val4,
+ const QGenericArgument &val5, const QGenericArgument &val6,
+ const QGenericArgument &val7, const QGenericArgument &val8) {
+
+ // Now we try to find a handler for this message. BTW, I do love the Trolltech guys ;-)
+ QString handler = member.toLower();
+ handler[0] = handler[0].toUpper();
+ handler = "handle" + handler;
+
+ if(!QMetaObject::invokeMethod(this, handler.toAscii(), val0, val1, val2, val3, val4, val5, val6, val7, val8))
+ // Ok. Default handler it is.
+ QMetaObject::invokeMethod(this, "defaultHandler", Q_ARG(QString, member), val0, val1, val2, val3, val4, val5, val6, val7, val8);
+
+}
+
+// ====================
+// protected:
+// ====================
+NetworkInfo *BasicHandler::networkInfo() const {
+ return server->networkInfo();
+}
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2005/06 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 _BASICHANDLER_H_
+#define _BASICHANDLER_H_
+
+#include <QObject>
+#include <QString>
+#include <QStringList>
+#include <QGenericArgument>
+
+#include "message.h"
+
+class Server;
+class NetworkInfo;
+
+class BasicHandler : public QObject {
+ Q_OBJECT
+
+public:
+ BasicHandler(Server *parent = 0);
+
+ QStringList providesHandlers() const;
+
+signals:
+ void displayMsg(Message::Type, QString target, QString text, QString sender = "", quint8 flags = Message::None);
+ void putCmd(QString cmd, QStringList params, QString prefix = 0);
+ void putRawLine(QString msg);
+
+protected:
+ virtual void handle(const QString &member, const QGenericArgument &val0 = QGenericArgument(0),
+ const QGenericArgument &val1 = QGenericArgument(), const QGenericArgument &val2 = QGenericArgument(),
+ const QGenericArgument &val3 = QGenericArgument(), const QGenericArgument &val4 = QGenericArgument(),
+ const QGenericArgument &val5 = QGenericArgument(), const QGenericArgument &val6 = QGenericArgument(),
+ const QGenericArgument &val7 = QGenericArgument(), const QGenericArgument &val8 = QGenericArgument());
+
+ Server *server;
+
+
+protected:
+ NetworkInfo *networkInfo() const;
+
+};
+#endif
Core *Core::instanceptr = 0;
-Core * Core::instance() {
+Core *Core::instance() {
if(instanceptr) return instanceptr;
instanceptr = new Core();
instanceptr->init();
}
Core::Core() {
-
}
void Core::init() {
return;
}
}
- blockSizes[socket] = bsize = 0; // FIXME blockSizes aufräum0rn!
+ blockSizes[socket] = bsize = 0; // FIXME blockSizes aufräum0rn!
}
// FIXME: no longer called, since connection handling is now in SignalProxy
QVariant Core::initSession(UserId uid) {
// Find or create session for validated user
CoreSession *sess;
- if(sessions.contains(uid)) sess = sessions[uid];
- else {
+ if(sessions.contains(uid))
+ sess = sessions[uid];
+ else
sess = createSession(uid);
- }
QVariantMap reply;
reply["SessionState"] = sess->sessionState();
return reply;
DEPMOD = common contrib/qxt
QT_MOD = core network sql
-SRCS = core.cpp coresession.cpp server.cpp serverinfo.cpp sqlitestorage.cpp storage.cpp
-HDRS = core.h coresession.h server.h serverinfo.h sqlitestorage.h storage.h
+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
#include "coresession.h"
#include "server.h"
+
#include "signalproxy.h"
#include "storage.h"
+
+#include "synchronizer.h"
+#include "networkinfo.h"
+#include "ircuser.h"
+#include "ircchannel.h"
+
#include "util.h"
-CoreSession::CoreSession(UserId uid, Storage *_storage, QObject *parent) : QObject(parent), user(uid), storage(_storage) {
- _signalProxy = new SignalProxy(SignalProxy::Server, 0, this);
+
+CoreSession::CoreSession(UserId uid, Storage *_storage, QObject *parent)
+ : QObject(parent),
+ user(uid),
+ _signalProxy(new SignalProxy(SignalProxy::Server, 0, this)),
+ storage(_storage)
+{
QSettings s;
s.beginGroup(QString("SessionData/%1").arg(user));
SignalProxy *p = signalProxy();
- p->attachSlot(SIGNAL(requestNetworkStates()), this, SIGNAL(serverStateRequested()));
+ p->attachSlot(SIGNAL(requestNetworkStates()), this, SLOT(serverStateRequested()));
p->attachSlot(SIGNAL(requestConnect(QString)), this, SLOT(connectToNetwork(QString)));
- p->attachSlot(SIGNAL(sendInput(BufferId, QString)), this, SLOT(msgFromGui(BufferId, QString)));
+ p->attachSlot(SIGNAL(sendInput(BufferInfo, QString)), this, SLOT(msgFromGui(BufferInfo, QString)));
p->attachSlot(SIGNAL(importOldBacklog()), storage, SLOT(importOldBacklog()));
- p->attachSlot(SIGNAL(requestBacklog(BufferId, QVariant, QVariant)), this, SLOT(sendBacklog(BufferId, QVariant, QVariant)));
- p->attachSlot(SIGNAL(requestNetworkStates()), this, SLOT(sendServerStates()));
+ 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)));
- p->attachSignal(this, SIGNAL(backlogData(BufferId, QVariantList, bool)));
- p->attachSignal(this, SIGNAL(bufferIdUpdated(BufferId)));
- p->attachSignal(storage, SIGNAL(bufferIdUpdated(BufferId)));
+ p->attachSignal(this, SIGNAL(backlogData(BufferInfo, QVariantList, bool)));
+ p->attachSignal(this, SIGNAL(bufferInfoUpdated(BufferInfo)));
+ p->attachSignal(storage, SIGNAL(bufferInfoUpdated(BufferInfo)));
p->attachSignal(this, SIGNAL(sessionDataChanged(const QString &, const QVariant &)), SIGNAL(coreSessionDataChanged(const QString &, const QVariant &)));
p->attachSlot(SIGNAL(clientSessionDataChanged(const QString &, const QVariant &)), this, SLOT(storeSessionData(const QString &, const QVariant &)));
/* Autoconnect. (When) do we actually do this?
}
CoreSession::~CoreSession() {
-
}
UserId CoreSession::userId() const {
return data;
}
+// FIXME switch to NetworkIDs
void CoreSession::connectToNetwork(QString network) {
- QStringList networks; networks << network; // FIXME obsolete crap
- foreach(QString net, networks) {
- if(servers.contains(net)) {
-
- } else {
- Server *server = new Server(userId(), net);
- connect(this, SIGNAL(serverStateRequested()), server, SLOT(sendState()));
- connect(this, SIGNAL(connectToIrc(QString)), server, SLOT(connectToIrc(QString)));
- 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(connected(QString)), this, SLOT(serverConnected(QString)));
- connect(server, SIGNAL(disconnected(QString)), this, SLOT(serverDisconnected(QString)));
- 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)));
-
- SignalProxy *p = signalProxy();
- p->attachSignal(server, SIGNAL(serverState(QString, QVariantMap)), SIGNAL(networkState(QString, QVariantMap)));
- p->attachSignal(server, SIGNAL(modeSet(QString, QString, QString)));
- p->attachSignal(server, SIGNAL(nickAdded(QString, QString, QVariantMap)));
- p->attachSignal(server, SIGNAL(nickRenamed(QString, QString, QString)));
- p->attachSignal(server, SIGNAL(nickRemoved(QString, QString)));
- p->attachSignal(server, SIGNAL(nickUpdated(QString, QString, QVariantMap)));
- p->attachSignal(server, SIGNAL(ownNickSet(QString, QString)));
- p->attachSignal(server, SIGNAL(queryRequested(QString, QString)));
- // TODO add error handling
- p->attachSignal(server, SIGNAL(connected(QString)), SIGNAL(networkConnected(QString)));
- p->attachSignal(server, SIGNAL(disconnected(QString)), SIGNAL(networkDisconnected(QString)));
-
- server->start();
- servers[net] = server;
- }
- emit connectToIrc(net);
+ uint networkid = getNetworkId(network);
+ if(!servers.contains(networkid)) {
+ Server *server = new Server(userId(), networkid, network);
+ attachServer(server);
+ server->start();
+ servers[networkid] = server;
}
+ emit connectToIrc(network);
+}
+
+void CoreSession::attachServer(Server *server) {
+ connect(this, SIGNAL(connectToIrc(QString)), server, SLOT(connectToIrc(QString)));
+ connect(this, SIGNAL(disconnectFromIrc(QString)), server, SLOT(disconnectFromIrc(QString)));
+ connect(this, SIGNAL(msgFromGui(uint, QString, QString)), server, SLOT(userInput(uint, QString, QString)));
+
+ connect(server, SIGNAL(connected(uint)), this, SLOT(serverConnected(uint)));
+ connect(server, SIGNAL(disconnected(uint)), this, SLOT(serverDisconnected(uint)));
+ 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 serversignals to proxy
+ signalProxy()->attachSignal(server, SIGNAL(serverState(QString, QVariantMap)), SIGNAL(networkState(QString, QVariantMap)));
+ signalProxy()->attachSignal(server, SIGNAL(connected(uint)), SIGNAL(networkConnected(uint)));
+ signalProxy()->attachSignal(server, SIGNAL(disconnected(uint)), SIGNAL(networkDisconnected(uint)));
+ // TODO add error handling
+}
+
+void CoreSession::serverStateRequested() {
}
void CoreSession::addClient(QIODevice *device) {
return _signalProxy;
}
-void CoreSession::serverConnected(QString net) {
- storage->getBufferId(userId(), net); // create status buffer
+void CoreSession::serverConnected(uint networkid) {
+ storage->getBufferInfo(userId(), servers[networkid]->networkName()); // create status buffer
}
-void CoreSession::serverDisconnected(QString net) {
- delete servers[net];
- servers.remove(net);
- signalProxy()->sendSignal(SIGNAL(networkDisconnected(QString)), net); // FIXME does this work?
+void CoreSession::serverDisconnected(uint networkid) {
+ servers.remove(networkid);
+ delete servers[networkid];
}
-void CoreSession::msgFromGui(BufferId bufid, QString msg) {
- emit msgFromGui(bufid.network(), bufid.buffer(), msg);
+void CoreSession::msgFromGui(BufferInfo bufid, QString msg) {
+ emit msgFromGui(bufid.networkId(), 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 CoreSession::recvMessageFromServer(Message::Type type, QString target, QString text, QString sender, quint8 flags) {
Server *s = qobject_cast<Server*>(this->sender());
Q_ASSERT(s);
- BufferId buf;
+ BufferInfo buf;
if((flags & Message::PrivMsg) && !(flags & Message::Self)) {
- buf = storage->getBufferId(user, s->getNetwork(), nickFromMask(sender));
+ buf = storage->getBufferInfo(user, s->networkName(), nickFromMask(sender));
} else {
- buf = storage->getBufferId(user, s->getNetwork(), target);
+ buf = storage->getBufferInfo(user, s->networkName(), target);
}
Message msg(buf, type, text, sender, flags);
msg.setMsgId(storage->logMessage(msg));
void CoreSession::recvStatusMsgFromServer(QString msg) {
Server *s = qobject_cast<Server*>(sender());
Q_ASSERT(s);
- emit displayStatusMsg(s->getNetwork(), msg);
+ emit displayStatusMsg(s->networkName(), msg);
}
-QList<BufferId> CoreSession::buffers() const {
+uint CoreSession::getNetworkId(const QString &net) const {
+ return storage->getNetworkId(user, net);
+}
+
+QList<BufferInfo> CoreSession::buffers() const {
return storage->requestBuffers(user);
}
QVariant CoreSession::sessionState() {
QVariantMap v;
- QList<QVariant> bufs;
- foreach(BufferId id, storage->requestBuffers(user)) { bufs.append(QVariant::fromValue(id)); }
+
+ QVariantList bufs;
+ foreach(BufferInfo id, storage->requestBuffers(user))
+ bufs.append(QVariant::fromValue(id));
v["Buffers"] = bufs;
+
mutex.lock();
v["SessionData"] = sessionData;
mutex.unlock();
- v["Networks"] = QVariant(servers.keys());
+
+ QVariantList networks;
+ foreach(uint networkid, servers.keys())
+ networks.append(QVariant(networkid));
+ v["Networks"] = QVariant(networks);
+
// v["Payload"] = QByteArray(100000000, 'a'); // for testing purposes
return v;
}
-void CoreSession::sendServerStates() {
- emit serverStateRequested();
-}
-
-void CoreSession::sendBacklog(BufferId id, QVariant v1, QVariant v2) {
+void CoreSession::sendBacklog(BufferInfo id, QVariant v1, QVariant v2) {
QList<QVariant> log;
QList<Message> msglist;
if(v1.type() == QVariant::DateTime) {
class CoreSession : public QObject {
Q_OBJECT
- public:
- CoreSession(UserId, Storage *, QObject *parent = 0);
- ~CoreSession();
-
- QList<BufferId> buffers() const;
- UserId userId() const;
- QVariant sessionState();
-
- public slots:
- //! Store a piece session-wide data and distribute it to connected clients.
- void storeSessionData(const QString &key, const QVariant &data);
-
- void addClient(QIODevice *connection);
-
- public:
- //! Retrieve a piece of session-wide data.
- QVariant retrieveSessionData(const QString &key, const QVariant &def = QVariant());
-
- SignalProxy *signalProxy() const;
-
- public slots:
- void connectToNetwork(QString);
- //void processSignal(ClientSignal, QVariant, QVariant, QVariant);
- void sendBacklog(BufferId, QVariant, QVariant);
- void msgFromGui(BufferId, QString message);
- void sendServerStates();
-
- signals:
- 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, QVariantList, bool done);
-
- void bufferIdUpdated(BufferId);
- void sessionDataChanged(const QString &key);
- void sessionDataChanged(const QString &key, const QVariant &data);
-
- private slots:
- void recvStatusMsgFromServer(QString msg);
- void recvMessageFromServer(Message::Type, QString target, QString text, QString sender = "", quint8 flags = Message::None);
- void serverConnected(QString net);
- void serverDisconnected(QString net);
-
- private:
- UserId user;
-
- SignalProxy *_signalProxy;
- Storage *storage;
- QHash<QString, Server *> servers;
-
- QVariantMap sessionData;
- QMutex mutex;
+public:
+ CoreSession(UserId, Storage *, QObject *parent = 0);
+ virtual ~CoreSession();
+
+ uint getNetworkId(const QString &network) const;
+ QList<BufferInfo> buffers() const;
+ UserId userId() const;
+ QVariant sessionState();
+
+ //! Retrieve a piece of session-wide data.
+ QVariant retrieveSessionData(const QString &key, const QVariant &def = QVariant());
+
+ SignalProxy *signalProxy() const;
+
+ void attachServer(Server *server);
+
+public slots:
+ //! Store a piece session-wide data and distribute it to connected clients.
+ void storeSessionData(const QString &key, const QVariant &data);
+
+ void serverStateRequested();
+
+ void addClient(QIODevice *connection);
+
+ void connectToNetwork(QString);
+
+ //void processSignal(ClientSignal, QVariant, QVariant, QVariant);
+ void sendBacklog(BufferInfo, QVariant, QVariant);
+ void msgFromGui(BufferInfo, QString message);
+
+signals:
+ void msgFromGui(uint netid, QString buf, QString message);
+ void displayMsg(Message message);
+ void displayStatusMsg(QString, QString);
+
+ void connectToIrc(QString net);
+ void disconnectFromIrc(QString net);
+
+ void backlogData(BufferInfo, QVariantList, bool done);
+
+ void bufferInfoUpdated(BufferInfo);
+ void sessionDataChanged(const QString &key);
+ void sessionDataChanged(const QString &key, const QVariant &data);
+
+private slots:
+ void recvStatusMsgFromServer(QString msg);
+ void recvMessageFromServer(Message::Type, QString target, QString text, QString sender = "", quint8 flags = Message::None);
+ void serverConnected(uint networkid);
+ void serverDisconnected(uint networkid);
+
+private:
+ UserId user;
+
+ SignalProxy *_signalProxy;
+ Storage *storage;
+ QHash<uint, Server *> servers;
+
+ QVariantMap sessionData;
+ QMutex mutex;
};
#endif
--- /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 "ctcphandler.h"
+
+#include "util.h"
+#include "message.h"
+
+CtcpHandler::CtcpHandler(Server *parent)
+ : BasicHandler(parent) {
+
+ QString MQUOTE = QString('\020');
+ ctcpMDequoteHash[MQUOTE + '0'] = QString('\000');
+ ctcpMDequoteHash[MQUOTE + 'n'] = QString('\n');
+ ctcpMDequoteHash[MQUOTE + 'r'] = QString('\r');
+ ctcpMDequoteHash[MQUOTE + MQUOTE] = MQUOTE;
+
+ XDELIM = QString('\001');
+ QString XQUOTE = QString('\134');
+ ctcpXDelimDequoteHash[XQUOTE + XQUOTE] = XQUOTE;
+ ctcpXDelimDequoteHash[XQUOTE + QString('a')] = XDELIM;
+}
+
+QString CtcpHandler::dequote(QString message) {
+ QString dequotedMessage;
+ QString messagepart;
+ QHash<QString, QString>::iterator ctcpquote;
+
+ // copy dequote Message
+ for(int i = 0; i < message.size(); i++) {
+ messagepart = message[i];
+ if(i+1 < message.size()) {
+ for(ctcpquote = ctcpMDequoteHash.begin(); ctcpquote != ctcpMDequoteHash.end(); ++ctcpquote) {
+ if(message.mid(i,2) == ctcpquote.key()) {
+ dequotedMessage += ctcpquote.value();
+ i++;
+ break;
+ }
+ }
+ }
+ dequotedMessage += messagepart;
+ }
+ return dequotedMessage;
+}
+
+
+QString CtcpHandler::XdelimDequote(QString message) {
+ QString dequotedMessage;
+ QString messagepart;
+ QHash<QString, QString>::iterator xdelimquote;
+
+ for(int i = 0; i < message.size(); i++) {
+ messagepart = message[i];
+ if(i+1 < message.size()) {
+ for(xdelimquote = ctcpXDelimDequoteHash.begin(); xdelimquote != ctcpXDelimDequoteHash.end(); ++xdelimquote) {
+ if(message.mid(i,2) == xdelimquote.key()) {
+ messagepart = xdelimquote.value();
+ i++;
+ break;
+ }
+ }
+ }
+ dequotedMessage += messagepart;
+ }
+ return dequotedMessage;
+}
+
+QStringList CtcpHandler::parse(CtcpType ctcptype, QString prefix, QString target, QString message) {
+ QStringList messages;
+ QString ctcp;
+
+ //lowlevel message dequote
+ QString dequotedMessage = dequote(message);
+
+ // extract tagged / extended data
+ while(dequotedMessage.contains(XDELIM)) {
+ messages << dequotedMessage.section(XDELIM,0,0);
+ ctcp = XdelimDequote(dequotedMessage.section(XDELIM,1,1));
+ dequotedMessage = dequotedMessage.section(XDELIM,2,2);
+
+ //dispatch the ctcp command
+ QString ctcpcmd = ctcp.section(' ', 0, 0);
+ QString ctcpparam = ctcp.section(' ', 1);
+
+ handle(ctcpcmd, Q_ARG(CtcpType, ctcptype), Q_ARG(QString, prefix), Q_ARG(QString, target), Q_ARG(QString, ctcpparam));
+ }
+ if(!dequotedMessage.isEmpty()) {
+ messages << dequotedMessage;
+ }
+ return messages;
+}
+
+QString CtcpHandler::pack(QString ctcpTag, QString message) {
+ return XDELIM + ctcpTag + ' ' + message + XDELIM;
+}
+
+void CtcpHandler::query(QString bufname, QString ctcpTag, QString message) {
+ QStringList params;
+ params << bufname << pack(ctcpTag, message);
+ emit putCmd("PRIVMSG", params);
+}
+
+void CtcpHandler::reply(QString bufname, QString ctcpTag, QString message) {
+ QStringList params;
+ params << bufname << pack(ctcpTag, message);
+ emit putCmd("NOTICE", params);
+}
+
+//******************************/
+// CTCP HANDLER
+//******************************/
+void CtcpHandler::handleAction(CtcpType ctcptype, QString prefix, QString target, QString param) {
+ emit displayMsg(Message::Action, target, param, prefix);
+}
+
+void CtcpHandler::handlePing(CtcpType ctcptype, QString prefix, QString target, QString param) {
+ if(ctcptype == CtcpQuery) {
+ reply(nickFromMask(prefix), "PING", param);
+ emit displayMsg(Message::Server, "", tr("Received CTCP PING request from %1").arg(prefix));
+ } else {
+ // display ping answer
+ }
+}
+
+void CtcpHandler::handleVersion(CtcpType ctcptype, QString prefix, QString target, QString param) {
+ if(ctcptype == CtcpQuery) {
+ // FIXME use real Info about quassel :)
+ reply(nickFromMask(prefix), "VERSION", QString("Quassel IRC (Pre-Release) - http://www.quassel-irc.org"));
+ emit displayMsg(Message::Server, "", tr("Received CTCP VERSION request by %1").arg(prefix));
+ } else {
+ // TODO display Version answer
+ }
+}
+
+void CtcpHandler::defaultHandler(QString cmd, CtcpType ctcptype, QString prefix, QString target, QString param) {
+ emit displayMsg(Message::Error, "", tr("Received unknown CTCP %1 by %2").arg(cmd).arg(prefix));
+}
+
+
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2005/06 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 _CTCPHANDLER_H_
+#define _CTCPHANDLER_H_
+
+#include <QHash>
+#include <QStringList>
+
+#include "basichandler.h"
+
+class CtcpHandler : public BasicHandler {
+ Q_OBJECT
+
+public:
+ CtcpHandler(Server *parent = 0);
+
+ enum CtcpType {CtcpQuery, CtcpReply};
+
+ QStringList parse(CtcpType, QString, QString, QString);
+
+ QString dequote(QString);
+ QString XdelimDequote(QString);
+
+ QString pack(QString ctcpTag, QString message);
+ void query(QString bufname, QString ctcpTag, QString message);
+ void reply(QString bufname, QString ctcpTag, QString message);
+
+public slots:
+ void handleAction(CtcpType, QString prefix, QString target, QString param);
+ void handlePing(CtcpType, QString prefix, QString target, QString param);
+ void handleVersion(CtcpType, QString prefix, QString target, QString param);
+
+ void defaultHandler(QString cmd, CtcpType ctcptype, QString prefix, QString target, QString param);
+
+private:
+ QString XDELIM;
+ QHash<QString, QString> ctcpMDequoteHash;
+ QHash<QString, QString> ctcpXDelimDequoteHash;
+
+
+};
+
+
+#endif
--- /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 "ircserverhandler.h"
+
+#include "util.h"
+
+#include "server.h"
+#include "networkinfo.h"
+#include "ctcphandler.h"
+
+#include "ircuser.h"
+#include "ircchannel.h"
+
+#include <QDebug>
+
+IrcServerHandler::IrcServerHandler(Server *parent)
+ : BasicHandler(parent) {
+}
+
+IrcServerHandler::~IrcServerHandler() {
+}
+
+/*! Handle a raw message string sent by the server. We try to find a suitable handler, otherwise we call a default handler. */
+void IrcServerHandler::handleServerMsg(QByteArray rawmsg) {
+ try {
+ if(rawmsg.isEmpty()) {
+ qWarning() << "Received empty string from server!";
+ return;
+ }
+ // TODO Implement encoding conversion
+ /* At this point, we have a raw message as a byte array. This needs to be converted to a QString somewhere.
+ * Problem is, that at this point we don't know which encoding to use for the various parts of the message.
+ * This is something the command handler needs to take care of (e.g. PRIVMSG needs to first parse for CTCP,
+ * and then convert the raw strings into the correct encoding.
+ * We _can_ safely assume Server encoding for prefix and cmd, but not for the params. Therefore, we need to
+ * change from a QStringList to a QList<QByteArray> in all the handlers, and have the handlers call decodeString
+ * where needed...
+ */
+ QString msg = QString::fromLatin1(rawmsg);
+
+ // OK, first we split the raw message into its various parts...
+ QString prefix = "";
+ QString cmd;
+ QStringList params;
+
+ // a colon as the first chars indicates the existance of a prefix
+ if(msg[0] == ':') {
+ msg.remove(0,1);
+ prefix = msg.section(' ', 0, 0);
+ msg = msg.section(' ', 1);
+ }
+
+ // next string without a whitespace is the command
+ cmd = msg.section(' ', 0, 0).toUpper();
+ msg = msg.mid(cmd.length());
+
+ // get the parameters
+ QString trailing = "";
+ if(msg.contains(" :")) {
+ trailing = msg.section(" :", 1);
+ msg = msg.section(" :", 0, 0);
+ }
+ if(!msg.isEmpty()) {
+ params << msg.split(' ', QString::SkipEmptyParts);
+ }
+ if(!trailing.isEmpty()) {
+ params << trailing;
+ }
+
+ // numeric replies have the target as first param (RFC 2812 - 2.4). this is usually our own nick. Remove this!
+ uint num = cmd.toUInt();
+ if(num > 0) {
+ Q_ASSERT(params.count() > 0); // Violation to RFC
+ params.removeFirst();
+ }
+
+ // Now we try to find a handler for this message. BTW, I do love the Trolltech guys ;-)
+ handle(cmd, Q_ARG(QString, prefix), Q_ARG(QStringList, params));
+ //handle(cmd, Q_ARG(QString, prefix));
+ } catch(Exception e) {
+ emit displayMsg(Message::Error, "", e.msg());
+ }
+}
+
+
+void IrcServerHandler::defaultHandler(QString cmd, QString prefix, QStringList params) {
+ uint num = cmd.toUInt();
+ if(num) {
+ // A lot of server messages don't really need their own handler because they don't do much.
+ // Catch and handle these here.
+ 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);
+ break;
+ // Server error messages without param, just display them
+ case 409: case 411: case 412: case 422: case 424: 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:
+ case 431: // ERR_NONICKNAMEGIVEN
+ 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 442:
+ { QString p = params.takeFirst();
+ 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 441: case 444: case 461:
+ case 467: case 471: case 473: case 474: case 475: case 476: case 477: case 478: case 482:
+ case 436: // ERR_NICKCOLLISION
+ { QString p = params.takeFirst();
+ emit displayMsg(Message::Error, "", p + ": " + params.join(" "));
+ break;
+ }
+ // Ignore these commands.
+ case 366: case 376:
+ break;
+
+ // Everything else will be marked in red, so we can add them somewhere.
+ default:
+ emit displayMsg(Message::Error, "", cmd + " " + params.join(" "), prefix);
+ }
+ //qDebug() << prefix <<":"<<cmd<<params;
+ } else {
+ emit displayMsg(Message::Error, "", QString("Unknown: ") + cmd + " " + params.join(" "), prefix);
+ //qDebug() << prefix <<":"<<cmd<<params;
+ }
+}
+
+//******************************/
+// IRC SERVER HANDLER
+//******************************/
+void IrcServerHandler::handleJoin(QString prefix, QStringList params) {
+ Q_ASSERT(params.count() == 1);
+ QString channel = params[0];
+ IrcUser *ircuser = networkInfo()->updateNickFromMask(prefix);
+ emit displayMsg(Message::Join, channel, channel, prefix);
+
+ ircuser->joinChannel(channel);
+}
+
+void IrcServerHandler::handleKick(QString prefix, QStringList params) {
+ networkInfo()->updateNickFromMask(prefix);
+ IrcUser *victim = networkInfo()->ircUser(params[1]);
+ QString channel = params[0];
+ Q_ASSERT(victim);
+
+ victim->partChannel(channel);
+
+ QString msg;
+ if(params.count() > 2) // someone got a reason!
+ msg = QString("%1 %2").arg(victim->nick()).arg(params[2]);
+ else
+ msg = victim->nick();
+
+ emit displayMsg(Message::Kick, params[0], msg, prefix);
+}
+
+void IrcServerHandler::handleMode(QString prefix, QStringList params) {
+// if(isChannelName(params[0])) {
+// // TODO only channel-user modes supported by now
+// QString prefixes = serverSupports["PrefixModes"].toString();
+// QString modes = params[1];
+// int p = 2;
+// int m = 0;
+// bool add = true;
+// while(m < modes.length()) {
+// if(modes[m] == '+') { add = true; m++; continue; }
+// if(modes[m] == '-') { add = false; m++; continue; }
+// if(prefixes.contains(modes[m])) { // it's a user channel mode
+// Q_ASSERT(params.count() > m);
+// QString nick = params[p++];
+// if(nicks.contains(nick)) { // sometimes, a server might try to set a MODE on a nick that is no longer there
+// QVariantMap n = nicks[nick]; QVariantMap clist = n["Channels"].toMap(); QVariantMap chan = clist[params[0]].toMap();
+// QString mstr = chan["Mode"].toString();
+// add ? mstr += modes[m] : mstr.remove(modes[m]);
+// chan["Mode"] = mstr; clist[params[0]] = chan; n["Channels"] = clist; nicks[nick] = n;
+// emit nickUpdated(network, nick, n);
+// }
+// m++;
+// } else {
+// // TODO add more modes
+// m++;
+// }
+// }
+// emit displayMsg(Message::Mode, params[0], params.join(" "), prefix);
+// } else {
+// //Q_ASSERT(nicks.contains(params[0]));
+// //QVariantMap n = nicks[params[0]].toMap();
+// //QString mode = n["Mode"].toString();
+// emit displayMsg(Message::Mode, "", params.join(" "));
+// }
+}
+
+void IrcServerHandler::handleNick(QString prefix, QStringList params) {
+ IrcUser *ircuser = networkInfo()->updateNickFromMask(prefix);
+ Q_ASSERT(ircuser);
+ QString newnick = params[0];
+ QString oldnick = ircuser->nick();
+
+ foreach(QString channel, ircuser->channels()) {
+ if(networkInfo()->isMyNick(oldnick))
+ emit displayMsg(Message::Nick, channel, newnick, prefix);
+ else
+ emit displayMsg(Message::Nick, channel, newnick, newnick);
+ }
+ ircuser->setNick(newnick);
+}
+
+void IrcServerHandler::handleNotice(QString prefix, QStringList params) {
+ if(networkInfo()->currentServer().isEmpty() || networkInfo()->currentServer() == prefix)
+ emit displayMsg(Message::Server, "", params[1], prefix);
+ else
+ emit displayMsg(Message::Notice, "", params[1], prefix);
+}
+
+void IrcServerHandler::handlePart(QString prefix, QStringList params) {
+ IrcUser *ircuser = networkInfo()->updateNickFromMask(prefix);
+ QString channel = params[0];
+ Q_ASSERT(ircuser);
+
+ ircuser->partChannel(channel);
+
+ QString msg;
+ if(params.count() > 1)
+ msg = params[1];
+
+ emit displayMsg(Message::Part, params[0], msg, prefix);
+}
+
+void IrcServerHandler::handlePing(QString prefix, QStringList params) {
+ emit putCmd("PONG", params);
+}
+
+void IrcServerHandler::handlePrivmsg(QString prefix, QStringList params) {
+ networkInfo()->updateNickFromMask(prefix);
+ Q_ASSERT(params.count() >= 2);
+ if(params.count()<2)
+ emit displayMsg(Message::Plain, params[0], "", prefix);
+ else {
+ // it's possible to pack multiple privmsgs into one param using ctcp
+ QStringList messages = server->ctcpHandler()->parse(CtcpHandler::CtcpQuery, prefix, params[0], params[1]);
+
+ // are we the target or is it a channel?
+ if(networkInfo()->isMyNick(params[0])) {
+ foreach(QString message, messages) {
+ if(!message.isEmpty()) {
+ emit displayMsg(Message::Plain, "", message, prefix, Message::PrivMsg);
+ }
+ }
+
+ } else {
+ Q_ASSERT(isChannelName(params[0])); // should be channel!
+ foreach(QString message, messages) {
+ if(!message.isEmpty()) {
+ emit displayMsg(Message::Plain, params[0], message, prefix);
+ }
+ }
+ }
+ }
+}
+
+void IrcServerHandler::handleQuit(QString prefix, QStringList params) {
+ IrcUser *ircuser = networkInfo()->updateNickFromMask(prefix);
+ Q_ASSERT(ircuser);
+
+ QString msg;
+ if(params.count())
+ msg = params[0];
+
+ foreach(QString channel, ircuser->channels())
+ emit displayMsg(Message::Quit, channel, msg, prefix);
+
+ ircuser->deleteLater();
+}
+
+void IrcServerHandler::handleTopic(QString prefix, QStringList params) {
+ IrcUser *ircuser = networkInfo()->updateNickFromMask(prefix);
+ QString channel = params[0];
+ QString topic = params[1];
+ Q_ASSERT(ircuser);
+
+ networkInfo()->ircChannel(channel)->setTopic(topic);
+
+ emit displayMsg(Message::Server, params[0], tr("%1 has changed topic for %2 to: \"%3\"").arg(ircuser->nick()).arg(channel).arg(topic));
+}
+
+/* RPL_WELCOME */
+void IrcServerHandler::handle001(QString prefix, QStringList params) {
+ // there should be only one param: "Welcome to the Internet Relay Network <nick>!<user>@<host>"
+ QString myhostmask = params[0].section(' ', -1, -1);
+ networkInfo()->setCurrentServer(prefix);
+ networkInfo()->setMyNick(nickFromMask(myhostmask));
+
+ emit displayMsg(Message::Server, "", params[0], prefix);
+
+ // TODO: reimplement perform List!
+ //// send performlist
+ //QStringList performList = networkSettings["Perform"].toString().split( "\n" );
+ //int count = performList.count();
+ //for(int a = 0; a < count; a++) {
+ // if(!performList[a].isEmpty() ) {
+ // userInput(network, "", performList[a]);
+ // }
+ //}
+}
+
+/* RPL_ISUPPORT */
+// TODO Complete 005 handling, also use sensible defaults for non-sent stuff
+void IrcServerHandler::handle005(QString prefix, QStringList params) {
+ QString rpl_isupport_suffix = params.takeLast();
+ if(rpl_isupport_suffix.toLower() != QString("are supported by this server")) {
+ qWarning() << "Received invalid RPL_ISUPPORT! Suffix is:" << rpl_isupport_suffix << "Excpected: are supported by this server";
+ return;
+ }
+
+ foreach(QString param, params) {
+ QString key = param.section("=", 0, 0);
+ QString value = param.section("=", 1);
+ networkInfo()->addSupport(key, value);
+ }
+}
+
+
+/* RPL_NOTOPIC */
+void IrcServerHandler::handle331(QString prefix, QStringList params) {
+ networkInfo()->ircChannel(params[0])->setTopic(QString());
+ emit displayMsg(Message::Server, params[0], tr("No topic is set for %1.").arg(params[0]));
+}
+
+/* RPL_TOPIC */
+void IrcServerHandler::handle332(QString prefix, QStringList params) {
+ networkInfo()->ircChannel(params[0])->setTopic(params[1]);
+ emit displayMsg(Message::Server, params[0], tr("Topic for %1 is \"%2\"").arg(params[0]).arg(params[1]));
+}
+
+/* Topic set by... */
+void IrcServerHandler::handle333(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()));
+}
+
+/* RPL_NAMREPLY */
+void IrcServerHandler::handle353(QString prefix, QStringList params) {
+ params.removeFirst(); // either "=", "*" or "@" indicating a public, private or secret channel
+ QString channelname = params.takeFirst();
+
+ foreach(QString nick, params.takeFirst().split(' ')) {
+ QString mode = QString();
+
+ if(networkInfo()->prefixes().contains(nick[0])) {
+ mode = networkInfo()->prefixToMode(nick[0]);
+ nick = nick.mid(1);
+ }
+
+ IrcUser *ircuser = networkInfo()->newIrcUser(nick);
+ ircuser->joinChannel(channelname);
+
+ if(!mode.isNull())
+ networkInfo()->ircChannel(channelname)->addUserMode(ircuser, mode);
+ }
+}
+
+/* ERR_ERRONEUSNICKNAME */
+void IrcServerHandler::handle432(QString prefix, QStringList params) {
+// if(params.size() < 2) {
+// // handle unreal-ircd bug, where unreal ircd doesnt supply a TARGET in ERR_ERRONEUSNICKNAME during registration phase:
+// // nick @@@
+// // :irc.scortum.moep.net 432 @@@ :Erroneous Nickname: Illegal characters
+// // correct server reply:
+// // :irc.scortum.moep.net 432 * @@@ :Erroneous Nickname: Illegal characters
+// emit displayMsg(Message::Error, "", tr("There is a nickname in your identity's nicklist which contains illegal characters"));
+// emit displayMsg(Message::Error, "", tr("Due to a bug in Unreal IRCd (and maybe other irc-servers too) we're unable to determine the erroneous nick"));
+// emit displayMsg(Message::Error, "", tr("Please use: /nick <othernick> to continue or clean up your nicklist"));
+// } else {
+// QString errnick = params[0];
+// emit displayMsg(Message::Error, "", tr("Nick %1 contains illegal characters").arg(errnick));
+// // if there is a problem while connecting to the server -> we handle it
+// // TODO rely on another source...
+// if(currentServer.isEmpty()) {
+// QStringList desiredNicks = identity["NickList"].toStringList();
+// int nextNick = desiredNicks.indexOf(errnick) + 1;
+// if (desiredNicks.size() > nextNick) {
+// putCmd("NICK", QStringList(desiredNicks[nextNick]));
+// } else {
+// emit displayMsg(Message::Error, "", tr("No free and valid nicks in nicklist found. use: /nick <othernick> to continue"));
+// }
+// }
+// }
+}
+
+/* ERR_NICKNAMEINUSE */
+void IrcServerHandler::handle433(QString prefix, QStringList params) {
+// QString errnick = params[0];
+// 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()) {
+// QStringList desiredNicks = identity["NickList"].toStringList();
+// int nextNick = desiredNicks.indexOf(errnick) + 1;
+// if (desiredNicks.size() > nextNick) {
+// putCmd("NICK", QStringList(desiredNicks[nextNick]));
+// } else {
+// emit displayMsg(Message::Error, "", tr("No free and valid nicks in nicklist found. use: /nick <othernick> to continue"));
+// }
+// }
+}
+
+/***********************************************************************************/
+
+
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2005/06 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 _IRCSERVERHANDLER_H_
+#define _IRCSERVERHANDLER_H_
+
+#include "basichandler.h"
+
+class IrcServerHandler : public BasicHandler {
+ Q_OBJECT
+
+public:
+ IrcServerHandler(Server *parent = 0);
+ ~IrcServerHandler();
+
+ void handleServerMsg(QByteArray rawMsg);
+
+public slots:
+ void handleJoin(QString, QStringList);
+ void handleKick(QString, QStringList);
+ void handleMode(QString, QStringList);
+ void handleNick(QString, QStringList);
+ void handleNotice(QString, QStringList);
+ void handlePart(QString, QStringList);
+ void handlePing(QString, QStringList);
+ void handlePrivmsg(QString, QStringList);
+ void handleQuit(QString, QStringList);
+ void handleTopic(QString, QStringList);
+
+ void handle001(QString, QStringList); // RPL_WELCOME
+ void handle005(QString, QStringList); // RPL_ISUPPORT
+ void handle331(QString, QStringList); // RPL_NOTOPIC
+ void handle332(QString, QStringList); // RPL_TOPIC
+ void handle333(QString, QStringList); // Topic set by...
+ void handle353(QString, QStringList); // RPL_NAMREPLY
+ void handle432(QString, QStringList); // ERR_ERRONEUSNICKNAME
+ void handle433(QString, QStringList); // ERR_NICKNAMEINUSE
+
+ void defaultHandler(QString cmd, QString prefix, QStringList params);
+};
+
+
+#endif
#include "core.h"
#include "coresession.h"
-Server::Server(UserId uid, QString net) : user(uid), network(net) {
- QString MQUOTE = QString('\020');
- ctcpMDequoteHash[MQUOTE + '0'] = QString('\000');
- ctcpMDequoteHash[MQUOTE + 'n'] = QString('\n');
- ctcpMDequoteHash[MQUOTE + 'r'] = QString('\r');
- ctcpMDequoteHash[MQUOTE + MQUOTE] = MQUOTE;
+#include "networkinfo.h"
+#include "synchronizer.h"
- XDELIM = QString('\001');
- QString XQUOTE = QString('\134');
- ctcpXDelimDequoteHash[XQUOTE + XQUOTE] = XQUOTE;
- ctcpXDelimDequoteHash[XQUOTE + QString('a')] = XDELIM;
-
- serverinfo = new ServerInfo();
+#include "ircserverhandler.h"
+#include "userinputhandler.h"
+#include "ctcphandler.h"
+
+Server::Server(UserId uid, uint networkId, QString net)
+ : _userId(uid),
+ _networkId(networkId),
+ _ircServerHandler(new IrcServerHandler(this)),
+ _userInputHandler(new UserInputHandler(this)),
+ _ctcpHandler(new CtcpHandler(this)),
+ _networkInfo(new NetworkInfo(networkId, coreSession()->signalProxy(), this))
+{
+ networkInfo()->setNetworkName(net);
}
Server::~Server() {
- delete serverinfo;
+ delete _ircServerHandler;
+ delete _userInputHandler;
+ delete _ctcpHandler;
}
void Server::run() {
exec();
}
-void Server::sendState() {
- QVariantMap s;
- QVariantMap n, t;
- foreach(QString key, nicks.keys()) { n[key] = nicks[key]; }
- foreach(QString key, topics.keys()) { t[key] = topics[key];}
- s["Nicks"] = n;
- s["Topics"] = t;
- s["OwnNick"] = ownNick;
- s["ServerSupports"] = serverSupports;
- emit serverState(network, s);
-}
-
void Server::connectToIrc(QString net) {
- if(net != network) return; // not me!
- CoreSession *sess = Core::session(user);
- //networkSettings = Global::data(user, "Networks").toMap()[net].toMap();
+ if(net != networkName())
+ return; // not me!
+
+ CoreSession *sess = coreSession();
networkSettings = sess->retrieveSessionData("Networks").toMap()[net].toMap();
- //identity = Global::data(user, "Identities").toMap()[networkSettings["Identity"].toString()].toMap();
identity = sess->retrieveSessionData("Identities").toMap()[networkSettings["Identity"].toString()].toMap();
+
+ //FIXME this will result in a pretty fuckup if there are no servers in the list
QList<QVariant> servers = networkSettings["Servers"].toList();
QString host = servers[0].toMap()["Address"].toString();
quint16 port = servers[0].toMap()["Port"].toUInt();
}
void Server::disconnectFromIrc(QString net) {
- if(net != network) return; // not me!
+ if(net != networkName())
+ return; // not me!
socket.disconnectFromHost();
}
void Server::socketHasData() {
while(socket.canReadLine()) {
QByteArray s = socket.readLine().trimmed();
- //qDebug() << "Read" << s;
- //emit recvRawServerMsg(s); // signal not needed, and we should make sure we consider encodings where we need them
- //Message *msg = Message::createFromServerString(this, s);
- handleServerMsg(s);
+ ircServerHandler()->handleServerMsg(s);
}
}
void Server::socketError( QAbstractSocket::SocketError err ) {
//qDebug() << "Socket Error!";
- //emit error(err);
}
void Server::socketConnected( ) {
- emit connected(network);
+ emit connected(networkId());
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()));
}
void Server::socketDisconnected( ) {
- //qDebug() << "Socket disconnected!";
- emit disconnected(network);
- topics.clear();
- nicks.clear();
+ emit disconnected(networkId());
+ // propagate to networkInfo, so we can clear up
}
void Server::socketStateChanged(QAbstractSocket::SocketState state) {
//qDebug() << "Socket state changed: " << state;
}
-QString Server::updateNickFromMask(QString mask) {
- QString user = userFromMask(mask);
- QString host = hostFromMask(mask);
- QString nick = nickFromMask(mask);
- if(nicks.contains(nick) && !user.isEmpty() && !host.isEmpty()) {
- QVariantMap n = nicks[nick];
- if(n["User"].toString() != user || n["Host"].toString() != host) {
- if(!n["User"].toString().isEmpty() || !n["Host"].toString().isEmpty())
- qWarning(QString("Strange: Hostmask for nick %1 has changed!").arg(nick).toAscii());
- n["User"] = user; n["Host"] = host;
- nicks[nick] = n;
- emit nickUpdated(network, nick, n);
- }
- }
- return nick;
-}
-
-void Server::userInput(QString net, QString buf, QString msg) {
- if(net != network) return; // not me!
- //msg = msg.trimmed(); // remove whitespace from start and end
- if(msg.isEmpty()) return;
- if(!msg.startsWith('/')) {
- msg = QString("/SAY ") + msg;
- }
- handleUserInput(buf, msg);
+void Server::userInput(uint netid, QString buf, QString msg) {
+ if(netid != networkId())
+ return; // not me!
+ userInputHandler()->handleUserInput(buf, msg);
}
void Server::putRawLine(QString s) {
-// qDebug() << "SentRaw: " << s;
s += "\r\n";
socket.write(s.toAscii());
}
void Server::putCmd(QString cmd, QStringList params, QString prefix) {
- QString m;
- if(!prefix.isEmpty()) m += ":" + prefix + " ";
- m += cmd.toUpper();
- for(int i = 0; i < params.size() - 1; i++) {
- m += " " + params[i];
- }
- if(!params.isEmpty()) m += " :" + params.last();
-// qDebug() << "Sent: " << m;
- m += "\r\n";
- socket.write(m.toAscii());
-}
-
-/*! Handle a raw message string sent by the server. We try to find a suitable handler, otherwise we call a default handler. */
-void Server::handleServerMsg(QByteArray rawmsg) {
- try {
- if(rawmsg.isEmpty()) {
- qWarning() << "Received empty string from server!";
- return;
- }
- // TODO Implement encoding conversion
- /* At this point, we have a raw message as a byte array. This needs to be converted to a QString somewhere.
- * Problem is, that at this point we don't know which encoding to use for the various parts of the message.
- * This is something the command handler needs to take care of (e.g. PRIVMSG needs to first parse for CTCP,
- * and then convert the raw strings into the correct encoding.
- * We _can_ safely assume Server encoding for prefix and cmd, but not for the params. Therefore, we need to
- * change from a QStringList to a QList<QByteArray> in all the handlers, and have the handlers call decodeString
- * where needed...
- */
- QString msg = QString::fromLatin1(rawmsg);
-
- // OK, first we split the raw message into its various parts...
- QString prefix = "";
- QString cmd;
- QStringList params;
-
- // check for prefix by checking for a colon as the first char
- if(msg[0] == ':') {
- msg.remove(0,1);
- prefix = msg.section(' ', 0, 0);
- msg = msg.section(' ', 1);
- }
-
- // next string without a whitespace is the command
- cmd = msg.section(' ', 0, 0).toUpper();
- msg = msg.mid(cmd.length());
-
- // get the parameters
- QString trailing = "";
- if(msg.contains(" :")) {
- trailing = msg.section(" :", 1);
- msg = msg.section(" :", 0, 0);
- }
- if(!msg.isEmpty()) {
- params << msg.split(' ', QString::SkipEmptyParts);
- }
- if(!trailing.isEmpty()) {
- params << trailing;
- }
-
- // numeric replies have the target as first param (RFC 2812 - 2.4). this is usually our own nick. Remove this!
- uint num = cmd.toUInt();
- if(num > 0) {
- Q_ASSERT(params.count() > 0); // Violation to RFC
- params.removeFirst();
- }
-
- // Now we try to find a handler for this message. BTW, I do love the Trolltech guys ;-)
- QString hname = cmd.toLower();
- hname[0] = hname[0].toUpper();
- hname = "handleServer" + hname;
- if(!QMetaObject::invokeMethod(this, hname.toAscii(), Q_ARG(QString, prefix), Q_ARG(QStringList, params))) {
- // Ok. Default handler it is.
- defaultServerHandler(cmd, prefix, params);
- }
- } catch(Exception e) {
- emit displayMsg(Message::Error, "", e.msg());
- }
-}
-
-void Server::defaultServerHandler(QString cmd, QString prefix, QStringList params) {
- uint num = cmd.toUInt();
- if(num) {
- // A lot of server messages don't really need their own handler because they don't do much.
- // Catch and handle these here.
- 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);
- break;
- // Server error messages without param, just display them
- case 409: case 411: case 412: case 422: case 424: 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:
- case 431: // ERR_NONICKNAMEGIVEN
- 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 442:
- { QString p = params.takeFirst();
- 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 441: case 444: case 461:
- case 467: case 471: case 473: case 474: case 475: case 476: case 477: case 478: case 482:
- case 436: // ERR_NICKCOLLISION
- { QString p = params.takeFirst();
- emit displayMsg(Message::Error, "", p + ": " + params.join(" "));
- break;
- }
- // Ignore these commands.
- case 366: case 376:
- break;
-
- // Everything else will be marked in red, so we can add them somewhere.
- default:
- emit displayMsg(Message::Error, "", cmd + " " + params.join(" "), prefix);
- }
- //qDebug() << prefix <<":"<<cmd<<params;
- } else {
- emit displayMsg(Message::Error, "", QString("Unknown: ") + cmd + " " + params.join(" "), prefix);
- //qDebug() << prefix <<":"<<cmd<<params;
- }
-}
-
-void Server::handleUserInput(QString bufname, QString usrMsg) {
- try {
- /* Looks like we don't need core-side buffers...
- Buffer *buffer = 0;
- if(!bufname.isEmpty()) {
- Q_ASSERT(buffers.contains(bufname));
- buffer = buffers[bufname];
- }
- */
- QString cmd = usrMsg.section(' ', 0, 0).remove(0, 1).toUpper();
- QString msg = usrMsg.section(' ', 1);
- QString hname = cmd.toLower();
- hname[0] = hname[0].toUpper();
- hname = "handleUser" + hname;
- if(!QMetaObject::invokeMethod(this, hname.toAscii(), Q_ARG(QString, bufname), Q_ARG(QString, msg))) {
- // Ok. Default handler it is.
- defaultUserHandler(bufname, cmd, msg);
- }
- } catch(Exception e) {
- emit displayMsg(Message::Error, "", e.msg());
- }
-}
-
-void Server::defaultUserHandler(QString bufname, QString cmd, QString msg) {
- emit displayMsg(Message::Error, "", QString("Error: %1 %2").arg(cmd).arg(msg));
-
-}
-
-QStringList Server::providesUserHandlers() {
- QStringList userHandlers;
- for(int i=0; i < metaObject()->methodCount(); i++) {
- QString methodSignature(metaObject()->method(i).signature());
- if (methodSignature.startsWith("handleUser")) {
- methodSignature = methodSignature.section('(',0,0); // chop the attribute list
- methodSignature = methodSignature.mid(10); // strip "handleUser"
- userHandlers << methodSignature;
- }
- }
- return userHandlers;
-}
-
-QString Server::ctcpDequote(QString message) {
- QString dequotedMessage;
- QString messagepart;
- QHash<QString, QString>::iterator ctcpquote;
-
- // copy dequote Message
- for(int i = 0; i < message.size(); i++) {
- messagepart = message[i];
- if(i+1 < message.size()) {
- for(ctcpquote = ctcpMDequoteHash.begin(); ctcpquote != ctcpMDequoteHash.end(); ++ctcpquote) {
- if(message.mid(i,2) == ctcpquote.key()) {
- dequotedMessage += ctcpquote.value();
- i++;
- break;
- }
- }
- }
- dequotedMessage += messagepart;
- }
- return dequotedMessage;
-}
-
-
-QString Server::ctcpXdelimDequote(QString message) {
- QString dequotedMessage;
- QString messagepart;
- QHash<QString, QString>::iterator xdelimquote;
-
- for(int i = 0; i < message.size(); i++) {
- messagepart = message[i];
- if(i+1 < message.size()) {
- for(xdelimquote = ctcpXDelimDequoteHash.begin(); xdelimquote != ctcpXDelimDequoteHash.end(); ++xdelimquote) {
- if(message.mid(i,2) == xdelimquote.key()) {
- messagepart = xdelimquote.value();
- i++;
- break;
- }
- }
- }
- dequotedMessage += messagepart;
- }
- return dequotedMessage;
-}
-
-QStringList Server::parseCtcp(CtcpType ctcptype, QString prefix, QString target, QString message) {
- QStringList messages;
- QString ctcp;
-
- //lowlevel message dequote
- QString dequotedMessage = ctcpDequote(message);
+ QString msg;
+ if(!prefix.isEmpty())
+ msg += ":" + prefix + " ";
+ msg += cmd.toUpper();
- // extract tagged / extended data
- while(dequotedMessage.contains(XDELIM)) {
- messages << dequotedMessage.section(XDELIM,0,0);
- ctcp = ctcpXdelimDequote(dequotedMessage.section(XDELIM,1,1));
- dequotedMessage = dequotedMessage.section(XDELIM,2,2);
-
- //dispatch the ctcp command
- QString ctcpcmd = ctcp.section(' ', 0, 0);
- QString ctcpparam = ctcp.section(' ', 1);
-
- QString hname = ctcpcmd.toLower();
- hname[0] = hname[0].toUpper();
- hname = "handleCtcp" + hname;
- if(!QMetaObject::invokeMethod(this, hname.toAscii(), Q_ARG(CtcpType, ctcptype), Q_ARG(QString, prefix), Q_ARG(QString, target), Q_ARG(QString, ctcpparam))) {
- // Ok. Default handler it is.
- defaultCtcpHandler(ctcptype, prefix, ctcpcmd, target, ctcpparam);
- }
- }
- if(!dequotedMessage.isEmpty()) {
- messages << dequotedMessage;
+ for(int i = 0; i < params.size() - 1; i++) {
+ msg += " " + params[i];
}
- return messages;
-}
-
-QString Server::ctcpPack(QString ctcpTag, QString message) {
- return XDELIM + ctcpTag + ' ' + message + XDELIM;
-}
-
-void Server::ctcpQuery(QString bufname, QString ctcpTag, QString message) {
- QStringList params;
- params << bufname << ctcpPack(ctcpTag, message);
- putCmd("PRIVMSG", params);
-}
-
-void Server::ctcpReply(QString bufname, QString ctcpTag, QString message) {
- QStringList params;
- params << bufname << ctcpPack(ctcpTag, message);
- putCmd("NOTICE", params);
-}
-
-/**********************************************************************************/
-
-/*
-void Server::handleUser(QString bufname, QString msg) {
-
-
-}
-*/
-
-void Server::handleUserAway(QString bufname, QString msg) {
- putCmd("AWAY", QStringList(msg));
-}
-
-void Server::handleUserDeop(QString bufname, QString msg) {
- QStringList nicks = msg.split(' ', QString::SkipEmptyParts);
- QString m = "-"; for(int i = 0; i < nicks.count(); i++) m += 'o';
- QStringList params;
- params << bufname << m << nicks;
- putCmd("MODE", params);
-}
-
-void Server::handleUserDevoice(QString bufname, QString msg) {
- QStringList nicks = msg.split(' ', QString::SkipEmptyParts);
- QString m = "-"; for(int i = 0; i < nicks.count(); i++) m += 'v';
- QStringList params;
- params << bufname << m << nicks;
- putCmd("MODE", params);
-}
-
-void Server::handleUserInvite(QString bufname, QString msg) {
- QStringList params;
- params << msg << bufname;
- putCmd("INVITE", params);
-}
-
-void Server::handleUserJoin(QString bufname, QString msg) {
- putCmd("JOIN", QStringList(msg));
-}
-
-void Server::handleUserKick(QString bufname, QString msg) {
- QStringList params;
- params << bufname << msg.split(' ', QString::SkipEmptyParts);
- putCmd("KICK", params);
-}
-
-void Server::handleUserList(QString bufname, QString msg) {
- putCmd("LIST", msg.split(' ', QString::SkipEmptyParts));
-}
-
-void Server::handleUserMode(QString bufname, QString msg) {
- putCmd("MODE", msg.split(' ', QString::SkipEmptyParts));
-}
-
-// TODO: show privmsgs
-void Server::handleUserMsg(QString bufname, QString msg) {
- QString nick = msg.section(" ", 0, 0);
- msg = msg.section(" ", 1);
- if(nick.isEmpty() || msg.isEmpty()) return;
- QStringList params;
- params << nick << msg;
- putCmd("PRIVMSG", params);
-}
-
-void Server::handleUserNick(QString bufname, QString msg) {
- QString nick = msg.section(' ', 0, 0);
- putCmd("NICK", QStringList(nick));
-}
-
-void Server::handleUserOp(QString bufname, QString msg) {
- QStringList nicks = msg.split(' ', QString::SkipEmptyParts);
- QString m = "+"; for(int i = 0; i < nicks.count(); i++) m += 'o';
- QStringList params;
- params << bufname << m << nicks;
- putCmd("MODE", params);
-}
-
-void Server::handleUserPart(QString bufname, QString msg) {
- QStringList params;
- params << bufname << msg;
- putCmd("PART", params);
-}
+ if(!params.isEmpty())
+ msg += " :" + params.last();
-// TODO: implement queries
-void Server::handleUserQuery(QString bufname, QString msg) {
- QString nick = msg.section(' ', 0, 0);
- if(!nick.isEmpty()) emit queryRequested(network, nick);
-}
-
-void Server::handleUserQuit(QString bufname, QString msg) {
- putCmd("QUIT", QStringList(msg));
-}
-
-void Server::handleUserQuote(QString bufname, QString msg) {
putRawLine(msg);
}
-void Server::handleUserSay(QString bufname, QString msg) {
- if(bufname.isEmpty()) return; // server buffer
- QStringList params;
- params << bufname << msg;
- putCmd("PRIVMSG", params);
- if(isChannelName(bufname)) {
- emit displayMsg(Message::Plain, params[0], msg, ownNick, Message::Self);
- } else {
- emit displayMsg(Message::Plain, params[0], msg, ownNick, Message::Self|Message::PrivMsg);
- }
-}
-
-void Server::handleUserMe(QString bufname, QString msg) {
- if(bufname.isEmpty()) return; // server buffer
- ctcpQuery(bufname, "ACTION", msg);
- emit displayMsg(Message::Action, bufname, msg, ownNick);
-}
-
-void Server::handleUserTopic(QString bufname, QString msg) {
- if(bufname.isEmpty()) return;
- QStringList params;
- params << bufname << msg;
- putCmd("TOPIC", params);
-}
-
-void Server::handleUserVoice(QString bufname, QString msg) {
- QStringList nicks = msg.split(' ', QString::SkipEmptyParts);
- QString m = "+"; for(int i = 0; i < nicks.count(); i++) m += 'v';
- QStringList params;
- params << bufname << m << nicks;
- putCmd("MODE", params);
-}
-
-/**********************************************************************************/
-
-void Server::handleServerJoin(QString prefix, QStringList params) {
- Q_ASSERT(params.count() == 1);
- QString nick = updateNickFromMask(prefix);
- emit displayMsg(Message::Join, params[0], params[0], prefix);
- if(nick == ownNick) {
- // Q_ASSERT(!buffers.contains(params[0])); // cannot join a buffer twice!
- // Buffer *buf = new Buffer(params[0]);
- // buffers[params[0]] = buf;
- topics[params[0]] = "";
- emit topicSet(network, params[0], "");
- } //else {
- QVariantMap n;
- if(nicks.contains(nick)) {
- n = nicks[nick];
- QVariantMap chans = n["Channels"].toMap();
- // Q_ASSERT(!chans.keys().contains(params[0])); TODO uncomment
- chans[params[0]] = QVariantMap();
- n["Channels"] = chans;
- nicks[nick] = n;
- emit nickUpdated(network, nick, n);
- } else {
- QVariantMap chans;
- chans[params[0]] = QVariantMap();
- n["Channels"] = chans;
- n["User"] = userFromMask(prefix);
- n["Host"] = hostFromMask(prefix);
- nicks[nick] = n;
- emit nickAdded(network, nick, n);
- }
- //emit displayMsg(Message::Join, params[0], params[0], prefix);
- //}
-}
-
-void Server::handleServerKick(QString prefix, QStringList params) {
- QString kicker = updateNickFromMask(prefix);
- QString nick = params[1];
- Q_ASSERT(nicks.contains(nick));
- QVariantMap n = nicks[nick];
- QVariantMap chans = n["Channels"].toMap();
- Q_ASSERT(chans.contains(params[0]));
- chans.remove(params[0]);
- QString msg = nick;
- if(params.count() > 2) msg = QString("%1 %2").arg(msg).arg(params[2]);
- emit displayMsg(Message::Kick, params[0], msg, prefix);
- if(chans.count() > 0) {
- n["Channels"] = chans;
- nicks[nick] = n;
- emit nickUpdated(network, nick, n);
- } else {
- nicks.remove(nick);
- emit nickRemoved(network, nick);
- }
- if(nick == ownNick) {
- topics.remove(params[0]);
- }
-}
-
-void Server::handleServerMode(QString prefix, QStringList params) {
- if(isChannelName(params[0])) {
- // TODO only channel-user modes supported by now
- QString prefixes = serverSupports["PrefixModes"].toString();
- QString modes = params[1];
- int p = 2;
- int m = 0;
- bool add = true;
- while(m < modes.length()) {
- if(modes[m] == '+') { add = true; m++; continue; }
- if(modes[m] == '-') { add = false; m++; continue; }
- if(prefixes.contains(modes[m])) { // it's a user channel mode
- Q_ASSERT(params.count() > m);
- QString nick = params[p++];
- if(nicks.contains(nick)) { // sometimes, a server might try to set a MODE on a nick that is no longer there
- QVariantMap n = nicks[nick]; QVariantMap clist = n["Channels"].toMap(); QVariantMap chan = clist[params[0]].toMap();
- QString mstr = chan["Mode"].toString();
- add ? mstr += modes[m] : mstr.remove(modes[m]);
- chan["Mode"] = mstr; clist[params[0]] = chan; n["Channels"] = clist; nicks[nick] = n;
- emit nickUpdated(network, nick, n);
- }
- m++;
- } else {
- // TODO add more modes
- m++;
- }
- }
- emit displayMsg(Message::Mode, params[0], params.join(" "), prefix);
- } else {
- //Q_ASSERT(nicks.contains(params[0]));
- //QVariantMap n = nicks[params[0]].toMap();
- //QString mode = n["Mode"].toString();
- emit displayMsg(Message::Mode, "", params.join(" "));
- }
-}
-
-void Server::handleServerNick(QString prefix, QStringList params) {
- QString oldnick = updateNickFromMask(prefix);
- QString newnick = params[0];
- QVariantMap v = nicks.take(oldnick);
- nicks[newnick] = v;
- QVariantMap 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); }
- }
- emit nickRenamed(network, oldnick, newnick);
- if(oldnick == ownNick) {
- ownNick = newnick;
- emit ownNickSet(network, newnick);
- }
-}
-
-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);
-}
-
-void Server::handleServerPart(QString prefix, QStringList params) {
- QString nick = updateNickFromMask(prefix);
- Q_ASSERT(nicks.contains(nick));
- QVariantMap n = nicks[nick];
- QVariantMap chans = n["Channels"].toMap();
- Q_ASSERT(chans.contains(params[0]));
- chans.remove(params[0]);
- QString msg;
- if(params.count() > 1) msg = params[1];
- emit displayMsg(Message::Part, params[0], msg, prefix);
- if(chans.count() > 0) {
- n["Channels"] = chans;
- nicks[nick] = n;
- emit nickUpdated(network, nick, n);
- } else {
- nicks.remove(nick);
- emit nickRemoved(network, nick);
- }
- if(nick == ownNick) {
- Q_ASSERT(topics.contains(params[0]));
- topics.remove(params[0]);
- }
-}
-
-void Server::handleServerPing(QString prefix, QStringList params) {
- putCmd("PONG", 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);
- else {
- // it's possible to pack multiple privmsgs into one param using ctcp
- QStringList messages = parseCtcp(Server::CtcpQuery, prefix, params[0], params[1]);
- if(params[0].toLower() == ownNick.toLower()) { // Freenode sends nickname in lower case!
- foreach(QString message, messages) {
- if(!message.isEmpty()) {
- emit displayMsg(Message::Plain, "", message, prefix, Message::PrivMsg);
- }
- }
-
- } else {
- //qDebug() << prefix << params;
- Q_ASSERT(isChannelName(params[0])); // should be channel!
- foreach(QString message, messages) {
- if(!message.isEmpty()) {
- emit displayMsg(Message::Plain, params[0], message, prefix);
- }
- }
- }
- }
-}
-
-void Server::handleServerQuit(QString prefix, QStringList params) {
- QString nick = updateNickFromMask(prefix);
- Q_ASSERT(nicks.contains(nick));
- QVariantMap chans = nicks[nick]["Channels"].toMap();
- QString msg;
- if(params.count()) msg = params[0];
- foreach(QString c, chans.keys()) {
- emit displayMsg(Message::Quit, c, msg, prefix);
- }
- nicks.remove(nick);
- emit nickRemoved(network, nick);
-}
-
-void Server::handleServerTopic(QString prefix, QStringList params) {
- QString nick = updateNickFromMask(prefix);
- 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]));
-}
-
-/* RPL_WELCOME */
-void Server::handleServer001(QString prefix, QStringList params) {
- // there should be only one param: "Welcome to the Internet Relay Network <nick>!<user>@<host>"
- currentServer = prefix;
- ownNick = params[0].section(' ', -1, -1).section('!', 0, 0);
- QVariantMap n;
- n["Channels"] = QVariantMap();
- nicks[ownNick] = n;
- emit ownNickSet(network, ownNick);
- emit nickAdded(network, ownNick, QVariantMap());
- emit displayMsg(Message::Server, "", params[0], prefix);
- // send performlist
- QStringList performList = networkSettings["Perform"].toString().split( "\n" );
- int count = performList.count();
- for(int a = 0; a < count; a++) {
- if(!performList[a].isEmpty() ) {
- userInput(network, "", performList[a]);
- }
- }
-}
-
-/* RPL_ISUPPORT */
-// TODO Complete 005 handling, also use sensible defaults for non-sent stuff
-void Server::handleServer005(QString prefix, QStringList params) {
- //qDebug() << prefix << params;
- params.removeLast();
- foreach(QString p, params) {
- QString key = p.section("=", 0, 0);
- QString val = p.section("=", 1);
- serverSupports[key] = val;
- // handle some special cases
- if(key == "PREFIX") {
- QVariantMap foo; QString modes, prefixes;
- Q_ASSERT(val.contains(')') && val.startsWith('('));
- int m = 1, p;
- for(p = 2; p < val.length(); p++) if(val[p] == ')') break;
- p++;
- for(; val[m] != ')'; m++, p++) {
- Q_ASSERT(p < val.length());
- foo[QString(val[m])] = QString(val[p]);
- modes += val[m]; prefixes += val[p];
- }
- serverSupports["PrefixModes"] = modes; serverSupports["Prefixes"] = prefixes;
- serverSupports["ModePrefixMap"] = foo;
- }
- }
-}
-
-
-/* RPL_NOTOPIC */
-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]));
-}
-
-/* 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]));
-}
-
-/* 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()));
-}
-
-/* RPL_NAMREPLY */
-void Server::handleServer353(QString prefix, QStringList params) {
- params.removeFirst(); // = or *
- QString buf = params.takeFirst();
- QString prefixes = serverSupports["Prefixes"].toString();
- foreach(QString nick, params[0].split(' ')) {
- QString mode = "", pfx = "";
- if(prefixes.contains(nick[0])) {
- pfx = nick[0];
- for(int i = 0;; i++)
- if(prefixes[i] == nick[0]) { mode = serverSupports["PrefixModes"].toString()[i]; break; }
- nick.remove(0,1);
- }
- QVariantMap c; c["Mode"] = mode; c["Prefix"] = pfx;
- if(nicks.contains(nick)) {
- QVariantMap n = nicks[nick];
- QVariantMap chans = n["Channels"].toMap();
- chans[buf] = c;
- n["Channels"] = chans;
- nicks[nick] = n;
- emit nickUpdated(network, nick, n);
- } else {
- QVariantMap n; QVariantMap c; QVariantMap chans;
- c["Mode"] = mode;
- chans[buf] = c;
- n["Channels"] = chans;
- nicks[nick] = n;
- emit nickAdded(network, nick, n);
- }
- }
-}
-
-/* ERR_ERRONEUSNICKNAME */
-void Server::handleServer432(QString prefix, QStringList params) {
- if(params.size() < 2) {
- // handle unreal-ircd bug, where unreal ircd doesnt supply a TARGET in ERR_ERRONEUSNICKNAME during registration phase:
- // nick @@@
- // :irc.scortum.moep.net 432 @@@ :Erroneous Nickname: Illegal characters
- // correct server reply:
- // :irc.scortum.moep.net 432 * @@@ :Erroneous Nickname: Illegal characters
- emit displayMsg(Message::Error, "", tr("There is a nickname in your identity's nicklist which contains illegal characters"));
- emit displayMsg(Message::Error, "", tr("Due to a bug in Unreal IRCd (and maybe other irc-servers too) we're unable to determine the erroneous nick"));
- emit displayMsg(Message::Error, "", tr("Please use: /nick <othernick> to continue or clean up your nicklist"));
- } else {
- QString errnick = params[0];
- emit displayMsg(Message::Error, "", tr("Nick %1 contains illegal characters").arg(errnick));
- // if there is a problem while connecting to the server -> we handle it
- // TODO rely on another source...
- if(currentServer.isEmpty()) {
- QStringList desiredNicks = identity["NickList"].toStringList();
- int nextNick = desiredNicks.indexOf(errnick) + 1;
- if (desiredNicks.size() > nextNick) {
- putCmd("NICK", QStringList(desiredNicks[nextNick]));
- } else {
- emit displayMsg(Message::Error, "", tr("No free and valid nicks in nicklist found. use: /nick <othernick> to continue"));
- }
- }
- }
-}
-
-/* ERR_NICKNAMEINUSE */
-void Server::handleServer433(QString prefix, QStringList params) {
- QString errnick = params[0];
- 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()) {
- QStringList desiredNicks = identity["NickList"].toStringList();
- int nextNick = desiredNicks.indexOf(errnick) + 1;
- if (desiredNicks.size() > nextNick) {
- putCmd("NICK", QStringList(desiredNicks[nextNick]));
- } else {
- emit displayMsg(Message::Error, "", tr("No free and valid nicks in nicklist found. use: /nick <othernick> to continue"));
- }
- }
-}
-
-/***********************************************************************************/
-// CTCP HANDLER
-void Server::handleCtcpAction(CtcpType ctcptype, QString prefix, QString target, QString param) {
- emit displayMsg(Message::Action, target, param, prefix);
-}
-
-void Server::handleCtcpPing(CtcpType ctcptype, QString prefix, QString target, QString param) {
- if(ctcptype == CtcpQuery) {
- ctcpReply(nickFromMask(prefix), "PING", param);
- emit displayMsg(Message::Server, "", tr("Received CTCP PING request by %1").arg(prefix));
- } else {
- // display ping answer
- }
+uint Server::networkId() const {
+ return _networkId;
}
-void Server::handleCtcpVersion(CtcpType ctcptype, QString prefix, QString target, QString param) {
- if(ctcptype == CtcpQuery) {
- // FIXME use real Info about quassel :)
- //ctcpReply(nickFromMask(prefix), "VERSION", QString("Quassel:pre Release:*nix"));
- ctcpReply(nickFromMask(prefix), "VERSION", QString("Quassel IRC (Pre-Release) - http://www.quassel-irc.org"));
- emit displayMsg(Message::Server, "", tr("Received CTCP VERSION request by %1").arg(prefix));
- } else {
- // TODO display Version answer
- }
+QString Server::networkName() {
+ return networkInfo()->networkName();
}
-void Server::defaultCtcpHandler(CtcpType ctcptype, QString prefix, QString cmd, QString target, QString param) {
- emit displayMsg(Message::Error, "", tr("Received unknown CTCP %1 by %2").arg(cmd).arg(prefix));
+CoreSession *Server::coreSession() const {
+ return Core::session(userId());
}
-
-/***********************************************************************************/
-
/* Exception classes for message handling */
Server::ParseError::ParseError(QString cmd, QString prefix, QStringList params) {
_msg = QString("Command Parse Error: ") + cmd + params.join(" ");
-
}
Server::UnknownCmdError::UnknownCmdError(QString cmd, QString prefix, QStringList params) {
_msg = QString("Unknown Command: ") + cmd;
-
}
#include <QTimer>
#include "message.h"
-#include "serverinfo.h"
+#include "signalproxy.h"
+class NetworkInfo;
+
+class IrcServerHandler;
+class UserInputHandler;
+class CtcpHandler;
+class CoreSession;
/*!
* This is a server object, managing a single connection to an IRC server, handling the associated channels and so on.
class Server : public QThread {
Q_OBJECT
- public:
- Server(UserId uid, QString network);
- ~Server();
-
- UserId userId() const { return user; }
- // serverState state();
- bool isConnected() const { return socket.state() == QAbstractSocket::ConnectedState; }
- QString getNetwork() { return network; }
- QStringList providesUserHandlers();
-
- enum CtcpType {CtcpQuery, CtcpReply};
-
- public slots:
- // void setServerOptions();
- void sendState();
- void connectToIrc(QString net);
- void disconnectFromIrc(QString net);
- void userInput(QString net, QString buffer, QString msg);
-
- void putRawLine(QString input);
- void putCmd(QString cmd, QStringList params, QString prefix = 0);
-
- //void exitThread();
-
- signals:
- void serverState(QString net, QVariantMap data);
- void recvRawServerMsg(QString);
- void displayStatusMsg(QString);
- //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);
-
- void nickAdded(QString network, QString nick, QVariantMap props);
- void nickRenamed(QString network, QString oldnick, QString newnick);
- void nickRemoved(QString network, QString nick);
- void nickUpdated(QString network, QString nick, QVariantMap props);
- void modeSet(QString network, QString target, QString mode);
- void topicSet(QString network, QString buffer, QString topic);
- void ownNickSet(QString network, QString newNick);
- void queryRequested(QString network, QString nick);
-
-
- private slots:
- void run();
- void socketHasData();
- void socketError(QAbstractSocket::SocketError);
- void socketConnected();
- void socketDisconnected();
- void socketStateChanged(QAbstractSocket::SocketState);
-
- /* Message Handlers */
-
- /* void handleUser(QString, QString); */
- void handleUserAway(QString, QString);
- void handleUserDeop(QString, QString);
- void handleUserDevoice(QString, QString);
- void handleUserInvite(QString, QString);
- void handleUserJoin(QString, QString);
- void handleUserKick(QString, QString);
- void handleUserList(QString, QString);
- void handleUserMode(QString, QString);
- void handleUserMsg(QString, QString);
- void handleUserNick(QString, QString);
- void handleUserOp(QString, QString);
- void handleUserPart(QString, QString);
- void handleUserQuery(QString, QString);
- void handleUserQuit(QString, QString);
- void handleUserQuote(QString, QString);
- void handleUserSay(QString, QString);
- void handleUserTopic(QString, QString);
- void handleUserVoice(QString, QString);
- void handleUserMe(QString, QString);
-
- /* void handleServer(QString, QStringList); */
- void handleServerJoin(QString, QStringList);
- void handleServerKick(QString, QStringList);
- void handleServerMode(QString, QStringList);
- void handleServerNick(QString, QStringList);
- void handleServerNotice(QString, QStringList);
- void handleServerPart(QString, QStringList);
- void handleServerPing(QString, QStringList);
- void handleServerPrivmsg(QString, QStringList);
- void handleServerQuit(QString, QStringList);
- void handleServerTopic(QString, QStringList);
-
- void handleServer001(QString, QStringList); // RPL_WELCOME
- void handleServer005(QString, QStringList); // RPL_ISUPPORT
- void handleServer331(QString, QStringList); // RPL_NOTOPIC
- void handleServer332(QString, QStringList); // RPL_TOPIC
- void handleServer333(QString, QStringList); // Topic set by...
- void handleServer353(QString, QStringList); // RPL_NAMREPLY
- void handleServer432(QString, QStringList); // ERR_ERRONEUSNICKNAME
- void handleServer433(QString, QStringList); // ERR_NICKNAMEINUSE
-
- void handleCtcpAction(CtcpType, QString, QString, QString);
- void handleCtcpPing(CtcpType, QString, QString, QString);
- void handleCtcpVersion(CtcpType, QString, QString, QString);
-
- void defaultServerHandler(QString cmd, QString prefix, QStringList params);
- void defaultUserHandler(QString buf, QString cmd, QString msg);
- void defaultCtcpHandler(CtcpType ctcptype, QString prefix, QString cmd, QString target, QString param);
-
- private:
- UserId user;
- QString network;
- QTcpSocket socket;
- //QHash<QString, Buffer*> buffers;
-
- QString ownNick;
- QString currentServer;
- QVariantMap networkSettings;
- QVariantMap identity;
- QHash<QString, QVariantMap> nicks; // stores all known nicks for the server
- QHash<QString, QString> topics; // stores topics for each buffer
- QVariantMap serverSupports; // stores results from RPL_ISUPPORT
-
- void handleServerMsg(QByteArray rawMsg);
- void handleUserInput(QString buffer, QString usrMsg);
-
- // CTCP Stuff
- QString XDELIM;
- QHash<QString, QString> ctcpMDequoteHash;
- QHash<QString, QString> ctcpXDelimDequoteHash;
- QString ctcpDequote(QString);
- QString ctcpXdelimDequote(QString);
- QStringList parseCtcp(CtcpType, QString, QString, QString);
-
- QString ctcpPack(QString ctcpTag, QString message);
- void ctcpQuery(QString bufname, QString ctcpTag, QString message);
- void ctcpReply(QString bufname, QString ctcpTag, QString message);
-
- QString updateNickFromMask(QString mask);
+public:
+ Server(UserId uid, uint networkId, QString network);
+ ~Server();
+
+ UserId userId() const { return _userId; }
+
+ // serverState state();
+ bool isConnected() const { return socket.state() == QAbstractSocket::ConnectedState; }
+
+ uint networkId() const;
+ QString networkName(); // hasbeen getNetwork()
+
+ NetworkInfo *networkInfo() { return _networkInfo; }
+ IrcServerHandler *ircServerHandler() {return _ircServerHandler; }
+ UserInputHandler *userInputHandler() {return _userInputHandler; }
+ CtcpHandler *ctcpHandler() {return _ctcpHandler; }
+
+public slots:
+ // void setServerOptions();
+ void connectToIrc(QString net);
+ void disconnectFromIrc(QString net);
+ void userInput(uint netid, QString buffer, QString msg);
+
+ void putRawLine(QString input);
+ void putCmd(QString cmd, QStringList params, QString prefix = 0);
+
+ //void exitThread();
+
+signals:
+ void serverState(QString net, QVariantMap data);
+ void recvRawServerMsg(QString);
+ void displayStatusMsg(QString);
+ //void displayMsg(Message msg);
+ void displayMsg(Message::Type, QString target, QString text, QString sender = "", quint8 flags = Message::None);
+ void connected(uint networkId);
+ void disconnected(uint networkId);
- class ParseError : public Exception {
- public:
- ParseError(QString cmd, QString prefix, QStringList params);
- };
+ void synchronizeClients();
+
+ void queryRequested(QString network, QString nick);
- class UnknownCmdError : public Exception {
- public:
- UnknownCmdError(QString cmd, QString prefix, QStringList params);
- };
+
+private slots:
+ void run();
+ void socketHasData();
+ void socketError(QAbstractSocket::SocketError);
+ void socketConnected();
+ void socketDisconnected();
+ void socketStateChanged(QAbstractSocket::SocketState);
+
+private:
+ UserId _userId;
+ uint _networkId;
+
+ QTcpSocket socket;
+
+ IrcServerHandler *_ircServerHandler;
+ UserInputHandler *_userInputHandler;
+ CtcpHandler *_ctcpHandler;
+
+ NetworkInfo *_networkInfo;
+
+ QVariantMap networkSettings;
+ QVariantMap identity;
+
+ CoreSession *coreSession() const;
+
+ class ParseError : public Exception {
+ public:
+ ParseError(QString cmd, QString prefix, QStringList params);
+ };
+
+ class UnknownCmdError : public Exception {
+ public:
+ UnknownCmdError(QString cmd, QString prefix, QStringList params);
+ };
- // stuff needed for new separation of server information
- ServerInfo *serverinfo;
};
#endif
+++ /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 "serverinfo.h"
-
-ServerInfo::ServerInfo(QObject *parent)
- : QObject(parent) {
-}
-
-ServerInfo::~ServerInfo() {
-}
-
-void ServerInfo::setNetworkname(const QString &networkname) {
- networkname_ = networkname;
-}
-
-QString ServerInfo::networkname() const {
- return networkname_;
-}
-
-void ServerInfo::setCurrentServer(const QString ¤tServer) {
- currentServer_ = currentServer;
-}
-
-QString ServerInfo::currentServer() const {
- return currentServer_;
-}
-
-void ServerInfo::setOwnNick(const QString &ownnick) {
- ownNick_ = ownnick;
-}
-
-QString ServerInfo::ownNick() const {
- return ownNick_;
-}
-
-QList<IrcUser *> ServerInfo::ircUsers() const {
- return ircUsers_.values();
-}
-
-
-IrcUser *ServerInfo::newIrcUser(const QString &hostmask) {
- IrcUser *ircuser = new IrcUser(hostmask);
- return ircUsers_[ircuser->nick()] = ircuser;
-}
-
-IrcUser *ServerInfo::ircUser(const QString &nickname) const {
- if(ircUsers_.contains(nickname))
- return ircUsers_[nickname];
- else
- throw NoSuchNickException();
-}
-
-void ServerInfo::setTopics(const QHash<QString, QString> &topics) {
- topics_ = topics;
-}
-
-QHash<QString, QString> ServerInfo::topics() const {
- return topics_;
-}
-
-void ServerInfo::updateTopic(const QString &channel, const QString &topic) {
- topics_[channel] = topic;
-}
-
-QString ServerInfo::topic(const QString &channel) const {
- if(topics_.contains(channel))
- return topics_[channel];
- else
- throw NoSuchChannelException();
-}
-
-void ServerInfo::setSupports(const QHash<QString, QString> &supports) {
- supports_ = supports;
-}
-
-QHash<QString, QString> ServerInfo::supports() const {
- return supports_;
-}
-
-QString ServerInfo::supports(const QString &feature) const {
- if(supports_.contains(feature))
- return supports_[feature];
- else
- throw UnsupportedFeatureException();
-}
-
-bool ServerInfo::isOwnNick(const QString &nick) const {
- return (ownNick_.toLower() == nick.toLower());
-}
-
-bool ServerInfo::isOwnNick(const IrcUser &ircuser) const {
- return (ircuser.nick().toLower() == ownNick_.toLower());
-}
-
-
+++ /dev/null
-/***************************************************************************
- * Copyright (C) 2005/06 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 _SERVERINFO_H_
-#define _SERVERINFO_H_
-
-#include <QString>
-#include <QList>
-#include <QHash>
-
-#include "global.h"
-#include "ircuser.h"
-
-class ServerInfo : public QObject {
- Q_OBJECT
-
- Q_PROPERTY(QString networkname READ networkname WRITE setNetworkname)
- Q_PROPERTY(QString currentServer READ currentServer WRITE setCurrentServer)
- Q_PROPERTY(QString ownNick READ ownNick WRITE setOwnNick)
- Q_PROPERTY(QList<IrcUser *> ircUsers READ ircUsers)
-
-public:
- ServerInfo(QObject *parent = 0);
- ~ServerInfo();
-
- void setNetworkname(const QString &networkname);
- QString networkname() const;
-
- void setCurrentServer(const QString ¤tServer);
- QString currentServer() const;
-
- void setOwnNick(const QString &ownnick);
- QString ownNick() const;
-
- QList<IrcUser *> ircUsers() const;
- IrcUser *newIrcUser(const QString &hostmask);
- IrcUser *ircUser(const QString &nickname) const;
-
- void setTopics(const QHash<QString, QString> &topics);
- QHash<QString, QString> topics() const;
-
- void updateTopic(const QString &channel, const QString &topic);
- QString topic(const QString &channel) const;
-
- void setSupports(const QHash<QString, QString> &supports);
- QHash<QString, QString> supports() const;
- QString supports(const QString &feature) const;
-
- bool isOwnNick(const QString &nick) const;
- bool isOwnNick(const IrcUser &ircuser) const;
-
-private:
- QString networkname_;
- QString currentServer_;
- QString ownNick_;
-
- //QVariantMap networkSettings;
- //QVariantMap identity;
-
- QHash<QString, IrcUser *> ircUsers_; // stores all known nicks for the server
- QHash<QString, QString> topics_; // stores topics for each buffer
- QHash<QString, QString> supports_; // stores results from RPL_ISUPPORT
-};
-
-struct UnsupportedFeatureException : public Exception {};
-
-#endif
createNetworkQuery = new QSqlQuery(logDb);
createNetworkQuery->prepare("INSERT INTO network (userid, networkname) VALUES (:userid, :networkname)");
- getBufferIdQuery = new QSqlQuery(logDb);
- getBufferIdQuery->prepare("SELECT bufferid FROM buffer "
+ getBufferInfoQuery = new QSqlQuery(logDb);
+ getBufferInfoQuery->prepare("SELECT bufferid FROM buffer "
"JOIN network ON buffer.networkid = network.networkid "
"WHERE network.networkname = :networkname AND buffer.userid = :userid AND buffer.buffername = :buffername ");
delete requestMsgRangeQuery;
delete createNetworkQuery;
delete createBufferQuery;
- delete getBufferIdQuery;
+ delete getBufferInfoQuery;
logDb.close();
}
return 0;
}
-BufferId SqliteStorage::getBufferId(UserId user, const QString &network, const QString &buffer) {
- BufferId bufferid;
+BufferInfo SqliteStorage::getBufferInfo(UserId user, const QString &network, const QString &buffer) {
+ BufferInfo bufferid;
uint networkId = getNetworkId(user, network);
- getBufferIdQuery->bindValue(":networkname", network);
- getBufferIdQuery->bindValue(":userid", user);
- getBufferIdQuery->bindValue(":buffername", buffer);
- getBufferIdQuery->exec();
+ getBufferInfoQuery->bindValue(":networkname", network);
+ getBufferInfoQuery->bindValue(":userid", user);
+ getBufferInfoQuery->bindValue(":buffername", buffer);
+ getBufferInfoQuery->exec();
- if(!getBufferIdQuery->first()) {
+ if(!getBufferInfoQuery->first()) {
createBuffer(user, network, buffer);
- getBufferIdQuery->exec();
- if(getBufferIdQuery->first()) {
- bufferid = BufferId(getBufferIdQuery->value(0).toUInt(), networkId, 0, network, buffer);
- emit bufferIdUpdated(bufferid);
+ getBufferInfoQuery->exec();
+ if(getBufferInfoQuery->first()) {
+ bufferid = BufferInfo(getBufferInfoQuery->value(0).toUInt(), networkId, 0, network, buffer);
+ emit bufferInfoUpdated(bufferid);
}
} else {
- bufferid = BufferId(getBufferIdQuery->value(0).toUInt(), networkId, 0, network, buffer);
+ bufferid = BufferInfo(getBufferInfoQuery->value(0).toUInt(), networkId, 0, network, buffer);
}
- Q_ASSERT(!getBufferIdQuery->next());
+ Q_ASSERT(!getBufferInfoQuery->next());
return bufferid;
}
-QList<BufferId> SqliteStorage::requestBuffers(UserId user, QDateTime since) {
- QList<BufferId> bufferlist;
+QList<BufferInfo> SqliteStorage::requestBuffers(UserId user, QDateTime since) {
+ QList<BufferInfo> bufferlist;
QSqlQuery query(logDb);
query.prepare("SELECT DISTINCT buffer.bufferid, networkname, buffername FROM buffer "
"JOIN network ON buffer.networkid = network.networkid "
query.exec();
while(query.next()) {
- bufferlist << BufferId(query.value(0).toUInt(), getNetworkId(user, query.value(1).toString()), 0, query.value(1).toString(), query.value(2).toString());
+ bufferlist << BufferInfo(query.value(0).toUInt(), getNetworkId(user, query.value(1).toString()), 0, query.value(1).toString(), query.value(2).toString());
}
return bufferlist;
}
}
}
-QList<Message> SqliteStorage::requestMsgs(BufferId buffer, int lastmsgs, int offset) {
+QList<Message> SqliteStorage::requestMsgs(BufferInfo buffer, int lastmsgs, int offset) {
QList<Message> messagelist;
// we have to determine the real offset first
requestMsgsOffsetQuery->bindValue(":bufferid", buffer.uid());
}
-QList<Message> SqliteStorage::requestMsgs(BufferId buffer, QDateTime since, int offset) {
+QList<Message> SqliteStorage::requestMsgs(BufferInfo buffer, QDateTime since, int offset) {
QList<Message> messagelist;
// we have to determine the real offset first
requestMsgsSinceOffsetQuery->bindValue(":bufferid", buffer.uid());
}
-QList<Message> SqliteStorage::requestMsgRange(BufferId buffer, int first, int last) {
+QList<Message> SqliteStorage::requestMsgRange(BufferInfo buffer, int first, int last) {
QList<Message> messagelist;
requestMsgRangeQuery->bindValue(":bufferid", buffer.uid());
requestMsgRangeQuery->bindValue(":bufferid2", buffer.uid());
#include <QCryptographicHash>
-#include "global.h"
#include "storage.h"
class QSqlQuery;
virtual uint getNetworkId(UserId user, const QString &network);
/* Buffer handling */
- virtual BufferId getBufferId(UserId user, const QString &network, const QString &buffer = "");
- virtual QList<BufferId> requestBuffers(UserId user, QDateTime since = QDateTime());
+ virtual BufferInfo getBufferInfo(UserId user, const QString &network, const QString &buffer = "");
+ virtual QList<BufferInfo> requestBuffers(UserId user, QDateTime since = QDateTime());
/* Message handling */
virtual MsgId logMessage(Message msg);
- virtual QList<Message> requestMsgs(BufferId buffer, int lastmsgs = -1, int offset = -1);
- virtual QList<Message> requestMsgs(BufferId buffer, QDateTime since, int offset = -1);
- virtual QList<Message> requestMsgRange(BufferId buffer, int first, int last);
+ virtual QList<Message> requestMsgs(BufferInfo buffer, int lastmsgs = -1, int offset = -1);
+ 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 */
void importOldBacklog();
signals:
- void bufferIdUpdated(BufferId);
+ void bufferInfoUpdated(BufferInfo);
protected:
QSqlQuery *requestMsgRangeQuery;
QSqlQuery *createNetworkQuery;
QSqlQuery *createBufferQuery;
- QSqlQuery *getBufferIdQuery;
+ QSqlQuery *getBufferInfoQuery;
};
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;
+ nextMsgId = 1; nextBufferInfo = 1; nextSenderId = 1;
qDebug() << "Importing old backlog files...";
initBackLogOld();
if(!backLogEnabledOld) return;
QString target = QString::fromUtf8(targ);
QString sender = QString::fromUtf8(s);
QString text = QString::fromUtf8(m);
- BufferId id;
+ BufferInfo id;
if((f & Message::PrivMsg) && !(f & Message::Self)) {
- id = getBufferId(uid, net, sender);
+ id = getBufferInfo(uid, net, sender);
} else {
- id = getBufferId(uid, net, target);
+ id = getBufferInfo(uid, net, target);
}
Message msg(QDateTime::fromTime_t(ts), id, (Message::Type)t, text, sender, f);
//backLog[net].append(m);
//! Get the unique NetworkId of the network for a user.
/** \param user The core user who owns this buffername
* \param network The network name
- * \return The BufferId corresponding to the given network and buffer name, or 0 if not found
+ * \return The BufferInfo corresponding to the given network and buffer name, or 0 if not found
*/
virtual uint getNetworkId(UserId user, const QString &network) = 0;
/* Buffer handling */
- //! Get the unique BufferId for the given combination of network and buffername for a user.
+ //! Get the unique BufferInfo for the given combination of network and buffername for a user.
/** \param user The core user who owns this buffername
* \param network The network name
* \param buffer The buffer name (if empty, the net's status buffer is returned)
- * \return The BufferId corresponding to the given network and buffer name, or 0 if not found
+ * \return The BufferInfo corresponding to the given network and buffer name, or 0 if not found
*/
- virtual BufferId getBufferId(UserId user, const QString &network, const QString &buffer = "") = 0;
+ virtual BufferInfo getBufferInfo(UserId user, const QString &network, const QString &buffer = "") = 0;
//! Request a list of all buffers known to a user since a certain point in time.
/** This method is used to get a list of all buffers we have stored a backlog from.
* since that point in time.
* \param user The user whose buffers we request
* \param since If this is defined, older buffers will be ignored
- * \return A list of the BufferIds for all buffers as requested
+ * \return A list of the BufferInfos for all buffers as requested
*/
- virtual QList<BufferId> requestBuffers(UserId user, QDateTime since = QDateTime()) = 0;
+ virtual QList<BufferInfo> requestBuffers(UserId user, QDateTime since = QDateTime()) = 0;
/* Message handling */
* \param offset Do not return (but DO count) messages with MsgId >= offset, if offset >= 0
* \return The requested list of messages
*/
- virtual QList<Message> requestMsgs(BufferId buffer, int lastmsgs = -1, int offset = -1) = 0;
+ virtual QList<Message> requestMsgs(BufferInfo buffer, int lastmsgs = -1, int offset = -1) = 0;
//! Request messages stored in a given buffer since a certain point in time.
/** \param buffer The buffer we request messages from
* \param offset Do not return messages with MsgId >= offset, if offset >= 0
* \return The requested list of messages
*/
- virtual QList<Message> requestMsgs(BufferId buffer, QDateTime since, int offset = -1) = 0;
+ virtual QList<Message> requestMsgs(BufferInfo buffer, QDateTime since, int offset = -1) = 0;
//! Request a range of messages stored in a given buffer.
/** \param buffer The buffer we request messages from
* \param last Return messages with first <= MsgId <= last
* \return The requested list of messages
*/
- virtual QList<Message> requestMsgRange(BufferId buffer, int first, int last) = 0;
+ virtual QList<Message> requestMsgRange(BufferInfo buffer, int first, int last) = 0;
public slots:
//! This is just for importing the old file-based backlog */
virtual void importOldBacklog() = 0;
signals:
- //! Sent when a new BufferId is created, or an existing one changed somehow.
- void bufferIdUpdated(BufferId);
+ //! Sent when a new BufferInfo is created, or an existing one changed somehow.
+ void bufferInfoUpdated(BufferInfo);
//! Sent when a new user has been added
void userAdded(UserId, const QString &username);
//! Sent when a user has been renamed
--- /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 "userinputhandler.h"
+
+#include "util.h"
+
+#include "server.h"
+#include "networkinfo.h"
+#include "ctcphandler.h"
+
+#include <QDebug>
+
+UserInputHandler::UserInputHandler(Server *parent)
+ : BasicHandler(parent) {
+}
+
+void UserInputHandler::handleUserInput(QString bufname, QString msg) {
+ try {
+ if(msg.isEmpty())
+ return;
+ QString cmd;
+ if(!msg.startsWith('/')) {
+ cmd = QString("SAY");
+ } else {
+ cmd = msg.section(' ', 0, 0).remove(0, 1).toUpper();
+ msg = msg.section(' ', 1);
+ }
+ handle(cmd, Q_ARG(QString, bufname), Q_ARG(QString, msg));
+ } catch(Exception e) {
+ emit displayMsg(Message::Error, "", e.msg());
+ }
+}
+
+// ====================
+// Public Slots
+// ====================
+
+void UserInputHandler::handleAway(QString bufname, QString msg) {
+ emit putCmd("AWAY", QStringList(msg));
+}
+
+void UserInputHandler::handleDeop(QString bufname, QString msg) {
+ QStringList nicks = msg.split(' ', QString::SkipEmptyParts);
+ QString m = "-"; for(int i = 0; i < nicks.count(); i++) m += 'o';
+ QStringList params;
+ params << bufname << m << nicks;
+ emit putCmd("MODE", params);
+}
+
+void UserInputHandler::handleDevoice(QString bufname, QString msg) {
+ QStringList nicks = msg.split(' ', QString::SkipEmptyParts);
+ QString m = "-"; for(int i = 0; i < nicks.count(); i++) m += 'v';
+ QStringList params;
+ params << bufname << m << nicks;
+ emit putCmd("MODE", params);
+}
+
+void UserInputHandler::handleInvite(QString bufname, QString msg) {
+ QStringList params;
+ params << msg << bufname;
+ emit putCmd("INVITE", params);
+}
+
+void UserInputHandler::handleJoin(QString bufname, QString msg) {
+ emit putCmd("JOIN", QStringList(msg));
+}
+
+void UserInputHandler::handleKick(QString bufname, QString msg) {
+ QStringList params;
+ params << bufname << msg.split(' ', QString::SkipEmptyParts);
+ emit putCmd("KICK", params);
+}
+
+void UserInputHandler::handleList(QString bufname, QString msg) {
+ emit putCmd("LIST", msg.split(' ', QString::SkipEmptyParts));
+}
+
+void UserInputHandler::handleMode(QString bufname, QString msg) {
+ emit putCmd("MODE", msg.split(' ', QString::SkipEmptyParts));
+}
+
+// TODO: show privmsgs
+void UserInputHandler::handleMsg(QString bufname, QString msg) {
+ QString nick = msg.section(" ", 0, 0);
+ msg = msg.section(" ", 1);
+ if(nick.isEmpty() || msg.isEmpty()) return;
+ QStringList params;
+ params << nick << msg;
+ emit putCmd("PRIVMSG", params);
+}
+
+void UserInputHandler::handleNick(QString bufname, QString msg) {
+ QString nick = msg.section(' ', 0, 0);
+ emit putCmd("NICK", QStringList(nick));
+}
+
+void UserInputHandler::handleOp(QString bufname, QString msg) {
+ QStringList nicks = msg.split(' ', QString::SkipEmptyParts);
+ QString m = "+"; for(int i = 0; i < nicks.count(); i++) m += 'o';
+ QStringList params;
+ params << bufname << m << nicks;
+ emit putCmd("MODE", params);
+}
+
+void UserInputHandler::handlePart(QString bufname, QString msg) {
+ QStringList params;
+ params << bufname << msg;
+ emit putCmd("PART", params);
+}
+
+// TODO: implement queries
+void UserInputHandler::handleQuery(QString bufname, QString msg) {
+ QString nick = msg.section(' ', 0, 0);
+ // TODO: usenetworkids
+// if(!nick.isEmpty())
+// emit queryRequested(network, nick);
+}
+
+void UserInputHandler::handleQuit(QString bufname, QString msg) {
+ emit putCmd("QUIT", QStringList(msg));
+}
+
+void UserInputHandler::handleQuote(QString bufname, QString msg) {
+ emit putRawLine(msg);
+}
+
+void UserInputHandler::handleSay(QString bufname, QString msg) {
+ if(bufname.isEmpty()) return; // server buffer
+ QStringList params;
+ params << bufname << msg;
+ emit putCmd("PRIVMSG", params);
+ if(isChannelName(bufname)) {
+ emit displayMsg(Message::Plain, params[0], msg, networkInfo()->myNick(), Message::Self);
+ } else {
+ emit displayMsg(Message::Plain, params[0], msg, networkInfo()->myNick(), Message::Self|Message::PrivMsg);
+ }
+}
+
+void UserInputHandler::handleMe(QString bufname, QString msg) {
+ if(bufname.isEmpty()) return; // server buffer
+ server->ctcpHandler()->query(bufname, "ACTION", msg);
+ emit displayMsg(Message::Action, bufname, msg, networkInfo()->myNick());
+}
+
+void UserInputHandler::handleTopic(QString bufname, QString msg) {
+ if(bufname.isEmpty()) return;
+ QStringList params;
+ params << bufname << msg;
+ emit putCmd("TOPIC", params);
+}
+
+void UserInputHandler::handleVoice(QString bufname, QString msg) {
+ QStringList nicks = msg.split(' ', QString::SkipEmptyParts);
+ QString m = "+"; for(int i = 0; i < nicks.count(); i++) m += 'v';
+ QStringList params;
+ params << bufname << m << nicks;
+ emit putCmd("MODE", params);
+}
+
+
+void UserInputHandler::defaultHandler(QString cmd, QString bufname, QString msg) {
+ emit displayMsg(Message::Error, "", QString("Error: %1 %2").arg(cmd).arg(msg));
+
+}
+
+
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2005/06 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 _USERINPUTHANDLER_H_
+#define _USERINPUTHANDLER_H_
+
+#include "basichandler.h"
+
+class Server;
+
+class UserInputHandler : public BasicHandler {
+ Q_OBJECT
+
+public:
+ UserInputHandler(Server *parent = 0);
+
+ void handleUserInput(QString buffer, QString msg);
+
+public slots:
+ void handleAway(QString, QString);
+ void handleDeop(QString, QString);
+ void handleDevoice(QString, QString);
+ void handleInvite(QString, QString);
+ void handleJoin(QString, QString);
+ void handleKick(QString, QString);
+ void handleList(QString, QString);
+ void handleMode(QString, QString);
+ void handleMsg(QString, QString);
+ void handleNick(QString, QString);
+ void handleOp(QString, QString);
+ void handlePart(QString, QString);
+ void handleQuery(QString, QString);
+ void handleQuit(QString, QString);
+ void handleQuote(QString, QString);
+ void handleSay(QString, QString);
+ void handleTopic(QString, QString);
+ void handleVoice(QString, QString);
+ void handleMe(QString, QString);
+
+ void defaultHandler(QString cmd, QString buf, QString msg);
+
+};
+
+
+#endif
if(!(data->hasFormat("application/Quassel/BufferItem/row")
&& data->hasFormat("application/Quassel/BufferItem/network")
- && data->hasFormat("application/Quassel/BufferItem/bufferId")))
+ && data->hasFormat("application/Quassel/BufferItem/bufferInfo")))
return; // whatever the drop is... it's not a buffer...
event->accept();
- uint bufferuid = data->data("application/Quassel/BufferItem/bufferId").toUInt();
+ uint bufferuid = data->data("application/Quassel/BufferItem/bufferInfo").toUInt();
QString networkname = QString::fromUtf8("application/Quassel/BufferItem/network");
for(int rowid = 0; rowid < rowCount(); rowid++) {
if(index.parent() == QModelIndex())
return; // only child elements can be deleted
- uint bufferuid = index.data(BufferTreeModel::BufferIdRole).toUInt();
+ uint bufferuid = index.data(BufferTreeModel::BufferInfoRole).toUInt();
if(customBuffers.contains(bufferuid)) {
beginRemoveRows(index.parent(), index.row(), index.row());
customBuffers.removeAt(customBuffers.indexOf(bufferuid));
if((mode & NoInactive) && !isActive) return false;
if((mode & FullCustom)) {
- uint bufferuid = source_bufferIndex.data(BufferTreeModel::BufferIdRole).toUInt();
+ uint bufferuid = source_bufferIndex.data(BufferTreeModel::BufferInfoRole).toUInt();
if(!customBuffers.contains(bufferuid))
return false;
}
int childcount = sourceModel()->rowCount(source_index);
for(int rowid = 0; rowid < childcount; rowid++) {
QModelIndex child = sourceModel()->index(rowid, 0, source_index);
- uint bufferuid = child.data(BufferTreeModel::BufferIdRole).toUInt();
+ uint bufferuid = child.data(BufferTreeModel::BufferInfoRole).toUInt();
if(customBuffers.contains(bufferuid))
return true;
}
return msg.buffer().uid();
}
-BufferId ChatLine::bufferId() const {
+BufferInfo ChatLine::bufferInfo() const {
return msg.buffer();
}
QString sender() const;
QString text() const;
MsgId msgId() const;
- BufferId bufferId() const;
+ BufferInfo bufferInfo() const;
bool isUrl(int pos) const;
QUrl getUrl(int pos) const;
//#include "settingspage.h"
#include "signalproxy.h"
+#include "topicwidget.h"
+
MainWin::MainWin(QtGui *_gui, QWidget *parent) : QMainWindow(parent), gui(_gui) {
ui.setupUi(this);
setWindowTitle("Quassel IRC");
}
void MainWin::init() {
- Client::signalProxy()->attachSignal(this, SIGNAL(requestBacklog(BufferId, QVariant, QVariant)));
+ Client::signalProxy()->attachSignal(this, SIGNAL(requestBacklog(BufferInfo, QVariant, QVariant)));
ui.bufferWidget->init();
show();
systray->setIcon(QIcon(":/qirc-icon.png"));
systray->show();
- serverListDlg = new ServerListDlg(this);
- serverListDlg->setVisible(serverListDlg->showOnStartup());
-
//setupSettingsDlg();
setupMenus();
disconnectedFromCore(); // Disable menus and stuff
showCoreConnectionDlg(true); // autoconnect if appropriate
//ui.actionConnectCore->activate(QAction::Trigger);
+
+ serverListDlg = new ServerListDlg(this);
+ if(serverListDlg->showOnStartup()) {
+ showServerList();
+ }
+
+ // TESTING
+// setCorner(Qt::TopLeftCorner, Qt::LeftDockWidgetArea);
+// setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea);
+
+// setCorner(Qt::TopRightCorner, Qt::RightDockWidgetArea);
+// setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea);
+
+// QDockWidget *dock = new QDockWidget("Topic Dock", this);
+// dock->setAllowedAreas(Qt::TopDockWidgetArea | Qt::BottomDockWidgetArea);
+
+// TopicWidget *topicwidget = new TopicWidget(dock);
+// dock->setWidget(topicwidget);
+
+// addDockWidget(Qt::TopDockWidgetArea, dock);
+
+// ui.menuViews->addAction(dock->toggleViewAction());
+
}
MainWin::~MainWin() {
}
void MainWin::connectedToCore() {
- foreach(BufferId id, Client::allBufferIds()) {
+ foreach(BufferInfo id, Client::allBufferInfos()) {
emit requestBacklog(id, 100, -1);
}
//}
}
-void MainWin::showBuffer(BufferId id) {
+void MainWin::showBuffer(BufferInfo id) {
showBuffer(Client::buffer(id));
}
void MainWin::showBuffer(Buffer *b) {
- currentBuffer = b->bufferId().groupId();
+ currentBuffer = b->bufferInfo().groupId();
//emit bufferSelected(b);
//qApp->processEvents();
void showCoreConnectionDlg(bool autoConnect = false);
void coreConnectionDlgFinished(int result);
- void showBuffer(BufferId);
+ void showBuffer(BufferInfo);
void showBuffer(Buffer *);
void importBacklog();
signals:
void connectToCore(const QVariantMap &connInfo);
void disconnectFromCore();
- void requestBacklog(BufferId, QVariant, QVariant);
+ void requestBacklog(BufferInfo, QVariant, QVariant);
void importOldBacklog();
private:
SRCS += bufferview.cpp bufferviewfilter.cpp bufferwidget.cpp channelwidgetinput.cpp chatline.cpp \
chatwidget.cpp coreconnectdlg.cpp \
- guisettings.cpp identities.cpp mainwin.cpp qtgui.cpp serverlist.cpp settingsdlg.cpp style.cpp tabcompleter.cpp
+ guisettings.cpp identities.cpp mainwin.cpp qtgui.cpp serverlist.cpp settingsdlg.cpp style.cpp tabcompleter.cpp topicwidget.cpp
HDRS += bufferview.h bufferviewfilter.h bufferwidget.h channelwidgetinput.h chatline.h chatwidget.h coreconnectdlg.h \
- guisettings.h identities.h mainwin.h qtgui.h serverlist.h settingsdlg.h settingspage.h style.h tabcompleter.h
+ guisettings.h identities.h mainwin.h qtgui.h serverlist.h settingsdlg.h settingspage.h style.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
+ buffermgmtpage.ui connectionpage.ui usermgmtpage.ui topicwidget.ui
for(ui, FORMNAMES) {
FRMS += ui/$${ui}
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2005/06 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 "topicwidget.h"
+
+#include <QDebug>
+
+TopicWidget::TopicWidget(QWidget *parent)
+ : QWidget(parent)
+{
+ ui.setupUi(this);
+ ui.topicLineEdit->setText("+++ DUMMY TOPIC +++ DUMMY TOPIC +++");
+}
+
+TopicWidget::~TopicWidget() {
+}
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2005/06 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 _TOPICWIDGET_H_
+#define _TOPICWIDGET_H_
+
+#include <QWidget>
+
+#include "ui_topicwidget.h"
+
+class TopicWidget : public QWidget {
+ Q_OBJECT
+
+public:
+ TopicWidget(QWidget *parent = 0);
+ virtual ~TopicWidget();
+
+
+private:
+ Ui::TopicWidget ui;
+};
+
+
+#endif
--- /dev/null
+<ui version="4.0" >
+ <class>TopicWidget</class>
+ <widget class="QWidget" name="TopicWidget" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>568</width>
+ <height>25</height>
+ </rect>
+ </property>
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Preferred" hsizetype="Preferred" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize" >
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="baseSize" >
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="windowTitle" >
+ <string>Form</string>
+ </property>
+ <layout class="QHBoxLayout" >
+ <property name="leftMargin" >
+ <number>0</number>
+ </property>
+ <property name="topMargin" >
+ <number>0</number>
+ </property>
+ <property name="rightMargin" >
+ <number>0</number>
+ </property>
+ <property name="bottomMargin" >
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QLineEdit" name="topicLineEdit" />
+ </item>
+ <item>
+ <widget class="QToolButton" name="topicEditButton" >
+ <property name="text" >
+ <string>...</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
return _msgId;
}
-BufferId ChatLine::bufferId() const {
- return _bufferId;
+BufferInfo ChatLine::bufferInfo() const {
+ return _bufferInfo;
}
QDateTime ChatLine::timeStamp() const {
virtual QString sender() const;
virtual QString text() const;
virtual MsgId msgId() const;
- virtual BufferId bufferId() const;
+ virtual BufferInfo bufferInfo() const;
virtual QDateTime timeStamp() const;
private:
QString _sender, _text;
MsgId _msgId;
- BufferId _bufferId;
+ BufferInfo _bufferInfo;
QDateTime _timeStamp;
};
QtopiaMainWin::QtopiaMainWin(QWidget *parent, Qt::WFlags flags) : QMainWindow(parent, flags) {
qRegisterMetaType<QVariant>("QVariant");
qRegisterMetaType<Message>("Message");
- qRegisterMetaType<BufferId>("BufferId");
+ qRegisterMetaType<BufferInfo>("BufferInfo");
qRegisterMetaTypeStreamOperators<QVariant>("QVariant");
qRegisterMetaTypeStreamOperators<Message>("Message");
- qRegisterMetaTypeStreamOperators<BufferId>("BufferId");
+ qRegisterMetaTypeStreamOperators<BufferInfo>("BufferInfo");
Global::runMode = Global::ClientOnly;
// at this point, client is fully initialized
void QtopiaMainWin::init() {
- Client::signalProxy()->attachSignal(this, SIGNAL(requestBacklog(BufferId, QVariant, QVariant)));
+ Client::signalProxy()->attachSignal(this, SIGNAL(requestBacklog(BufferInfo, QVariant, QVariant)));
connect(Client::bufferModel(), SIGNAL(bufferSelected(Buffer *)), this, SLOT(showBuffer(Buffer *)));
CoreConnectDlg *dlg = new CoreConnectDlg(this);
}
void QtopiaMainWin::connectedToCore() {
- foreach(BufferId id, Client::allBufferIds()) {
+ foreach(BufferInfo id, Client::allBufferInfos()) {
emit requestBacklog(id, 100, -1);
}
// FIXME just for testing: select first available buffer
- if(Client::allBufferIds().count()) {
- Buffer *b = Client::buffer(Client::allBufferIds()[0]);
+ if(Client::allBufferInfos().count()) {
+ Buffer *b = Client::buffer(Client::allBufferInfos()[0]);
Client::bufferModel()->selectBuffer(b);
}
}
signals:
void connectToCore(const QVariantMap &connInfo);
void disconnectFromCore();
- void requestBacklog(BufferId, QVariant, QVariant);
+ void requestBacklog(BufferInfo, QVariant, QVariant);
private slots:
void showBuffer(Buffer *);