Committing a lot of identity stuff which is still disabled.
authorManuel Nickschas <sputnick@quassel-irc.org>
Mon, 7 Jan 2008 16:34:59 +0000 (16:34 +0000)
committerManuel Nickschas <sputnick@quassel-irc.org>
Mon, 7 Jan 2008 16:34:59 +0000 (16:34 +0000)
25 files changed:
Quassel.kdevelop.filelist
src/client/client.cpp
src/common/global.h
src/common/identity.cpp
src/common/identity.h
src/common/main.cpp
src/common/signalproxy.cpp
src/common/types.h
src/core/coresession.cpp
src/core/coresession.h
src/core/coresettings.h
src/core/coreusersettings.cpp
src/core/coreusersettings.h
src/qtui/mainwin.cpp
src/qtui/qtui.h
src/qtui/settingsdlg.cpp
src/qtui/settingsdlg.h
src/qtui/settingspages/createidentitydlg.ui [new file with mode: 0644]
src/qtui/settingspages/identitiessettingspage.cpp
src/qtui/settingspages/identitiessettingspage.h
src/qtui/settingspages/identitiessettingspage.ui
src/qtui/settingspages/saveidentitiesdlg.ui [new file with mode: 0644]
src/qtui/settingspages/settingspages.pri
src/uisupport/settingspage.cpp
src/uisupport/settingspage.h

index 7ab1c81..9f4e17e 100644 (file)
@@ -70,6 +70,8 @@ src/common/settings.cpp
 src/common/settings.h
 src/common/signalproxy.cpp
 src/common/signalproxy.h
+src/common/syncableobject.cpp
+src/common/syncableobject.h
 src/common/types.h
 src/common/util.cpp
 src/common/util.h
@@ -91,8 +93,6 @@ src/core/ircserverhandler.cpp
 src/core/ircserverhandler.h
 src/core/server.cpp
 src/core/server.h
-src/core/sessionsettings.cpp
-src/core/sessionsettings.h
 src/core/sqlitestorage.cpp
 src/core/sqlitestorage.h
 src/core/storage.cpp
@@ -172,8 +172,15 @@ src/qtui/settingsdlg.h
 src/qtui/settingspages
 src/qtui/settingspages.cpp
 src/qtui/settingspages.h
+src/qtui/settingspages/createidentitydlg.ui
+src/qtui/settingspages/fontssettingspage.cpp
+src/qtui/settingspages/fontssettingspage.h
+src/qtui/settingspages/fontssettingspage.ui
 src/qtui/settingspages/identitiessettingspage.cpp
 src/qtui/settingspages/identitiessettingspage.h
+src/qtui/settingspages/identitiessettingspage.ui
+src/qtui/settingspages/networkssettingspage.ui
+src/qtui/settingspages/servereditdlg.ui
 src/qtui/settingspages/settingspages.pri
 src/qtui/topicwidget.cpp
 src/qtui/topicwidget.h
