common: Apply RegEx, CS column to sender, channel
authorShane Synan <digitalcircuit36939@gmail.com>
Mon, 28 May 2018 20:33:05 +0000 (15:33 -0500)
committerManuel Nickschas <sputnick@quassel-irc.org>
Wed, 6 Jun 2018 17:15:14 +0000 (19:15 +0200)
Modify scopeMatch to optionally treat the rule as a regular
expression, and to treat it as case-sensitive or not.

Modify highlight rule processing to...
* Use scopeMatch for "Sender", allowing easy multi-sender rules
* Treat both "Sender" and "Channel" as regular expressions if "RegEx"
  is checked, allowing for full regular expression power.
  (Breaks existing rules with RegEx matching, but in a different way)

This means it is no longer possible to use RegEx matching for the
"Sender" and "Channel" yet not on the phrase itself.  However, it
should be easy enough to work around this by using the same phrase
regular expression Quassel does.

This should simplify common highlight rules without limiting those
who know regular expressions.  Win-win, hopefully?

Update tooltips to reflect these changes.

src/client/clientignorelistmanager.cpp
src/common/highlightrulemanager.cpp
src/common/ignorelistmanager.cpp
src/common/util.cpp
src/common/util.h
src/qtui/qtuimessageprocessor.cpp
src/qtui/settingspages/corehighlightsettingspage.cpp
src/qtui/settingspages/highlightsettingspage.cpp
src/qtui/settingspages/ignorelisteditdlg.ui

