From c6bc07febff322910675a1eb60c44f6be209a934 Mon Sep 17 00:00:00 2001 From: Manuel Nickschas Date: Sat, 5 Jan 2008 20:51:57 +0000 Subject: [PATCH] Committing a whole bunch of Identity-related stuff that's not actually used yet, so that I can fix an annoying QSettings related bug (and move us over to the new settings location while I'm at it). --- Quassel.kdevelop.filelist | 28 +++ src/client/client.cpp | 173 ++++++++++++------ src/client/client.h | 51 +++++- src/common/common.pri | 4 +- src/common/global.cpp | 32 ++++ src/common/global.h | 9 + src/common/identity.cpp | 164 +++++++++++++++++ src/common/identity.h | 94 ++++++++++ src/common/main.cpp | 24 +-- src/common/types.h | 10 +- src/core/coresession.cpp | 89 +++++++-- src/core/coresession.h | 27 ++- src/core/sqlitestorage.cpp | 2 + src/core/storage.h | 2 +- src/qtopia/qtopiamainwin.cpp | 7 +- src/qtui/mainwin.cpp | 2 +- .../settingspages/identitiessettingspage.cpp | 12 +- .../settingspages/identitiessettingspage.h | 3 + .../settingspages/identitiessettingspage.ui | 2 +- src/qtui/ui/topicwidget.ui | 4 +- templates/cpp | 2 +- templates/h | 2 +- 22 files changed, 635 insertions(+), 108 deletions(-) create mode 100644 src/common/identity.cpp create mode 100644 src/common/identity.h diff --git a/Quassel.kdevelop.filelist b/Quassel.kdevelop.filelist index ca168e9e..46917963 100644 --- a/Quassel.kdevelop.filelist +++ b/Quassel.kdevelop.filelist @@ -1,5 +1,27 @@ # KDevelop Custom Project File List build +build/buildconf.pri +build/contrib +build/contrib/contrib.pri +build/contrib/libqxt-config.pri +build/contrib/libqxt-version.pri +build/contrib/libqxt.pro +build/modules +build/modules/client.pro +build/modules/common.pro +build/modules/core.pro +build/modules/module.pri +build/modules/qtui.pro +build/modules/uisupport.pro +build/quassel.pro +build/targets +build/targets/core.pri +build/targets/core.pro +build/targets/monolithic.pri +build/targets/monolithic.pro +build/targets/qtclient.pri +build/targets/qtclient.pro +build/targets/target.pri qtopia-build qtopia-build/quasseltopia.pro quassel.pro @@ -31,6 +53,8 @@ src/common/bufferinfo.h src/common/common.pri src/common/global.cpp src/common/global.h +src/common/identity.cpp +src/common/identity.h src/common/ircchannel.cpp src/common/ircchannel.h src/common/ircuser.cpp @@ -170,6 +194,10 @@ src/qtui/ui/settingsdlg.ui src/qtui/ui/topicwidget.ui src/qtui/ui/usermgmtpage.ui src/uisupport +src/uisupport/action.cpp +src/uisupport/action.h +src/uisupport/actioncollection.cpp +src/uisupport/actioncollection.h src/uisupport/bufferview.cpp src/uisupport/bufferview.h src/uisupport/bufferviewfilter.cpp diff --git a/src/client/client.cpp b/src/client/client.cpp index 7f464c40..ab543118 100644 --- a/src/client/client.cpp +++ b/src/client/client.cpp @@ -22,6 +22,7 @@ #include "bufferinfo.h" #include "global.h" +#include "identity.h" #include "ircchannel.h" #include "ircuser.h" #include "message.h" @@ -33,9 +34,8 @@ QPointer Client::instanceptr = 0; -// ============================== -// public Static Methods -// ============================== +/*** Initialization/destruction ***/ + Client *Client::instance() { if(!instanceptr) instanceptr = new Client(); @@ -51,6 +51,76 @@ void Client::init(AbstractUi *ui) { instance()->init(); } +Client::Client(QObject *parent) + : QObject(parent), + socket(0), + _signalProxy(new SignalProxy(SignalProxy::Client, this)), + mainUi(0), + _networkModel(0), + connectedToCore(false) +{ + +} + +Client::~Client() { + +} + +void Client::init() { + blockSize = 0; + + _networkModel = new NetworkModel(this); + + connect(this, SIGNAL(bufferSelected(Buffer *)), + _networkModel, SLOT(selectBuffer(Buffer *))); + connect(this, SIGNAL(bufferUpdated(Buffer *)), + _networkModel, SLOT(bufferUpdated(Buffer *))); + connect(this, SIGNAL(bufferActivity(Buffer::ActivityLevel, Buffer *)), + _networkModel, SLOT(bufferActivity(Buffer::ActivityLevel, Buffer *))); + + SignalProxy *p = signalProxy(); + p->attachSignal(this, SIGNAL(sendSessionData(const QString &, const QVariant &)), + SIGNAL(clientSessionDataChanged(const QString &, const QVariant &))); + p->attachSlot(SIGNAL(coreSessionDataChanged(const QString &, const QVariant &)), + this, SLOT(recvSessionData(const QString &, const QVariant &))); + p->attachSlot(SIGNAL(coreState(const QVariant &)), + this, SLOT(recvCoreState(const QVariant &))); + p->attachSlot(SIGNAL(networkConnected(uint)), + this, SLOT(networkConnected(uint))); + p->attachSlot(SIGNAL(networkDisconnected(uint)), + this, SLOT(networkDisconnected(uint))); + p->attachSlot(SIGNAL(displayMsg(const Message &)), + this, SLOT(recvMessage(const Message &))); + p->attachSlot(SIGNAL(displayStatusMsg(QString, QString)), + this, SLOT(recvStatusMsg(QString, QString))); + + + p->attachSlot(SIGNAL(backlogData(BufferInfo, const QVariantList &, bool)), this, SLOT(recvBacklogData(BufferInfo, const QVariantList &, bool))); + p->attachSlot(SIGNAL(bufferInfoUpdated(BufferInfo)), this, SLOT(updateBufferInfo(BufferInfo))); + p->attachSignal(this, SIGNAL(sendInput(BufferInfo, QString))); + p->attachSignal(this, SIGNAL(requestNetworkStates())); + + p->attachSignal(this, SIGNAL(requestCreateIdentity(const Identity &)), SIGNAL(createIdentity(const Identity &))); + p->attachSignal(this, SIGNAL(requestUpdateIdentity(const Identity &)), SIGNAL(updateIdentity(const Identity &))); + p->attachSignal(this, SIGNAL(requestRemoveIdentity(IdentityId)), SIGNAL(removeIdentity(IdentityId))); + p->attachSlot(SIGNAL(identityCreated(const Identity &)), this, SLOT(coreIdentityCreated(const Identity &))); + p->attachSlot(SIGNAL(identityRemoved(IdentityId)), this, SLOT(coreIdentityRemoved(IdentityId))); + + 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())); + + layoutTimer = new QTimer(this); + layoutTimer->setInterval(0); + layoutTimer->setSingleShot(false); + connect(layoutTimer, SIGNAL(timeout()), this, SLOT(layoutMsg())); + +} + +/*** public static methods ***/ + + QList Client::networkInfos() { return instance()->_networkInfo.values(); } @@ -126,68 +196,53 @@ SignalProxy *Client::signalProxy() { return instance()->_signalProxy; } -// ============================== -// Constructor / Decon -// ============================== -Client::Client(QObject *parent) - : QObject(parent), - socket(0), - _signalProxy(new SignalProxy(SignalProxy::Client, this)), - mainUi(0), - _networkModel(0), - connectedToCore(false) -{ -} -Client::~Client() { - +/*** Identity handling ***/ + +QList Client::identityIds() { + return instance()->_identities.keys(); } -void Client::init() { - blockSize = 0; +const Identity * Client::identity(IdentityId id) { + if(instance()->_identities.contains(id)) return instance()->_identities[id]; + else return 0; +} - _networkModel = new NetworkModel(this); - connect(this, SIGNAL(bufferSelected(Buffer *)), - _networkModel, SLOT(selectBuffer(Buffer *))); - connect(this, SIGNAL(bufferUpdated(Buffer *)), - _networkModel, SLOT(bufferUpdated(Buffer *))); - connect(this, SIGNAL(bufferActivity(Buffer::ActivityLevel, Buffer *)), - _networkModel, SLOT(bufferActivity(Buffer::ActivityLevel, Buffer *))); +void Client::createIdentity(const Identity &id) { + emit instance()->requestCreateIdentity(id); +} - 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(networkConnected(uint)), - this, SLOT(networkConnected(uint))); - p->attachSlot(SIGNAL(networkDisconnected(uint)), - this, SLOT(networkDisconnected(uint))); - p->attachSlot(SIGNAL(displayMsg(const Message &)), - this, SLOT(recvMessage(const Message &))); - p->attachSlot(SIGNAL(displayStatusMsg(QString, QString)), - this, SLOT(recvStatusMsg(QString, QString))); +void Client::updateIdentity(const Identity &id) { + emit instance()->requestUpdateIdentity(id); +} +void Client::removeIdentity(IdentityId id) { + emit instance()->requestRemoveIdentity(id); +} - p->attachSlot(SIGNAL(backlogData(BufferInfo, const QVariantList &, bool)), this, SLOT(recvBacklogData(BufferInfo, const QVariantList &, bool))); - p->attachSlot(SIGNAL(bufferInfoUpdated(BufferInfo)), this, SLOT(updateBufferInfo(BufferInfo))); - p->attachSignal(this, SIGNAL(sendInput(BufferInfo, QString))); - p->attachSignal(this, SIGNAL(requestNetworkStates())); +void Client::coreIdentityCreated(const Identity &other) { + if(!_identities.contains(other.id())) { + Identity *identity = new Identity(other, this); + _identities[other.id()] = identity; + identity->setInitialized(); + signalProxy()->synchronize(identity); + emit identityCreated(other.id()); + } else { + qWarning() << tr("Identity already exists in client!"); + } +} - 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())); +void Client::coreIdentityRemoved(IdentityId id) { + if(_identities.contains(id)) { + emit identityRemoved(id); + Identity *i = _identities.take(id); + i->deleteLater(); + } +} - layoutTimer = new QTimer(this); - layoutTimer->setInterval(0); - layoutTimer->setSingleShot(false); - connect(layoutTimer, SIGNAL(timeout()), this, SLOT(layoutMsg())); +/*** ***/ -} bool Client::isConnected() { return instance()->connectedToCore; @@ -259,6 +314,7 @@ void Client::coreSocketConnected() { void Client::coreSocketDisconnected() { instance()->connectedToCore = false; emit disconnected(); + emit coreConnectionStateChanged(false); socket->deleteLater(); blockSize = 0; @@ -312,6 +368,14 @@ void Client::syncToCore(const QVariant &coreState) { foreach(QString key, sessData.keys()) recvSessionData(key, sessData[key]); + // create identities + foreach(QVariant vid, sessionState["Identities"].toList()) { + Identity *id = new Identity(vid.value(), this); + _identities[id->id()] = id; + signalProxy()->synchronize(id); + qDebug() << "received identity" << id->identityName(); + } + // store Buffer details QVariantList coreBuffers = sessionState["Buffers"].toList(); /* make lookups by id faster */ @@ -382,6 +446,7 @@ void Client::updateCoreConnectionProgress() { emit coreConnectionProgress(1,1); emit connected(); + emit coreConnectionStateChanged(true); foreach(NetworkInfo *net, networkInfos()) { disconnect(net, 0, this, SLOT(updateCoreConnectionProgress())); } diff --git a/src/client/client.h b/src/client/client.h index cae4f9f8..60aa7c1f 100644 --- a/src/client/client.h +++ b/src/client/client.h @@ -30,6 +30,7 @@ class BufferInfo; class Message; +class Identity; class NetworkInfo; @@ -59,6 +60,27 @@ public: static BufferInfo statusBufferInfo(QString net); static BufferInfo bufferInfo(QString net, QString buf); + static QList identityIds(); + static const Identity * identity(IdentityId); + + //! Request creation of an identity with the given data. + /** The request will be sent to the core, and will be propagated back to all the clients + * with a new valid IdentityId. + * \param identity The identity template for the new identity. It does not need to have a valid ID. + */ + static void createIdentity(const Identity &identity); + + //! Request update of an identity with the given data. + /** The request will be sent to the core, and will be propagated back to all the clients. + * \param identity The identity to be updated. + */ + static void updateIdentity(const Identity &identity); + + //! Request removal of the identity with the given ID from the core (and all the clients, of course). + /** \param id The ID of the identity to be removed. + */ + static void removeIdentity(IdentityId id); + static NetworkModel *networkModel(); static SignalProxy *signalProxy(); @@ -94,11 +116,32 @@ signals: void connected(); void disconnected(); + void coreConnectionStateChanged(bool); void sessionDataChanged(const QString &key); void sessionDataChanged(const QString &key, const QVariant &data); void sendSessionData(const QString &key, const QVariant &data); + //! The identity with the given ID has been newly created in core and client. + /** \param id The ID of the newly created identity. + */ + void identityCreated(IdentityId id); + + //! The identity with the given ID has been removed. + /** Upon emitting this signal, the identity is already gone from the core, and it will + * be deleted from the client immediately afterwards, so connected slots need to clean + * up their stuff. + * \param id The ID of the identity about to be removed. + */ + void identityRemoved(IdentityId id); + + //! Sent to the core when an identity shall be created. Should not be used elsewhere. + void requestCreateIdentity(const Identity &); + //! Sent to the core when an identity shall be updated. Should not be used elsewhere. + void requestUpdateIdentity(const Identity &); + //! Sent to the core when an identity shall be removed. Should not be used elsewhere. + void requestRemoveIdentity(IdentityId); + public slots: //void selectBuffer(Buffer *); //void connectToLocalCore(); @@ -129,10 +172,11 @@ private slots: void layoutMsg(); -private slots: void bufferDestroyed(); void networkInfoDestroyed(); void ircChannelAdded(QString); + void coreIdentityCreated(const Identity &); + void coreIdentityRemoved(IdentityId); private: Client(QObject *parent = 0); @@ -154,8 +198,9 @@ private: bool connectedToCore; QVariantMap coreConnectionInfo; - QHash _buffers; - QHash _networkInfo; + QHash _buffers; + QHash _networkInfo; + QHash _identities; QTimer *layoutTimer; QList layoutQueue; diff --git a/src/common/common.pri b/src/common/common.pri index cab2cd08..13f971c8 100644 --- a/src/common/common.pri +++ b/src/common/common.pri @@ -1,4 +1,4 @@ DEPMOD = QT_MOD = network -SRCS += bufferinfo.cpp global.cpp logger.cpp message.cpp settings.cpp signalproxy.cpp util.cpp networkinfo.cpp ircuser.cpp ircchannel.cpp -HDRS += bufferinfo.h global.h logger.h message.h settings.h signalproxy.h util.h networkinfo.h ircuser.h ircchannel.h types.h +SRCS += bufferinfo.cpp global.cpp identity.cpp logger.cpp message.cpp settings.cpp signalproxy.cpp util.cpp networkinfo.cpp ircuser.cpp ircchannel.cpp +HDRS += bufferinfo.h global.h identity.h logger.h message.h settings.h signalproxy.h util.h networkinfo.h ircuser.h ircchannel.h types.h diff --git a/src/common/global.cpp b/src/common/global.cpp index 53178dff..a2742d87 100644 --- a/src/common/global.cpp +++ b/src/common/global.cpp @@ -18,9 +18,14 @@ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include +#include #include "global.h" #include "logger.h" +#include "message.h" +#include "identity.h" +#include "bufferinfo.h" +#include "types.h" extern void messageHandler(QtMsgType type, const char *msg); @@ -56,6 +61,33 @@ void Global::initIconMap() { // return 0; //} +//! Register our custom types with Qt's Meta Object System. +/** This makes them available for QVariant and in signals/slots, among other things. + */ +void Global::registerMetaTypes() { + // Complex types + qRegisterMetaType("QVariant"); + qRegisterMetaType("Message"); + qRegisterMetaType("BufferInfo"); + qRegisterMetaType("Identity"); + + qRegisterMetaTypeStreamOperators("QVariant"); + qRegisterMetaTypeStreamOperators("Message"); + qRegisterMetaTypeStreamOperators("BufferInfo"); + qRegisterMetaTypeStreamOperators("Identity"); + + // Basic types (typedefs) + // These use the standard stream operators + qRegisterMetaType("IdentityId"); + qRegisterMetaType("BufferId"); + qRegisterMetaType("NetworkId"); + + qRegisterMetaTypeStreamOperators("IdentityId"); + qRegisterMetaTypeStreamOperators("BufferId"); + qRegisterMetaTypeStreamOperators("NetworkId"); + +} + Global::RunMode Global::runMode; uint Global::defaultPort; diff --git a/src/common/global.h b/src/common/global.h index 79cfce53..e8db8bb8 100644 --- a/src/common/global.h +++ b/src/common/global.h @@ -23,6 +23,8 @@ #ifndef _GLOBAL_H_ #define _GLOBAL_H_ +#include + // Enable some shortcuts and stuff //#define DEVELMODE @@ -35,9 +37,16 @@ /* Some global stuff */ namespace Global { + // We need different config (QSettings) files for client and gui, since the core cannot work with GUI types + // Set these here. They're used in ClientSettings and CoreSettings. + const QString coreApplicationName = "Quassel IRC Core"; + const QString clientApplicationName = "Quassel IRC Client"; + enum RunMode { Monolithic, ClientOnly, CoreOnly }; extern RunMode runMode; extern unsigned int defaultPort; + + void registerMetaTypes(); } #endif diff --git a/src/common/identity.cpp b/src/common/identity.cpp new file mode 100644 index 00000000..c35b8412 --- /dev/null +++ b/src/common/identity.cpp @@ -0,0 +1,164 @@ +/*************************************************************************** + * Copyright (C) 2005-08 by the Quassel IRC Team * + * devel@quassel-irc.org * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) version 3. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include +#include + +#include "identity.h" + +Identity::Identity(IdentityId id, QObject *parent) : QObject(parent), _identityId(id) { + init(); + setToDefaults(); +} + +Identity::Identity(const Identity &other, QObject *parent) : QObject(parent), + _identityId(other.id()), + _identityName(other.identityName()), + _realName(other.realName()), + _nicks(other.nicks()), + _awayNick(other.awayNick()), + _awayReason(other.awayReason()), + _returnMessage(other.returnMessage()) { + init(); +} + +void Identity::init() { + _initialized = false; + setObjectName(QString::number(id())); +} + +void Identity::setToDefaults() { + setIdentityName(tr("Default Identity")); + setRealName(tr("Quassel IRC User")); + QStringList n; + n << QString("quassel%1").arg(qrand() & 0xff); // FIXME provide more sensible default nicks + setNicks(n); + setAwayNick(""); + setAwayReason(tr("Gone fishing.")); + setReturnMessage(tr("Brought fish.")); + +} + +bool Identity::initialized() const { + return _initialized; +} + +void Identity::setInitialized() { + _initialized = true; +} + +IdentityId Identity::id() const { + return _identityId; +} + +QString Identity::identityName() const { + return _identityName; +} + +QString Identity::realName() const { + return _realName; +} + +QStringList Identity::nicks() const { + return _nicks; +} + +QString Identity::awayNick() const { + return _awayNick; +} + +QString Identity::awayReason() const { + return _awayReason; +} + +QString Identity::returnMessage() const { + return _returnMessage; +} + +////////////////////// + +void Identity::setIdentityName(const QString &identityName) { + _identityName = identityName; + emit identityNameSet(identityName); +} + +void Identity::setRealName(const QString &realName) { + _realName = realName; + emit realNameSet(realName); +} + +void Identity::setNicks(const QStringList &nicks) { + _nicks = nicks; + emit nicksSet(nicks); +} + +void Identity::setAwayNick(const QString &nick) { + _awayNick = nick; + emit awayNickSet(nick); +} + +void Identity::setAwayReason(const QString &reason) { + _awayReason = reason; + emit awayReasonSet(reason); +} + +void Identity::setReturnMessage(const QString &message) { + _returnMessage = message; + emit returnMessageSet(message); +} + +void Identity::update(const Identity &other) { + for(int idx = 0; idx < metaObject()->propertyCount(); idx++) { + QMetaProperty metaProp = metaObject()->property(metaObject()->propertyOffset() + idx); + Q_ASSERT(metaProp.isValid()); + if(this->property(metaProp.name()) != other.property(metaProp.name())) { + setProperty(metaProp.name(), other.property(metaProp.name())); + } + } +} + +/////////////////////////////// + +// we use a hash, so we can easily extend identities without breaking saved ones +QDataStream &operator<<(QDataStream &out, const Identity &id) { + QVariantMap i; + i["IdentityId"] = id.id(); + i["IdentityName"] = id.identityName(); + i["RealName"] = id.realName(); + i["Nicks"] = id.nicks(); + i["AwayNick"] = id.awayNick(); + i["AwayReason"] = id.awayReason(); + i["ReturnMessage"] = id.returnMessage(); + out << i; + return out; +} + +QDataStream &operator>>(QDataStream &in, Identity &id) { + QVariantMap i; + in >> i; + id._identityId = i["IdentityId"].toUInt(); + id.setIdentityName(i["IdentityName"].toString()); + id.setRealName(i["RealName"].toString()); + id.setNicks(i["Nicks"].toStringList()); + id.setAwayNick(i["AwayNick"].toString()); + id.setAwayReason(i["AwayReason"].toString()); + id.setReturnMessage(i["ReturnMessage"].toString()); + return in; +} diff --git a/src/common/identity.h b/src/common/identity.h new file mode 100644 index 00000000..446ecfe5 --- /dev/null +++ b/src/common/identity.h @@ -0,0 +1,94 @@ +/*************************************************************************** + * Copyright (C) 2005-08 by the Quassel IRC Team * + * devel@quassel-irc.org * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) version 3. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#ifndef _IDENTITY_H_ +#define _IDENTITY_H_ + +#include +#include +#include +#include + +#include "types.h" + +class Identity : public QObject { + Q_OBJECT + + Q_PROPERTY(IdentityId identityId READ id STORED false) + Q_PROPERTY(QString identityName READ identityName WRITE setIdentityName STORED false) + Q_PROPERTY(QString realName READ realName WRITE setRealName STORED false) + Q_PROPERTY(QStringList nicks READ nicks WRITE setNicks STORED false) + Q_PROPERTY(QString awayNick READ awayNick WRITE setAwayNick STORED false) + Q_PROPERTY(QString awayReason READ awayReason WRITE setAwayReason STORED false) + Q_PROPERTY(QString returnMessage READ returnMessage WRITE setReturnMessage STORED false) + //Q_PROPERTY( + + public: + Identity(IdentityId id = -1, QObject *parent = 0); + Identity(const Identity &other, QObject *parent = 0); + void setToDefaults(); + + IdentityId id() const; + QString identityName() const; + QString realName() const; + QStringList nicks() const; + QString awayNick() const; + QString awayReason() const; + QString returnMessage() const; + + bool initialized() const; + void setInitialized(); + + public slots: + void setIdentityName(const QString &name); + void setRealName(const QString &realName); + void setNicks(const QStringList &nicks); + void setAwayNick(const QString &awayNick); + void setAwayReason(const QString &awayReason); + void setReturnMessage(const QString &returnMessage); + + void update(const Identity &other); + + signals: + void identityNameSet(const QString &name); + void realNameSet(const QString &realName); + void nicksSet(const QStringList &nicks); + void awayNickSet(const QString &awayNick); + void awayReasonSet(const QString &awayReason); + void returnMessageSet(const QString &returnMessage); + + private: + bool _initialized; + IdentityId _identityId; + QString _identityName, _realName; + QStringList _nicks; + QString _awayNick, _awayReason, _returnMessage; + + void init(); + + friend QDataStream &operator>>(QDataStream &in, Identity &identity); +}; + +QDataStream &operator<<(QDataStream &out, const Identity &identity); +QDataStream &operator>>(QDataStream &in, Identity &identity); + +Q_DECLARE_METATYPE(Identity); + +#endif diff --git a/src/common/main.cpp b/src/common/main.cpp index 9f6f066b..f7151923 100644 --- a/src/common/main.cpp +++ b/src/common/main.cpp @@ -19,6 +19,7 @@ ***************************************************************************/ #include "global.h" +#include "identity.h" #include "settings.h" #include #include @@ -58,13 +59,7 @@ int main(int argc, char **argv) { signal(SIGTERM, handle_signal); signal(SIGINT, handle_signal); - qRegisterMetaType("QVariant"); - qRegisterMetaType("Message"); - qRegisterMetaType("BufferInfo"); - qRegisterMetaTypeStreamOperators("QVariant"); - qRegisterMetaTypeStreamOperators("Message"); - qRegisterMetaTypeStreamOperators("BufferInfo"); - + Global::registerMetaTypes(); #if defined BUILD_CORE Global::runMode = Global::CoreOnly; @@ -79,16 +74,21 @@ int main(int argc, char **argv) { // Set up i18n support QLocale locale = QLocale::system(); - QTranslator translator; - translator.load(QString(":i18n/quassel_%1").arg(locale.name())); - app.installTranslator(&translator); + + QTranslator qtTranslator; + qtTranslator.load(QString(":i18n/qt_%1").arg(locale.name())); + app.installTranslator(&qtTranslator); + + QTranslator quasselTranslator; + quasselTranslator.load(QString(":i18n/quassel_%1").arg(locale.name())); + app.installTranslator(&quasselTranslator); QCoreApplication::setOrganizationDomain("quassel-irc.org"); QCoreApplication::setApplicationName("Quassel IRC"); QCoreApplication::setOrganizationName("Quassel IRC Development Team"); // FIXME // Check if a non-standard core port is requested - QStringList args = QCoreApplication::arguments(); + QStringList args = QCoreApplication::arguments(); // TODO Build a CLI parser Global::defaultPort = 4242; int idx; @@ -110,7 +110,7 @@ int main(int argc, char **argv) { #endif #ifndef BUILD_QTUI - if(!QCoreApplication::arguments().contains("--norestore")) { + if(args.contains("--norestore")) { Core::restoreState(); } #endif diff --git a/src/common/types.h b/src/common/types.h index 9e62ffd8..40ebf2f0 100644 --- a/src/common/types.h +++ b/src/common/types.h @@ -23,10 +23,12 @@ #include -typedef uint UserId; //!< Identifies a core user. -typedef uint MsgId; //!< Identifies a message. -typedef uint BufferId; //!< Identifies a buffer. -typedef uint NetworkId; //!< Identifies an IRC Network. +// FIXME make all ID types quint32 as soon as they all have been replaced +typedef uint UserId; //!< Identifies a core user. +typedef uint MsgId; //!< Identifies a message. +typedef uint BufferId; //!< Identifies a buffer. +typedef uint NetworkId; //!< Identifies an IRC Network. +typedef quint32 IdentityId; //!< Identifies an identity. //! Base class for exceptions. struct Exception { diff --git a/src/core/coresession.cpp b/src/core/coresession.cpp index 426bcdc7..bb24c7ab 100644 --- a/src/core/coresession.cpp +++ b/src/core/coresession.cpp @@ -27,6 +27,7 @@ #include "networkinfo.h" #include "ircuser.h" #include "ircchannel.h" +#include "identity.h" #include "util.h" @@ -39,16 +40,41 @@ CoreSession::CoreSession(UserId uid, Storage *_storage, QObject *parent) storage(_storage), scriptEngine(new QScriptEngine(this)) { - - QSettings s; - s.beginGroup(QString("SessionData/%1").arg(user)); + + SignalProxy *p = signalProxy(); + + QSettings s; // FIXME don't use QSettings anymore mutex.lock(); + s.beginGroup(QString("SessionData/%1").arg(user)); foreach(QString key, s.allKeys()) { sessionData[key] = s.value(key); } + s.endGroup(); + mutex.unlock(); // FIXME remove + /* temporarily disabled + s.beginGroup(QString("Identities/%1").arg(user)); + foreach(QString id, s.childKeys()) { + Identity *i = new Identity(s.value(id).value(), this); + if(i->id() < 1) { + qDebug() << QString("Invalid identity!"); + continue; + } + if(_identities.contains(i->id())) { + qDebug() << "Duplicate identity, ignoring!"; + continue; + } + qDebug() << "loaded identity" << id; + _identities[i->id()] = i; + } + s.endGroup(); mutex.unlock(); - - SignalProxy *p = signalProxy(); + if(!_identities.count()) { + Identity i(1); + i.setToDefaults(); + //_identities[i->id()] = i; + createOrUpdateIdentity(i); + } + */ p->attachSlot(SIGNAL(requestNetworkStates()), this, SLOT(serverStateRequested())); p->attachSlot(SIGNAL(requestConnect(QString)), this, SLOT(connectToNetwork(QString))); @@ -61,19 +87,18 @@ CoreSession::CoreSession(UserId uid, Storage *_storage, QObject *parent) p->attachSignal(storage, SIGNAL(bufferInfoUpdated(BufferInfo))); p->attachSignal(this, SIGNAL(sessionDataChanged(const QString &, const QVariant &)), SIGNAL(coreSessionDataChanged(const QString &, const QVariant &))); p->attachSlot(SIGNAL(clientSessionDataChanged(const QString &, const QVariant &)), this, SLOT(storeSessionData(const QString &, const QVariant &))); - /* Autoconnect. (When) do we actually do this? - --> session restore should be enough! - QStringList list; - QVariantMap networks = retrieveSessionData("Networks").toMap(); - foreach(QString net, networks.keys()) { - if(networks[net].toMap()["AutoConnect"].toBool()) { - list << net; - } - } qDebug() << list; - if(list.count()) connectToIrc(list); - */ + + p->attachSignal(this, SIGNAL(identityCreated(const Identity &))); + p->attachSignal(this, SIGNAL(identityRemoved(IdentityId))); + p->attachSlot(SIGNAL(createIdentity(const Identity &)), this, SLOT(createOrUpdateIdentity(const Identity &))); + p->attachSlot(SIGNAL(updateIdentity(const Identity &)), this, SLOT(createOrUpdateIdentity(const Identity &))); + p->attachSlot(SIGNAL(removeIdentity(IdentityId)), this, SLOT(removeIdentity(IdentityId))); initScriptEngine(); + + foreach(Identity *id, _identities.values()) { + p->synchronize(id); + } } CoreSession::~CoreSession() { @@ -236,10 +261,14 @@ QVariant CoreSession::sessionState() { mutex.unlock(); QVariantList networks; - foreach(uint networkid, servers.keys()) + foreach(NetworkId networkid, servers.keys()) networks.append(QVariant(networkid)); v["Networks"] = QVariant(networks); + QList idlist; + foreach(Identity *i, _identities.values()) idlist << QVariant::fromValue(*i); + v["Identities"] = idlist; + // v["Payload"] = QByteArray(100000000, 'a'); // for testing purposes return v; } @@ -277,4 +306,28 @@ void CoreSession::initScriptEngine() { void CoreSession::scriptRequest(QString script) { emit scriptResult(scriptEngine->evaluate(script).toString()); } - + +void CoreSession::createOrUpdateIdentity(const Identity &id) { + if(!_identities.contains(id.id())) { + // create new + _identities[id.id()] = new Identity(id, this); + signalProxy()->synchronize(_identities[id.id()]); + emit identityCreated(id.id()); + } else { + // update + _identities[id.id()]->update(id); + } + QSettings s; // FIXME don't use QSettings + s.beginGroup(QString("Identities/%1").arg(user)); + s.setValue(QString::number(id.id()), QVariant::fromValue(*_identities[id.id()])); + s.endGroup(); +} + +void CoreSession::removeIdentity(IdentityId id) { + Identity *i = _identities.take(id); + if(i) { + emit identityRemoved(id); + i->deleteLater(); + } +} + diff --git a/src/core/coresession.h b/src/core/coresession.h index 33b09d77..304c70dd 100644 --- a/src/core/coresession.h +++ b/src/core/coresession.h @@ -27,6 +27,7 @@ #include "message.h" +class Identity; class Server; class SignalProxy; class Storage; @@ -71,6 +72,16 @@ public slots: void sendBacklog(BufferInfo, QVariant, QVariant); void msgFromGui(BufferInfo, QString message); + //! Create or update an identity and propagate the changes to the clients. + /** \param identity The identity to be created/updated. + */ + void createOrUpdateIdentity(const Identity &identity); + + //! Remove identity and propagate that fact to the clients. + /** \param identity The identity to be removed. + */ + void removeIdentity(IdentityId identity); + signals: void msgFromGui(uint netid, QString buf, QString message); void displayMsg(Message message); @@ -86,7 +97,19 @@ signals: void sessionDataChanged(const QString &key, const QVariant &data); void scriptResult(QString result); - + + //! Identity has been created. + /** This signal is propagated to the clients to tell them that the given identity has been created. + * \param identity The new identity. + */ + void identityCreated(const Identity &identity); + + //! Identity has been removed. + /** This signal is propagated to the clients to inform them about the removal of the given identity. + * \param identity The identity that has been removed. + */ + void identityRemoved(IdentityId identity); + private slots: void recvStatusMsgFromServer(QString msg); void recvMessageFromServer(Message::Type, QString target, QString text, QString sender = "", quint8 flags = Message::None); @@ -108,6 +131,8 @@ private: QMutex mutex; QScriptEngine *scriptEngine; + + QHash _identities; }; #endif diff --git a/src/core/sqlitestorage.cpp b/src/core/sqlitestorage.cpp index 52846cda..8a6afe34 100644 --- a/src/core/sqlitestorage.cpp +++ b/src/core/sqlitestorage.cpp @@ -62,6 +62,7 @@ QString SqliteStorage::displayName() { } bool SqliteStorage::setup(const QVariantMap &settings) { + Q_UNUSED(settings); bool ok; // this extra scope is needed to be able to remove the database connection later { @@ -135,6 +136,7 @@ bool SqliteStorage::setup(const QVariantMap &settings) { } bool SqliteStorage::init(const QVariantMap &settings) { + Q_UNUSED(settings); bool ok; // i need the extra scope to be able to remove the database connection { diff --git a/src/core/storage.h b/src/core/storage.h index c049dc17..4a225243 100644 --- a/src/core/storage.h +++ b/src/core/storage.h @@ -52,7 +52,7 @@ class Storage : public QObject { * \param settings Hostname, port, username, password, ... * \return True if and only if the storage provider was initialized successfully. */ - virtual bool setup(const QVariantMap &settings = QVariantMap()) { return false; } + virtual bool setup(const QVariantMap &settings = QVariantMap()) { Q_UNUSED(settings); return false; } //! Initialize the storage provider /** \param settings Hostname, port, username, password, ... diff --git a/src/qtopia/qtopiamainwin.cpp b/src/qtopia/qtopiamainwin.cpp index 68b2ef1e..b35c0435 100644 --- a/src/qtopia/qtopiamainwin.cpp +++ b/src/qtopia/qtopiamainwin.cpp @@ -39,12 +39,7 @@ // This constructor is the first thing to be called for a Qtopia app, so we do the init stuff // here (rather than in a main.cpp). QtopiaMainWin::QtopiaMainWin(QWidget *parent, Qt::WFlags flags) : QMainWindow(parent, flags) { - qRegisterMetaType("QVariant"); - qRegisterMetaType("Message"); - qRegisterMetaType("BufferInfo"); - qRegisterMetaTypeStreamOperators("QVariant"); - qRegisterMetaTypeStreamOperators("Message"); - qRegisterMetaTypeStreamOperators("BufferInfo"); + Global::registerMetaTypes(); Global::runMode = Global::ClientOnly; Global::defaultPort = 4242; diff --git a/src/qtui/mainwin.cpp b/src/qtui/mainwin.cpp index a12b0434..fee617d4 100644 --- a/src/qtui/mainwin.cpp +++ b/src/qtui/mainwin.cpp @@ -66,7 +66,7 @@ void MainWin::init() { statusBar()->showMessage(tr("Not connected to core.")); systray = new QSystemTrayIcon(this); - systray->setIcon(QIcon(":/qirc-icon.png")); + systray->setIcon(QIcon(":/icons/quassel-icon.png")); systray->show(); //setupSettingsDlg(); diff --git a/src/qtui/settingspages/identitiessettingspage.cpp b/src/qtui/settingspages/identitiessettingspage.cpp index a961712a..3c8ce359 100644 --- a/src/qtui/settingspages/identitiessettingspage.cpp +++ b/src/qtui/settingspages/identitiessettingspage.cpp @@ -20,16 +20,26 @@ #include "identitiessettingspage.h" +#include "client.h" + IdentitiesSettingsPage::IdentitiesSettingsPage(QWidget *parent) : SettingsPage(tr("General"), tr("Identities"), parent) { ui.setupUi(this); + setEnabled(false); // need a core connection! + connect(Client::instance(), SIGNAL(coreConnectionStateChanged(bool)), this, SLOT(coreConnectionStateChanged(bool))); +} +void IdentitiesSettingsPage::coreConnectionStateChanged(bool state) { + //this->setEnabled(state); + if(state) { + load(); + } } bool IdentitiesSettingsPage::hasChanged() const { - + return true; } void IdentitiesSettingsPage::save() { diff --git a/src/qtui/settingspages/identitiessettingspage.h b/src/qtui/settingspages/identitiessettingspage.h index 5d6dd232..70031d25 100644 --- a/src/qtui/settingspages/identitiessettingspage.h +++ b/src/qtui/settingspages/identitiessettingspage.h @@ -38,6 +38,9 @@ class IdentitiesSettingsPage : public SettingsPage { void load(); void defaults(); + private slots: + void coreConnectionStateChanged(bool); + private: Ui::IdentitiesSettingsPage ui; diff --git a/src/qtui/settingspages/identitiessettingspage.ui b/src/qtui/settingspages/identitiessettingspage.ui index 0a221675..19bb198f 100644 --- a/src/qtui/settingspages/identitiessettingspage.ui +++ b/src/qtui/settingspages/identitiessettingspage.ui @@ -10,7 +10,7 @@ - Form + diff --git a/src/qtui/ui/topicwidget.ui b/src/qtui/ui/topicwidget.ui index e06b7e3c..53d88254 100644 --- a/src/qtui/ui/topicwidget.ui +++ b/src/qtui/ui/topicwidget.ui @@ -6,7 +6,7 @@ 0 0 568 - 31 + 28 @@ -28,7 +28,7 @@ - + Form diff --git a/templates/cpp b/templates/cpp index 38628a3d..ea31117c 100644 --- a/templates/cpp +++ b/templates/cpp @@ -5,7 +5,7 @@ * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * + * (at your option) version 3. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * diff --git a/templates/h b/templates/h index 8893effd..f579a1dd 100644 --- a/templates/h +++ b/templates/h @@ -5,7 +5,7 @@ * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * + * (at your option) version 3. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * -- 2.20.1