common: Port remote nicks to NickHighlightMatcher
authorShane Synan <digitalcircuit36939@gmail.com>
Sat, 1 Sep 2018 21:36:45 +0000 (16:36 -0500)
committerManuel Nickschas <sputnick@quassel-irc.org>
Mon, 3 Sep 2018 20:12:02 +0000 (22:12 +0200)
Port HighlightRuleManager nick highlights to NickHighlightMatcher
class, providing easy caching and simplifying expression handling.

This fixes nickname caching being reset when switching between
networks.

Add SIGNAL/SLOT traversal to pass on information about network
removal to clean up per-network nickname highlight caches, avoiding
memory leaks.

src/client/client.cpp
src/common/highlightrulemanager.cpp
src/common/highlightrulemanager.h
src/core/corehighlightrulemanager.cpp
src/core/coresession.cpp

index 23b838f..c20fa8b 100644 (file)
@@ -444,6 +444,9 @@ void Client::setSyncedToCore()
     Q_ASSERT(!_highlightRuleManager);
     _highlightRuleManager = new HighlightRuleManager(this);
     p->synchronize(highlightRuleManager());
+    // Listen to network removed events
+    connect(this, SIGNAL(networkRemoved(NetworkId)),
+        _highlightRuleManager, SLOT(networkRemoved(NetworkId)));
 
 /*  not ready yet
     // create TransferManager and DccConfig if core supports them
index c9c4cfc..d3c2384 100644 (file)
@@ -141,13 +141,14 @@ void HighlightRuleManager::addHighlightRule(int id, const QString &name, bool is
 }
 
 
-bool HighlightRuleManager::match(const QString &msgContents,
+bool HighlightRuleManager::match(const NetworkId &netId,
+                                 const QString &msgContents,
                                  const QString &msgSender,
                                  Message::Type msgType,
                                  Message::Flags msgFlags,
                                  const QString &bufferName,
                                  const QString &currentNick,
-                                 const QStringList identityNicks)
+                                 const QStringList &identityNicks)
 {
     if (!((msgType & (Message::Plain | Message::Notice | Message::Action)) && !(msgFlags & Message::Self))) {
        return false;
@@ -194,13 +195,9 @@ bool HighlightRuleManager::match(const QString &msgContents,
 
     // Check nicknames
     if (_highlightNick != HighlightNickType::NoNick && !currentNick.isEmpty()) {
-        // Update cache if needed
-        determineNickExpressions(currentNick, identityNicks);
-
-        // Check for a match
-        if (_cachedNickMatcher.isValid()
-                && _cachedNickMatcher.match(stripFormatCodes(msgContents))) {
-            // Nick matcher is valid and match found
+        // Nickname matching allowed and current nickname is known
+        // Run the nickname matcher on the unformatted string
+        if (_nickMatcher.match(stripFormatCodes(msgContents), netId, currentNick, identityNicks)) {
             return true;
         }
     }
@@ -228,44 +225,8 @@ void HighlightRuleManager::toggleHighlightRule(int highlightRule)
 
 bool HighlightRuleManager::match(const Message &msg, const QString &currentNick, const QStringList &identityNicks)
 {
-    return match(msg.contents(), msg.sender(), msg.type(), msg.flags(), msg.bufferInfo().bufferName(), currentNick, identityNicks);
-}
-
-
-void HighlightRuleManager::determineNickExpressions(const QString &currentNick,
-                                                    const QStringList identityNicks) const
-{
-    // Don't do anything for no nicknames
-    if (_highlightNick == HighlightNickType::NoNick) {
-        return;
-    }
-
-    // Only update if needed (check nickname config, current nick, identity nicks for change)
-    if (!_cacheNickConfigInvalid
-          && _cachedNickCurrent == currentNick
-          && _cachedIdentityNicks == identityNicks) {
-        return;
-    }
-
-    // Add all nicknames
-    QStringList nickList;
-    if (_highlightNick == CurrentNick) {
-        nickList << currentNick;
-    }
-    else if (_highlightNick == AllNicks) {
-        nickList = identityNicks;
-        if (!nickList.contains(currentNick))
-            nickList.prepend(currentNick);
-    }
-
-    // Set up phrase matcher, joining with newlines
-    _cachedNickMatcher = ExpressionMatch(nickList.join("\n"),
-                                        ExpressionMatch::MatchMode::MatchMultiPhrase,
-                                        _nicksCaseSensitive);
-
-    _cacheNickConfigInvalid = false;
-    _cachedNickCurrent = currentNick;
-    _cachedIdentityNicks = identityNicks;
+    return match(msg.bufferInfo().networkId(), msg.contents(), msg.sender(), msg.type(), msg.flags(),
+                 msg.bufferInfo().bufferName(), currentNick, identityNicks);
 }
 
 
index cabf0d2..d98c867 100644 (file)
@@ -29,6 +29,7 @@
 
 #include "expressionmatch.h"
 #include "message.h"
+#include "nickhighlightmatcher.h"
 #include "syncableobject.h"
 
 class HighlightRuleManager : public SyncableObject
@@ -364,7 +365,10 @@ public slots:
 
     inline void setHighlightNick(int highlightNick) {
         _highlightNick = static_cast<HighlightNickType>(highlightNick);
-        _cacheNickConfigInvalid = true;
+        // Convert from HighlightRuleManager::HighlightNickType to
+        // NickHighlightMatcher::HighlightNickType
+        _nickMatcher.setHighlightMode(
+                    static_cast<NickHighlightMatcher::HighlightNickType>(_highlightNick));
     }
 
     virtual inline void requestSetNicksCaseSensitive(bool nicksCaseSensitive)
@@ -374,49 +378,42 @@ public slots:
 
     inline void setNicksCaseSensitive(bool nicksCaseSensitive) {
         _nicksCaseSensitive = nicksCaseSensitive;
-        _cacheNickConfigInvalid = true;
+        // Update nickname matcher, too
+        _nickMatcher.setCaseSensitive(nicksCaseSensitive);
+    }
+
+    /**
+     * Network removed from system
+     *
+     * Handles cleaning up cache from stale networks.
+     *
+     * @param id Network ID of removed network
+     */
+    inline void networkRemoved(NetworkId id) {
+        // Clean up nickname matching cache
+        _nickMatcher.removeNetwork(id);
     }
 
 protected:
     void setHighlightRuleList(const QList<HighlightRule> &HighlightRuleList) { _highlightRuleList = HighlightRuleList; }
 
