signals and slots can be attached to the SignalProxy, rather than having hard-coded
stuff in the old CoreProxy and ClientProxy classes. This was made possible by integrating
QxtRPCPeer from the guys at <http://www.libqxt.org>.
Everything should work now as before, except connections to an internal core, which are disabled
for the moment. The connection handling had to be completely rewritten, and I still need a QIODevice
that can do loopback connections.
The code is still a big mess, I am deliberately committing this before clean-up, in case I
delete something we still need. Expect a much cleaner version soon.
Oh, and VarMap has been substituted by QVariantMap project-wide. We cannot send VarMap through the
SignalProxy, and I decided to change the naming consistently everywhere.
src/contrib/qxt/CMakeLists.txt
src/common/signalproxy.cpp
src/common/signalproxy.h
+src/contrib/qxt/qxtboundcfunction.h
+src/contrib/qxt/qxtboundfunctionbase.h
+src/contrib/qxt/qxtboundfunction.h
+src/contrib/qxt/qxtmetaobject.cpp
+src/contrib/qxt/qxtmetaobject.h
+src/contrib/qxt/qxtnullable.h
+src/contrib/qxt/qxtnull.cpp
+src/contrib/qxt/qxtnull.h
return layoutedMsgs;
}
-VarMap Buffer::nickList() const {
+QVariantMap Buffer::nickList() const {
return nicks;
}
emit bufferUpdated(this);
}
-void Buffer::addNick(QString nick, VarMap props) {
+void Buffer::addNick(QString nick, QVariantMap props) {
if(nick == ownNick()) setActive(true);
nicks[nick] = props;
emit nickListChanged(nicks);
}
-void Buffer::updateNick(QString nick, VarMap props) {
+void Buffer::updateNick(QString nick, QVariantMap props) {
nicks[nick] = props;
emit nickListChanged(nicks);
}
QString displayName() const;
BufferId bufferId() const;
QList<AbstractUiMsg *> contents() const;
- VarMap nickList() const;
+ QVariantMap nickList() const;
QString topic() const;
QString ownNick() const;
bool isStatusBuffer() const;
signals:
void userInput(const BufferId &, QString);
- void nickListChanged(VarMap nicks);
+ void nickListChanged(QVariantMap nicks);
void topicSet(QString topic);
void ownNickSet(QString ownNick);
void bufferUpdated(Buffer *);
bool layoutMsg();
void setTopic(QString);
//void setNicks(QStringList);
- void addNick(QString nick, VarMap props);
+ void addNick(QString nick, QVariantMap props);
void renameNick(QString oldnick, QString newnick);
void removeNick(QString nick);
- void updateNick(QString nick, VarMap props);
+ void updateNick(QString nick, QVariantMap props);
void setOwnNick(QString nick);
void processUserInput(QString);
bool active;
Type type;
- VarMap nicks;
+ QVariantMap nicks;
QString _topic;
QString _ownNick;
QString _networkName, _bufferName;
#include <QColor> // FIXME Dependency on QtGui!
-#include "clientproxy.h"
+#include "client.h"
+//#include "clientproxy.h"
#include "buffertreemodel.h"
+#include "signalproxy.h"
/*****************************************
* Fancy Buffer Items
BufferTreeModel::BufferTreeModel(QObject *parent)
: TreeModel(BufferTreeModel::defaultHeader(), parent)
{
- connect(this, SIGNAL(fakeUserInput(BufferId, QString)),
- ClientProxy::instance(), SLOT(gsUserInput(BufferId, QString)));
+ //connect(this, SIGNAL(fakeUserInput(BufferId, QString)),
+ // ClientProxy::instance(), SLOT(gsUserInput(BufferId, QString)));
+ Client::signalProxy()->attachSignal(this, SIGNAL(fakeUserInput(BufferId, QString)), SIGNAL(sendInput(BufferId, QString)));
}
QList<QVariant >BufferTreeModel::defaultHeader() {
#include "buffer.h"
#include "buffertreemodel.h"
-#include "clientproxy.h"
+//#include "clientproxy.h"
#include "quasselui.h"
+#include "signalproxy.h"
#include "util.h"
Client * Client::instanceptr = 0;
bool Client::connectedToCore = false;
Client::ClientMode Client::clientMode;
-VarMap Client::coreConnectionInfo;
+QVariantMap Client::coreConnectionInfo;
QHash<BufferId, Buffer *> Client::buffers;
QHash<uint, BufferId> Client::bufferIds;
-QHash<QString, QHash<QString, VarMap> > Client::nicks;
+QHash<QString, QHash<QString, QVariantMap> > Client::nicks;
QHash<QString, bool> Client::netConnected;
QStringList Client::netsAwaitingInit;
QHash<QString, QString> Client::ownNick;
}
Client::Client() {
- clientProxy = ClientProxy::instance();
-
- _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 *)));
+ //clientProxy = ClientProxy::instance();
+ _signalProxy = new SignalProxy(SignalProxy::Client, 0, this);
// TODO: make this configurable (allow monolithic client to connect to remote cores)
- if(Global::runMode == Global::Monolithic) clientMode = LocalCore;
- else clientMode = RemoteCore;
+ //if(Global::runMode == Global::Monolithic) clientMode = LocalCore;
+ //else clientMode = RemoteCore;
connectedToCore = false;
+ socket = 0;
}
void Client::init(AbstractUi *ui) {
void Client::init() {
blockSize = 0;
- connect(&socket, SIGNAL(readyRead()), this, SLOT(serverHasData()));
- connect(&socket, SIGNAL(connected()), this, SLOT(coreSocketConnected()));
- connect(&socket, SIGNAL(disconnected()), this, SLOT(coreSocketDisconnected()));
- connect(&socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(serverError(QAbstractSocket::SocketError)));
-
- connect(this, SIGNAL(sendSessionData(const QString &, const QVariant &)), clientProxy, SLOT(gsSessionDataChanged(const QString &, const QVariant &)));
- connect(clientProxy, SIGNAL(csSessionDataChanged(const QString &, const QVariant &)), this, SLOT(recvSessionData(const QString &, const QVariant &)));
-
- connect(clientProxy, SIGNAL(send(ClientSignal, QVariant, QVariant, QVariant)), this, SLOT(recvProxySignal(ClientSignal, QVariant, QVariant, QVariant)));
- connect(clientProxy, SIGNAL(csCoreState(QVariant)), this, SLOT(recvCoreState(const QVariant &)));
- connect(clientProxy, SIGNAL(csServerState(QString, QVariant)), this, SLOT(recvNetworkState(QString, QVariant)));
- connect(clientProxy, SIGNAL(csServerConnected(QString)), this, SLOT(networkConnected(QString)));
- connect(clientProxy, SIGNAL(csServerDisconnected(QString)), this, SLOT(networkDisconnected(QString)));
- connect(clientProxy, SIGNAL(csDisplayMsg(Message)), this, SLOT(recvMessage(const Message &)));
- connect(clientProxy, SIGNAL(csDisplayStatusMsg(QString, QString)), this, SLOT(recvStatusMsg(QString, QString)));
- connect(clientProxy, SIGNAL(csTopicSet(QString, QString, QString)), this, SLOT(setTopic(QString, QString, QString)));
- connect(clientProxy, SIGNAL(csNickAdded(QString, QString, VarMap)), this, SLOT(addNick(QString, QString, VarMap)));
- connect(clientProxy, SIGNAL(csNickRemoved(QString, QString)), this, SLOT(removeNick(QString, QString)));
- connect(clientProxy, SIGNAL(csNickRenamed(QString, QString, QString)), this, SLOT(renameNick(QString, QString, QString)));
- connect(clientProxy, SIGNAL(csNickUpdated(QString, QString, VarMap)), this, SLOT(updateNick(QString, QString, VarMap)));
- connect(clientProxy, SIGNAL(csOwnNickSet(QString, QString)), this, SLOT(setOwnNick(QString, QString)));
- connect(clientProxy, SIGNAL(csBacklogData(BufferId, const QList<QVariant> &, bool)), this, SLOT(recvBacklogData(BufferId, QList<QVariant>, bool)));
- connect(clientProxy, SIGNAL(csUpdateBufferId(BufferId)), this, SLOT(updateBufferId(BufferId)));
- connect(this, SIGNAL(sendInput(BufferId, QString)), clientProxy, SLOT(gsUserInput(BufferId, QString)));
- connect(this, SIGNAL(requestBacklog(BufferId, QVariant, QVariant)), clientProxy, SLOT(gsRequestBacklog(BufferId, QVariant, QVariant)));
- connect(this, SIGNAL(requestNetworkStates()), clientProxy, SLOT(gsRequestNetworkStates()));
-
- connect(mainUi, SIGNAL(connectToCore(const VarMap &)), this, SLOT(connectToCore(const VarMap &)));
+ _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(&socket, SIGNAL(readyRead()), this, SLOT(serverHasData()));
+ //connect(&socket, SIGNAL(connected()), this, SLOT(coreSocketConnected()));
+ //connect(&socket, SIGNAL(disconnected()), this, SLOT(coreSocketDisconnected()));
+ //connect(&socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(serverError(QAbstractSocket::SocketError)));
+
+ //connect(this, SIGNAL(sendSessionData(const QString &, const QVariant &)), clientProxy, SLOT(gsSessionDataChanged(const QString &, const QVariant &)));
+ //connect(clientProxy, SIGNAL(csSessionDataChanged(const QString &, const QVariant &)), this, SLOT(recvSessionData(const QString &, const QVariant &)));
+
+ //connect(clientProxy, SIGNAL(send(ClientSignal, QVariant, QVariant, QVariant)), this, SLOT(recvProxySignal(ClientSignal, QVariant, QVariant, QVariant)));
+ //connect(clientProxy, SIGNAL(csCoreState(QVariant)), this, SLOT(recvCoreState(const QVariant &)));
+ //connect(clientProxy, SIGNAL(csServerState(QString, QVariant)), this, SLOT(recvNetworkState(QString, QVariant)));
+ //connect(clientProxy, SIGNAL(csServerConnected(QString)), this, SLOT(networkConnected(QString)));
+ //connect(clientProxy, SIGNAL(csServerDisconnected(QString)), this, SLOT(networkDisconnected(QString)));
+ //connect(clientProxy, SIGNAL(csDisplayMsg(Message)), this, SLOT(recvMessage(const Message &)));
+ //connect(clientProxy, SIGNAL(csDisplayStatusMsg(QString, QString)), this, SLOT(recvStatusMsg(QString, QString)));
+ //connect(clientProxy, SIGNAL(csTopicSet(QString, QString, QString)), this, SLOT(setTopic(QString, QString, QString)));
+ //connect(clientProxy, SIGNAL(csNickAdded(QString, QString, QVariantMap)), this, SLOT(addNick(QString, QString, QVariantMap)));
+ //connect(clientProxy, SIGNAL(csNickRemoved(QString, QString)), this, SLOT(removeNick(QString, QString)));
+ //connect(clientProxy, SIGNAL(csNickRenamed(QString, QString, QString)), this, SLOT(renameNick(QString, QString, QString)));
+ //connect(clientProxy, SIGNAL(csNickUpdated(QString, QString, QVariantMap)), this, SLOT(updateNick(QString, QString, QVariantMap)));
+ //connect(clientProxy, SIGNAL(csOwnNickSet(QString, QString)), this, SLOT(setOwnNick(QString, QString)));
+ //connect(clientProxy, SIGNAL(csBacklogData(BufferId, const QList<QVariant> &, bool)), this, SLOT(recvBacklogData(BufferId, QList<QVariant>, bool)));
+ //connect(clientProxy, SIGNAL(csUpdateBufferId(BufferId)), this, SLOT(updateBufferId(BufferId)));
+ //connect(this, SIGNAL(sendInput(BufferId, QString)), clientProxy, SLOT(gsUserInput(BufferId, QString)));
+ //connect(this, SIGNAL(requestBacklog(BufferId, QVariant, QVariant)), clientProxy, SLOT(gsRequestBacklog(BufferId, QVariant, QVariant)));
+ //connect(this, SIGNAL(requestNetworkStates()), clientProxy, SLOT(gsRequestNetworkStates()));
+
+ 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(requestBacklog(BufferId, QVariant, QVariant)), "requestBacklog");
+ p->attachSignal(this, SIGNAL(requestNetworkStates()));
+
+ connect(mainUi, SIGNAL(connectToCore(const QVariantMap &)), this, SLOT(connectToCore(const QVariantMap &)));
connect(mainUi, SIGNAL(disconnectFromCore()), this, SLOT(disconnectFromCore()));
connect(this, SIGNAL(connected()), mainUi, SLOT(connectedToCore()));
connect(this, SIGNAL(disconnected()), mainUi, SLOT(disconnectedFromCore()));
Client::~Client() {
//delete mainUi;
//delete _bufferModel;
- foreach(Buffer *buf, buffers.values()) delete buf; // this is done by disconnectFromCore()!
- ClientProxy::destroy();
+ foreach(Buffer *buf, buffers.values()) delete buf; // this is done by disconnectFromCore()! FIXME?
+ //ClientProxy::destroy();
Q_ASSERT(!buffers.count());
}
return instance()->_bufferModel;
}
-bool Client::isConnected() { return connectedToCore; }
+SignalProxy *Client::signalProxy() {
+ return instance()->_signalProxy;
+}
+
+bool Client::isConnected() {
+ return connectedToCore;
+}
-void Client::connectToCore(const VarMap &conn) {
+void Client::connectToCore(const QVariantMap &conn) {
// TODO implement SSL
coreConnectionInfo = conn;
- if(isConnected()) {
+ if(isConnected() || socket != 0) {
emit coreConnectionError(tr("Already connected to Core!"));
return;
}
if(conn["Host"].toString().isEmpty()) {
clientMode = LocalCore;
- QVariant state = connectToLocalCore(coreConnectionInfo["User"].toString(), coreConnectionInfo["Password"].toString());
- syncToCore(state);
+ socket = new QBuffer(this);
+ connect(socket, SIGNAL(readyRead()), this, SLOT(coreHasData()));
+ socket->open(QIODevice::ReadWrite);
+ //QVariant state = connectToLocalCore(coreConnectionInfo["User"].toString(), coreConnectionInfo["Password"].toString());
+ //syncToCore(state);
+ coreSocketConnected();
} else {
clientMode = RemoteCore;
emit coreConnectionMsg(tr("Connecting..."));
- socket.connectToHost(conn["Host"].toString(), conn["Port"].toUInt());
+ Q_ASSERT(!socket);
+ QTcpSocket *sock = new QTcpSocket(this);
+ socket = sock;
+ connect(sock, SIGNAL(readyRead()), this, SLOT(coreHasData()));
+ connect(sock, SIGNAL(connected()), this, SLOT(coreSocketConnected()));
+ connect(sock, SIGNAL(disconnected()), this, SLOT(coreSocketDisconnected()));
+ connect(signalProxy(), SIGNAL(peerDisconnected()), this, SLOT(coreSocketDisconnected()));
+ //connect(sock, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(coreSocketStateChanged(QAbstractSocket::SocketState)));
+ connect(sock, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(coreSocketError(QAbstractSocket::SocketError)));
+ sock->connectToHost(conn["Host"].toString(), conn["Port"].toUInt());
}
}
void Client::disconnectFromCore() {
if(clientMode == RemoteCore) {
- socket.close();
+ socket->close();
+ //QAbstractSocket *sock = qobject_cast<QAbstractSocket*>(socket);
+ //Q_ASSERT(sock);
+ //sock->disconnectFromHost();
} else {
- disconnectFromLocalCore();
+ socket->close();
+ //disconnectFromLocalCore();
coreSocketDisconnected();
}
}
void Client::coreSocketConnected() {
connect(this, SIGNAL(recvPartialItem(uint, uint)), this, SIGNAL(coreConnectionProgress(uint, uint)));
emit coreConnectionMsg(tr("Synchronizing to core..."));
- VarMap clientInit;
+ QVariantMap clientInit;
clientInit["GuiProtocol"] = GUI_PROTOCOL;
clientInit["User"] = coreConnectionInfo["User"].toString();
clientInit["Password"] = coreConnectionInfo["Password"].toString();
- writeDataToDevice(&socket, clientInit);
+ writeDataToDevice(socket, clientInit);
}
void Client::coreSocketDisconnected() {
connectedToCore = false;
emit disconnected();
+ socket->deleteLater();
+
/* 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.
layoutTimer->stop();
}
+void Client::coreSocketStateChanged(QAbstractSocket::SocketState state) { qDebug() << state;
+ if(state == QAbstractSocket::UnconnectedState) coreSocketDisconnected();
+}
+
void Client::recvCoreState(const QVariant &state) {
disconnect(this, SIGNAL(recvPartialItem(uint, uint)), this, SIGNAL(coreConnectionProgress(uint, uint)));
+ disconnect(socket, 0, this, 0); // rest of communication happens through SignalProxy
+ signalProxy()->addPeer(socket);
syncToCore(state);
-
}
void Client::syncToCore(const QVariant &coreState) {
- VarMap sessionState = coreState.toMap()["SessionState"].toMap();
- VarMap sessData = sessionState["SessionData"].toMap();
+ if(!coreState.toMap().contains("SessionState")) {
+ emit coreConnectionError(tr("Invalid data received from core!"));
+ disconnectFromCore();
+ return;
+ }
+ QVariantMap sessionState = coreState.toMap()["SessionState"].toMap();
+ QVariantMap sessData = sessionState["SessionData"].toMap();
foreach(QString key, sessData.keys()) {
recvSessionData(key, sessData[key]);
QList<QVariant> sigdata;
sigdata.append(sig); sigdata.append(arg1); sigdata.append(arg2); sigdata.append(arg3);
//qDebug() << "Sending signal: " << sigdata;
- writeDataToDevice(&socket, QVariant(sigdata));
+ writeDataToDevice(socket, QVariant(sigdata));
}
-void Client::serverError(QAbstractSocket::SocketError) {
- emit coreConnectionError(socket.errorString());
+void Client::coreSocketError(QAbstractSocket::SocketError) {
+ emit coreConnectionError(socket->errorString());
}
-void Client::serverHasData() {
+void Client::coreHasData() {
QVariant item;
- while(readDataFromDevice(&socket, blockSize, item)) {
+ if(readDataFromDevice(socket, blockSize, item)) {
emit recvPartialItem(1,1);
- QList<QVariant> sigdata = item.toList();
- Q_ASSERT(sigdata.size() == 4);
- ClientProxy::instance()->recv((CoreSignal)sigdata[0].toInt(), sigdata[1], sigdata[2], sigdata[3]);
+ //QList<QVariant> sigdata = item.toList();
+ //Q_ASSERT(sigdata.size() == 4);
+ //ClientProxy::instance()->recv((CoreSignal)sigdata[0].toInt(), sigdata[1], sigdata[2], sigdata[3]);
+ recvCoreState(item);
blockSize = 0;
+ return;
}
if(blockSize > 0) {
- emit recvPartialItem(socket.bytesAvailable(), blockSize);
+ emit recvPartialItem(socket->bytesAvailable(), blockSize);
}
}
netConnected[net] = true;
setOwnNick(net, state.toMap()["OwnNick"].toString());
buffer(statusBufferId(net))->setActive(true);
- VarMap t = state.toMap()["Topics"].toMap();
- VarMap n = state.toMap()["Nicks"].toMap();
+ 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);
}
-void Client::recvBacklogData(BufferId id, const QList<QVariant> &msgs, bool /*done*/) {
+void Client::recvBacklogData(BufferId id, QVariantList msgs, bool /*done*/) {
Buffer *b = buffer(id);
foreach(QVariant v, msgs) {
Message msg = v.value<Message>();
//}
}
-void Client::addNick(QString net, QString nick, VarMap props) {
+void Client::addNick(QString net, QString nick, QVariantMap props) {
if(!netConnected[net]) return;
nicks[net][nick] = props;
- VarMap chans = props["Channels"].toMap();
+ QVariantMap chans = props["Channels"].toMap();
QStringList c = chans.keys();
foreach(QString bufname, c) {
buffer(bufferId(net, bufname))->addNick(nick, props);
nicks[net][newnick] = nicks[net].take(oldnick);
}
-void Client::updateNick(QString net, QString nick, VarMap props) {
+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();
void Client::removeNick(QString net, QString nick) {
if(!netConnected[net]) return;
- VarMap chans = nicks[net][nick]["Channels"].toMap();
+ QVariantMap chans = nicks[net][nick]["Channels"].toMap();
foreach(QString bufname, chans.keys()) {
buffer(bufferId(net, bufname))->removeNick(nick);
}
#include <QAbstractSocket>
#include <QTcpSocket>
#include <QList>
+#include <QPointer>
#include "buffer.h"
#include "message.h"
class ClientProxy;
class BufferTreeModel;
class QtGui;
+class SignalProxy;
class QTimer;
static BufferId bufferId(QString net, QString buf);
static BufferTreeModel *bufferModel();
+ static SignalProxy *signalProxy();
static AbstractUiMsg *layoutMsg(const Message &);
public slots:
//void selectBuffer(Buffer *);
//void connectToLocalCore();
- void connectToCore(const VarMap &);
+ void connectToCore(const QVariantMap &);
void disconnectFromCore();
private slots:
void recvSessionData(const QString &key, const QVariant &data);
void recvProxySignal(ClientSignal sig, QVariant arg1, QVariant arg2, QVariant arg3);
- void serverError(QAbstractSocket::SocketError);
- void serverHasData();
+ void coreSocketError(QAbstractSocket::SocketError);
+ void coreHasData();
void coreSocketConnected();
void coreSocketDisconnected();
+ void coreSocketStateChanged(QAbstractSocket::SocketState);
void userInput(BufferId, QString);
void networkConnected(QString);
void recvMessage(const Message &message);
void recvStatusMsg(QString network, QString message);
void setTopic(QString net, QString buf, QString);
- void addNick(QString net, QString nick, VarMap props);
+ 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, VarMap props);
+ void updateNick(QString net, QString nick, QVariantMap props);
void setOwnNick(QString net, QString nick);
- void recvBacklogData(BufferId, const QList<QVariant> &, bool);
+ void recvBacklogData(BufferId, QVariantList, bool);
void updateBufferId(BufferId);
void removeBuffer(Buffer *);
void disconnectFromLocalCore(); // defined in main.cpp
AbstractUi *mainUi;
- ClientProxy *clientProxy;
+ //ClientProxy *clientProxy;
+ SignalProxy *_signalProxy;
BufferTreeModel *_bufferModel;
- QTcpSocket socket;
+ QPointer<QIODevice> socket;
quint32 blockSize;
static bool connectedToCore;
- static VarMap coreConnectionInfo;
+ static QVariantMap coreConnectionInfo;
static QHash<BufferId, Buffer *> buffers;
static QHash<uint, BufferId> bufferIds;
- static QHash<QString, QHash<QString, VarMap> > nicks;
+ 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;
- VarMap sessionData;
+ QVariantMap sessionData;
};
#endif
void csSessionDataChanged(const QString &key, const QVariant &data);
void csModeSet(QString, QString, QString);
void csTopicSet(QString, QString, QString);
- void csNickAdded(QString, QString, VarMap);
+ void csNickAdded(QString, QString, QVariantMap);
void csNickRemoved(QString, QString);
void csNickRenamed(QString, QString, QString);
- void csNickUpdated(QString, QString, VarMap);
+ void csNickUpdated(QString, QString, QVariantMap);
void csOwnNickSet(QString, QString);
void csQueryRequested(QString, QString);
void csBacklogData(BufferId, QList<QVariant>, bool);
#include <QVariant>
/* Some global stuff */
-typedef QMap<QString, QVariant> VarMap;
typedef uint UserId;
typedef uint MsgId;
#include <QCoreApplication>
#include <QDir>
#include "core.h"
+#include "message.h"
#elif defined BUILD_QTGUI
#include <QApplication>
#include "client.h"
-#include "clientproxy.h"
+//#include "clientproxy.h"
#include "qtgui.h"
#include "style.h"
#elif defined BUILD_MONO
#include <QApplication>
#include "client.h"
-#include "clientproxy.h"
+//#include "clientproxy.h"
#include "core.h"
#include "coresession.h"
#include "qtgui.h"
signal(SIGTERM, handle_signal);
signal(SIGINT, handle_signal);
+ qRegisterMetaType<QVariant>("QVariant");
qRegisterMetaType<Message>("Message");
qRegisterMetaType<BufferId>("BufferId");
+ qRegisterMetaTypeStreamOperators<QVariant>("QVariant");
qRegisterMetaTypeStreamOperators<Message>("Message");
qRegisterMetaTypeStreamOperators<BufferId>("BufferId");
#elif defined BUILD_MONO
QVariant Client::connectToLocalCore(QString user, QString passwd) {
// TODO catch exceptions
+ /*
QVariant reply = Core::connectLocalClient(user, passwd);
QObject::connect(Core::localSession(), SIGNAL(proxySignal(CoreSignal, QVariant, QVariant, QVariant)), ClientProxy::instance(), SLOT(recv(CoreSignal, QVariant, QVariant, QVariant)));
QObject::connect(ClientProxy::instance(), SIGNAL(send(ClientSignal, QVariant, QVariant, QVariant)), Core::localSession(), SLOT(processSignal(ClientSignal, QVariant, QVariant, QVariant)));
return reply;
+ */
+ return QVariant();
}
void Client::disconnectFromLocalCore() {
+ /*
disconnect(Core::localSession(), 0, ClientProxy::instance(), 0);
disconnect(ClientProxy::instance(), 0, Core::localSession(), 0);
Core::disconnectLocalClient();
+ */
}
#endif
virtual void disconnectedFromCore() {}
signals:
- void connectToCore(const VarMap &connInfo);
+ void connectToCore(const QVariantMap &connInfo);
void disconnectFromCore();
};
Connection conn;
conn.device = dev;
conn.peer = new QxtRPCPeer(dev, QxtRPCPeer::Peer, this);
+ connect(conn.peer, SIGNAL(peerDisconnected()), this, SLOT(socketDisconnected()));
foreach(SlotDesc slot, attachedSlots) {
conn.peer->attachSlot(slot.rpcFunction, slot.recv, slot.slot);
}
+void SignalProxy::socketDisconnected() {
+ for(int i = 0; i < peers.count(); i++) {
+ Connection conn = peers[i];
+ QAbstractSocket *sock = qobject_cast<QAbstractSocket*>(conn.device);
+ if(!sock) continue;
+ if(sock->state() == QAbstractSocket::UnconnectedState) {
+ peers[i].peer->deleteLater(); peers[i].device->deleteLater();
+ peers.removeAt(i);
+ emit peerDisconnected();
+ i--;
+ }
+ }
+}
+
void SignalProxy::attachSignal(QObject* sender, const char* signal, const QByteArray& rpcFunction) {
foreach(Connection conn, peers) {
conn.peer->attachSignal(sender, signal, rpcFunction);
}
+void SignalProxy::sendSignal(const char *signal, QVariant p1, QVariant p2, QVariant p3, QVariant p4, QVariant p5, QVariant p6, QVariant p7, QVariant p8, QVariant p9) {
+ foreach(Connection conn, peers) {
+ conn.peer->call(signal, p1, p2, p3, p4, p5, p6, p7, p8, p9);
+ }
+}
+
void sendSignal(const char *signal, QVariant p1 = QVariant(), QVariant p2 = QVariant(), QVariant p3 = QVariant(), QVariant p4 = QVariant(),
QVariant p5 = QVariant(), QVariant p6 = QVariant(), QVariant p7 = QVariant(), QVariant p8 = QVariant(), QVariant p9 = QVariant());
- void detachSender();
+ //void detachSender();
signals:
- //void peerDisconnected();
+ void peerDisconnected();
private slots:
+ void socketDisconnected();
private:
struct Connection {
-SET(qxt_SRCS qxtrpcpeer.cpp)
-SET(qxt_HDRS qxtglobal.h qxtpimpl.h)
-SET(qxt_MOCS qxtrpcpeer.h)
+SET(qxt_SRCS qxtmetaobject.cpp qxtnull.cpp qxtrpcpeer.cpp)
+SET(qxt_HDRS qxtboundcfunction.h qxtboundfunctionbase.h qxtboundfunction.h qxtglobal.h qxtpimpl.h qxtmetaobject.h qxtnullable.h qxtnull.h)
+SET(qxt_MOCS qxtboundfunction.h qxtrpcpeer.h)
QT4_WRAP_CPP(_MOC ${qxt_MOCS})
ADD_LIBRARY(qxt ${qxt_SRCS} ${_MOC})
--- /dev/null
+/****************************************************************************
+**
+** Copyright (C) Qxt Foundation. Some rights reserved.
+**
+** This file is part of the QxtCore module of the Qt eXTension library
+**
+** This library is free software; you can redistribute it and/or modify it
+** under the terms of th Common Public License, version 1.0, as published by
+** IBM.
+**
+** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY
+** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
+** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR
+** FITNESS FOR A PARTICULAR PURPOSE.
+**
+** You should have received a copy of the CPL along with this file.
+** See the LICENSE file and the cpl1.0.txt file included with the source
+** distribution for more information. If you did not receive a copy of the
+** license, contact the Qxt Foundation.
+**
+** <http://libqxt.sourceforge.net> <foundation@libqxt.org>
+**
+****************************************************************************/
+
+#ifndef QXTBOUNDCFUNCTION_H
+#define QXTBOUNDCFUNCTION_H
+
+#include <QObject>
+#include <QMetaObject>
+#include <QGenericArgument>
+#include <qxtmetaobject.h>
+#include <qxtboundfunctionbase.h>
+#include <qxtnull.h>
+#include <QThread>
+/*
+template <typename FUNCTION, int argc, typename RETURN = void>
+class QxtBoundCFunction : public QxtBoundFunctionBase {
+public:
+ FUNCTION funcPtr;
+
+ QxtBoundCFunction(QObject* parent, FUNCTION funcPointer, QGenericArgument* params[argc], QByteArray types[argc]) : QxtBoundFunctionBase(parent, params, types), funcPtr(funcPointer) {
+ // initializers only, thanks to template magic
+ }
+
+ virtual bool invokeImpl(Qt::ConnectionType type, QGenericReturnArgument returnValue, QXT_IMPL_10ARGS(QGenericArgument)) {
+ return qxt_invoke_cfunction_return<FUNCTION, argc, RETURN>(funcPtr, returnValue, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
+ }
+};
+
+template <typename FUNCTION, int argc>
+class QxtBoundCFunction<FUNCTION, argc, void> : public QxtBoundFunctionBase {
+public:
+ FUNCTION funcPtr;
+
+ QxtBoundCFunction(QObject* parent, FUNCTION funcPointer, QGenericArgument* params[argc], QByteArray types[argc]) : QxtBoundFunctionBase(parent, params, types), funcPtr(funcPointer) {
+ // initializers only, thanks to template magic
+ }
+
+ virtual bool invokeImpl(Qt::ConnectionType type, QGenericReturnArgument returnValue, QXT_IMPL_10ARGS(QGenericArgument)) {
+ return qxt_invoke_cfunction<FUNCTION, argc>(funcPtr, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
+ }
+};
+
+QGenericArgument* qbcfP[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+QByteArray types[10] = { "", "", "", "", "", "", "", "", "", "" };
+
+void testFunction(int a) { a++; return; }
+template < typename FP > QxtBoundFunction* testBind(FP fn) { return new QxtBoundCFunction<FP, 1>(0, fn, qbcfP, types); }
+QxtBoundCFunction<void(*)(int), 1> qbcf(0, testFunction, qbcfP, types);
+QxtBoundFunction* qbf = testBind(testFunction);
+*/
+#endif
--- /dev/null
+/****************************************************************************
+**
+** Copyright (C) Qxt Foundation. Some rights reserved.
+**
+** This file is part of the QxtCore module of the Qt eXTension library
+**
+** This library is free software; you can redistribute it and/or modify it
+** under the terms of th Common Public License, version 1.0, as published by
+** IBM.
+**
+** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY
+** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
+** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR
+** FITNESS FOR A PARTICULAR PURPOSE.
+**
+** You should have received a copy of the CPL along with this file.
+** See the LICENSE file and the cpl1.0.txt file included with the source
+** distribution for more information. If you did not receive a copy of the
+** license, contact the Qxt Foundation.
+**
+** <http://libqxt.sourceforge.net> <foundation@libqxt.org>
+**
+****************************************************************************/
+
+#ifndef QXTBOUNDFUNCTION_H
+#define QXTBOUNDFUNCTION_H
+
+#include <QObject>
+#include <QMetaObject>
+#include <QGenericArgument>
+#include <qxtmetaobject.h>
+#include <qxtnull.h>
+#include <QThread>
+
+class QxtBoundFunction : public QObject
+{
+ Q_OBJECT
+public:
+ template <class T>
+ inline QxtNullable<T> invoke(QXT_PROTO_10ARGS(QVariant))
+ {
+ if (QThread::currentThread() == parent()->thread())
+ return invoke<T>(Qt::DirectConnection, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
+#if QT_VERSION >= 0x040300
+ return invoke<T>(Qt::BlockingQueuedConnection, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
+#else
+ qWarning() << "QxtBoundFunction::invoke: Cannot return a value using a queued connection";
+ return QxtNull;
+#endif
+ }
+
+ template <class T>
+ QxtNullable<T> invoke(Qt::ConnectionType type, QXT_PROTO_10ARGS(QVariant))
+ {
+ if (type == Qt::QueuedConnection)
+ {
+ qWarning() << "QxtBoundFunction::invoke: Cannot return a value using a queued connection";
+ return qxtNull;
+ }
+ T retval;
+ // I know this is a totally ugly function call
+ if (invoke(type, QGenericReturnArgument(qVariantFromValue<T>(*reinterpret_cast<T*>(0)).typeName(), reinterpret_cast<void*>(&retval)),
+ p1, p2, p3, p4, p5, p6, p7, p8, p9, p10))
+ {
+ return retval;
+ }
+ else
+ {
+ return qxtNull;
+ }
+ }
+
+ inline bool invoke(QXT_PROTO_10ARGS(QVariant))
+ {
+ return invoke(Qt::AutoConnection, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
+ }
+ bool invoke(Qt::ConnectionType, QXT_PROTO_10ARGS(QVariant));
+
+ inline bool invoke(QXT_PROTO_10ARGS(QGenericArgument))
+ {
+ return invoke(Qt::AutoConnection, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
+ }
+ inline bool invoke(Qt::ConnectionType type, QXT_PROTO_10ARGS(QGenericArgument)) {
+ return invoke(type, QGenericReturnArgument(), p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
+ }
+
+ inline bool invoke(QGenericReturnArgument returnValue, QXT_PROTO_10ARGS(QVariant))
+ {
+ return invoke(Qt::AutoConnection, returnValue, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
+ }
+ bool invoke(Qt::ConnectionType type, QGenericReturnArgument returnValue, QXT_PROTO_10ARGS(QVariant));
+
+ inline bool invoke(QGenericReturnArgument returnValue, QXT_PROTO_10ARGS(QGenericArgument))
+ {
+ return invoke(Qt::AutoConnection, returnValue, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
+ }
+ bool invoke(Qt::ConnectionType type, QGenericReturnArgument returnValue, QXT_PROTO_10ARGS(QGenericArgument));
+
+protected:
+ QxtBoundFunction(QObject* parent = 0);
+ virtual bool invokeImpl(Qt::ConnectionType type, QGenericReturnArgument returnValue, QXT_PROTO_10ARGS(QGenericArgument)) = 0;
+};
+
+#endif
--- /dev/null
+/****************************************************************************
+**
+** Copyright (C) Qxt Foundation. Some rights reserved.
+**
+** This file is part of the QxtCore module of the Qt eXTension library
+**
+** This library is free software; you can redistribute it and/or modify it
+** under the terms of th Common Public License, version 1.0, as published by
+** IBM.
+**
+** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY
+** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
+** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR
+** FITNESS FOR A PARTICULAR PURPOSE.
+**
+** You should have received a copy of the CPL along with this file.
+** See the LICENSE file and the cpl1.0.txt file included with the source
+** distribution for more information. If you did not receive a copy of the
+** license, contact the Qxt Foundation.
+**
+** <http://libqxt.sourceforge.net> <foundation@libqxt.org>
+**
+****************************************************************************/
+
+// This file exists for the convenience of QxtBoundCFunction.
+// It is not part of the public API and is subject to change.
+//
+// We mean it.
+
+#ifndef QXTBOUNDFUNCTIONBASE_H
+#define QXTBOUNDFUNCTIONBASE_H
+
+#include <QObject>
+#include <QMetaObject>
+#include <QGenericArgument>
+#include <qxtmetaobject.h>
+#include <qxtboundfunction.h>
+
+class QxtBoundFunctionBase : public QxtBoundFunction
+{
+public:
+ QByteArray bindTypes[10];
+ QGenericArgument arg[10], p[10];
+ void* data[10];
+
+ QxtBoundFunctionBase(QObject* parent, QGenericArgument* params[10], QByteArray types[10]);
+ virtual ~QxtBoundFunctionBase();
+
+ int qt_metacall(QMetaObject::Call _c, int _id, void **_a);
+ bool invokeBase(Qt::ConnectionType type, QGenericReturnArgument returnValue, QXT_PROTO_10ARGS(QGenericArgument));
+};
+
+#endif
** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY
** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR
-** FITNESS FOR A PARTICULAR PURPOSE.
+** FITNESS FOR A PARTICULAR PURPOSE.
**
** You should have received a copy of the CPL along with this file.
** See the LICENSE file and the cpl1.0.txt file included with the source
** distribution for more information. If you did not receive a copy of the
** license, contact the Qxt Foundation.
-**
+**
** <http://libqxt.sourceforge.net> <foundation@libqxt.org>
**
****************************************************************************/
-#define QXT_VERSION ( (2<<16) + (2<<8) + 3 )
+#define QXT_VERSION ( (2<<16) + (2<<8) + 3 )
--- /dev/null
+/****************************************************************************
+**
+** Copyright (C) Qxt Foundation. Some rights reserved.
+**
+** This file is part of the QxtCore module of the Qt eXTension library
+**
+** This library is free software; you can redistribute it and/or modify it
+** under the terms of th Common Public License, version 1.0, as published by
+** IBM.
+**
+** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY
+** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
+** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR
+** FITNESS FOR A PARTICULAR PURPOSE.
+**
+** You should have received a copy of the CPL along with this file.
+** See the LICENSE file and the cpl1.0.txt file included with the source
+** distribution for more information. If you did not receive a copy of the
+** license, contact the Qxt Foundation.
+**
+** <http://libqxt.sourceforge.net> <foundation@libqxt.org>
+**
+****************************************************************************/
+/**
+\class QxtMetaObject QxtMetaObject
+
+\ingroup core
+
+\brief provides extensions to QMetaObject
+
+including QxtMetaObject::bind \n
+
+*/
+#include "qxtmetaobject.h"
+#include "qxtboundfunction.h"
+#include "qxtboundcfunction.h"
+
+#include <QByteArray>
+#include <QMetaObject>
+#include <QMetaMethod>
+#include <QtDebug>
+
+class QxtBoundArgument
+{
+ // This class intentionally left blank
+};
+Q_DECLARE_METATYPE(QxtBoundArgument)
+
+class QxtBoundFunctionBase;
+
+QxtBoundFunction::QxtBoundFunction(QObject* parent) : QObject(parent)
+{
+ // initializer only
+}
+
+#define QXT_ARG(i) ((argCount>i)?QGenericArgument(p ## i .typeName(), p ## i .constData()):QGenericArgument())
+#define QXT_VAR_ARG(i) (p ## i .isValid())?QGenericArgument(p ## i .typeName(), p ## i .constData()):QGenericArgument()
+bool QxtBoundFunction::invoke(Qt::ConnectionType type, QXT_IMPL_10ARGS(QVariant))
+{
+ return invoke(type, QXT_VAR_ARG(1), QXT_VAR_ARG(2), QXT_VAR_ARG(3), QXT_VAR_ARG(4), QXT_VAR_ARG(5), QXT_VAR_ARG(6), QXT_VAR_ARG(7), QXT_VAR_ARG(8), QXT_VAR_ARG(9), QXT_VAR_ARG(10));
+}
+
+bool QxtBoundFunction::invoke(Qt::ConnectionType type, QGenericReturnArgument returnValue, QXT_IMPL_10ARGS(QVariant))
+{
+ return invoke(type, returnValue, QXT_VAR_ARG(1), QXT_VAR_ARG(2), QXT_VAR_ARG(3), QXT_VAR_ARG(4), QXT_VAR_ARG(5), QXT_VAR_ARG(6), QXT_VAR_ARG(7), QXT_VAR_ARG(8), QXT_VAR_ARG(9), QXT_VAR_ARG(10));
+}
+
+QxtBoundFunctionBase::QxtBoundFunctionBase(QObject* parent, QGenericArgument* params[10], QByteArray types[10]) : QxtBoundFunction(parent)
+{
+ for (int i=0; i<10; i++)
+ {
+ if (!params[i]) break;
+ if (QByteArray(params[i]->name()) == "QxtBoundArgument")
+ {
+ arg[i] = QGenericArgument("QxtBoundArgument", params[i]->data());
+ }
+ else
+ {
+ data[i] = QMetaType::construct(QMetaType::type(params[i]->name()), params[i]->data());
+ arg[i] = p[i] = QGenericArgument(params[i]->name(), data[i]);
+ }
+ bindTypes[i] = types[i];
+ }
+}
+
+QxtBoundFunctionBase::~QxtBoundFunctionBase()
+{
+ for (int i=0; i<10; i++)
+ {
+ if (arg[i].name() == 0) return;
+ if (QByteArray(arg[i].name()) != "QxtBoundArgument") QMetaType::destroy(QMetaType::type(arg[i].name()), arg[i].data());
+ }
+}
+
+int QxtBoundFunctionBase::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
+{
+ _id = QObject::qt_metacall(_c, _id, _a);
+ if (_id < 0)
+ return _id;
+ if (_c == QMetaObject::InvokeMetaMethod)
+ {
+ if (_id == 0)
+ {
+ for (int i = 0; i < 10; i++)
+ {
+ if (QByteArray(arg[i].name()) == "QxtBoundArgument")
+ {
+ p[i] = QGenericArgument(bindTypes[i].constData(), _a[(quintptr)(arg[i].data())]);
+ }
+ }
+ invokeImpl(Qt::DirectConnection, QGenericReturnArgument(), p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8], p[9]);
+ }
+ _id = -1;
+ }
+ return _id;
+}
+
+bool QxtBoundFunctionBase::invokeBase(Qt::ConnectionType type, QGenericReturnArgument returnValue, QXT_IMPL_10ARGS(QGenericArgument))
+{
+ QGenericArgument* args[10] = { &p1, &p2, &p3, &p4, &p5, &p6, &p7, &p8, &p9, &p10 };
+ for (int i = 0; i < 10; i++)
+ {
+ if (QByteArray(arg[i].name()) == "QxtBoundArgument")
+ {
+ p[i] = *args[(quintptr)(arg[i].data())-1];
+ }
+ }
+ return invokeImpl(type, returnValue, p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8], p[9]);
+}
+
+bool QxtBoundFunction::invoke(Qt::ConnectionType type, QGenericReturnArgument returnValue, QXT_IMPL_10ARGS(QGenericArgument))
+{
+ return reinterpret_cast<QxtBoundFunctionBase*>(this)->invokeBase(type, returnValue, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
+}
+
+class QxtBoundSlot : public QxtBoundFunctionBase
+{
+public:
+ QByteArray sig;
+
+ QxtBoundSlot(QObject* receiver, const char* invokable, QGenericArgument* params[10], QByteArray types[10]) : QxtBoundFunctionBase(receiver, params, types), sig(invokable)
+ {
+ // initializers only
+ }
+
+ virtual bool invokeImpl(Qt::ConnectionType type, QGenericReturnArgument returnValue, QXT_IMPL_10ARGS(QGenericArgument))
+ {
+ if (!QMetaObject::invokeMethod(parent(), QxtMetaObject::methodName(sig.constData()), type, returnValue, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10))
+ {
+ qWarning() << "QxtBoundFunction: call to" << sig << "failed";
+ return false;
+ }
+ return true;
+ }
+};
+
+namespace QxtMetaObject
+{
+
+/*!
+\relates QxtMetaObject
+
+ \fn methodName(const char* method)
+
+ Returns the name of the given method.
+
+ Example usage:
+ \code
+ QByteArray method = QxtMetaObject::methodName(" int foo ( int bar, double baz )");
+ // method is now "foo"
+ \endcode
+ */
+QByteArray methodName(const char* method)
+{
+ QByteArray name = methodSignature(method);
+ const int idx = name.indexOf("(");
+ if (idx != -1)
+ name.truncate(idx);
+ return name;
+}
+
+/*!
+\relates QxtMetaObject
+
+\fn methodSignature(const char* method)
+
+Returns the signature of the given method.
+ */
+QByteArray methodSignature(const char* method)
+{
+ QByteArray name = QMetaObject::normalizedSignature(method);
+ if (name.startsWith("1") || name.startsWith("2"))
+ return name.mid(1);
+ return name;
+}
+
+/*!
+\relates QxtMetaObject
+
+\fn bool isSignalOrSlot(const char* method)
+
+checks if \p method contains parantesis and begins with 1 or 2 */
+bool isSignalOrSlot (const char* method)
+{
+ QByteArray m(method);
+ return (m.count() && (m[0] == '1'||m[0] == '2') && m.contains('(') && m.contains(')'));
+}
+
+/**
+\relates QxtMetaObject
+\fn bind(QObject* recv, const char* invokable, QXT_IMPL_10ARGS(QVariant))
+
+creates a QxtBoundFunction from a slot + arguments \n
+can be used for QxtMetaObject::connect \
+
+\code
+QxtMetaObject::connect(\n
+ this, SIGNAL(init()), \\n
+ QxtMetaObject::bind(this, SLOT(say(QString)), Q_ARG(QString,"hello")));
+\endcode
+\n
+\code
+QxtMetaObject::connect( \n
+ this, SIGNAL(init(int i)), \n
+ QxtMetaObject::bind(this, SLOT(say(QString),int), Q_ARG(QString,"hello"),Q_BIND(1)));
+\endcode
+
+ */
+QxtBoundFunction* bind(QObject* recv, const char* invokable, QXT_IMPL_10ARGS(QVariant))
+{
+ if (!recv)
+ {
+ qWarning() << "QxtMetaObject::bind: cannot connect to null QObject";
+ return 0;
+ }
+
+ QVariant* args[10] = { &p1, &p2, &p3, &p4, &p5, &p6, &p7, &p8, &p9, &p10 };
+ QByteArray connSlot("2"), recvSlot(QMetaObject::normalizedSignature(invokable));
+ const QMetaObject* meta = recv->metaObject();
+ int methodID = meta->indexOfMethod(QxtMetaObject::methodSignature(recvSlot.constData()));
+ if (methodID == -1)
+ {
+ qWarning() << "QxtMetaObject::bind: no such method " << recvSlot;
+ return 0;
+ }
+ QMetaMethod method = meta->method(methodID);
+ int argCount = method.parameterTypes().count();
+ const QList<QByteArray> paramTypes = method.parameterTypes();
+
+ for (int i=0; i<argCount; i++)
+ {
+ if (paramTypes[i] == "QxtBoundArgument") continue;
+ int type = QMetaType::type(paramTypes[i].constData());
+ if (!args[i]->canConvert((QVariant::Type)type))
+ {
+ qWarning() << "QxtMetaObject::bind: incompatible parameter list for " << recvSlot;
+ return 0;
+ }
+ }
+
+ return QxtMetaObject::bind(recv, invokable, QXT_ARG(1), QXT_ARG(2), QXT_ARG(3), QXT_ARG(4), QXT_ARG(5), QXT_ARG(6), QXT_ARG(7), QXT_ARG(8), QXT_ARG(9), QXT_ARG(10));
+}
+
+QxtBoundFunction* bind(QObject* recv, const char* invokable, QXT_IMPL_10ARGS(QGenericArgument))
+{
+ if (!recv)
+ {
+ qWarning() << "QxtMetaObject::bind: cannot connect to null QObject";
+ return 0;
+ }
+
+ QGenericArgument* args[10] = { &p1, &p2, &p3, &p4, &p5, &p6, &p7, &p8, &p9, &p10 };
+ QByteArray connSlot("2"), recvSlot(QMetaObject::normalizedSignature(invokable)), bindTypes[10];
+ const QMetaObject* meta = recv->metaObject();
+ int methodID = meta->indexOfMethod(QxtMetaObject::methodSignature(recvSlot.constData()).constData());
+ if (methodID == -1)
+ {
+ qWarning() << "QxtMetaObject::bind: no such method " << recvSlot;
+ return 0;
+ }
+ QMetaMethod method = meta->method(methodID);
+ int argCount = method.parameterTypes().count();
+
+ connSlot += QxtMetaObject::methodName(invokable) + "(";
+ for (int i=0; i<10; i++)
+ {
+ if (args[i]->name() == 0) break; // done
+ if (i >= argCount)
+ {
+ qWarning() << "QxtMetaObject::bind: too many arguments passed to " << invokable;
+ return 0;
+ }
+ if (i > 0) connSlot += ","; // argument separator
+ if (QByteArray(args[i]->name()) == "QxtBoundArgument")
+ {
+ Q_ASSERT_X((quintptr)(args[i]->data()) > 0 && (quintptr)(args[i]->data()) <= 10, "QXT_BIND", "invalid argument number");
+ connSlot += method.parameterTypes()[i];
+ bindTypes[i] = method.parameterTypes()[i];
+ }
+ else
+ {
+ connSlot += args[i]->name(); // type name
+ }
+ }
+ connSlot = QMetaObject::normalizedSignature(connSlot += ")");
+
+ if (!QMetaObject::checkConnectArgs(recvSlot.constData(), connSlot.constData()))
+ {
+ qWarning() << "QxtMetaObject::bind: provided parameters " << connSlot.mid(connSlot.indexOf('(')) << " is incompatible with " << invokable;
+ return 0;
+ }
+
+ return new QxtBoundSlot(recv, invokable, args, bindTypes);
+}
+
+/**
+\relates QxtMetaObject
+\fn connect(QObject* sender, const char* signal, QxtBoundFunction* slot, Qt::ConnectionType type) {
+
+connects a signal to a QxtBoundFunction \n
+ */
+bool connect(QObject* sender, const char* signal, QxtBoundFunction* slot, Qt::ConnectionType type)
+{
+ const QMetaObject* meta = sender->metaObject();
+ int methodID = meta->indexOfMethod(meta->normalizedSignature(signal).mid(1).constData());
+ if (methodID < 0)
+ {
+ qWarning() << "QxtMetaObject::connect: no such signal: " << QByteArray(signal).mid(1);
+ return false;
+ }
+
+ return QMetaObject::connect(sender, methodID, slot, QObject::staticMetaObject.methodCount(), (int)(type));
+}
+
+}
--- /dev/null
+/****************************************************************************
+**
+** Copyright (C) Qxt Foundation. Some rights reserved.
+**
+** This file is part of the QxtCore module of the Qt eXTension library
+**
+** This library is free software; you can redistribute it and/or modify it
+** under the terms of th Common Public License, version 1.0, as published by
+** IBM.
+**
+** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY
+** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
+** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR
+** FITNESS FOR A PARTICULAR PURPOSE.
+**
+** You should have received a copy of the CPL along with this file.
+** See the LICENSE file and the cpl1.0.txt file included with the source
+** distribution for more information. If you did not receive a copy of the
+** license, contact the Qxt Foundation.
+**
+** <http://libqxt.sourceforge.net> <foundation@libqxt.org>
+**
+****************************************************************************/
+#ifndef QXTMETAOBJECT_H
+#define QXTMETAOBJECT_H
+
+#include <QMetaObject>
+#include <QVariant>
+#include <QGenericArgument>
+#include "qxtnullable.h"
+class QByteArray;
+class QxtBoundArgument;
+class QxtBoundFunction;
+
+#define QXT_PROTO_10ARGS(T) T p1 = T(), T p2 = T(), T p3 = T(), T p4 = T(), \
+ T p5 = T(), T p6 = T(), T p7 = T(), T p8 = T(), T p9 = T(), T p10 = T()
+#define QXT_IMPL_10ARGS(T) T p1, T p2, T p3, T p4, T p5, T p6, T p7, T p8, T p9, T p10
+namespace QxtMetaObject
+{
+QByteArray methodName(const char* method);
+QByteArray methodSignature(const char* method);
+
+bool isSignalOrSlot (const char* method);
+
+
+QxtBoundFunction* bind(QObject* recv, const char* invokable, QXT_PROTO_10ARGS(QVariant));
+QxtBoundFunction* bind(QObject* recv, const char* invokable, QXT_PROTO_10ARGS(QGenericArgument));
+template <typename FP>
+QxtBoundFunction* bindFunction(FP funcPointer, QXT_PROTO_10ARGS(QGenericArgument));
+template <class T, typename FP>
+QxtBoundFunction* bindMethod(T recv, FP funcPointer, QXT_PROTO_10ARGS(QGenericArgument));
+bool connect(QObject* sender, const char* signal, QxtBoundFunction* slot,
+ Qt::ConnectionType type = Qt::AutoConnection);
+}
+
+#define QXT_BIND(i) QGenericArgument("QxtBoundArgument", reinterpret_cast<void*>(i))
+
+#endif // QXTMETAOBJECT_H
--- /dev/null
+#include "qxtnull.h"
+
+QxtNull qxtNull; // static storage for extern
--- /dev/null
+/****************************************************************************
+**
+** Copyright (C) Qxt Foundation. Some rights reserved.
+**
+** This file is part of the QxtCore module of the Qt eXTension library
+**
+** This library is free software; you can redistribute it and/or modify it
+** under the terms of th Common Public License, version 1.0, as published by
+** IBM.
+**
+** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY
+** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
+** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR
+** FITNESS FOR A PARTICULAR PURPOSE.
+**
+** You should have received a copy of the CPL along with this file.
+** See the LICENSE file and the cpl1.0.txt file included with the source
+** distribution for more information. If you did not receive a copy of the
+** license, contact the Qxt Foundation.
+**
+** <http://libqxt.sourceforge.net> <foundation@libqxt.org>
+**
+****************************************************************************/
+
+#ifndef QXTNULL_DEFINED
+#define QXTNULL_DEFINED
+#include <qxtglobal.h>
+
+/**
+\class QxtNull QxtNull
+
+
+\ingroup core
+
+\brief An object representing the "null" value for QxtNullable.
+
+seealso: QxtNullable
+*/
+
+struct QXT_CORE_EXPORT QxtNull
+{
+ /** integer cast operator
+ * In expressions, QxtNull behaves as an integer zero for compatibility with generic functions.
+ */
+ operator int() const
+ {
+ return 0;
+ }
+ enum { isNull = true };
+};
+
+/*! \relates QxtNull
+ * A predefined null object that can be assigned to any QxtNullable object.
+ */
+extern QxtNull qxtNull;
+
+#ifndef QXT_NO_MACROS
+/*! \relates QxtNull
+ * A convenience alias for qxtNull.
+ */
+#define SKIP qxtNull
+#endif
+
+#endif
--- /dev/null
+/****************************************************************************
+**
+** Copyright (C) Qxt Foundation. Some rights reserved.
+**
+** This file is part of the QxtCore module of the Qt eXTension library
+**
+** This library is free software; you can redistribute it and/or modify it
+** under the terms of th Common Public License, version 1.0, as published by
+** IBM.
+**
+** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY
+** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
+** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR
+** FITNESS FOR A PARTICULAR PURPOSE.
+**
+** You should have received a copy of the CPL along with this file.
+** See the LICENSE file and the cpl1.0.txt file included with the source
+** distribution for more information. If you did not receive a copy of the
+** license, contact the Qxt Foundation.
+**
+** <http://libqxt.sourceforge.net> <foundation@libqxt.org>
+**
+****************************************************************************/
+
+/**
+\class QxtNullable QxtNullable
+\ingroup core
+\brief distinct null value compatible with any data type.
+
+in general it's a templated abstraction to allow any data type to be
+expressed with a null value distinct from any real value. An example
+of such a use is for optional arguments.
+\n
+prepare a function for argument skipping:
+
+\code
+void somefunction( qxtNull(int,a) , qxtNull(int,b) )
+{
+
+if (!a.isNull())
+ {
+ int i = a.value();
+ //do something with i
+ }
+ if (!b.isNull())
+ {
+ int x = b.value();
+ //do something with x
+ }
+}
+\endcode
+
+usage:
+\code
+
+somefunction(SKIP,1,2);
+somefunction(3,4);
+somefunction(3,SKIP,6);
+somefunction(1);
+\endcode
+
+*/
+
+#ifndef QXTNULLABLE_H
+#define QXTNULLABLE_H
+#include <qxtglobal.h>
+
+/*! \relates QxtNullable
+ * defines a skipable argument with type \a t and variable name \a n
+ */
+#define qxtNull(t,n) QxtNullable<t> n = QxtNullable<t>()
+
+#include <qxtnull.h>
+
+template<typename T>
+class QXT_CORE_EXPORT QxtNullable
+{
+public:
+ QxtNullable(QxtNull);
+ QxtNullable(const T& p);
+ QxtNullable();
+
+ ///determinates if the Value is set to something meaningfull
+ bool isNull() const;
+
+ ///delete Value
+ void nullify();
+
+ T& value() const;
+ operator T() const;
+ void operator=(const T& p);
+
+private:
+ T* val;
+};
+
+template<typename T>
+QxtNullable<T>::QxtNullable(QxtNull)
+{
+ val = 0;
+}
+
+template<typename T>
+QxtNullable<T>::QxtNullable(const T& p)
+{
+ val = const_cast<T*>(&p);
+}
+
+template<typename T>
+QxtNullable<T>::QxtNullable()
+{
+ val = 0;
+}
+
+template<typename T>
+QxtNullable<T>::operator T() const
+{
+ return *val;
+}
+
+template<typename T>
+T& QxtNullable<T>::value() const
+{
+ return *val;
+}
+
+template<typename T>
+bool QxtNullable<T>::isNull() const
+{
+ return (val==0);
+}
+
+template<typename T>
+void QxtNullable<T>::nullify()
+{
+ val=0;
+}
+
+template<typename T>
+void QxtNullable<T>::operator=(const T& p)
+{
+ val = const_cast<T*>(&p);
+}
+
+#endif
** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY
** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR
-** FITNESS FOR A PARTICULAR PURPOSE.
+** FITNESS FOR A PARTICULAR PURPOSE.
**
** You should have received a copy of the CPL along with this file.
** See the LICENSE file and the cpl1.0.txt file included with the source
** distribution for more information. If you did not receive a copy of the
** license, contact the Qxt Foundation.
-**
+**
** <http://libqxt.sourceforge.net> <foundation@libqxt.org>
**
****************************************************************************/
\class QxtPimpl QxtPimpl
\ingroup core
\brief Hide private details of a class
-
+
Application code generally doesn't have to be concerned about hiding its
implementation details, but when writing library code it is important to
maintain a constant interface, both source and binary. Maintaining a constant
d-pointer, idiom is a common method of implementing this separation. QxtPimpl
offers a convenient way to connect the public and private sides of your class.
-\section start Getting Started
+\section start Getting Started
Before you declare the public class, you need to make a forward declaration
of the private class. The private class must have the same name as the public
class, followed by the word Private. For example, a class named MyTest would
class MyTestPrivate;
\endcode
-\subsection pub The Public Class
+\subsection pub The Public Class
Generally, you shouldn't keep any data members in the public class without a
good reason. Functions that are part of the public interface should be declared
in the public class, and functions that need to be available to subclasses (for
-calling or overriding) should be in the protected section of the public class.
+calling or overriding) should be in the protected section of the public class.
To connect the private class to the public class, include the
QXT_DECLARE_PRIVATE macro in the private section of the public class. In the
-example above, the private class is connected as follows:
+example above, the private class is connected as follows:
\code
private:
QXT_DECLARE_PRIVATE(MyTest);
Additionally, you must include the QXT_INIT_PRIVATE macro in the public class's
constructor. Continuing with the MyTest example, your constructor might look
-like this:
+like this:
\code
MyTest::MyTest() {
// initialization
}
\endcode
-\subsection priv The Private Class
+\subsection priv The Private Class
As mentioned above, data members should usually be kept in the private class.
This allows the memory layout of the private class to change without breaking
binary compatibility for the public class. Functions that exist only as
implementation details, or functions that need access to private data members,
-should be implemented here.
+should be implemented here.
To define the private class, inherit from the template QxtPrivate class, and
include the QXT_DECLARE_PUBLIC macro in its public section. The template
*
* This may be put anywhere in the declaration of the private class. The parameter is the name of the public class.
*/
-#define QXT_DECLARE_PUBLIC(PUB) friend class PUB;
+#define QXT_DECLARE_PUBLIC(PUB) friend class PUB;
/*! \relates QxtPimpl
* Initializes resources owned by the private class.
*
#ifndef QXT_DOXYGEN_RUN
template <typename PUB>
-class QxtPrivate {
+class QxtPrivate
+{
public:
- virtual ~QxtPrivate() {}
- inline void QXT_setPublic(PUB* pub) { qxt_p_ptr = pub; }
+ virtual ~QxtPrivate()
+ {}
+ inline void QXT_setPublic(PUB* pub)
+ {
+ qxt_p_ptr = pub;
+ }
protected:
- inline PUB& qxt_p() { return *qxt_p_ptr; }
- inline const PUB& qxt_p() const { return *qxt_p_ptr; }
+ inline PUB& qxt_p()
+ {
+ return *qxt_p_ptr;
+ }
+ inline const PUB& qxt_p() const
+ {
+ return *qxt_p_ptr;
+ }
private:
PUB* qxt_p_ptr;
};
template <typename PUB, typename PVT>
-class QxtPrivateInterface {
-friend class QxtPrivate<PUB>;
+class QxtPrivateInterface
+{
+ friend class QxtPrivate<PUB>;
public:
- QxtPrivateInterface() { pvt = new PVT; }
- ~QxtPrivateInterface() { delete pvt; }
-
- inline void setPublic(PUB* pub) { pvt->QXT_setPublic(pub); }
- inline PVT& operator()() { return *static_cast<PVT*>(pvt); }
- inline const PVT& operator()() const { return *static_cast<PVT*>(pvt); }
+ QxtPrivateInterface()
+ {
+ pvt = new PVT;
+ }
+ ~QxtPrivateInterface()
+ {
+ delete pvt;
+ }
+
+ inline void setPublic(PUB* pub)
+ {
+ pvt->QXT_setPublic(pub);
+ }
+ inline PVT& operator()()
+ {
+ return *static_cast<PVT*>(pvt);
+ }
+ inline const PVT& operator()() const
+ {
+ return *static_cast<PVT*>(pvt);
+ }
private:
QxtPrivate<PUB>* pvt;
};
/****************************************************************************
-**
-** Copyright (C) Qxt Foundation. Some rights reserved.
-**
-** This file is part of the QxtNetwork module of the Qt eXTension library
-**
-** This library is free software; you can redistribute it and/or modify it
-** under the terms of th Common Public License, version 1.0, as published by
-** IBM.
-**
-** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY
-** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
-** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR
-** FITNESS FOR A PARTICULAR PURPOSE.
-**
-** You should have received a copy of the CPL along with this file.
-** See the LICENSE file and the cpl1.0.txt file included with the source
-** distribution for more information. If you did not receive a copy of the
-** license, contact the Qxt Foundation.
-**
-** <http://libqxt.sourceforge.net> <foundation@libqxt.org>
-**
-****************************************************************************/
+ **
+ ** Copyright (C) Qxt Foundation. Some rights reserved.
+ **
+ ** This file is part of the QxtNetwork module of the Qt eXTension library
+ **
+ ** This library is free software; you can redistribute it and/or modify it
+ ** under the terms of th Common Public License, version 1.0, as published by
+ ** IBM.
+ **
+ ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY
+ ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
+ ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR
+ ** FITNESS FOR A PARTICULAR PURPOSE.
+ **
+ ** You should have received a copy of the CPL along with this file.
+ ** See the LICENSE file and the cpl1.0.txt file included with the source
+ ** distribution for more information. If you did not receive a copy of the
+ ** license, contact the Qxt Foundation.
+ **
+ ** <http://libqxt.sourceforge.net> <foundation@libqxt.org>
+ **
+ ****************************************************************************/
#include "qxtrpcpeer.h"
#include <QObject>
#include <QDebug>
#include <QMetaMethod>
#include <cassert>
-
-class QxtIntrospector: public QObject {
- // This class MANUALLY implements the necessary parts of QObject.
- // Do NOT add the Q_OBJECT macro. As this class isn't intended
- // for direct use, it doesn't offer any sort of useful meta-object.
+#include "qxtmetaobject.h"
+#include <QStack>
+
+class QxtIntrospector: public QObject
+{
+// This class MANUALLY implements the necessary parts of QObject.
+// Do NOT add the Q_OBJECT macro. As this class isn't intended
+// for direct use, it doesn't offer any sort of useful meta-object.
public:
QxtIntrospector(QxtRPCPeer* parent, QObject* source, const char* signal);
QList<int> argTypes;
};
-struct QxtRPCConnection {
+struct QxtRPCConnection
+{
QTcpSocket* socket;
QByteArray buffer;
QString lastMethod;
};
-class QxtRPCPeerPrivate : public QxtPrivate<QxtRPCPeer> {
+class QxtRPCPeerPrivate : public QxtPrivate<QxtRPCPeer>, public QTcpServer
+{
public:
QXT_DECLARE_PUBLIC(QxtRPCPeer);
+ void incomingConnection ( int socketDescriptor );
+
+
void receivePeerSignal(QString fn, QVariant p0 = QVariant(), QVariant p1 = QVariant(), QVariant p2 = QVariant(), QVariant p3 = QVariant(),
- QVariant p4 = QVariant(), QVariant p5 = QVariant(), QVariant p6 = QVariant(), QVariant p7 = QVariant(), QVariant p8 = QVariant()) const;
+ QVariant p4 = QVariant(), QVariant p5 = QVariant(), QVariant p6 = QVariant(), QVariant p7 = QVariant(), QVariant p8 = QVariant()) const;
void receiveClientSignal(quint64 id, QString fn, QVariant p0 = QVariant(), QVariant p1 = QVariant(), QVariant p2 = QVariant(), QVariant p3 = QVariant(),
- QVariant p4 = QVariant(), QVariant p5 = QVariant(), QVariant p6 = QVariant(), QVariant p7 = QVariant()) const;
+ QVariant p4 = QVariant(), QVariant p5 = QVariant(), QVariant p6 = QVariant(), QVariant p7 = QVariant()) const;
void processInput(QIODevice* socket, QByteArray& buffer);
typedef QHash<QObject*, QxtRPCConnection*> ConnHash;
ConnHash m_clients;
- QTcpServer* m_server;
- QIODevice* m_peer; ///aep: doom
+ QIODevice* m_peer;
QByteArray m_buffer;
int m_rpctype;
+
+
+ QStack<QTcpSocket*> pending_connections;
+
};
-QxtRPCPeer::QxtRPCPeer(QObject* parent) : QObject(parent) {
- QXT_INIT_PRIVATE(QxtRPCPeer);
- qxt_d().m_rpctype = Peer;
- qxt_d().m_server = new QTcpServer(this);
- qxt_d().m_peer = new QTcpSocket(this);
- QObject::connect(qxt_d().m_peer, SIGNAL(connected()), this, SIGNAL(peerConnected()));
- QObject::connect(qxt_d().m_peer, SIGNAL(disconnected()), this, SIGNAL(peerDisconnected()));
- QObject::connect(qxt_d().m_peer, SIGNAL(disconnected()), this, SLOT(disconnectSender()));
- QObject::connect(qxt_d().m_peer, SIGNAL(readyRead()), this, SLOT(dataAvailable()));
- QObject::connect(qxt_d().m_peer, SIGNAL(error(QAbstractSocket::SocketError)), this, SIGNAL(peerError(QAbstractSocket::SocketError)));
- QObject::connect(qxt_d().m_server, SIGNAL(newConnection()), this, SLOT(newConnection()));
+QxtRPCPeer::QxtRPCPeer(QObject* parent) : QObject(parent)
+{
+ QXT_INIT_PRIVATE(QxtRPCPeer);
+ qxt_d().m_rpctype = Peer;
+ qxt_d().m_peer = new QTcpSocket(this);
+ QObject::connect(qxt_d().m_peer, SIGNAL(connected()), this, SIGNAL(peerConnected()));
+ QObject::connect(qxt_d().m_peer, SIGNAL(disconnected()), this, SIGNAL(peerDisconnected()));
+ QObject::connect(qxt_d().m_peer, SIGNAL(disconnected()), this, SLOT(disconnectSender()));
+ QObject::connect(qxt_d().m_peer, SIGNAL(readyRead()), this, SLOT(dataAvailable()));
+ QObject::connect(qxt_d().m_peer, SIGNAL(error(QAbstractSocket::SocketError)), this, SIGNAL(peerError(QAbstractSocket::SocketError)));
}
-QxtRPCPeer::QxtRPCPeer(RPCTypes type, QObject* parent) : QObject(parent) {
- QXT_INIT_PRIVATE(QxtRPCPeer);
- qxt_d().m_rpctype = type;
- qxt_d().m_server = new QTcpServer(this);
- qxt_d().m_peer = new QTcpSocket(this);
- QObject::connect(qxt_d().m_peer, SIGNAL(connected()), this, SIGNAL(peerConnected()));
- QObject::connect(qxt_d().m_peer, SIGNAL(disconnected()), this, SIGNAL(peerDisconnected()));
- QObject::connect(qxt_d().m_peer, SIGNAL(disconnected()), this, SLOT(disconnectSender()));
- QObject::connect(qxt_d().m_peer, SIGNAL(readyRead()), this, SLOT(dataAvailable()));
- QObject::connect(qxt_d().m_peer, SIGNAL(error(QAbstractSocket::SocketError)), this, SIGNAL(peerError(QAbstractSocket::SocketError)));
- QObject::connect(qxt_d().m_server, SIGNAL(newConnection()), this, SLOT(newConnection()));
+
+QxtRPCPeer::QxtRPCPeer(RPCTypes type, QObject* parent) : QObject(parent)
+{
+ QXT_INIT_PRIVATE(QxtRPCPeer);
+ qxt_d().m_rpctype = type;
+ qxt_d().m_peer = new QTcpSocket(this);
+ QObject::connect(qxt_d().m_peer, SIGNAL(connected()), this, SIGNAL(peerConnected()));
+ QObject::connect(qxt_d().m_peer, SIGNAL(disconnected()), this, SIGNAL(peerDisconnected()));
+ QObject::connect(qxt_d().m_peer, SIGNAL(disconnected()), this, SLOT(disconnectSender()));
+ QObject::connect(qxt_d().m_peer, SIGNAL(readyRead()), this, SLOT(dataAvailable()));
+ QObject::connect(qxt_d().m_peer, SIGNAL(error(QAbstractSocket::SocketError)), this, SIGNAL(peerError(QAbstractSocket::SocketError)));
}
-QxtRPCPeer::QxtRPCPeer(QIODevice* device, RPCTypes type, QObject* parent) : QObject(parent) {
- if (!device->isOpen())
- {
- qWarning("QxtRPCPeer::the device you passed is not open!");
- }
+
+QxtRPCPeer::QxtRPCPeer(QIODevice* device, RPCTypes type, QObject* parent) : QObject(parent)
+{
+ if (!device->isOpen())
+ {
+ qWarning("QxtRPCPeer::the device you passed is not open!");
+ }
QXT_INIT_PRIVATE(QxtRPCPeer);
qxt_d().m_rpctype = type;
- qxt_d().m_server = new QTcpServer(this);
qxt_d().m_peer = device;
- if (qobject_cast<QTcpSocket *>(device)!=0)
- {
- QObject::connect(qxt_d().m_peer, SIGNAL(connected()), this, SIGNAL(peerConnected()));
- QObject::connect(qxt_d().m_peer, SIGNAL(disconnected()), this, SIGNAL(peerDisconnected()));
- QObject::connect(qxt_d().m_peer, SIGNAL(disconnected()), this, SLOT(disconnectSender()));
- QObject::connect(qxt_d().m_peer, SIGNAL(error(QAbstractSocket::SocketError)), this, SIGNAL(peerError(QAbstractSocket::SocketError)));
- }
+ if (qobject_cast<QAbstractSocket *>(device)!=0)
+ {
+ QObject::connect(qxt_d().m_peer, SIGNAL(connected()), this, SIGNAL(peerConnected()));
+ QObject::connect(qxt_d().m_peer, SIGNAL(disconnected()), this, SIGNAL(peerDisconnected()));
+ QObject::connect(qxt_d().m_peer, SIGNAL(disconnected()), this, SLOT(disconnectSender()));
+ QObject::connect(qxt_d().m_peer, SIGNAL(error(QAbstractSocket::SocketError)), this, SIGNAL(peerError(QAbstractSocket::SocketError)));
+ }
QObject::connect(qxt_d().m_peer, SIGNAL(readyRead()), this, SLOT(dataAvailable()));
- QObject::connect(qxt_d().m_server, SIGNAL(newConnection()), this, SLOT(newConnection()));
}
-void QxtRPCPeer::setRPCType(RPCTypes type) {
- if(qxt_d().m_peer->isOpen () || qxt_d().m_server->isListening()) {
+
+void QxtRPCPeer::setRPCType(RPCTypes type)
+{
+ if (qxt_d().m_peer->isOpen () || qxt_d().isListening())
+ {
qWarning() << "QxtRPCPeer: Cannot change RPC types while connected or listening";
return;
}
qxt_d().m_rpctype = type;
}
-QxtRPCPeer::RPCTypes QxtRPCPeer::rpcType() const {
+
+QxtRPCPeer::RPCTypes QxtRPCPeer::rpcType() const
+{
return (RPCTypes)(qxt_d().m_rpctype);
}
-void QxtRPCPeer::connect(QHostAddress addr, int port) {
- if(qxt_d().m_rpctype == Server) {
+
+void QxtRPCPeer::connect(QHostAddress addr, int port)
+{
+ if (qxt_d().m_rpctype == Server)
+ {
qWarning() << "QxtRPCPeer: Cannot connect outward in Server mode";
return;
- } else if(qxt_d().m_peer->isOpen ()) {
- qWarning() << "QxtRPCPeer: Already connected";
+ }
+
+ QAbstractSocket * sock = qobject_cast<QAbstractSocket*>(qxt_d().m_peer);
+ if (!sock)
+ {
+ qWarning("QxtRPCPeer: cannot connect a custom QIODevice");
return;
}
- QTcpSocket * sock = qobject_cast<QTcpSocket*>(qxt_d().m_peer);
- assert(sock);
+
+ if (sock->state()!=QAbstractSocket::UnconnectedState)
+ {
+ qWarning("QxtRPCPeer: Already connected");
+ return;
+ }
+
sock->connectToHost(addr, port);
}
-bool QxtRPCPeer::listen(QHostAddress iface, int port) {
- if(qxt_d().m_rpctype == Client) {
+
+bool QxtRPCPeer::listen(QHostAddress iface, int port)
+{
+ if (qxt_d().m_rpctype == Client)
+ {
qWarning() << "QxtRPCPeer: Cannot listen in Client mode";
return false;
- } else if(qxt_d().m_rpctype == Peer && qxt_d().m_peer->isOpen ()) {
+ }
+ else if (qxt_d().m_rpctype == Peer && qxt_d().m_peer->isOpen ())
+ {
qWarning() << "QxtRPCPeer: Cannot listen while connected to a peer";
return false;
- } else if(qxt_d().m_server->isListening()) {
+ }
+ else if (qxt_d().isListening())
+ {
qWarning() << "QxtRPCPeer: Already listening";
return false;
}
- return qxt_d().m_server->listen(iface, port);
+ return qxt_d().listen(iface, port);
}
-void QxtRPCPeer::disconnectPeer(quint64 id) {
- if(qxt_d().m_rpctype == Server && id==0) {
+
+void QxtRPCPeer::disconnectPeer(quint64 id)
+{
+ if (qxt_d().m_rpctype == Server && id==(quint64)-1)
+ {
qWarning() << "QxtRPCPeer: Server mode does not have a peer";
return;
- } else if(qxt_d().m_rpctype!= Server && id!=0) {
+ }
+ else if (qxt_d().m_rpctype!= Server && id!=(quint64)-1)
+ {
qWarning() << "QxtRPCPeer: Must specify a client ID to disconnect";
return;
}
QxtRPCConnection* conn;
- if(id==0) {
+ if (id==(quint64)-1)
+ {
qxt_d().m_peer->close();
- } else if((conn = qxt_d().m_clients.take((QObject*)(id)))!= 0) {
+ ///hackaround for qt bug
+ QAbstractSocket *s =qobject_cast<QAbstractSocket*>( qxt_d().m_peer);
+ if (s)
+ s->disconnectFromHost();
+
+ }
+ else if ((conn = qxt_d().m_clients.take((QObject*)(id)))!= 0)
+ {
conn->socket->disconnectFromHost();
conn->socket->deleteLater();
delete conn;
- } else {
+ }
+ else
+ {
qWarning() << "QxtRPCPeer: no client with id " << id;
}
}
-void QxtRPCPeer::disconnectAll() {
- if(qxt_d().m_rpctype!= Server)
+
+void QxtRPCPeer::disconnectAll()
+{
+ if (qxt_d().m_rpctype!= Server)
disconnectPeer();
- else {
- for(QxtRPCPeerPrivate::ConnHash::const_iterator i = qxt_d().m_clients.constBegin(); i!= qxt_d().m_clients.constEnd(); i++) {
+ else
+ {
+ for (QxtRPCPeerPrivate::ConnHash::const_iterator i = qxt_d().m_clients.constBegin(); i!= qxt_d().m_clients.constEnd(); i++)
+ {
(*i)->socket->deleteLater();
delete *i;
}
}
}
-void QxtRPCPeer::stopListening() {
- if(!qxt_d().m_server->isListening()) {
+
+void QxtRPCPeer::stopListening()
+{
+ if (!qxt_d().isListening())
+ {
qWarning() << "QxtRPCPeer: Not listening";
return;
}
- qxt_d().m_server->close();
+ qxt_d().close();
}
-bool QxtRPCPeer::attachSignal(QObject* sender, const char* signal, const QByteArray& rpcFunction) {
+
+bool QxtRPCPeer::attachSignal(QObject* sender, const char* signal, const QByteArray& rpcFunction)
+{
const QMetaObject* meta = sender->metaObject();
QByteArray sig(meta->normalizedSignature(signal).mid(1));
int methodID = meta->indexOfMethod(sig.constData());
- if(methodID == -1 || meta->method(methodID).methodType() != QMetaMethod::Signal) {
+ if (methodID == -1 || meta->method(methodID).methodType() != QMetaMethod::Signal)
+ {
qWarning() << "QxtRPCPeer::attachSignal: No such signal " << signal;
return false;
}
+
+
QxtIntrospector* spec = new QxtIntrospector(this, sender, signal);
- if(!rpcFunction.isEmpty()) {
- spec->rpcFunction = rpcFunction.simplified();
- } else {
- spec->rpcFunction = sig;
+ if (!rpcFunction.isEmpty())
+ {
+ if (QxtMetaObject::isSignalOrSlot(rpcFunction.constData()))
+ {
+ spec->rpcFunction = QMetaObject::normalizedSignature(rpcFunction.constData());
+ }
+ else
+ {
+ spec->rpcFunction = rpcFunction.simplified();
+ }
+ }
+ else
+ {
+ spec->rpcFunction = QMetaObject::normalizedSignature(signal);
}
qxt_d().attachedSignals.insertMulti(sender, spec);
return true;
}
-bool QxtRPCPeer::attachSlot(const QByteArray& rpcFunction, QObject* recv, const char* slot) {
+
+bool QxtRPCPeer::attachSlot(const QByteArray& rpcFunction, QObject* recv, const char* slot)
+{
const QMetaObject* meta = recv->metaObject();
int methodID = meta->indexOfMethod(meta->normalizedSignature(slot).mid(1));
- if(methodID == -1 || meta->method(methodID).methodType() == QMetaMethod::Method) {
+ if (methodID == -1 || meta->method(methodID).methodType() == QMetaMethod::Method)
+ {
qWarning() << "QxtRPCPeer::attachSlot: No such slot " << slot;
return false;
}
QString fn;
- if(rpcFunction[0] == '1' && rpcFunction.contains('(') && rpcFunction.contains(')')) {
- fn = QMetaObject::normalizedSignature(rpcFunction.mid(1).constData());
- } else {
+
+ if (QxtMetaObject::isSignalOrSlot(rpcFunction.constData()))
+ {
+ fn = QMetaObject::normalizedSignature(rpcFunction.constData());
+ }
+ else
+ {
fn = rpcFunction.simplified();
}
return true;
}
-void QxtRPCPeer::detachSender() {
+
+void QxtRPCPeer::detachSender()
+{
detachObject(sender());
}
-void QxtRPCPeer::detachObject(QObject* obj) {
+
+void QxtRPCPeer::detachObject(QObject* obj)
+{
foreach(QxtIntrospector* i, qxt_d().attachedSignals.values(obj)) i->deleteLater();
qxt_d().attachedSignals.remove(obj);
- foreach(QString slot, qxt_d().attachedSlots.keys()) {
- for(QList<QPair<QObject*, int> >::iterator i(qxt_d().attachedSlots[slot].begin());
- i!= qxt_d().attachedSlots[slot].end(); ) {
- if((*i).first == obj)
+ foreach(QString slot, qxt_d().attachedSlots.keys())
+ {
+ for (QList<QPair<QObject*, int> >::iterator i(qxt_d().attachedSlots[slot].begin());
+ i!= qxt_d().attachedSlots[slot].end(); )
+ {
+ if ((*i).first == obj)
i = qxt_d().attachedSlots[slot].erase(i);
else
i++;
}
}
-QByteArray QxtRPCPeer::serialize(QString fn, QVariant p1, QVariant p2, QVariant p3, QVariant p4, QVariant p5, QVariant p6, QVariant p7, QVariant p8, QVariant p9) const {
+
+QByteArray QxtRPCPeer::serialize(QString fn, QVariant p1, QVariant p2, QVariant p3, QVariant p4, QVariant p5, QVariant p6, QVariant p7, QVariant p8, QVariant p9) const
+{
QByteArray rv;
QDataStream str(&rv, QIODevice::WriteOnly);
str << fn;
unsigned char ct = 9;
- if(p1.isNull()) ct = 0;
- else if(p2.isNull()) ct = 1;
- else if(p3.isNull()) ct = 2;
- else if(p4.isNull()) ct = 3;
- else if(p5.isNull()) ct = 4;
- else if(p6.isNull()) ct = 5;
- else if(p7.isNull()) ct = 6;
- else if(p8.isNull()) ct = 7;
- else if(p9.isNull()) ct = 8;
+ if (p1.isNull()) ct = 0;
+ else if (p2.isNull()) ct = 1;
+ else if (p3.isNull()) ct = 2;
+ else if (p4.isNull()) ct = 3;
+ else if (p5.isNull()) ct = 4;
+ else if (p6.isNull()) ct = 5;
+ else if (p7.isNull()) ct = 6;
+ else if (p8.isNull()) ct = 7;
+ else if (p9.isNull()) ct = 8;
str << ct;
- if(ct--) str << p1;
- if(ct--) str << p2;
- if(ct--) str << p3;
- if(ct--) str << p4;
- if(ct--) str << p5;
- if(ct--) str << p6;
- if(ct--) str << p7;
- if(ct--) str << p8;
- if(ct--) str << p9;
+ if (ct--) str << p1;
+ if (ct--) str << p2;
+ if (ct--) str << p3;
+ if (ct--) str << p4;
+ if (ct--) str << p5;
+ if (ct--) str << p6;
+ if (ct--) str << p7;
+ if (ct--) str << p8;
+ if (ct--) str << p9;
rv.replace(QByteArray("\\"), QByteArray("\\\\"));
rv.replace(QByteArray("\n"), QByteArray("\\n"));
rv.append("\n");
return rv;
}
-void QxtRPCPeer::call(const char * signal , QVariant p1, QVariant p2, QVariant p3, QVariant p4, QVariant p5, QVariant p6, QVariant p7, QVariant p8, QVariant p9) {
+
+void QxtRPCPeer::call(const char * signal , QVariant p1, QVariant p2, QVariant p3, QVariant p4, QVariant p5, QVariant p6, QVariant p7, QVariant p8, QVariant p9)
+{
QByteArray sig=QMetaObject::normalizedSignature(signal);
- if(!qxt_d().m_peer->isOpen ())
- {
- qWarning("can't call on a closed device");
- return;
- }
+ QAbstractSocket * sock = qobject_cast<QAbstractSocket*>(qxt_d().m_peer);
+ if (!qxt_d().m_peer->isOpen () || ( sock && sock->state()!=QAbstractSocket::ConnectedState ))
+ {
+ qWarning("can't call on a closed device");
+ return;
+ }
qxt_d().m_peer->write(serialize(sig, p1, p2, p3, p4, p5, p6, p7, p8, p9));
}
-void QxtRPCPeer::callClientList(QList<quint64> ids, QString fn, QVariant p1, QVariant p2, QVariant p3, QVariant p4, QVariant p5, QVariant p6, QVariant p7, QVariant p8) {
+
+void QxtRPCPeer::callClientList(QList<quint64> ids, QString fn, QVariant p1, QVariant p2, QVariant p3, QVariant p4, QVariant p5, QVariant p6, QVariant p7, QVariant p8)
+{
QByteArray c = serialize(fn, p1, p2, p3, p4, p5, p6, p7, p8, QVariant());
- foreach(quint64 id, ids) {
+ foreach(quint64 id, ids)
+ {
QxtRPCConnection* conn = qxt_d().m_clients.value((QObject*)(id));
- if(!conn) {
+ if (!conn)
+ {
qWarning() << "QxtRPCPeer: no client with id" << id;
- } else {
+ }
+ else
+ {
conn->socket->write(c);
}
}
}
-void QxtRPCPeer::callClient(quint64 id, QString fn, QVariant p1, QVariant p2, QVariant p3, QVariant p4, QVariant p5, QVariant p6, QVariant p7, QVariant p8) {
+
+void QxtRPCPeer::callClient(quint64 id, QString fn, QVariant p1, QVariant p2, QVariant p3, QVariant p4, QVariant p5, QVariant p6, QVariant p7, QVariant p8)
+{
callClientList(QList<quint64>() << id, fn, p1, p2, p3, p4, p5, p6, p7, p8);
}
-void QxtRPCPeer::callClientsExcept(quint64 id, QString fn, QVariant p1, QVariant p2, QVariant p3, QVariant p4, QVariant p5, QVariant p6, QVariant p7, QVariant p8) {
+
+void QxtRPCPeer::callClientsExcept(quint64 id, QString fn, QVariant p1, QVariant p2, QVariant p3, QVariant p4, QVariant p5, QVariant p6, QVariant p7, QVariant p8)
+{
QList<quint64> cs = clients();
cs.removeAll(id);
callClientList(cs, fn, p1, p2, p3, p4, p5, p6, p7, p8);
}
+#include <QStringList>
#define QXT_ARG(i) ((numParams>i)?QGenericArgument(p ## i .typeName(), p ## i .constData()):QGenericArgument())
-void QxtRPCPeerPrivate::receivePeerSignal(QString fn, QVariant p0, QVariant p1, QVariant p2, QVariant p3, QVariant p4, QVariant p5, QVariant p6, QVariant p7, QVariant p8) const {
+void QxtRPCPeerPrivate::receivePeerSignal(QString fn, QVariant p0, QVariant p1, QVariant p2, QVariant p3, QVariant p4, QVariant p5, QVariant p6, QVariant p7, QVariant p8) const
+{
QByteArray sig;
int numParams;
- foreach(QxtRPCPeerPrivate::MethodID i, attachedSlots.value(fn)) {
+ if(!attachedSlots.value(fn).count()) qDebug() << "no attached slot for signal" << fn;// qDebug() << attachedSlots;
+ foreach(QxtRPCPeerPrivate::MethodID i, attachedSlots.value(fn))
+ {
sig = i.first->metaObject()->method(i.second).signature();
sig = sig.left(sig.indexOf('('));
- numParams = i.first->metaObject()->method(i.second).parameterTypes().count();
- QMetaObject::invokeMethod(i.first, sig, QXT_ARG(0), QXT_ARG(1), QXT_ARG(2), QXT_ARG(3), QXT_ARG(4), QXT_ARG(5), QXT_ARG(6), QXT_ARG(7), QXT_ARG(8));
+ numParams = i.first->metaObject()->method(i.second).parameterTypes().count(); //qDebug() << "calling" << fn << p0 << p1 << p2;
+ bool res = QMetaObject::invokeMethod(i.first, sig, QXT_ARG(0), QXT_ARG(1), QXT_ARG(2), QXT_ARG(3), QXT_ARG(4), QXT_ARG(5), QXT_ARG(6), QXT_ARG(7), QXT_ARG(8));
+ if(!res) qDebug() << "rpccall failed" << fn << sig << p0 << p1 << p2;
}
}
-void QxtRPCPeerPrivate::receiveClientSignal(quint64 id, QString fn, QVariant p0, QVariant p1, QVariant p2, QVariant p3, QVariant p4, QVariant p5, QVariant p6, QVariant p7) const {
+
+void QxtRPCPeerPrivate::receiveClientSignal(quint64 id, QString fn, QVariant p0, QVariant p1, QVariant p2, QVariant p3, QVariant p4, QVariant p5, QVariant p6, QVariant p7) const
+{
QByteArray sig;
int numParams;
- foreach(QxtRPCPeerPrivate::MethodID i, attachedSlots.value(fn)) {
+ foreach(QxtRPCPeerPrivate::MethodID i, attachedSlots.value(fn))
+ {
sig = i.first->metaObject()->method(i.second).signature();
sig = sig.left(sig.indexOf('('));
numParams = i.first->metaObject()->method(i.second).parameterTypes().count();
QMetaObject::invokeMethod(i.first, sig, Q_ARG(quint64, id), QXT_ARG(0), QXT_ARG(1), QXT_ARG(2), QXT_ARG(3), QXT_ARG(4), QXT_ARG(5), QXT_ARG(6), QXT_ARG(7));
}
}
+
+
#undef QXT_ARG
-void QxtRPCPeer::newConnection() {
- QTcpSocket* next = qxt_d().m_server->nextPendingConnection();
- if(qxt_d().m_rpctype == QxtRPCPeer::Peer) {
- if(qxt_d().m_peer->isOpen ()) {
+void QxtRPCPeerPrivate::incomingConnection ( int socketDescriptor )
+{
+ QTcpSocket* next = qxt_p().incomingConnection(socketDescriptor);
+ if (m_rpctype == QxtRPCPeer::Peer)
+ {
+ if (m_peer->isOpen ())
+ {
qWarning() << "QxtRPCPeer: Rejected connection from " << next->peerAddress().toString() << "; another peer is connected";
next->disconnectFromHost();
next->deleteLater();
- } else {
- qxt_d().m_peer->deleteLater();
- qxt_d().m_peer = next;
- QObject::connect(qxt_d().m_peer, SIGNAL(connected()), this, SIGNAL(peerConnected()));
- QObject::connect(qxt_d().m_peer, SIGNAL(disconnected()), this, SIGNAL(peerDisconnected()));
- QObject::connect(qxt_d().m_peer, SIGNAL(disconnected()), this, SLOT(disconnectSender()));
- QObject::connect(qxt_d().m_peer, SIGNAL(readyRead()), this, SLOT(dataAvailable()));
- QObject::connect(qxt_d().m_peer, SIGNAL(error(QAbstractSocket::SocketError)), this, SIGNAL(peerError(QAbstractSocket::SocketError)));
- emit peerConnected();
}
- } else {
+ else
+ {
+ m_peer->deleteLater();
+ m_peer = next;
+ QObject::connect(m_peer, SIGNAL(connected()), &qxt_p(), SIGNAL(peerConnected()));
+ QObject::connect(m_peer, SIGNAL(disconnected()), &qxt_p(), SIGNAL(peerDisconnected()));
+ QObject::connect(m_peer, SIGNAL(disconnected()), &qxt_p(), SLOT(disconnectSender()));
+ QObject::connect(m_peer, SIGNAL(readyRead()), &qxt_p(), SLOT(dataAvailable()));
+ QObject::connect(m_peer, SIGNAL(error(QAbstractSocket::SocketError)), &qxt_p(), SIGNAL(peerError(QAbstractSocket::SocketError)));
+ emit qxt_p().peerConnected();
+ }
+ }
+ else
+ {
QxtRPCConnection* conn = new QxtRPCConnection;
conn->socket = next;
- qxt_d().m_clients[next] = conn;
- QObject::connect(next, SIGNAL(disconnected()), this, SLOT(disconnectSender()));
- QObject::connect(next, SIGNAL(readyRead()), this, SLOT(dataAvailable()));
- QObject::connect(next, SIGNAL(error(QAbstractSocket::SocketError)), this, SIGNAL(peerError(QAbstractSocket::SocketError)));
- emit clientConnected((quint64)(next));
+ m_clients[next] = conn;
+ QObject::connect(next, SIGNAL(disconnected()), &qxt_p(), SLOT(disconnectSender()));
+ QObject::connect(next, SIGNAL(readyRead()), &qxt_p(), SLOT(dataAvailable()));
+ QObject::connect(next, SIGNAL(error(QAbstractSocket::SocketError)), &qxt_p(), SIGNAL(peerError(QAbstractSocket::SocketError)));
+ emit qxt_p().clientConnected((quint64)(next));
}
}
-void QxtRPCPeer::dataAvailable() {
- if(qxt_d().m_rpctype!=QxtRPCPeer::Server && qxt_d().m_peer==sender()) {
+
+void QxtRPCPeer::dataAvailable()
+{
+ if (qxt_d().m_rpctype!=QxtRPCPeer::Server && qxt_d().m_peer==sender())
+ {
qxt_d().m_buffer.append(qxt_d().m_peer->readAll());
qxt_d().processInput(qxt_d().m_peer, qxt_d().m_buffer);
return;
- } else {
+ }
+ else
+ {
QxtRPCConnection* conn = qxt_d().m_clients.value(sender());
- if(!conn) {
+ if (!conn)
+ {
qWarning() << "QxtRPCPeer: Unrecognized client object connected to dataAvailable";
return;
}
qWarning() << "QxtRPCPeer: Unrecognized peer object connected to dataAvailable";
}
-void QxtRPCPeer::disconnectSender() {
+
+void QxtRPCPeer::disconnectSender()
+{
QxtRPCConnection* conn = qxt_d().m_clients.value(sender());
- if(!conn) {
- if(qxt_d().m_peer!= qobject_cast<QTcpSocket*>(sender())) {
+ if (!conn)
+ {
+ if (qxt_d().m_peer!= qobject_cast<QAbstractSocket*>(sender())) // SPUT: why not QTcpSocket*?
+ {
qWarning() << "QxtRPCPeer: Unrecognized object connected to disconnectSender";
return;
}
qxt_d().m_clients.remove(sender());
}
-void QxtRPCPeerPrivate::processInput(QIODevice* socket, QByteArray& buffer) {
- while(qxt_p().canDeserialize(buffer)) {
+
+void QxtRPCPeerPrivate::processInput(QIODevice* socket, QByteArray& buffer)
+{
+ while (qxt_p().canDeserialize(buffer))
+ {
QPair<QString, QList<QVariant> > sig = qxt_p().deserialize(buffer);
- if(sig.first.isEmpty()) {
- if(sig.second.count()) {
+ if (sig.first.isEmpty())
+ {
+ if (sig.second.count())
+ {
qWarning() << "QxtRPCPeer: Invalid data received; disconnecting";
- if(socket == m_peer)
+ if (socket == m_peer)
qxt_p().disconnectPeer();
else
qxt_p().disconnectPeer((quint64)(socket));
}
continue;
}
- while(sig.second.count() < 9) sig.second << QVariant();
- if(socket == m_peer) {
+ while (sig.second.count() < 9) sig.second << QVariant();
+ if (socket == m_peer)
+ {
receivePeerSignal(sig.first, sig.second[0], sig.second[1], sig.second[2], sig.second[3], sig.second[4], sig.second[5], sig.second[6], sig.second[7], sig.second[8]);
- } else {
+ }
+ else
+ {
receiveClientSignal((quint64)(socket), sig.first, sig.second[0], sig.second[1], sig.second[2], sig.second[3], sig.second[4], sig.second[5], sig.second[6], sig.second[7]);
}
}
}
-QList<quint64> QxtRPCPeer::clients() const {
+
+QList<quint64> QxtRPCPeer::clients() const
+{
QList<quint64> rv;
QList<QObject*> cs = qxt_d().m_clients.keys();
foreach(QObject* id, cs) rv << (const quint64)(id);
return rv;
}
-QxtIntrospector::QxtIntrospector(QxtRPCPeer* parent, QObject* source, const char* signal): QObject(parent) {
+
+QxtIntrospector::QxtIntrospector(QxtRPCPeer* parent, QObject* source, const char* signal): QObject(parent)
+{
peer = parent;
QByteArray sig_ba = QMetaObject::normalizedSignature(QByteArray(signal).mid(1));
- ///FIXME: use normalizedsignature
const char * sig=sig_ba.constData();
int idx = source->metaObject()->indexOfSignal(sig);
- if(idx<0)
- qWarning("no such signal: %s",sig_ba.constData());
+ if (idx<0)
+ qWarning("no such signal: %s",sig_ba.constData());
- // Our "method" will have the first ID not used by the superclass.
+// Our "method" will have the first ID not used by the superclass.
QMetaObject::connect(source, idx, this, QObject::staticMetaObject.methodCount());
QObject::connect(source, SIGNAL(destroyed()), peer, SLOT(detachSender()));
QList<QByteArray> p = source->metaObject()->method(idx).parameterTypes();
int ct = p.count();
- for(int i=0; i<ct; i++) argTypes.append(QMetaType::type(p.value(i).constData()));
+ for (int i=0; i<ct; i++) argTypes.append(QMetaType::type(p.value(i).constData()));
}
-int QxtIntrospector::qt_metacall(QMetaObject::Call _c, int _id, void **_a) {
+
+int QxtIntrospector::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
+{
_id = QObject::qt_metacall(_c, _id, _a);
if (_id < 0)
return _id;
- if (_c == QMetaObject::InvokeMetaMethod) {
- if(_id==0) {
+ if (_c == QMetaObject::InvokeMetaMethod)
+ {
+ if (_id==0)
+ {
QVariant v[9];
int n = argTypes.size();
- for(int i=0; i<n; i++) v[i] = QVariant(argTypes[i], _a[i+1]);
+ for (int i=0; i<n; i++) v[i] = QVariant(argTypes[i], _a[i+1]);
peer->call(rpcFunction.toUtf8().constData(), v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8]);
}
_id -= 1;
return _id;
}
-QPair<QString, QList<QVariant> > QxtRPCPeer::deserialize(QByteArray& data) {
+
+QPair<QString, QList<QVariant> > QxtRPCPeer::deserialize(QByteArray& data)
+{
QByteArray cmd;
int pos = data.indexOf('\n');
cmd = data.left(pos-1);
data = data.mid(pos+1);
- if(cmd.length()==0) return qMakePair(QString(), QList<QVariant>());
+ if (cmd.length()==0) return qMakePair(QString(), QList<QVariant>());
cmd.replace(QByteArray("\\n"), QByteArray("\n"));
cmd.replace(QByteArray("\\\\"), QByteArray("\\"));
QDataStream str(cmd);
QVariant t;
str >> signal >> argCount;
- if(str.status() == QDataStream::ReadCorruptData) {
+ if (str.status() == QDataStream::ReadCorruptData)
+ {
v << QVariant();
return qMakePair(QString(), v);
}
- for(int i=0; i<argCount; i++) {
+ for (int i=0; i<argCount; i++)
+ {
str >> t;
v << t;
}
return qMakePair(signal, v);
}
-bool QxtRPCPeer::canDeserialize(const QByteArray& buffer) const {
- if (buffer.indexOf('\n') == -1)
- {
- return false;
- }
+
+bool QxtRPCPeer::canDeserialize(const QByteArray& buffer) const
+{
+ if (buffer.indexOf('\n') == -1)
+ {
+ return false;
+ }
return true;
-
+
+}
+
+
+
+
+QIODevice * QxtRPCPeer::socket()
+{
+ if (qxt_d().m_rpctype == Server)return 0;
+ return qxt_d().m_peer;
+}
+
+
+
+
+QTcpSocket * QxtRPCPeer::incomingConnection ( int socketDescriptor )
+{
+ QTcpSocket * t = new QTcpSocket;
+ t->setSocketDescriptor (socketDescriptor);
+ return t;
}
+
+
+
+
+const QTcpSocket * QxtRPCPeer::clientSocket(quint64 id) const
+ {
+ if (qxt_d().m_rpctype != Server)
+ return 0;
+
+ return qxt_d().m_clients[(QTcpSocket*)(id)]->socket;
+ }
+QList<quint64> QxtRPCPeer::clients()
+ {
+ QList<quint64> list;
+ foreach(QObject * o,qxt_d().m_clients.keys ())
+ {
+ list.append((quint64)o);
+ }
+ return list;
+ }
+
+
+
/****************************************************************************
-**
-** Copyright (C) Qxt Foundation. Some rights reserved.
-**
-** This file is part of the QxtNetwork module of the Qt eXTension library
-**
-** This library is free software; you can redistribute it and/or modify it
-** under the terms of th Common Public License, version 1.0, as published by
-** IBM.
-**
-** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY
-** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
-** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR
-** FITNESS FOR A PARTICULAR PURPOSE.
-**
-** You should have received a copy of the CPL along with this file.
-** See the LICENSE file and the cpl1.0.txt file included with the source
-** distribution for more information. If you did not receive a copy of the
-** license, contact the Qxt Foundation.
-**
-** <http://libqxt.sourceforge.net> <foundation@libqxt.org>
-**
-*****************************************************************************
-**
-** This file has been modified from its original state to suit the needs of
-** Quassel IRC. We have virtualized some methods.
-**
-*****************************************************************************/
+ **
+ ** Copyright (C) Qxt Foundation. Some rights reserved.
+ **
+ ** This file is part of the QxtNetwork module of the Qt eXTension library
+ **
+ ** This library is free software; you can redistribute it and/or modify it
+ ** under the terms of th Common Public License, version 1.0, as published by
+ ** IBM.
+ **
+ ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY
+ ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
+ ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR
+ ** FITNESS FOR A PARTICULAR PURPOSE.
+ **
+ ** You should have received a copy of the CPL along with this file.
+ ** See the LICENSE file and the cpl1.0.txt file included with the source
+ ** distribution for more information. If you did not receive a copy of the
+ ** license, contact the Qxt Foundation.
+ **
+ ** <http://libqxt.sourceforge.net> <foundation@libqxt.org>
+ **
+ ****************************************************************************/
#ifndef QXTRPCPEER
#define QXTRPCPEER
#include <QHostAddress>
#include <qxtpimpl.h>
#include <qxtglobal.h>
-
+class QTcpSocket;
class QxtRPCPeerPrivate;
/*!
* \class QxtRPCPeer QxtRPCPeer
*
* QxtRPCPeer is a tool that encapsulates Qt signals and transmits them over a network connection.
* The signal is subsequently re-emitted on the receiving end of the connection.
- *
+ *
* QxtRPCPeer can operate in peer-to-peer mode (that is, one-to-one) or client-server (that is, one-to-many) mode.
* In peer or server mode, QxtRPCPeer can listen for and accept incoming connections. In peer or client mode,
* QxtRPCPeer can connect to a listening peer or server.
- *
+ *
* All data types used in attached signals and slots must be declared and registered with QMetaType using
* Q_DECLARE_METATYPE and qRegisterMetaType, and they must have stream operators registered with qRegisterMetaTypeStreamOperators.
*
* The limits on the number of parameters passed to call() and related functions are a restriction of Qt,
* which limits parameters on a signal or slot to 10.
- */
-class QXT_NETWORK_EXPORT QxtRPCPeer : public QObject {
-Q_OBJECT
+ */
+class QXT_NETWORK_EXPORT QxtRPCPeer : public QObject
+{
+ Q_OBJECT
public:
/*!
* This enum is used with the \a setRPCType() to describe the role played in a connection. It is also returned by \a rpcType().
*/
- enum RPCTypes {
- Server, /**< Listen for clients and accept multiple connections. */
- Client, /**< Connect to a server. */
- Peer /**< Listen for a connection or connect to a peer. */
+ enum RPCTypes
+ {
+ Server, /**< Listen for clients and accept multiple connections. */
+ Client, /**< Connect to a server. */
+ Peer /**< Listen for a connection or connect to a peer. */
};
/*!
- * Creates a QxtRPCPeer object with the given parent. Unless changed later, this object will use Peer mode and QTcpSocket for its I/O device.
- */
+ * Creates a QxtRPCPeer object with the given parent. Unless changed later, this object will use Peer mode and QTcpSocket for its I/O device.
+ */
QxtRPCPeer(QObject* parent = 0);
/*!
- * Creates a QxtRPCPeer object with the given parent and type. Unless changed later, this object will use QTcpSocket for its I/O device.
- */
+ * Creates a QxtRPCPeer object with the given parent and type. Unless changed later, this object will use QTcpSocket for its I/O device.
+ */
QxtRPCPeer(RPCTypes type, QObject* parent = 0);
/*!
- * Creates a QxtRPCPeer object with the given parent and type and connects it to the specified I/O device.
- *
- * Note that the I/O device must already be opened for reading and writing. This constructor cannot be used for Server mode.
- */
+ * Creates a QxtRPCPeer object with the given parent and type and connects it to the specified I/O device.
+ *
+ * Note that the I/O device must already be opened for reading and writing. This constructor cannot be used for Server mode.
+ */
QxtRPCPeer(QIODevice* device, RPCTypes type = QxtRPCPeer::Peer, QObject* parent = 0);
/*!
- * Sets the RPC type.
+ * Sets the RPC type.
*
* Attempting to change the RPC type while listening or connected will be ignored with a warning.
*/
void connect(QHostAddress addr, int port = 80);
/*!
- * Listens on the specified interface on the specified port for connections.
+ * Listens on the specified interface on the specified port for connections.
*
* Attempting to listen while in Client mode or while connected in Peer mode will be ignored with a warning. In Peer mode, only one connection
* can be active at a time. Additional incoming connections while connected to a peer will be dropped. When a peer connects, the \a peerConnected()
* Stops listening for connections. Any connections still open will remain connected.
*/
void stopListening();
-
+
/*!
* Returns a list of client IDs for all connected clients.
*/
QList<quint64> clients() const;
/*!
- * Attaches the given signal.
+ * Attaches the given signal.
*
* When the attached signal is emitted, it will be transmitted to all connected servers, clients, or peers.
* If an optional rpcFunction is provided, it will be used in place of the name of the transmitted signal.
bool attachSignal(QObject* sender, const char* signal, const QByteArray& rpcFunction = QByteArray());
/*!
- * Attaches the given slot.
+ * Attaches the given slot.
*
- * When a signal with the name given by rpcFunction is received from the network, the attached slot is executed.
- * Use the SLOT() macro to specify the slot, just as you would for QObject::connect().
+ * When a signal with the name given by rpcFunction is received from the network, the attached slot is executed.
+ * Use the SLOT() macro to specify the slot, just as you would for QObject::connect().
*
* Like QObject::connect(), attachSignal returns false if the connection cannot be established.
*
*/
void detachObject(QObject* obj);
+
+ /*!
+ * Returns the current used iodevice (might be asocket or a custom iodevie) in client and peer mode.
+ * returns 0 for server mode
+ */
+ QIODevice * socket();
+
public slots:
/*!
- * Sends the signal fn with the given parameter list to the server or peer.
+ * Sends the signal fn with the given parameter list to the server or peer.
*
- * This function accepts up to 9 QVariant parameters.
+ * This function accepts up to 9 QVariant parameters.
*
* The receiver is not obligated to act upon the signal. If no server or peer is connected, the call is ignored.
* In particular, this function does nothing in Server mode.
* is ignored with a warning.
*/
void callClientList(QList<quint64> ids, QString fn, QVariant p1 = QVariant(), QVariant p2 = QVariant(), QVariant p3 = QVariant(), QVariant p4 = QVariant(),
- QVariant p5 = QVariant(), QVariant p6 = QVariant(), QVariant p7 = QVariant(), QVariant p8 = QVariant());
+ QVariant p5 = QVariant(), QVariant p6 = QVariant(), QVariant p7 = QVariant(), QVariant p8 = QVariant());
/*!
* Sends the signal fn with the given parameter list to the specified client.
*
- * This function accepts up to 8 QVariant parameters.
- *
+ * This function accepts up to 8 QVariant parameters.
+ *
* The receiver is not obligated to act upon the signal. If no client with the given ID is connected, the call will be ignored with a warning.
*/
void callClient(quint64 id, QString fn, QVariant p1 = QVariant(), QVariant p2 = QVariant(), QVariant p3 = QVariant(), QVariant p4 = QVariant(),
- QVariant p5 = QVariant(), QVariant p6 = QVariant(), QVariant p7 = QVariant(), QVariant p8 = QVariant());
+ QVariant p5 = QVariant(), QVariant p6 = QVariant(), QVariant p7 = QVariant(), QVariant p8 = QVariant());
/*!
* Sends the signal fn with the given parameter list to all connected clients except for the client specified.
* to all other connected clients.
*/
void callClientsExcept(quint64 id, QString fn, QVariant p1 = QVariant(), QVariant p2 = QVariant(), QVariant p3 = QVariant(), QVariant p4 = QVariant(),
- QVariant p5 = QVariant(), QVariant p6 = QVariant(), QVariant p7 = QVariant(), QVariant p8 = QVariant());
+ QVariant p5 = QVariant(), QVariant p6 = QVariant(), QVariant p7 = QVariant(), QVariant p8 = QVariant());
/*!
* Detaches all signals and slots for the object that emitted the signal connected to detachSender().
*/
void detachSender();
+ /*!
+ * gives Access to the socket of the client \n
+ * usefull to get information about the client, like adress, port, etc..\n
+ * returns 0 when not in server mode or if the client \p id does not exist.
+ */
+
+ const QTcpSocket * clientSocket(quint64 id) const;
+
+ /*!
+ * returns alist of all clients currently connected \n
+ * returns an empty List when not in server mode
+ */
+
+ QList<quint64> clients();
+
signals:
/*!
* This signal is emitted after a successful connection to or from a peer or server.
void peerConnected();
/*!
- * This signal is emitted after a successful connection from a client.
+ * This signal is emitted after a successful connection from a client.
*
* The given ID is used for disconnectPeer(), callClient(), and related functions.
*/
*/
virtual bool canDeserialize(const QByteArray& buffer) const;
-//protected:
-// void newConnection();
+
+
+ /*!
+ * is called in Server mode when a new connection is available. the default implementation returns a new QTCPSocket
+ * for the \p socketDescriptor
+ */
+ virtual QTcpSocket * incomingConnection ( int socketDescriptor );
+
private:
QXT_DECLARE_PRIVATE(QxtRPCPeer);
private slots:
- void newConnection();
void dataAvailable();
void disconnectSender();
};
}
void Core::destroy() {
+ //instanceptr->deleteLater();
delete instanceptr;
instanceptr = 0;
}
}
Core::~Core() {
- foreach(QTcpSocket *sock, validClients.keys()) {
- delete sock;
- }
+ //foreach(QTcpSocket *sock, validClients.keys()) {
+ // delete sock;
+ //}
qDeleteAll(sessions);
delete storage;
}
Q_ASSERT(!core->sessions.contains(uid));
CoreSession *sess = new CoreSession(uid, core->storage);
core->sessions[uid] = sess;
- connect(sess, SIGNAL(proxySignal(CoreSignal, QVariant, QVariant, QVariant)), core, SLOT(recvProxySignal(CoreSignal, QVariant, QVariant, QVariant)));
+ //connect(sess, SIGNAL(proxySignal(CoreSignal, QVariant, QVariant, QVariant)), core, SLOT(recvProxySignal(CoreSignal, QVariant, QVariant, QVariant)));
return sess;
}
Q_ASSERT(socket && blockSizes.contains(socket));
quint32 bsize = blockSizes.value(socket);
QVariant item;
- while(readDataFromDevice(socket, bsize, item)) {
+ if(readDataFromDevice(socket, bsize, item)) {
+ /* this is probably obsolete now */
if(validClients.contains(socket)) {
- QList<QVariant> sigdata = item.toList();
- sessions[validClients[socket]]->processSignal((ClientSignal)sigdata[0].toInt(), sigdata[1], sigdata[2], sigdata[3]);
+ Q_ASSERT(false);
+ //QList<QVariant> sigdata = item.toList();
+ //sessions[validClients[socket]]->processSignal((ClientSignal)sigdata[0].toInt(), sigdata[1], sigdata[2], sigdata[3]);
} else {
// we need to auth the client
try {
return;
}
}
- blockSizes[socket] = bsize = 0;
+ blockSizes[socket] = bsize = 0; // FIXME blockSizes aufräum0rn!
}
blockSizes[socket] = bsize;
}
}
void Core::processClientInit(QTcpSocket *socket, const QVariant &v) {
- VarMap msg = v.toMap();
+ QVariantMap msg = v.toMap();
if(msg["GuiProtocol"].toUInt() != GUI_PROTOCOL) {
//qWarning() << "Client version mismatch.";
throw Exception("GUI client version mismatch");
// Auth
UserId uid = storage->validateUser(msg["User"].toString(), msg["Password"].toString()); // throws exception if this failed
QVariant reply = initSession(uid);
- validClients[socket] = uid;
- QList<QVariant> sigdata;
- sigdata.append(CS_CORE_STATE); sigdata.append(reply); sigdata.append(QVariant()); sigdata.append(QVariant());
- writeDataToDevice(socket, QVariant(sigdata));
+ validClients[socket] = uid; // still needed? FIXME
+ //QList<QVariant> sigdata;
+ //sigdata.append(CS_CORE_STATE); sigdata.append(reply); sigdata.append(QVariant()); sigdata.append(QVariant());
+ disconnect(socket, 0, this, 0);
+ sessions[uid]->addClient(socket);
+ writeDataToDevice(socket, reply);
}
QVariant Core::initSession(UserId uid) {
sess = createSession(uid);
//validClients[socket] = uid;
}
- VarMap reply;
+ QVariantMap reply;
reply["SessionState"] = sess->sessionState();
return reply;
}
+/*
void Core::recvProxySignal(CoreSignal sig, QVariant arg1, QVariant arg2, QVariant arg3) {
CoreSession *sess = qobject_cast<CoreSession*>(sender());
Q_ASSERT(sess);
if(validClients[socket] == uid) writeDataToDevice(socket, QVariant(sigdata));
}
}
+*/
#include <QTcpServer>
#include <QTcpSocket>
-#include "coreproxy.h"
+#include "global.h"
class CoreSession;
class Storage;
static void disconnectLocalClient();
private slots:
- void recvProxySignal(CoreSignal, QVariant, QVariant, QVariant);
+ //void recvProxySignal(CoreSignal, QVariant, QVariant, QVariant);
bool startListening(uint port = DEFAULT_PORT);
void stopListening();
void incomingConnection();
inline void csSessionDataChanged(const QString &key, const QVariant &data) { send(CS_SESSION_DATA_CHANGED, key, data); }
inline void csServerConnected(QString net) { send(CS_SERVER_CONNECTED, net); }
inline void csServerDisconnected(QString net) { send(CS_SERVER_DISCONNECTED, net); }
- inline void csServerState(QString net, VarMap data) { send(CS_SERVER_STATE, net, data); }
+ inline void csServerState(QString net, QVariantMap data) { send(CS_SERVER_STATE, net, data); }
inline void csDisplayMsg(Message msg) { send(CS_DISPLAY_MSG, QVariant::fromValue(msg));}
inline void csDisplayStatusMsg(QString net, QString msg) { send(CS_DISPLAY_STATUS_MSG, net, msg); }
inline void csModeSet(QString net, QString target, QString mode) { send(CS_MODE_SET, net, target, mode); }
inline void csTopicSet(QString net, QString buf, QString topic) { send(CS_TOPIC_SET, net, buf, topic); }
- inline void csNickAdded(QString net, QString nick, VarMap props) { send(CS_NICK_ADDED, net, nick, props); }
+ inline void csNickAdded(QString net, QString nick, QVariantMap props) { send(CS_NICK_ADDED, net, nick, props); }
inline void csNickRemoved(QString net, QString nick) { send(CS_NICK_REMOVED, net, nick); }
inline void csNickRenamed(QString net, QString oldn, QString newn) { send(CS_NICK_RENAMED, net, oldn, newn); }
- inline void csNickUpdated(QString net, QString nick, VarMap props) { send(CS_NICK_UPDATED, net, nick, props); }
+ inline void csNickUpdated(QString net, QString nick, QVariantMap props) { send(CS_NICK_UPDATED, net, nick, props); }
inline void csOwnNickSet(QString net, QString nick) { send(CS_OWN_NICK_SET, net, nick); }
inline void csQueryRequested(QString net, QString nick) { send(CS_QUERY_REQUESTED, net, nick); }
inline void csBacklogData(BufferId id, QList<QVariant> msg, bool done) { send(CS_BACKLOG_DATA, QVariant::fromValue(id), msg, done); }
#include "coresession.h"
#include "server.h"
+#include "signalproxy.h"
#include "storage.h"
#include "util.h"
-CoreSession::CoreSession(UserId uid, Storage *_storage) : user(uid), storage(_storage) {
- coreProxy = new CoreProxy();
+CoreSession::CoreSession(UserId uid, Storage *_storage, QObject *parent) : QObject(parent), user(uid), storage(_storage) {
+ _signalProxy = new SignalProxy(SignalProxy::Server, 0, this);
QSettings s;
s.beginGroup(QString("SessionData/%1").arg(user));
}
mutex.unlock();
- connect(coreProxy, SIGNAL(send(CoreSignal, QVariant, QVariant, QVariant)), this, SIGNAL(proxySignal(CoreSignal, QVariant, QVariant, QVariant)));
- connect(coreProxy, SIGNAL(requestServerStates()), this, SIGNAL(serverStateRequested()));
- connect(coreProxy, SIGNAL(gsRequestConnect(QStringList)), this, SLOT(connectToIrc(QStringList)));
- connect(coreProxy, SIGNAL(gsUserInput(BufferId, QString)), this, SLOT(msgFromGui(BufferId, QString)));
- connect(coreProxy, SIGNAL(gsImportBacklog()), storage, SLOT(importOldBacklog()));
- connect(coreProxy, SIGNAL(gsRequestBacklog(BufferId, QVariant, QVariant)), this, SLOT(sendBacklog(BufferId, QVariant, QVariant)));
- connect(coreProxy, SIGNAL(gsRequestNetworkStates()), this, SLOT(sendServerStates()));
- connect(this, SIGNAL(displayMsg(Message)), coreProxy, SLOT(csDisplayMsg(Message)));
- connect(this, SIGNAL(displayStatusMsg(QString, QString)), coreProxy, SLOT(csDisplayStatusMsg(QString, QString)));
- connect(this, SIGNAL(backlogData(BufferId, QList<QVariant>, bool)), coreProxy, SLOT(csBacklogData(BufferId, QList<QVariant>, bool)));
- connect(this, SIGNAL(bufferIdUpdated(BufferId)), coreProxy, SLOT(csUpdateBufferId(BufferId)));
- connect(storage, SIGNAL(bufferIdUpdated(BufferId)), coreProxy, SLOT(csUpdateBufferId(BufferId)));
- connect(this, SIGNAL(sessionDataChanged(const QString &, const QVariant &)), coreProxy, SLOT(csSessionDataChanged(const QString &, const QVariant &)));
- connect(coreProxy, SIGNAL(gsSessionDataChanged(const QString &, const QVariant &)), this, SLOT(storeSessionData(const QString &, const QVariant &)));
+ //connect(coreProxy, SIGNAL(send(CoreSignal, QVariant, QVariant, QVariant)), this, SIGNAL(proxySignal(CoreSignal, QVariant, QVariant, QVariant)));
+ //connect(coreProxy, SIGNAL(requestServerStates()), this, SIGNAL(serverStateRequested()));
+ //connect(coreProxy, SIGNAL(gsRequestConnect(QStringList)), this, SLOT(connectToIrc(QStringList)));
+ //connect(coreProxy, SIGNAL(gsUserInput(BufferId, QString)), this, SLOT(msgFromGui(BufferId, QString)));
+ //connect(coreProxy, SIGNAL(gsImportBacklog()), storage, SLOT(importOldBacklog()));
+ //connect(coreProxy, SIGNAL(gsRequestBacklog(BufferId, QVariant, QVariant)), this, SLOT(sendBacklog(BufferId, QVariant, QVariant)));
+ //connect(coreProxy, SIGNAL(gsRequestNetworkStates()), this, SLOT(sendServerStates()));
+ //connect(this, SIGNAL(displayMsg(Message)), coreProxy, SLOT(csDisplayMsg(Message)));
+ //connect(this, SIGNAL(displayStatusMsg(QString, QString)), coreProxy, SLOT(csDisplayStatusMsg(QString, QString)));
+ //connect(this, SIGNAL(backlogData(BufferId, QList<QVariant>, bool)), coreProxy, SLOT(csBacklogData(BufferId, QList<QVariant>, bool)));
+ //connect(this, SIGNAL(bufferIdUpdated(BufferId)), coreProxy, SLOT(csUpdateBufferId(BufferId)));
+ //connect(storage, SIGNAL(bufferIdUpdated(BufferId)), coreProxy, SLOT(csUpdateBufferId(BufferId)));
+ //connect(this, SIGNAL(sessionDataChanged(const QString &, const QVariant &)), coreProxy, SLOT(csSessionDataChanged(const QString &, const QVariant &)));
+ //connect(coreProxy, SIGNAL(gsSessionDataChanged(const QString &, const QVariant &)), this, SLOT(storeSessionData(const QString &, const QVariant &)));
+
+ SignalProxy *p = signalProxy();
+
+ p->attachSlot(SIGNAL(requestNetworkStates()), this, SIGNAL(serverStateRequested()));
+ p->attachSlot(SIGNAL(requestConnect(QString)), this, SLOT(connectToNetwork(QString)));
+ p->attachSlot(SIGNAL(sendInput(BufferId, QString)), this, SLOT(msgFromGui(BufferId, 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->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(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?
QStringList list;
- VarMap networks = retrieveSessionData("Networks").toMap();
+ QVariantMap networks = retrieveSessionData("Networks").toMap();
foreach(QString net, networks.keys()) {
if(networks[net].toMap()["AutoConnect"].toBool()) {
list << net;
return user;
}
+/*
void CoreSession::processSignal(ClientSignal sig, QVariant arg1, QVariant arg2, QVariant arg3) {
coreProxy->recv(sig, arg1, arg2, arg3);
}
+*/
void CoreSession::storeSessionData(const QString &key, const QVariant &data) {
QSettings s;
return data;
}
-void CoreSession::connectToIrc(QStringList networks) {
+void CoreSession::connectToNetwork(QString network) {
+ QStringList networks; networks << network; // FIXME obsolete crap
foreach(QString net, networks) {
if(servers.contains(net)) {
connect(server, SIGNAL(connected(QString)), this, SLOT(serverConnected(QString)));
connect(server, SIGNAL(disconnected(QString)), this, SLOT(serverDisconnected(QString)));
- connect(server, SIGNAL(serverState(QString, VarMap)), coreProxy, SLOT(csServerState(QString, VarMap)));
- //connect(server, SIGNAL(displayMsg(Message)), this, SLOT(recvMessageFromServer(Message)));
+ //connect(server, SIGNAL(serverState(QString, QVariantMap)), coreProxy, SLOT(csServerState(QString, QVariantMap)));
+ ////connect(server, SIGNAL(displayMsg(Message)), this, SLOT(recvMessageFromServer(Message)));
connect(server, SIGNAL(displayMsg(Message::Type, QString, QString, QString, quint8)), this, SLOT(recvMessageFromServer(Message::Type, QString, QString, QString, quint8)));
connect(server, SIGNAL(displayStatusMsg(QString)), this, SLOT(recvStatusMsgFromServer(QString)));
- connect(server, SIGNAL(modeSet(QString, QString, QString)), coreProxy, SLOT(csModeSet(QString, QString, QString)));
- connect(server, SIGNAL(topicSet(QString, QString, QString)), coreProxy, SLOT(csTopicSet(QString, QString, QString)));
- connect(server, SIGNAL(nickAdded(QString, QString, VarMap)), coreProxy, SLOT(csNickAdded(QString, QString, VarMap)));
- connect(server, SIGNAL(nickRenamed(QString, QString, QString)), coreProxy, SLOT(csNickRenamed(QString, QString, QString)));
- connect(server, SIGNAL(nickRemoved(QString, QString)), coreProxy, SLOT(csNickRemoved(QString, QString)));
- connect(server, SIGNAL(nickUpdated(QString, QString, VarMap)), coreProxy, SLOT(csNickUpdated(QString, QString, VarMap)));
- connect(server, SIGNAL(ownNickSet(QString, QString)), coreProxy, SLOT(csOwnNickSet(QString, QString)));
- connect(server, SIGNAL(queryRequested(QString, QString)), coreProxy, SLOT(csQueryRequested(QString, QString)));
+ //connect(server, SIGNAL(modeSet(QString, QString, QString)), coreProxy, SLOT(csModeSet(QString, QString, QString)));
+ //connect(server, SIGNAL(topicSet(QString, QString, QString)), coreProxy, SLOT(csTopicSet(QString, QString, QString)));
+ //connect(server, SIGNAL(nickAdded(QString, QString, QVariantMap)), coreProxy, SLOT(csNickAdded(QString, QString, QVariantMap)));
+ //connect(server, SIGNAL(nickRenamed(QString, QString, QString)), coreProxy, SLOT(csNickRenamed(QString, QString, QString)));
+ //connect(server, SIGNAL(nickRemoved(QString, QString)), coreProxy, SLOT(csNickRemoved(QString, QString)));
+ //connect(server, SIGNAL(nickUpdated(QString, QString, QVariantMap)), coreProxy, SLOT(csNickUpdated(QString, QString, QVariantMap)));
+ //connect(server, SIGNAL(ownNickSet(QString, QString)), coreProxy, SLOT(csOwnNickSet(QString, QString)));
+ //connect(server, SIGNAL(queryRequested(QString, QString)), coreProxy, SLOT(csQueryRequested(QString, QString)));
+ //// TODO add error handling
+ //connect(server, SIGNAL(connected(QString)), coreProxy, SLOT(csServerConnected(QString)));
+ //connect(server, SIGNAL(disconnected(QString)), coreProxy, SLOT(csServerDisconnected(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
- connect(server, SIGNAL(connected(QString)), coreProxy, SLOT(csServerConnected(QString)));
- connect(server, SIGNAL(disconnected(QString)), coreProxy, SLOT(csServerDisconnected(QString)));
+ p->attachSignal(server, SIGNAL(connected(QString)), SIGNAL(networkConnected(QString)));
+ p->attachSignal(server, SIGNAL(disconnected(QString)), SIGNAL(networkDisconnected(QString)));
server->start();
servers[net] = server;
}
}
+void CoreSession::addClient(QIODevice *device) {
+ signalProxy()->addPeer(device);
+}
+
+SignalProxy *CoreSession::signalProxy() const {
+ return _signalProxy;
+}
+
void CoreSession::serverConnected(QString net) {
storage->getBufferId(userId(), net); // create status buffer
}
void CoreSession::serverDisconnected(QString net) {
delete servers[net];
servers.remove(net);
- coreProxy->csServerDisconnected(net);
+ //coreProxy->csServerDisconnected(net);
+ signalProxy()->sendSignal(SIGNAL(networkDisconnected(QString)), net); // FIXME does this work?
}
void CoreSession::msgFromGui(BufferId bufid, QString msg) {
QVariant CoreSession::sessionState() {
- VarMap v;
+ QVariantMap v;
QList<QVariant> bufs;
foreach(BufferId id, storage->requestBuffers(user)) { bufs.append(QVariant::fromValue(id)); }
v["Buffers"] = bufs;
#include <QString>
#include <QVariant>
-#include "coreproxy.h"
+//#include "coreproxy.h"
+#include "message.h"
class Server;
+class SignalProxy;
class Storage;
class CoreSession : public QObject {
Q_OBJECT
public:
- CoreSession(UserId, Storage *);
+ CoreSession(UserId, Storage *, QObject *parent = 0);
~CoreSession();
QList<BufferId> buffers() const;
//! 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());
- CoreProxy *proxy();
+ //CoreProxy *proxy();
+ SignalProxy *signalProxy() const;
public slots:
- void connectToIrc(QStringList);
- void processSignal(ClientSignal, QVariant, QVariant, QVariant);
+ void connectToNetwork(QString);
+ //void processSignal(ClientSignal, QVariant, QVariant, QVariant);
void sendBacklog(BufferId, QVariant, QVariant);
void msgFromGui(BufferId, QString message);
void sendServerStates();
signals:
- void proxySignal(CoreSignal, QVariant arg1 = QVariant(), QVariant arg2 = QVariant(), QVariant arg3 = QVariant());
+ //void proxySignal(CoreSignal, QVariant arg1 = QVariant(), QVariant arg2 = QVariant(), QVariant arg3 = QVariant());
void msgFromGui(QString net, QString buf, QString message);
void displayMsg(Message message);
void disconnectFromIrc(QString net);
void serverStateRequested();
- void backlogData(BufferId, QList<QVariant>, bool done);
+ void backlogData(BufferId, QVariantList, bool done);
void bufferIdUpdated(BufferId);
void sessionDataChanged(const QString &key);
private:
UserId user;
- CoreProxy *coreProxy;
+ //CoreProxy *coreProxy;
+ SignalProxy *_signalProxy;
Storage *storage;
QHash<QString, Server *> servers;
- VarMap sessionData;
+ QVariantMap sessionData;
QMutex mutex;
};
}
void Server::sendState() {
- VarMap s;
- VarMap n, t;
+ 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;
QString host = hostFromMask(mask);
QString nick = nickFromMask(mask);
if(nicks.contains(nick) && !user.isEmpty() && !host.isEmpty()) {
- VarMap n = nicks[nick];
+ 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());
topics[params[0]] = "";
emit topicSet(network, params[0], "");
} //else {
- VarMap n;
+ QVariantMap n;
if(nicks.contains(nick)) {
n = nicks[nick];
- VarMap chans = n["Channels"].toMap();
+ QVariantMap chans = n["Channels"].toMap();
// Q_ASSERT(!chans.keys().contains(params[0])); TODO uncomment
- chans[params[0]] = VarMap();
+ chans[params[0]] = QVariantMap();
n["Channels"] = chans;
- nicks[nick] = n;
+ nicks[nick] = n; qDebug() << network << nick << n;
emit nickUpdated(network, nick, n);
} else {
- VarMap chans;
- chans[params[0]] = VarMap();
+ QVariantMap chans;
+ chans[params[0]] = QVariantMap();
n["Channels"] = chans;
n["User"] = userFromMask(prefix);
n["Host"] = hostFromMask(prefix);
QString kicker = updateNickFromMask(prefix);
QString nick = params[1];
Q_ASSERT(nicks.contains(nick));
- VarMap n = nicks[nick];
- VarMap chans = n["Channels"].toMap();
+ QVariantMap n = nicks[nick];
+ QVariantMap chans = n["Channels"].toMap();
Q_ASSERT(chans.contains(params[0]));
chans.remove(params[0]);
QString msg = nick;
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
- VarMap n = nicks[nick]; VarMap clist = n["Channels"].toMap(); VarMap chan = clist[params[0]].toMap();
+ 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 displayMsg(Message::Mode, params[0], params.join(" "), prefix);
} else {
//Q_ASSERT(nicks.contains(params[0]));
- //VarMap n = nicks[params[0]].toMap();
+ //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];
- VarMap v = nicks.take(oldnick);
+ QVariantMap v = nicks.take(oldnick);
nicks[newnick] = v;
- VarMap chans = v["Channels"].toMap();
+ 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); }
void Server::handleServerPart(QString prefix, QStringList params) {
QString nick = updateNickFromMask(prefix);
Q_ASSERT(nicks.contains(nick));
- VarMap n = nicks[nick];
- VarMap chans = n["Channels"].toMap();
+ QVariantMap n = nicks[nick];
+ QVariantMap chans = n["Channels"].toMap();
Q_ASSERT(chans.contains(params[0]));
chans.remove(params[0]);
QString msg;
void Server::handleServerQuit(QString prefix, QStringList params) {
QString nick = updateNickFromMask(prefix);
Q_ASSERT(nicks.contains(nick));
- VarMap chans = nicks[nick]["Channels"].toMap();
+ QVariantMap chans = nicks[nick]["Channels"].toMap();
QString msg;
if(params.count()) msg = params[0];
foreach(QString c, chans.keys()) {
// 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);
- VarMap n;
- n["Channels"] = VarMap();
+ QVariantMap n;
+ n["Channels"] = QVariantMap();
nicks[ownNick] = n;
emit ownNickSet(network, ownNick);
- emit nickAdded(network, ownNick, VarMap());
+ emit nickAdded(network, ownNick, QVariantMap());
emit displayMsg(Message::Server, "", params[0], prefix);
// send performlist
QStringList performList = networkSettings["Perform"].toString().split( "\n" );
serverSupports[key] = val;
// handle some special cases
if(key == "PREFIX") {
- VarMap foo; QString modes, prefixes;
+ 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;
if(prefixes[i] == nick[0]) { mode = serverSupports["PrefixModes"].toString()[i]; break; }
nick.remove(0,1);
}
- VarMap c; c["Mode"] = mode; c["Prefix"] = pfx;
+ QVariantMap c; c["Mode"] = mode; c["Prefix"] = pfx;
if(nicks.contains(nick)) {
- VarMap n = nicks[nick];
- VarMap chans = n["Channels"].toMap();
+ QVariantMap n = nicks[nick];
+ QVariantMap chans = n["Channels"].toMap();
chans[buf] = c;
n["Channels"] = chans;
nicks[nick] = n;
emit nickUpdated(network, nick, n);
} else {
- VarMap n; VarMap c; VarMap chans;
+ QVariantMap n; QVariantMap c; QVariantMap chans;
c["Mode"] = mode;
chans[buf] = c;
n["Channels"] = chans;
//void exitThread();
signals:
- void serverState(QString net, VarMap data);
+ void serverState(QString net, QVariantMap data);
void recvRawServerMsg(QString);
void displayStatusMsg(QString);
//void displayMsg(Message msg);
void connected(QString network);
void disconnected(QString network);
- void nickAdded(QString network, QString nick, VarMap props);
+ 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, VarMap props);
+ 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);
QString ownNick;
QString currentServer;
- VarMap networkSettings;
- VarMap identity;
- QHash<QString, VarMap> nicks; // stores all known nicks for the server
+ QVariantMap networkSettings;
+ QVariantMap identity;
+ QHash<QString, QVariantMap> nicks; // stores all known nicks for the server
QHash<QString, QString> topics; // stores topics for each buffer
- VarMap serverSupports; // stores results from RPL_ISUPPORT
+ QVariantMap serverSupports; // stores results from RPL_ISUPPORT
void handleServerMsg(QByteArray rawMsg);
void handleUserInput(QString buffer, QString usrMsg);
QString currentServer_;
QString ownNick_;
- //VarMap networkSettings;
- //VarMap identity;
+ //QVariantMap networkSettings;
+ //QVariantMap identity;
QHash<QString, IrcUser *> ircUsers_; // stores all known nicks for the server
QHash<QString, QString> topics_; // stores topics for each buffer
}
SqliteStorage::~SqliteStorage() {
+ //logDb.close();
delete logMessageQuery;
delete addSenderQuery;
delete getLastMessageIdQuery;
s->topic = buf->topic();
updateNickList(s, buf->nickList());
s->splitter->restoreState(s->splitterState);
- connect(buf, SIGNAL(nickListChanged(VarMap)), this, SLOT(updateNickList(VarMap)));
+ connect(buf, SIGNAL(nickListChanged(QVariantMap)), this, SLOT(updateNickList(QVariantMap)));
connect(s->nickTree, SIGNAL(itemExpanded(QTreeWidgetItem *)), this, SLOT(itemExpansionChanged(QTreeWidgetItem*)));
connect(s->nickTree, SIGNAL(itemCollapsed(QTreeWidgetItem *)), this, SLOT(itemExpansionChanged(QTreeWidgetItem*)));
} else {
}
-void BufferWidget::updateNickList(VarMap nicks) {
+void BufferWidget::updateNickList(QVariantMap nicks) {
Buffer *buf = qobject_cast<Buffer*>(sender());
Q_ASSERT(buf);
updateNickList(states[buf], nicks);
}
// TODO Use 005
-void BufferWidget::updateNickList(BufferState *state, VarMap nicks) {
+void BufferWidget::updateNickList(BufferState *state, QVariantMap nicks) {
emit nickListUpdated(nicks.keys());
QTreeWidget *tree = state->nickTree;
if(!tree) return;
void updateTitle();
//void displayMsg(Message);
- void updateNickList(BufferState *state, VarMap nicks);
- void updateNickList(VarMap nicks);
+ void updateNickList(BufferState *state, QVariantMap nicks);
+ void updateNickList(QVariantMap nicks);
void setOwnNick(QString ownNick);
void setTopic(QString topic);
void setActive(bool act = true);
#include <QtGui>
#include "coreconnectdlg.h"
-#include "clientproxy.h"
+//#include "clientproxy.h"
#include "global.h"
#include "client.h"
#include "clientsettings.h"
void CoreConnectDlg::accountChanged(const QString &text) {
AccountSettings s;
if(!curacc.isEmpty()) {
- VarMap oldAcc;
+ QVariantMap oldAcc;
oldAcc["User"] = ui.userEdit->text();
oldAcc["Host"] = ui.hostEdit->text();
oldAcc["Port"] = ui.port->value();
if(!text.isEmpty()) { // empty text: just save stuff
curacc = text;
s.setLastAccount(curacc);
- VarMap newAcc = s.value(curacc, "AccountData").toMap();
+ QVariantMap newAcc = s.value(curacc, "AccountData").toMap();
ui.userEdit->setText(newAcc["User"].toString());
ui.hostEdit->setText(newAcc["Host"].toString());
ui.port->setValue(newAcc["Port"].toInt());
QMessageBox::warning(this, tr("Account name already exists!"), tr("An account named '%1' already exists, and account names must be unique!").arg(accname));
return;
}
- VarMap defdata;
+ QVariantMap defdata;
ui.accountList->addItem(accname);
ui.accountList->setCurrentIndex(ui.accountList->findText(accname));
setAccountEditEnabled(true);
void CoreConnectDlg::doConnect() {
accountChanged(); // save current account info
- VarMap conninfo;
+ QVariantMap conninfo;
ui.stackedWidget->setCurrentIndex(1);
if(ui.internalCore->isChecked()) {
+ // FIXME
+ coreConnectionError(tr("Can't connect to internal core at the moment [serious breakage due to switch to dynamic signals]. Please check back later."));
+ return;
if(Global::runMode != Global::Monolithic) {
coreConnectionError(tr("Can't connect to internal core, since we are running as a standalone GUI!"));
return;
connect(ClientProxy::instance(), SIGNAL(recvPartialItem(quint32, quint32)), this, SLOT(updateProgressBar(quint32, quint32)));
connect(ClientProxy::instance(), SIGNAL(csCoreState(QVariant)), this, SLOT(recvCoreState(QVariant)));
ui.progressBar->show();
- VarMap initmsg;
+ QVariantMap initmsg;
initmsg["GUIProtocol"] = GUI_PROTOCOL;
// FIXME guiProxy->send(GS_CLIENT_INIT, QVariant(initmsg)); */
ui.connectionStatus->setText(tr("Connected to core."));
ui.stackedWidget->setCurrentIndex(0);
show(); // just in case we started hidden
QMessageBox::warning(this, tr("Connection Error"), tr("<b>Could not connect to Quassel Core!</b><br>\n") + err, QMessageBox::Retry);
- disconnect(ClientProxy::instance(), 0, this, 0);
+ //disconnect(ClientProxy::instance(), 0, this, 0); FIXME?
//ui.autoConnect->setChecked(false);
setStartState();
}
void cancelConnect();
void setStartState();
- VarMap accountData;
+ QVariantMap accountData;
QString curacc;
};
nameMapping[name] = name;
}
if(identities.size() == 0) {
- VarMap id = createDefaultIdentity();
+ QVariantMap id = createDefaultIdentity();
id["IdName"] = "Default";
identities["Default"] = id;
nameMapping["Default"] = "Default";
}
}
-VarMap IdentitiesDlg::createDefaultIdentity() {
- VarMap id;
+QVariantMap IdentitiesDlg::createDefaultIdentity() {
+ QVariantMap id;
id["RealName"] = "foo";
id["Ident"] = "";
id["NickList"] = QStringList();
}
void IdentitiesDlg::updateWidgets() {
- VarMap id = identities[getCurIdentity()].toMap();
+ QVariantMap id = identities[getCurIdentity()].toMap();
ui.realNameEdit->setText(id["RealName"].toString());
ui.identEdit->setText(id["Ident"].toString());
ui.nickList->clear();
}
void IdentitiesDlg::updateIdentity(QString idName) {
- VarMap id;
+ QVariantMap id;
id["RealName"] = ui.realNameEdit->text();
id["Ident"] = ui.identEdit->text();
QStringList nicks;
if(result.length() == 0) {
Client::storeSessionData("Identities", identities);
// We have to care about renamed identities and update the network list appropriately...
- VarMap networks = Client::retrieveSessionData("Networks").toMap();
+ QVariantMap networks = Client::retrieveSessionData("Networks").toMap();
foreach(QString netname, networks.keys()) {
- VarMap net = networks[netname].toMap();
+ QVariantMap net = networks[netname].toMap();
if(nameMapping.contains(net["Identity"].toString())) {
net["Identity"] = nameMapping[net["Identity"].toString()];
} else net["Identity"] = "Default";
QString reason;
foreach(QString name, identities.keys()) {
QString r;
- VarMap id = identities[name].toMap();
+ QVariantMap id = identities[name].toMap();
if(name == "Default") name = tr("Default Identity");
if(id["RealName"].toString().isEmpty()) {
r += tr(" You have not set a real name.");
/******************************************************************************/
-IdentitiesEditDlg::IdentitiesEditDlg(QWidget *parent, VarMap _identities, QMap<QString, QString> _mapping, VarMap templ, QString selected)
+IdentitiesEditDlg::IdentitiesEditDlg(QWidget *parent, QVariantMap _identities, QMap<QString, QString> _mapping, QVariantMap templ, QString selected)
: QDialog(parent) {
ui.setupUi(this);
identities = _identities;
void IdentitiesEditDlg::addIdentity() {
RenameIdentityDlg dlg(this, identities.keys());
if(dlg.exec() == QDialog::Accepted) {
- VarMap id = identTemplate;
+ QVariantMap id = identTemplate;
identities[dlg.getName()] = id;
Q_ASSERT(!mapping.contains(dlg.getName()));
mapping[dlg.getName()] = dlg.getName();
public:
IdentitiesDlg(QWidget *parent, QString selectedId = QString());
- VarMap getIdentities() { return identities; }
+ QVariantMap getIdentities() { return identities; }
QMap<QString, QString> getNameMapping() { return nameMapping; }
public slots:
private:
Ui::IdentitiesDlg ui;
- VarMap identities;
+ QVariantMap identities;
QMap<QString, QString> nameMapping;
QString lastIdentity;
QString checkValidity();
- VarMap createDefaultIdentity();
+ QVariantMap createDefaultIdentity();
QString getCurIdentity();
void updateWidgets();
void updateIdentity(QString);
Q_OBJECT
public:
- IdentitiesEditDlg(QWidget *parent, VarMap identities, QMap<QString, QString> mapping, VarMap templ, QString selected = QString());
+ IdentitiesEditDlg(QWidget *parent, QVariantMap identities, QMap<QString, QString> mapping, QVariantMap templ, QString selected = QString());
- VarMap getIdentities() { return identities; }
+ QVariantMap getIdentities() { return identities; }
QMap<QString, QString> getMapping() { return mapping; }
QString getSelectedIdentity() { return ui.identList->currentItem()->text(); }
private:
Ui::IdentitiesEditDlg ui;
- VarMap identities;
- VarMap identTemplate;
+ QVariantMap identities;
+ QVariantMap identTemplate;
QMap<QString, QString> mapping;
void sortList();
#include "bufferview.h"
#include "chatline.h"
#include "client.h"
-#include "clientproxy.h"
+//#include "clientproxy.h"
#include "coreconnectdlg.h"
#include "serverlist.h"
#include "settingsdlg.h"
//#include "settingspage.h"
+#include "signalproxy.h"
MainWin::MainWin(QtGui *_gui, QWidget *parent) : QMainWindow(parent), gui(_gui) {
ui.setupUi(this);
}
void MainWin::init() {
- connect(this, SIGNAL(requestBacklog(BufferId, QVariant, QVariant)), ClientProxy::instance(), SLOT(gsRequestBacklog(BufferId, QVariant, QVariant)));
+ //connect(this, SIGNAL(requestBacklog(BufferId, QVariant, QVariant)), ClientProxy::instance(), SLOT(gsRequestBacklog(BufferId, QVariant, QVariant)));
+ Client::signalProxy()->attachSignal(this, SIGNAL(requestBacklog(BufferId, QVariant, QVariant)));
ui.bufferWidget->init();
show();
- //VarMap connInfo;
+ //QVariantMap connInfo;
//connInfo["User"] = "Default";
//connInfo["Password"] = "password";
//connectToCore(connInfo);
connect(ui.actionAboutQt, SIGNAL(triggered()), QApplication::instance(), SLOT(aboutQt()));
// for debugging
connect(ui.actionImportBacklog, SIGNAL(triggered()), this, SLOT(importBacklog()));
- connect(this, SIGNAL(importOldBacklog()), ClientProxy::instance(), SLOT(gsImportBacklog()));
+ //connect(this, SIGNAL(importOldBacklog()), ClientProxy::instance(), SLOT(gsImportBacklog()));
+ Client::signalProxy()->attachSignal(this, SIGNAL(importOldBacklog()));
}
void MainWin::setupViews() {
void importBacklog();
signals:
- void connectToCore(const VarMap &connInfo);
+ void connectToCore(const QVariantMap &connInfo);
void disconnectFromCore();
void requestBacklog(BufferId, QVariant, QVariant);
void importOldBacklog();
QtGui::QtGui() : AbstractUi() {
mainWin = new MainWin(this);
- connect(mainWin, SIGNAL(connectToCore(const VarMap &)), this, SIGNAL(connectToCore(const VarMap &)));
+ connect(mainWin, SIGNAL(connectToCore(const QVariantMap &)), this, SIGNAL(connectToCore(const QVariantMap &)));
connect(mainWin, SIGNAL(disconnectFromCore()), this, SIGNAL(disconnectFromCore()));
}
#include "serverlist.h"
#include "identities.h"
#include "client.h"
-#include "clientproxy.h"
+//#include "clientproxy.h"
+#include "signalproxy.h"
/* NOTE: This dialog holds not only the server list, but also the identities.
* This makes perfect sense given the fact that connections are initiated from
settings.endGroup();
- connect(this, SIGNAL(requestConnect(QStringList)), ClientProxy::instance(), SLOT(gsRequestConnect(QStringList)));
+ //connect(this, SIGNAL(requestConnect(QStringList)), ClientProxy::instance(), SLOT(gsRequestConnect(QStringList)));
+ Client::signalProxy()->attachSignal(this, SIGNAL(requestConnect(QString)));
// Autoconnect
/* Should not be the client's task... :-P
QStringList list;
- VarMap networks = Client::retrieveSessionData("Networks").toMap();
+ QVariantMap networks = Client::retrieveSessionData("Networks").toMap();
foreach(QString net, networks.keys()) {
if(networks[net].toMap()["AutoConnect"].toBool()) {
list << net;
}
void ServerListDlg::updateNetworkTree() {
- VarMap networks = Client::retrieveSessionData("Networks").toMap();
+ QVariantMap networks = Client::retrieveSessionData("Networks").toMap();
//QStringList headers;
//headers << "Network" << "Autoconnect";
ui.networkTree->clear();
ui.networkTree->setHeaderLabel("Networks");
QHash<QString, QTreeWidgetItem *> groups;
foreach(QString net, networks.keys()) {
- VarMap s = networks[net].toMap();
+ QVariantMap s = networks[net].toMap();
QString gr = s["Group"].toString();
QTreeWidgetItem *item = 0;
if(gr.isEmpty()) {
}
void ServerListDlg::on_addButton_clicked() {
- NetworkEditDlg dlg(this, VarMap());
+ NetworkEditDlg dlg(this, QVariantMap());
if(dlg.exec() == QDialog::Accepted) {
- VarMap networks = Client::retrieveSessionData("Networks").toMap();
- VarMap net = dlg.getNetwork();
+ QVariantMap networks = Client::retrieveSessionData("Networks").toMap();
+ QVariantMap net = dlg.getNetwork();
networks[net["Name"].toString()] = net;
Client::storeSessionData("Networks", networks);
updateNetworkTree();
void ServerListDlg::on_editButton_clicked() {
QString curnet = ui.networkTree->currentItem()->text(0);
- VarMap networks = Client::retrieveSessionData("Networks").toMap();
+ QVariantMap networks = Client::retrieveSessionData("Networks").toMap();
NetworkEditDlg dlg(this, networks[curnet].toMap());
if(dlg.exec() == QDialog::Accepted) {
- VarMap net = dlg.getNetwork();
+ QVariantMap net = dlg.getNetwork();
networks.remove(curnet);
networks[net["Name"].toString()] = net;
Client::storeSessionData("Networks", networks);
void ServerListDlg::on_deleteButton_clicked() {
if(QMessageBox::warning(this, tr("Remove Network?"), tr("Are you sure you want to delete the selected network(s)?"),
QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
- VarMap networks = Client::retrieveSessionData("Networks").toMap();
+ QVariantMap networks = Client::retrieveSessionData("Networks").toMap();
QList<QTreeWidgetItem *> sel = ui.networkTree->selectedItems();
foreach(QTreeWidgetItem *item, sel) {
networks.remove(item->text(0));
foreach(QTreeWidgetItem *item, list) {
nets << item->text(0);
}
- emit requestConnect(nets);
+ emit requestConnect(nets[0]); // FIXME
QDialog::accept();
}
/***************************************************************************/
-NetworkEditDlg::NetworkEditDlg(QWidget *parent, VarMap _network) : QDialog(parent) {
+NetworkEditDlg::NetworkEditDlg(QWidget *parent, QVariantMap _network) : QDialog(parent) {
ui.setupUi(this);
network = _network;
oldName = network["Name"].toString();
connect(ui.serverList, SIGNAL(itemSelectionChanged()), this, SLOT(updateServerButtons()));
- VarMap identities = Client::retrieveSessionData("Identities").toMap();
+ QVariantMap identities = Client::retrieveSessionData("Identities").toMap();
ui.identityList->addItem(tr("Default Identity"));
foreach(QString id, identities.keys()) {
if(id != "Default") ui.identityList->addItem(id);
}
QStringList groups; groups << "";
- VarMap nets = Client::retrieveSessionData("Networks").toMap();
+ QVariantMap nets = Client::retrieveSessionData("Networks").toMap();
foreach(QString net, nets.keys()) {
QString gr = nets[net].toMap()["Group"].toString();
if(!groups.contains(gr) && !gr.isEmpty()) {
ui.networkName->setFocus();
}
-VarMap NetworkEditDlg::createDefaultNetwork() {
- VarMap net;
+QVariantMap NetworkEditDlg::createDefaultNetwork() {
+ QVariantMap net;
net["Name"] = QString();
net["Group"] = QString();
void NetworkEditDlg::updateWidgets() {
ui.serverList->clear();
foreach(QVariant s, network["Servers"].toList()) {
- VarMap server = s.toMap();
+ QVariantMap server = s.toMap();
QString entry = QString("%1:%2").arg(server["Address"].toString()).arg(server["Port"].toInt());
QListWidgetItem *item = new QListWidgetItem(entry);
//if(server["Exclude"].toBool()) item->setCheckState(Qt::Checked);
QString NetworkEditDlg::checkValidity() {
QString r;
- VarMap nets = Client::retrieveSessionData("Networks").toMap();
+ QVariantMap nets = Client::retrieveSessionData("Networks").toMap();
if(ui.networkName->text() != oldName && nets.keys().contains(ui.networkName->text())) {
r += tr(" Network name already exists.");
}
else id = "Default";
IdentitiesDlg dlg(this, id);
if(dlg.exec() == QDialog::Accepted) {
- VarMap identities = Client::retrieveSessionData("Identities").toMap();
+ QVariantMap identities = Client::retrieveSessionData("Identities").toMap();
ui.identityList->clear();
ui.identityList->addItem(tr("Default Identity"));
foreach(QString i, identities.keys()) {
/***************************************************************************/
-ServerEditDlg::ServerEditDlg(QWidget *parent, VarMap server) : QDialog(parent) {
+ServerEditDlg::ServerEditDlg(QWidget *parent, QVariantMap server) : QDialog(parent) {
ui.setupUi(this);
if(!server.isEmpty()) {
ui.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(!ui.serverAddress->text().isEmpty());
}
-VarMap ServerEditDlg::getServer() {
- VarMap s;
+QVariantMap ServerEditDlg::getServer() {
+ QVariantMap s;
s["Address"] = ui.serverAddress->text();
s["Port"] = ui.serverPort->text();
return s;
virtual void accept();
signals:
- void requestConnect(QStringList networks);
+ void requestConnect(QString network);
private slots:
void updateButtons();
private:
Ui::ServerListDlg ui;
- //VarMap networks;
- //VarMap identities; <-- this is now stored in global
+ //QVariantMap networks;
+ //QVariantMap identities; <-- this is now stored in global
};
class NetworkEditDlg : public QDialog {
Q_OBJECT
public:
- NetworkEditDlg(QWidget *parent, VarMap network);
+ NetworkEditDlg(QWidget *parent, QVariantMap network);
- VarMap getNetwork() { return network; }
+ QVariantMap getNetwork() { return network; }
public slots:
virtual void accept();
private:
Ui::NetworkEditDlg ui;
- VarMap network;
- //VarMap identities;
+ QVariantMap network;
+ //QVariantMap identities;
QString oldName;
- VarMap createDefaultNetwork();
+ QVariantMap createDefaultNetwork();
QString checkValidity();
};
Q_OBJECT
public:
- ServerEditDlg(QWidget *parent, VarMap server = VarMap());
+ ServerEditDlg(QWidget *parent, QVariantMap server = QVariantMap());
- VarMap getServer();
+ QVariantMap getServer();
private slots:
void on_serverAddress_textChanged();