X-Git-Url: https://git.quassel-irc.org/?p=quassel.git;a=blobdiff_plain;f=src%2Fqtui%2Fqtuimessageprocessor.cpp;h=ccde0c3fa0aeb318ecce1e7ee91943e1642ffa64;hp=84deebee27371e1cd58134f4d787fc05738976e1;hb=ddfb1d2574c4bffd180361a80df9b1cd584bb040;hpb=83662b607de9eb742fe9de4dd9445914a6bd9456 diff --git a/src/qtui/qtuimessageprocessor.cpp b/src/qtui/qtuimessageprocessor.cpp index 84deebee..ccde0c3f 100644 --- a/src/qtui/qtuimessageprocessor.cpp +++ b/src/qtui/qtuimessageprocessor.cpp @@ -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 * @@ -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,55 +117,64 @@ 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()) { - QStringList nickList; - if (_highlightNick == NotificationSettings::CurrentNick) { - nickList << net->myNick(); - } - else if (_highlightNick == NotificationSettings::AllNicks) { - const Identity *myIdentity = Client::identity(net->identity()); - if (myIdentity) - nickList = myIdentity->nicks(); - if (!nickList.contains(net->myNick())) - nickList.prepend(net->myNick()); - } - foreach(QString nickname, nickList) { - QRegExp nickRegExp("(^|\\W)" + QRegExp::escape(nickname) + "(\\W|$)", _nicksCaseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive); - if (nickRegExp.indexIn(msg.contents()) >= 0) { - msg.setFlags(msg.flags() | Message::Highlight); - return; - } + // Get current nick + QString currentNick = net->myNick(); + // Get identity nicks + QStringList identityNicks = {}; + const Identity *myIdentity = Client::identity(net->identity()); + if (myIdentity) { + identityNicks = myIdentity->nicks(); } - for (int i = 0; i < _highlightRules.count(); i++) { - const HighlightRule &rule = _highlightRules.at(i); - if (!rule.isEnabled) + // Get buffer name, message contents + QString bufferName = msg.bufferInfo().bufferName(); + QString msgContents = msg.contents(); + bool matches = false; + + for (int i = 0; i < _highlightRuleList.count(); i++) { + auto &rule = _highlightRuleList.at(i); + if (!rule.isEnabled()) continue; - if (rule.chanName.size() > 0 && rule.chanName.compare(".*") != 0) { - if (rule.chanName.startsWith("!")) { - QRegExp rx(rule.chanName.mid(1), Qt::CaseInsensitive); - if (rx.exactMatch(msg.bufferInfo().bufferName())) - continue; - } - else { - QRegExp rx(rule.chanName, Qt::CaseInsensitive); - if (!rx.exactMatch(msg.bufferInfo().bufferName())) - continue; - } + // Skip if channel name doesn't match and channel rule is not empty + // + // Match succeeds if... + // Channel name matches a defined rule + // Defined rule is empty + // And take the inverse of the above + if (!rule.chanNameMatcher().match(bufferName, true)) { + // A channel name rule is specified and does NOT match the current buffer name, skip + // this rule + continue; } - QRegExp rx; - if (rule.isRegExp) { - rx = QRegExp(rule.name, rule.caseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive); - } - else { - rx = QRegExp("(^|\\W)" + QRegExp::escape(rule.name) + "(\\W|$)", rule.caseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive); + // Check message according to specified rule, allowing empty rules to match + bool contentsMatch = rule.contentsMatcher().match(stripFormatCodes(msgContents), true); + + // Support for sender matching can be added here + + if (contentsMatch) { + // Support for inverse rules can be added here + matches = true; } - bool match = (rx.indexIn(msg.contents()) >= 0); - if (match) { + } + + if (matches) { + msg.setFlags(msg.flags() | Message::Highlight); + return; + } + + // Check nicknames + if (_highlightNick != HighlightNickType::NoNick && !currentNick.isEmpty()) { + // 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; } @@ -174,6 +186,8 @@ void QtUiMessageProcessor::checkForHighlight(Message &msg) void QtUiMessageProcessor::nicksCaseSensitiveChanged(const QVariant &variant) { _nicksCaseSensitive = variant.toBool(); + // Update nickname matcher, too + _nickMatcher.setCaseSensitive(_nicksCaseSensitive); } @@ -181,15 +195,15 @@ void QtUiMessageProcessor::highlightListChanged(const QVariant &variant) { QVariantList varList = variant.toList(); - _highlightRules.clear(); + _highlightRuleList.clear(); QVariantList::const_iterator iter = varList.constBegin(); while (iter != varList.constEnd()) { QVariantMap rule = iter->toMap(); - _highlightRules << HighlightRule(rule["Name"].toString(), - rule["Enable"].toBool(), - rule["CS"].toBool() ? Qt::CaseSensitive : Qt::CaseInsensitive, - rule["RegEx"].toBool(), - rule["Channel"].toString()); + _highlightRuleList << LegacyHighlightRule(rule["Name"].toString(), + rule["RegEx"].toBool(), + rule["CS"].toBool(), + rule["Enable"].toBool(), + rule["Channel"].toString()); ++iter; } } @@ -197,5 +211,47 @@ void QtUiMessageProcessor::highlightListChanged(const QVariant &variant) void QtUiMessageProcessor::highlightNickChanged(const QVariant &variant) { - _highlightNick = (NotificationSettings::HighlightNickType)variant.toInt(); + _highlightNick = (HighlightNickType)variant.toInt(); + // Convert from QtUiMessageProcessor::HighlightNickType (which is from NotificationSettings) to + // NickHighlightMatcher::HighlightNickType + _nickMatcher.setHighlightMode( + static_cast(_highlightNick)); +} + + +/************************************************************************** + * LegacyHighlightRule + *************************************************************************/ +bool QtUiMessageProcessor::LegacyHighlightRule::operator!=(const LegacyHighlightRule &other) const +{ + return (_contents != other._contents || + _isRegEx != other._isRegEx || + _isCaseSensitive != other._isCaseSensitive || + _isEnabled != other._isEnabled || + _chanName != other._chanName); + // Don't compare ExpressionMatch objects as they are created as needed from the above +} + + +void QtUiMessageProcessor::LegacyHighlightRule::determineExpressions() const +{ + // Don't update if not needed + if (!_cacheInvalid) { + return; + } + + // Set up matching rules + // Message is either phrase or regex + ExpressionMatch::MatchMode contentsMode = + _isRegEx ? ExpressionMatch::MatchMode::MatchRegEx : + ExpressionMatch::MatchMode::MatchPhrase; + // Sender (when added) and channel are either multiple wildcard entries or regex + ExpressionMatch::MatchMode scopeMode = + _isRegEx ? ExpressionMatch::MatchMode::MatchRegEx : + ExpressionMatch::MatchMode::MatchMultiWildcard; + + _contentsMatch = ExpressionMatch(_contents, contentsMode, _isCaseSensitive); + _chanNameMatch = ExpressionMatch(_chanName, scopeMode, _isCaseSensitive); + + _cacheInvalid = false; }