diff --git a/src/controllers/ignores/IgnoreModel.cpp b/src/controllers/ignores/IgnoreModel.cpp index 3b495de3d..a5b241c5e 100644 --- a/src/controllers/ignores/IgnoreModel.cpp +++ b/src/controllers/ignores/IgnoreModel.cpp @@ -8,7 +8,7 @@ namespace chatterino { // commandmodel IgnoreModel::IgnoreModel(QObject *parent) - : SignalVectorModel(4, parent) + : SignalVectorModel(5, parent) { } @@ -20,7 +20,8 @@ IgnorePhrase IgnoreModel::getItemFromRow(std::vector &row, return IgnorePhrase{ row[0]->data(Qt::DisplayRole).toString(), row[1]->data(Qt::CheckStateRole).toBool(), - row[2]->data(Qt::CheckStateRole).toBool(), row[3]->data(Qt::DisplayRole).toString()}; + row[3]->data(Qt::CheckStateRole).toBool(), row[4]->data(Qt::DisplayRole).toString(), + row[2]->data(Qt::CheckStateRole).toBool()}; } // turns a row in the model into a vector item @@ -28,8 +29,9 @@ void IgnoreModel::getRowFromItem(const IgnorePhrase &item, std::vectorpattern_, this->isRegex_, this->isReplace_, this->replace_) == - std::tie(other.pattern_, other.isRegex_, other.isReplace_, other.replace_); + return std::tie(this->pattern_, this->isRegex_, this->isReplace_, this->replace_, + this->caseInsensitive_) == std::tie(other.pattern_, other.isRegex_, + other.isReplace_, other.replace_, + other.caseInsensitive_); } - IgnorePhrase(const QString &pattern, bool isRegex, bool isReplace, const QString &replace) + IgnorePhrase(const QString &pattern, bool isRegex, bool isReplace, const QString &replace, + bool caseInsensitive) : pattern_(pattern) , isRegex_(isRegex) - , regex_(!isRegex ? pattern : QRegularExpression::escape(pattern), - QRegularExpression::CaseInsensitiveOption | - QRegularExpression::UseUnicodePropertiesOption) + , regex_(pattern) , isReplace_(isReplace) , replace_(replace) + , caseInsensitive_(caseInsensitive) { + if (this->caseInsensitive_) { + regex_.setPatternOptions(QRegularExpression::CaseInsensitiveOption | + QRegularExpression::UseUnicodePropertiesOption); + } else { + regex_.setPatternOptions(QRegularExpression::UseUnicodePropertiesOption); + } } const QString &getPattern() const @@ -41,14 +49,11 @@ public: return this->isRegex_; } - bool isValid() const - { - return !this->pattern_.isEmpty() && this->regex_.isValid(); - } - bool isMatch(const QString &subject) const { - return this->isValid() && this->regex_.match(subject).hasMatch(); + return !this->pattern_.isEmpty() && + (this->isRegex() ? (this->regex_.isValid() && this->regex_.match(subject).hasMatch()) + : subject.contains(this->pattern_, this->caseSensitivity())); } const QRegularExpression &getRegex() const @@ -66,12 +71,23 @@ public: return this->replace_; } + bool caseInsensitive() const + { + return this->caseInsensitive_; + } + + Qt::CaseSensitivity caseSensitivity() const + { + return this->caseInsensitive_ ? Qt::CaseInsensitive : Qt::CaseSensitive; + } + private: QString pattern_; bool isRegex_; QRegularExpression regex_; bool isReplace_; QString replace_; + bool caseInsensitive_; }; } // namespace chatterino @@ -89,6 +105,7 @@ struct Serialize { AddMember(ret, "regex", value.isRegex(), a); AddMember(ret, "onlyWord", value.isReplace(), a); AddMember(ret, "replace", value.getReplace(), a); + AddMember(ret, "caseInsens", value.caseInsensitive(), a); return ret; } @@ -101,20 +118,22 @@ struct Deserialize { if (!value.IsObject()) { return chatterino::IgnorePhrase( QString(), false, false, - ::chatterino::getSettings()->ignoredPhraseReplace.getValue()); + ::chatterino::getSettings()->ignoredPhraseReplace.getValue(), false); } QString _pattern; bool _isRegex = false; bool _isReplace = false; QString _replace; + bool _caseInsens = false; chatterino::rj::getSafe(value, "pattern", _pattern); chatterino::rj::getSafe(value, "regex", _isRegex); chatterino::rj::getSafe(value, "onlyWord", _isReplace); chatterino::rj::getSafe(value, "replace", _replace); + chatterino::rj::getSafe(value, "caseInsens", _caseInsens); - return chatterino::IgnorePhrase(_pattern, _isRegex, _isReplace, _replace); + return chatterino::IgnorePhrase(_pattern, _isRegex, _isReplace, _replace, _caseInsens); } }; diff --git a/src/providers/twitch/TwitchMessageBuilder.cpp b/src/providers/twitch/TwitchMessageBuilder.cpp index fdca2f9ae..73654ae0f 100644 --- a/src/providers/twitch/TwitchMessageBuilder.cpp +++ b/src/providers/twitch/TwitchMessageBuilder.cpp @@ -186,11 +186,14 @@ MessagePtr TwitchMessageBuilder::build() }; for (const auto &phrase : phrases) { - if (!phrase.isReplace() || !phrase.isValid()) { + if (!phrase.isReplace()) { continue; } if (phrase.isRegex()) { const auto ®ex = phrase.getRegex(); + if (!regex.isValid()) { + continue; + } QRegularExpressionMatch match; int from = 0; while ((from = this->originalMessage_.indexOf(regex, from, &match)) != -1) { @@ -205,8 +208,12 @@ MessagePtr TwitchMessageBuilder::build() } } else { const auto &pattern = phrase.getPattern(); + if (pattern.isEmpty()) { + continue; + } int from = 0; - while ((from = this->originalMessage_.indexOf(pattern, from)) != -1) { + while ((from = this->originalMessage_.indexOf(pattern, from, + phrase.caseSensitivity())) != -1) { int len = pattern.size(); removeEmotesInRange(from, len); const auto &replace = phrase.getReplace(); diff --git a/src/widgets/settingspages/IgnoresPage.cpp b/src/widgets/settingspages/IgnoresPage.cpp index 6c642b0f5..743320cc7 100644 --- a/src/widgets/settingspages/IgnoresPage.cpp +++ b/src/widgets/settingspages/IgnoresPage.cpp @@ -45,7 +45,7 @@ void addPhrasesTab(LayoutCreator layout) { EditableModelView *view = layout.emplace(getApp()->ignores->createModel(nullptr)).getElement(); - view->setTitles({"Pattern", "Regex", "Replace", "Pattern"}); + view->setTitles({"Pattern", "Regex", "Case Insensitive", "Replace", "Pattern"}); view->getTableView()->horizontalHeader()->setSectionResizeMode(QHeaderView::Fixed); view->getTableView()->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch); @@ -56,7 +56,7 @@ void addPhrasesTab(LayoutCreator layout) view->addButtonPressed.connect([] { getApp()->ignores->phrases.appendItem(IgnorePhrase{ - "my phrase", false, false, getSettings()->ignoredPhraseReplace.getValue()}); + "my phrase", false, false, getSettings()->ignoredPhraseReplace.getValue(), false}); }); }