Skip to content

Commit

Permalink
common: Port local nicks to NickHighlightMatcher
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
digitalcircuit committed Aug 25, 2018
1 parent 628d03e commit 461a2a5
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 73 deletions.
4 changes: 4 additions & 0 deletions src/client/client.cpp
Expand Up @@ -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)));
Expand Down
65 changes: 17 additions & 48 deletions src/qtui/qtuimessageprocessor.cpp
Expand Up @@ -33,7 +33,10 @@ QtUiMessageProcessor::QtUiMessageProcessor(QObject *parent)
{
NotificationSettings notificationSettings;
_nicksCaseSensitive = notificationSettings.nicksCaseSensitive();
_nickMatcher.setCaseSensitive(_nicksCaseSensitive);
_highlightNick = notificationSettings.highlightNick();
_nickMatcher.setHighlightMode(
static_cast<NickHighlightMatcher::HighlightNickType>(_highlightNick));
highlightListChanged(notificationSettings.highlightList());
notificationSettings.notify("Highlights/NicksCaseSensitive", this, SLOT(nicksCaseSensitiveChanged(const QVariant &)));
notificationSettings.notify("Highlights/CustomList", this, SLOT(highlightListChanged(const QVariant &)));
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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;
}
Expand All @@ -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);
}


Expand All @@ -209,44 +212,10 @@ void QtUiMessageProcessor::highlightListChanged(const QVariant &variant)
void QtUiMessageProcessor::highlightNickChanged(const QVariant &variant)
{
_highlightNick = (NotificationSettings::HighlightNickType)variant.toInt();
_cacheNickConfigInvalid = true;
}


void QtUiMessageProcessor::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 == 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;
// Convert from HighlightRuleManager::HighlightNickType to
// NickHighlightMatcher::HighlightNickType
_nickMatcher.setHighlightMode(
static_cast<NickHighlightMatcher::HighlightNickType>(_highlightNick));
}


Expand Down
42 changes: 17 additions & 25 deletions src/qtui/qtuimessageprocessor.h
Expand Up @@ -25,6 +25,7 @@

#include "abstractmessageprocessor.h"
#include "expressionmatch.h"
#include "nickhighlightmatcher.h"

class QtUiMessageProcessor : public AbstractMessageProcessor
{
Expand All @@ -47,6 +48,18 @@ public slots:
void process(Message &msg);
void process(QList<Message> &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);
Expand Down Expand Up @@ -210,33 +223,12 @@ private slots:

using HighlightNickType = NotificationSettings::HighlightNickType;

/**
* Update internal cache of expression matching if needed
*/
void determineNickExpressions(const QString &currentNick,
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 &currentNick, 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<QList<Message> > _processQueue;
QList<Message> _currentBatch;
Expand Down

0 comments on commit 461a2a5

Please sign in to comment.