Core now remembers the channels you've joined if a disconnect happens, so you'll...
authorManuel Nickschas <sputnick@quassel-irc.org>
Tue, 19 Feb 2008 22:42:25 +0000 (22:42 +0000)
committerManuel Nickschas <sputnick@quassel-irc.org>
Tue, 19 Feb 2008 22:42:25 +0000 (22:42 +0000)
rejoin those channels upon reconnect. Moved session restore over to this mechanism - maybe it works
now better? (Though I don't believe that...).
Aaaand, especially for son: channel passwords are now remembered, so that +k channels will be
automatically rejoined as well :)

src/common/ircchannel.cpp
src/common/ircchannel.h
src/common/network.cpp
src/common/network.h
src/core/coresession.cpp
src/core/coresession.h
src/core/ircserverhandler.cpp
src/core/networkconnection.cpp
src/core/networkconnection.h
src/core/userinputhandler.cpp

index f5710ba..832a5a9 100644 (file)
@@ -73,18 +73,6 @@ bool IrcChannel::isValidChannelUserMode(const QString &mode) const {
   return isvalid;
 }
 
   return isvalid;
 }
 
-QString IrcChannel::name() const {
-  return _name;
-}
-
-QString IrcChannel::topic() const {
-  return _topic;
-}
-
-QList<IrcUser *> IrcChannel::ircUsers() const {
-  return _userModes.keys();
-}
-
 QString IrcChannel::userModes(IrcUser *ircuser) const {
   if(_userModes.contains(ircuser))
     return _userModes[ircuser];
 QString IrcChannel::userModes(IrcUser *ircuser) const {
   if(_userModes.contains(ircuser))
     return _userModes[ircuser];
@@ -96,10 +84,6 @@ QString IrcChannel::userModes(const QString &nick) const {
   return userModes(network->ircUser(nick));
 }
 
   return userModes(network->ircUser(nick));
 }
 
-QTextCodec *IrcChannel::codecForEncoding() const {
-  return _codecForEncoding;
-}
-
 void IrcChannel::setCodecForEncoding(const QString &name) {
   setCodecForEncoding(QTextCodec::codecForName(name.toAscii()));
 }
 void IrcChannel::setCodecForEncoding(const QString &name) {
   setCodecForEncoding(QTextCodec::codecForName(name.toAscii()));
 }
@@ -108,10 +92,6 @@ void IrcChannel::setCodecForEncoding(QTextCodec *codec) {
   _codecForEncoding = codec;
 }
 
   _codecForEncoding = codec;
 }
 
-QTextCodec *IrcChannel::codecForDecoding() const {
-  return _codecForDecoding;
-}
-
 void IrcChannel::setCodecForDecoding(const QString &name) {
   setCodecForDecoding(QTextCodec::codecForName(name.toAscii()));
 }
 void IrcChannel::setCodecForDecoding(const QString &name) {
   setCodecForDecoding(QTextCodec::codecForName(name.toAscii()));
 }
@@ -140,6 +120,11 @@ void IrcChannel::setTopic(const QString &topic) {
   emit topicSet(topic);
 }
 
   emit topicSet(topic);
 }
 
