Committing a whole bunch of Identity-related stuff that's not actually used yet,
authorManuel Nickschas <sputnick@quassel-irc.org>
Sat, 5 Jan 2008 20:51:57 +0000 (20:51 +0000)
committerManuel Nickschas <sputnick@quassel-irc.org>
Sat, 5 Jan 2008 20:51:57 +0000 (20:51 +0000)
so that I can fix an annoying QSettings related bug (and move us over to
the new settings location while I'm at it).

22 files changed:
Quassel.kdevelop.filelist
src/client/client.cpp
src/client/client.h
src/common/common.pri
src/common/global.cpp
src/common/global.h
src/common/identity.cpp [new file with mode: 0644]
src/common/identity.h [new file with mode: 0644]
src/common/main.cpp
src/common/types.h
src/core/coresession.cpp
src/core/coresession.h
src/core/sqlitestorage.cpp
src/core/storage.h
src/qtopia/qtopiamainwin.cpp
src/qtui/mainwin.cpp
src/qtui/settingspages/identitiessettingspage.cpp
src/qtui/settingspages/identitiessettingspage.h
src/qtui/settingspages/identitiessettingspage.ui
src/qtui/ui/topicwidget.ui
templates/cpp
templates/h

index ca168e9..4691796 100644 (file)
@@ -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
index 7f464c4..ab54311 100644 (file)
@@ -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> 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<NetworkInfo *> 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<IdentityId> 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<Identity>(), 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()));
   }
index cae4f9f..60aa7c1 100644 (file)
@@ -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<IdentityId> 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<uint, Buffer *> _buffers;
-  QHash<uint, NetworkInfo*> _networkInfo;
+  QHash<BufferId, Buffer *> _buffers;
+  QHash<NetworkId, NetworkInfo *> _networkInfo;
+  QHash<IdentityId, Identity *> _identities;
 
   QTimer *layoutTimer;
   QList<Buffer *> layoutQueue;
index cab2cd0..13f971c 100644 (file)
@@ -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
index 53178df..a2742d8 100644 (file)
  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
  ***************************************************************************/
 #include <QObject>
+#include <QMetaType>
 
 #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>("QVariant");
+  qRegisterMetaType<Message>("Message");
+  qRegisterMetaType<BufferInfo>("BufferInfo");
+  qRegisterMetaType<Identity>("Identity");
+
+  qRegisterMetaTypeStreamOperators<QVariant>("QVariant");
+  qRegisterMetaTypeStreamOperators<Message>("Message");
+  qRegisterMetaTypeStreamOperators<BufferInfo>("BufferInfo");
+  qRegisterMetaTypeStreamOperators<Identity>("Identity");
+
+  // Basic types (typedefs)
+  // These use the standard stream operators
+  qRegisterMetaType<IdentityId>("IdentityId");
+  qRegisterMetaType<BufferId>("BufferId");
+  qRegisterMetaType<NetworkId>("NetworkId");
+
+  qRegisterMetaTypeStreamOperators<IdentityId>("IdentityId");
+  qRegisterMetaTypeStreamOperators<BufferId>("BufferId");
+  qRegisterMetaTypeStreamOperators<NetworkId>("NetworkId");
+
+}
+
 Global::RunMode Global::runMode;
 uint Global::defaultPort;
 
index 79cfce5..e8db8bb 100644 (file)
@@ -23,6 +23,8 @@
 #ifndef _GLOBAL_H_
 #define _GLOBAL_H_
 
+#include <QString>
+
 // Enable some shortcuts and stuff
 //#define DEVELMODE
 
 /* 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 (file)
index 0000000..c35b841
--- /dev/null
@@ -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 <QMetaProperty>
+#include <QVariantMap>
+
+#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 (file)
index 0000000..446ecfe
--- /dev/null
@@ -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 <QDataStream>
+#include <QMetaType>
+#include <QString>
+#include <QStringList>
+
+#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
index 9f6f066..f715192 100644 (file)
@@ -19,6 +19,7 @@
  ***************************************************************************/
 
 #include "global.h"
+#include "identity.h"
 #include "settings.h"
 #include <QString>
 #include <QTranslator>
@@ -58,13 +59,7 @@ int main(int argc, char **argv) {
   signal(SIGTERM, handle_signal);
   signal(SIGINT, handle_signal);
 
-  qRegisterMetaType<QVariant>("QVariant");
-  qRegisterMetaType<Message>("Message");
-  qRegisterMetaType<BufferInfo>("BufferInfo");
-  qRegisterMetaTypeStreamOperators<QVariant>("QVariant");
-  qRegisterMetaTypeStreamOperators<Message>("Message");
-  qRegisterMetaTypeStreamOperators<BufferInfo>("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
index 9e62ffd..40ebf2f 100644 (file)
 
 #include <QString>
 
-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 {
index 426bcdc..bb24c7a 100644 (file)
@@ -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<Identity>(), 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<QVariant> idlist;
+  foreach(Identity *i, _identities.values()) idlist << QVariant::fromValue<Identity>(*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<Identity>(*_identities[id.id()]));
+  s.endGroup();
+}
+
+void CoreSession::removeIdentity(IdentityId id) {
+  Identity *i = _identities.take(id);
+  if(i) {
+    emit identityRemoved(id);
+    i->deleteLater();
+  }
+}
+
index 33b09d7..304c70d 100644 (file)
@@ -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<IdentityId, Identity *> _identities;
 };
 
 #endif
index 52846cd..8a6afe3 100644 (file)
@@ -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
   {
index c049dc1..4a22524 100644 (file)
@@ -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, ...  
index 68b2ef1..b35c043 100644 (file)
 // 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>("QVariant");
-  qRegisterMetaType<Message>("Message");
-  qRegisterMetaType<BufferInfo>("BufferInfo");
-  qRegisterMetaTypeStreamOperators<QVariant>("QVariant");
-  qRegisterMetaTypeStreamOperators<Message>("Message");
-  qRegisterMetaTypeStreamOperators<BufferInfo>("BufferInfo");
+  Global::registerMetaTypes();
 
   Global::runMode = Global::ClientOnly;
   Global::defaultPort = 4242;
index a12b043..fee617d 100644 (file)
@@ -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();
index a961712..3c8ce35 100644 (file)
 
 #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() {
index 5d6dd23..70031d2 100644 (file)
@@ -38,6 +38,9 @@ class IdentitiesSettingsPage : public SettingsPage {
     void load();
     void defaults();
 
+  private slots:
+    void coreConnectionStateChanged(bool);
+
   private:
     Ui::IdentitiesSettingsPage ui;
 
index 0a22167..19bb198 100644 (file)
@@ -10,7 +10,7 @@
    </rect>
   </property>
   <property name="windowTitle" >
-   <string>Form</string>
+   <string/>
   </property>
   <layout class="QVBoxLayout" >
    <item>
index e06b7e3..53d8825 100644 (file)
@@ -6,7 +6,7 @@
     <x>0</x>
     <y>0</y>
     <width>568</width>
-    <height>31</height>
+    <height>28</height>
    </rect>
   </property>
   <property name="sizePolicy" >
@@ -28,7 +28,7 @@
    </size>
   </property>
   <property name="windowTitle" >
-   <string/>
+   <string>Form</string>
   </property>
   <layout class="QHBoxLayout" >
    <property name="leftMargin" >
index 38628a3..ea31117 100644 (file)
@@ -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        *
index 8893eff..f579a1d 100644 (file)
@@ -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        *