common: Port HighlightRule to ExpressionMatch
[quassel.git] / src / common / network.cpp
index c4019cc..dcca4f4 100644 (file)
@@ -18,6 +18,8 @@
  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.         *
  ***************************************************************************/
 
+#include <algorithm>
+
 #include <QTextCodec>
 
 #include "network.h"
@@ -177,6 +179,42 @@ QString Network::modeToPrefix(const QString &mode) const
 }
 
 
+QString Network::sortPrefixModes(const QString &modes) const
+{
+    // If modes is empty or we don't have any modes, nothing can be sorted, bail out early
+    if (modes.isEmpty() || prefixModes().isEmpty()) {
+        return modes;
+    }
+
+    // Store a copy of the modes for modification
+    // QString should be efficient and not copy memory if nothing changes, but if mistaken,
+    // std::is_sorted could be called first.
+    QString sortedModes = QString(modes);
+
+    // Sort modes as if a QChar array
+    // See https://en.cppreference.com/w/cpp/algorithm/sort
+    // Defining lambda with [&] implicitly captures variables by reference
+    std::sort(sortedModes.begin(), sortedModes.end(), [&](const QChar &lmode, const QChar &rmode) {
+        // Compare characters according to prefix modes
+        // Return true if lmode comes before rmode (is "less than")
+
+        // Check for unknown modes...
+        if (!prefixModes().contains(lmode)) {
+            // Left mode not in prefix list, send to end
+            return false;
+        } else if (!prefixModes().contains(rmode)) {
+            // Right mode not in prefix list, send to end
+            return true;
+        } else {
+            // Both characters known, sort according to index in prefixModes()
+            return (prefixModes().indexOf(lmode) < prefixModes().indexOf(rmode));
+        }
+    });
+
+    return sortedModes;
+}
+
+
 QStringList Network::nicks() const
 {
     // we don't use _ircUsers.keys() since the keys may be
@@ -892,16 +930,17 @@ QVariantMap Network::initIrcUsersAndChannels() const
         QHash<QString, IrcUser *>::const_iterator end = _ircUsers.end();
         while (it != end) {
             QVariantMap map = it.value()->toVariantMap();
-            // If the peer doesn't support LongTime, replace the lastAwayMessage field
-            // with the 32-bit numerical seconds value used in older versions
+            // If the peer doesn't support LongTime, replace the lastAwayMessageTime field
+            // with the 32-bit numerical seconds value (lastAwayMessage) used in older versions
             if (!proxy()->targetPeer()->hasFeature(Quassel::Feature::LongTime)) {
 #if QT_VERSION >= 0x050800
-                int lastAwayMessage = it.value()->lastAwayMessage().toSecsSinceEpoch();
+                int lastAwayMessage = it.value()->lastAwayMessageTime().toSecsSinceEpoch();
 #else
                 // toSecsSinceEpoch() was added in Qt 5.8.  Manually downconvert to seconds for now.
                 // See https://doc.qt.io/qt-5/qdatetime.html#toMSecsSinceEpoch
-                int lastAwayMessage = it.value()->lastAwayMessage().toMSecsSinceEpoch() / 1000;
+                int lastAwayMessage = it.value()->lastAwayMessageTime().toMSecsSinceEpoch() / 1000;
 #endif
+                map.remove("lastAwayMessageTime");
                 map["lastAwayMessage"] = lastAwayMessage;
             }
 
@@ -972,19 +1011,19 @@ void Network::initSetIrcUsersAndChannels(const QVariantMap &usersAndChannels)
         foreach(const QString &key, users.keys())
             map[key] = users[key].toList().at(i);
 
-        // If the peer doesn't support LongTime, upconvert the lastAwayMessage field
+        // If the peer doesn't support LongTime, upconvert the lastAwayMessageTime field
         // from the 32-bit numerical seconds value used in older versions to QDateTime
         if (!proxy()->sourcePeer()->hasFeature(Quassel::Feature::LongTime)) {
-            QDateTime lastAwayMessage = QDateTime();
-            lastAwayMessage.setTimeSpec(Qt::UTC);
+            QDateTime lastAwayMessageTime = QDateTime();
+            lastAwayMessageTime.setTimeSpec(Qt::UTC);
 #if QT_VERSION >= 0x050800
-            lastAwayMessage.fromSecsSinceEpoch(map["lastAwayMessage"].toInt());
+            lastAwayMessageTime.fromSecsSinceEpoch(map.take("lastAwayMessage").toInt());
 #else
             // toSecsSinceEpoch() was added in Qt 5.8.  Manually downconvert to seconds for now.
             // See https://doc.qt.io/qt-5/qdatetime.html#toMSecsSinceEpoch
-            lastAwayMessage.fromMSecsSinceEpoch(map["lastAwayMessage"].toInt() * 1000);
+            lastAwayMessageTime.fromMSecsSinceEpoch(map.take("lastAwayMessage").toInt() * 1000);
 #endif
-            map["lastAwayMessage"] = lastAwayMessage;
+            map["lastAwayMessageTime"] = lastAwayMessageTime;
         }
 
         newIrcUser(map["nick"].toString(), map); // newIrcUser() properly handles the hostmask being just the nick