+void IrcChannel::setPassword(const QString &password) {
+  _password = password;
+  emit passwordSet(password);
+}
+
 void IrcChannel::join(IrcUser *ircuser) {
   if(!_userModes.contains(ircuser) && ircuser) {
     _userModes[ircuser] = QString();
 void IrcChannel::join(IrcUser *ircuser) {
   if(!_userModes.contains(ircuser) && ircuser) {
     _userModes[ircuser] = QString();
index 2bf5f64..dfc8de0 100644 (file)
@@ -37,6 +37,7 @@ class IrcChannel : public SyncableObject {
 
   Q_PROPERTY(QString name READ name STORED false)
   Q_PROPERTY(QString topic READ topic WRITE setTopic STORED false)
 
   Q_PROPERTY(QString name READ name STORED false)
   Q_PROPERTY(QString topic READ topic WRITE setTopic STORED false)
+  Q_PROPERTY(QString password READ password WRITE setPassword STORED false)
 
 public:
   IrcChannel(const QString &channelname, Network *network);
 
 public:
   IrcChannel(const QString &channelname, Network *network);
@@ -45,16 +46,17 @@ public:
   bool isKnownUser(IrcUser *ircuser) const;
   bool isValidChannelUserMode(const QString &mode) const;
 
   bool isKnownUser(IrcUser *ircuser) const;
   bool isValidChannelUserMode(const QString &mode) const;
 
-  QString name() const;
-  QString topic() const;
+  inline QString name() const { return _name; }
+  inline QString topic() const { return _topic; }
+  inline QString password() const { return _password; }
 
 
-  QList<IrcUser *> ircUsers() const;
+  inline QList<IrcUser *> ircUsers() const { return _userModes.keys(); }
 
   QString userModes(IrcUser *ircuser) const;
   QString userModes(const QString &nick) const;
 
 
   QString userModes(IrcUser *ircuser) const;
   QString userModes(const QString &nick) const;
 
-  QTextCodec *codecForEncoding() const;
-  QTextCodec *codecForDecoding() const;
+  inline QTextCodec *codecForEncoding() const { return _codecForEncoding; }
+  inline QTextCodec *codecForDecoding() const { return _codecForDecoding; }
   void setCodecForEncoding(const QString &codecName);
   void setCodecForEncoding(QTextCodec *codec);
   void setCodecForDecoding(const QString &codecName);
   void setCodecForEncoding(const QString &codecName);
   void setCodecForEncoding(QTextCodec *codec);
   void setCodecForDecoding(const QString &codecName);
@@ -65,6 +67,7 @@ public:
 
 public slots:
   void setTopic(const QString &topic);
 
 public slots:
   void setTopic(const QString &topic);
+  void setPassword(const QString &password);
 
   void join(IrcUser *ircuser);
   void join(const QString &nick);
 
   void join(IrcUser *ircuser);
   void join(const QString &nick);
@@ -88,7 +91,8 @@ public slots:
   void initSetUserModes(const QVariantMap &usermodes);
 
 signals:
   void initSetUserModes(const QVariantMap &usermodes);
 
 signals:
-  void topicSet(QString topic);
+  void topicSet(const QString &topic);
+  void passwordSet(const QString &password);
   void userModesSet(QString nick, QString modes);
   //void userModesSet(IrcUser *ircuser, QString modes);
   void userModeAdded(QString nick, QString mode);
   void userModesSet(QString nick, QString modes);
   //void userModesSet(IrcUser *ircuser, QString modes);
   void userModeAdded(QString nick, QString mode);
@@ -111,6 +115,7 @@ private:
   bool _initialized;
   QString _name;
   QString _topic;
   bool _initialized;
   QString _name;
   QString _topic;
+  QString _password;
 
   QHash<IrcUser *, QString> _userModes;
 
 
   QHash<IrcUser *, QString> _userModes;
 
index 7fa2a2a..b1a17a6 100644 (file)
@@ -631,6 +631,14 @@ QStringList Network::initIrcChannels() const {
   return _ircChannels.keys();
 }
 
   return _ircChannels.keys();
 }
 
+QStringList Network::initPersistentChannels() const {
+  QStringList list;
+  foreach(QString chan, _persistentChannels.keys()) {
+    list << QString("%1/%2").arg(chan).arg(_persistentChannels.value(chan));
+  }
+  return list;
+}
+
 void Network::initSetSupports(const QVariantMap &supports) {
   QMapIterator<QString, QVariant> iter(supports);
   while(iter.hasNext()) {
 void Network::initSetSupports(const QVariantMap &supports) {
   QMapIterator<QString, QVariant> iter(supports);
   while(iter.hasNext()) {
@@ -651,13 +659,39 @@ void Network::initSetIrcUsers(const QStringList &hostmasks) {
   }
 }
 
   }
 }
 
-void Network::initSetChannels(const QStringList &channels) {
+void Network::initSetIrcChannels(const QStringList &channels) {
+  // FIXME This does not work correctly, "received data for unknown User" triggers
+  //       So we disable this for now
+  return;
+
   if(!_ircChannels.empty())
     return;
   foreach(QString channel, channels)
     newIrcChannel(channel);
 }
 
   if(!_ircChannels.empty())
     return;
   foreach(QString channel, channels)
     newIrcChannel(channel);
 }
 
+void Network::initSetPersistentChannels(const QStringList &channels) {
+  foreach(QString chan, channels) {
+    QStringList l = chan.split("/");
+    _persistentChannels[l[0]] = l[1];
+  }
+}
+
+void Network::addPersistentChannel(const QString &channel, const QString &key) {
+  _persistentChannels[channel.toLower()] = key;
+  emit persistentChannelAdded(channel, key);
+}
+
+void Network::removePersistentChannel(const QString &channel) {
+  _persistentChannels.remove(channel.toLower());
+  emit persistentChannelRemoved(channel);
+}
+
+void Network::setPersistentChannelKey(const QString &channel, const QString &key) {
+  _persistentChannels[channel.toLower()] = key;
+  emit persistentChannelKeySet(channel, key);
+}
+
 IrcUser *Network::updateNickFromMask(const QString &mask) {
   QString nick(nickFromMask(mask).toLower());
   IrcUser *ircuser;
 IrcUser *Network::updateNickFromMask(const QString &mask) {
   QString nick(nickFromMask(mask).toLower());
   IrcUser *ircuser;
index c52cd59..c67fea8 100644 (file)
@@ -133,6 +133,8 @@ public:
   QList<IrcChannel *> ircChannels() const;
   quint32 ircChannelCount() const;
 
   QList<IrcChannel *> ircChannels() const;
   quint32 ircChannelCount() const;
 
+  inline QHash<QString, QString> persistentChannels() const { return _persistentChannels; }
+
   QByteArray codecForServer() const;
   QByteArray codecForEncoding() const;
   QByteArray codecForDecoding() const;
   QByteArray codecForServer() const;
   QByteArray codecForEncoding() const;
   QByteArray codecForDecoding() const;
@@ -183,18 +185,24 @@ public slots:
   inline void addIrcUser(const QString &hostmask) { newIrcUser(hostmask); }
   void removeIrcUser(const QString &nick);
   void removeIrcChannel(const QString &channel);
   inline void addIrcUser(const QString &hostmask) { newIrcUser(hostmask); }
   void removeIrcUser(const QString &nick);
   void removeIrcChannel(const QString &channel);
-  
+
+  void addPersistentChannel(const QString &channel, const QString &key = QString());
+  void removePersistentChannel(const QString &channel);
+  void setPersistentChannelKey(const QString &channel, const QString &key);
+
   //init geters
   QVariantMap initSupports() const;
   QVariantList initServerList() const;
   QStringList initIrcUsers() const;
   QStringList initIrcChannels() const;
   //init geters
   QVariantMap initSupports() const;
   QVariantList initServerList() const;
   QStringList initIrcUsers() const;
   QStringList initIrcChannels() const;
+  QStringList initPersistentChannels() const;
   
   //init seters
   void initSetSupports(const QVariantMap &supports);
   void initSetServerList(const QVariantList &serverList);
   void initSetIrcUsers(const QStringList &hostmasks);
   
   //init seters
   void initSetSupports(const QVariantMap &supports);
   void initSetServerList(const QVariantList &serverList);
   void initSetIrcUsers(const QStringList &hostmasks);
-  void initSetChannels(const QStringList &channels);
+  void initSetIrcChannels(const QStringList &channels);
+  void initSetPersistentChannels(const QStringList &channels);
   
   IrcUser *updateNickFromMask(const QString &mask);
 
   
   IrcUser *updateNickFromMask(const QString &mask);
 
@@ -253,6 +261,10 @@ signals:
   void ircUserRemoved(const QString &nick);
   void ircChannelRemoved(const QString &channel);
 
   void ircUserRemoved(const QString &nick);
   void ircChannelRemoved(const QString &channel);
 
+  void persistentChannelAdded(const QString &channel, const QString &key);
+  void persistentChannelRemoved(const QString &channel);
+  void persistentChannelKeySet(const QString &channel, const QString &key);
+
   // needed for client sync progress
   void ircUserRemoved(QObject *);
   void ircChannelRemoved(QObject *);
   // needed for client sync progress
   void ircUserRemoved(QObject *);
   void ircChannelRemoved(QObject *);
@@ -281,6 +293,7 @@ private:
   QHash<QString, IrcUser *> _ircUsers;  // stores all known nicks for the server
   QHash<QString, IrcChannel *> _ircChannels; // stores all known channels
   QHash<QString, QString> _supports;  // stores results from RPL_ISUPPORT
   QHash<QString, IrcUser *> _ircUsers;  // stores all known nicks for the server
   QHash<QString, IrcChannel *> _ircChannels; // stores all known channels
   QHash<QString, QString> _supports;  // stores results from RPL_ISUPPORT
+  QHash<QString, QString> _persistentChannels;  // stores persistent channels and their passwords, if any
 
   QVariantList _serverList;
   bool _useRandomServer;
 
   QVariantList _serverList;
   bool _useRandomServer;
index 33f094c..e3c5845 100644 (file)
@@ -45,8 +45,7 @@ CoreSession::CoreSession(UserId uid, bool restoreState, QObject *parent) : QObje
 
   SignalProxy *p = signalProxy();
 
 
   SignalProxy *p = signalProxy();
 
-  p->attachSlot(SIGNAL(requestConnect(QString)), this, SLOT(connectToNetwork(QString)));
-  p->attachSlot(SIGNAL(disconnectFromNetwork(NetworkId)), this, SLOT(disconnectFromNetwork(NetworkId))); // FIXME
+  //p->attachSlot(SIGNAL(disconnectFromNetwork(NetworkId)), this, SLOT(disconnectFromNetwork(NetworkId))); // FIXME
   p->attachSlot(SIGNAL(sendInput(BufferInfo, QString)), this, SLOT(msgFromClient(BufferInfo, QString)));
   p->attachSlot(SIGNAL(requestBacklog(BufferInfo, QVariant, QVariant)), this, SLOT(sendBacklog(BufferInfo, QVariant, QVariant)));
   p->attachSignal(this, SIGNAL(displayMsg(Message)));
   p->attachSlot(SIGNAL(sendInput(BufferInfo, QString)), this, SLOT(msgFromClient(BufferInfo, QString)));
   p->attachSlot(SIGNAL(requestBacklog(BufferInfo, QVariant, QVariant)), this, SLOT(sendBacklog(BufferInfo, QVariant, QVariant)));
   p->attachSignal(this, SIGNAL(displayMsg(Message)));
@@ -170,10 +169,13 @@ void CoreSession::loadSettings() {
 void CoreSession::saveSessionState() const {
   QVariantMap res;
   QVariantList conn;
 void CoreSession::saveSessionState() const {
   QVariantMap res;
   QVariantList conn;
-  foreach(NetworkConnection *net, _connections.values()) {
+  foreach(NetworkConnection *nc, _connections.values()) {
+    QHash<QString, QString> persistentChans = nc->network()->persistentChannels();
+    QStringList list;
+    foreach(QString chan, persistentChans.keys()) list << QString("%1/%2").arg(chan).arg(persistentChans.value(chan));
     QVariantMap m;
     QVariantMap m;
-    m["NetworkId"] = QVariant::fromValue<NetworkId>(net->networkId());
-    m["State"] = net->state();
+    m["NetworkId"] = QVariant::fromValue<NetworkId>(nc->networkId());
+    m["PersistentChannels"] = list;
     conn << m;
   }
   res["CoreBuild"] = Global::quasselBuild;
     conn << m;
   }
   res["CoreBuild"] = Global::quasselBuild;
@@ -192,7 +194,19 @@ void CoreSession::restoreSessionState() {
   QVariantList conn = s.sessionState().toMap()["ConnectedNetworks"].toList();
   foreach(QVariant v, conn) {
     NetworkId id = v.toMap()["NetworkId"].value<NetworkId>();
   QVariantList conn = s.sessionState().toMap()["ConnectedNetworks"].toList();
   foreach(QVariant v, conn) {
     NetworkId id = v.toMap()["NetworkId"].value<NetworkId>();
-    if(_networks.keys().contains(id)) connectToNetwork(id, v.toMap()["State"]);
+    // TODO remove migration code some time
+    QStringList list = v.toMap()["PersistentChannels"].toStringList();
+    if(!list.count()) {
+      // migrate older state
+      QStringList old = v.toMap()["State"].toStringList();
+      foreach(QString chan, old) list << QString("%1/").arg(chan);
+    }
+    foreach(QString chan, list) {
+      QStringList l = chan.split("/");
+      network(id)->addPersistentChannel(l[0], l[1]);
+    }
+    qDebug() << "User" << user() << "connecting to" << network(id)->networkName();
+    connectToNetwork(id);
   }
 }
 
   }
 }
 
@@ -201,6 +215,7 @@ void CoreSession::updateBufferInfo(UserId uid, const BufferInfo &bufinfo) {
 }
 
 // FIXME remove
 }
 
 // FIXME remove
+/*
 void CoreSession::connectToNetwork(QString netname, const QVariant &previousState) {
   Network *net = 0;
   foreach(Network *n, _networks.values()) {
 void CoreSession::connectToNetwork(QString netname, const QVariant &previousState) {
   Network *net = 0;
   foreach(Network *n, _networks.values()) {
@@ -214,8 +229,9 @@ void CoreSession::connectToNetwork(QString netname, const QVariant &previousStat
   }
   connectToNetwork(net->networkId(), previousState);
 }
   }
   connectToNetwork(net->networkId(), previousState);
 }
+*/
 
 
-void CoreSession::connectToNetwork(NetworkId id, const QVariant &previousState) {
+void CoreSession::connectToNetwork(NetworkId id) {
   Network *net = network(id);
   if(!net) {
     qWarning() << "Connect to unknown network requested! net:" << id << "user:" << user();
   Network *net = network(id);
   if(!net) {
     qWarning() << "Connect to unknown network requested! net:" << id << "user:" << user();
@@ -224,7 +240,7 @@ void CoreSession::connectToNetwork(NetworkId id, const QVariant &previousState)
 
   NetworkConnection *conn = networkConnection(id);
   if(!conn) {
 
   NetworkConnection *conn = networkConnection(id);
   if(!conn) {
-    conn = new NetworkConnection(net, this, previousState);
+    conn = new NetworkConnection(net, this);
     _connections[id] = conn;
     attachNetworkConnection(conn);
   }
     _connections[id] = conn;
     attachNetworkConnection(conn);
   }
index a52e039..f8134cc 100644 (file)
@@ -63,8 +63,8 @@ public slots:
 
   void addClient(QObject *socket);
 
 
   void addClient(QObject *socket);
 
-  void connectToNetwork(QString, const QVariant &previousState = QVariant());
-  void connectToNetwork(NetworkId, const QVariant &previousState = QVariant());
+//  void connectToNetwork(QString, const QVariant &previousState = QVariant());
+  void connectToNetwork(NetworkId);
   void disconnectFromNetwork(NetworkId id);
 
   //void processSignal(ClientSignal, QVariant, QVariant, QVariant);
   void disconnectFromNetwork(NetworkId id);
 
   //void processSignal(ClientSignal, QVariant, QVariant, QVariant);
index fd7e055..3b58903 100644 (file)
@@ -136,7 +136,7 @@ void IrcServerHandler::defaultHandler(QString cmd, const QString &prefix, const
         break;
       }
       // Server error messages which will be displayed with a colon between the first param and the rest
         break;
       }
       // Server error messages which will be displayed with a colon between the first param and the rest
-      case 413: case 414: case 423: case 441: case 444: case 461:
+      case 413: case 414: case 423: case 441: case 444: case 461:  // FIXME see below for the 47x codes
       case 467: case 471: case 473: case 474: case 475: case 476: case 477: case 478: case 482:
       case 436: // ERR_NICKCOLLISION
       { QString p = params.takeFirst();
       case 467: case 471: case 473: case 474: case 475: case 476: case 477: case 478: case 482:
       case 436: // ERR_NICKCOLLISION
       { QString p = params.takeFirst();
@@ -168,6 +168,7 @@ void IrcServerHandler::handleJoin(const QString &prefix, const QList<QByteArray>
   emit displayMsg(Message::Join, BufferInfo::ChannelBuffer, channel, channel, prefix);
   //qDebug() << "IrcServerHandler::handleJoin()" << prefix << params;
   ircuser->joinChannel(channel);
   emit displayMsg(Message::Join, BufferInfo::ChannelBuffer, channel, channel, prefix);
   //qDebug() << "IrcServerHandler::handleJoin()" << prefix << params;
   ircuser->joinChannel(channel);
+  if(network()->isMe(ircuser)) network()->addPersistentChannel(channel, networkConnection()->channelKey(channel));
 }
 
 void IrcServerHandler::handleKick(const QString &prefix, const QList<QByteArray> &params) {
 }
 
 void IrcServerHandler::handleKick(const QString &prefix, const QList<QByteArray> &params) {
@@ -185,6 +186,7 @@ void IrcServerHandler::handleKick(const QString &prefix, const QList<QByteArray>
     msg = victim->nick();
 
   emit displayMsg(Message::Kick, BufferInfo::ChannelBuffer, channel, msg, prefix);
     msg = victim->nick();
 
   emit displayMsg(Message::Kick, BufferInfo::ChannelBuffer, channel, msg, prefix);
+  //if(network()->isMe(victim)) networkConnection()->setKickedFromChannel(channel);
 }
 
 void IrcServerHandler::handleMode(const QString &prefix, const QList<QByteArray> &params) {
 }
 
 void IrcServerHandler::handleMode(const QString &prefix, const QList<QByteArray> &params) {
@@ -276,6 +278,7 @@ void IrcServerHandler::handlePart(const QString &prefix, const QList<QByteArray>
     msg = userDecode(ircuser->nick(), params[1]);
 
   emit displayMsg(Message::Part, BufferInfo::ChannelBuffer, channel, msg, prefix);
     msg = userDecode(ircuser->nick(), params[1]);
 
   emit displayMsg(Message::Part, BufferInfo::ChannelBuffer, channel, msg, prefix);
+  if(network()->isMe(ircuser)) network()->removePersistentChannel(channel);
 }
 
 void IrcServerHandler::handlePing(const QString &prefix, const QList<QByteArray> &params) {
 }
 
 void IrcServerHandler::handlePing(const QString &prefix, const QList<QByteArray> &params) {
@@ -608,6 +611,13 @@ void IrcServerHandler::handle433(const QString &prefix, const QList<QByteArray>
   tryNextNick(errnick);
 }
 
   tryNextNick(errnick);
 }
 
+/* */
+
+// FIXME networkConnection()->setChannelKey("") for all ERR replies indicating that a JOIN went wrong
+//       mostly, these are codes in the 47x range
+
+/* */
+
 void IrcServerHandler::tryNextNick(const QString &errnick) {
   QStringList desiredNicks = networkConnection()->coreSession()->identity(network()->identity())->nicks();
   int nextNick = desiredNicks.indexOf(errnick) + 1;
 void IrcServerHandler::tryNextNick(const QString &errnick) {
   QStringList desiredNicks = networkConnection()->coreSession()->identity(network()->identity())->nicks();
   int nextNick = desiredNicks.indexOf(errnick) + 1;
index 5830d02..651a1be 100644 (file)
 #include "userinputhandler.h"
 #include "ctcphandler.h"
 
 #include "userinputhandler.h"
 #include "ctcphandler.h"
 
-NetworkConnection::NetworkConnection(Network *network, CoreSession *session, const QVariant &state) : QObject(network),
+NetworkConnection::NetworkConnection(Network *network, CoreSession *session) : QObject(network),
     _connectionState(Network::Disconnected),
     _network(network),
     _coreSession(session),
     _ircServerHandler(new IrcServerHandler(this)),
     _userInputHandler(new UserInputHandler(this)),
     _ctcpHandler(new CtcpHandler(this)),
     _connectionState(Network::Disconnected),
     _network(network),
     _coreSession(session),
     _ircServerHandler(new IrcServerHandler(this)),
     _userInputHandler(new UserInputHandler(this)),
     _ctcpHandler(new CtcpHandler(this)),
-    _previousState(state),
     _autoReconnectCount(0)
 {
   _autoReconnectTimer.setSingleShot(true);
     _autoReconnectCount(0)
 {
   _autoReconnectTimer.setSingleShot(true);
@@ -201,20 +200,11 @@ void NetworkConnection::networkInitialized(const QString &currentServer) {
 
   sendPerform();
 
 
   sendPerform();
 
-    // rejoin channels we've been in
-  QStringList chans = _previousState.toStringList();
-  if(chans.count() > 0) {
-    qDebug() << "autojoining" << chans;
-    QVariantList list;
-    list << serverEncode(chans.join(",")); // TODO add channel passwords
-    putCmd("JOIN", list);  // FIXME check for 512 byte limit!
-  }
-  // delete _previousState, we won't need it again
-  _previousState = QVariant();
   // now we are initialized
   setConnectionState(Network::Initialized);
   network()->setConnected(true);
   emit connected(networkId());
   // now we are initialized
   setConnectionState(Network::Initialized);
   network()->setConnected(true);
   emit connected(networkId());
+
 }
 
 void NetworkConnection::sendPerform() {
 }
 
 void NetworkConnection::sendPerform() {
@@ -227,12 +217,18 @@ void NetworkConnection::sendPerform() {
   foreach(QString line, network()->perform()) {
     if(!line.isEmpty()) userInput(statusBuf, line);
   }
   foreach(QString line, network()->perform()) {
     if(!line.isEmpty()) userInput(statusBuf, line);
   }
-}
 
 
-QVariant NetworkConnection::state() const {
-  IrcUser *me = network()->ircUser(network()->myNick());
-  if(!me) return QVariant();  // this shouldn't really happen, I guess
-  return me->channels();
+  // rejoin channels we've been in
+  QStringList channels, keys;
+  foreach(QString chan, network()->persistentChannels().keys()) {
+    QString key = network()->persistentChannels()[chan];
+    if(!key.isEmpty()) {
+      channels.prepend(chan); keys.prepend(key);
+    } else {
+      channels.append(chan);
+    }
+  }
+  userInputHandler()->handleJoin(statusBuf, QString("%1 %2").arg(channels.join(",")).arg(keys.join(",")));
 }
 
 void NetworkConnection::disconnectFromIrc() {
 }
 
 void NetworkConnection::disconnectFromIrc() {
@@ -342,6 +338,15 @@ void NetworkConnection::putCmd(const QString &cmd, const QVariantList &params, c
   putRawLine(msg);
 }
 
   putRawLine(msg);
 }
 
+void NetworkConnection::addChannelKey(const QString &channel, const QString &key) {
+  if(key.isEmpty()) removeChannelKey(channel);
+  else _channelKeys[channel] = key;
+}
+
+void NetworkConnection::removeChannelKey(const QString &channel) {
+  _channelKeys.remove(channel);
+}
+
 void NetworkConnection::nickChanged(const QString &newNick, const QString &oldNick) {
   emit nickChanged(_network->networkId(), newNick, oldNick);
 }
 void NetworkConnection::nickChanged(const QString &newNick, const QString &oldNick) {
   emit nickChanged(_network->networkId(), newNick, oldNick);
 }
index 83dcdec..f9db515 100644 (file)
@@ -43,7 +43,7 @@ class NetworkConnection : public QObject {
   Q_OBJECT
 
 public:
   Q_OBJECT
 
 public:
-  NetworkConnection(Network *network, CoreSession *session, const QVariant &previousState = QVariant());
+  NetworkConnection(Network *network, CoreSession *session);
   ~NetworkConnection();
 
   NetworkId networkId() const;
   ~NetworkConnection();
 
   NetworkId networkId() const;
@@ -59,9 +59,6 @@ public:
   UserInputHandler *userInputHandler() const;
   CtcpHandler *ctcpHandler() const;
 
   UserInputHandler *userInputHandler() const;
   CtcpHandler *ctcpHandler() const;
 
-  //! Return data necessary to restore the connection state upon core restart
-  QVariant state() const;
-
   //! Decode a string using the server (network) decoding.
   QString serverDecode(const QByteArray &string) const;
 
   //! Decode a string using the server (network) decoding.
   QString serverDecode(const QByteArray &string) const;
 
@@ -80,6 +77,8 @@ public:
   //! Encode a string using the user-specific encoding, if set, and use the standard encoding else.
   QByteArray userEncode(const QString &userNick, const QString &string) const;
 
   //! Encode a string using the user-specific encoding, if set, and use the standard encoding else.
   QByteArray userEncode(const QString &userNick, const QString &string) const;
 
+  inline QString channelKey(const QString &channel) const { return _channelKeys.value(channel, QString()); }
+
 public slots:
   // void setServerOptions();
   void connectToIrc(bool reconnecting = false);
 public slots:
   // void setServerOptions();
   void connectToIrc(bool reconnecting = false);
@@ -89,6 +88,8 @@ public slots:
   void putRawLine(QByteArray input);
   void putCmd(const QString &cmd, const QVariantList &params, const QByteArray &prefix = QByteArray());
 
   void putRawLine(QByteArray input);
   void putCmd(const QString &cmd, const QVariantList &params, const QByteArray &prefix = QByteArray());
 
+  void addChannelKey(const QString &channel, const QString &key);
+  void removeChannelKey(const QString &channel);
 
 private slots:
   void sendPerform();
 
 private slots:
   void sendPerform();
@@ -133,8 +134,7 @@ private:
   UserInputHandler *_userInputHandler;
   CtcpHandler *_ctcpHandler;
 
   UserInputHandler *_userInputHandler;
   CtcpHandler *_ctcpHandler;
 
-  QVariant _previousState;
-
+  QHash<QString, QString> _channelKeys;
   QTimer _autoReconnectTimer;
   int _autoReconnectCount;
 
   QTimer _autoReconnectTimer;
   int _autoReconnectCount;
 
index 956e352..0856134 100644 (file)
@@ -107,18 +107,27 @@ void UserInputHandler::handleInvite(const BufferInfo &bufferInfo, const QString
 }
 
 void UserInputHandler::handleJ(const BufferInfo &bufferInfo, const QString &msg) {
 }
 
 void UserInputHandler::handleJ(const BufferInfo &bufferInfo, const QString &msg) {
-  Q_UNUSED(bufferInfo)
-  QStringList params = msg.split(" ");
-  if(params.size() > 0 && !params[0].startsWith("#")) {
-    params[0] = QString("#%1").arg(params[0]);
-  }
-  emit putCmd("JOIN", serverEncode(params));
+  QString trimmed = msg.trimmed();
+  if(trimmed.length() == 0) return;
+  if(trimmed[0].isLetter()) trimmed.prepend("#");
+  handleJoin(bufferInfo, trimmed);
 }
 
 void UserInputHandler::handleJoin(const BufferInfo &bufferInfo, const QString &msg) {
   Q_UNUSED(bufferInfo)
 }
 
 void UserInputHandler::handleJoin(const BufferInfo &bufferInfo, const QString &msg) {
   Q_UNUSED(bufferInfo)
-  QStringList params = msg.split(" ");
-  emit putCmd("JOIN", serverEncode(params));
+  QStringList params = msg.trimmed().split(" ");
+  QStringList chans = params[0].split(",");
+  QStringList keys;
+  if(params.count() > 1) keys = params[1].split(",");
+  emit putCmd("JOIN", serverEncode(params)); // FIXME handle messages longer than 512 bytes!
+  int i = 0;
+  for(; i < keys.count(); i++) {
+    if(i >= chans.count()) break;
+    networkConnection()->addChannelKey(chans[i], keys[i]);
+  }
+  for(; i < chans.count(); i++) {
+    networkConnection()->removeChannelKey(chans[i]);
+  }
 }
 
 void UserInputHandler::handleKick(const BufferInfo &bufferInfo, const QString &msg) {
 }
 
 void UserInputHandler::handleKick(const BufferInfo &bufferInfo, const QString &msg) {