modernize: Replace most remaining old-style connects by PMF ones
[quassel.git] / src / common / nickhighlightmatcher.h
1 /***************************************************************************
2  *   Copyright (C) 2005-2018 by the Quassel Project                        *
3  *   devel@quassel-irc.org                                                 *
4  *                                                                         *
5  *   This program is free software; you can redistribute it and/or modify  *
6  *   it under the terms of the GNU General Public License as published by  *
7  *   the Free Software Foundation; either version 2 of the License, or     *
8  *   (at your option) version 3.                                           *
9  *                                                                         *
10  *   This program is distributed in the hope that it will be useful,       *
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
13  *   GNU General Public License for more details.                          *
14  *                                                                         *
15  *   You should have received a copy of the GNU General Public License     *
16  *   along with this program; if not, write to the                         *
17  *   Free Software Foundation, Inc.,                                       *
18  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.         *
19  ***************************************************************************/
20
21 #pragma once
22
23 #include "common-export.h"
24
25 #include <QHash>
26 #include <QString>
27 #include <QStringList>
28
29 #include "expressionmatch.h"
30 #include "types.h"
31
32 /**
33  * Nickname matcher with automatic caching for performance
34  */
35 class COMMON_EXPORT NickHighlightMatcher
36 {
37 public:
38     /// Nickname highlighting mode
39     enum class HighlightNickType {
40         NoNick = 0x00,      ///< Don't match any nickname
41         CurrentNick = 0x01, ///< Match the current nickname
42         AllNicks = 0x02     ///< Match all configured nicknames in the chosen identity
43     };
44     // NOTE: Keep this in sync with HighlightRuleManager::HighlightNickType and
45     // NotificationSettings::HighlightNickType!
46
47     /**
48      * Construct an empty NicknameMatcher
49      */
50     NickHighlightMatcher() = default;
51
52     /**
53      * Construct a configured NicknameMatcher
54      *
55      * @param highlightMode    Nickname highlighting mode
56      * @param isCaseSensitive  If true, nick matching is case-sensitive, otherwise case-insensitive
57      */
58     NickHighlightMatcher(HighlightNickType highlightMode, bool isCaseSensitive)
59         : _highlightMode(highlightMode),
60           _isCaseSensitive(isCaseSensitive) {}
61
62     /**
63      * Gets the nickname highlighting policy
64      *
65      * @return HighlightNickType for the given network
66      */
67     inline HighlightNickType highlightMode() const { return _highlightMode; }
68
69     /**
70      * Sets the nickname highlighting policy
71      *
72      * @param highlightMode Nickname highlighting mode
73      */
74     void setHighlightMode(HighlightNickType highlightMode) {
75         if (_highlightMode != highlightMode) {
76             _highlightMode = highlightMode;
77             invalidateNickCache();
78         }
79     }
80
81     /**
82      * Gets the nickname case-sensitivity policy
83      *
84      * @return True if nickname highlights are case-sensitive, otherwise false
85      */
86     inline bool isCaseSensitive() const { return _isCaseSensitive; }
87
88     /**
89      * Sets the nickname case-sensitivity policy
90      *
91      * @param isCaseSensitive If true, nick matching is case-sensitive, otherwise case-insensitive
92      */
93     void setCaseSensitive(bool isCaseSensitive) {
94         if (_isCaseSensitive != isCaseSensitive) {
95             _isCaseSensitive = isCaseSensitive;
96             invalidateNickCache();
97         }
98     }
99
100     /**
101      * Checks if the given string matches the specified network's nickname matcher
102      *
103      * Updates cache when called if needed.
104      *
105      * @param string         String to match against
106      * @param netId          Network ID of source network
107      * @param currentNick    Current nickname
108      * @param identityNicks  All nicknames configured for the current identity
109      * @return True if match found, otherwise false
110      */
111     bool match(const QString &string, const NetworkId &netId, const QString &currentNick,
112                const QStringList &identityNicks) const;
113
114 public slots:
115     /**
116      * Removes the specified network ID from the cache
117      *
118      * @param netId Network ID of source network
119      */
120     void removeNetwork(const NetworkId &netId) {
121         // Remove the network from the cache list
122         if (_nickMatchCache.remove(netId) > 0) {
123             qDebug() << "Cleared nickname matching cache for removed network ID" << netId;
124         }
125     }
126
127 private:
128     struct NickMatchCache {
129         // These represent internal cache and should be safe to mutate in 'const' functions
130         QString nickCurrent = {};        ///< Last cached current nick
131         QStringList identityNicks = {};  ///< Last cached identity nicks
132         ExpressionMatch matcher = {};    ///< Expression match cache for nicks
133     };
134
135     /**
136      * Update internal cache of nickname matching if needed
137      *
138      * @param netId          Network ID of source network
139      * @param currentNick    Current nickname
140      * @param identityNicks  All nicknames configured for the current identity
141      */
142     void determineExpressions(const NetworkId &netId, const QString &currentNick,
143                               const QStringList &identityNicks) const;
144
145     /**
146      * Invalidate all nickname match caches
147      *
148      * Use this after changing global configuration.
149      */
150     inline void invalidateNickCache() {
151         // Mark all as invalid
152         if (_nickMatchCache.size() > 0) {
153             _nickMatchCache.clear();
154             qDebug() << "Cleared all nickname matching cache (settings changed)";
155         }
156     }
157
158     // Global nickname configuration
159     /// Nickname highlighting mode
160     HighlightNickType _highlightMode = HighlightNickType::CurrentNick;
161     bool _isCaseSensitive = false;  ///< If true, match nicknames with exact case
162
163     // These represent internal cache and should be safe to mutate in 'const' functions
164     mutable QHash<NetworkId, NickMatchCache> _nickMatchCache; ///< Per-network nick matching cache
165
166 };