index 96216e1..2f112ef 100644 (file)
@@ -50,8 +50,8 @@ QMap<QString, bool> ClientIgnoreListManager::matchingRulesForHostmask(const QStr
     QMap<QString, bool> result;
     foreach(IgnoreListItem item, ignoreList()) {
         if (item.type == SenderIgnore && pureMatch(item, hostmask)
-            && ((network.isEmpty() && channel.isEmpty()) || item.scope == GlobalScope || (item.scope == NetworkScope && scopeMatch(item.scopeRule, network))
-                || (item.scope == ChannelScope && scopeMatch(item.scopeRule, channel)))) {
+            && ((network.isEmpty() && channel.isEmpty()) || item.scope == GlobalScope || (item.scope == NetworkScope && scopeMatch(network, item.scopeRule))
+                || (item.scope == ChannelScope && scopeMatch(channel, item.scopeRule)))) {
             result[item.ignoreRule] = item.isActive;
 //      qDebug() << "matchingRulesForHostmask found: " << item.ignoreRule << "is active: " << item.isActive;
         }
index 21b8932..3fe3691 100644 (file)
@@ -145,7 +145,8 @@ bool HighlightRuleManager::match(const QString &msgContents,
         if (!rule.isEnabled)
             continue;
 
-        if (!rule.chanName.isEmpty() && !scopeMatch(rule.chanName, bufferName)) {
+        if (!rule.chanName.isEmpty()
+                && !scopeMatch(bufferName, rule.chanName, rule.isRegEx, rule.isCaseSensitive)) {
             // A channel name rule is specified and does NOT match the current buffer name, skip
             // this rule
             continue;
@@ -163,12 +164,8 @@ bool HighlightRuleManager::match(const QString &msgContents,
         if (rule.sender.isEmpty()) {
             senderMatch = true;
         } else {
-            if (rule.isRegEx) {
-                rx = QRegExp(rule.sender, rule.isCaseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive);
-            } else {
-                rx = QRegExp(rule.sender, Qt::CaseInsensitive, QRegExp::Wildcard);
-            }
-            senderMatch = rx.exactMatch(msgSender);
+            // A sender name rule is specified, match according to scope rules.
+            senderMatch = scopeMatch(msgSender, rule.sender, rule.isRegEx, rule.isCaseSensitive);
         }
 
         if (nameMatch && senderMatch) {
index e2e515c..b01273e 100644 (file)
@@ -136,8 +136,8 @@ IgnoreListManager::StrictnessType IgnoreListManager::_match(const QString &msgCo
         if (!item.isActive || item.type == CtcpIgnore)
             continue;
         if (item.scope == GlobalScope
-            || (item.scope == NetworkScope && scopeMatch(item.scopeRule, network))
-            || (item.scope == ChannelScope && scopeMatch(item.scopeRule, bufferName))) {
+            || (item.scope == NetworkScope && scopeMatch(network, item.scopeRule))
+            || (item.scope == ChannelScope && scopeMatch(bufferName, item.scopeRule))) {
             QString str;
             if (item.type == MessageIgnore)
                 str = msgContents;
@@ -182,7 +182,7 @@ bool IgnoreListManager::ctcpMatch(const QString sender, const QString &network,
     foreach(IgnoreListItem item, _ignoreList) {
         if (!item.isActive)
             continue;
-        if (item.scope == GlobalScope || (item.scope == NetworkScope && scopeMatch(item.scopeRule, network))) {
+        if (item.scope == GlobalScope || (item.scope == NetworkScope && scopeMatch(network, item.scopeRule))) {
             QString sender_;
             QStringList types = item.ignoreRule.split(QRegExp("\\s+"), QString::SkipEmptyParts);
 
index da3ea10..b42f4fb 100644 (file)
@@ -282,57 +282,84 @@ QString formatCurrentDateTimeInString(const QString &formatStr)
 }
 
 
-bool scopeMatch(const QString &scopeRule, const QString &string)
+bool scopeMatch(const QString &string, const QString &scopeRule, const bool &isRegEx,
+                const bool &isCaseSensitive)
 {
+    // When isRegEx is false:
     // A match happens when the string does NOT match ANY inverted rules and matches AT LEAST one
     // normal rule, unless no normal rules exist (implicit wildcard match).  This gives inverted
     // rules higher priority regardless of ordering.
     //
+    // When isRegEx is true:
+    // A match happens when the normal regular expression matches.  If prefixed with '!', the match
+    // happens UNLESS the following regular expression matches.
+
     // TODO: After switching to Qt 5, use of this should be split into two parts, one part that
     // would generate compiled QRegularExpressions for match/inverted match, regenerating it on any
     // rule changes, and another part that would check each message against these compiled rules.
 
-    // Keep track if any matches are found
-    bool matches = false;
-    // Keep track if normal rules and inverted rules are found, allowing for implicit wildcard
-    bool normalRuleFound = false, invertedRuleFound = false;
-
-    // Split each scope rule by separator, ignoring empty parts
-    foreach(QString rule, scopeRule.split(";", QString::SkipEmptyParts)) {
-        // Trim whitespace from the start/end of the rule
-        rule = rule.trimmed();
-        // Ignore empty rules
-        if (rule.isEmpty())
-            continue;
+    // Cache case sensitivity
+    Qt::CaseSensitivity ruleExactCase = (isCaseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive);
 
+    if (isRegEx) {
+        // Regular expression tests
+        // -------
         // Check if this is an inverted rule (starts with '!')
-        if (rule.startsWith("!")) {
-            // Inverted rule found
-            invertedRuleFound = true;
-
+        if (scopeRule.startsWith("!")) {
             // Take the reminder of the string
-            QRegExp ruleRx(rule.mid(1), Qt::CaseInsensitive);
-            ruleRx.setPatternSyntax(QRegExp::Wildcard);
-            if (ruleRx.exactMatch(string)) {
-                // Matches an inverted rule, full rule cannot match
-                return false;
-            }
+            QRegExp ruleRx(scopeRule.mid(1), ruleExactCase);
+            // Matching an inverted rule: matched (true) implies rule failure (false)
+            return !ruleRx.exactMatch(string);
         } else {
-            // Normal rule found
-            normalRuleFound = true;
-
-            QRegExp ruleRx(rule, Qt::CaseInsensitive);
-            ruleRx.setPatternSyntax(QRegExp::Wildcard);
-            if (ruleRx.exactMatch(string)) {
-                // Matches a normal rule, full rule might match
-                matches = true;
-                // Continue checking in case other inverted rules negate this
+            QRegExp ruleRx(scopeRule, ruleExactCase);
+            // Matching a normal rule: matched (true) implies rule success (true)
+            return ruleRx.exactMatch(string);
+        }
+    } else {
+        // Wildcard expression tests
+        // -------
+        // Keep track if any matches are found
+        bool matches = false;
+        // Keep track if normal rules and inverted rules are found, allowing for implicit wildcard
+        bool normalRuleFound = false, invertedRuleFound = false;
+
+        // Split each scope rule by separator, ignoring empty parts
+        foreach(QString rule, scopeRule.split(";", QString::SkipEmptyParts)) {
+            // Trim whitespace from the start/end of the rule
+            rule = rule.trimmed();
+            // Ignore empty rules
+            if (rule.isEmpty())
+                continue;
+
+            // Check if this is an inverted rule (starts with '!')
+            if (rule.startsWith("!")) {
+                // Inverted rule found
+                invertedRuleFound = true;
+
+                // Take the reminder of the string
+                QRegExp ruleRx(rule.mid(1), ruleExactCase);
+                ruleRx.setPatternSyntax(QRegExp::Wildcard);
+                if (ruleRx.exactMatch(string)) {
+                    // Matches an inverted rule, full rule cannot match
+                    return false;
+                }
+            } else {
+                // Normal rule found
+                normalRuleFound = true;
+
+                QRegExp ruleRx(rule, ruleExactCase);
+                ruleRx.setPatternSyntax(QRegExp::Wildcard);
+                if (ruleRx.exactMatch(string)) {
+                    // Matches a normal rule, full rule might match
+                    matches = true;
+                    // Continue checking in case other inverted rules negate this
+                }
             }
         }
+        // No inverted rules matched, okay to match normally
+        // Return true if...
+        // ...we found a normal match
+        // ...implicit wildcard: we had inverted rules (that didn't match) and no normal rules
+        return matches || (invertedRuleFound && !normalRuleFound);
     }
-    // No inverted rules matched, okay to match normally
-    // Return true if...
-    // ...we found a normal match
-    // ...implicit wildcard: we had inverted rules (that didn't match) and no normal rules
-    return matches || (invertedRuleFound && !normalRuleFound);
 }
index 85d7910..8b312f9 100644 (file)
@@ -82,14 +82,22 @@ QString formatCurrentDateTimeInString(const QString &formatStr);
 
 /** Check if a scope rule matches a string
  *
+ * When isRegEx is false:
  * Checks that the string does NOT match ANY inverted rules (prefixed by '!'), then checks that
  * it matches AT LEAST one normal (non-inverted) rule.
  *
  * If only inverted rules are specified, it'll match so long as the string does not match any
  * inverted rules (implicit wildcard).
  *
- * @param scopeRule  A ';'-separated list of wildcard expressions, prefix of '!' inverts subrule
- * @param string     String to test, e.g. network/channel name
+ * When isRegEx is true:
+ * Checks that the string matches the entire scopeRule as a regular expression.  If scopeRule starts
+ * with a '!', check that the string does NOT match the regular expression.
+ *
+ * @param string           String to test, e.g. network/channel name
+ * @param scopeRule        ';'-separated list of wildcard expressions, prefix of '!' inverts subrule
+ * @param isRegEx          If true, treat entire scope rule as regular expression, not wildcards
+ * @param isCaseSensitive  If true, treat as case-sensitive, else case-insensitive
  * @return True if matches, otherwise false
  */
-bool scopeMatch(const QString &scopeRule, const QString &string);
+bool scopeMatch(const QString &string, const QString &scopeRule,
+                const bool &isRegEx = false, const bool &isCaseSensitive = false);
index 76415cc..0e0dca5 100644 (file)
@@ -142,7 +142,8 @@ void QtUiMessageProcessor::checkForHighlight(Message &msg)
                 continue;
 
             if (!rule.chanName.isEmpty()
-                    && !scopeMatch(rule.chanName, msg.bufferInfo().bufferName())) {
+                    && !scopeMatch(msg.bufferInfo().bufferName(), rule.chanName,
+                                   rule.isRegExp, rule.caseSensitive)) {
                 // A channel name rule is specified and does NOT match the current buffer name, skip
                 // this rule
                 continue;
index 68d6017..78805cf 100644 (file)
@@ -105,29 +105,57 @@ void CoreHighlightSettingsPage::setupRuleTable(QTableWidget *table) const
     table->verticalHeader()->hide();
     table->setShowGrid(false);
 
+    table->horizontalHeaderItem(CoreHighlightSettingsPage::EnableColumn)->setToolTip(
+                tr("Enable/disable this rule"));
+    table->horizontalHeaderItem(CoreHighlightSettingsPage::EnableColumn)->setWhatsThis(
+                table->horizontalHeaderItem(CoreHighlightSettingsPage::EnableColumn)->toolTip());
+
+    table->horizontalHeaderItem(CoreHighlightSettingsPage::NameColumn)->setToolTip(
+                tr("Phrase to match"));
+    table->horizontalHeaderItem(CoreHighlightSettingsPage::NameColumn)->setWhatsThis(
+                table->horizontalHeaderItem(CoreHighlightSettingsPage::NameColumn)->toolTip());
+
     table->horizontalHeaderItem(CoreHighlightSettingsPage::RegExColumn)->setToolTip(
-                tr("<b>RegEx</b>: This option determines if the highlight rule should be "
-                   "interpreted as a <b>regular expression</b> or just as a keyword."));
+                tr("<b>RegEx</b>: This option determines if the highlight rule, <i>Sender</i>, and "
+                   "<i>Channel</i> should be interpreted as <b>regular expressions</b> or just as "
+                   "keywords."));
     table->horizontalHeaderItem(CoreHighlightSettingsPage::RegExColumn)->setWhatsThis(
                 table->horizontalHeaderItem(CoreHighlightSettingsPage::RegExColumn)->toolTip());
 
     table->horizontalHeaderItem(CoreHighlightSettingsPage::CsColumn)->setToolTip(
-                tr("<b>CS</b>: This option determines if the highlight rule should be interpreted "
-                   "<b>case sensitive</b>."));
+                tr("<b>CS</b>: This option determines if the highlight rule, <i>Sender</i>, and "
+                   "<i>Channel</i> should be interpreted <b>case sensitive</b>."));
     table->horizontalHeaderItem(CoreHighlightSettingsPage::CsColumn)->setWhatsThis(
                 table->horizontalHeaderItem(CoreHighlightSettingsPage::CsColumn)->toolTip());
 
+    table->horizontalHeaderItem(CoreHighlightSettingsPage::SenderColumn)->setToolTip(
+                tr("<p><b>Sender</b>: Semicolon separated list of <i>nick!ident@host</i> names, "
+                   "leave blank to match any nickname.</p>"
+                   "<p><i>Example:</i><br />"
+                   "<i>Alice!*; Bob!*@example.com; Carol*!*; !Caroline!*</i><br />"
+                   "would match on <i>Alice</i>, <i>Bob</i> with hostmask <i>example.com</i>, and "
+                   "any nickname starting with <i>Carol</i> except for <i>Caroline</i><br />"
+                   "<p>If only inverted names are specified, it will match anything except for "
+                   "what's specified (implicit wildcard).</p>"
+                   "<p><i>Example:</i><br />"
+                   "<i>!Announce*!*; !Wheatley!aperture@*</i><br />"
+                   "would match anything except for <i>Wheatley</i> with ident <i>aperture</i> or "
+                   "any nickname starting with <i>Announce</i></p>"));
+    table->horizontalHeaderItem(CoreHighlightSettingsPage::SenderColumn)->setWhatsThis(
+                table->horizontalHeaderItem(CoreHighlightSettingsPage::SenderColumn)->toolTip());
+
     table->horizontalHeaderItem(CoreHighlightSettingsPage::ChanColumn)->setToolTip(
-                tr("<p><b>Channel</b>: Semicolon separated list of channel names.</p>"
+                tr("<p><b>Channel</b>: Semicolon separated list of channel names, leave blank to "
+                   "match any name.</p>"
                    "<p><i>Example:</i><br />"
                    "<i>#quassel*; #foobar; !#quasseldroid</i><br />"
-                   "would match on #foobar and on any channel starting with <i>#quassel</i> except "
-                   "for <i>#quasseldroid</i><br />"
+                   "would match on <i>#foobar</i> and any channel starting with <i>#quassel</i> "
+                   "except for <i>#quasseldroid</i><br />"
                    "<p>If only inverted names are specified, it will match anything except for "
                    "what's specified (implicit wildcard).</p>"
                    "<p><i>Example:</i><br />"
                    "<i>!#quassel*; !#foobar</i><br />"
-                   "would match anything except for #foobar or any channel starting with "
+                   "would match anything except for <i>#foobar</i> or any channel starting with "
                    "<i>#quassel</i></p>"));
     table->horizontalHeaderItem(CoreHighlightSettingsPage::ChanColumn)->setWhatsThis(
                 table->horizontalHeaderItem(CoreHighlightSettingsPage::ChanColumn)->toolTip());
@@ -221,32 +249,44 @@ void CoreHighlightSettingsPage::addNewHighlightRow(bool enable, const QString &n
         enableItem->setCheckState(Qt::Unchecked);
     enableItem->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
 
-    auto *chanNameItem = new QTableWidgetItem(chanName);
-
     auto *senderItem = new QTableWidgetItem(sender);
 
+    auto *chanNameItem = new QTableWidgetItem(chanName);
+
     enableItem->setToolTip(tr("Enable/disable this rule"));
     nameItem->setToolTip(tr("Phrase to match"));
     regexItem->setToolTip(
-                tr("<b>RegEx</b>: This option determines if the highlight rule should be "
-                   "interpreted as a <b>regular expression</b> or just as a keyword."));
+                tr("<b>RegEx</b>: This option determines if the highlight rule, <i>Sender</i>, and "
+                   "<i>Channel</i> should be interpreted as <b>regular expressions</b> or just as "
+                   "keywords."));
     csItem->setToolTip(
-                tr("<b>CS</b>: This option determines if the highlight rule should be interpreted "
-                   "<b>case sensitive</b>."));
+                tr("<b>CS</b>: This option determines if the highlight rule, <i>Sender</i>, and "
+                   "<i>Channel</i> should be interpreted <b>case sensitive</b>."));
     senderItem->setToolTip(
-                tr("<b>Sender</b>: This option specifies which sender to match.  Leave blank to "
-                   "match any nickname."));
+                tr("<p><b>Sender</b>: Semicolon separated list of <i>nick!ident@host</i> names, "
+                   "leave blank to match any nickname.</p>"
+                   "<p><i>Example:</i><br />"
+                   "<i>Alice!*; Bob!*@example.com; Carol*!*; !Caroline!*</i><br />"
+                   "would match on <i>Alice</i>, <i>Bob</i> with hostmask <i>example.com</i>, and "
+                   "any nickname starting with <i>Carol</i> except for <i>Caroline</i><br />"
+                   "<p>If only inverted names are specified, it will match anything except for "
+                   "what's specified (implicit wildcard).</p>"
+                   "<p><i>Example:</i><br />"
+                   "<i>!Announce*!*; !Wheatley!aperture@*</i><br />"
+                   "would match anything except for <i>Wheatley</i> with ident <i>aperture</i> or "
+                   "any nickname starting with <i>Announce</i></p>"));
     chanNameItem->setToolTip(
-                tr("<p><b>Channel</b>: Semicolon separated list of channel names.</p>"
+                tr("<p><b>Channel</b>: Semicolon separated list of channel names, leave blank to "
+                   "match any name.</p>"
                    "<p><i>Example:</i><br />"
                    "<i>#quassel*; #foobar; !#quasseldroid</i><br />"
-                   "would match on #foobar and on any channel starting with <i>#quassel</i> except "
-                   "for <i>#quasseldroid</i><br />"
+                   "would match on <i>#foobar</i> and any channel starting with <i>#quassel</i> "
+                   "except for <i>#quasseldroid</i><br />"
                    "<p>If only inverted names are specified, it will match anything except for "
                    "what's specified (implicit wildcard).</p>"
                    "<p><i>Example:</i><br />"
                    "<i>!#quassel*; !#foobar</i><br />"
-                   "would match anything except for #foobar or any channel starting with "
+                   "would match anything except for <i>#foobar</i> or any channel starting with "
                    "<i>#quassel</i></p>"));
 
     int lastRow = ui.highlightTable->rowCount() - 1;
@@ -310,7 +350,7 @@ void CoreHighlightSettingsPage::addNewIgnoredRow(bool enable, const QString &nam
                 tr("<p><b>Channel</b>: Semicolon separated list of channel names.</p>"
                    "<p><i>Example:</i><br />"
                    "<i>#quassel*; #foobar; !#quasseldroid</i><br />"
-                   "would match on #foobar and on any channel starting with <i>#quassel</i> except "
+                   "would match on #foobar and any channel starting with <i>#quassel</i> except "
                    "for <i>#quasseldroid</i><br />"
                    "<p>If only inverted names are specified, it will match anything except for "
                    "what's specified (implicit wildcard).</p>"
index 7a000e9..e610d85 100644 (file)
@@ -34,29 +34,41 @@ HighlightSettingsPage::HighlightSettingsPage(QWidget *parent)
     ui.highlightTable->verticalHeader()->hide();
     ui.highlightTable->setShowGrid(false);
 
+
+    ui.highlightTable->horizontalHeaderItem(HighlightSettingsPage::EnableColumn)->setToolTip(
+                tr("Enable/disable this rule"));
+    ui.highlightTable->horizontalHeaderItem(HighlightSettingsPage::EnableColumn)->setWhatsThis(
+                ui.highlightTable->horizontalHeaderItem(HighlightSettingsPage::EnableColumn)->toolTip());
+
+    ui.highlightTable->horizontalHeaderItem(HighlightSettingsPage::NameColumn)->setToolTip(
+                tr("Phrase to match"));
+    ui.highlightTable->horizontalHeaderItem(HighlightSettingsPage::NameColumn)->setWhatsThis(
+                ui.highlightTable->horizontalHeaderItem(HighlightSettingsPage::NameColumn)->toolTip());
+
     ui.highlightTable->horizontalHeaderItem(HighlightSettingsPage::RegExColumn)->setToolTip(
-                tr("<b>RegEx</b>: This option determines if the highlight rule should be "
-                   "interpreted as a <b>regular expression</b> or just as a keyword."));
+                tr("<b>RegEx</b>: This option determines if the highlight rule and <i>Channel</i> "
+                   "should be interpreted as <b>regular expressions</b> or just as keywords."));
     ui.highlightTable->horizontalHeaderItem(HighlightSettingsPage::RegExColumn)->setWhatsThis(
                 ui.highlightTable->horizontalHeaderItem(HighlightSettingsPage::RegExColumn)->toolTip());
 
     ui.highlightTable->horizontalHeaderItem(HighlightSettingsPage::CsColumn)->setToolTip(
-                tr("<b>CS</b>: This option determines if the highlight rule should be interpreted "
-                   "<b>case sensitive</b>."));
+                tr("<b>CS</b>: This option determines if the highlight rule and <i>Channel</i> "
+                   "should be interpreted <b>case sensitive</b>."));
     ui.highlightTable->horizontalHeaderItem(HighlightSettingsPage::CsColumn)->setWhatsThis(
                 ui.highlightTable->horizontalHeaderItem(HighlightSettingsPage::CsColumn)->toolTip());
 
     ui.highlightTable->horizontalHeaderItem(HighlightSettingsPage::ChanColumn)->setToolTip(
-                tr("<p><b>Channel</b>: Semicolon separated list of channel names.</p>"
+                tr("<p><b>Channel</b>: Semicolon separated list of channel names, leave blank to "
+                   "match any name.</p>"
                    "<p><i>Example:</i><br />"
                    "<i>#quassel*; #foobar; !#quasseldroid</i><br />"
-                   "would match on #foobar and on any channel starting with <i>#quassel</i> except "
-                   "for <i>#quasseldroid</i><br />"
+                   "would match on <i>#foobar</i> and any channel starting with <i>#quassel</i> "
+                   "except for <i>#quasseldroid</i><br />"
                    "<p>If only inverted names are specified, it will match anything except for "
                    "what's specified (implicit wildcard).</p>"
                    "<p><i>Example:</i><br />"
                    "<i>!#quassel*; !#foobar</i><br />"
-                   "would match anything except for #foobar or any channel starting with "
+                   "would match anything except for <i>#foobar</i> or any channel starting with "
                    "<i>#quassel</i></p>"));
     ui.highlightTable->horizontalHeaderItem(HighlightSettingsPage::ChanColumn)->setWhatsThis(
                 ui.highlightTable->horizontalHeaderItem(HighlightSettingsPage::ChanColumn)->toolTip());
@@ -152,22 +164,23 @@ void HighlightSettingsPage::addNewRow(QString name, bool regex, bool cs, bool en
     enableItem->setToolTip(tr("Enable/disable this rule"));
     nameItem->setToolTip(tr("Phrase to match"));
     regexItem->setToolTip(
-                tr("<b>RegEx</b>: This option determines if the highlight rule should be "
-                   "interpreted as a <b>regular expression</b> or just as a keyword."));
+                tr("<b>RegEx</b>: This option determines if the highlight rule and <i>Channel</i> "
+                   "should be interpreted as <b>regular expressions</b> or just as keywords."));
     csItem->setToolTip(
-                tr("<b>CS</b>: This option determines if the highlight rule should be interpreted "
-                   "<b>case sensitive</b>."));
+                tr("<b>CS</b>: This option determines if the highlight rule and <i>Channel</i> "
+                   "should be interpreted <b>case sensitive</b>."));
     chanNameItem->setToolTip(
-                tr("<p><b>Channel</b>: Semicolon separated list of channel names.</p>"
+                tr("<p><b>Channel</b>: Semicolon separated list of channel names, leave blank to "
+                   "match any name.</p>"
                    "<p><i>Example:</i><br />"
                    "<i>#quassel*; #foobar; !#quasseldroid</i><br />"
-                   "would match on #foobar and on any channel starting with <i>#quassel</i> except "
-                   "for <i>#quasseldroid</i><br />"
+                   "would match on <i>#foobar</i> and any channel starting with <i>#quassel</i> "
+                   "except for <i>#quasseldroid</i><br />"
                    "<p>If only inverted names are specified, it will match anything except for "
                    "what's specified (implicit wildcard).</p>"
                    "<p><i>Example:</i><br />"
                    "<i>!#quassel*; !#foobar</i><br />"
-                   "would match anything except for #foobar or any channel starting with "
+                   "would match anything except for <i>#foobar</i> or any channel starting with "
                    "<i>#quassel</i></p>"));
 
     int lastRow = ui.highlightTable->rowCount()-1;
index 5cf6070..1e893a6 100644 (file)
@@ -186,14 +186,14 @@ Whenever you disable/delete the ignore rule, the messages are shown again.&lt;/p
 &lt;br /&gt;
 &lt;i&gt;#quassel*; #foobar; !#quasseldroid&lt;/i&gt;
 &lt;br /&gt;
-would match on #foobar and on any channel starting with &lt;i&gt;#quassel&lt;/i&gt; except for &lt;i&gt;#quasseldroid&lt;/i&gt;
+would match on &lt;i&gt;#foobar&lt;/i&gt; and any channel starting with &lt;i&gt;#quassel&lt;/i&gt; except for &lt;i&gt;#quasseldroid&lt;/i&gt;
 &lt;br /&gt;
 &lt;p&gt;If only inverted names are specified, it will match anything except for what's specified (implicit wildcard).&lt;/p&gt;
 &lt;p&gt;&lt;i&gt;Example:&lt;/i&gt;
 &lt;br /&gt;
 &lt;i&gt;!#quassel*; !#foobar&lt;/i&gt;
 &lt;br /&gt;
-would match anything except for #foobar or any channel starting with &lt;i&gt;#quassel&lt;/i&gt;&lt;/p&gt;</string>
+would match anything except for &lt;i&gt;#foobar&lt;/i&gt; or any channel starting with &lt;i&gt;#quassel&lt;/i&gt;&lt;/p&gt;</string>
         </property>
        </widget>
       </item>