From b95388107f20f914ca7f25748d2a2ef72768c3d3 Mon Sep 17 00:00:00 2001 From: fourtf Date: Sun, 6 May 2018 12:52:47 +0200 Subject: [PATCH] added regex highlights --- chatterino.pro | 11 +- src/application.cpp | 2 +- src/controllers/accounts/account.cpp | 30 ++++ src/controllers/accounts/account.hpp | 25 +++ .../accounts/accountcontroller.cpp | 24 +++ .../accounts/accountcontroller.hpp | 29 ++++ src/controllers/accounts/accountmodel.cpp | 27 ++++ src/controllers/accounts/accountmodel.hpp | 30 ++++ src/controllers/highlights/highlightmodel.cpp | 8 +- .../highlights/highlightphrase.hpp | 88 +++++++--- src/providers/twitch/ircmessagehandler.cpp | 152 +++++++++--------- src/providers/twitch/twitchaccount.cpp | 8 +- src/providers/twitch/twitchaccount.hpp | 6 +- src/providers/twitch/twitchaccountmanager.cpp | 4 +- src/providers/twitch/twitchaccountmanager.hpp | 8 +- src/providers/twitch/twitchchannel.cpp | 4 +- src/providers/twitch/twitchmessagebuilder.cpp | 30 ++-- src/providers/twitch/twitchserver.cpp | 2 +- src/singletons/emotemanager.cpp | 2 +- src/util/sharedptrelementless.hpp | 17 ++ src/util/signalvector2.hpp | 12 +- src/widgets/accountpopup.cpp | 2 +- .../settingspages/highlightingpage.cpp | 4 +- src/widgets/window.cpp | 2 +- 24 files changed, 388 insertions(+), 139 deletions(-) create mode 100644 src/controllers/accounts/account.cpp create mode 100644 src/controllers/accounts/account.hpp create mode 100644 src/controllers/accounts/accountcontroller.cpp create mode 100644 src/controllers/accounts/accountcontroller.hpp create mode 100644 src/controllers/accounts/accountmodel.cpp create mode 100644 src/controllers/accounts/accountmodel.hpp create mode 100644 src/util/sharedptrelementless.hpp diff --git a/chatterino.pro b/chatterino.pro index 0af8bbdf..65097d7e 100644 --- a/chatterino.pro +++ b/chatterino.pro @@ -191,7 +191,10 @@ SOURCES += \ src/controllers/commands/commandcontroller.cpp \ src/controllers/highlights/highlightcontroller.cpp \ src/controllers/highlights/highlightmodel.cpp \ - src/widgets/helper/editablemodelview.cpp + src/widgets/helper/editablemodelview.cpp \ + src/controllers/accounts/accountcontroller.cpp \ + src/controllers/accounts/accountmodel.cpp \ + src/controllers/accounts/account.cpp HEADERS += \ src/precompiled_header.hpp \ @@ -330,7 +333,11 @@ HEADERS += \ src/controllers/highlights/highlightcontroller.hpp \ src/controllers/highlights/highlightphrase.hpp \ src/controllers/highlights/highlightmodel.hpp \ - src/widgets/helper/editablemodelview.hpp + src/widgets/helper/editablemodelview.hpp \ + src/controllers/accounts/accountcontroller.hpp \ + src/controllers/accounts/accountmodel.hpp \ + src/controllers/accounts/account.hpp \ + src/util/sharedptrelementless.hpp RESOURCES += \ resources/resources.qrc diff --git a/src/application.cpp b/src/application.cpp index a8312ca4..a53c0b13 100644 --- a/src/application.cpp +++ b/src/application.cpp @@ -203,7 +203,7 @@ void Application::initialize() this->twitch.pubsub->listenToWhispers(this->accounts->Twitch.getCurrent()); // }; - this->accounts->Twitch.userChanged.connect(RequestModerationActions); + this->accounts->Twitch.currentUserChanged.connect(RequestModerationActions); RequestModerationActions(); } diff --git a/src/controllers/accounts/account.cpp b/src/controllers/accounts/account.cpp new file mode 100644 index 00000000..a0dfc46b --- /dev/null +++ b/src/controllers/accounts/account.cpp @@ -0,0 +1,30 @@ +#include "account.hpp" + +namespace chatterino { +namespace controllers { +namespace accounts { + +Account::Account(const QString &category) +{ +} + +const QString &Account::getCategory() const +{ + return this->category; +} + +bool Account::operator<(const Account &other) const +{ + if (this->category < other.category) { + return true; + } else if (this->category == other.category) { + if (this->toString() < other.toString()) { + return true; + } + } + return false; +} + +} // namespace accounts +} // namespace controllers +} // namespace chatterino diff --git a/src/controllers/accounts/account.hpp b/src/controllers/accounts/account.hpp new file mode 100644 index 00000000..81b2652e --- /dev/null +++ b/src/controllers/accounts/account.hpp @@ -0,0 +1,25 @@ +#pragma once + +#include + +namespace chatterino { +namespace controllers { +namespace accounts { + +class Account +{ +public: + Account(const QString &category); + + virtual QString toString() const = 0; + const QString &getCategory() const; + + bool operator<(const Account &other) const; + +private: + QString category; +}; + +} // namespace accounts +} // namespace controllers +} // namespace chatterino diff --git a/src/controllers/accounts/accountcontroller.cpp b/src/controllers/accounts/accountcontroller.cpp new file mode 100644 index 00000000..ce720435 --- /dev/null +++ b/src/controllers/accounts/accountcontroller.cpp @@ -0,0 +1,24 @@ +#include "accountcontroller.hpp" + +#include "controllers/accounts/accountmodel.hpp" + +namespace chatterino { +namespace controllers { +namespace accounts { + +AccountController::AccountController() +{ +} + +AccountModel *AccountController::createModel(QObject *parent) +{ + AccountModel *model = new AccountModel(parent); + + //(util::BaseSignalVector *) + model->init(&this->accounts); + return model; +} + +} // namespace accounts +} // namespace controllers +} // namespace chatterino diff --git a/src/controllers/accounts/accountcontroller.hpp b/src/controllers/accounts/accountcontroller.hpp new file mode 100644 index 00000000..242cf767 --- /dev/null +++ b/src/controllers/accounts/accountcontroller.hpp @@ -0,0 +1,29 @@ +#pragma once + +#include + +#include "controllers/accounts/account.hpp" +#include "util/sharedptrelementless.hpp" +#include "util/signalvector2.hpp" + +namespace chatterino { +namespace controllers { +namespace accounts { + +class AccountModel; + +class AccountController +{ +public: + AccountController(); + + AccountModel *createModel(QObject *parent); + +private: + util::SortedSignalVector, util::SharedPtrElementLess> + accounts; +}; + +} // namespace accounts +} // namespace controllers +} // namespace chatterino diff --git a/src/controllers/accounts/accountmodel.cpp b/src/controllers/accounts/accountmodel.cpp new file mode 100644 index 00000000..9d527570 --- /dev/null +++ b/src/controllers/accounts/accountmodel.cpp @@ -0,0 +1,27 @@ +#include "accountmodel.hpp" + +namespace chatterino { +namespace controllers { +namespace accounts { + +AccountModel::AccountModel(QObject *parent) + : util::SignalVectorModel>(1, parent) +{ +} + +// turn a vector item into a model row +std::shared_ptr AccountModel::getItemFromRow(std::vector &row) +{ + return nullptr; +} + +// turns a row in the model into a vector item +void AccountModel::getRowFromItem(const std::shared_ptr &item, + std::vector &row) +{ + row[0]->setData(item->toString(), Qt::DisplayRole); +} + +} // namespace accounts +} // namespace controllers +} // namespace chatterino diff --git a/src/controllers/accounts/accountmodel.hpp b/src/controllers/accounts/accountmodel.hpp new file mode 100644 index 00000000..67a1ef1e --- /dev/null +++ b/src/controllers/accounts/accountmodel.hpp @@ -0,0 +1,30 @@ +#pragma + +#include "controllers/accounts/account.hpp" +#include "util/signalvectormodel.hpp" + +namespace chatterino { +namespace controllers { +namespace accounts { + +class AccountController; + +class AccountModel : public util::SignalVectorModel> +{ +public: + AccountModel(QObject *parent); + +protected: + // turn a vector item into a model row + virtual std::shared_ptr getItemFromRow(std::vector &row) override; + + // turns a row in the model into a vector item + virtual void getRowFromItem(const std::shared_ptr &item, + std::vector &row) override; + + friend class AccountController; +}; + +} // namespace accounts +} // namespace controllers +} // namespace chatterino diff --git a/src/controllers/highlights/highlightmodel.cpp b/src/controllers/highlights/highlightmodel.cpp index 39ab5f57..b32df7e0 100644 --- a/src/controllers/highlights/highlightmodel.cpp +++ b/src/controllers/highlights/highlightmodel.cpp @@ -45,10 +45,10 @@ HighlightPhrase HighlightModel::getItemFromRow(std::vector &row // turns a row in the model into a vector item void HighlightModel::getRowFromItem(const HighlightPhrase &item, std::vector &row) { - util::setStringItem(row[0], item.key); - util::setBoolItem(row[1], item.alert); - util::setBoolItem(row[2], item.sound); - util::setBoolItem(row[3], item.regex); + util::setStringItem(row[0], item.getPattern()); + util::setBoolItem(row[1], item.getAlert()); + util::setBoolItem(row[2], item.getSound()); + util::setBoolItem(row[3], item.isRegex()); } void HighlightModel::afterInit() diff --git a/src/controllers/highlights/highlightphrase.hpp b/src/controllers/highlights/highlightphrase.hpp index 3a39acb4..c21ecd49 100644 --- a/src/controllers/highlights/highlightphrase.hpp +++ b/src/controllers/highlights/highlightphrase.hpp @@ -2,24 +2,71 @@ #include "util/serialize-custom.hpp" +#include #include +#include #include namespace chatterino { namespace controllers { namespace highlights { -struct HighlightPhrase { - QString key; +class HighlightPhrase +{ + QString pattern; bool alert; bool sound; - bool regex; + bool _isRegex; + QRegularExpression regex; +public: bool operator==(const HighlightPhrase &other) const { - return std::tie(this->key, this->sound, this->alert, this->regex) == - std::tie(other.key, other.sound, other.alert, other.regex); + return std::tie(this->pattern, this->sound, this->alert, this->_isRegex) == + std::tie(other.pattern, other.sound, other.alert, other._isRegex); } + + HighlightPhrase(const QString &_pattern, bool _alert, bool _sound, bool isRegex) + : pattern(_pattern) + , alert(_alert) + , sound(_sound) + , _isRegex(isRegex) + , regex(_isRegex ? _pattern : "\b" + QRegularExpression::escape(_pattern) + "\b", + QRegularExpression::CaseInsensitiveOption) + { + } + + const QString &getPattern() const + { + return this->pattern; + } + bool getAlert() const + { + return this->alert; + } + bool getSound() const + { + return this->sound; + } + bool isRegex() const + { + 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(); + } + + // const QRegularExpression &getRegex() const + // { + // return this->regex; + // } }; } // namespace highlights } // namespace controllers @@ -35,10 +82,10 @@ struct Serialize { { rapidjson::Value ret(rapidjson::kObjectType); - AddMember(ret, "key", value.key, a); - AddMember(ret, "alert", value.alert, a); - AddMember(ret, "sound", value.sound, a); - AddMember(ret, "regex", value.regex, a); + AddMember(ret, "pattern", value.getPattern(), a); + AddMember(ret, "alert", value.getAlert(), a); + AddMember(ret, "sound", value.getSound(), a); + AddMember(ret, "regex", value.isRegex(), a); return ret; } @@ -48,40 +95,45 @@ template <> struct Deserialize { static chatterino::controllers::highlights::HighlightPhrase get(const rapidjson::Value &value) { - chatterino::controllers::highlights::HighlightPhrase ret; if (!value.IsObject()) { - return ret; + return chatterino::controllers::highlights::HighlightPhrase(QString(), true, false, + false); } - if (value.HasMember("key")) { - const rapidjson::Value &key = value["key"]; + QString _pattern; + if (value.HasMember("pattern")) { + const rapidjson::Value &key = value["pattern"]; if (key.IsString()) { - ret.key = key.GetString(); + _pattern = key.GetString(); } } + bool _alert = true; if (value.HasMember("alert")) { const rapidjson::Value &alert = value["alert"]; if (alert.IsBool()) { - ret.alert = alert.GetBool(); + _alert = alert.GetBool(); } } + bool _sound = false; if (value.HasMember("sound")) { const rapidjson::Value &sound = value["sound"]; if (sound.IsBool()) { - ret.sound = sound.GetBool(); + _sound = sound.GetBool(); } } + bool _isRegex = false; if (value.HasMember("regex")) { const rapidjson::Value ®ex = value["regex"]; if (regex.IsBool()) { - ret.regex = regex.GetBool(); + _isRegex = regex.GetBool(); } } - return ret; + return chatterino::controllers::highlights::HighlightPhrase(_pattern, _alert, _sound, + _isRegex); } }; diff --git a/src/providers/twitch/ircmessagehandler.cpp b/src/providers/twitch/ircmessagehandler.cpp index ccbf3464..7111a0f5 100644 --- a/src/providers/twitch/ircmessagehandler.cpp +++ b/src/providers/twitch/ircmessagehandler.cpp @@ -61,77 +61,79 @@ void IrcMessageHandler::handleRoomStateMessage(Communi::IrcMessage *message) void IrcMessageHandler::handleClearChatMessage(Communi::IrcMessage *message) { return; - // check parameter count - if (message->parameters().length() < 1) { - return; - } + // // check parameter count + // if (message->parameters().length() < 1) { + // return; + // } - QString chanName; - if (!TrimChannelName(message->parameter(0), chanName)) { - return; - } + // QString chanName; + // if (!TrimChannelName(message->parameter(0), chanName)) { + // return; + // } - auto app = getApp(); + // auto app = getApp(); - // get channel - auto chan = app->twitch.server->getChannelOrEmpty(chanName); + // // get channel + // auto chan = app->twitch.server->getChannelOrEmpty(chanName); - if (chan->isEmpty()) { - debug::Log("[IrcMessageHandler:handleClearChatMessage] Twitch channel {} not found", - chanName); - return; - } + // if (chan->isEmpty()) { + // debug::Log("[IrcMessageHandler:handleClearChatMessage] Twitch channel {} not found", + // chanName); + // return; + // } - // check if the chat has been cleared by a moderator - if (message->parameters().length() == 1) { - chan->addMessage(Message::createSystemMessage("Chat has been cleared by a moderator.")); + // // check if the chat has been cleared by a moderator + // if (message->parameters().length() == 1) { + // chan->addMessage(Message::createSystemMessage("Chat has been cleared by a + // moderator.")); - return; - } + // return; + // } - // get username, duration and message of the timed out user - QString username = message->parameter(1); - QString durationInSeconds, reason; - QVariant v = message->tag("ban-duration"); - if (v.isValid()) { - durationInSeconds = v.toString(); - } + // // get username, duration and message of the timed out user + // QString username = message->parameter(1); + // QString durationInSeconds, reason; + // QVariant v = message->tag("ban-duration"); + // if (v.isValid()) { + // durationInSeconds = v.toString(); + // } - v = message->tag("ban-reason"); - if (v.isValid()) { - reason = v.toString(); - } + // v = message->tag("ban-reason"); + // if (v.isValid()) { + // reason = v.toString(); + // } - // add the notice that the user has been timed out - LimitedQueueSnapshot snapshot = chan->getMessageSnapshot(); - bool addMessage = true; - int snapshotLength = snapshot.getLength(); + // // add the notice that the user has been timed out + // LimitedQueueSnapshot snapshot = chan->getMessageSnapshot(); + // bool addMessage = true; + // int snapshotLength = snapshot.getLength(); - for (int i = std::max(0, snapshotLength - 20); i < snapshotLength; i++) { - auto &s = snapshot[i]; - if (s->flags.HasFlag(Message::Timeout) && s->timeoutUser == username) { - MessagePtr replacement( - Message::createTimeoutMessage(username, durationInSeconds, reason, true)); - chan->replaceMessage(s, replacement); - addMessage = false; - break; - } - } + // for (int i = std::max(0, snapshotLength - 20); i < snapshotLength; i++) { + // auto &s = snapshot[i]; + // if (s->flags.HasFlag(Message::Timeout) && s->timeoutUser == username) { + // MessagePtr replacement( + // Message::createTimeoutMessage(username, durationInSeconds, reason, true)); + // chan->replaceMessage(s, replacement); + // addMessage = false; + // break; + // } + // } - if (addMessage) { - chan->addMessage(Message::createTimeoutMessage(username, durationInSeconds, reason, false)); - } + // if (addMessage) { + // chan->addMessage(Message::createTimeoutMessage(username, durationInSeconds, reason, + // false)); + // } - // disable the messages from the user - for (int i = 0; i < snapshotLength; i++) { - auto &s = snapshot[i]; - if (!(s->flags & Message::Timeout) && s->loginName == username) { - s->flags.EnableFlag(Message::Disabled); - } - } + // // disable the messages from the user + // for (int i = 0; i < snapshotLength; i++) { + // auto &s = snapshot[i]; + // if (!(s->flags & Message::Timeout) && s->loginName == username) { + // s->flags.EnableFlag(Message::Disabled); + // } + // } - // refresh all - app->windows->repaintVisibleChatWidgets(chan.get()); + // // refresh all + // app->windows->repaintVisibleChatWidgets(chan.get()); } void IrcMessageHandler::handleUserStateMessage(Communi::IrcMessage *message) @@ -213,28 +215,28 @@ void IrcMessageHandler::handleModeMessage(Communi::IrcMessage *message) void IrcMessageHandler::handleNoticeMessage(Communi::IrcNoticeMessage *message) { return; - auto app = getApp(); - MessagePtr msg = Message::createSystemMessage(message->content()); + // auto app = getApp(); + // MessagePtr msg = Message::createSystemMessage(message->content()); - QString channelName; - if (!TrimChannelName(message->target(), channelName)) { - // Notice wasn't targeted at a single channel, send to all twitch channels - app->twitch.server->forEachChannelAndSpecialChannels([msg](const auto &c) { - c->addMessage(msg); // - }); + // QString channelName; + // if (!TrimChannelName(message->target(), channelName)) { + // // Notice wasn't targeted at a single channel, send to all twitch channels + // app->twitch.server->forEachChannelAndSpecialChannels([msg](const auto &c) { + // c->addMessage(msg); // + // }); - return; - } + // return; + // } - auto channel = app->twitch.server->getChannelOrEmpty(channelName); + // auto channel = app->twitch.server->getChannelOrEmpty(channelName); - if (channel->isEmpty()) { - debug::Log("[IrcManager:handleNoticeMessage] Channel {} not found in channel manager", - channelName); - return; - } + // if (channel->isEmpty()) { + // debug::Log("[IrcManager:handleNoticeMessage] Channel {} not found in channel manager", + // channelName); + // return; + // } - channel->addMessage(msg); + // channel->addMessage(msg); } void IrcMessageHandler::handleWriteConnectionNoticeMessage(Communi::IrcNoticeMessage *message) diff --git a/src/providers/twitch/twitchaccount.cpp b/src/providers/twitch/twitchaccount.cpp index 12951424..801d499f 100644 --- a/src/providers/twitch/twitchaccount.cpp +++ b/src/providers/twitch/twitchaccount.cpp @@ -7,7 +7,8 @@ namespace twitch { TwitchAccount::TwitchAccount(const QString &_username, const QString &_oauthToken, const QString &_oauthClient, const QString &_userID) - : oauthClient(_oauthClient) + : controllers::accounts::Account("Twitch") + , oauthClient(_oauthClient) , oauthToken(_oauthToken) , userName(_username) , userId(_userID) @@ -15,6 +16,11 @@ TwitchAccount::TwitchAccount(const QString &_username, const QString &_oauthToke { } +QString TwitchAccount::toString() const +{ + return this->getUserName(); +} + const QString &TwitchAccount::getUserName() const { return this->userName; diff --git a/src/providers/twitch/twitchaccount.hpp b/src/providers/twitch/twitchaccount.hpp index 1ac8a502..dde6855c 100644 --- a/src/providers/twitch/twitchaccount.hpp +++ b/src/providers/twitch/twitchaccount.hpp @@ -3,16 +3,20 @@ #include #include +#include "controllers/accounts/account.hpp" + namespace chatterino { namespace providers { namespace twitch { -class TwitchAccount +class TwitchAccount : public controllers::accounts::Account { public: TwitchAccount(const QString &username, const QString &oauthToken, const QString &oauthClient, const QString &_userID); + virtual QString toString() const override; + const QString &getUserName() const; const QString &getOAuthToken() const; const QString &getOAuthClient() const; diff --git a/src/providers/twitch/twitchaccountmanager.cpp b/src/providers/twitch/twitchaccountmanager.cpp index 47c55620..b13ef4b5 100644 --- a/src/providers/twitch/twitchaccountmanager.cpp +++ b/src/providers/twitch/twitchaccountmanager.cpp @@ -94,7 +94,7 @@ void TwitchAccountManager::reloadUsers() debug::Log("User {} already exists, and values updated!", userData.username); if (userData.username == this->getCurrent()->getUserName()) { debug::Log("It was the current user, so we need to reconnect stuff!"); - this->userChanged.invoke(); + this->currentUserChanged.invoke(); } } break; case AddUserResponse::UserAdded: { @@ -126,7 +126,7 @@ void TwitchAccountManager::load() this->currentUser = this->anonymousUser; } - this->userChanged.invoke(); + this->currentUserChanged.invoke(); }); } diff --git a/src/providers/twitch/twitchaccountmanager.hpp b/src/providers/twitch/twitchaccountmanager.hpp index 25f0b900..2486ad8c 100644 --- a/src/providers/twitch/twitchaccountmanager.hpp +++ b/src/providers/twitch/twitchaccountmanager.hpp @@ -1,6 +1,8 @@ #pragma once #include "providers/twitch/twitchaccount.hpp" +#include "util/sharedptrelementless.hpp" +#include "util/signalvector2.hpp" #include @@ -47,9 +49,13 @@ public: bool removeUser(const QString &username); pajlada::Settings::Setting currentUsername = {"/accounts/current", ""}; - pajlada::Signals::NoArgSignal userChanged; + pajlada::Signals::NoArgSignal currentUserChanged; pajlada::Signals::NoArgSignal userListUpdated; + util::SortedSignalVector, + util::SharedPtrElementLess> + accounts; + private: enum class AddUserResponse { UserAlreadyExists, diff --git a/src/providers/twitch/twitchchannel.cpp b/src/providers/twitch/twitchchannel.cpp index 59abd0e7..4acff566 100644 --- a/src/providers/twitch/twitchchannel.cpp +++ b/src/providers/twitch/twitchchannel.cpp @@ -45,7 +45,7 @@ TwitchChannel::TwitchChannel(const QString &channelName, Communi::IrcConnection this->refreshLiveStatus(); // }); - this->managedConnect(app->accounts->Twitch.userChanged, [this]() { this->setMod(false); }); + this->managedConnect(app->accounts->Twitch.currentUserChanged, [this]() { this->setMod(false); }); auto refreshPubSubState = [=]() { if (!this->hasModRights()) { @@ -64,7 +64,7 @@ TwitchChannel::TwitchChannel(const QString &channelName, Communi::IrcConnection this->userStateChanged.connect(refreshPubSubState); this->roomIDchanged.connect(refreshPubSubState); - this->managedConnect(app->accounts->Twitch.userChanged, refreshPubSubState); + this->managedConnect(app->accounts->Twitch.currentUserChanged, refreshPubSubState); refreshPubSubState(); this->fetchMessages.connect([this] { diff --git a/src/providers/twitch/twitchmessagebuilder.cpp b/src/providers/twitch/twitchmessagebuilder.cpp index 61612f0e..52a127ab 100644 --- a/src/providers/twitch/twitchmessagebuilder.cpp +++ b/src/providers/twitch/twitchmessagebuilder.cpp @@ -404,10 +404,9 @@ void TwitchMessageBuilder::parseHighlights() app->highlights->phrases.getVector(); if (app->settings->enableHighlightsSelf && currentUsername.size() > 0) { - controllers::highlights::HighlightPhrase selfHighlight; - selfHighlight.key = currentUsername; - selfHighlight.sound = app->settings->enableHighlightSound; - selfHighlight.alert = app->settings->enableHighlightTaskbar; + controllers::highlights::HighlightPhrase selfHighlight( + currentUsername, app->settings->enableHighlightTaskbar, + app->settings->enableHighlightSound, false); activeHighlights.emplace_back(std::move(selfHighlight)); } @@ -419,26 +418,17 @@ void TwitchMessageBuilder::parseHighlights() if (!blackList.contains(this->ircMessage->nick(), Qt::CaseInsensitive)) { for (const controllers::highlights::HighlightPhrase &highlight : activeHighlights) { - int index = -1; - - while ((index = this->originalMessage.indexOf(highlight.key, index + 1, - Qt::CaseInsensitive)) != -1) { - if ((index != 0 && this->originalMessage[index - 1] != ' ') || - (index + highlight.key.length() != this->originalMessage.length() && - this->originalMessage[index + highlight.key.length()] != ' ')) { - continue; - } - - debug::Log("Highlight because {} contains {}", this->originalMessage, - highlight.key); + if (highlight.isMatch(this->originalMessage)) { + debug::Log("Highlight because {} matches {}", this->originalMessage, + highlight.getPattern()); doHighlight = true; - if (highlight.sound) { - playSound = true; + if (highlight.getAlert()) { + doAlert = true; } - if (highlight.alert) { - doAlert = true; + if (highlight.getSound()) { + playSound = true; } if (playSound && doAlert) { diff --git a/src/providers/twitch/twitchserver.cpp b/src/providers/twitch/twitchserver.cpp index 7c803f7b..6a6843f5 100644 --- a/src/providers/twitch/twitchserver.cpp +++ b/src/providers/twitch/twitchserver.cpp @@ -27,7 +27,7 @@ TwitchServer::TwitchServer() void TwitchServer::initialize() { - getApp()->accounts->Twitch.userChanged.connect( + getApp()->accounts->Twitch.currentUserChanged.connect( [this]() { util::postToThread([this] { this->connect(); }); }); } diff --git a/src/singletons/emotemanager.cpp b/src/singletons/emotemanager.cpp index d3c22232..4b77f458 100644 --- a/src/singletons/emotemanager.cpp +++ b/src/singletons/emotemanager.cpp @@ -86,7 +86,7 @@ EmoteManager::EmoteManager() void EmoteManager::initialize() { - getApp()->accounts->Twitch.userChanged.connect([this] { + getApp()->accounts->Twitch.currentUserChanged.connect([this] { auto currentUser = getApp()->accounts->Twitch.getCurrent(); assert(currentUser); this->refreshTwitchEmotes(currentUser); diff --git a/src/util/sharedptrelementless.hpp b/src/util/sharedptrelementless.hpp new file mode 100644 index 00000000..a046fec1 --- /dev/null +++ b/src/util/sharedptrelementless.hpp @@ -0,0 +1,17 @@ +#pragma once + +#include + +namespace chatterino { +namespace util { + +template +struct SharedPtrElementLess { + bool operator()(const std::shared_ptr &a, const std::shared_ptr &b) const + { + return a->operator<(*b); + } +}; + +} // namespace util +} // namespace chatterino diff --git a/src/util/signalvector2.hpp b/src/util/signalvector2.hpp index 22d1e830..8ad90d03 100644 --- a/src/util/signalvector2.hpp +++ b/src/util/signalvector2.hpp @@ -103,17 +103,19 @@ public: } }; -template +template class SortedSignalVector : public BaseSignalVector { public: - virtual int insertItem(const TVectorItem &item, int index = -1, void *caller = 0) override + virtual int insertItem(const TVectorItem &item, int proposedIndex = -1, + void *caller = 0) override { util::assertInGuiThread(); - int index = this->vector.insert( - std::lower_bound(this->vector.begin(), this->vector.end(), item), item) - - this->vector.begin(); + int index = + this->vector.insert( + std::lower_bound(this->vector.begin(), this->vector.end(), item, Compare{}), item) - + this->vector.begin(); typename ReadOnlySignalVector::ItemArgs args{item, index, caller}; this->itemInserted.invoke(args); this->invokeDelayedItemsChanged(); diff --git a/src/widgets/accountpopup.cpp b/src/widgets/accountpopup.cpp index df423f5f..5ba54a5b 100644 --- a/src/widgets/accountpopup.cpp +++ b/src/widgets/accountpopup.cpp @@ -40,7 +40,7 @@ AccountPopupWidget::AccountPopupWidget(ChannelPtr _channel) connect(this, &AccountPopupWidget::refreshButtons, this, &AccountPopupWidget::actuallyRefreshButtons, Qt::QueuedConnection); - app->accounts->Twitch.userChanged.connect([=] { + app->accounts->Twitch.currentUserChanged.connect([=] { auto currentTwitchUser = app->accounts->Twitch.getCurrent(); if (!currentTwitchUser) { // No twitch user set (should never happen) diff --git a/src/widgets/settingspages/highlightingpage.cpp b/src/widgets/settingspages/highlightingpage.cpp index 1b485117..0a608c2c 100644 --- a/src/widgets/settingspages/highlightingpage.cpp +++ b/src/widgets/settingspages/highlightingpage.cpp @@ -47,15 +47,13 @@ HighlightingPage::HighlightingPage() helper::EditableModelView *view = *highlights.emplace( app->highlights->createModel(nullptr)); - view->getTableView()->hideColumn(3); - view->setTitles({"Pattern", "Flash taskbar", "Play sound", "Regex"}); view->getTableView()->horizontalHeader()->setSectionResizeMode(QHeaderView::Fixed); // fourtf: make class extrend BaseWidget and add this to dpiChanged QTimer::singleShot(1, [view] { view->getTableView()->resizeColumnsToContents(); - view->getTableView()->setColumnWidth(0, 250); + view->getTableView()->setColumnWidth(0, 200); }); view->addButtonPressed.connect([] { diff --git a/src/widgets/window.cpp b/src/widgets/window.cpp index 19307787..b2020ea2 100644 --- a/src/widgets/window.cpp +++ b/src/widgets/window.cpp @@ -47,7 +47,7 @@ Window::Window(WindowType _type) app->windows->showAccountSelectPopup(QCursor::pos()); // }); - app->accounts->Twitch.userChanged.connect( + app->accounts->Twitch.currentUserChanged.connect( [=] { user->getLabel().setText(app->accounts->Twitch.getCurrent()->getUserName()); }); }