From 4c4fe2b514fc7ecf3186202d73b3b5ff8847763f Mon Sep 17 00:00:00 2001 From: Shane Synan Date: Sat, 1 Sep 2018 16:37:32 -0500 Subject: [PATCH] common: Port local nicks to NickHighlightMatcher Port QtUiMessageProcessor 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 | 4 ++ src/qtui/qtuimessageprocessor.cpp | 67 +++++++++---------------------- src/qtui/qtuimessageprocessor.h | 42 ++++++++----------- 3 files changed, 39 insertions(+), 74 deletions(-) diff --git a/src/client/client.cpp b/src/client/client.cpp index c20fa8b6..87fa59f8 100644 --- a/src/client/client.cpp +++ b/src/client/client.cpp @@ -168,6 +168,10 @@ void Client::init() connect(this, SIGNAL(connected()), mainUi(), SLOT(connectedToCore())); connect(this, SIGNAL(disconnected()), mainUi(), SLOT(disconnectedFromCore())); + // Listen to network removed events + connect(this, SIGNAL(networkRemoved(NetworkId)), + _messageProcessor, SLOT(networkRemoved(NetworkId))); + // attach backlog manager p->synchronize(backlogManager()); connect(backlogManager(), SIGNAL(messagesReceived(BufferId, int)), _messageModel, SLOT(messagesReceived(BufferId, int))); diff --git a/src/qtui/qtuimessageprocessor.cpp b/src/qtui/qtuimessageprocessor.cpp index f1eb47f6..ccde0c3f 100644 --- a/src/qtui/qtuimessageprocessor.cpp +++ b/src/qtui/qtuimessageprocessor.cpp @@ -33,7 +33,10 @@ QtUiMessageProcessor::QtUiMessageProcessor(QObject *parent) { NotificationSettings notificationSettings; _nicksCaseSensitive = notificationSettings.nicksCaseSensitive(); + _nickMatcher.setCaseSensitive(_nicksCaseSensitive); _highlightNick = notificationSettings.highlightNick(); + _nickMatcher.setHighlightMode( + static_cast(_highlightNick)); highlightListChanged(notificationSettings.highlightList()); notificationSettings.notify("Highlights/NicksCaseSensitive", this, SLOT(nicksCaseSensitiveChanged(const QVariant &))); notificationSettings.notify("Highlights/CustomList", this, SLOT(highlightListChanged(const QVariant &))); @@ -114,8 +117,10 @@ void QtUiMessageProcessor::checkForHighlight(Message &msg) if (!((msg.type() & (Message::Plain | Message::Notice | Message::Action)) && !(msg.flags() & Message::Self))) return; - // TODO: Cache this (per network) - const Network *net = Client::network(msg.bufferInfo().networkId()); + // Cached per network + const NetworkId &netId = msg.bufferInfo().networkId(); + const Network *net = Client::network(netId); + if (net && !net->myNick().isEmpty()) { // Get current nick QString currentNick = net->myNick(); @@ -166,13 +171,10 @@ void QtUiMessageProcessor::checkForHighlight(Message &msg) // 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)) { msg.setFlags(msg.flags() | Message::Highlight); return; } @@ -184,7 +186,8 @@ void QtUiMessageProcessor::checkForHighlight(Message &msg) void QtUiMessageProcessor::nicksCaseSensitiveChanged(const QVariant &variant) { _nicksCaseSensitive = variant.toBool(); - _cacheNickConfigInvalid = true; + // Update nickname matcher, too + _nickMatcher.setCaseSensitive(_nicksCaseSensitive); } @@ -208,45 +211,11 @@ void QtUiMessageProcessor::highlightListChanged(const QVariant &variant) void QtUiMessageProcessor::highlightNickChanged(const QVariant &variant) { - _highlightNick = (NotificationSettings::HighlightNickType)variant.toInt(); - _cacheNickConfigInvalid = true; -} - - -void QtUiMessageProcessor::determineNickExpressions(const QString ¤tNick, - 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 == HighlightNickType::CurrentNick) { - nickList << currentNick; - } - else if (_highlightNick == HighlightNickType::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; + _highlightNick = (HighlightNickType)variant.toInt(); + // Convert from QtUiMessageProcessor::HighlightNickType (which is from NotificationSettings) to + // NickHighlightMatcher::HighlightNickType + _nickMatcher.setHighlightMode( + static_cast(_highlightNick)); } diff --git a/src/qtui/qtuimessageprocessor.h b/src/qtui/qtuimessageprocessor.h index d8559d36..6a9684f7 100644 --- a/src/qtui/qtuimessageprocessor.h +++ b/src/qtui/qtuimessageprocessor.h @@ -25,6 +25,7 @@ #include "abstractmessageprocessor.h" #include "expressionmatch.h" +#include "nickhighlightmatcher.h" class QtUiMessageProcessor : public AbstractMessageProcessor { @@ -47,6 +48,18 @@ public slots: void process(Message &msg); void process(QList &msgs); + /** + * 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); + } + private slots: void processNextMessage(); void nicksCaseSensitiveChanged(const QVariant &variant); @@ -239,33 +252,12 @@ private: using HighlightNickType = NotificationSettings::HighlightNickType; - /** - * Update internal cache of expression matching if needed - */ - void determineNickExpressions(const QString ¤tNick, - const QStringList identityNicks) const; + LegacyHighlightRuleList _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 ¤tNick, const QStringList identityNicks) const { - if (_cacheNickConfigInvalid) return true; - if (_cachedNickCurrent != currentNick) return true; - if (_cachedIdentityNicks != identityNicks) return true; - } - - LegacyHighlightRuleList _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 QList > _processQueue; QList _currentBatch; -- 2.20.1