index f77ab6c..1b6e0bb 100644 (file)
@@ -321,7 +321,7 @@ void Client::coreSocketDisconnected() {
   /* Clear internal data. Hopefully nothing relies on it at this point. */
   _networkModel->clear();
 
-  QHash<uint, Buffer *>::iterator bufferIter =  _buffers.begin();
+  QHash<BufferId, Buffer *>::iterator bufferIter =  _buffers.begin();
   while(bufferIter != _buffers.end()) {
     Buffer *buffer = bufferIter.value();
     disconnect(buffer, SIGNAL(destroyed()), this, 0);
@@ -331,7 +331,7 @@ void Client::coreSocketDisconnected() {
   Q_ASSERT(_buffers.isEmpty());
 
 
-  QHash<uint, NetworkInfo*>::iterator netIter = _networkInfo.begin();
+  QHash<NetworkId, NetworkInfo*>::iterator netIter = _networkInfo.begin();
   while(netIter != _networkInfo.end()) {
     NetworkInfo *net = netIter.value();
     disconnect(net, SIGNAL(destroyed()), this, 0);
@@ -340,6 +340,15 @@ void Client::coreSocketDisconnected() {
   }
   Q_ASSERT(_networkInfo.isEmpty());
 
+  QHash<IdentityId, Identity*>::iterator idIter = _identities.begin();
+  while(idIter != _identities.end()) {
+    Identity *id = idIter.value();
+    emit identityRemoved(id->id());
+    idIter = _identities.erase(idIter);
+    id->deleteLater();
+  }
+  Q_ASSERT(_identities.isEmpty());
+
   coreConnectionInfo.clear();
   sessionData.clear();
   layoutQueue.clear();
@@ -370,10 +379,11 @@ void Client::syncToCore(const QVariant &coreState) {
 
   // 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();
+    coreIdentityCreated(vid.value<Identity>());
+    //Identity *id = new Identity(vid.value<Identity>(), this);
+    //_identities[id->id()] = id;
+    //signalProxy()->synchronize(id);
+    //qDebug() << "received identity" << id->identityName();
   }
 
   // store Buffer details
index bd25ccd..dadbb91 100644 (file)
@@ -28,7 +28,6 @@
 // Enable some shortcuts and stuff
 //#define DEVELMODE
 
-
 /** The protocol version we use fo the communication between core and GUI */
 #define GUI_PROTOCOL 4
 
index b25b5eb..c2fdeaf 100644 (file)
@@ -34,8 +34,23 @@ Identity::Identity(const Identity &other, QObject *parent) : QObject(parent),
             _realName(other.realName()),
             _nicks(other.nicks()),
             _awayNick(other.awayNick()),
+            _awayNickEnabled(other.awayNickEnabled()),
             _awayReason(other.awayReason()),
-            _returnMessage(other.returnMessage()) {
+            _awayReasonEnabled(other.awayReasonEnabled()),
+            _returnMessage(other.returnMessage()),
+            _returnMessageEnabled(other.returnMessageEnabled()),
+            _autoAwayEnabled(other.autoAwayEnabled()),
+            _autoAwayTime(other.autoAwayTime()),
+            _autoAwayReason(other.autoAwayReason()),
+            _autoAwayReasonEnabled(other.autoAwayReasonEnabled()),
+            _autoReturnMessage(other.autoReturnMessage()),
+            _autoReturnMessageEnabled(other.autoReturnMessageEnabled()),
+            _ident(other.ident()),
+            _kickReason(other.kickReason()),
+            _partReason(other.partReason()),
+            _quitReason(other.quitReason())
+
+{
   init();
 }
 
@@ -51,9 +66,26 @@ void Identity::setToDefaults() {
   n << QString("quassel%1").arg(qrand() & 0xff); // FIXME provide more sensible default nicks
   setNicks(n);
   setAwayNick("");
+  setAwayNickEnabled(false);
   setAwayReason(tr("Gone fishing."));
+  setAwayReasonEnabled(true);
   setReturnMessage(tr("Brought fish."));
+  setReturnMessageEnabled(false);
+  setAutoAwayEnabled(false);
+  setAutoAwayTime(10);
+  setAutoAwayReason(tr("Not here. No, really. not here!"));
+  setAutoAwayReasonEnabled(false);
+  setAutoReturnMessage(tr("Back in action again!"));
+  setAutoReturnMessageEnabled(false);
+  setIdent("quassel");
+  setKickReason(tr("Kindergarten is elsewhere!"));
+  setPartReason(tr("http://quassel-irc.org - Chat comfortably. Anywhere."));
+  setQuitReason(tr("http://quassel-irc.org - Chat comfortably. Anywhere."));
+
+}
 
+bool Identity::isValid() const {
+  return (id() > 0);
 }
 
 bool Identity::initialized() const {
@@ -84,15 +116,73 @@ QString Identity::awayNick() const {
   return _awayNick;
 }
 
+bool Identity::awayNickEnabled() const {
+  return _awayNickEnabled;
+}
+
 QString Identity::awayReason() const {
   return _awayReason;
 }
 
+bool Identity::awayReasonEnabled() const {
+  return _awayReasonEnabled;
+}
+
 QString Identity::returnMessage() const {
   return _returnMessage;
 }
 
-//////////////////////
+bool Identity::returnMessageEnabled() const {
+  return _returnMessageEnabled;
+}
+
+bool Identity::autoAwayEnabled() const {
+  return _autoAwayEnabled;
+}
+
+int Identity::autoAwayTime() const {
+  return _autoAwayTime;
+}
+
+QString Identity::autoAwayReason() const {
+  return _autoAwayReason;
+}
+
+bool Identity::autoAwayReasonEnabled() const {
+  return _autoAwayReasonEnabled;
+}
+
+QString Identity::autoReturnMessage() const {
+  return _autoReturnMessage;
+}
+
+bool Identity::autoReturnMessageEnabled() const {
+  return _autoReturnMessageEnabled;
+}
+
+QString Identity::ident() const {
+  return _ident;
+}
+
+QString Identity::kickReason() const {
+  return _kickReason;
+}
+
+QString Identity::partReason() const
+{return _partReason;}
+
+QString Identity::quitReason() const {
+  return _quitReason;
+}
+
+/*** setters ***/
+
+// NOTE: DO NOT USE ON SYNCHRONIZED OBJECTS!
+void Identity::setId(IdentityId _id) {
+  _identityId = _id;
+  setObjectName(QString::number(id()));
+  //emit idSet(id);
+}
 
 void Identity::setIdentityName(const QString &identityName) {
   _identityName = identityName;
@@ -124,15 +214,102 @@ void Identity::setReturnMessage(const QString &message) {
   emit returnMessageSet(message);
 }
 
+void Identity::setAwayNickEnabled(bool enabled) {
+  _awayNickEnabled = enabled;
+  emit awayNickEnabledSet(enabled);
+}
+
+void Identity::setAwayReasonEnabled(bool enabled) {
+  _awayReasonEnabled = enabled;
+  emit awayReasonEnabledSet(enabled);
+}
+
+void Identity::setReturnMessageEnabled(bool enabled) {
+  _returnMessageEnabled = enabled;
+  emit returnMessageEnabledSet(enabled);
+}
+
+void Identity::setAutoAwayEnabled(bool enabled) {
+  _autoAwayEnabled = enabled;
+  emit autoAwayEnabledSet(enabled);
+}
+
+void Identity::setAutoAwayTime(int time) {
+  _autoAwayTime = time;
+  emit autoAwayTimeSet(time);
+}
+
+void Identity::setAutoAwayReason(const QString & reason) {
+  _autoAwayReason = reason;
+  emit autoAwayReasonSet(reason);
+}
+
+void Identity::setAutoAwayReasonEnabled(bool enabled) {
+  _autoAwayReasonEnabled = enabled;
+  emit autoAwayReasonEnabledSet(enabled);
+}
+
+void Identity::setAutoReturnMessage(const QString & message) {
+  _autoReturnMessage = message;
+  emit autoReturnMessageSet(message);
+}
+
+void Identity::setAutoReturnMessageEnabled(bool enabled) {
+  _autoReturnMessageEnabled = enabled;
+  emit autoReturnMessageEnabledSet(enabled);
+}
+
+void Identity::setIdent(const QString & ident) {
+  _ident = ident;
+  emit identSet(ident);
+}
+
+void Identity::setKickReason(const QString & reason) {
+  _kickReason = reason;
+  emit kickReasonSet(reason);
+}
+
+void Identity::setPartReason(const QString & reason) {
+  _partReason = reason;
+  emit partReasonSet(reason);
+}
+
+void Identity::setQuitReason(const QString & reason) {
+  _quitReason = reason;
+  emit quitReasonSet(reason);
+}
+
+/***  ***/
+
 void Identity::update(const Identity &other) {
-  for(int idx = 0; idx < metaObject()->propertyCount(); idx++) {
-    QMetaProperty metaProp = metaObject()->property(metaObject()->propertyOffset() + idx);
+for(int idx = metaObject()->propertyOffset(); idx < metaObject()->propertyCount(); idx++) {
+    QMetaProperty metaProp = metaObject()->property(idx);
     Q_ASSERT(metaProp.isValid());
     if(this->property(metaProp.name()) != other.property(metaProp.name())) {
       setProperty(metaProp.name(), other.property(metaProp.name()));
     }
   }
 }
+#include <QDebug>
+bool Identity::operator==(const Identity &other) {
+  for(int idx = metaObject()->propertyOffset(); idx < metaObject()->propertyCount(); idx++) {
+    QMetaProperty metaProp = metaObject()->property(idx);
+    Q_ASSERT(metaProp.isValid());
+    QVariant v1 = this->property(metaProp.name());
+    QVariant v2 = other.property(metaProp.name()); //qDebug() << v1 << v2;
+    // QVariant cannot compare custom types, so we need to check for this case
+    if(QString(v1.typeName()) == "IdentityId") {
+      if(v1.value<IdentityId>() != v2.value<IdentityId>()) return false;
+    } else {
+      if(v1 != v2) return false;
+    }
+  }
+  return true;
+}
+
+bool Identity::operator!=(const Identity &other) {
+  return !(*this == other);
+}
 
 ///////////////////////////////
 
@@ -144,8 +321,21 @@ QDataStream &operator<<(QDataStream &out, const Identity &id) {
   i["RealName"] = id.realName();
   i["Nicks"] = id.nicks();
   i["AwayNick"] = id.awayNick();
+  i["AwayNickEnabled"] = id.awayNickEnabled();
   i["AwayReason"] = id.awayReason();
+  i["AwayReasonEnabled"] = id.awayReasonEnabled();
   i["ReturnMessage"] = id.returnMessage();
+  i["ReturnMessageEnabled"] = id.returnMessageEnabled();
+  i["AutoAwayEnabled"] = id.autoAwayEnabled();
+  i["AutoAwayTime"] = id.autoAwayTime();
+  i["AutoAwayReason"] = id.autoAwayReason();
+  i["AutoAwayReasonEnabled"] = id.autoAwayReasonEnabled();
+  i["AutoReturnMessage"] = id.autoReturnMessage();
+  i["AutoReturnMessageEnabled"] = id.autoReturnMessageEnabled();
+  i["Ident"] = id.ident();
+  i["KickReason"] = id.kickReason();
+  i["PartReason"] = id.partReason();
+  i["QuitReason"] = id.quitReason();
   out << i;
   return out;
 }
@@ -158,7 +348,21 @@ QDataStream &operator>>(QDataStream &in, Identity &id) {
   id.setRealName(i["RealName"].toString());
   id.setNicks(i["Nicks"].toStringList());
   id.setAwayNick(i["AwayNick"].toString());
+  id.setAwayNickEnabled(i["AwayNickEnabled"].toBool());
   id.setAwayReason(i["AwayReason"].toString());
+  id.setAwayReasonEnabled(i["AwayReasonEnabled"].toBool());
   id.setReturnMessage(i["ReturnMessage"].toString());
+  id.setReturnMessageEnabled(i["ReturnMessageEnabled"].toBool());
+  id.setAutoAwayEnabled(i["AutoAwayEnabled"].toBool());
+  id.setAutoAwayTime(i["AutoAwayTime"].toInt());
+  id.setAutoAwayReason(i["AutoAwayReason"].toString());
+  id.setAutoAwayReasonEnabled(i["AutoAwayReasonEnabled"].toBool());
+  id.setAutoReturnMessage(i["AutoReturnMessage"].toString());
+  id.setAutoReturnMessageEnabled(i["AutoReturnMessageEnabled"].toBool());
+  id.setIdent(i["Ident"].toString());
+  id.setKickReason(i["KickReason"].toString());
+  id.setPartReason(i["PartReason"].toString());
+  id.setQuitReason(i["QuitReason"].toString());
   return in;
 }
+
index 66d7153..3db8a28 100644 (file)
 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(
+  Q_PROPERTY(IdentityId identityId READ id WRITE setId 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(bool awayNickEnabled READ awayNickEnabled WRITE setAwayNickEnabled STORED false);
+  Q_PROPERTY(QString awayReason READ awayReason WRITE setAwayReason STORED false);
+  Q_PROPERTY(bool awayReasonEnabled READ awayReasonEnabled WRITE setAwayReasonEnabled STORED false);
+  Q_PROPERTY(QString returnMessage READ returnMessage WRITE setReturnMessage STORED false);
+  Q_PROPERTY(bool returnMessageEnabled READ returnMessageEnabled WRITE setReturnMessageEnabled STORED false);
+  Q_PROPERTY(bool autoAwayEnabled READ autoAwayEnabled WRITE setAutoAwayEnabled STORED false);
+  Q_PROPERTY(int autoAwayTime READ autoAwayTime WRITE setAutoAwayTime STORED false);
+  Q_PROPERTY(QString autoAwayReason READ autoAwayReason WRITE setAutoAwayReason STORED false);
+  Q_PROPERTY(bool autoAwayReasonEnabled READ autoAwayReasonEnabled WRITE setAutoAwayReasonEnabled STORED false);
+  Q_PROPERTY(QString autoReturnMessage READ autoReturnMessage WRITE setAutoReturnMessage STORED false);
+  Q_PROPERTY(bool autoReturnMessageEnabled READ autoReturnMessageEnabled WRITE setAutoReturnMessageEnabled STORED false);
+  Q_PROPERTY(QString ident READ ident WRITE setIdent STORED false);
+  Q_PROPERTY(QString kickReason READ kickReason WRITE setKickReason STORED false);
+  Q_PROPERTY(QString partReason READ partReason WRITE setPartReason STORED false);
+  Q_PROPERTY(QString quitReason READ quitReason WRITE setQuitReason STORED false);
 
   public:
-    Identity(IdentityId id = -1, QObject *parent = 0);
+    Identity(IdentityId id = 0, QObject *parent = 0);
     Identity(const Identity &other, QObject *parent = 0);
     void setToDefaults();
 
+    bool operator==(const Identity &other);
+    bool operator!=(const Identity &other);
+
+    bool isValid() const;
+
     IdentityId id() const;
     QString identityName() const;
     QString realName() const;
     QStringList nicks() const;
     QString awayNick() const;
+    bool awayNickEnabled() const;
     QString awayReason() const;
+    bool awayReasonEnabled() const;
     QString returnMessage() const;
+    bool returnMessageEnabled() const;
+    bool autoAwayEnabled() const;
+    int autoAwayTime() const;
+    QString autoAwayReason() const;
+    bool autoAwayReasonEnabled() const;
+    QString autoReturnMessage() const;
+    bool autoReturnMessageEnabled() const;
+    QString ident() const;
+    QString kickReason() const;
+    QString partReason() const;
+    QString quitReason() const;
 
     bool initialized() const;
     void setInitialized();
 
   public slots:
+    void setId(IdentityId id);
     void setIdentityName(const QString &name);
     void setRealName(const QString &realName);
     void setNicks(const QStringList &nicks);
     void setAwayNick(const QString &awayNick);
+    void setAwayNickEnabled(bool enabled);
     void setAwayReason(const QString &awayReason);
+    void setAwayReasonEnabled(bool enabled);
     void setReturnMessage(const QString &returnMessage);
+    void setReturnMessageEnabled(bool enabled);
+    void setAutoAwayEnabled(bool enabled);
+    void setAutoAwayTime(int time);
+    void setAutoAwayReason(const QString &reason);
+    void setAutoAwayReasonEnabled(bool enabled);
+    void setAutoReturnMessage(const QString &message);
+    void setAutoReturnMessageEnabled(bool enabled);
+    void setIdent(const QString &ident);
+    void setKickReason(const QString &reason);
+    void setPartReason(const QString &reason);
+    void setQuitReason(const QString &reason);
 
     void update(const Identity &other);
 
   signals:
+    void idSet(IdentityId id);
     void identityNameSet(const QString &name);
     void realNameSet(const QString &realName);
     void nicksSet(const QStringList &nicks);
     void awayNickSet(const QString &awayNick);
+    void awayNickEnabledSet(bool);
     void awayReasonSet(const QString &awayReason);
+    void awayReasonEnabledSet(bool);
     void returnMessageSet(const QString &returnMessage);
+    void returnMessageEnabledSet(bool);
+    void autoAwayEnabledSet(bool);
+    void autoAwayTimeSet(int);
+    void autoAwayReasonSet(const QString &);
+    void autoAwayReasonEnabledSet(bool);
+    void autoReturnMessageSet(const QString &);
+    void autoReturnMessageEnabledSet(bool);
+    void identSet(const QString &);
+    void kickReasonSet(const QString &);
+    void partReasonSet(const QString &);
+    void quitReasonSet(const QString &);
 
     void updatedRemotely();
 
@@ -81,7 +139,19 @@ class Identity : public QObject {
     IdentityId _identityId;
     QString _identityName, _realName;
     QStringList _nicks;
-    QString  _awayNick, _awayReason, _returnMessage;
+    QString _awayNick;
+    bool _awayNickEnabled;
+    QString _awayReason;
+    bool _awayReasonEnabled;
+    QString _returnMessage;
+    bool _returnMessageEnabled;
+    bool _autoAwayEnabled;
+    int _autoAwayTime;
+    QString _autoAwayReason;
+    bool _autoAwayReasonEnabled;
+    QString _autoReturnMessage;
+    bool _autoReturnMessageEnabled;
+    QString _ident, _kickReason, _partReason, _quitReason;
 
     void init();
 
index 5251acd..7fa59aa 100644 (file)
@@ -22,6 +22,7 @@
 #include "identity.h"
 #include "settings.h"
 #include <QString>
+#include <QTimer>
 #include <QTranslator>
 
 #if defined BUILD_CORE
@@ -106,7 +107,9 @@ int main(int argc, char **argv) {
 #ifndef BUILD_CORE
   QtUi *gui = new QtUi();
   Client::init(gui);
-  gui->init();
+  // init gui only after the event loop has started
+  QTimer::singleShot(0, gui, SLOT(init()));
+  //gui->init();
 #endif
 
 #ifndef BUILD_QTUI
index 5393cff..03861d3 100644 (file)
@@ -253,6 +253,7 @@ void SignalProxy::removePeerBySender() {
   // OK we're brutal here... but since it's a private slot we know what we've got connected to it...
   QIODevice *ioDev = (QIODevice *)(sender());
   removePeer(ioDev);
+  qDebug() << "Client disconnected.";
 }
 
 void SignalProxy::objectRenamed(QString oldname, QString newname) {
index 05fdf2c..b0dd0d1 100644 (file)
@@ -28,7 +28,8 @@ 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.
+// IdentityId must be signed!
+typedef qint32 IdentityId; //!< Identifies an identity.
 
 //! Base class for exceptions.
 struct Exception {
index cffb375..cd75f66 100644 (file)
@@ -46,30 +46,27 @@ CoreSession::CoreSession(UserId uid, Storage *_storage, QObject *parent)
 
   CoreUserSettings s(user);
   sessionData = s.sessionData();
-/*
-  CoreSettings cs;
-  foreach(QString id, cs.localChildKeys(QString("Identities/%1").arg(user))) {
-    Identity *i = new Identity(cs.localValue(QString("Identities/%1/%2").arg(user).arg(id)).value<Identity>(), this);
-    if(i->id() < 1) {
+#ifdef SPUTDEV
+  foreach(IdentityId id, s.identityIds()) {
+    Identity *i = new Identity(s.identity(id), this);
+    if(!i->isValid()) {
       qDebug() << QString("Invalid identity!");
+      delete i;
       continue;
     }
     if(_identities.contains(i->id())) {
       qDebug() << "Duplicate identity, ignoring!";
+      delete i;
       continue;
     }
-    qDebug() << "loaded identity" << id;
     _identities[i->id()] = i;
   }
-  s.endGroup();
-  mutex.unlock();
   if(!_identities.count()) {
     Identity i(1);
     i.setToDefaults();
-    //_identities[i->id()] = i;
-    createOrUpdateIdentity(i);
+    createIdentity(i);
   }
-  */
+#endif
 
   p->attachSlot(SIGNAL(requestNetworkStates()), this, SLOT(serverStateRequested()));
   p->attachSlot(SIGNAL(requestConnect(QString)), this, SLOT(connectToNetwork(QString)));
@@ -85,8 +82,8 @@ CoreSession::CoreSession(UserId uid, Storage *_storage, QObject *parent)
 
   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(createIdentity(const Identity &)), this, SLOT(createIdentity(const Identity &)));
+  p->attachSlot(SIGNAL(updateIdentity(const Identity &)), this, SLOT(updateIdentity(const Identity &)));
   p->attachSlot(SIGNAL(removeIdentity(IdentityId)), this, SLOT(removeIdentity(IdentityId)));
 
   initScriptEngine();
@@ -300,27 +297,39 @@ void CoreSession::scriptRequest(QString script) {
   emit scriptResult(scriptEngine->evaluate(script).toString());
 }
 
-void CoreSession::createOrUpdateIdentity(const Identity &id) {
+void CoreSession::createIdentity(const Identity &id) {
+  // find free ID
+  int i;
+  for(i = 1; i <= _identities.count(); i++) {
+    if(!_identities.keys().contains(i)) break;
+  }
+  //qDebug() << "found free id" << i;
+  Identity *newId = new Identity(id, this);
+  newId->setId(i);
+  _identities[i] = newId;
+  signalProxy()->synchronize(newId);
+  CoreUserSettings s(user);
+  s.storeIdentity(*newId);
+  emit identityCreated(i);
+}
+
+void CoreSession::updateIdentity(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);
+    qWarning() << "Update request for unknown identity received!";
+    return;
   }
-/*
-  CoreSettings s;
-  s.beginGroup(QString("Identities/%1").arg(user));
-  s.setValue(QString::number(id.id()), QVariant::fromValue<Identity>(*_identities[id.id()]));
-  s.endGroup();*/
+  _identities[id.id()]->update(id);
+
+  CoreUserSettings s(user);
+  s.storeIdentity(id);
 }
 
 void CoreSession::removeIdentity(IdentityId id) {
   Identity *i = _identities.take(id);
   if(i) {
     emit identityRemoved(id);
+    CoreUserSettings s(user);
+    s.removeIdentity(id);
     i->deleteLater();
   }
 }
index 32e34ec..2f45701 100644 (file)
@@ -72,10 +72,15 @@ 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.
+  //! Create an identity and propagate the changes to the clients.
+  /** \param identity The identity to be created.
    */
-  void createOrUpdateIdentity(const Identity &identity);
+  void createIdentity(const Identity &identity);
+
+  //! Update an identity and propagate the changes to the clients.
+  /** \param identity The identity to be updated.
+   */
+  void updateIdentity(const Identity &identity);
 
   //! Remove identity and propagate that fact to the clients.
   /** \param identity The identity to be removed.
index 551a971..0e204d1 100644 (file)
@@ -41,4 +41,4 @@ class CoreSettings : public Settings {
 
 };
 
-#endif /*CORESETTINGS_H_*/
+#endif /*_CORESETTINGS_H_*/
index 49a9837..277b7ad 100644 (file)
@@ -25,8 +25,29 @@ CoreUserSettings::CoreUserSettings(UserId uid) : CoreSettings(QString("CoreUser/
 
 }
 
+void CoreUserSettings::storeIdentity(const Identity &identity) {
+  setLocalValue(QString("Identities/%1").arg(identity.id()), QVariant::fromValue<Identity>(identity));
+}
+
+void CoreUserSettings::removeIdentity(const Identity &identity) {
+  removeLocalKey(QString("Identities/%1").arg(identity.id()));
+}
 
+Identity CoreUserSettings::identity(IdentityId id) {
+  QVariant v = localValue(QString("Identities/%1").arg(id));
+  if(qVariantCanConvert<Identity>(v)) {
+    return v.value<Identity>();
+  }
+  return Identity();
+}
 
+QList<IdentityId> CoreUserSettings::identityIds() {
+  QList<IdentityId> res;
+  foreach(QString id, localChildKeys("Identities")) {
+    res << id.toUInt();
+  }
+  return res;
+}
 
 QVariantMap CoreUserSettings::sessionData() {
   QVariantMap res;
index 4a8621d..eee2e57 100644 (file)
@@ -32,9 +32,11 @@ class CoreUserSettings : public CoreSettings {
   public:
     CoreUserSettings(UserId user);
 
-    void setIdentity(const Identity &identity);
-    Identity identity(IdentityId id);
+    void storeIdentity(const Identity &identity);
+    void removeIdentity(const Identity &identity);
 
+    Identity identity(IdentityId id);
+    QList<IdentityId> identityIds();
 
   private:
     // this stuff should only be accessed by CoreSession!
index 672938d..d7c3bba 100644 (file)
@@ -123,7 +123,9 @@ void MainWin::init() {
 
   ui.menuViews->addAction(dock->toggleViewAction());
 
-  //showSettingsDlg();
+#ifdef SPUTDEV
+  showSettingsDlg();
+#endif
 
 }
 
@@ -180,7 +182,7 @@ void MainWin::addBufferView(const QString &viewname, QAbstractItemModel *model,
   view->setFilteredModel(model, mode, nets);
   Client::networkModel()->synchronizeView(view);
   dock->setWidget(view);
-  
+
   addDockWidget(Qt::LeftDockWidgetArea, dock);
   ui.menuViews->addAction(dock->toggleViewAction());
 
@@ -189,8 +191,9 @@ void MainWin::addBufferView(const QString &viewname, QAbstractItemModel *model,
 
 void MainWin::setupSettingsDlg() {
   settingsDlg->registerSettingsPage(new FontsSettingsPage(settingsDlg));
+#ifdef SPUTDEV
   settingsDlg->registerSettingsPage(new IdentitiesSettingsPage(settingsDlg));
-
+#endif
 }
 
 void MainWin::connectedToCore() {
index 93e9457..f6f1db5 100644 (file)
@@ -36,11 +36,14 @@ class QtUi : public AbstractUi {
   public:
     QtUi();
     ~QtUi();
-    void init();
+    //void init();
     AbstractUiMsg *layoutMsg(const Message &);
 
     static QtUiStyle *style();
 
+  public slots:
+    void init();
+
   protected slots:
     void connectedToCore();
     void disconnectedFromCore();
index 66a646b..6c7d24a 100644 (file)
@@ -22,6 +22,7 @@
 
 SettingsDlg::SettingsDlg(QWidget *parent) : QDialog(parent) {
   ui.setupUi(this);
+  _currentPage = 0;
 
   //ui.settingsFrame->setWidgetResizable(true);
   //ui.settingsFrame->setWidget(ui.settingsStack);
@@ -31,10 +32,14 @@ SettingsDlg::SettingsDlg(QWidget *parent) : QDialog(parent) {
   connect(ui.buttonBox, SIGNAL(clicked(QAbstractButton *)), this, SLOT(buttonClicked(QAbstractButton *)));
 }
 
+SettingsPage *SettingsDlg::currentPage() const {
+  return _currentPage;
+}
 
 void SettingsDlg::registerSettingsPage(SettingsPage *sp) {
   sp->setParent(ui.settingsStack);
   ui.settingsStack->addWidget(sp);
+  connect(sp, SIGNAL(changed(bool)), this, SLOT(setButtonStates()));
 
   QTreeWidgetItem *cat;
   QList<QTreeWidgetItem *> cats = ui.settingsTree->findItems(sp->category(), Qt::MatchExactly);
@@ -51,12 +56,17 @@ void SettingsDlg::registerSettingsPage(SettingsPage *sp) {
 }
 
 void SettingsDlg::selectPage(const QString &cat, const QString &title) {
-  QWidget *w = pages[QString("%1$%2").arg(cat, title)];
-  Q_ASSERT(w);
-  ui.settingsStack->setCurrentWidget(w);
+  SettingsPage *sp = pages[QString("%1$%2").arg(cat, title)];
+  Q_ASSERT(sp); // FIXME allow for invalid settings pages
+  ui.settingsStack->setCurrentWidget(sp);
+  _currentPage = sp;
+  setButtonStates();
 }
 
 void SettingsDlg::itemSelected() {
+  // Check if we have changed anything...
+  // TODO
+
   QList<QTreeWidgetItem *> items = ui.settingsTree->selectedItems();
   if(!items.count()) {
     return;
@@ -70,11 +80,17 @@ void SettingsDlg::itemSelected() {
   }
 }
 
+void SettingsDlg::setButtonStates() {
+  SettingsPage *sp = currentPage();
+  ui.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(sp && sp->hasChanged());
+  ui.buttonBox->button(QDialogButtonBox::Apply)->setEnabled(sp && sp->hasChanged());
+  ui.buttonBox->button(QDialogButtonBox::Reset)->setEnabled(sp && sp->hasChanged());
+}
+
 void SettingsDlg::buttonClicked(QAbstractButton *button) {
   switch(ui.buttonBox->standardButton(button)) {
     case QDialogButtonBox::Ok:
-      applyChanges();
-      accept();
+      if(applyChanges()) accept();
       break;
     case QDialogButtonBox::Apply:
       applyChanges();
@@ -93,12 +109,16 @@ void SettingsDlg::buttonClicked(QAbstractButton *button) {
   }
 }
 
-void SettingsDlg::applyChanges() {
-  foreach(SettingsPage *page, pages.values()) {
-    page->save();
+bool SettingsDlg::applyChanges() {
+  if(!currentPage()) return false;
+  if(currentPage()->aboutToSave()) {
+    currentPage()->save();
+    return true;
   }
+  return false;
 }
 
+// TODO add messagebox
 void SettingsDlg::reload() {
   SettingsPage *page = qobject_cast<SettingsPage *>(ui.settingsStack->currentWidget());
   if(page) page->load();
index d3cc96d..ca15811 100644 (file)
@@ -33,19 +33,23 @@ class SettingsDlg : public QDialog {
     void registerSettingsPage(SettingsPage *);
     void unregisterSettingsPage(SettingsPage *);
 
+    SettingsPage *currentPage() const;
+
   public slots:
     void selectPage(const QString &category, const QString &title);
 
   private slots:
     void itemSelected();
     void buttonClicked(QAbstractButton *);
-    void applyChanges();
+    bool applyChanges();
     void reload();
     void loadDefaults();
+    void setButtonStates();
 
   private:
     Ui::SettingsDlg ui;
 
+    SettingsPage *_currentPage;
     QHash<QString, SettingsPage *> pages;
 };
 
diff --git a/src/qtui/settingspages/createidentitydlg.ui b/src/qtui/settingspages/createidentitydlg.ui
new file mode 100644 (file)
index 0000000..522f09f
--- /dev/null
@@ -0,0 +1,143 @@
+<ui version="4.0" >
+ <class>CreateIdentityDlg</class>
+ <widget class="QDialog" name="CreateIdentityDlg" >
+  <property name="windowModality" >
+   <enum>Qt::WindowModal</enum>
+  </property>
+  <property name="geometry" >
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>399</width>
+    <height>135</height>
+   </rect>
+  </property>
+  <property name="windowTitle" >
+   <string>Create New Identity</string>
+  </property>
+  <layout class="QVBoxLayout" >
+   <item>
+    <layout class="QHBoxLayout" >
+     <item>
+      <widget class="QLabel" name="label" >
+       <property name="text" >
+        <string>Identity name:</string>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QLineEdit" name="identityName" />
+     </item>
+    </layout>
+   </item>
+   <item>
+    <widget class="QRadioButton" name="createBlankIdentity" >
+     <property name="text" >
+      <string>Create blank identity</string>
+     </property>
+     <property name="checked" >
+      <bool>true</bool>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <layout class="QHBoxLayout" >
+     <item>
+      <widget class="QRadioButton" name="duplicateIdentity" >
+       <property name="text" >
+        <string>Duplicate:</string>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QComboBox" name="identityList" >
+       <property name="enabled" >
+        <bool>false</bool>
+       </property>
+       <property name="sizePolicy" >
+        <sizepolicy vsizetype="Fixed" hsizetype="Expanding" >
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+      </widget>
+     </item>
+    </layout>
+   </item>
+   <item>
+    <spacer>
+     <property name="orientation" >
+      <enum>Qt::Vertical</enum>
+     </property>
+     <property name="sizeHint" >
+      <size>
+       <width>20</width>
+       <height>40</height>
+      </size>
+     </property>
+    </spacer>
+   </item>
+   <item>
+    <widget class="QDialogButtonBox" name="buttonBox" >
+     <property name="orientation" >
+      <enum>Qt::Horizontal</enum>
+     </property>
+     <property name="standardButtons" >
+      <set>QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok</set>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>accepted()</signal>
+   <receiver>CreateIdentityDlg</receiver>
+   <slot>accept()</slot>
+   <hints>
+    <hint type="sourcelabel" >
+     <x>222</x>
+     <y>127</y>
+    </hint>
+    <hint type="destinationlabel" >
+     <x>157</x>
+     <y>134</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>rejected()</signal>
+   <receiver>CreateIdentityDlg</receiver>
+   <slot>reject()</slot>
+   <hints>
+    <hint type="sourcelabel" >
+     <x>290</x>
+     <y>127</y>
+    </hint>
+    <hint type="destinationlabel" >
+     <x>286</x>
+     <y>134</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>duplicateIdentity</sender>
+   <signal>toggled(bool)</signal>
+   <receiver>identityList</receiver>
+   <slot>setEnabled(bool)</slot>
+   <hints>
+    <hint type="sourcelabel" >
+     <x>55</x>
+     <y>80</y>
+    </hint>
+    <hint type="destinationlabel" >
+     <x>166</x>
+     <y>84</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+</ui>
index 49796b0..2817b84 100644 (file)
@@ -18,6 +18,8 @@
  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
  ***************************************************************************/
 
+#include <QMessageBox>
+
 #include "identitiessettingspage.h"
 
 #include "client.h"
@@ -28,28 +30,358 @@ IdentitiesSettingsPage::IdentitiesSettingsPage(QWidget *parent)
   ui.setupUi(this);
   setEnabled(false);  // need a core connection!
   connect(Client::instance(), SIGNAL(coreConnectionStateChanged(bool)), this, SLOT(coreConnectionStateChanged(bool)));
+  connect(Client::instance(), SIGNAL(identityCreated(IdentityId)), this, SLOT(clientIdentityCreated(IdentityId)));
+  connect(Client::instance(), SIGNAL(identityRemoved(IdentityId)), this, SLOT(clientIdentityRemoved(IdentityId)));
+
+  currentId = 0;
+
+  // We need to know whenever the state of input widgets changes...
+  //connect(ui.identityList, SIGNAL(editTextChanged(const QString &)), this, SLOT(widgetHasChanged()));
+  connect(ui.realName, SIGNAL(textEdited(const QString &)), this, SLOT(widgetHasChanged()));
+  connect(ui.nicknameList, SIGNAL(itemChanged(QListWidgetItem *)), this, SLOT(widgetHasChanged()));
+  connect(ui.awayNick, SIGNAL(textEdited(const QString &)), this, SLOT(widgetHasChanged()));
+  connect(ui.awayNickEnabled, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged()));
+  connect(ui.awayReason, SIGNAL(textEdited(const QString &)), this, SLOT(widgetHasChanged()));
+  connect(ui.awayReasonEnabled, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged()));
+  connect(ui.returnMessage, SIGNAL(textEdited(const QString &)), this, SLOT(widgetHasChanged()));
+  connect(ui.returnMessageEnabled, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged()));
+  connect(ui.autoAwayEnabled, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged()));
+  connect(ui.autoAwayTime, SIGNAL(valueChanged(int)), this, SLOT(widgetHasChanged()));
+  connect(ui.autoAwayReason, SIGNAL(textEdited(const QString &)), this, SLOT(widgetHasChanged()));
+  connect(ui.autoAwayReasonEnabled, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged()));
+  connect(ui.autoReturnMessage, SIGNAL(textEdited(const QString &)), this, SLOT(widgetHasChanged()));
+  connect(ui.autoReturnMessageEnabled, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged()));
+  connect(ui.ident, SIGNAL(textEdited(const QString &)), this, SLOT(widgetHasChanged()));
+  connect(ui.kickReason, SIGNAL(textEdited(const QString &)), this, SLOT(widgetHasChanged()));
+  connect(ui.partReason, SIGNAL(textEdited(const QString &)), this, SLOT(widgetHasChanged()));
+  connect(ui.quitReason, SIGNAL(textEdited(const QString &)), this, SLOT(widgetHasChanged()));
 
 }
 
 void IdentitiesSettingsPage::coreConnectionStateChanged(bool state) {
-  //this->setEnabled(state);
+  this->setEnabled(state);
   if(state) {
     load();
+  } else {
+    // reset
+    currentId = 0;
   }
 }
 
-bool IdentitiesSettingsPage::hasChanged() const {
-  return true;
-}
-
 void IdentitiesSettingsPage::save() {
+  setEnabled(false);
+  QList<Identity *> toCreate, toUpdate;
+  // we need to remove our temporarily created identities.
+  // these are going to be re-added after the core has propagated them back...
+  for(QHash<IdentityId, Identity *>::iterator i = identities.begin(); i != identities.end(); ++i) {
+    if((*i)->id() < 0) {
+      Identity *temp = *i;
+      i = identities.erase(i);
+      toCreate.append(temp);
+      ui.identityList->removeItem(ui.identityList->findData(temp->id()));
+    } else {
+      if(**i != *Client::identity((*i)->id())) {
+        toUpdate.append(*i);
+      }
+    }
+  }
+  SaveIdentitiesDlg dlg(toCreate, toUpdate, deletedIdentities, this);
+  int ret = dlg.exec();
+  if(ret == QDialog::Rejected) {
+    // canceled -> reload everything to be safe
+    load();
+  }
+  foreach(Identity *id, toCreate) {
+    id->deleteLater();
+  }
+  changeState(false);
+  setEnabled(true);
 
 }
 
 void IdentitiesSettingsPage::load() {
-
+  currentId = 0;
+  foreach(Identity *identity, identities.values()) {
+    identity->deleteLater();
+  }
+  identities.clear();
+  deletedIdentities.clear();
+  changedIdentities.clear();
+  ui.identityList->clear();
+  foreach(IdentityId id, Client::identityIds()) {
+    clientIdentityCreated(id);
+  }
+  changeState(false);
 }
 
 void IdentitiesSettingsPage::defaults() {
+  // TODO implement bool hasDefaults()
+}
+
+void IdentitiesSettingsPage::widgetHasChanged() {
+  bool changed = testHasChanged();
+  if(changed != hasChanged()) changeState(changed);
+}
+
+bool IdentitiesSettingsPage::testHasChanged() {
+  if(deletedIdentities.count()) return true;
+  if(currentId < 0) {
+    return true; // new identity
+  } else {
+    changedIdentities.removeAll(currentId);
+    Identity temp(currentId, this);
+    saveToIdentity(&temp);
+    if(temp != *identities[currentId]) changedIdentities.append(currentId);
+    return changedIdentities.count();
+  }
+}
+
+bool IdentitiesSettingsPage::aboutToSave() {
+  saveToIdentity(identities[currentId]);
+  QList<int> errors;
+  foreach(Identity *id, identities.values()) {
+    if(id->identityName().isEmpty()) errors.append(1);
+    if(!id->nicks().count()) errors.append(2);
+    if(id->realName().isEmpty()) errors.append(3);
+    if(id->ident().isEmpty()) errors.append(4);
+  }
+  if(!errors.count()) return true;
+  QString error(tr("<b>The following problems need to be corrected before your changes can be applied:</b><ul>"));
+  if(errors.contains(1)) error += tr("<li>All identities need an identity name set</li>");
+  if(errors.contains(2)) error += tr("<li>Every identity needs at least one nickname defined</li>");
+  if(errors.contains(3)) error += tr("<li>You need to specify a real name for every identity</li>");
+  if(errors.contains(4)) error += tr("<li>You need to specify an ident for every identity</li>");
+  error += tr("</ul>");
+  QMessageBox::warning(this, tr("One or more identities are invalid"), error);
+  return false;
+}
+
+void IdentitiesSettingsPage::clientIdentityCreated(IdentityId id) {
+  insertIdentity(new Identity(*Client::identity(id), this));
+  connect(Client::identity(id), SIGNAL(updatedRemotely()), this, SLOT(clientIdentityUpdated()));
+}
+
+void IdentitiesSettingsPage::clientIdentityUpdated() {
+  Identity *identity = qobject_cast<Identity *>(sender());
+  if(!identity) {
+    qWarning() << "Invalid identity to update!";
+    return;
+  }
+  if(!identities.contains(identity->id())) {
+    qWarning() << "Unknown identity to update:" << identity->identityName();
+    return;
+  }
+  identities[identity->id()]->update(*identity);
+  ui.identityList->setItemText(ui.identityList->findData(identity->id()), identity->identityName());
+  if(identity->id() == currentId) displayIdentity(identity, true);
+}
+
+void IdentitiesSettingsPage::clientIdentityRemoved(IdentityId id) {
+  if(identities.contains(id)) {
+    removeIdentity(identities[id]);
+    changedIdentities.removeAll(id);
+    deletedIdentities.removeAll(id);
+  }
+}
+
+void IdentitiesSettingsPage::insertIdentity(Identity *identity) {
+  IdentityId id = identity->id();
+  identities[id] = identity;
+  if(id == 1) {
+    // default identity is always the first one!
+    ui.identityList->insertItem(0, identity->identityName(), id);
+  } else {
+    QString name = identity->identityName();
+    for(int j = 0; j < ui.identityList->count(); j++) {
+      if((j>0 || ui.identityList->itemData(0).toInt() != 1) && name.localeAwareCompare(ui.identityList->itemText(j)) < 0) {
+        ui.identityList->insertItem(j, name, id);
+        widgetHasChanged();
+        return;
+      }
+    }
+    // append
+    ui.identityList->insertItem(ui.identityList->count(), name, id);
+    widgetHasChanged();
+  }
+}
+
+void IdentitiesSettingsPage::removeIdentity(Identity *id) {
+  ui.identityList->removeItem(ui.identityList->findData(id->id()));
+  identities.remove(id->id());
+  id->deleteLater();
+  widgetHasChanged();
+}
+
+void IdentitiesSettingsPage::on_identityList_currentIndexChanged(int index) {
+  if(index < 0) {
+    //ui.identityList->setEditable(false);
+    displayIdentity(0);
+  } else {
+    IdentityId id = ui.identityList->itemData(index).toInt();
+    if(identities.contains(id)) displayIdentity(identities[id]);
+    ui.deleteIdentity->setEnabled(id != 1); // default identity cannot be deleted
+    //ui.identityList->setEditable(id != 1);  // ...or renamed
+  }
+}
+
+void IdentitiesSettingsPage::displayIdentity(Identity *id, bool dontsave) {
+  if(currentId != 0 && !dontsave && identities.contains(currentId)) {
+    saveToIdentity(identities[currentId]);
+  }
+  if(id) {
+    currentId = id->id();
+    ui.realName->setText(id->realName());
+    ui.nicknameList->clear();
+    ui.nicknameList->addItems(id->nicks());
+    //for(int i = 0; i < ui.nicknameList->count(); i++) {
+    //  ui.nicknameList->item(i)->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEditable|Qt::ItemIsEnabled);
+    //}
+    if(ui.nicknameList->count()) ui.nicknameList->setCurrentRow(0);
+    ui.awayNick->setText(id->awayNick());
+    ui.awayNickEnabled->setChecked(id->awayNickEnabled());
+    ui.awayReason->setText(id->awayReason());
+    ui.awayReasonEnabled->setChecked(id->awayReasonEnabled());
+    ui.returnMessage->setText(id->returnMessage());
+    ui.returnMessageEnabled->setChecked(id->returnMessageEnabled());
+    ui.autoAwayEnabled->setChecked(id->autoAwayEnabled());
+    ui.autoAwayTime->setValue(id->autoAwayTime());
+    ui.autoAwayReason->setText(id->autoAwayReason());
+    ui.autoAwayReasonEnabled->setChecked(id->autoAwayReasonEnabled());
+    ui.autoReturnMessage->setText(id->autoReturnMessage());
+    ui.autoReturnMessageEnabled->setChecked(id->autoReturnMessageEnabled());
+    ui.ident->setText(id->ident());
+    ui.kickReason->setText(id->kickReason());
+    ui.partReason->setText(id->partReason());
+    ui.quitReason->setText(id->quitReason());
+  }
+}
+
+void IdentitiesSettingsPage::saveToIdentity(Identity *id) {
+  id->setIdentityName(ui.identityList->currentText());
+  id->setRealName(ui.realName->text());
+  QStringList nicks;
+  for(int i = 0; i < ui.nicknameList->count(); i++) {
+    nicks << ui.nicknameList->item(i)->text();
+  }
+  id->setNicks(nicks);
+  id->setAwayNick(ui.awayNick->text());
+  id->setAwayNickEnabled(ui.awayNickEnabled->isChecked());
+  id->setAwayReason(ui.awayReason->text());
+  id->setAwayReasonEnabled(ui.awayReasonEnabled->isChecked());
+  id->setReturnMessage(ui.returnMessage->text());
+  id->setReturnMessageEnabled(ui.returnMessageEnabled->isChecked());
+  id->setAutoAwayEnabled(ui.autoAwayEnabled->isChecked());
+  id->setAutoAwayTime(ui.autoAwayTime->value());
+  id->setAutoAwayReason(ui.autoAwayReason->text());
+  id->setAutoAwayReasonEnabled(ui.autoAwayReasonEnabled->isChecked());
+  id->setAutoReturnMessage(ui.autoReturnMessage->text());
+  id->setAutoReturnMessageEnabled(ui.autoReturnMessageEnabled->isChecked());
+  id->setIdent(ui.ident->text());
+  id->setKickReason(ui.kickReason->text());
+  id->setPartReason(ui.partReason->text());
+  id->setQuitReason(ui.quitReason->text());
+}
+
+void IdentitiesSettingsPage::on_addIdentity_clicked() {
+  CreateIdentityDlg dlg(ui.identityList->model(), this);
+  if(dlg.exec() == QDialog::Accepted) {
+    // find a free (negative) ID
+    IdentityId id;
+    for(id = 1; id <= identities.count(); id++) {
+      if(!identities.keys().contains(-id)) break;
+    }
+    id *= -1;
+    Identity *newId = new Identity(id, this);
+    if(dlg.duplicateId() != 0) {
+      // duplicate
+      newId->update(*identities[dlg.duplicateId()]);
+      newId->setId(id);
+    }
+    newId->setIdentityName(dlg.identityName());
+    identities[id] = newId;
+    insertIdentity(newId);
+    ui.identityList->setCurrentIndex(ui.identityList->findData(id));
+    widgetHasChanged();
+  }
+}
+
+void IdentitiesSettingsPage::on_deleteIdentity_clicked() {
+  Identity *id = identities[currentId];
+  int ret = QMessageBox::question(this, tr("Delete Identity?"),
+                                  tr("Do you really want to delete identity \"%1\"?").arg(id->identityName()),
+                                  QMessageBox::Yes|QMessageBox::No, QMessageBox::No);
+  if(ret != QMessageBox::Yes) return;
+  if(id->id() > 0) deletedIdentities.append(id->id());
+  removeIdentity(id);
+}
+
+void IdentitiesSettingsPage::on_identityList_editTextChanged(const QString &text) {
+  ui.identityList->setItemText(ui.identityList->currentIndex(), text);
+}
+
+/*****************************************************************************************/
+
+CreateIdentityDlg::CreateIdentityDlg(QAbstractItemModel *model, QWidget *parent) : QDialog(parent) {
+  ui.setupUi(this);
+
+  ui.identityList->setModel(model);  // now we use the identity list of the main page... Trolltech <3
+  on_identityName_textChanged("");   // disable ok button :)
+}
+
+QString CreateIdentityDlg::identityName() const {
+  return ui.identityName->text();
+}
+
+IdentityId CreateIdentityDlg::duplicateId() const {
+  if(!ui.duplicateIdentity->isChecked()) return 0;
+  if(ui.identityList->currentIndex() >= 0) {
+    return ui.identityList->itemData(ui.identityList->currentIndex()).toInt();
+  }
+  return 0;
+}
+
+void CreateIdentityDlg::on_identityName_textChanged(const QString &text) {
+  ui.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(text.count());
+
+}
+
+/*********************************************************************************************/
+
+SaveIdentitiesDlg::SaveIdentitiesDlg(QList<Identity *> tocreate, QList<Identity *> toupdate, QList<IdentityId> toremove, QWidget *parent)
+  : QDialog(parent), toCreate(tocreate), toUpdate(toupdate), toRemove(toremove) {
+  ui.setupUi(this);
+  numevents = toCreate.count() + toUpdate.count() + toRemove.count();
+  rcvevents = 0;
+  if(numevents) {
+    ui.progressBar->setMaximum(numevents);
+    ui.progressBar->setValue(0);
+
+    connect(Client::instance(), SIGNAL(identityCreated(IdentityId)), this, SLOT(clientEvent()));
+    connect(Client::instance(), SIGNAL(identityRemoved(IdentityId)), this, SLOT(clientEvent()));
+
+    foreach(Identity *id, toCreate) {
+      Client::createIdentity(*id);
+    }
+    foreach(Identity *id, toUpdate) {
+      const Identity *cid = Client::identity(id->id());
+      if(!cid) {
+        qWarning() << "Invalid client identity!";
+        numevents--;
+        continue;
+      }
+      connect(cid, SIGNAL(updatedRemotely()), this, SLOT(clientEvent()));
+      Client::updateIdentity(*id);
+    }
+    foreach(IdentityId id, toRemove) {
+      Client::removeIdentity(id);
+    }
+  } else {
+    qWarning() << "Sync dialog called without stuff to change!";
+    accept();
+  }
+}
 
+void SaveIdentitiesDlg::clientEvent() {
+  ui.progressBar->setValue(++rcvevents);
+  if(rcvevents >= numevents) accept();
 }
index ea43c8c..0e21662 100644 (file)
 #ifndef _IDENTITIESSETTINGSPAGE_H_
 #define _IDENTITIESSETTINGSPAGE_H_
 
+#include "identity.h"
 #include "settingspage.h"
 
 #include "ui_identitiessettingspage.h"
+#include "ui_createidentitydlg.h"
+#include "ui_saveidentitiesdlg.h"
+
+class QAbstractItemModel;
 
 class IdentitiesSettingsPage : public SettingsPage {
   Q_OBJECT
@@ -31,7 +36,7 @@ class IdentitiesSettingsPage : public SettingsPage {
   public:
     IdentitiesSettingsPage(QWidget *parent = 0);
 
-    bool hasChanged() const;
+    bool aboutToSave();
 
   public slots:
     void save();
@@ -40,10 +45,68 @@ class IdentitiesSettingsPage : public SettingsPage {
 
   private slots:
     void coreConnectionStateChanged(bool);
+    void clientIdentityCreated(IdentityId);
+    void clientIdentityUpdated();
+    void clientIdentityRemoved(IdentityId);
+
+    void on_identityList_currentIndexChanged(int index);
+    void on_identityList_editTextChanged(const QString &);
+
+    void on_addIdentity_clicked();
+    void on_deleteIdentity_clicked();
+
+    void widgetHasChanged();
 
   private:
     Ui::IdentitiesSettingsPage ui;
 
+    QHash<IdentityId, Identity *> identities;
+    IdentityId currentId;
+
+    QList<IdentityId> changedIdentities;  // for setting the widget changed state
+    QList<IdentityId> deletedIdentities;
+
+    void insertIdentity(Identity *identity);
+    void removeIdentity(Identity *identity);
+    void displayIdentity(Identity *, bool dontsave = false);
+    void saveToIdentity(Identity *);
+
+    bool testHasChanged();
+};
+
+class CreateIdentityDlg : public QDialog {
+  Q_OBJECT
+
+  public:
+    CreateIdentityDlg(QAbstractItemModel *model, QWidget *parent = 0);
+
+    QString identityName() const;
+    IdentityId duplicateId() const;
+
+  private slots:
+    void on_identityName_textChanged(const QString &text);
+
+  private:
+    Ui::CreateIdentityDlg ui;
+};
+
+class SaveIdentitiesDlg : public QDialog {
+  Q_OBJECT
+
+  public:
+    SaveIdentitiesDlg(QList<Identity *> toCreate, QList<Identity *> toUpdate, QList<IdentityId> toRemove, QWidget *parent = 0);
+
+  private slots:
+    void clientEvent();
+
+  private:
+    Ui::SaveIdentitiesDlg ui;
+
+    QList<Identity *> toCreate, toUpdate;
+    QList<IdentityId> toRemove;
+
+    int numevents, rcvevents;
+
 };
 
 #endif
index 19bb198..fdd03e7 100644 (file)
    <item>
     <layout class="QHBoxLayout" >
      <item>
-      <widget class="QComboBox" name="comboBox" />
+      <widget class="QComboBox" name="identityList" >
+       <property name="insertPolicy" >
+        <enum>QComboBox::InsertAtBottom</enum>
+       </property>
+       <property name="duplicatesEnabled" >
+        <bool>true</bool>
+       </property>
+      </widget>
      </item>
      <item>
       <widget class="QToolButton" name="addIdentity" >
        </property>
       </widget>
      </item>
-     <item>
-      <widget class="QToolButton" name="renameIdentity" >
-       <property name="text" >
-        <string>...</string>
-       </property>
-       <property name="icon" >
-        <iconset resource="../../icons/icons.qrc" >:/22x22/actions/oxygen/22x22/actions/user-properties.png</iconset>
-       </property>
-       <property name="iconSize" >
-        <size>
-         <width>22</width>
-         <height>22</height>
-        </size>
-       </property>
-      </widget>
-     </item>
      <item>
       <widget class="QToolButton" name="deleteIdentity" >
        <property name="text" >
           <number>6</number>
          </property>
          <item row="0" column="1" >
-          <widget class="QLineEdit" name="awayNick" />
+          <widget class="QLineEdit" name="awayNick" >
+           <property name="enabled" >
+            <bool>false</bool>
+           </property>
+          </widget>
          </item>
          <item row="1" column="0" >
-          <widget class="QCheckBox" name="enableAwayReason" >
+          <widget class="QCheckBox" name="awayReasonEnabled" >
            <property name="text" >
             <string>Away Reason</string>
            </property>
           </widget>
          </item>
          <item row="1" column="1" >
-          <widget class="QLineEdit" name="awayReason" />
+          <widget class="QLineEdit" name="awayReason" >
+           <property name="enabled" >
+            <bool>false</bool>
+           </property>
+          </widget>
          </item>
          <item row="2" column="0" >
-          <widget class="QCheckBox" name="enableReturnMessage" >
+          <widget class="QCheckBox" name="returnMessageEnabled" >
            <property name="text" >
             <string>Return Message</string>
            </property>
           </widget>
          </item>
          <item row="2" column="1" >
-          <widget class="QLineEdit" name="returnMessage" />
+          <widget class="QLineEdit" name="returnMessage" >
+           <property name="enabled" >
+            <bool>false</bool>
+           </property>
+          </widget>
          </item>
          <item row="0" column="0" >
-          <widget class="QCheckBox" name="enableAwayNick" >
+          <widget class="QCheckBox" name="awayNickEnabled" >
            <property name="text" >
             <string>Away Nick</string>
            </property>
         </layout>
        </item>
        <item>
-        <widget class="QGroupBox" name="autoAway" >
+        <widget class="QGroupBox" name="autoAwayEnabled" >
          <property name="title" >
           <string>Auto Away</string>
          </property>
              <number>6</number>
             </property>
             <item row="1" column="0" >
-             <widget class="QCheckBox" name="enableAutoAwayReturn" >
+             <widget class="QCheckBox" name="autoReturnMessageEnabled" >
               <property name="text" >
                <string>Return Message</string>
               </property>
              </widget>
             </item>
             <item row="0" column="0" >
-             <widget class="QCheckBox" name="enableAutoAwayReason" >
+             <widget class="QCheckBox" name="autoAwayReasonEnabled" >
               <property name="text" >
                <string>Away Reason</string>
               </property>
              </widget>
             </item>
             <item row="1" column="1" >
-             <widget class="QLineEdit" name="autoAwayReturn" />
+             <widget class="QLineEdit" name="autoReturnMessage" />
             </item>
             <item row="0" column="1" >
              <widget class="QLineEdit" name="autoAwayReason" />
  <resources>
   <include location="../../icons/icons.qrc" />
  </resources>
- <connections/>
+ <connections>
+  <connection>
+   <sender>awayNickEnabled</sender>
+   <signal>toggled(bool)</signal>
+   <receiver>awayNick</receiver>
+   <slot>setEnabled(bool)</slot>
+   <hints>
+    <hint type="sourcelabel" >
+     <x>47</x>
+     <y>85</y>
+    </hint>
+    <hint type="destinationlabel" >
+     <x>185</x>
+     <y>90</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>awayReasonEnabled</sender>
+   <signal>toggled(bool)</signal>
+   <receiver>awayReason</receiver>
+   <slot>setEnabled(bool)</slot>
+   <hints>
+    <hint type="sourcelabel" >
+     <x>57</x>
+     <y>120</y>
+    </hint>
+    <hint type="destinationlabel" >
+     <x>177</x>
+     <y>123</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>returnMessageEnabled</sender>
+   <signal>toggled(bool)</signal>
+   <receiver>returnMessage</receiver>
+   <slot>setEnabled(bool)</slot>
+   <hints>
+    <hint type="sourcelabel" >
+     <x>85</x>
+     <y>154</y>
+    </hint>
+    <hint type="destinationlabel" >
+     <x>240</x>
+     <y>160</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>autoAwayReasonEnabled</sender>
+   <signal>toggled(bool)</signal>
+   <receiver>autoAwayReason</receiver>
+   <slot>setEnabled(bool)</slot>
+   <hints>
+    <hint type="sourcelabel" >
+     <x>107</x>
+     <y>262</y>
+    </hint>
+    <hint type="destinationlabel" >
+     <x>186</x>
+     <y>264</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>autoReturnMessageEnabled</sender>
+   <signal>toggled(bool)</signal>
+   <receiver>autoReturnMessage</receiver>
+   <slot>setEnabled(bool)</slot>
+   <hints>
+    <hint type="sourcelabel" >
+     <x>122</x>
+     <y>292</y>
+    </hint>
+    <hint type="destinationlabel" >
+     <x>204</x>
+     <y>299</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
 </ui>
diff --git a/src/qtui/settingspages/saveidentitiesdlg.ui b/src/qtui/settingspages/saveidentitiesdlg.ui
new file mode 100644 (file)
index 0000000..c0b3303
--- /dev/null
@@ -0,0 +1,124 @@
+<ui version="4.0" >
+ <class>SaveIdentitiesDlg</class>
+ <widget class="QDialog" name="SaveIdentitiesDlg" >
+  <property name="geometry" >
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>246</width>
+    <height>104</height>
+   </rect>
+  </property>
+  <property name="windowTitle" >
+   <string>Sync With Core</string>
+  </property>
+  <layout class="QVBoxLayout" >
+   <item>
+    <widget class="QLabel" name="label" >
+     <property name="text" >
+      <string>Syncing data with core, please wait...</string>
+     </property>
+     <property name="alignment" >
+      <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
+     </property>
+     <property name="wordWrap" >
+      <bool>true</bool>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QProgressBar" name="progressBar" >
+     <property name="maximum" >
+      <number>0</number>
+     </property>
+     <property name="value" >
+      <number>0</number>
+     </property>
+     <property name="invertedAppearance" >
+      <bool>false</bool>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <spacer>
+     <property name="orientation" >
+      <enum>Qt::Vertical</enum>
+     </property>
+     <property name="sizeHint" >
+      <size>
+       <width>20</width>
+       <height>40</height>
+      </size>
+     </property>
+    </spacer>
+   </item>
+   <item>
+    <layout class="QHBoxLayout" >
+     <item>
+      <spacer>
+       <property name="orientation" >
+        <enum>Qt::Horizontal</enum>
+       </property>
+       <property name="sizeHint" >
+        <size>
+         <width>40</width>
+         <height>20</height>
+        </size>
+       </property>
+      </spacer>
+     </item>
+     <item>
+      <widget class="QPushButton" name="abort" >
+       <property name="sizePolicy" >
+        <sizepolicy vsizetype="Fixed" hsizetype="Preferred" >
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="text" >
+        <string>Abort</string>
+       </property>
+       <property name="icon" >
+        <iconset resource="../../icons/icons.qrc" >:/22x22/actions/oxygen/22x22/actions/dialog-cancel.png</iconset>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <spacer>
+       <property name="orientation" >
+        <enum>Qt::Horizontal</enum>
+       </property>
+       <property name="sizeHint" >
+        <size>
+         <width>40</width>
+         <height>20</height>
+        </size>
+       </property>
+      </spacer>
+     </item>
+    </layout>
+   </item>
+  </layout>
+ </widget>
+ <resources>
+  <include location="../../icons/icons.qrc" />
+ </resources>
+ <connections>
+  <connection>
+   <sender>abort</sender>
+   <signal>clicked()</signal>
+   <receiver>SaveIdentitiesDlg</receiver>
+   <slot>reject()</slot>
+   <hints>
+    <hint type="sourcelabel" >
+     <x>122</x>
+     <y>85</y>
+    </hint>
+    <hint type="destinationlabel" >
+     <x>122</x>
+     <y>51</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+</ui>
index 8aec6ed..2e007c9 100644 (file)
@@ -4,4 +4,4 @@ SETTINGSPAGES = fonts identities
 
 SP_SRCS = 
 SP_HDRS =
-SP_FRMS =
+SP_FRMS = createidentitydlg.ui saveidentitiesdlg.ui
index dd29e7e..8b8e423 100644 (file)
@@ -34,11 +34,22 @@ QString SettingsPage::title() const {
   return _title;
 }
 
+bool SettingsPage::hasChanged() const {
+  return _changed;
+}
+
+bool SettingsPage::aboutToSave() {
+  return true;
+}
+
 void SettingsPage::changed() {
-  _changed = true;
-  emit changed(true);
+  changeState(true);
 }
 
 void SettingsPage::changeState(bool hasChanged) {
-  if(hasChanged != _changed) emit changed(hasChanged);
+  if(hasChanged != _changed) {
+    _changed = hasChanged;
+    emit changed(hasChanged);
+  }
 }
+
index 926d4d7..2d73e82 100644 (file)
@@ -33,7 +33,13 @@ class SettingsPage : public QWidget {
     virtual QString category() const;
     virtual QString title() const;
 
-    virtual bool hasChanged() const = 0;
+    bool hasChanged() const;
+
+    //! Called immediately before save() is called.
+    /** Derived classes should return false if saving is not possible (e.g. the current settings are invalid).
+     *  \return false, if the SettingsPage cannot be saved in its current state.
+     */
+    virtual bool aboutToSave();
 
   public slots:
     virtual void save() = 0;
@@ -41,7 +47,7 @@ class SettingsPage : public QWidget {
     virtual void defaults() = 0;
 
   protected slots:
-    //! Calling this slot is equivalent to emitting changed(true).
+    //! Calling this slot is equivalent to calling changeState(true).
     void changed();
 
   protected:
@@ -49,6 +55,7 @@ class SettingsPage : public QWidget {
     void changeState(bool hasChanged = true);
 
   signals:
+    //! Emitted whenever the widget state changes.
     void changed(bool hasChanged);
 
   private: