Fixing BR #315: Nicks missing from nick lists
authorMarcus Eggenberger <egs@quassel-irc.org>
Tue, 2 Dec 2008 00:06:40 +0000 (01:06 +0100)
committerMarcus Eggenberger <egs@quassel-irc.org>
Tue, 2 Dec 2008 00:06:46 +0000 (01:06 +0100)
 - also fixes BR #310: Nicklist freaks out when cycling
 - breaks protocol

src/client/clientsyncer.cpp
src/client/networkmodel.cpp
src/client/networkmodel.h
src/common/ircchannel.cpp
src/common/ircchannel.h
src/common/ircuser.cpp
src/common/ircuser.h
src/common/network.cpp
src/common/network.h
src/core/ircserverhandler.cpp
version.inc

index 139f44b..a8e08ef 100644 (file)
@@ -26,8 +26,6 @@
 
 #include "client.h"
 #include "identity.h"
-#include "ircuser.h"
-#include "ircchannel.h"
 #include "network.h"
 #include "networkmodel.h"
 #include "quassel.h"
index f58dc97..c75dd57 100644 (file)
@@ -363,12 +363,12 @@ QString QueryBufferItem::toolTip(int column) const {
 
 void QueryBufferItem::attachIrcUser(IrcUser *ircUser) {
   _ircUser = ircUser;
-  connect(_ircUser, SIGNAL(destroyed()), this, SLOT(ircUserDestroyed()));
+  connect(_ircUser, SIGNAL(quited()), this, SLOT(ircUserQuited()));
   connect(_ircUser, SIGNAL(awaySet(bool)), this, SIGNAL(dataChanged()));
   emit dataChanged();
 }
 
-void QueryBufferItem::ircUserDestroyed() {
+void QueryBufferItem::ircUserQuited() {
   _ircUser = 0;
   emit dataChanged();
 }
@@ -442,8 +442,8 @@ void ChannelBufferItem::attachIrcChannel(IrcChannel *ircChannel) {
          this, SLOT(join(QList<IrcUser *>)));
   connect(ircChannel, SIGNAL(ircUserParted(IrcUser *)),
          this, SLOT(part(IrcUser *)));
-  connect(ircChannel, SIGNAL(destroyed()),
-         this, SLOT(ircChannelDestroyed()));
+  connect(ircChannel, SIGNAL(parted()),
+         this, SLOT(ircChannelParted()));
   connect(ircChannel, SIGNAL(ircUserModesSet(IrcUser *, QString)),
          this, SLOT(userModeChanged(IrcUser *)));
   connect(ircChannel, SIGNAL(ircUserModeAdded(IrcUser *, QString)),
@@ -457,7 +457,7 @@ void ChannelBufferItem::attachIrcChannel(IrcChannel *ircChannel) {
   emit dataChanged();
 }
 
-void ChannelBufferItem::ircChannelDestroyed() {
+void ChannelBufferItem::ircChannelParted() {
   Q_CHECK_PTR(_ircChannel);
   disconnect(_ircChannel, 0, this, 0);
   _ircChannel = 0;
@@ -672,7 +672,7 @@ IrcUserItem::IrcUserItem(IrcUser *ircUser, AbstractTreeItem *parent)
     _ircUser(ircUser)
 {
   setObjectName(ircUser->nick());
-  connect(ircUser, SIGNAL(destroyed()), this, SLOT(ircUserDestroyed()));
+  connect(ircUser, SIGNAL(quited()), this, SLOT(ircUserQuited()));
   connect(ircUser, SIGNAL(nickSet(QString)), this, SIGNAL(dataChanged()));
   connect(ircUser, SIGNAL(awaySet(bool)), this, SIGNAL(dataChanged()));
 }
@@ -729,12 +729,6 @@ QString IrcUserItem::toolTip(int column) const {
   return QString("<p> %1 </p>").arg(toolTip.join("<br />"));
 }
 
-// void IrcUserItem::ircUserDestroyed() {
-//   parent()->removeChild(this);
-//   if(parent()->childCount() == 0)
-//     parent()->parent()->removeChild(parent());
-// }
-
 /*****************************************
  * NetworkModel
  *****************************************/
index 018d6e7..807403e 100644 (file)
@@ -158,7 +158,7 @@ public:
 
 public slots:
   void attachIrcUser(IrcUser *ircUser);
-  void ircUserDestroyed();
+  void ircUserQuited();
 
 private:
   IrcUser *_ircUser;
@@ -195,7 +195,7 @@ public slots:
   void userModeChanged(IrcUser *ircUser);
 
 private slots:
-  void ircChannelDestroyed();
+  void ircChannelParted();
 
 private:
   IrcChannel *_ircChannel;
@@ -246,7 +246,7 @@ public:
   virtual QString toolTip(int column) const;
 
 private slots:
-  inline void ircUserDestroyed() { parent()->removeChild(this); }
+  inline void ircUserQuited() { parent()->removeChild(this); }
 
 private:
   QPointer<IrcUser> _ircUser;
index fd98360..04ff143 100644 (file)
@@ -43,6 +43,9 @@ IrcChannel::IrcChannel(const QString &channelname, Network *network)
   setObjectName(QString::number(network->networkId().toInt()) + "/" +  channelname);
 }
 
+IrcChannel::~IrcChannel() {
+}
+
 // ====================
 //  PUBLIC:
 // ====================
@@ -144,9 +147,8 @@ void IrcChannel::joinIrcUsers(const QList<IrcUser *> &users, const QStringList &
 
     _userModes[ircuser] = modes[i];
     ircuser->joinChannel(this);
-    //qDebug() << "JOIN" << name() << ircuser->nick() << ircUsers().count();
     connect(ircuser, SIGNAL(nickSet(QString)), this, SLOT(ircUserNickSet(QString)));
-    connect(ircuser, SIGNAL(destroyed()), this, SLOT(ircUserDestroyed()));
+    // connect(ircuser, SIGNAL(destroyed()), this, SLOT(ircUserDestroyed()));
     // if you wonder why there is no counterpart to ircUserJoined:
     // the joines are propagted by the ircuser. the signal ircUserJoined is only for convenience
 
@@ -185,13 +187,22 @@ void IrcChannel::part(IrcUser *ircuser) {
   if(isKnownUser(ircuser)) {
     _userModes.remove(ircuser);
     ircuser->partChannel(this);
-    //qDebug() << "PART" << name() << ircuser->nick() << ircUsers().count();
     // if you wonder why there is no counterpart to ircUserParted:
     // the joines are propagted by the ircuser. the signal ircUserParted is only for convenience
     disconnect(ircuser, 0, this, 0);
     emit ircUserParted(ircuser);
-    if(network->isMe(ircuser))
-       deleteLater();
+    
+    if(network->isMe(ircuser)) {
+      // we left -> clean up the channel and destroy it
+      QList<IrcUser *> users = _userModes.keys();
+      _userModes.clear();
+      foreach(IrcUser *user, users) {
+       disconnect(user, 0, this, 0);
+       user->partChannel(this);
+      }
+      emit parted();
+      network->removeIrcChannel(this);
+    }
   }
 }
 
index 24347a8..5bcaa79 100644 (file)
@@ -18,8 +18,8 @@
  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
  ***************************************************************************/
 
-#ifndef _IRCCHANNEL_H_
-#define _IRCCHANNEL_H_
+#ifndef IRCCHANNEL_H
+#define IRCCHANNEL_H
 
 #include <QHash>
 #include <QSet>
@@ -41,6 +41,7 @@ class IrcChannel : public SyncableObject {
 
 public:
   IrcChannel(const QString &channelname, Network *network);
+  ~IrcChannel();
 
   bool isKnownUser(IrcUser *ircuser) const;
   bool isValidChannelUserMode(const QString &mode) const;
@@ -118,6 +119,8 @@ signals:
   void ircUserModeRemoved(IrcUser *ircuser, QString mode);
   void ircUserModesSet(IrcUser *ircuser, QString modes);
 
+  void parted(); // convenience signal emitted before channels destruction
+
 private slots:
    void ircUserDestroyed();
    void ircUserNickSet(QString nick);
index 22df0c9..ab773d9 100644 (file)
@@ -218,7 +218,7 @@ void IrcUser::joinChannel(IrcChannel *channel) {
   if(!_channels.contains(channel)) {
     _channels.insert(channel);
     channel->joinIrcUsers(this);
-    connect(channel, SIGNAL(destroyed()), this, SLOT(channelDestroyed()));
+    // connect(channel, SIGNAL(destroyed()), this, SLOT(channelDestroyed()));
   }
 }
 
@@ -233,7 +233,7 @@ void IrcUser::partChannel(IrcChannel *channel) {
     channel->part(this);
     emit channelParted(channel->name());
     if(_channels.isEmpty() && !network()->isMe(this))
-      deleteLater();
+      quit();
   }
 }
 
@@ -246,13 +246,24 @@ void IrcUser::partChannel(const QString &channelname) {
   }
 }
 
+void IrcUser::quit() {
+  QList<IrcChannel *> channels = _channels.toList();
+  _channels.clear();
+  foreach(IrcChannel *channel, channels) {
+    disconnect(channel, 0, this, 0);
+    channel->part(this);
+  }
+  network()->removeIrcUser(this);
+  emit quited();
+}
+
 void IrcUser::channelDestroyed() {
   // private slot!
   IrcChannel *channel = static_cast<IrcChannel*>(sender());
   if(_channels.contains(channel)) {
     _channels.remove(channel);
-    if(_channels.isEmpty())
-      deleteLater();
+    if(_channels.isEmpty() && !network()->isMe(this))
+      quit();
   }
 }
 
index 00df169..4a9a5be 100644 (file)
@@ -18,8 +18,8 @@
  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
  ***************************************************************************/
 
-#ifndef _IRCUSER_H_
-#define _IRCUSER_H_
+#ifndef IRCUSER_H
+#define IRCUSER_H
 
 #include <QSet>
 #include <QString>
@@ -110,6 +110,7 @@ public slots:
   void joinChannel(const QString &channelname);
   void partChannel(IrcChannel *channel);
   void partChannel(const QString &channelname);
+  void quit();
 
   void addUserModes(const QString &modes);
   void removeUserModes(const QString &modes);
@@ -134,6 +135,7 @@ signals:
 
   // void channelJoined(QString channel);
   void channelParted(QString channel);
+  void quited();
 
   void userModesAdded(QString modes);
   void userModesRemoved(QString modes);
index 23ce589..9c0f915 100644 (file)
@@ -197,34 +197,22 @@ IrcUser *Network::newIrcUser(const QString &hostmask, const QVariantMap &initDat
       qWarning() << "unable to synchronize new IrcUser" << hostmask << "forgot to call Network::setProxy(SignalProxy *)?";
 
     connect(ircuser, SIGNAL(nickSet(QString)), this, SLOT(ircUserNickChanged(QString)));
-    connect(ircuser, SIGNAL(destroyed()), this, SLOT(ircUserDestroyed()));
-    if(!ircuser->isInitialized())
-      connect(ircuser, SIGNAL(initDone()), this, SLOT(ircUserInitDone()));
 
     _ircUsers[nick] = ircuser;
 
     emit ircUserAdded(hostmask);
     emit ircUserAdded(ircuser);
-    if(ircuser->isInitialized())
-      emit ircUserInitDone(ircuser);
   }
 
   return _ircUsers[nick];
 }
 
-void Network::ircUserDestroyed() {
-  IrcUser *ircUser = static_cast<IrcUser *>(sender());
-  if(!ircUser)
-    return;
-
-  QHash<QString, IrcUser *>::iterator ircUserIter = _ircUsers.begin();
-  while(ircUserIter != _ircUsers.end()) {
-    if(ircUser == *ircUserIter) {
-      ircUserIter = _ircUsers.erase(ircUserIter);
-      break;
-    }
-    ircUserIter++;
-  }
+IrcUser *Network::ircUser(QString nickname) const {
+  nickname = nickname.toLower();
+  if(_ircUsers.contains(nickname))
+    return _ircUsers[nickname];
+  else
+    return 0;
 }
 
 void Network::removeIrcUser(IrcUser *ircuser) {
@@ -234,34 +222,34 @@ void Network::removeIrcUser(IrcUser *ircuser) {
 
   _ircUsers.remove(nick);
   disconnect(ircuser, 0, this, 0);
-  emit ircUserRemoved(nick);
-  emit ircUserRemoved(ircuser);
   ircuser->deleteLater();
 }
 
-void Network::removeIrcUser(const QString &nick) {
-  IrcUser *ircuser;
-  if((ircuser = ircUser(nick)) != 0)
-    removeIrcUser(ircuser);
+void Network::removeIrcChannel(IrcChannel *channel) {
+  QString chanName = _ircChannels.key(channel);
+  if(chanName.isNull())
+    return;
+
+  _ircChannels.remove(chanName);
+  disconnect(channel, 0, this, 0);
+  channel->deleteLater();
 }
 
 void Network::removeChansAndUsers() {
   QList<IrcUser *> users = ircUsers();
-  foreach(IrcUser *user, users) {
-    removeIrcUser(user);
-  }
+  _ircUsers.clear();
   QList<IrcChannel *> channels = ircChannels();
+  _ircChannels.clear();
+  
   foreach(IrcChannel *channel, channels) {
-    removeIrcChannel(channel);
+    disconnect(channel, 0, this, 0);
   }
-}
-
-IrcUser *Network::ircUser(QString nickname) const {
-  nickname = nickname.toLower();
-  if(_ircUsers.contains(nickname))
-    return _ircUsers[nickname];
-  else
-    return 0;
+  foreach(IrcUser *user, users) {
+    disconnect(user, 0, this, 0);
+    user->quit();
+  }
+  qDeleteAll(users);
+  qDeleteAll(channels);
 }
 
 IrcChannel *Network::newIrcChannel(const QString &channelname, const QVariantMap &initData) {
@@ -277,16 +265,10 @@ IrcChannel *Network::newIrcChannel(const QString &channelname, const QVariantMap
     else
       qWarning() << "unable to synchronize new IrcChannel" << channelname << "forgot to call Network::setProxy(SignalProxy *)?";
 
-    connect(channel, SIGNAL(destroyed()), this, SLOT(channelDestroyed()));
-    if(!channel->isInitialized())
-      connect(channel, SIGNAL(initDone()), this, SLOT(ircChannelInitDone()));
-
     _ircChannels[channelname.toLower()] = channel;
 
     emit ircChannelAdded(channelname);
     emit ircChannelAdded(channel);
-    if(channel->isInitialized())
-      emit ircChannelInitDone(channel);
   }
   return _ircChannels[channelname.toLower()];
 }
@@ -623,45 +605,6 @@ void Network::ircUserNickChanged(QString newnick) {
     setMyNick(newnick);
 }
 
-void Network::ircUserInitDone() {
-  IrcUser *ircuser = static_cast<IrcUser *>(sender());
-  Q_ASSERT(ircuser);
-  connect(ircuser, SIGNAL(initDone()), this, SLOT(ircUserInitDone()));
-  emit ircUserInitDone(ircuser);
-}
-
-void Network::ircChannelInitDone() {
-  IrcChannel *ircChannel = static_cast<IrcChannel *>(sender());
-  Q_ASSERT(ircChannel);
-  disconnect(ircChannel, SIGNAL(initDone()), this, SLOT(ircChannelInitDone()));
-  emit ircChannelInitDone(ircChannel);
-}
-
-void Network::removeIrcChannel(IrcChannel *channel) {
-  QString chanName = _ircChannels.key(channel);
-  if(chanName.isNull())
-    return;
-
-  _ircChannels.remove(chanName);
-  disconnect(channel, 0, this, 0);
-  emit ircChannelRemoved(chanName);
-  emit ircChannelRemoved(channel);
-  channel->deleteLater();
-}
-
-void Network::removeIrcChannel(const QString &channel) {
-  IrcChannel *chan;
-  if((chan = ircChannel(channel)) != 0)
-    removeIrcChannel(chan);
-}
-
-void Network::channelDestroyed() {
-  IrcChannel *channel = static_cast<IrcChannel *>(sender());
-  Q_ASSERT(channel);
-  _ircChannels.remove(_ircChannels.key(channel));
-  emit ircChannelRemoved(channel);
-}
-
 void Network::emitConnectionError(const QString &errorMsg) {
   emit connectionError(errorMsg);
 }
index 1785372..4a432d8 100644 (file)
@@ -210,8 +210,6 @@ public slots:
 
   inline void addIrcUser(const QString &hostmask) { newIrcUser(hostmask); }
   inline void addIrcChannel(const QString &channel) { newIrcChannel(channel); }
-  void removeIrcUser(const QString &nick);
-  void removeIrcChannel(const QString &channel);
 
   //init geters
   QVariantMap initSupports() const;
@@ -240,13 +238,9 @@ public slots:
   void emitConnectionError(const QString &);
 
 private slots:
-  void ircUserDestroyed();
-  void channelDestroyed();
   void removeIrcUser(IrcUser *ircuser);
   void removeIrcChannel(IrcChannel *ircChannel);
   void removeChansAndUsers();
-  void ircUserInitDone();
-  void ircChannelInitDone();
 
 signals:
   void aboutToBeDestroyed();
@@ -284,16 +278,6 @@ signals:
   void ircChannelAdded(const QString &channelname);
   void ircChannelAdded(IrcChannel *);
 
-  void ircUserRemoved(const QString &nick);
-  void ircChannelRemoved(const QString &channel);
-
-  // needed for client sync progress
-  void ircUserRemoved(QObject *);
-  void ircChannelRemoved(QObject *);
-
-  void ircUserInitDone(IrcUser *);
-  void ircChannelInitDone(IrcChannel *);
-
   void connectRequested(NetworkId id = 0) const;
   void disconnectRequested(NetworkId id = 0) const;
   void setNetworkInfoRequested(const NetworkInfo &) const;
@@ -346,6 +330,9 @@ private:
   static QTextCodec *_defaultCodecForDecoding;
 
   bool _autoAwayActive; // when this is active handle305 and handle306 don't trigger any output
+
+  friend class IrcUser;
+  friend class IrcChannel;
 };
 
 //! Stores all editable information about a network (as opposed to runtime state).
index 4d32f1d..4f5206a 100644 (file)
@@ -438,7 +438,7 @@ void IrcServerHandler::handleQuit(const QString &prefix, const QList<QByteArray>
   foreach(QString channel, ircuser->channels())
     emit displayMsg(Message::Quit, BufferInfo::ChannelBuffer, channel, msg, prefix);
 
-  network()->removeIrcUser(nickFromMask(prefix));
+  ircuser->quit();
 }
 
 void IrcServerHandler::handleTopic(const QString &prefix, const QList<QByteArray> &params) {
index d641931..fb1f18d 100644 (file)
@@ -1,9 +1,9 @@
 //! This is the fallback version number in case we can't autogenerate one
 baseVersion = "0.3.1";
 
-protocolVersion = 6;       //< Version of the client/core protocol
-coreNeedsProtocol   = 6;   //< Minimum protocol version the core needs
-clientNeedsProtocol = 6;   //< Minimum protocol version the client needs
+protocolVersion = 7;       //< Version of the client/core protocol
+coreNeedsProtocol   = 7;   //< Minimum protocol version the core needs
+clientNeedsProtocol = 7;   //< Minimum protocol version the client needs
 
 distCommittish = $Format:%H$
 distCommitDate = $Format:%at$