modernize: Use nullptr
[quassel.git] / src / common / ircchannel.cpp
index c111b9f..dd47f85 100644 (file)
@@ -1,5 +1,5 @@
 /***************************************************************************
- *   Copyright (C) 2005-2015 by the Quassel Project                        *
+ *   Copyright (C) 2005-2018 by the Quassel Project                        *
  *   devel@quassel-irc.org                                                 *
  *                                                                         *
  *   This program is free software; you can redistribute it and/or modify  *
@@ -30,7 +30,6 @@
 
 #include <QDebug>
 
-INIT_SYNCABLE_OBJECT(IrcChannel)
 IrcChannel::IrcChannel(const QString &channelname, Network *network)
     : SyncableObject(network),
     _initialized(false),
@@ -38,8 +37,8 @@ IrcChannel::IrcChannel(const QString &channelname, Network *network)
     _topic(QString()),
     _encrypted(false),
     _network(network),
-    _codecForEncoding(0),
-    _codecForDecoding(0)
+    _codecForEncoding(nullptr),
+    _codecForDecoding(nullptr)
 {
     setObjectName(QString::number(network->networkId().toInt()) + "/" +  channelname);
 }
@@ -55,13 +54,13 @@ IrcChannel::~IrcChannel()
 // ====================
 bool IrcChannel::isKnownUser(IrcUser *ircuser) const
 {
-    if (ircuser == 0) {
+    if (ircuser == nullptr) {
         qWarning() << "Channel" << name() << "received IrcUser Nullpointer!";
         return false;
     }
 
     if (!_userModes.contains(ircuser)) {
-        qWarning() << "Channel" << name() << "received data for unknown User" << ircuser->nick();
+        // This can happen e.g. when disconnecting from a network, so don't log a warning
         return false;
     }
 
@@ -170,6 +169,9 @@ void IrcChannel::joinIrcUsers(const QList<IrcUser *> &users, const QStringList &
         return;
     }
 
+    // Sort user modes first
+    const QStringList sortedModes = network()->sortPrefixModes(modes);
+
     QStringList newNicks;
     QStringList newModes;
     QList<IrcUser *> newUsers;
@@ -177,12 +179,22 @@ void IrcChannel::joinIrcUsers(const QList<IrcUser *> &users, const QStringList &
     IrcUser *ircuser;
     for (int i = 0; i < users.count(); i++) {
         ircuser = users[i];
-        if (!ircuser || _userModes.contains(ircuser)) {
-            addUserMode(ircuser, modes[i]);
+        if (!ircuser)
+            continue;
+        if (_userModes.contains(ircuser)) {
+            if (sortedModes[i].count() > 1) {
+                // Multiple modes received, do it one at a time
+                // TODO Better way of syncing this without breaking protocol?
+                for (int i_m = 0; i_m < sortedModes[i].count(); ++i_m) {
+                    addUserMode(ircuser, sortedModes[i][i_m]);
+                }
+            } else {
+                addUserMode(ircuser, sortedModes[i]);
+            }
             continue;
         }
 
-        _userModes[ircuser] = modes[i];
+        _userModes[ircuser] = sortedModes[i];
         ircuser->joinChannel(this, true);
         connect(ircuser, SIGNAL(nickSet(QString)), this, SLOT(ircUserNickSet(QString)));
 
@@ -191,7 +203,7 @@ void IrcChannel::joinIrcUsers(const QList<IrcUser *> &users, const QStringList &
         // the joins are propagated by the ircuser. The signal ircUserJoined is only for convenience
 
         newNicks << ircuser->nick();
-        newModes << modes[i];
+        newModes << sortedModes[i];
         newUsers << ircuser;
     }
 
@@ -229,7 +241,7 @@ void IrcChannel::part(IrcUser *ircuser)
         ircuser->partChannel(this);
         // If you wonder why there is no counterpart to ircUserParted:
         // the joins are propagted by the ircuser. The signal ircUserParted is only for convenience
-        disconnect(ircuser, 0, this, 0);
+        disconnect(ircuser, nullptr, this, nullptr);
         emit ircUserParted(ircuser);
 
         if (network()->isMe(ircuser) || _userModes.isEmpty()) {
@@ -238,7 +250,7 @@ void IrcChannel::part(IrcUser *ircuser)
             QList<IrcUser *> users = _userModes.keys();
             _userModes.clear();
             foreach(IrcUser *user, users) {
-                disconnect(user, 0, this, 0);
+                disconnect(user, nullptr, this, nullptr);
                 user->partChannel(this);
             }
             emit parted();
@@ -258,7 +270,8 @@ void IrcChannel::part(const QString &nick)
 void IrcChannel::setUserModes(IrcUser *ircuser, const QString &modes)
 {
     if (isKnownUser(ircuser)) {
-        _userModes[ircuser] = modes;
+        // Keep user modes sorted
+        _userModes[ircuser] = network()->sortPrefixModes(modes);
         QString nick = ircuser->nick();
         SYNC_OTHER(setUserModes, ARG(nick), ARG(modes))
         emit ircUserModesSet(ircuser, modes);
@@ -279,7 +292,8 @@ void IrcChannel::addUserMode(IrcUser *ircuser, const QString &mode)
         return;
 
     if (!_userModes[ircuser].contains(mode)) {
-        _userModes[ircuser] += mode;
+        // Keep user modes sorted
+        _userModes[ircuser] = network()->sortPrefixModes(_userModes[ircuser] + mode);
         QString nick = ircuser->nick();
         SYNC_OTHER(addUserMode, ARG(nick), ARG(mode))
         emit ircUserModeAdded(ircuser, mode);
@@ -300,6 +314,7 @@ void IrcChannel::removeUserMode(IrcUser *ircuser, const QString &mode)
         return;
 
     if (_userModes[ircuser].contains(mode)) {
+        // Removing modes shouldn't mess up ordering
         _userModes[ircuser].remove(mode);
         QString nick = ircuser->nick();
         SYNC_OTHER(removeUserMode, ARG(nick), ARG(mode));
@@ -337,6 +352,7 @@ void IrcChannel::initSetUserModes(const QVariantMap &usermodes)
         modes << iter.value().toString();
         ++iter;
     }
+    // joinIrcUsers handles sorting modes
     joinIrcUsers(users, modes);
 }
 
@@ -547,9 +563,8 @@ bool IrcChannel::hasMode(const QChar &mode) const
         return _C_channelModes.contains(mode);
     case Network::D_CHANMODE:
         return _D_channelModes.contains(mode);
-    default:
-        return false;
     }
+    return false;
 }
 
 
@@ -582,9 +597,11 @@ QStringList IrcChannel::modeValueList(const QChar &mode) const
     case Network::A_CHANMODE:
         if (_A_channelModes.contains(mode))
             return _A_channelModes[mode];
+        break;
     default:
-        return QStringList();
+        ;
     }
+    return {};
 }