-    bool match(const QString &msgContents,
+    bool match(const NetworkId &netId,
+               const QString &msgContents,
                const QString &msgSender,
                Message::Type msgType,
                Message::Flags msgFlags,
                const QString &bufferName,
                const QString &currentNick,
-               const QStringList identityNicks);
+               const QStringList &identityNicks);
 
 signals:
     void ruleAdded(QString name, bool isRegEx, bool isCaseSensitive, bool isEnabled, bool isInverse, QString sender, QString chanName);
 
 private:
-    /**
-     * Update internal cache of expression matching if needed
-     */
-    void determineNickExpressions(const QString &currentNick,
-                                  const QStringList identityNicks) const;
+    HighlightRuleList _highlightRuleList = {}; ///< Custom highlight rule list
+    NickHighlightMatcher _nickMatcher = {};    ///< Nickname highlight matcher
 
-    /**
-     * Check if nickname matching cache is invalid
-     * @param currentNick
-     * @param identityNicks
-     * @return
-     */
-    bool cacheNickInvalid(const QString &currentNick, const QStringList identityNicks) const {
-        if (_cacheNickConfigInvalid) return true;
-        if (_cachedNickCurrent != currentNick) return true;
-        if (_cachedIdentityNicks != identityNicks) return true;
-    }
-
-    HighlightRuleList _highlightRuleList;
+    /// Nickname highlighting mode
     HighlightNickType _highlightNick = HighlightNickType::CurrentNick;
-    bool _nicksCaseSensitive = false;
-
-    // These represent internal cache and should be safe to mutate in 'const' functions
-    mutable bool _cacheNickConfigInvalid = true;     ///< If true, nick match cache needs redone
-    mutable QString _cachedNickCurrent = {};         ///< Last cached current nick
-    mutable QStringList _cachedIdentityNicks = {};   ///< Last cached identity nicks
-    mutable ExpressionMatch _cachedNickMatcher = {}; ///< Expression match cache for nicks
+    bool _nicksCaseSensitive = false; ///< If true, match nicknames with exact case
 };
index eed5655..b9c81be 100644 (file)
@@ -48,5 +48,6 @@ void CoreHighlightRuleManager::save()
 bool CoreHighlightRuleManager::match(const RawMessage &msg, const QString &currentNick,
                                      const QStringList &identityNicks)
 {
-    return match(msg.text, msg.sender, msg.type, msg.flags, msg.target, currentNick, identityNicks);
+    return match(msg.networkId, msg.text, msg.sender, msg.type, msg.flags, msg.target, currentNick,
+                 identityNicks);
 }
index 200fadc..359c365 100644 (file)
@@ -142,6 +142,9 @@ CoreSession::CoreSession(UserId uid, bool restoreState, bool strictIdentEnabled,
     p->synchronize(_coreInfo);
     p->synchronize(&_ignoreListManager);
     p->synchronize(&_highlightRuleManager);
+    // Listen to network removed events
+    connect(this, SIGNAL(networkRemoved(NetworkId)),
+        &_highlightRuleManager, SLOT(networkRemoved(NetworkId)));
     p->synchronize(transferManager());
     // Restore session state
     if (restoreState)