From 44f5a15da3a7acbdb23fa7fccecfb4deb57106c7 Mon Sep 17 00:00:00 2001 From: fourtf Date: Sat, 11 Aug 2018 22:23:06 +0200 Subject: [PATCH 01/14] turning a lot of includes into forward declares --- src/Application.cpp | 3 + src/Application.hpp | 3 +- src/common/Aliases.hpp | 2 + src/common/Channel.hpp | 4 +- src/common/Common.hpp | 4 +- src/common/CompletionModel.cpp | 1 + src/common/CompletionModel.hpp | 2 - src/common/NetworkCommon.hpp | 3 +- src/common/NetworkManager.hpp | 9 -- src/common/NetworkRequest.cpp | 2 + src/common/NetworkRequest.hpp | 3 +- .../accounts/AccountController.cpp | 2 + .../accounts/AccountController.hpp | 5 +- src/controllers/accounts/AccountModel.cpp | 1 + src/controllers/accounts/AccountModel.hpp | 1 + .../commands/CommandController.cpp | 3 + .../highlights/HighlightController.hpp | 9 +- src/controllers/ignores/IgnoreController.hpp | 5 +- .../moderationactions/ModerationAction.cpp | 1 + .../moderationactions/ModerationAction.hpp | 4 +- src/messages/Emote.hpp | 3 - src/messages/EmoteCache.hpp | 93 ---------------- src/messages/Image.cpp | 1 + src/messages/Image.hpp | 4 +- src/messages/Link.hpp | 1 - src/messages/Message.hpp | 4 +- src/messages/MessageBuilder.cpp | 9 +- src/messages/MessageBuilder.hpp | 8 +- src/messages/MessageColor.cpp | 2 + src/messages/MessageColor.hpp | 3 +- src/messages/MessageElement.cpp | 2 + src/messages/MessageElement.hpp | 10 +- src/messages/layouts/MessageLayout.cpp | 48 +++++---- src/messages/layouts/MessageLayout.hpp | 17 +-- .../layouts/MessageLayoutContainer.cpp | 6 +- .../layouts/MessageLayoutContainer.hpp | 14 +-- src/messages/layouts/MessageLayoutElement.cpp | 2 + src/messages/layouts/MessageLayoutElement.hpp | 6 +- src/providers/bttv/BttvEmotes.cpp | 1 + src/providers/bttv/BttvEmotes.hpp | 2 + src/providers/chatterino/ChatterinoBadges.cpp | 46 ++++---- src/providers/chatterino/ChatterinoBadges.hpp | 12 +-- src/providers/emoji/Emojis.cpp | 1 + src/providers/emoji/Emojis.hpp | 4 +- src/providers/ffz/FfzEmotes.cpp | 1 + src/providers/irc/AbstractIrcServer.cpp | 2 + src/providers/irc/AbstractIrcServer.hpp | 4 +- src/providers/twitch/IrcMessageHandler.cpp | 1 + src/providers/twitch/PartialTwitchUser.cpp | 1 + src/providers/twitch/PubsubHelpers.cpp | 1 + src/providers/twitch/PubsubHelpers.hpp | 4 +- src/providers/twitch/TwitchAccount.cpp | 1 + src/providers/twitch/TwitchAccount.hpp | 1 + src/providers/twitch/TwitchAccountManager.cpp | 1 + src/providers/twitch/TwitchAccountManager.hpp | 1 + src/providers/twitch/TwitchApi.cpp | 1 + src/providers/twitch/TwitchApi.hpp | 1 + src/providers/twitch/TwitchBadges.cpp | 2 + src/providers/twitch/TwitchBadges.hpp | 4 +- src/providers/twitch/TwitchChannel.cpp | 1 + src/providers/twitch/TwitchChannel.hpp | 14 +-- src/providers/twitch/TwitchEmotes.cpp | 1 + src/providers/twitch/TwitchEmotes.hpp | 8 +- src/providers/twitch/TwitchMessageBuilder.cpp | 2 + src/providers/twitch/TwitchMessageBuilder.hpp | 7 +- src/providers/twitch/TwitchServer.cpp | 1 + src/providers/twitch/TwitchServer.hpp | 4 +- src/singletons/Fonts.cpp | 41 +++---- src/singletons/Fonts.hpp | 51 +++++---- src/singletons/Settings.hpp | 1 - src/singletons/Updates.cpp | 1 + src/singletons/WindowManager.cpp | 29 +++-- src/singletons/WindowManager.hpp | 17 ++- src/util/InitUpdateButton.cpp | 5 +- src/util/InitUpdateButton.hpp | 1 - src/widgets/AccountSwitchWidget.cpp | 1 + src/widgets/AttachedWindow.hpp | 8 +- src/widgets/BaseWindow.cpp | 19 ++-- src/widgets/BaseWindow.hpp | 6 +- src/widgets/Notebook.cpp | 20 ++-- src/widgets/Notebook.hpp | 13 +-- src/widgets/Scrollbar.cpp | 12 +-- src/widgets/Scrollbar.hpp | 1 - src/widgets/StreamView.cpp | 1 + src/widgets/TooltipWidget.cpp | 2 +- src/widgets/Window.cpp | 64 +++++------ src/widgets/Window.hpp | 24 ++--- src/widgets/dialogs/EmotePopup.cpp | 3 + src/widgets/dialogs/EmotePopup.hpp | 7 +- src/widgets/dialogs/LoginDialog.cpp | 1 + src/widgets/dialogs/LogsPopup.cpp | 2 + src/widgets/dialogs/LogsPopup.hpp | 9 +- src/widgets/dialogs/NotificationPopup.cpp | 2 + src/widgets/dialogs/NotificationPopup.hpp | 8 +- src/widgets/dialogs/SelectChannelDialog.cpp | 2 + src/widgets/dialogs/SelectChannelDialog.hpp | 6 +- src/widgets/dialogs/UserInfoPopup.cpp | 1 + src/widgets/dialogs/UserInfoPopup.hpp | 3 +- src/widgets/helper/ChannelView.cpp | 89 ++++++++------- src/widgets/helper/ChannelView.hpp | 27 +++-- src/widgets/helper/NotebookButton.cpp | 1 + src/widgets/helper/NotebookTab.cpp | 2 + src/widgets/helper/ScrollbarHighlight.hpp | 2 - src/widgets/helper/SearchPopup.cpp | 1 + src/widgets/helper/SearchPopup.hpp | 4 +- src/widgets/helper/TitlebarButton.cpp | 16 +-- src/widgets/helper/TitlebarButton.hpp | 26 ++--- src/widgets/settingspages/IgnoresPage.cpp | 1 + src/widgets/settingspages/LookPage.cpp | 6 +- src/widgets/splits/Split.cpp | 102 +++++++++--------- src/widgets/splits/Split.hpp | 21 ++-- src/widgets/splits/SplitContainer.cpp | 1 + src/widgets/splits/SplitContainer.hpp | 11 +- src/widgets/splits/SplitHeader.cpp | 3 + src/widgets/splits/SplitInput.cpp | 14 ++- src/widgets/splits/SplitInput.hpp | 8 +- src/widgets/splits/SplitOverlay.cpp | 1 + 117 files changed, 591 insertions(+), 536 deletions(-) delete mode 100644 src/messages/EmoteCache.hpp diff --git a/src/Application.cpp b/src/Application.cpp index 85b4f382c..22ae0c34b 100644 --- a/src/Application.cpp +++ b/src/Application.cpp @@ -6,11 +6,13 @@ #include "controllers/ignores/IgnoreController.hpp" #include "controllers/moderationactions/ModerationActions.hpp" #include "controllers/taggedusers/TaggedUsersController.hpp" +#include "debug/Log.hpp" #include "messages/MessageBuilder.hpp" #include "providers/bttv/BttvEmotes.hpp" #include "providers/ffz/FfzEmotes.hpp" #include "providers/twitch/PubsubClient.hpp" #include "providers/twitch/TwitchServer.hpp" +#include "singletons/Emotes.hpp" #include "singletons/Fonts.hpp" #include "singletons/Logging.hpp" #include "singletons/NativeMessaging.hpp" @@ -21,6 +23,7 @@ #include "singletons/WindowManager.hpp" #include "util/IsBigEndian.hpp" #include "util/PostToThread.hpp" +#include "widgets/Window.hpp" #include diff --git a/src/Application.hpp b/src/Application.hpp index 2a62503bf..e32f29bdd 100644 --- a/src/Application.hpp +++ b/src/Application.hpp @@ -1,7 +1,6 @@ #pragma once #include "common/Singleton.hpp" -#include "singletons/Resources.hpp" #include #include @@ -26,7 +25,7 @@ class AccountManager; class Emotes; class Settings; class Fonts; -class Resources; +class Resources2; class Application { diff --git a/src/common/Aliases.hpp b/src/common/Aliases.hpp index 8a61a9639..2dea876b7 100644 --- a/src/common/Aliases.hpp +++ b/src/common/Aliases.hpp @@ -32,3 +32,5 @@ QStringAlias(UserName); QStringAlias(UserId); QStringAlias(Url); QStringAlias(Tooltip); +QStringAlias(EmoteId); +QStringAlias(EmoteName); diff --git a/src/common/Channel.hpp b/src/common/Channel.hpp index cb93c1694..c1dd06651 100644 --- a/src/common/Channel.hpp +++ b/src/common/Channel.hpp @@ -1,9 +1,7 @@ #pragma once #include "common/CompletionModel.hpp" -#include "messages/Image.hpp" #include "messages/LimitedQueue.hpp" -#include "messages/Message.hpp" #include #include @@ -12,7 +10,9 @@ #include namespace chatterino { + struct Message; +using MessagePtr = std::shared_ptr; class Channel : public std::enable_shared_from_this { diff --git a/src/common/Common.hpp b/src/common/Common.hpp index 251727c24..46de4a7cb 100644 --- a/src/common/Common.hpp +++ b/src/common/Common.hpp @@ -3,7 +3,6 @@ #include "common/Aliases.hpp" #include "common/Outcome.hpp" #include "common/ProviderId.hpp" -#include "debug/Log.hpp" #include #include @@ -39,4 +38,7 @@ std::weak_ptr weakOf(T *element) return element->shared_from_this(); } +struct Message; +using MessagePtr = std::shared_ptr; + } // namespace chatterino diff --git a/src/common/CompletionModel.cpp b/src/common/CompletionModel.cpp index 9e2f4d024..04425a624 100644 --- a/src/common/CompletionModel.cpp +++ b/src/common/CompletionModel.cpp @@ -5,6 +5,7 @@ #include "controllers/accounts/AccountController.hpp" #include "controllers/commands/CommandController.hpp" #include "debug/Log.hpp" +#include "providers/twitch/TwitchChannel.hpp" #include "providers/twitch/TwitchServer.hpp" #include "singletons/Emotes.hpp" diff --git a/src/common/CompletionModel.hpp b/src/common/CompletionModel.hpp index d9baac7b3..977768474 100644 --- a/src/common/CompletionModel.hpp +++ b/src/common/CompletionModel.hpp @@ -1,7 +1,5 @@ #pragma once -#include "common/Common.hpp" - #include #include diff --git a/src/common/NetworkCommon.hpp b/src/common/NetworkCommon.hpp index 30d1e9267..b214f5472 100644 --- a/src/common/NetworkCommon.hpp +++ b/src/common/NetworkCommon.hpp @@ -2,12 +2,11 @@ #include -#include "Common.hpp" - class QNetworkReply; namespace chatterino { +class Outcome; class NetworkResult; using NetworkSuccessCallback = std::function; diff --git a/src/common/NetworkManager.hpp b/src/common/NetworkManager.hpp index 12c0c6a51..530aaae1f 100644 --- a/src/common/NetworkManager.hpp +++ b/src/common/NetworkManager.hpp @@ -1,16 +1,7 @@ #pragma once -#include "common/NetworkRequester.hpp" -#include "common/NetworkWorker.hpp" -#include "debug/Log.hpp" - -#include -#include #include -#include #include -#include -#include namespace chatterino { diff --git a/src/common/NetworkRequest.cpp b/src/common/NetworkRequest.cpp index f54192190..0a2e45533 100644 --- a/src/common/NetworkRequest.cpp +++ b/src/common/NetworkRequest.cpp @@ -1,7 +1,9 @@ #include "common/NetworkRequest.hpp" #include "Application.hpp" +#include "common/NetworkData.hpp" #include "common/NetworkManager.hpp" +#include "common/Outcome.hpp" #include "debug/Log.hpp" #include "providers/twitch/TwitchCommon.hpp" #include "singletons/Paths.hpp" diff --git a/src/common/NetworkRequest.hpp b/src/common/NetworkRequest.hpp index 09b2cccee..f1940621d 100644 --- a/src/common/NetworkRequest.hpp +++ b/src/common/NetworkRequest.hpp @@ -1,14 +1,13 @@ #pragma once -#include "Application.hpp" #include "common/NetworkCommon.hpp" -#include "common/NetworkData.hpp" #include "common/NetworkRequester.hpp" #include "common/NetworkResult.hpp" #include "common/NetworkTimer.hpp" #include "common/NetworkWorker.hpp" namespace chatterino { +class NetworkData; class NetworkRequest { diff --git a/src/controllers/accounts/AccountController.cpp b/src/controllers/accounts/AccountController.cpp index 6cd1f2558..7d2c84266 100644 --- a/src/controllers/accounts/AccountController.cpp +++ b/src/controllers/accounts/AccountController.cpp @@ -1,6 +1,8 @@ #include "AccountController.hpp" +#include "controllers/accounts/Account.hpp" #include "controllers/accounts/AccountModel.hpp" +#include "providers/twitch/TwitchAccount.hpp" namespace chatterino { diff --git a/src/controllers/accounts/AccountController.hpp b/src/controllers/accounts/AccountController.hpp index 023ad9c9e..b47ec86be 100644 --- a/src/controllers/accounts/AccountController.hpp +++ b/src/controllers/accounts/AccountController.hpp @@ -1,16 +1,15 @@ #pragma once -#include "common/Singleton.hpp" - #include #include "common/SignalVector.hpp" -#include "controllers/accounts/Account.hpp" +#include "common/Singleton.hpp" #include "providers/twitch/TwitchAccountManager.hpp" #include "util/SharedPtrElementLess.hpp" namespace chatterino { +class Account; class Settings; class Paths; diff --git a/src/controllers/accounts/AccountModel.cpp b/src/controllers/accounts/AccountModel.cpp index d63f2c288..23ded2881 100644 --- a/src/controllers/accounts/AccountModel.cpp +++ b/src/controllers/accounts/AccountModel.cpp @@ -1,5 +1,6 @@ #include "AccountModel.hpp" +#include "controllers/accounts/Account.hpp" #include "util/StandardItemHelper.hpp" namespace chatterino { diff --git a/src/controllers/accounts/AccountModel.hpp b/src/controllers/accounts/AccountModel.hpp index c0b4538d5..a8b020410 100644 --- a/src/controllers/accounts/AccountModel.hpp +++ b/src/controllers/accounts/AccountModel.hpp @@ -8,6 +8,7 @@ namespace chatterino { +class Account; class AccountController; class AccountModel : public SignalVectorModel> diff --git a/src/controllers/commands/CommandController.cpp b/src/controllers/commands/CommandController.cpp index 3aaefca8b..f931aa073 100644 --- a/src/controllers/commands/CommandController.cpp +++ b/src/controllers/commands/CommandController.cpp @@ -5,7 +5,10 @@ #include "controllers/accounts/AccountController.hpp" #include "controllers/commands/Command.hpp" #include "controllers/commands/CommandModel.hpp" +#include "debug/Log.hpp" +#include "messages/Message.hpp" #include "messages/MessageBuilder.hpp" +#include "messages/MessageElement.hpp" #include "providers/twitch/TwitchApi.hpp" #include "providers/twitch/TwitchChannel.hpp" #include "providers/twitch/TwitchServer.hpp" diff --git a/src/controllers/highlights/HighlightController.hpp b/src/controllers/highlights/HighlightController.hpp index 09d686cb2..963f23aaa 100644 --- a/src/controllers/highlights/HighlightController.hpp +++ b/src/controllers/highlights/HighlightController.hpp @@ -1,15 +1,16 @@ #pragma once -#include "common/Singleton.hpp" - +#include "common/ChatterinoSetting.hpp" #include "common/SignalVector.hpp" +#include "common/Singleton.hpp" #include "controllers/highlights/HighlightBlacklistUser.hpp" #include "controllers/highlights/HighlightPhrase.hpp" -#include "messages/Message.hpp" -#include "singletons/Settings.hpp" namespace chatterino { +struct Message; +using MessagePtr = std::shared_ptr; + class Settings; class Paths; diff --git a/src/controllers/ignores/IgnoreController.hpp b/src/controllers/ignores/IgnoreController.hpp index e7a0472e6..10c83ac10 100644 --- a/src/controllers/ignores/IgnoreController.hpp +++ b/src/controllers/ignores/IgnoreController.hpp @@ -1,10 +1,9 @@ #pragma once -#include "common/Singleton.hpp" - +#include "common/ChatterinoSetting.hpp" #include "common/SignalVector.hpp" +#include "common/Singleton.hpp" #include "controllers/ignores/IgnorePhrase.hpp" -#include "singletons/Settings.hpp" namespace chatterino { diff --git a/src/controllers/moderationactions/ModerationAction.cpp b/src/controllers/moderationactions/ModerationAction.cpp index 49d302b34..cc2b8463e 100644 --- a/src/controllers/moderationactions/ModerationAction.cpp +++ b/src/controllers/moderationactions/ModerationAction.cpp @@ -2,6 +2,7 @@ #include #include "Application.hpp" +#include "messages/Image.hpp" #include "singletons/Resources.hpp" namespace chatterino { diff --git a/src/controllers/moderationactions/ModerationAction.hpp b/src/controllers/moderationactions/ModerationAction.hpp index f509f79c5..6a36157df 100644 --- a/src/controllers/moderationactions/ModerationAction.hpp +++ b/src/controllers/moderationactions/ModerationAction.hpp @@ -4,11 +4,13 @@ #include #include -#include "messages/Image.hpp" #include "util/RapidjsonHelpers.hpp" namespace chatterino { +class Image; +using ImagePtr = std::shared_ptr; + class ModerationAction { public: diff --git a/src/messages/Emote.hpp b/src/messages/Emote.hpp index 89cadc623..143d3ea64 100644 --- a/src/messages/Emote.hpp +++ b/src/messages/Emote.hpp @@ -7,9 +7,6 @@ #include #include -QStringAlias(EmoteId); -QStringAlias(EmoteName); - namespace chatterino { struct Emote { diff --git a/src/messages/EmoteCache.hpp b/src/messages/EmoteCache.hpp deleted file mode 100644 index 1bbb01fd4..000000000 --- a/src/messages/EmoteCache.hpp +++ /dev/null @@ -1,93 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -#include "common/UniqueAccess.hpp" -#include "messages/Emote.hpp" - -namespace chatterino { - -template -class MapReplacement -{ -public: - MapReplacement(std::unordered_map &items) - : oldItems_(items) - { - } - - void add(const TKey &key, const Emote &data) - { - this->add(key, Emote(data)); - } - - void add(const TKey &key, Emote &&data) - { - auto it = this->oldItems_.find(key); - if (it != this->oldItems_.end() && *it->second == data) { - this->newItems_[key] = it->second; - } else { - this->newItems_[key] = std::make_shared(std::move(data)); - } - } - - void apply() - { - this->oldItems_ = std::move(this->newItems_); - } - -private: - std::unordered_map &oldItems_; - std::unordered_map newItems_; -}; - -template -class EmoteCache -{ -public: - using Iterator = typename std::unordered_map::iterator; - using ConstIterator = typename std::unordered_map::iterator; - - Iterator begin() - { - return this->items_.begin(); - } - - ConstIterator begin() const - { - return this->items_.begin(); - } - - Iterator end() - { - return this->items_.end(); - } - - ConstIterator end() const - { - return this->items_.end(); - } - - boost::optional get(const TKey &key) const - { - auto it = this->items_.find(key); - - if (it == this->items_.end()) - return boost::none; - else - return it->second; - } - - MapReplacement makeReplacment() - { - return MapReplacement(this->items_); - } - -private: - std::unordered_map items_; -}; - -} // namespace chatterino diff --git a/src/messages/Image.cpp b/src/messages/Image.cpp index 572432cdd..b48234536 100644 --- a/src/messages/Image.cpp +++ b/src/messages/Image.cpp @@ -1,6 +1,7 @@ #include "messages/Image.hpp" #include "Application.hpp" +#include "common/Common.hpp" #include "common/NetworkRequest.hpp" #include "debug/AssertInGuiThread.hpp" #include "debug/Benchmark.hpp" diff --git a/src/messages/Image.hpp b/src/messages/Image.hpp index 3d869f798..68b96392b 100644 --- a/src/messages/Image.hpp +++ b/src/messages/Image.hpp @@ -1,18 +1,18 @@ #pragma once -#include "common/Common.hpp" - #include #include #include #include #include #include +#include #include #include #include #include +#include "common/Aliases.hpp" #include "common/NullablePtr.hpp" namespace chatterino { diff --git a/src/messages/Link.hpp b/src/messages/Link.hpp index a6c503540..a07d21cf3 100644 --- a/src/messages/Link.hpp +++ b/src/messages/Link.hpp @@ -1,7 +1,6 @@ #pragma once #include -#include namespace chatterino { diff --git a/src/messages/Message.hpp b/src/messages/Message.hpp index 76039ec41..7aacc47e5 100644 --- a/src/messages/Message.hpp +++ b/src/messages/Message.hpp @@ -1,16 +1,16 @@ #pragma once #include "common/FlagsEnum.hpp" -#include "messages/MessageElement.hpp" -#include "providers/twitch/PubsubActions.hpp" #include "widgets/helper/ScrollbarHighlight.hpp" #include +#include #include #include #include namespace chatterino { +class MessageElement; enum class MessageFlag : uint16_t { None = 0, diff --git a/src/messages/MessageBuilder.cpp b/src/messages/MessageBuilder.cpp index f4ebd2301..49c96c946 100644 --- a/src/messages/MessageBuilder.cpp +++ b/src/messages/MessageBuilder.cpp @@ -1,6 +1,9 @@ #include "MessageBuilder.hpp" #include "common/LinkParser.hpp" +#include "messages/Message.hpp" +#include "messages/MessageElement.hpp" +#include "providers/twitch/PubsubActions.hpp" #include "singletons/Emotes.hpp" #include "singletons/Resources.hpp" #include "singletons/Theme.hpp" @@ -17,7 +20,7 @@ MessagePtr makeSystemMessage(const QString &text) } MessageBuilder::MessageBuilder() - : message_(std::make_unique()) + : message_(std::make_shared()) { } @@ -165,7 +168,9 @@ Message &MessageBuilder::message() MessagePtr MessageBuilder::release() { - return MessagePtr(this->message_.release()); + std::shared_ptr ptr; + this->message_.swap(ptr); + return ptr; } void MessageBuilder::append(std::unique_ptr element) diff --git a/src/messages/MessageBuilder.hpp b/src/messages/MessageBuilder.hpp index a2e78ec29..d3cbdb8d0 100644 --- a/src/messages/MessageBuilder.hpp +++ b/src/messages/MessageBuilder.hpp @@ -1,11 +1,15 @@ #pragma once -#include "messages/Message.hpp" +#include "messages/MessageElement.hpp" #include #include namespace chatterino { +struct BanAction; +struct UnbanAction; +struct Message; +using MessagePtr = std::shared_ptr; struct SystemMessageTag { }; @@ -56,7 +60,7 @@ public: } private: - std::unique_ptr message_; + std::shared_ptr message_; }; } // namespace chatterino diff --git a/src/messages/MessageColor.cpp b/src/messages/MessageColor.cpp index f22654b51..fe793b30e 100644 --- a/src/messages/MessageColor.cpp +++ b/src/messages/MessageColor.cpp @@ -1,5 +1,7 @@ #include "MessageColor.hpp" +#include "singletons/Theme.hpp" + namespace chatterino { MessageColor::MessageColor(const QColor &color) diff --git a/src/messages/MessageColor.hpp b/src/messages/MessageColor.hpp index e7d828745..dd19692c9 100644 --- a/src/messages/MessageColor.hpp +++ b/src/messages/MessageColor.hpp @@ -1,10 +1,9 @@ #pragma once -#include "singletons/Theme.hpp" - #include namespace chatterino { +class Theme; struct MessageColor { enum Type { Custom, Text, Link, System }; diff --git a/src/messages/MessageElement.cpp b/src/messages/MessageElement.cpp index e31076107..24b526c29 100644 --- a/src/messages/MessageElement.cpp +++ b/src/messages/MessageElement.cpp @@ -3,9 +3,11 @@ #include "Application.hpp" #include "controllers/moderationactions/ModerationActions.hpp" #include "debug/Benchmark.hpp" +#include "messages/Emote.hpp" #include "messages/layouts/MessageLayoutContainer.hpp" #include "messages/layouts/MessageLayoutElement.hpp" #include "singletons/Settings.hpp" +#include "singletons/Theme.hpp" #include "util/DebugCount.hpp" namespace chatterino { diff --git a/src/messages/MessageElement.hpp b/src/messages/MessageElement.hpp index 79f222789..8d96d1135 100644 --- a/src/messages/MessageElement.hpp +++ b/src/messages/MessageElement.hpp @@ -1,8 +1,6 @@ #pragma once #include "common/FlagsEnum.hpp" -#include "messages/Emote.hpp" -#include "messages/Image.hpp" #include "messages/Link.hpp" #include "messages/MessageColor.hpp" #include "singletons/Fonts.hpp" @@ -11,14 +9,20 @@ #include #include #include - #include #include +#include namespace chatterino { class Channel; struct MessageLayoutContainer; +class Image; +using ImagePtr = std::shared_ptr; + +struct Emote; +using EmotePtr = std::shared_ptr; + enum class MessageElementFlag { None = 0, Misc = (1 << 0), diff --git a/src/messages/layouts/MessageLayout.cpp b/src/messages/layouts/MessageLayout.cpp index 9847c1950..c077ac4fb 100644 --- a/src/messages/layouts/MessageLayout.cpp +++ b/src/messages/layouts/MessageLayout.cpp @@ -2,8 +2,12 @@ #include "Application.hpp" #include "debug/Benchmark.hpp" +#include "messages/Message.hpp" +#include "messages/MessageElement.hpp" +#include "messages/layouts/MessageLayoutContainer.hpp" #include "singletons/Emotes.hpp" #include "singletons/Settings.hpp" +#include "singletons/Theme.hpp" #include "singletons/WindowManager.hpp" #include "util/DebugCount.hpp" @@ -24,6 +28,7 @@ namespace chatterino { MessageLayout::MessageLayout(MessagePtr message) : message_(message) , buffer_(nullptr) + , container_(std::make_shared()) { DebugCount::increase("message layout"); } @@ -41,7 +46,7 @@ const Message *MessageLayout::getMessage() // Height int MessageLayout::getHeight() const { - return container_.getHeight(); + return container_->getHeight(); } // Layout @@ -82,9 +87,9 @@ bool MessageLayout::layout(int width, float scale, MessageElementFlags flags) return false; } - int oldHeight = this->container_.getHeight(); + int oldHeight = this->container_->getHeight(); this->actuallyLayout(width, flags); - if (widthChanged || this->container_.getHeight() != oldHeight) { + if (widthChanged || this->container_->getHeight() != oldHeight) { this->deleteBuffer(); } this->invalidateBuffer(); @@ -103,22 +108,22 @@ void MessageLayout::actuallyLayout(int width, MessageElementFlags _flags) messageFlags.unset(MessageFlag::Collapsed); } - this->container_.begin(width, this->scale_, messageFlags); + this->container_->begin(width, this->scale_, messageFlags); for (const auto &element : this->message_->elements) { - element->addToContainer(this->container_, _flags); + element->addToContainer(*this->container_, _flags); } - if (this->height_ != this->container_.getHeight()) { + if (this->height_ != this->container_->getHeight()) { this->deleteBuffer(); } - this->container_.end(); - this->height_ = this->container_.getHeight(); + this->container_->end(); + this->height_ = this->container_->getHeight(); // collapsed state this->flags.unset(MessageLayoutFlag::Collapsed); - if (this->container_.isCollapsed()) { + if (this->container_->isCollapsed()) { this->flags.set(MessageLayoutFlag::Collapsed); } } @@ -135,11 +140,12 @@ void MessageLayout::paint(QPainter &painter, int width, int y, int messageIndex, if (!pixmap) { #ifdef Q_OS_MACOS pixmap = new QPixmap(int(width * painter.device()->devicePixelRatioF()), - int(container_.getHeight() * + int(container_->getHeight() * painter.device()->devicePixelRatioF())); pixmap->setDevicePixelRatio(painter.device()->devicePixelRatioF()); #else - pixmap = new QPixmap(width, std::max(16, this->container_.getHeight())); + pixmap = + new QPixmap(width, std::max(16, this->container_->getHeight())); #endif this->buffer_ = std::shared_ptr(pixmap); @@ -157,7 +163,7 @@ void MessageLayout::paint(QPainter &painter, int width, int y, int messageIndex, // this->container.getHeight(), *pixmap); // draw gif emotes - this->container_.paintAnimatedElements(painter, y); + this->container_->paintAnimatedElements(painter, y); // draw disabled if (this->message_->flags.has(MessageFlag::Disabled)) { @@ -167,12 +173,12 @@ void MessageLayout::paint(QPainter &painter, int width, int y, int messageIndex, // draw selection if (!selection.isEmpty()) { - this->container_.paintSelection(painter, messageIndex, selection, y); + this->container_->paintSelection(painter, messageIndex, selection, y); } // draw message seperation line if (app->settings->separateMessages.getValue()) { - painter.fillRect(0, y, this->container_.getWidth(), 1, + painter.fillRect(0, y, this->container_->getWidth(), 1, app->themes->splits.messageSeperator); } @@ -186,7 +192,7 @@ void MessageLayout::paint(QPainter &painter, int width, int y, int messageIndex, QBrush brush(color, static_cast( app->settings->lastMessagePattern.getValue())); - painter.fillRect(0, y + this->container_.getHeight() - 1, + painter.fillRect(0, y + this->container_->getHeight() - 1, pixmap->width(), 1, brush); } @@ -217,7 +223,7 @@ void MessageLayout::updateBuffer(QPixmap *buffer, int /*messageIndex*/, painter.fillRect(buffer->rect(), backgroundColor); // draw message - this->container_.paintElements(painter); + this->container_->paintElements(painter); #ifdef FOURTF // debug @@ -252,7 +258,7 @@ void MessageLayout::deleteCache() this->deleteBuffer(); #ifdef XD - this->container_.clear(); + this->container_->clear(); #endif } @@ -265,22 +271,22 @@ void MessageLayout::deleteCache() const MessageLayoutElement *MessageLayout::getElementAt(QPoint point) { // go through all words and return the first one that contains the point. - return this->container_.getElementAt(point); + return this->container_->getElementAt(point); } int MessageLayout::getLastCharacterIndex() const { - return this->container_.getLastCharacterIndex(); + return this->container_->getLastCharacterIndex(); } int MessageLayout::getSelectionIndex(QPoint position) { - return this->container_.getSelectionIndex(position); + return this->container_->getSelectionIndex(position); } void MessageLayout::addSelectionText(QString &str, int from, int to) { - this->container_.addSelectionText(str, from, to); + this->container_->addSelectionText(str, from, to); } } // namespace chatterino diff --git a/src/messages/layouts/MessageLayout.hpp b/src/messages/layouts/MessageLayout.hpp index 0f0d5cab3..2ab015856 100644 --- a/src/messages/layouts/MessageLayout.hpp +++ b/src/messages/layouts/MessageLayout.hpp @@ -1,19 +1,24 @@ #pragma once #include "common/FlagsEnum.hpp" -#include "messages/Message.hpp" -#include "messages/Selection.hpp" -#include "messages/layouts/MessageLayoutContainer.hpp" -#include "messages/layouts/MessageLayoutElement.hpp" #include - #include #include #include namespace chatterino { +struct Message; +using MessagePtr = std::shared_ptr; + +struct Selection; +struct MessageLayoutContainer; +class MessageLayoutElement; + +enum class MessageElementFlag; +using MessageElementFlags = FlagsEnum; + enum class MessageLayoutFlag : uint8_t { RequiresBufferUpdate = 1 << 1, RequiresLayout = 1 << 2, @@ -57,7 +62,7 @@ public: private: // variables MessagePtr message_; - MessageLayoutContainer container_; + std::shared_ptr container_; std::shared_ptr buffer_ = nullptr; bool bufferValid_ = false; diff --git a/src/messages/layouts/MessageLayoutContainer.cpp b/src/messages/layouts/MessageLayoutContainer.cpp index 699cfc604..2092524c9 100644 --- a/src/messages/layouts/MessageLayoutContainer.cpp +++ b/src/messages/layouts/MessageLayoutContainer.cpp @@ -1,9 +1,13 @@ #include "MessageLayoutContainer.hpp" #include "Application.hpp" -#include "MessageLayoutElement.hpp" +#include "messages/Message.hpp" +#include "messages/MessageElement.hpp" #include "messages/Selection.hpp" +#include "messages/layouts/MessageLayoutElement.hpp" +#include "singletons/Fonts.hpp" #include "singletons/Settings.hpp" +#include "singletons/Theme.hpp" #include #include diff --git a/src/messages/layouts/MessageLayoutContainer.hpp b/src/messages/layouts/MessageLayoutContainer.hpp index f52f181e6..cab849ed0 100644 --- a/src/messages/layouts/MessageLayoutContainer.hpp +++ b/src/messages/layouts/MessageLayoutContainer.hpp @@ -1,18 +1,20 @@ #pragma once -#include -#include - #include #include +#include +#include -#include "messages/Message.hpp" +#include "common/FlagsEnum.hpp" #include "messages/Selection.hpp" +#include "messages/layouts/MessageLayoutElement.hpp" class QPainter; namespace chatterino { -class MessageLayoutElement; + +enum class MessageFlag : uint16_t; +using MessageFlags = FlagsEnum; struct Margin { int top; @@ -92,7 +94,7 @@ private: // variables float scale_ = 1.f; int width_ = 0; - MessageFlags flags_ = MessageFlag::None; + MessageFlags flags_{}; int line_ = 0; int height_ = 0; int currentX_ = 0; diff --git a/src/messages/layouts/MessageLayoutElement.cpp b/src/messages/layouts/MessageLayoutElement.cpp index e8d333e2b..385451141 100644 --- a/src/messages/layouts/MessageLayoutElement.cpp +++ b/src/messages/layouts/MessageLayoutElement.cpp @@ -1,7 +1,9 @@ #include "messages/layouts/MessageLayoutElement.hpp" #include "Application.hpp" +#include "messages/Image.hpp" #include "messages/MessageElement.hpp" +#include "singletons/Theme.hpp" #include "util/DebugCount.hpp" #include diff --git a/src/messages/layouts/MessageLayoutElement.hpp b/src/messages/layouts/MessageLayoutElement.hpp index 44b4c9316..7167adaa9 100644 --- a/src/messages/layouts/MessageLayoutElement.hpp +++ b/src/messages/layouts/MessageLayoutElement.hpp @@ -3,19 +3,19 @@ #include #include #include - #include #include -#include "messages/Image.hpp" #include "messages/Link.hpp" #include "messages/MessageColor.hpp" -#include "singletons/Fonts.hpp" class QPainter; namespace chatterino { class MessageElement; +class Image; +using ImagePtr = std::shared_ptr; +enum class FontStyle : uint8_t; class MessageLayoutElement : boost::noncopyable { diff --git a/src/providers/bttv/BttvEmotes.cpp b/src/providers/bttv/BttvEmotes.cpp index 1d9115c09..70c7cdbdb 100644 --- a/src/providers/bttv/BttvEmotes.cpp +++ b/src/providers/bttv/BttvEmotes.cpp @@ -1,5 +1,6 @@ #include "providers/bttv/BttvEmotes.hpp" +#include "common/Common.hpp" #include "common/NetworkRequest.hpp" #include "debug/Log.hpp" #include "messages/Image.hpp" diff --git a/src/providers/bttv/BttvEmotes.hpp b/src/providers/bttv/BttvEmotes.hpp index 7392cd6bc..ff4809411 100644 --- a/src/providers/bttv/BttvEmotes.hpp +++ b/src/providers/bttv/BttvEmotes.hpp @@ -1,6 +1,8 @@ #pragma once +#include #include + #include "common/Atomic.hpp" #include "messages/Emote.hpp" diff --git a/src/providers/chatterino/ChatterinoBadges.cpp b/src/providers/chatterino/ChatterinoBadges.cpp index 98b1841d4..37dc8f6f0 100644 --- a/src/providers/chatterino/ChatterinoBadges.cpp +++ b/src/providers/chatterino/ChatterinoBadges.cpp @@ -14,39 +14,41 @@ ChatterinoBadges::ChatterinoBadges() boost::optional ChatterinoBadges::getBadge(const UserName &username) { - return this->badges.access()->get(username); + return boost::none; + // return this->badges.access()->get(username); } void ChatterinoBadges::loadChatterinoBadges() { - static QString url("https://fourtf.com/chatterino/badges.json"); + // static QString url("https://fourtf.com/chatterino/badges.json"); - NetworkRequest req(url); - req.setCaller(QThread::currentThread()); + // NetworkRequest req(url); + // req.setCaller(QThread::currentThread()); - req.onSuccess([this](auto result) { - auto jsonRoot = result.parseJson(); - auto badges = this->badges.access(); - auto replacement = badges->makeReplacment(); + // req.onSuccess([this](auto result) { + // auto jsonRoot = result.parseJson(); + // auto badges = this->badges.access(); + // auto replacement = badges->makeReplacment(); - for (auto jsonBadge_ : jsonRoot.value("badges").toArray()) { - auto jsonBadge = jsonBadge_.toObject(); + // for (auto jsonBadge_ : jsonRoot.value("badges").toArray()) { + // auto jsonBadge = jsonBadge_.toObject(); - auto emote = Emote{ - EmoteName{}, ImageSet{Url{jsonBadge.value("image").toString()}}, - Tooltip{jsonBadge.value("tooltip").toString()}, Url{}}; + // auto emote = Emote{ + // EmoteName{}, + // ImageSet{Url{jsonBadge.value("image").toString()}}, + // Tooltip{jsonBadge.value("tooltip").toString()}, Url{}}; - for (auto jsonUser : jsonBadge.value("users").toArray()) { - replacement.add(UserName{jsonUser.toString()}, - std::move(emote)); - } - } + // for (auto jsonUser : jsonBadge.value("users").toArray()) { + // replacement.add(UserName{jsonUser.toString()}, + // std::move(emote)); + // } + // } - replacement.apply(); - return Success; - }); + // replacement.apply(); + // return Success; + //}); - req.execute(); + // req.execute(); } } // namespace chatterino diff --git a/src/providers/chatterino/ChatterinoBadges.hpp b/src/providers/chatterino/ChatterinoBadges.hpp index 3162c75b1..89870fd16 100644 --- a/src/providers/chatterino/ChatterinoBadges.hpp +++ b/src/providers/chatterino/ChatterinoBadges.hpp @@ -1,14 +1,14 @@ #pragma once #include -#include -#include "common/Common.hpp" -#include "common/UniqueAccess.hpp" -#include "messages/Emote.hpp" -#include "messages/EmoteCache.hpp" + +#include "common/Aliases.hpp" namespace chatterino { +struct Emote; +using EmotePtr = std::shared_ptr; + class ChatterinoBadges { public: @@ -19,7 +19,7 @@ public: private: void loadChatterinoBadges(); - UniqueAccess> badges; + // UniqueAccess> badges; }; } // namespace chatterino diff --git a/src/providers/emoji/Emojis.cpp b/src/providers/emoji/Emojis.cpp index 06d4e798b..d0403e75c 100644 --- a/src/providers/emoji/Emojis.cpp +++ b/src/providers/emoji/Emojis.cpp @@ -2,6 +2,7 @@ #include "Application.hpp" #include "debug/Log.hpp" +#include "messages/Emote.hpp" #include "singletons/Settings.hpp" #include diff --git a/src/providers/emoji/Emojis.hpp b/src/providers/emoji/Emojis.hpp index 18bd33522..62443b9aa 100644 --- a/src/providers/emoji/Emojis.hpp +++ b/src/providers/emoji/Emojis.hpp @@ -1,6 +1,5 @@ #pragma once -#include "messages/Emote.hpp" #include "util/ConcurrentMap.hpp" #include @@ -12,6 +11,9 @@ namespace chatterino { +struct Emote; +using EmotePtr = std::shared_ptr; + struct EmojiData { // actual byte-representation of the emoji (i.e. \154075\156150 which is // :male:) diff --git a/src/providers/ffz/FfzEmotes.cpp b/src/providers/ffz/FfzEmotes.cpp index 24341a817..c22fe91fe 100644 --- a/src/providers/ffz/FfzEmotes.cpp +++ b/src/providers/ffz/FfzEmotes.cpp @@ -3,6 +3,7 @@ #include #include "common/NetworkRequest.hpp" +#include "common/Outcome.hpp" #include "debug/Log.hpp" #include "messages/Image.hpp" diff --git a/src/providers/irc/AbstractIrcServer.cpp b/src/providers/irc/AbstractIrcServer.cpp index b7995282f..25c810a4d 100644 --- a/src/providers/irc/AbstractIrcServer.cpp +++ b/src/providers/irc/AbstractIrcServer.cpp @@ -1,6 +1,8 @@ #include "AbstractIrcServer.hpp" +#include "common/Channel.hpp" #include "common/Common.hpp" +#include "debug/Log.hpp" #include "messages/LimitedQueueSnapshot.hpp" #include "messages/Message.hpp" #include "messages/MessageBuilder.hpp" diff --git a/src/providers/irc/AbstractIrcServer.hpp b/src/providers/irc/AbstractIrcServer.hpp index 580cdd0fe..109f869ef 100644 --- a/src/providers/irc/AbstractIrcServer.hpp +++ b/src/providers/irc/AbstractIrcServer.hpp @@ -1,6 +1,5 @@ #pragma once -#include "common/Channel.hpp" #include "providers/irc/IrcConnection2.hpp" #include @@ -11,6 +10,9 @@ namespace chatterino { +class Channel; +using ChannelPtr = std::shared_ptr; + class AbstractIrcServer { public: diff --git a/src/providers/twitch/IrcMessageHandler.cpp b/src/providers/twitch/IrcMessageHandler.cpp index 35c7c51d9..1679884b8 100644 --- a/src/providers/twitch/IrcMessageHandler.cpp +++ b/src/providers/twitch/IrcMessageHandler.cpp @@ -10,6 +10,7 @@ #include "providers/twitch/TwitchMessageBuilder.hpp" #include "providers/twitch/TwitchServer.hpp" #include "singletons/Resources.hpp" +#include "singletons/Settings.hpp" #include "singletons/WindowManager.hpp" #include "util/IrcHelpers.hpp" diff --git a/src/providers/twitch/PartialTwitchUser.cpp b/src/providers/twitch/PartialTwitchUser.cpp index c3d9e5102..6aca624b1 100644 --- a/src/providers/twitch/PartialTwitchUser.cpp +++ b/src/providers/twitch/PartialTwitchUser.cpp @@ -1,5 +1,6 @@ #include "providers/twitch/PartialTwitchUser.hpp" +#include "common/Common.hpp" #include "common/NetworkRequest.hpp" #include "debug/Log.hpp" #include "providers/twitch/TwitchCommon.hpp" diff --git a/src/providers/twitch/PubsubHelpers.cpp b/src/providers/twitch/PubsubHelpers.cpp index cf4560f6b..f9b4e784a 100644 --- a/src/providers/twitch/PubsubHelpers.cpp +++ b/src/providers/twitch/PubsubHelpers.cpp @@ -1,6 +1,7 @@ #include "providers/twitch/PubsubHelpers.hpp" #include "providers/twitch/PubsubActions.hpp" +#include "providers/twitch/TwitchAccount.hpp" #include "util/RapidjsonHelpers.hpp" namespace chatterino { diff --git a/src/providers/twitch/PubsubHelpers.hpp b/src/providers/twitch/PubsubHelpers.hpp index 8b9b3f322..3e92e332c 100644 --- a/src/providers/twitch/PubsubHelpers.hpp +++ b/src/providers/twitch/PubsubHelpers.hpp @@ -1,16 +1,14 @@ #pragma once -#include "debug/Log.hpp" -#include "providers/twitch/TwitchAccount.hpp" #include "util/RapidjsonHelpers.hpp" #include #include - #include namespace chatterino { +class TwitchAccount; struct ActionUser; const rapidjson::Value &getArgs(const rapidjson::Value &data); diff --git a/src/providers/twitch/TwitchAccount.cpp b/src/providers/twitch/TwitchAccount.cpp index 0258c6e72..238d9a6be 100644 --- a/src/providers/twitch/TwitchAccount.cpp +++ b/src/providers/twitch/TwitchAccount.cpp @@ -4,6 +4,7 @@ #include "Application.hpp" #include "common/NetworkRequest.hpp" +#include "common/Outcome.hpp" #include "debug/Log.hpp" #include "providers/twitch/PartialTwitchUser.hpp" #include "providers/twitch/TwitchCommon.hpp" diff --git a/src/providers/twitch/TwitchAccount.hpp b/src/providers/twitch/TwitchAccount.hpp index c59ca9d38..1ea718b73 100644 --- a/src/providers/twitch/TwitchAccount.hpp +++ b/src/providers/twitch/TwitchAccount.hpp @@ -1,5 +1,6 @@ #pragma once +#include "common/Aliases.hpp" #include "common/Atomic.hpp" #include "common/UniqueAccess.hpp" #include "controllers/accounts/Account.hpp" diff --git a/src/providers/twitch/TwitchAccountManager.cpp b/src/providers/twitch/TwitchAccountManager.cpp index 18210c2fd..097aa89ea 100644 --- a/src/providers/twitch/TwitchAccountManager.cpp +++ b/src/providers/twitch/TwitchAccountManager.cpp @@ -2,6 +2,7 @@ #include "common/Common.hpp" #include "debug/Log.hpp" +#include "providers/twitch/TwitchAccount.hpp" #include "providers/twitch/TwitchCommon.hpp" namespace chatterino { diff --git a/src/providers/twitch/TwitchAccountManager.hpp b/src/providers/twitch/TwitchAccountManager.hpp index 32961f092..7c79ea249 100644 --- a/src/providers/twitch/TwitchAccountManager.hpp +++ b/src/providers/twitch/TwitchAccountManager.hpp @@ -17,6 +17,7 @@ namespace chatterino { +class TwitchAccount; class AccountController; class TwitchAccountManager diff --git a/src/providers/twitch/TwitchApi.cpp b/src/providers/twitch/TwitchApi.cpp index dc0329b69..33e982191 100644 --- a/src/providers/twitch/TwitchApi.cpp +++ b/src/providers/twitch/TwitchApi.cpp @@ -1,5 +1,6 @@ #include "providers/twitch/TwitchApi.hpp" +#include "common/Common.hpp" #include "common/NetworkRequest.hpp" #include "debug/Log.hpp" #include "providers/twitch/TwitchCommon.hpp" diff --git a/src/providers/twitch/TwitchApi.hpp b/src/providers/twitch/TwitchApi.hpp index 67b26c1ca..fd7ad599c 100644 --- a/src/providers/twitch/TwitchApi.hpp +++ b/src/providers/twitch/TwitchApi.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include namespace chatterino { diff --git a/src/providers/twitch/TwitchBadges.cpp b/src/providers/twitch/TwitchBadges.cpp index fd9fe7461..8853f1add 100644 --- a/src/providers/twitch/TwitchBadges.cpp +++ b/src/providers/twitch/TwitchBadges.cpp @@ -5,6 +5,8 @@ #include #include #include "common/NetworkRequest.hpp" +#include "common/Outcome.hpp" +#include "messages/Emote.hpp" namespace chatterino { diff --git a/src/providers/twitch/TwitchBadges.hpp b/src/providers/twitch/TwitchBadges.hpp index a228365da..62196f8d8 100644 --- a/src/providers/twitch/TwitchBadges.hpp +++ b/src/providers/twitch/TwitchBadges.hpp @@ -1,12 +1,14 @@ #pragma once #include -#include #include #include "util/QStringHash.hpp" namespace chatterino { +struct Emote; +using EmotePtr = std::shared_ptr; + class Settings; class Paths; diff --git a/src/providers/twitch/TwitchChannel.cpp b/src/providers/twitch/TwitchChannel.cpp index 7e0a1efc1..0bb7ffe9c 100644 --- a/src/providers/twitch/TwitchChannel.cpp +++ b/src/providers/twitch/TwitchChannel.cpp @@ -1,5 +1,6 @@ #include "providers/twitch/TwitchChannel.hpp" +#include "Application.hpp" #include "common/Common.hpp" #include "common/NetworkRequest.hpp" #include "controllers/accounts/AccountController.hpp" diff --git a/src/providers/twitch/TwitchChannel.hpp b/src/providers/twitch/TwitchChannel.hpp index 8b2edeab4..940da72bf 100644 --- a/src/providers/twitch/TwitchChannel.hpp +++ b/src/providers/twitch/TwitchChannel.hpp @@ -2,21 +2,23 @@ #include +#include "common/Aliases.hpp" #include "common/Atomic.hpp" #include "common/Channel.hpp" -#include "common/Common.hpp" +#include "common/Outcome.hpp" #include "common/UniqueAccess.hpp" -#include "messages/Emote.hpp" -#include "singletons/Emotes.hpp" -#include "util/ConcurrentMap.hpp" - -#include +#include #include +#include #include namespace chatterino { +struct Emote; +using EmotePtr = std::shared_ptr; +class EmoteMap; + class TwitchServer; class TwitchChannel final : public Channel, pajlada::Signals::SignalHolder diff --git a/src/providers/twitch/TwitchEmotes.cpp b/src/providers/twitch/TwitchEmotes.cpp index 08c28286f..ce63d6864 100644 --- a/src/providers/twitch/TwitchEmotes.cpp +++ b/src/providers/twitch/TwitchEmotes.cpp @@ -3,6 +3,7 @@ #include "common/NetworkRequest.hpp" #include "debug/Benchmark.hpp" #include "debug/Log.hpp" +#include "messages/Emote.hpp" #include "messages/Image.hpp" #include "util/RapidjsonHelpers.hpp" diff --git a/src/providers/twitch/TwitchEmotes.hpp b/src/providers/twitch/TwitchEmotes.hpp index 69cf65e5e..90cafe440 100644 --- a/src/providers/twitch/TwitchEmotes.hpp +++ b/src/providers/twitch/TwitchEmotes.hpp @@ -3,18 +3,18 @@ #include #include +#include "common/Aliases.hpp" #include "common/UniqueAccess.hpp" -#include "messages/Emote.hpp" -#include "providers/twitch/EmoteValue.hpp" -#include "providers/twitch/TwitchAccount.hpp" #include "providers/twitch/TwitchEmotes.hpp" -#include "util/ConcurrentMap.hpp" #define TWITCH_EMOTE_TEMPLATE \ "https://static-cdn.jtvnw.net/emoticons/v1/{id}/{scale}" namespace chatterino { +struct Emote; +using EmotePtr = std::shared_ptr; + class TwitchEmotes { public: diff --git a/src/providers/twitch/TwitchMessageBuilder.cpp b/src/providers/twitch/TwitchMessageBuilder.cpp index e475b724d..67cd2998d 100644 --- a/src/providers/twitch/TwitchMessageBuilder.cpp +++ b/src/providers/twitch/TwitchMessageBuilder.cpp @@ -5,6 +5,7 @@ #include "controllers/highlights/HighlightController.hpp" #include "controllers/ignores/IgnoreController.hpp" #include "debug/Log.hpp" +#include "messages/Message.hpp" #include "providers/twitch/TwitchChannel.hpp" #include "singletons/Emotes.hpp" #include "singletons/Resources.hpp" @@ -12,6 +13,7 @@ #include "singletons/Theme.hpp" #include "singletons/WindowManager.hpp" #include "util/IrcHelpers.hpp" +#include "widgets/Window.hpp" #include #include diff --git a/src/providers/twitch/TwitchMessageBuilder.hpp b/src/providers/twitch/TwitchMessageBuilder.hpp index 385fed932..30b476f97 100644 --- a/src/providers/twitch/TwitchMessageBuilder.hpp +++ b/src/providers/twitch/TwitchMessageBuilder.hpp @@ -1,15 +1,18 @@ #pragma once +#include "common/Aliases.hpp" +#include "common/Outcome.hpp" #include "messages/MessageBuilder.hpp" -#include "singletons/Emotes.hpp" #include - #include #include namespace chatterino { +struct Emote; +using EmotePtr = std::shared_ptr; + class Channel; class TwitchChannel; diff --git a/src/providers/twitch/TwitchServer.cpp b/src/providers/twitch/TwitchServer.cpp index 4e3bcddad..e9325443c 100644 --- a/src/providers/twitch/TwitchServer.cpp +++ b/src/providers/twitch/TwitchServer.cpp @@ -7,6 +7,7 @@ #include "providers/twitch/IrcMessageHandler.hpp" #include "providers/twitch/PubsubClient.hpp" #include "providers/twitch/TwitchAccount.hpp" +#include "providers/twitch/TwitchChannel.hpp" #include "providers/twitch/TwitchHelpers.hpp" #include "providers/twitch/TwitchMessageBuilder.hpp" #include "util/PostToThread.hpp" diff --git a/src/providers/twitch/TwitchServer.hpp b/src/providers/twitch/TwitchServer.hpp index 7e204173f..72c4078bc 100644 --- a/src/providers/twitch/TwitchServer.hpp +++ b/src/providers/twitch/TwitchServer.hpp @@ -1,10 +1,10 @@ #pragma once #include "common/Atomic.hpp" +#include "common/Channel.hpp" #include "common/Singleton.hpp" +#include "pajlada/signals/signalholder.hpp" #include "providers/irc/AbstractIrcServer.hpp" -#include "providers/twitch/TwitchAccount.hpp" -#include "providers/twitch/TwitchChannel.hpp" #include #include diff --git a/src/singletons/Fonts.cpp b/src/singletons/Fonts.cpp index 69f327285..3c9efa79e 100644 --- a/src/singletons/Fonts.cpp +++ b/src/singletons/Fonts.cpp @@ -2,6 +2,7 @@ #include "Application.hpp" #include "debug/AssertInGuiThread.hpp" +#include "singletons/Settings.hpp" #include "singletons/WindowManager.hpp" #include @@ -26,7 +27,7 @@ Fonts::Fonts() : chatFontFamily("/appearance/currentFontFamily", DEFAULT_FONT_FAMILY) , chatFontSize("/appearance/currentFontSize", DEFAULT_FONT_SIZE) { - this->fontsByType_.resize(size_t(EndType)); + this->fontsByType_.resize(size_t(FontStyle::EndType)); } void Fonts::initialize(Settings &, Paths &) @@ -61,21 +62,21 @@ void Fonts::initialize(Settings &, Paths &) }); } -QFont Fonts::getFont(Fonts::Type type, float scale) +QFont Fonts::getFont(FontStyle type, float scale) { return this->getOrCreateFontData(type, scale).font; } -QFontMetrics Fonts::getFontMetrics(Fonts::Type type, float scale) +QFontMetrics Fonts::getFontMetrics(FontStyle type, float scale) { return this->getOrCreateFontData(type, scale).metrics; } -Fonts::FontData &Fonts::getOrCreateFontData(Type type, float scale) +Fonts::FontData &Fonts::getOrCreateFontData(FontStyle type, float scale) { assertInGuiThread(); - assert(type >= 0 && type < EndType); + assert(type < FontStyle::EndType); auto &map = this->fontsByType_[size_t(type)]; @@ -94,22 +95,22 @@ Fonts::FontData &Fonts::getOrCreateFontData(Type type, float scale) return result.first->second; } -Fonts::FontData Fonts::createFontData(Type type, float scale) +Fonts::FontData Fonts::createFontData(FontStyle type, float scale) { // check if it's a chat (scale the setting) - if (type >= ChatStart && type <= ChatEnd) { - static std::unordered_map sizeScale{ - {ChatSmall, {0.6f, false, QFont::Normal}}, - {ChatMediumSmall, {0.8f, false, QFont::Normal}}, - {ChatMedium, {1, false, QFont::Normal}}, - {ChatMediumBold, + if (type >= FontStyle::ChatStart && type <= FontStyle::ChatEnd) { + static std::unordered_map sizeScale{ + {FontStyle::ChatSmall, {0.6f, false, QFont::Normal}}, + {FontStyle::ChatMediumSmall, {0.8f, false, QFont::Normal}}, + {FontStyle::ChatMedium, {1, false, QFont::Normal}}, + {FontStyle::ChatMediumBold, {1, false, QFont::Weight(getApp()->settings->boldScale.getValue())}}, - {ChatMediumItalic, {1, true, QFont::Normal}}, - {ChatLarge, {1.2f, false, QFont::Normal}}, - {ChatVeryLarge, {1.4f, false, QFont::Normal}}, + {FontStyle::ChatMediumItalic, {1, true, QFont::Normal}}, + {FontStyle::ChatLarge, {1.2f, false, QFont::Normal}}, + {FontStyle::ChatVeryLarge, {1.4f, false, QFont::Normal}}, }; - sizeScale[ChatMediumBold] = { + sizeScale[FontStyle::ChatMediumBold] = { 1, false, QFont::Weight(getApp()->settings->boldScale.getValue())}; auto data = sizeScale[type]; return FontData( @@ -126,11 +127,11 @@ Fonts::FontData Fonts::createFontData(Type type, float scale) constexpr float multiplier = 1.f; #endif - static std::unordered_map defaultSize{ - {Tiny, {8, "Monospace", false, QFont::Normal}}, - {UiMedium, + static std::unordered_map defaultSize{ + {FontStyle::Tiny, {8, "Monospace", false, QFont::Normal}}, + {FontStyle::UiMedium, {int(9 * multiplier), DEFAULT_FONT_FAMILY, false, QFont::Normal}}, - {UiTabs, + {FontStyle::UiTabs, {int(9 * multiplier), DEFAULT_FONT_FAMILY, false, QFont::Normal}}, }; diff --git a/src/singletons/Fonts.hpp b/src/singletons/Fonts.hpp index 59c6550c3..61ba393d6 100644 --- a/src/singletons/Fonts.hpp +++ b/src/singletons/Fonts.hpp @@ -16,6 +16,27 @@ namespace chatterino { class Settings; class Paths; +enum class FontStyle : uint8_t { + Tiny, + ChatSmall, + ChatMediumSmall, + ChatMedium, + ChatMediumBold, + ChatMediumItalic, + ChatLarge, + ChatVeryLarge, + + UiMedium, + UiTabs, + + // don't remove this value + EndType, + + // make sure to update these values accordingly! + ChatStart = ChatSmall, + ChatEnd = ChatVeryLarge, +}; + class Fonts final : public Singleton { public: @@ -24,29 +45,9 @@ public: virtual void initialize(Settings &settings, Paths &paths) override; // font data gets set in createFontData(...) - enum Type : uint8_t { - Tiny, - ChatSmall, - ChatMediumSmall, - ChatMedium, - ChatMediumBold, - ChatMediumItalic, - ChatLarge, - ChatVeryLarge, - UiMedium, - UiTabs, - - // don't remove this value - EndType, - - // make sure to update these values accordingly! - ChatStart = ChatSmall, - ChatEnd = ChatVeryLarge, - }; - - QFont getFont(Type type, float scale); - QFontMetrics getFontMetrics(Type type, float scale); + QFont getFont(FontStyle type, float scale); + QFontMetrics getFontMetrics(FontStyle type, float scale); pajlada::Settings::Setting chatFontFamily; pajlada::Settings::Setting chatFontSize; @@ -78,12 +79,10 @@ private: QFont::Weight weight; }; - FontData &getOrCreateFontData(Type type, float scale); - FontData createFontData(Type type, float scale); + FontData &getOrCreateFontData(FontStyle type, float scale); + FontData createFontData(FontStyle type, float scale); std::vector> fontsByType_; }; -using FontStyle = Fonts::Type; - } // namespace chatterino diff --git a/src/singletons/Settings.hpp b/src/singletons/Settings.hpp index fbc813b4a..28d0e43d3 100644 --- a/src/singletons/Settings.hpp +++ b/src/singletons/Settings.hpp @@ -5,7 +5,6 @@ #include "common/ChatterinoSetting.hpp" #include "controllers/highlights/HighlightPhrase.hpp" #include "controllers/moderationactions/ModerationAction.hpp" -#include "messages/MessageElement.hpp" #include #include diff --git a/src/singletons/Updates.cpp b/src/singletons/Updates.cpp index d56a8f510..5782b4bea 100644 --- a/src/singletons/Updates.cpp +++ b/src/singletons/Updates.cpp @@ -1,6 +1,7 @@ #include "Updates.hpp" #include "common/NetworkRequest.hpp" +#include "common/Outcome.hpp" #include "common/Version.hpp" #include "singletons/Paths.hpp" #include "util/CombinePath.hpp" diff --git a/src/singletons/WindowManager.cpp b/src/singletons/WindowManager.cpp index 8ff34c7bf..17bf1ea83 100644 --- a/src/singletons/WindowManager.cpp +++ b/src/singletons/WindowManager.cpp @@ -3,13 +3,20 @@ #include "Application.hpp" #include "debug/AssertInGuiThread.hpp" #include "debug/Log.hpp" +#include "messages/MessageElement.hpp" #include "providers/twitch/TwitchServer.hpp" #include "singletons/Fonts.hpp" #include "singletons/Paths.hpp" +#include "singletons/Settings.hpp" #include "singletons/Theme.hpp" #include "util/Clamp.hpp" #include "widgets/AccountSwitchPopupWidget.hpp" +#include "widgets/Notebook.hpp" +#include "widgets/Window.hpp" #include "widgets/dialogs/SettingsDialog.hpp" +#include "widgets/helper/NotebookTab.hpp" +#include "widgets/splits/Split.hpp" +#include "widgets/splits/SplitContainer.hpp" #include #include @@ -174,7 +181,7 @@ Window &WindowManager::getSelectedWindow() return *this->selectedWindow_; } -Window &WindowManager::createWindow(Window::Type type) +Window &WindowManager::createWindow(WindowType type) { assertInGuiThread(); @@ -182,7 +189,7 @@ Window &WindowManager::createWindow(Window::Type type) this->windows_.push_back(window); window->show(); - if (type != Window::Type::Main) { + if (type != WindowType::Main) { window->setAttribute(Qt::WA_DeleteOnClose); QObject::connect(window, &QWidget::destroyed, [this, window] { @@ -239,16 +246,16 @@ void WindowManager::initialize(Settings &settings, Paths &paths) // get type QString type_val = window_obj.value("type").toString(); - Window::Type type = - type_val == "main" ? Window::Type::Main : Window::Type::Popup; + WindowType type = + type_val == "main" ? WindowType::Main : WindowType::Popup; - if (type == Window::Type::Main && mainWindow_ != nullptr) { - type = Window::Type::Popup; + if (type == WindowType::Main && mainWindow_ != nullptr) { + type = WindowType::Popup; } Window &window = createWindow(type); - if (type == Window::Type::Main) { + if (type == WindowType::Main) { mainWindow_ = &window; } @@ -308,7 +315,7 @@ void WindowManager::initialize(Settings &settings, Paths &paths) } if (mainWindow_ == nullptr) { - mainWindow_ = &createWindow(Window::Type::Main); + mainWindow_ = &createWindow(WindowType::Main); mainWindow_->getNotebook().addPage(true); } @@ -344,15 +351,15 @@ void WindowManager::save() // window type switch (window->getType()) { - case Window::Type::Main: + case WindowType::Main: window_obj.insert("type", "main"); break; - case Window::Type::Popup: + case WindowType::Popup: window_obj.insert("type", "popup"); break; - case Window::Type::Attached:; + case WindowType::Attached:; } // window geometry diff --git a/src/singletons/WindowManager.hpp b/src/singletons/WindowManager.hpp index eef2be2f1..74149876e 100644 --- a/src/singletons/WindowManager.hpp +++ b/src/singletons/WindowManager.hpp @@ -1,13 +1,20 @@ #pragma once +#include "common/Channel.hpp" +#include "common/FlagsEnum.hpp" #include "common/Singleton.hpp" -#include "widgets/Window.hpp" #include "widgets/splits/SplitContainer.hpp" namespace chatterino { class Settings; class Paths; +class Window; +class SplitContainer; + +enum class MessageElementFlag; +using MessageElementFlags = FlagsEnum; +enum class WindowType; class WindowManager final : public Singleton { @@ -34,7 +41,7 @@ public: Window &getMainWindow(); Window &getSelectedWindow(); - Window &createWindow(Window::Type type); + Window &createWindow(WindowType type); int windowCount(); Window *windowAt(int index); @@ -63,10 +70,10 @@ private: std::vector windows_; - Window *mainWindow_ = nullptr; - Window *selectedWindow_ = nullptr; + Window *mainWindow_{}; + Window *selectedWindow_{}; - MessageElementFlags wordFlags_ = MessageElementFlag::Default; + MessageElementFlags wordFlags_{}; pajlada::Settings::SettingListener wordFlagsListener_; }; diff --git a/src/util/InitUpdateButton.cpp b/src/util/InitUpdateButton.cpp index 25d131635..54f06976d 100644 --- a/src/util/InitUpdateButton.cpp +++ b/src/util/InitUpdateButton.cpp @@ -6,15 +6,12 @@ namespace chatterino { void initUpdateButton(Button &button, - std::unique_ptr &handle, pajlada::Signals::SignalHolder &signalHolder) { button.hide(); // show update prompt when clicking the button - QObject::connect(&button, &Button::clicked, [&button, &handle] { - (void)(handle); - + QObject::connect(&button, &Button::clicked, [&button] { auto dialog = new UpdateDialog(); dialog->setActionOnFocusLoss(BaseWindow::Delete); dialog->move(button.mapToGlobal( diff --git a/src/util/InitUpdateButton.hpp b/src/util/InitUpdateButton.hpp index e95fcd7bd..9a88382a2 100644 --- a/src/util/InitUpdateButton.hpp +++ b/src/util/InitUpdateButton.hpp @@ -14,7 +14,6 @@ class Button; class UpdateDialog; void initUpdateButton(Button &button, - std::unique_ptr &handle, pajlada::Signals::SignalHolder &signalHolder); } // namespace chatterino diff --git a/src/widgets/AccountSwitchWidget.cpp b/src/widgets/AccountSwitchWidget.cpp index 9c307ba73..3e201ded3 100644 --- a/src/widgets/AccountSwitchWidget.cpp +++ b/src/widgets/AccountSwitchWidget.cpp @@ -3,6 +3,7 @@ #include "Application.hpp" #include "common/Common.hpp" #include "controllers/accounts/AccountController.hpp" +#include "providers/twitch/TwitchAccount.hpp" #include "providers/twitch/TwitchCommon.hpp" namespace chatterino { diff --git a/src/widgets/AttachedWindow.hpp b/src/widgets/AttachedWindow.hpp index 80b030fca..64da52f6a 100644 --- a/src/widgets/AttachedWindow.hpp +++ b/src/widgets/AttachedWindow.hpp @@ -1,12 +1,14 @@ #pragma once +#include #include -#include "common/Channel.hpp" -#include "widgets/splits/Split.hpp" - namespace chatterino { +class Split; +class Channel; +using ChannelPtr = std::shared_ptr; + class AttachedWindow : public QWidget { AttachedWindow(void *_target, int _yOffset); diff --git a/src/widgets/BaseWindow.cpp b/src/widgets/BaseWindow.cpp index eccde0f97..5c80bc9a7 100644 --- a/src/widgets/BaseWindow.cpp +++ b/src/widgets/BaseWindow.cpp @@ -4,6 +4,7 @@ #include "boost/algorithm/algorithm.hpp" #include "debug/Log.hpp" #include "singletons/Settings.hpp" +#include "singletons/Theme.hpp" #include "singletons/WindowManager.hpp" #include "util/PostToThread.hpp" #include "util/WindowsHelper.hpp" @@ -110,11 +111,11 @@ void BaseWindow::init() // buttons TitleBarButton *_minButton = new TitleBarButton; - _minButton->setButtonStyle(TitleBarButton::Minimize); + _minButton->setButtonStyle(TitleBarButtonStyle::Minimize); TitleBarButton *_maxButton = new TitleBarButton; - _maxButton->setButtonStyle(TitleBarButton::Maximize); + _maxButton->setButtonStyle(TitleBarButtonStyle::Maximize); TitleBarButton *_exitButton = new TitleBarButton; - _exitButton->setButtonStyle(TitleBarButton::Close); + _exitButton->setButtonStyle(TitleBarButtonStyle::Close); QObject::connect(_minButton, &TitleBarButton::clicked, this, [this] { @@ -353,8 +354,8 @@ void BaseWindow::mouseMoveEvent(QMouseEvent *event) BaseWidget::mouseMoveEvent(event); } -TitleBarButton *BaseWindow::addTitleBarButton( - const TitleBarButton::Style &style, std::function onClicked) +TitleBarButton *BaseWindow::addTitleBarButton(const TitleBarButtonStyle &style, + std::function onClicked) { TitleBarButton *button = new TitleBarButton; button->setScaleIndependantSize(30, 30); @@ -389,10 +390,10 @@ void BaseWindow::changeEvent(QEvent *) #ifdef USEWINSDK if (this->ui_.maxButton) { - this->ui_.maxButton->setButtonStyle(this->windowState() & - Qt::WindowMaximized - ? TitleBarButton::Unmaximize - : TitleBarButton::Maximize); + this->ui_.maxButton->setButtonStyle( + this->windowState() & Qt::WindowMaximized + ? TitleBarButtonStyle::Unmaximize + : TitleBarButtonStyle::Maximize); } #endif diff --git a/src/widgets/BaseWindow.hpp b/src/widgets/BaseWindow.hpp index eac2ee55e..088c07c86 100644 --- a/src/widgets/BaseWindow.hpp +++ b/src/widgets/BaseWindow.hpp @@ -1,7 +1,6 @@ #pragma once #include "BaseWidget.hpp" -#include "widgets/helper/TitlebarButton.hpp" #include #include @@ -15,6 +14,7 @@ namespace chatterino { class Button; class EffectLabel; class TitleBarButton; +enum class TitleBarButtonStyle; class BaseWindow : public BaseWidget { @@ -36,7 +36,7 @@ public: QWidget *getLayoutContainer(); bool hasCustomWindowFrame(); - TitleBarButton *addTitleBarButton(const TitleBarButton::Style &style, + TitleBarButton *addTitleBarButton(const TitleBarButtonStyle &style, std::function onClicked); EffectLabel *addTitleBarLabel(std::function onClicked); @@ -114,6 +114,6 @@ private: pajlada::Signals::SignalHolder connections_; std::vector managedConnections_; -}; +}; // namespace chatterino } // namespace chatterino diff --git a/src/widgets/Notebook.cpp b/src/widgets/Notebook.cpp index d99d1f021..8cd5a6075 100644 --- a/src/widgets/Notebook.cpp +++ b/src/widgets/Notebook.cpp @@ -2,6 +2,7 @@ #include "Application.hpp" #include "debug/Log.hpp" +#include "singletons/Settings.hpp" #include "singletons/Theme.hpp" #include "singletons/WindowManager.hpp" #include "util/InitUpdateButton.hpp" @@ -27,11 +28,11 @@ namespace chatterino { Notebook::Notebook(QWidget *parent) : BaseWidget(parent) - , addButton_(this) + , addButton_(new NotebookButton(this)) { - this->addButton_.setIcon(NotebookButton::Icon::Plus); + this->addButton_->setIcon(NotebookButton::Icon::Plus); - this->addButton_.setHidden(true); + this->addButton_->setHidden(true); auto *shortcut_next = new QShortcut(QKeySequence("Ctrl+Tab"), this); QObject::connect(shortcut_next, &QShortcut::activated, @@ -290,14 +291,14 @@ void Notebook::setShowAddButton(bool value) { this->showAddButton_ = value; - this->addButton_.setHidden(!value); + this->addButton_->setHidden(!value); } void Notebook::scaleChangedEvent(float scale) { float h = NOTEBOOK_TAB_HEIGHT * this->getScale(); - this->addButton_.setFixedSize(h, h); + this->addButton_->setFixedSize(h, h); for (auto &i : this->items_) { i.tab->updateSize(); @@ -353,7 +354,7 @@ void Notebook::performLayout(bool animated) } if (this->showAddButton_) { - this->addButton_.move(x, y); + this->addButton_->move(x, y); } if (this->lineY_ != y + tabHeight) { @@ -368,7 +369,7 @@ void Notebook::performLayout(bool animated) } if (this->showAddButton_) { - this->addButton_.raise(); + this->addButton_->raise(); } if (this->selectedPage_ != nullptr) { @@ -389,7 +390,7 @@ void Notebook::paintEvent(QPaintEvent *event) NotebookButton *Notebook::getAddButton() { - return &this->addButton_; + return this->addButton_; } NotebookButton *Notebook::addCustomButton() @@ -460,8 +461,7 @@ void SplitNotebook::addCustomButtons() // updates auto updateBtn = this->addCustomButton(); - initUpdateButton(*updateBtn, this->updateDialogHandle_, - this->signalHolder_); + initUpdateButton(*updateBtn, this->signalHolder_); } SplitContainer *SplitNotebook::addPage(bool select) diff --git a/src/widgets/Notebook.hpp b/src/widgets/Notebook.hpp index 749d12594..022c075a2 100644 --- a/src/widgets/Notebook.hpp +++ b/src/widgets/Notebook.hpp @@ -2,10 +2,6 @@ #include "pajlada/signals/signal.hpp" #include "widgets/BaseWidget.hpp" -#include "widgets/dialogs/UpdateDialog.hpp" -#include "widgets/helper/NotebookButton.hpp" -#include "widgets/helper/NotebookTab.hpp" -#include "widgets/splits/SplitContainer.hpp" #include #include @@ -15,6 +11,10 @@ namespace chatterino { class Window; +class UpdateDialog; +class NotebookButton; +class NotebookTab; +class SplitContainer; class Notebook : public BaseWidget { @@ -22,6 +22,7 @@ class Notebook : public BaseWidget public: explicit Notebook(QWidget *parent); + ~Notebook() override = default; NotebookTab *addPage(QWidget *page, QString title = QString(), bool select = false); @@ -74,7 +75,7 @@ private: QList items_; QWidget *selectedPage_ = nullptr; - NotebookButton addButton_; + NotebookButton *addButton_; std::vector customButtons_; bool allowUserTabManagement_ = false; @@ -94,7 +95,7 @@ private: void addCustomButtons(); pajlada::Signals::SignalHolder signalHolder_; - std::unique_ptr updateDialogHandle_; + std::shared_ptr updateDialogHandle_; std::vector connections_; }; diff --git a/src/widgets/Scrollbar.cpp b/src/widgets/Scrollbar.cpp index 9c46cff80..879aa9af2 100644 --- a/src/widgets/Scrollbar.cpp +++ b/src/widgets/Scrollbar.cpp @@ -1,6 +1,7 @@ #include "widgets/Scrollbar.hpp" #include "Application.hpp" +#include "singletons/Settings.hpp" #include "singletons/Theme.hpp" #include "widgets/helper/ChannelView.hpp" @@ -103,8 +104,7 @@ void Scrollbar::setSmallChange(qreal value) void Scrollbar::setDesiredValue(qreal value, bool animated) { - auto app = getApp(); - animated &= app->settings->enableSmoothScrolling.getValue(); + animated &= getSettings()->enableSmoothScrolling.getValue(); value = std::max(this->minimum_, std::min(this->maximum_ - this->largeChange_, value)); @@ -221,8 +221,6 @@ void Scrollbar::printCurrentState(const QString &prefix) const void Scrollbar::paintEvent(QPaintEvent *) { - auto *app = getApp(); - bool mouseOver = this->mouseOverIndex_ != -1; int xOffset = mouseOver ? 0 : width() - int(4 * this->getScale()); @@ -267,9 +265,11 @@ void Scrollbar::paintEvent(QPaintEvent *) QColor color = [&] { switch (highlight.getColor()) { case ScrollbarHighlight::Highlight: - return app->themes->scrollbars.highlights.highlight; + return getApp() + ->themes->scrollbars.highlights.highlight; case ScrollbarHighlight::Subscription: - return app->themes->scrollbars.highlights.subscription; + return getApp() + ->themes->scrollbars.highlights.subscription; } return QColor(); }(); diff --git a/src/widgets/Scrollbar.hpp b/src/widgets/Scrollbar.hpp index fe72477c3..114a1dfe6 100644 --- a/src/widgets/Scrollbar.hpp +++ b/src/widgets/Scrollbar.hpp @@ -1,7 +1,6 @@ #pragma once #include "messages/LimitedQueue.hpp" -#include "singletons/Settings.hpp" #include "widgets/BaseWidget.hpp" #include "widgets/helper/ScrollbarHighlight.hpp" diff --git a/src/widgets/StreamView.cpp b/src/widgets/StreamView.cpp index ad3f1966c..9277ba825 100644 --- a/src/widgets/StreamView.cpp +++ b/src/widgets/StreamView.cpp @@ -3,6 +3,7 @@ #include "common/Channel.hpp" #include "util/Helpers.hpp" #include "util/LayoutCreator.hpp" +#include "widgets/helper/ChannelView.hpp" #include "widgets/splits/Split.hpp" #ifdef USEWEBENGINE diff --git a/src/widgets/TooltipWidget.cpp b/src/widgets/TooltipWidget.cpp index 0b3b83639..3479826b8 100644 --- a/src/widgets/TooltipWidget.cpp +++ b/src/widgets/TooltipWidget.cpp @@ -79,7 +79,7 @@ void TooltipWidget::updateFont() auto app = getApp(); this->setFont( - app->fonts->getFont(Fonts::Type::ChatMediumSmall, this->getScale())); + app->fonts->getFont(FontStyle::ChatMediumSmall, this->getScale())); } void TooltipWidget::setText(QString text) diff --git a/src/widgets/Window.cpp b/src/widgets/Window.cpp index 7088e5cb6..876f2a078 100644 --- a/src/widgets/Window.cpp +++ b/src/widgets/Window.cpp @@ -14,8 +14,11 @@ #include "widgets/dialogs/SettingsDialog.hpp" #include "widgets/dialogs/UpdateDialog.hpp" #include "widgets/dialogs/WelcomeDialog.hpp" +#include "widgets/helper/EffectLabel.hpp" #include "widgets/helper/Shortcut.hpp" +#include "widgets/helper/TitlebarButton.hpp" #include "widgets/splits/Split.hpp" +#include "widgets/splits/SplitContainer.hpp" #include #include @@ -28,10 +31,10 @@ namespace chatterino { -Window::Window(Type type) +Window::Window(WindowType type) : BaseWindow(nullptr, BaseWindow::EnableCustomFrame) , type_(type) - , notebook_(this) + , notebook_(new SplitNotebook(this)) { this->addCustomTitlebarButtons(); this->addDebugStuff(); @@ -42,26 +45,26 @@ Window::Window(Type type) [this] { this->onAccountSelected(); }); this->onAccountSelected(); - if (type == Type::Main) { + if (type == WindowType::Main) { this->resize(int(600 * this->getScale()), int(500 * this->getScale())); } else { this->resize(int(300 * this->getScale()), int(500 * this->getScale())); } } -Window::Type Window::getType() +WindowType Window::getType() { return this->type_; } SplitNotebook &Window::getNotebook() { - return this->notebook_; + return *this->notebook_; } void Window::repaintVisibleChatWidgets(Channel *channel) { - auto page = this->notebook_.getOrAddSelectedPage(); + auto page = this->notebook_->getOrAddSelectedPage(); for (const auto &split : page->getSplits()) { if (channel == nullptr || channel == split->getChannel().get()) { @@ -77,7 +80,7 @@ bool Window::event(QEvent *event) break; case QEvent::WindowDeactivate: { - auto page = this->notebook_.getOrAddSelectedPage(); + auto page = this->notebook_->getOrAddSelectedPage(); if (page != nullptr) { std::vector splits = page->getSplits(); @@ -135,7 +138,7 @@ void Window::showEvent(QShowEvent *event) void Window::closeEvent(QCloseEvent *) { - if (this->type_ == Type::Main) { + if (this->type_ == WindowType::Main) { auto app = getApp(); app->windows->save(); app->windows->closeAll(); @@ -143,7 +146,7 @@ void Window::closeEvent(QCloseEvent *) this->closed.invoke(); - if (this->type_ == Type::Main) { + if (this->type_ == WindowType::Main) { QApplication::exit(); } } @@ -152,35 +155,34 @@ void Window::addLayout() { QVBoxLayout *layout = new QVBoxLayout(this); - layout->addWidget(&this->notebook_); + layout->addWidget(this->notebook_); this->getLayoutContainer()->setLayout(layout); // set margin layout->setMargin(0); - this->notebook_.setAllowUserTabManagement(true); - this->notebook_.setShowAddButton(true); + this->notebook_->setAllowUserTabManagement(true); + this->notebook_->setShowAddButton(true); } void Window::addCustomTitlebarButtons() { if (!this->hasCustomWindowFrame()) return; - if (this->type_ != Type::Main) return; + if (this->type_ != WindowType::Main) return; // settings - this->addTitleBarButton(TitleBarButton::Settings, [] { - getApp()->windows->showSettingsDialog(); // - }); + this->addTitleBarButton(TitleBarButtonStyle::Settings, + [] { getApp()->windows->showSettingsDialog(); }); // updates - auto update = this->addTitleBarButton(TitleBarButton::None, [] {}); + auto update = this->addTitleBarButton(TitleBarButtonStyle::None, [] {}); - initUpdateButton(*update, this->updateDialogHandle_, this->signalHolder_); + initUpdateButton(*update, this->signalHolder_); // account this->userLabel_ = this->addTitleBarLabel([this] { getApp()->windows->showAccountSelectPopup(this->userLabel_->mapToGlobal( - this->userLabel_->rect().bottomLeft())); // + this->userLabel_->rect().bottomLeft())); }); this->userLabel_->setMinimumWidth(20 * getScale()); } @@ -252,27 +254,27 @@ void Window::addShortcuts() // Switch tab createWindowShortcut(this, "CTRL+T", [this] { - this->notebook_.getOrAddSelectedPage()->appendNewSplit(true); + this->notebook_->getOrAddSelectedPage()->appendNewSplit(true); }); createWindowShortcut(this, "CTRL+1", - [this] { this->notebook_.selectIndex(0); }); + [this] { this->notebook_->selectIndex(0); }); createWindowShortcut(this, "CTRL+2", - [this] { this->notebook_.selectIndex(1); }); + [this] { this->notebook_->selectIndex(1); }); createWindowShortcut(this, "CTRL+3", - [this] { this->notebook_.selectIndex(2); }); + [this] { this->notebook_->selectIndex(2); }); createWindowShortcut(this, "CTRL+4", - [this] { this->notebook_.selectIndex(3); }); + [this] { this->notebook_->selectIndex(3); }); createWindowShortcut(this, "CTRL+5", - [this] { this->notebook_.selectIndex(4); }); + [this] { this->notebook_->selectIndex(4); }); createWindowShortcut(this, "CTRL+6", - [this] { this->notebook_.selectIndex(5); }); + [this] { this->notebook_->selectIndex(5); }); createWindowShortcut(this, "CTRL+7", - [this] { this->notebook_.selectIndex(6); }); + [this] { this->notebook_->selectIndex(6); }); createWindowShortcut(this, "CTRL+8", - [this] { this->notebook_.selectIndex(7); }); + [this] { this->notebook_->selectIndex(7); }); createWindowShortcut(this, "CTRL+9", - [this] { this->notebook_.selectIndex(8); }); + [this] { this->notebook_->selectIndex(8); }); // Zoom in { @@ -296,11 +298,11 @@ void Window::addShortcuts() // New tab createWindowShortcut(this, "CTRL+SHIFT+T", - [this] { this->notebook_.addPage(true); }); + [this] { this->notebook_->addPage(true); }); // Close tab createWindowShortcut(this, "CTRL+SHIFT+W", - [this] { this->notebook_.removeCurrentPage(); }); + [this] { this->notebook_->removeCurrentPage(); }); } void Window::onAccountSelected() diff --git a/src/widgets/Window.hpp b/src/widgets/Window.hpp index 438f6b3e2..f9267a81f 100644 --- a/src/widgets/Window.hpp +++ b/src/widgets/Window.hpp @@ -1,13 +1,6 @@ #pragma once -#include "util/Helpers.hpp" #include "widgets/BaseWindow.hpp" -#include "widgets/Notebook.hpp" -#include "widgets/dialogs/UpdateDialog.hpp" - -//#ifdef USEWINSDK -//#include -//#endif #include #include @@ -16,17 +9,20 @@ namespace chatterino { class Theme; +class UpdateDialog; +class SplitNotebook; +class Channel; + +enum class WindowType { Main, Popup, Attached }; class Window : public BaseWindow { Q_OBJECT public: - enum class Type { Main, Popup, Attached }; + explicit Window(WindowType type); - explicit Window(Window::Type type); - - Type getType(); + WindowType getType(); SplitNotebook &getNotebook(); void repaintVisibleChatWidgets(Channel *channel = nullptr); @@ -45,11 +41,11 @@ private: void addLayout(); void onAccountSelected(); - Type type_; + WindowType type_; - SplitNotebook notebook_; + SplitNotebook *notebook_; EffectLabel *userLabel_ = nullptr; - std::unique_ptr updateDialogHandle_; + std::shared_ptr updateDialogHandle_; pajlada::Signals::SignalHolder signalHolder_; diff --git a/src/widgets/dialogs/EmotePopup.cpp b/src/widgets/dialogs/EmotePopup.cpp index 8c3fc87e1..92435065d 100644 --- a/src/widgets/dialogs/EmotePopup.cpp +++ b/src/widgets/dialogs/EmotePopup.cpp @@ -3,9 +3,12 @@ #include "Application.hpp" #include "controllers/accounts/AccountController.hpp" #include "debug/Benchmark.hpp" +#include "messages/Message.hpp" #include "messages/MessageBuilder.hpp" #include "providers/twitch/TwitchChannel.hpp" +#include "singletons/Emotes.hpp" #include "widgets/Notebook.hpp" +#include "widgets/helper/ChannelView.hpp" #include #include diff --git a/src/widgets/dialogs/EmotePopup.hpp b/src/widgets/dialogs/EmotePopup.hpp index 98331efa7..b8ea9ebf9 100644 --- a/src/widgets/dialogs/EmotePopup.hpp +++ b/src/widgets/dialogs/EmotePopup.hpp @@ -1,13 +1,16 @@ #pragma once -#include "common/Channel.hpp" #include "widgets/BaseWindow.hpp" -#include "widgets/helper/ChannelView.hpp" #include namespace chatterino { +class Link; +class ChannelView; +class Channel; +using ChannelPtr = std::shared_ptr; + class EmotePopup : public BaseWindow { public: diff --git a/src/widgets/dialogs/LoginDialog.cpp b/src/widgets/dialogs/LoginDialog.cpp index 1b73f143f..daf3c201e 100644 --- a/src/widgets/dialogs/LoginDialog.cpp +++ b/src/widgets/dialogs/LoginDialog.cpp @@ -1,5 +1,6 @@ #include "widgets/dialogs/LoginDialog.hpp" +#include "Application.hpp" #include "common/Common.hpp" #include "common/NetworkRequest.hpp" #include "controllers/accounts/AccountController.hpp" diff --git a/src/widgets/dialogs/LogsPopup.cpp b/src/widgets/dialogs/LogsPopup.cpp index 04aa78fb4..be799be53 100644 --- a/src/widgets/dialogs/LogsPopup.cpp +++ b/src/widgets/dialogs/LogsPopup.cpp @@ -1,6 +1,7 @@ #include "LogsPopup.hpp" #include "IrcMessage" +#include "common/Channel.hpp" #include "common/NetworkRequest.hpp" #include "providers/twitch/TwitchChannel.hpp" #include "providers/twitch/TwitchMessageBuilder.hpp" @@ -14,6 +15,7 @@ namespace chatterino { LogsPopup::LogsPopup() + : channel_(Channel::getEmpty()) { this->initLayout(); this->resize(400, 600); diff --git a/src/widgets/dialogs/LogsPopup.hpp b/src/widgets/dialogs/LogsPopup.hpp index 5ec39102e..395e1a384 100644 --- a/src/widgets/dialogs/LogsPopup.hpp +++ b/src/widgets/dialogs/LogsPopup.hpp @@ -1,6 +1,5 @@ #pragma once -#include "common/Channel.hpp" #include "widgets/BaseWindow.hpp" namespace chatterino { @@ -8,6 +7,12 @@ namespace chatterino { class Channel; class ChannelView; +class Channel; +using ChannelPtr = std::shared_ptr; + +struct Message; +using MessagePtr = std::shared_ptr; + class LogsPopup : public BaseWindow { public: @@ -17,7 +22,7 @@ public: private: ChannelView *channelView_ = nullptr; - ChannelPtr channel_ = Channel::getEmpty(); + ChannelPtr channel_; QString userName_; int roomID_; diff --git a/src/widgets/dialogs/NotificationPopup.cpp b/src/widgets/dialogs/NotificationPopup.cpp index 46ff7e8af..fb1822f40 100644 --- a/src/widgets/dialogs/NotificationPopup.cpp +++ b/src/widgets/dialogs/NotificationPopup.cpp @@ -1,5 +1,7 @@ #include "NotificationPopup.hpp" +#include "common/Channel.hpp" +#include "messages/Message.hpp" #include "widgets/helper/ChannelView.hpp" #include diff --git a/src/widgets/dialogs/NotificationPopup.hpp b/src/widgets/dialogs/NotificationPopup.hpp index 04a35b3a7..0f98a81bd 100644 --- a/src/widgets/dialogs/NotificationPopup.hpp +++ b/src/widgets/dialogs/NotificationPopup.hpp @@ -1,13 +1,17 @@ #pragma once -#include "common/Channel.hpp" -#include "messages/Message.hpp" #include "widgets/BaseWindow.hpp" namespace chatterino { class ChannelView; +class Channel; +using ChannelPtr = std::shared_ptr; + +struct Message; +using MessagePtr = std::shared_ptr; + class NotificationPopup : public BaseWindow { public: diff --git a/src/widgets/dialogs/SelectChannelDialog.cpp b/src/widgets/dialogs/SelectChannelDialog.cpp index 367b626b2..e760a823e 100644 --- a/src/widgets/dialogs/SelectChannelDialog.cpp +++ b/src/widgets/dialogs/SelectChannelDialog.cpp @@ -2,8 +2,10 @@ #include "Application.hpp" #include "providers/twitch/TwitchServer.hpp" +#include "singletons/Theme.hpp" #include "util/LayoutCreator.hpp" #include "widgets/Notebook.hpp" +#include "widgets/helper/NotebookTab.hpp" #include #include diff --git a/src/widgets/dialogs/SelectChannelDialog.hpp b/src/widgets/dialogs/SelectChannelDialog.hpp index 94f21595c..5d5890d9a 100644 --- a/src/widgets/dialogs/SelectChannelDialog.hpp +++ b/src/widgets/dialogs/SelectChannelDialog.hpp @@ -1,8 +1,8 @@ #pragma once +#include "Application.hpp" #include "common/Channel.hpp" #include "widgets/BaseWindow.hpp" -#include "widgets/Notebook.hpp" #include @@ -11,7 +11,9 @@ namespace chatterino { -class SelectChannelDialog : public BaseWindow +class Notebook; + +class SelectChannelDialog final : public BaseWindow { public: SelectChannelDialog(QWidget *parent = nullptr); diff --git a/src/widgets/dialogs/UserInfoPopup.cpp b/src/widgets/dialogs/UserInfoPopup.cpp index e822da8b7..e7d3681ea 100644 --- a/src/widgets/dialogs/UserInfoPopup.cpp +++ b/src/widgets/dialogs/UserInfoPopup.cpp @@ -1,6 +1,7 @@ #include "UserInfoPopup.hpp" #include "Application.hpp" +#include "common/Channel.hpp" #include "common/NetworkRequest.hpp" #include "controllers/accounts/AccountController.hpp" #include "controllers/highlights/HighlightController.hpp" diff --git a/src/widgets/dialogs/UserInfoPopup.hpp b/src/widgets/dialogs/UserInfoPopup.hpp index 3dd13a464..59437d3da 100644 --- a/src/widgets/dialogs/UserInfoPopup.hpp +++ b/src/widgets/dialogs/UserInfoPopup.hpp @@ -1,6 +1,5 @@ #pragma once -#include "common/Channel.hpp" #include "widgets/BaseWindow.hpp" #include @@ -9,6 +8,8 @@ class QCheckBox; namespace chatterino { +class Channel; +using ChannelPtr = std::shared_ptr; class Label; class UserInfoPopup final : public BaseWindow diff --git a/src/widgets/helper/ChannelView.cpp b/src/widgets/helper/ChannelView.cpp index 3803f2a21..45bc7b677 100644 --- a/src/widgets/helper/ChannelView.cpp +++ b/src/widgets/helper/ChannelView.cpp @@ -1,18 +1,24 @@ #include "ChannelView.hpp" #include "Application.hpp" +#include "common/Common.hpp" #include "debug/Benchmark.hpp" #include "debug/Log.hpp" +#include "messages/Emote.hpp" #include "messages/LimitedQueueSnapshot.hpp" #include "messages/Message.hpp" +#include "messages/MessageElement.hpp" #include "messages/layouts/MessageLayout.hpp" +#include "messages/layouts/MessageLayoutElement.hpp" #include "providers/twitch/TwitchServer.hpp" #include "singletons/Settings.hpp" #include "singletons/Theme.hpp" #include "singletons/WindowManager.hpp" #include "util/DistanceBetweenPoints.hpp" +#include "widgets/Scrollbar.hpp" #include "widgets/TooltipWidget.hpp" #include "widgets/dialogs/UserInfoPopup.hpp" +#include "widgets/helper/EffectLabel.hpp" #include "widgets/splits/Split.hpp" #include @@ -93,7 +99,7 @@ void addEmoteContextMenuItems(const Emote &emote, ChannelView::ChannelView(BaseWidget *parent) : BaseWidget(parent) - , scrollBar_(this) + , scrollBar_(new Scrollbar(this)) { this->setMouseTracking(true); @@ -124,7 +130,7 @@ void ChannelView::initializeLayout() QObject::connect(this->goToBottom_, &EffectLabel::clicked, this, [=] { QTimer::singleShot(180, [=] { - this->scrollBar_.scrollToBottom( + this->scrollBar_->scrollToBottom( getApp() ->settings->enableSmoothScrollingNewMessages.getValue()); }); @@ -133,18 +139,18 @@ void ChannelView::initializeLayout() void ChannelView::initializeScrollbar() { - this->scrollBar_.getCurrentValueChanged().connect([this] { + this->scrollBar_->getCurrentValueChanged().connect([this] { this->actuallyLayoutMessages(true); this->goToBottom_->setVisible(this->enableScrollingToBottom_ && - this->scrollBar_.isVisible() && - !this->scrollBar_.isAtBottom()); + this->scrollBar_->isVisible() && + !this->scrollBar_->isAtBottom()); this->queueUpdate(); }); - this->scrollBar_.getDesiredValueChanged().connect([this] { - this->pausedByScrollingUp_ = !this->scrollBar_.isAtBottom(); + this->scrollBar_->getDesiredValueChanged().connect([this] { + this->pausedByScrollingUp_ = !this->scrollBar_->isAtBottom(); }); } @@ -212,7 +218,7 @@ void ChannelView::actuallyLayoutMessages(bool causedByScrollbar) auto messagesSnapshot = this->getMessagesSnapshot(); if (messagesSnapshot.getLength() == 0) { - this->scrollBar_.setVisible(false); + this->scrollBar_->setVisible(false); return; } @@ -225,9 +231,9 @@ void ChannelView::actuallyLayoutMessages(bool causedByScrollbar) // The scrollbar was not visible // The scrollbar was visible and at the bottom this->showingLatestMessages_ = - this->scrollBar_.isAtBottom() || !this->scrollBar_.isVisible(); + this->scrollBar_->isAtBottom() || !this->scrollBar_->isVisible(); - size_t start = size_t(this->scrollBar_.getCurrentValue()); + size_t start = size_t(this->scrollBar_->getCurrentValue()); int layoutWidth = this->getLayoutWidth(); MessageElementFlags flags = this->getFlags(); @@ -235,7 +241,7 @@ void ChannelView::actuallyLayoutMessages(bool causedByScrollbar) // layout the visible messages in the view if (messagesSnapshot.getLength() > start) { int y = int(-(messagesSnapshot[start]->getHeight() * - (fmod(this->scrollBar_.getCurrentValue(), 1)))); + (fmod(this->scrollBar_->getCurrentValue(), 1)))); for (size_t i = start; i < messagesSnapshot.getLength(); ++i) { auto message = messagesSnapshot[i]; @@ -262,8 +268,9 @@ void ChannelView::actuallyLayoutMessages(bool causedByScrollbar) h -= message->getHeight(); if (h < 0) { - this->scrollBar_.setLargeChange((messagesSnapshot.getLength() - i) + - qreal(h) / message->getHeight()); + this->scrollBar_->setLargeChange( + (messagesSnapshot.getLength() - i) + + qreal(h) / message->getHeight()); // this->scrollBar.setDesiredValue(this->scrollBar.getDesiredValue()); showScrollbar = true; @@ -271,20 +278,20 @@ void ChannelView::actuallyLayoutMessages(bool causedByScrollbar) } } - this->scrollBar_.setVisible(showScrollbar); + this->scrollBar_->setVisible(showScrollbar); if (!showScrollbar && !causedByScrollbar) { - this->scrollBar_.setDesiredValue(0); + this->scrollBar_->setDesiredValue(0); } - this->scrollBar_.setMaximum(messagesSnapshot.getLength()); + this->scrollBar_->setMaximum(messagesSnapshot.getLength()); // If we were showing the latest messages and the scrollbar now wants to be // rendered, scroll to bottom if (this->enableScrollingToBottom_ && this->showingLatestMessages_ && showScrollbar) { if (!this->isPaused()) { - this->scrollBar_.scrollToBottom( + this->scrollBar_->scrollToBottom( // this->messageWasAdded && app->settings->enableSmoothScrollingNewMessages.getValue()); } @@ -309,7 +316,7 @@ void ChannelView::clearMessages() Scrollbar &ChannelView::getScrollBar() { - return this->scrollBar_; + return *this->scrollBar_; } QString ChannelView::getSelectedText() @@ -378,7 +385,7 @@ const boost::optional &ChannelView::getOverrideFlags() LimitedQueueSnapshot ChannelView::getMessagesSnapshot() { - if (!this->isPaused() /*|| this->scrollBar_.isVisible()*/) { + if (!this->isPaused() /*|| this->scrollBar_->isVisible()*/) { this->snapshot_ = this->messages.getSnapshot(); } @@ -413,10 +420,10 @@ void ChannelView::setChannel(ChannelPtr newChannel) if (this->messages.pushBack(MessageLayoutPtr(messageRef), deleted)) { // if (!this->isPaused()) { - if (this->scrollBar_.isAtBottom()) { - this->scrollBar_.scrollToBottom(); + if (this->scrollBar_->isAtBottom()) { + this->scrollBar_->scrollToBottom(); } else { - this->scrollBar_.offset(-1); + this->scrollBar_->offset(-1); } // } } @@ -431,7 +438,7 @@ void ChannelView::setChannel(ChannelPtr newChannel) } } - this->scrollBar_.addHighlight(message->getScrollBarHighlight()); + this->scrollBar_->addHighlight(message->getScrollBarHighlight()); this->messageWasAdded_ = true; this->layoutMessages(); @@ -449,10 +456,10 @@ void ChannelView::setChannel(ChannelPtr newChannel) if (!this->isPaused()) { if (this->messages.pushFront(messageRefs).size() > 0) { - if (this->scrollBar_.isAtBottom()) { - this->scrollBar_.scrollToBottom(); + if (this->scrollBar_->isAtBottom()) { + this->scrollBar_->scrollToBottom(); } else { - this->scrollBar_.offset(qreal(messages.size())); + this->scrollBar_->offset(qreal(messages.size())); } } } @@ -464,7 +471,7 @@ void ChannelView::setChannel(ChannelPtr newChannel) messages.at(i)->getScrollBarHighlight()); } - this->scrollBar_.addHighlightsAtStart(highlights); + this->scrollBar_->addHighlightsAtStart(highlights); this->messageWasAdded_ = true; this->layoutMessages(); @@ -503,7 +510,7 @@ void ChannelView::setChannel(ChannelPtr newChannel) newItem->flags.set(MessageLayoutFlag::AlternateBackground); } - this->scrollBar_.replaceHighlight( + this->scrollBar_->replaceHighlight( index, replacement->getScrollBarHighlight()); this->messages.replaceItem(message, newItem); @@ -563,12 +570,12 @@ void ChannelView::updateLastReadMessage() void ChannelView::resizeEvent(QResizeEvent *) { - this->scrollBar_.setGeometry(this->width() - this->scrollBar_.width(), 0, - this->scrollBar_.width(), this->height()); + this->scrollBar_->setGeometry(this->width() - this->scrollBar_->width(), 0, + this->scrollBar_->width(), this->height()); this->goToBottom_->setGeometry(0, this->height() - 32, this->width(), 32); - this->scrollBar_.raise(); + this->scrollBar_->raise(); this->layoutMessages(); @@ -625,9 +632,9 @@ bool ChannelView::isPaused() void ChannelView::updatePauseStatus() { if (this->isPaused()) { - this->scrollBar_.pauseHighlights(); + this->scrollBar_->pauseHighlights(); } else { - this->scrollBar_.unpauseHighlights(); + this->scrollBar_->unpauseHighlights(); } } @@ -651,14 +658,14 @@ void ChannelView::drawMessages(QPainter &painter) auto messagesSnapshot = this->getMessagesSnapshot(); - size_t start = size_t(this->scrollBar_.getCurrentValue()); + size_t start = size_t(this->scrollBar_->getCurrentValue()); if (start >= messagesSnapshot.getLength()) { return; } int y = int(-(messagesSnapshot[start].get()->getHeight() * - (fmod(this->scrollBar_.getCurrentValue(), 1)))); + (fmod(this->scrollBar_->getCurrentValue(), 1)))); MessageLayout *end = nullptr; bool windowFocused = this->window() == QApplication::activeWindow(); @@ -729,12 +736,12 @@ void ChannelView::wheelEvent(QWheelEvent *event) return; } - if (this->scrollBar_.isVisible()) { + if (this->scrollBar_->isVisible()) { auto app = getApp(); float mouseMultiplier = app->settings->mouseScrollMultiplier; - qreal desired = this->scrollBar_.getDesiredValue(); + qreal desired = this->scrollBar_->getDesiredValue(); qreal delta = event->delta() * qreal(1.5) * mouseMultiplier; auto snapshot = this->getMessagesSnapshot(); @@ -792,7 +799,7 @@ void ChannelView::wheelEvent(QWheelEvent *event) } } - this->scrollBar_.setDesiredValue(desired, true); + this->scrollBar_->setDesiredValue(desired, true); } } @@ -1192,14 +1199,14 @@ bool ChannelView::tryGetMessageAt(QPoint p, { auto messagesSnapshot = this->getMessagesSnapshot(); - size_t start = this->scrollBar_.getCurrentValue(); + size_t start = this->scrollBar_->getCurrentValue(); if (start >= messagesSnapshot.getLength()) { return false; } int y = -(messagesSnapshot[start]->getHeight() * - (fmod(this->scrollBar_.getCurrentValue(), 1))); + (fmod(this->scrollBar_->getCurrentValue(), 1))); for (size_t i = start; i < messagesSnapshot.getLength(); ++i) { auto message = messagesSnapshot[i]; @@ -1219,7 +1226,7 @@ bool ChannelView::tryGetMessageAt(QPoint p, int ChannelView::getLayoutWidth() const { - if (this->scrollBar_.isVisible()) + if (this->scrollBar_->isVisible()) return int(this->width() - 8 * this->getScale()); return this->width(); diff --git a/src/widgets/helper/ChannelView.hpp b/src/widgets/helper/ChannelView.hpp index cb8ad990f..46e51bebe 100644 --- a/src/widgets/helper/ChannelView.hpp +++ b/src/widgets/helper/ChannelView.hpp @@ -1,14 +1,10 @@ #pragma once -#include "common/Channel.hpp" -#include "messages/Image.hpp" +#include "common/FlagsEnum.hpp" +#include "messages/LimitedQueue.hpp" #include "messages/LimitedQueueSnapshot.hpp" -#include "messages/MessageElement.hpp" #include "messages/Selection.hpp" -#include "messages/layouts/MessageLayout.hpp" #include "widgets/BaseWidget.hpp" -#include "widgets/Scrollbar.hpp" -#include "widgets/helper/EffectLabel.hpp" #include #include @@ -20,8 +16,23 @@ #include namespace chatterino { +enum class HighlightState; -class ChannelView : public BaseWidget +class Channel; +using ChannelPtr = std::shared_ptr; + +class MessageLayout; +using MessageLayoutPtr = std::shared_ptr; + +enum class MessageElementFlag; +using MessageElementFlags = FlagsEnum; + +class Scrollbar; +class EffectLabel; +struct Link; +class MessageLayoutElement; + +class ChannelView final : public BaseWidget { Q_OBJECT @@ -121,7 +132,7 @@ private: ChannelPtr channel_; - Scrollbar scrollBar_; + Scrollbar *scrollBar_; EffectLabel *goToBottom_; // This variable can be used to decide whether or not we should render the diff --git a/src/widgets/helper/NotebookButton.cpp b/src/widgets/helper/NotebookButton.cpp index 926c42c24..c7ef9e1db 100644 --- a/src/widgets/helper/NotebookButton.cpp +++ b/src/widgets/helper/NotebookButton.cpp @@ -2,6 +2,7 @@ #include "singletons/Theme.hpp" #include "widgets/Notebook.hpp" #include "widgets/helper/Button.hpp" +#include "widgets/splits/Split.hpp" #include "widgets/splits/SplitContainer.hpp" #include diff --git a/src/widgets/helper/NotebookTab.cpp b/src/widgets/helper/NotebookTab.cpp index 5581f5e50..865eb6048 100644 --- a/src/widgets/helper/NotebookTab.cpp +++ b/src/widgets/helper/NotebookTab.cpp @@ -3,6 +3,7 @@ #include "Application.hpp" #include "common/Common.hpp" #include "debug/Log.hpp" +#include "singletons/Fonts.hpp" #include "singletons/Settings.hpp" #include "singletons/Theme.hpp" #include "util/Clamp.hpp" @@ -10,6 +11,7 @@ #include "widgets/Notebook.hpp" #include "widgets/dialogs/SettingsDialog.hpp" #include "widgets/dialogs/TextInputDialog.hpp" +#include "widgets/splits/SplitContainer.hpp" #include #include diff --git a/src/widgets/helper/ScrollbarHighlight.hpp b/src/widgets/helper/ScrollbarHighlight.hpp index b88cdae09..e34cf913b 100644 --- a/src/widgets/helper/ScrollbarHighlight.hpp +++ b/src/widgets/helper/ScrollbarHighlight.hpp @@ -1,7 +1,5 @@ #pragma once -#include - namespace chatterino { class ScrollbarHighlight diff --git a/src/widgets/helper/SearchPopup.cpp b/src/widgets/helper/SearchPopup.cpp index b67addb18..81439407a 100644 --- a/src/widgets/helper/SearchPopup.cpp +++ b/src/widgets/helper/SearchPopup.cpp @@ -6,6 +6,7 @@ #include #include "common/Channel.hpp" +#include "messages/Message.hpp" #include "widgets/helper/ChannelView.hpp" namespace chatterino { diff --git a/src/widgets/helper/SearchPopup.hpp b/src/widgets/helper/SearchPopup.hpp index 0a7065c55..1f2837fbe 100644 --- a/src/widgets/helper/SearchPopup.hpp +++ b/src/widgets/helper/SearchPopup.hpp @@ -1,7 +1,6 @@ #pragma once #include "messages/LimitedQueueSnapshot.hpp" -#include "messages/Message.hpp" #include "widgets/BaseWindow.hpp" #include @@ -13,6 +12,9 @@ namespace chatterino { class Channel; class ChannelView; +struct Message; +using MessagePtr = std::shared_ptr; + class SearchPopup : public BaseWindow { public: diff --git a/src/widgets/helper/TitlebarButton.cpp b/src/widgets/helper/TitlebarButton.cpp index c92e94ba6..d5ab4cc4a 100644 --- a/src/widgets/helper/TitlebarButton.cpp +++ b/src/widgets/helper/TitlebarButton.cpp @@ -9,12 +9,12 @@ TitleBarButton::TitleBarButton() { } -TitleBarButton::Style TitleBarButton::getButtonStyle() const +TitleBarButtonStyle TitleBarButton::getButtonStyle() const { return this->style_; } -void TitleBarButton::setButtonStyle(Style _style) +void TitleBarButton::setButtonStyle(TitleBarButtonStyle _style) { this->style_ = _style; this->update(); @@ -35,16 +35,16 @@ void TitleBarButton::paintEvent(QPaintEvent *event) painter.setRenderHint(QPainter::Antialiasing, false); switch (this->style_) { - case Minimize: { + case TitleBarButtonStyle::Minimize: { painter.fillRect(centerX - xD / 2, xD * 3 / 2, xD, 1, color); break; } - case Maximize: { + case TitleBarButtonStyle::Maximize: { painter.setPen(color); painter.drawRect(centerX - xD / 2, xD, xD - 1, xD - 1); break; } - case Unmaximize: { + case TitleBarButtonStyle::Unmaximize: { int xD2 = xD * 1 / 5; int xD3 = xD * 4 / 5; @@ -54,7 +54,7 @@ void TitleBarButton::paintEvent(QPaintEvent *event) painter.drawRect(centerX - xD / 2, xD + xD2, xD3, xD3); break; } - case Close: { + case TitleBarButtonStyle::Close: { QRect rect(centerX - xD / 2, xD, xD - 1, xD - 1); painter.setPen(QPen(color, 1)); @@ -62,7 +62,7 @@ void TitleBarButton::paintEvent(QPaintEvent *event) painter.drawLine(rect.topRight(), rect.bottomLeft()); break; } - case User: { + case TitleBarButtonStyle::User: { color = "#999"; painter.setRenderHint(QPainter::Antialiasing); @@ -88,7 +88,7 @@ void TitleBarButton::paintEvent(QPaintEvent *event) break; } - case Settings: { + case TitleBarButtonStyle::Settings: { color = "#999"; painter.setRenderHint(QPainter::Antialiasing); painter.setRenderHint(QPainter::HighQualityAntialiasing); diff --git a/src/widgets/helper/TitlebarButton.hpp b/src/widgets/helper/TitlebarButton.hpp index 33777660f..ed1261e9e 100644 --- a/src/widgets/helper/TitlebarButton.hpp +++ b/src/widgets/helper/TitlebarButton.hpp @@ -4,29 +4,29 @@ namespace chatterino { +enum class TitleBarButtonStyle { + None = 0, + Minimize = 1, + Maximize = 2, + Unmaximize = 4, + Close = 8, + User = 16, + Settings = 32 +}; + class TitleBarButton : public Button { public: - enum Style { - None = 0, - Minimize = 1, - Maximize = 2, - Unmaximize = 4, - Close = 8, - User = 16, - Settings = 32 - }; - TitleBarButton(); - Style getButtonStyle() const; - void setButtonStyle(Style style_); + TitleBarButtonStyle getButtonStyle() const; + void setButtonStyle(TitleBarButtonStyle style_); protected: void paintEvent(QPaintEvent *) override; private: - Style style_; + TitleBarButtonStyle style_; }; } // namespace chatterino diff --git a/src/widgets/settingspages/IgnoresPage.cpp b/src/widgets/settingspages/IgnoresPage.cpp index 51d7cda71..b23ecbb89 100644 --- a/src/widgets/settingspages/IgnoresPage.cpp +++ b/src/widgets/settingspages/IgnoresPage.cpp @@ -4,6 +4,7 @@ #include "controllers/accounts/AccountController.hpp" #include "controllers/ignores/IgnoreController.hpp" #include "controllers/ignores/IgnoreModel.hpp" +#include "providers/twitch/TwitchAccount.hpp" #include "singletons/Settings.hpp" #include "util/LayoutCreator.hpp" #include "widgets/helper/EditableModelView.hpp" diff --git a/src/widgets/settingspages/LookPage.cpp b/src/widgets/settingspages/LookPage.cpp index 8cdcfd5f9..08a6ec77a 100644 --- a/src/widgets/settingspages/LookPage.cpp +++ b/src/widgets/settingspages/LookPage.cpp @@ -1,10 +1,14 @@ #include "LookPage.hpp" #include "Application.hpp" +#include "messages/Image.hpp" #include "messages/MessageBuilder.hpp" +#include "singletons/Resources.hpp" +#include "singletons/Theme.hpp" #include "singletons/WindowManager.hpp" #include "util/LayoutCreator.hpp" #include "util/RemoveScrollAreaBackground.hpp" +#include "widgets/helper/ChannelView.hpp" #include "widgets/helper/Line.hpp" #include @@ -416,7 +420,7 @@ QLayout *LookPage::createFontChanger() button->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Policy::Fixed); QObject::connect(button, &QPushButton::clicked, [=]() { - QFontDialog dialog(app->fonts->getFont(Fonts::ChatMedium, 1.)); + QFontDialog dialog(app->fonts->getFont(FontStyle::ChatMedium, 1.)); dialog.setWindowFlag(Qt::WindowStaysOnTopHint); diff --git a/src/widgets/splits/Split.cpp b/src/widgets/splits/Split.cpp index 38b390697..01a2faaad 100644 --- a/src/widgets/splits/Split.cpp +++ b/src/widgets/splits/Split.cpp @@ -1,8 +1,8 @@ #include "widgets/splits/Split.hpp" -#include "Application.hpp" #include "common/Common.hpp" #include "common/NetworkRequest.hpp" +#include "debug/Log.hpp" #include "providers/twitch/EmoteValue.hpp" #include "providers/twitch/TwitchChannel.hpp" #include "providers/twitch/TwitchMessageBuilder.hpp" @@ -11,15 +11,20 @@ #include "singletons/Theme.hpp" #include "singletons/WindowManager.hpp" #include "util/StreamLink.hpp" +#include "widgets/Notebook.hpp" #include "widgets/Window.hpp" #include "widgets/dialogs/QualityPopup.hpp" #include "widgets/dialogs/SelectChannelDialog.hpp" #include "widgets/dialogs/TextInputDialog.hpp" #include "widgets/dialogs/UserInfoPopup.hpp" +#include "widgets/helper/ChannelView.hpp" #include "widgets/helper/DebugPopup.hpp" +#include "widgets/helper/ResizingTextEdit.hpp" #include "widgets/helper/SearchPopup.hpp" #include "widgets/helper/Shortcut.hpp" #include "widgets/splits/SplitContainer.hpp" +#include "widgets/splits/SplitHeader.hpp" +#include "widgets/splits/SplitInput.hpp" #include "widgets/splits/SplitOverlay.hpp" #include @@ -37,7 +42,6 @@ #include namespace chatterino { - pajlada::Signals::Signal Split::modifierStatusChanged; Qt::KeyboardModifiers Split::modifierStatus = Qt::NoModifier; @@ -51,20 +55,20 @@ Split::Split(QWidget *parent) : BaseWidget(parent) , container_(nullptr) , channel_(Channel::getEmpty()) - , vbox_(this) - , header_(this) - , view_(this) - , input_(this) + , vbox_(new QVBoxLayout(this)) + , header_(new SplitHeader(this)) + , view_(new ChannelView(this)) + , input_(new SplitInput(this)) , overlay_(new SplitOverlay(this)) { this->setMouseTracking(true); - this->vbox_.setSpacing(0); - this->vbox_.setMargin(1); + this->vbox_->setSpacing(0); + this->vbox_->setMargin(1); - this->vbox_.addWidget(&this->header_); - this->vbox_.addWidget(&this->view_, 1); - this->vbox_.addWidget(&this->input_); + this->vbox_->addWidget(this->header_); + this->vbox_->addWidget(this->view_, 1); + this->vbox_->addWidget(this->input_); // Initialize chat widget-wide hotkeys // CTRL+W: Close Split @@ -89,41 +93,41 @@ Split::Split(QWidget *parent) // CreateShortcut(this, "ALT+SHIFT+UP", &Split::doIncFlexY); // CreateShortcut(this, "ALT+SHIFT+DOWN", &Split::doDecFlexY); - this->input_.ui_.textEdit->installEventFilter(parent); + this->input_->ui_.textEdit->installEventFilter(parent); - this->view_.mouseDown.connect([this](QMouseEvent *) { + this->view_->mouseDown.connect([this](QMouseEvent *) { // this->giveFocus(Qt::MouseFocusReason); }); - this->view_.selectionChanged.connect([this]() { - if (view_.hasSelection()) { - this->input_.clearSelection(); + this->view_->selectionChanged.connect([this]() { + if (view_->hasSelection()) { + this->input_->clearSelection(); } }); - this->input_.textChanged.connect([=](const QString &newText) { + this->input_->textChanged.connect([=](const QString &newText) { if (getSettings()->showEmptyInput) { return; } if (newText.length() == 0) { - this->input_.hide(); - } else if (this->input_.isHidden()) { - this->input_.show(); + this->input_->hide(); + } else if (this->input_->isHidden()) { + this->input_->show(); } }); getSettings()->showEmptyInput.connect( [this](const bool &showEmptyInput, auto) { - if (!showEmptyInput && this->input_.getInputText().length() == 0) { - this->input_.hide(); + if (!showEmptyInput && this->input_->getInputText().length() == 0) { + this->input_->hide(); } else { - this->input_.show(); + this->input_->show(); } }, this->managedConnections_); - this->header_.updateModerationModeIcon(); + this->header_->updateModerationModeIcon(); this->overlay_->hide(); this->setSizePolicy(QSizePolicy::MinimumExpanding, @@ -139,9 +143,9 @@ Split::Split(QWidget *parent) } }); - this->input_.ui_.textEdit->focused.connect( + this->input_->ui_.textEdit->focused.connect( [this] { this->focused.invoke(); }); - this->input_.ui_.textEdit->focusLost.connect( + this->input_->ui_.textEdit->focusLost.connect( [this] { this->focusLost.invoke(); }); } @@ -155,7 +159,7 @@ Split::~Split() ChannelView &Split::getChannelView() { - return this->view_; + return *this->view_; } SplitContainer *Split::getContainer() @@ -187,7 +191,7 @@ void Split::setChannel(IndirectChannel newChannel) { this->channel_ = newChannel; - this->view_.setChannel(newChannel.get()); + this->view_->setChannel(newChannel.get()); this->usermodeChangedConnection_.disconnect(); this->roomModeChangedConnection_.disconnect(); @@ -197,12 +201,12 @@ void Split::setChannel(IndirectChannel newChannel) if (tc != nullptr) { this->usermodeChangedConnection_ = tc->userStateChanged.connect([this] { - this->header_.updateModerationModeIcon(); - this->header_.updateRoomModes(); + this->header_->updateModerationModeIcon(); + this->header_->updateRoomModes(); }); this->roomModeChangedConnection_ = tc->roomModesChanged.connect( - [this] { this->header_.updateRoomModes(); }); + [this] { this->header_->updateRoomModes(); }); } this->indirectChannelChangedConnection_ = @@ -210,9 +214,9 @@ void Split::setChannel(IndirectChannel newChannel) QTimer::singleShot(0, [this] { this->setChannel(this->channel_); }); }); - this->header_.updateModerationModeIcon(); - this->header_.updateChannelText(); - this->header_.updateRoomModes(); + this->header_->updateModerationModeIcon(); + this->header_->updateChannelText(); + this->header_->updateRoomModes(); this->channelChanged.invoke(); } @@ -221,8 +225,8 @@ void Split::setModerationMode(bool value) { if (value != this->moderationMode_) { this->moderationMode_ = value; - this->header_.updateModerationModeIcon(); - this->view_.layoutMessages(); + this->header_->updateModerationModeIcon(); + this->view_->layoutMessages(); } } @@ -233,7 +237,7 @@ bool Split::getModerationMode() const void Split::insertTextToInput(const QString &text) { - this->input_.insertText(text); + this->input_->insertText(text); } void Split::showChangeChannelPopup(const char *dialogTitle, bool empty, @@ -267,27 +271,27 @@ void Split::showChangeChannelPopup(const char *dialogTitle, bool empty, void Split::layoutMessages() { - this->view_.layoutMessages(); + this->view_->layoutMessages(); } void Split::updateGifEmotes() { - this->view_.queueUpdate(); + this->view_->queueUpdate(); } void Split::updateLastReadMessage() { - this->view_.updateLastReadMessage(); + this->view_->updateLastReadMessage(); } void Split::giveFocus(Qt::FocusReason reason) { - this->input_.ui_.textEdit->setFocus(reason); + this->input_->ui_.textEdit->setFocus(reason); } bool Split::hasFocus() const { - return this->input_.ui_.textEdit->hasFocus(); + return this->input_->ui_.textEdit->hasFocus(); } void Split::paintEvent(QPaintEvent *) @@ -305,13 +309,13 @@ void Split::mouseMoveEvent(QMouseEvent *event) void Split::keyPressEvent(QKeyEvent *event) { - this->view_.unsetCursor(); + this->view_->unsetCursor(); this->handleModifiers(QGuiApplication::queryKeyboardModifiers()); } void Split::keyReleaseEvent(QKeyEvent *event) { - this->view_.unsetCursor(); + this->view_->unsetCursor(); this->handleModifiers(QGuiApplication::queryKeyboardModifiers()); } @@ -389,7 +393,7 @@ void Split::changeChannel() void Split::popup() { auto app = getApp(); - Window &window = app->windows->createWindow(Window::Type::Popup); + Window &window = app->windows->createWindow(WindowType::Popup); Split *split = new Split(static_cast( window.getNotebook().getOrAddSelectedPage())); @@ -402,7 +406,7 @@ void Split::popup() void Split::clear() { - this->view_.clearMessages(); + this->view_->clearMessages(); } void Split::openInBrowser() @@ -442,8 +446,8 @@ void Split::showViewerList() QDockWidget::DockWidgetFloatable); viewerDock->resize( 0.5 * this->width(), - this->height() - this->header_.height() - this->input_.height()); - viewerDock->move(0, this->header_.height()); + this->height() - this->header_->height() - this->input_->height()); + viewerDock->move(0, this->header_->height()); auto multiWidget = new QWidget(viewerDock); auto dockVbox = new QVBoxLayout(viewerDock); @@ -543,7 +547,7 @@ void Split::showUserInfoPopup(const UserName &user) void Split::copyToClipboard() { - QApplication::clipboard()->setText(this->view_.getSelectedText()); + QApplication::clipboard()->setText(this->view_->getSelectedText()); } void Split::showSearch() diff --git a/src/widgets/splits/Split.hpp b/src/widgets/splits/Split.hpp index ca185dbdb..8c4ebf84a 100644 --- a/src/widgets/splits/Split.hpp +++ b/src/widgets/splits/Split.hpp @@ -1,17 +1,9 @@ #pragma once +#include "common/Aliases.hpp" #include "common/Channel.hpp" #include "common/NullablePtr.hpp" -#include "messages/LimitedQueueSnapshot.hpp" -#include "messages/MessageElement.hpp" -#include "messages/layouts/MessageLayout.hpp" -#include "messages/layouts/MessageLayoutElement.hpp" -#include "util/RapidJsonSerializeQString.hpp" #include "widgets/BaseWidget.hpp" -#include "widgets/helper/ChannelView.hpp" -#include "widgets/helper/EffectLabel.hpp" -#include "widgets/splits/SplitHeader.hpp" -#include "widgets/splits/SplitInput.hpp" #include #include @@ -20,6 +12,9 @@ namespace chatterino { +class ChannelView; +class SplitHeader; +class SplitInput; class SplitContainer; class SplitOverlay; class SelectChannelDialog; @@ -103,10 +98,10 @@ private: SplitContainer *container_; IndirectChannel channel_; - QVBoxLayout vbox_; - SplitHeader header_; - ChannelView view_; - SplitInput input_; + QVBoxLayout *vbox_; + SplitHeader *header_; + ChannelView *view_; + SplitInput *input_; SplitOverlay *overlay_; NullablePtr selectChannelDialog_; diff --git a/src/widgets/splits/SplitContainer.cpp b/src/widgets/splits/SplitContainer.cpp index ecbadc21d..cac6f2dfb 100644 --- a/src/widgets/splits/SplitContainer.cpp +++ b/src/widgets/splits/SplitContainer.cpp @@ -7,6 +7,7 @@ #include "util/Helpers.hpp" #include "util/LayoutCreator.hpp" #include "widgets/Notebook.hpp" +#include "widgets/helper/ChannelView.hpp" #include "widgets/helper/NotebookTab.hpp" #include "widgets/splits/Split.hpp" diff --git a/src/widgets/splits/SplitContainer.hpp b/src/widgets/splits/SplitContainer.hpp index 7bd2ced1a..1f0a2e701 100644 --- a/src/widgets/splits/SplitContainer.hpp +++ b/src/widgets/splits/SplitContainer.hpp @@ -1,8 +1,6 @@ #pragma once #include "widgets/BaseWidget.hpp" -#include "widgets/helper/NotebookTab.hpp" -#include "widgets/splits/Split.hpp" #include #include @@ -13,21 +11,24 @@ #include #include -#include - #include #include +#include class QJsonObject; namespace chatterino { +class Split; +class NotebookTab; +class Notebook; + // // Note: This class is a spaghetti container. There is a lot of spaghetti code // inside but it doesn't expose any of it publicly. // -class SplitContainer : public BaseWidget, pajlada::Signals::SignalHolder +class SplitContainer final : public BaseWidget, pajlada::Signals::SignalHolder { Q_OBJECT diff --git a/src/widgets/splits/SplitHeader.cpp b/src/widgets/splits/SplitHeader.cpp index 882f0b9eb..d99448221 100644 --- a/src/widgets/splits/SplitHeader.cpp +++ b/src/widgets/splits/SplitHeader.cpp @@ -5,17 +5,20 @@ #include "providers/twitch/TwitchChannel.hpp" #include "providers/twitch/TwitchServer.hpp" #include "singletons/Resources.hpp" +#include "singletons/Settings.hpp" #include "singletons/Theme.hpp" #include "util/LayoutCreator.hpp" #include "util/LayoutHelper.hpp" #include "widgets/Label.hpp" #include "widgets/TooltipWidget.hpp" +#include "widgets/helper/EffectLabel.hpp" #include "widgets/splits/Split.hpp" #include "widgets/splits/SplitContainer.hpp" #include #include #include +#include #include #include #include diff --git a/src/widgets/splits/SplitInput.cpp b/src/widgets/splits/SplitInput.cpp index 65bc37e5c..8fbc62f02 100644 --- a/src/widgets/splits/SplitInput.cpp +++ b/src/widgets/splits/SplitInput.cpp @@ -2,14 +2,20 @@ #include "Application.hpp" #include "controllers/commands/CommandController.hpp" +#include "messages/Link.hpp" #include "providers/twitch/TwitchChannel.hpp" #include "providers/twitch/TwitchServer.hpp" #include "singletons/Settings.hpp" #include "singletons/Theme.hpp" #include "util/LayoutCreator.hpp" #include "widgets/Notebook.hpp" +#include "widgets/dialogs/EmotePopup.hpp" +#include "widgets/helper/ChannelView.hpp" +#include "widgets/helper/EffectLabel.hpp" +#include "widgets/helper/ResizingTextEdit.hpp" #include "widgets/splits/Split.hpp" #include "widgets/splits/SplitContainer.hpp" +#include "widgets/splits/SplitInput.hpp" #include #include @@ -70,11 +76,11 @@ void SplitInput::initLayout() // set edit font this->ui_.textEdit->setFont( - app->fonts->getFont(Fonts::Type::ChatMedium, this->getScale())); + app->fonts->getFont(FontStyle::ChatMedium, this->getScale())); this->managedConnections_.push_back(app->fonts->fontChanged.connect([=]() { this->ui_.textEdit->setFont( - app->fonts->getFont(Fonts::Type::ChatMedium, this->getScale())); + app->fonts->getFont(FontStyle::ChatMedium, this->getScale())); })); // open emote popup @@ -98,7 +104,7 @@ void SplitInput::initLayout() QObject::connect(this->ui_.textEdit, &QTextEdit::copyAvailable, [this](bool available) { if (available) { - this->split_->view_.clearSelection(); + this->split_->view_->clearSelection(); } }); @@ -273,7 +279,7 @@ void SplitInput::installKeyPressedEvent() } } else if (event->key() == Qt::Key_C && event->modifiers() == Qt::ControlModifier) { - if (this->split_->view_.hasSelection()) { + if (this->split_->view_->hasSelection()) { this->split_->copyToClipboard(); event->accept(); } diff --git a/src/widgets/splits/SplitInput.hpp b/src/widgets/splits/SplitInput.hpp index ddcf2c97d..6ad6f4f83 100644 --- a/src/widgets/splits/SplitInput.hpp +++ b/src/widgets/splits/SplitInput.hpp @@ -1,9 +1,6 @@ #pragma once #include "widgets/BaseWidget.hpp" -#include "widgets/dialogs/EmotePopup.hpp" -#include "widgets/helper/ResizingTextEdit.hpp" -#include "widgets/helper/EffectLabel.hpp" #include #include @@ -16,6 +13,9 @@ namespace chatterino { class Split; +class EmotePopup; +class EffectLabel; +class ResizingTextEdit; class SplitInput : public BaseWidget { @@ -45,7 +45,7 @@ private: void updateEmoteButton(); Split *const split_; - std::unique_ptr emotePopup_; + std::shared_ptr emotePopup_; struct { ResizingTextEdit *textEdit; diff --git a/src/widgets/splits/SplitOverlay.cpp b/src/widgets/splits/SplitOverlay.cpp index 268811b20..1b38c0ca2 100644 --- a/src/widgets/splits/SplitOverlay.cpp +++ b/src/widgets/splits/SplitOverlay.cpp @@ -10,6 +10,7 @@ #include "Application.hpp" #include "singletons/Resources.hpp" +#include "singletons/Theme.hpp" #include "widgets/splits/Split.hpp" #include "widgets/splits/SplitContainer.hpp" From b3fd278c3cbd091dd21c0ae4e1a9f16566c659ce Mon Sep 17 00:00:00 2001 From: Touhou-fan <30899927+Touhou-fan@users.noreply.github.com> Date: Sat, 11 Aug 2018 23:53:20 +0200 Subject: [PATCH 02/14] Fix selecting incorrect image (#659) --- src/messages/ImageSet.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/messages/ImageSet.cpp b/src/messages/ImageSet.cpp index 0e500816f..1019d27e9 100644 --- a/src/messages/ImageSet.cpp +++ b/src/messages/ImageSet.cpp @@ -76,7 +76,7 @@ const ImagePtr &ImageSet::getImage(float scale) const } if (!this->imageX2_->isEmpty() && quality == 2) { - return this->imageX3_; + return this->imageX2_; } return this->imageX1_; From 1ec1ecd52b67c750d8d9765db2bcf5420784eb3b Mon Sep 17 00:00:00 2001 From: fourtf Date: Sun, 12 Aug 2018 00:01:37 +0200 Subject: [PATCH 03/14] fixed crash when moderation buttons are enabled --- .../moderationactions/ModerationActions.cpp | 8 ++++-- .../moderationactions/ModerationActions.hpp | 3 +- src/providers/bttv/BttvEmotes.cpp | 7 +++-- src/providers/bttv/BttvEmotes.hpp | 15 ++++++---- src/providers/emoji/Emojis.cpp | 25 +++-------------- src/providers/ffz/FfzEmotes.cpp | 9 +++--- src/providers/ffz/FfzEmotes.hpp | 15 ++++++---- src/providers/twitch/TwitchChannel.cpp | 19 +++++++++++-- src/providers/twitch/TwitchChannel.hpp | 28 +++++++++++++------ src/providers/twitch/TwitchMessageBuilder.cpp | 7 ++--- src/providers/twitch/TwitchServer.cpp | 7 +++-- src/providers/twitch/TwitchServer.hpp | 4 +++ src/singletons/Emotes.cpp | 2 -- src/singletons/Emotes.hpp | 2 -- src/widgets/dialogs/EmotePopup.cpp | 6 ++-- 15 files changed, 89 insertions(+), 68 deletions(-) diff --git a/src/controllers/moderationactions/ModerationActions.cpp b/src/controllers/moderationactions/ModerationActions.cpp index 68070f6b2..27cd5de30 100644 --- a/src/controllers/moderationactions/ModerationActions.cpp +++ b/src/controllers/moderationactions/ModerationActions.cpp @@ -17,12 +17,16 @@ void ModerationActions::initialize(Settings &settings, Paths &paths) assert(!this->initialized_); this->initialized_ = true; - for (auto &val : this->setting_.getValue()) { + this->setting_ = + std::make_unique>>( + "/moderation/actions"); + + for (auto &val : this->setting_->getValue()) { this->items.insertItem(val); } this->items.delayedItemsChanged.connect([this] { // - this->setting_.setValue(this->items.getVector()); + this->setting_->setValue(this->items.getVector()); }); } diff --git a/src/controllers/moderationactions/ModerationActions.hpp b/src/controllers/moderationactions/ModerationActions.hpp index d5e510f1c..08314eb22 100644 --- a/src/controllers/moderationactions/ModerationActions.hpp +++ b/src/controllers/moderationactions/ModerationActions.hpp @@ -25,8 +25,7 @@ public: ModerationActionModel *createModel(QObject *parent); private: - ChatterinoSetting> setting_ = { - "/moderation/actions"}; + std::unique_ptr>> setting_; bool initialized_ = false; }; diff --git a/src/providers/bttv/BttvEmotes.cpp b/src/providers/bttv/BttvEmotes.cpp index 70c7cdbdb..cf32bd414 100644 --- a/src/providers/bttv/BttvEmotes.cpp +++ b/src/providers/bttv/BttvEmotes.cpp @@ -3,6 +3,7 @@ #include "common/Common.hpp" #include "common/NetworkRequest.hpp" #include "debug/Log.hpp" +#include "messages/Emote.hpp" #include "messages/Image.hpp" #include "messages/ImageSet.hpp" #include "providers/twitch/TwitchChannel.hpp" @@ -89,12 +90,12 @@ BttvEmotes::BttvEmotes() { } -std::shared_ptr BttvEmotes::global() const +std::shared_ptr BttvEmotes::emotes() const { return this->global_.get(); } -boost::optional BttvEmotes::global(const EmoteName &name) const +boost::optional BttvEmotes::emote(const EmoteName &name) const { auto emotes = this->global_.get(); auto it = emotes->find(name); @@ -103,7 +104,7 @@ boost::optional BttvEmotes::global(const EmoteName &name) const return it->second; } -void BttvEmotes::loadGlobal() +void BttvEmotes::loadEmotes() { auto request = NetworkRequest(QString(globalEmoteApiUrl)); diff --git a/src/providers/bttv/BttvEmotes.hpp b/src/providers/bttv/BttvEmotes.hpp index ff4809411..c82cb67a4 100644 --- a/src/providers/bttv/BttvEmotes.hpp +++ b/src/providers/bttv/BttvEmotes.hpp @@ -1,13 +1,16 @@ #pragma once -#include #include - +#include "boost/optional.hpp" +#include "common/Aliases.hpp" #include "common/Atomic.hpp" -#include "messages/Emote.hpp" namespace chatterino { +struct Emote; +using EmotePtr = std::shared_ptr; +class EmoteMap; + class BttvEmotes final { static constexpr const char *globalEmoteApiUrl = @@ -18,9 +21,9 @@ class BttvEmotes final public: BttvEmotes(); - std::shared_ptr global() const; - boost::optional global(const EmoteName &name) const; - void loadGlobal(); + std::shared_ptr emotes() const; + boost::optional emote(const EmoteName &name) const; + void loadEmotes(); static void loadChannel(const QString &channelName, std::function callback); diff --git a/src/providers/emoji/Emojis.cpp b/src/providers/emoji/Emojis.cpp index d0403e75c..18ce18139 100644 --- a/src/providers/emoji/Emojis.cpp +++ b/src/providers/emoji/Emojis.cpp @@ -104,12 +104,10 @@ void Emojis::load() void Emojis::loadEmojis() { - std::map toneNames; - toneNames["1F3FB"] = "tone1"; - toneNames["1F3FC"] = "tone2"; - toneNames["1F3FD"] = "tone3"; - toneNames["1F3FE"] = "tone4"; - toneNames["1F3FF"] = "tone5"; + auto toneNames = std::map{ + {"1F3FB", "tone1"}, {"1F3FC", "tone2"}, {"1F3FD", "tone3"}, + {"1F3FE", "tone4"}, {"1F3FF", "tone5"}, + }; QFile file(":/emoji.json"); file.open(QFile::ReadOnly); @@ -234,27 +232,12 @@ void Emojis::loadEmojiSet() // {"Google", "https://cdn.jsdelivr.net/npm/emoji-datasource-google@4.0.4/img/google/64/"}, // {"Messenger", "https://cdn.jsdelivr.net/npm/emoji-datasource-messenger@4.0.4/img/messenger/64/"}, - // {"EmojiOne 2", "https://cdnjs.cloudflare.com/ajax/libs/emojione/2.2.6/assets/png/"}, - // {"EmojiOne 3", "https://braize.pajlada.com/emoji/img/emojione/64/"}, - // {"Twitter", "https://braize.pajlada.com/emoji/img/twitter/64/"}, - // {"Facebook", "https://braize.pajlada.com/emoji/img/facebook/64/"}, - // {"Apple", "https://braize.pajlada.com/emoji/img/apple/64/"}, - // {"Google", "https://braize.pajlada.com/emoji/img/google/64/"}, - // {"Messenger", "https://braize.pajlada.com/emoji/img/messenger/64/"}, - {"EmojiOne 3", "https://pajbot.com/static/emoji/img/emojione/64/"}, {"Twitter", "https://pajbot.com/static/emoji/img/twitter/64/"}, {"Facebook", "https://pajbot.com/static/emoji/img/facebook/64/"}, {"Apple", "https://pajbot.com/static/emoji/img/apple/64/"}, {"Google", "https://pajbot.com/static/emoji/img/google/64/"}, {"Messenger", "https://pajbot.com/static/emoji/img/messenger/64/"}, - -// {"EmojiOne 3", "https://cdn.fourtf.com/emoji/emojione/64/"}, -// {"Twitter", "https://cdn.fourtf.com/emoji/twitter/64/"}, -// {"Facebook", "https://cdn.fourtf.com/emoji/facebook/64/"}, -// {"Apple", "https://cdn.fourtf.com/emoji/apple/64/"}, -// {"Google", "https://cdn.fourtf.com/emoji/google/64/"}, -// {"Messenger", "https://cdn.fourtf.com/emoji/messenger/64/"}, }; // clang-format on diff --git a/src/providers/ffz/FfzEmotes.cpp b/src/providers/ffz/FfzEmotes.cpp index c22fe91fe..f8be4baa0 100644 --- a/src/providers/ffz/FfzEmotes.cpp +++ b/src/providers/ffz/FfzEmotes.cpp @@ -5,6 +5,7 @@ #include "common/NetworkRequest.hpp" #include "common/Outcome.hpp" #include "debug/Log.hpp" +#include "messages/Emote.hpp" #include "messages/Image.hpp" namespace chatterino { @@ -109,12 +110,12 @@ FfzEmotes::FfzEmotes() { } -std::shared_ptr FfzEmotes::global() const +std::shared_ptr FfzEmotes::emotes() const { return this->global_.get(); } -boost::optional FfzEmotes::global(const EmoteName &name) const +boost::optional FfzEmotes::emote(const EmoteName &name) const { auto emotes = this->global_.get(); auto it = emotes->find(name); @@ -122,7 +123,7 @@ boost::optional FfzEmotes::global(const EmoteName &name) const return boost::none; } -void FfzEmotes::loadGlobal() +void FfzEmotes::loadEmotes() { QString url("https://api.frankerfacez.com/v1/set/global"); @@ -131,7 +132,7 @@ void FfzEmotes::loadGlobal() request.setTimeout(30000); request.onSuccess([this](auto result) -> Outcome { - auto emotes = this->global(); + auto emotes = this->emotes(); auto pair = parseGlobalEmotes(result.parseJson(), *emotes); if (pair.first) this->global_.set( diff --git a/src/providers/ffz/FfzEmotes.hpp b/src/providers/ffz/FfzEmotes.hpp index cc75b09bd..8214cbf80 100644 --- a/src/providers/ffz/FfzEmotes.hpp +++ b/src/providers/ffz/FfzEmotes.hpp @@ -1,24 +1,27 @@ #pragma once #include +#include "boost/optional.hpp" +#include "common/Aliases.hpp" #include "common/Atomic.hpp" -#include "messages/Emote.hpp" namespace chatterino { +struct Emote; +using EmotePtr = std::shared_ptr; +class EmoteMap; + class FfzEmotes final { static constexpr const char *globalEmoteApiUrl = "https://api.frankerfacez.com/v1/set/global"; - static constexpr const char *channelEmoteApiUrl = - "https://api.betterttv.net/2/channels/"; public: FfzEmotes(); - std::shared_ptr global() const; - boost::optional global(const EmoteName &name) const; - void loadGlobal(); + std::shared_ptr emotes() const; + boost::optional emote(const EmoteName &name) const; + void loadEmotes(); static void loadChannel(const QString &channelName, std::function callback); diff --git a/src/providers/twitch/TwitchChannel.cpp b/src/providers/twitch/TwitchChannel.cpp index 0bb7ffe9c..6413629f6 100644 --- a/src/providers/twitch/TwitchChannel.cpp +++ b/src/providers/twitch/TwitchChannel.cpp @@ -51,13 +51,16 @@ auto parseRecentMessages(const QJsonObject &jsonRoot, TwitchChannel &channel) } } // namespace -TwitchChannel::TwitchChannel(const QString &name) +TwitchChannel::TwitchChannel(const QString &name, BttvEmotes &bttv, + FfzEmotes &ffz) : Channel(name, Channel::Type::Twitch) - , bttvEmotes_(std::make_shared()) - , ffzEmotes_(std::make_shared()) , subscriptionUrl_("https://www.twitch.tv/subs/" + name) , channelUrl_("https://twitch.tv/" + name) , popoutPlayerUrl_("https://player.twitch.tv/?channel=" + name) + , globalBttv_(bttv) + , globalFfz_(ffz) + , bttvEmotes_(std::make_shared()) + , ffzEmotes_(std::make_shared()) , mod_(false) { log("[TwitchChannel:{}] Opened", name); @@ -290,6 +293,16 @@ TwitchChannel::accessStreamStatus() const return this->streamStatus_.accessConst(); } +const BttvEmotes &TwitchChannel::globalBttv() const +{ + return this->globalBttv_; +} + +const FfzEmotes &TwitchChannel::globalFfz() const +{ + return this->globalFfz_; +} + boost::optional TwitchChannel::bttvEmote(const EmoteName &name) const { auto emotes = this->bttvEmotes_.get(); diff --git a/src/providers/twitch/TwitchChannel.hpp b/src/providers/twitch/TwitchChannel.hpp index 940da72bf..a444d26e2 100644 --- a/src/providers/twitch/TwitchChannel.hpp +++ b/src/providers/twitch/TwitchChannel.hpp @@ -19,6 +19,9 @@ struct Emote; using EmotePtr = std::shared_ptr; class EmoteMap; +class FfzEmotes; +class BttvEmotes; + class TwitchServer; class TwitchChannel final : public Channel, pajlada::Signals::SignalHolder @@ -60,25 +63,28 @@ public: void addJoinedUser(const QString &user); void addPartedUser(const QString &user); - // Twitch data bool isLive() const; virtual bool isMod() const override; void setMod(bool value); virtual bool isBroadcaster() const override; + // Data + const QString &subscriptionUrl(); + const QString &channelUrl(); + const QString &popoutPlayerUrl(); QString roomId() const; void setRoomId(const QString &id); AccessGuard accessRoomModes() const; void setRoomModes(const RoomModes &roomModes_); AccessGuard accessStreamStatus() const; + // Emotes + const BttvEmotes &globalBttv() const; + const FfzEmotes &globalFfz() const; boost::optional bttvEmote(const EmoteName &name) const; boost::optional ffzEmote(const EmoteName &name) const; std::shared_ptr bttvEmotes() const; std::shared_ptr ffzEmotes() const; - const QString &subscriptionUrl(); - const QString &channelUrl(); - const QString &popoutPlayerUrl(); boost::optional getTwitchBadge(const QString &set, const QString &version) const; @@ -109,7 +115,8 @@ private: std::vector cheerEmotes; }; - explicit TwitchChannel(const QString &channelName); + explicit TwitchChannel(const QString &channelName, BttvEmotes &bttv, + FfzEmotes &ffz); // Methods void refreshLiveStatus(); @@ -124,16 +131,19 @@ private: void loadBadges(); void loadCheerEmotes(); - // Twitch data + // Data + const QString subscriptionUrl_; + const QString channelUrl_; + const QString popoutPlayerUrl_; UniqueAccess streamStatus_; UniqueAccess userState_; UniqueAccess roomModes_; + // Emotes + BttvEmotes &globalBttv_; + FfzEmotes &globalFfz_; Atomic> bttvEmotes_; Atomic> ffzEmotes_; - const QString subscriptionUrl_; - const QString channelUrl_; - const QString popoutPlayerUrl_; bool mod_ = false; UniqueAccess roomID_; diff --git a/src/providers/twitch/TwitchMessageBuilder.cpp b/src/providers/twitch/TwitchMessageBuilder.cpp index 67cd2998d..5b4cef199 100644 --- a/src/providers/twitch/TwitchMessageBuilder.cpp +++ b/src/providers/twitch/TwitchMessageBuilder.cpp @@ -640,12 +640,11 @@ Outcome TwitchMessageBuilder::tryAppendEmote(const EmoteName &name) auto flags = MessageElementFlags(); auto emote = boost::optional{}; - if ((emote = getApp()->emotes->bttv.global(name))) { + if ((emote = this->twitchChannel->globalBttv().emote(name))) { flags = MessageElementFlag::BttvEmote; - } else if (twitchChannel && - (emote = this->twitchChannel->bttvEmote(name))) { + } else if ((emote = this->twitchChannel->bttvEmote(name))) { flags = MessageElementFlag::BttvEmote; - } else if ((emote = getApp()->emotes->ffz.global(name))) { + } else if ((emote = this->twitchChannel->globalFfz().emote(name))) { flags = MessageElementFlag::FfzEmote; } else if (twitchChannel && (emote = this->twitchChannel->ffzEmote(name))) { flags = MessageElementFlag::FfzEmote; diff --git a/src/providers/twitch/TwitchServer.cpp b/src/providers/twitch/TwitchServer.cpp index e9325443c..bb7b16fd9 100644 --- a/src/providers/twitch/TwitchServer.cpp +++ b/src/providers/twitch/TwitchServer.cpp @@ -40,6 +40,9 @@ void TwitchServer::initialize(Settings &settings, Paths &paths) { getApp()->accounts->twitch.currentUserChanged.connect( [this]() { postToThread([this] { this->connect(); }); }); + + this->bttv.loadEmotes(); + this->ffz.loadEmotes(); } void TwitchServer::initializeConnection(IrcConnection *connection, bool isRead, @@ -80,8 +83,8 @@ void TwitchServer::initializeConnection(IrcConnection *connection, bool isRead, std::shared_ptr TwitchServer::createChannel(const QString &channelName) { - auto channel = - std::shared_ptr(new TwitchChannel(channelName)); + auto channel = std::shared_ptr( + new TwitchChannel(channelName, this->bttv, this->ffz)); channel->refreshChannelEmotes(); channel->sendMessageSignal.connect( diff --git a/src/providers/twitch/TwitchServer.hpp b/src/providers/twitch/TwitchServer.hpp index 72c4078bc..127c2f62b 100644 --- a/src/providers/twitch/TwitchServer.hpp +++ b/src/providers/twitch/TwitchServer.hpp @@ -4,6 +4,8 @@ #include "common/Channel.hpp" #include "common/Singleton.hpp" #include "pajlada/signals/signalholder.hpp" +#include "providers/bttv/BttvEmotes.hpp" +#include "providers/ffz/FfzEmotes.hpp" #include "providers/irc/AbstractIrcServer.hpp" #include @@ -66,6 +68,8 @@ private: std::chrono::steady_clock::time_point lastErrorTimeAmount_; bool singleConnection_ = false; + BttvEmotes bttv; + FfzEmotes ffz; pajlada::Signals::SignalHolder signalHolder_; }; diff --git a/src/singletons/Emotes.cpp b/src/singletons/Emotes.cpp index cfc23f6d4..9916d2046 100644 --- a/src/singletons/Emotes.cpp +++ b/src/singletons/Emotes.cpp @@ -15,8 +15,6 @@ void Emotes::initialize(Settings &settings, Paths &paths) [] { getApp()->accounts->twitch.getCurrent()->loadEmotes(); }); this->emojis.load(); - this->bttv.loadGlobal(); - this->ffz.loadGlobal(); this->gifTimer.initialize(); } diff --git a/src/singletons/Emotes.hpp b/src/singletons/Emotes.hpp index e991fe674..fc475d752 100644 --- a/src/singletons/Emotes.hpp +++ b/src/singletons/Emotes.hpp @@ -25,8 +25,6 @@ public: bool isIgnoredEmote(const QString &emote); TwitchEmotes twitch; - BttvEmotes bttv; - FfzEmotes ffz; Emojis emojis; GIFTimer gifTimer; diff --git a/src/widgets/dialogs/EmotePopup.cpp b/src/widgets/dialogs/EmotePopup.cpp index 92435065d..ade2a88a5 100644 --- a/src/widgets/dialogs/EmotePopup.cpp +++ b/src/widgets/dialogs/EmotePopup.cpp @@ -125,8 +125,10 @@ void EmotePopup::loadChannel(ChannelPtr _channel) *globalChannel, *subChannel); // global - addEmotes(*globalChannel, *getApp()->emotes->bttv.global(), "BetterTTV"); - addEmotes(*globalChannel, *getApp()->emotes->ffz.global(), "FrankerFaceZ"); + addEmotes(*globalChannel, *twitchChannel->globalBttv().emotes(), + "BetterTTV"); + addEmotes(*globalChannel, *twitchChannel->globalBttv().emotes(), + "FrankerFaceZ"); // channel addEmotes(*channelChannel, *twitchChannel->bttvEmotes(), "BetterTTV"); From 7ff4f12257dc28eda587c4a0c889cb2b4c2c9aaa Mon Sep 17 00:00:00 2001 From: Lajamerr Mittesdine Date: Sat, 11 Aug 2018 19:12:03 -0400 Subject: [PATCH 04/14] Fix Global FFZ emotes in Emote Popup (#663) There was two instances of Global BTTV emotes. Changed the second instance to Global FFZ emotes. --- src/widgets/dialogs/EmotePopup.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/widgets/dialogs/EmotePopup.cpp b/src/widgets/dialogs/EmotePopup.cpp index ade2a88a5..735d68f63 100644 --- a/src/widgets/dialogs/EmotePopup.cpp +++ b/src/widgets/dialogs/EmotePopup.cpp @@ -127,7 +127,7 @@ void EmotePopup::loadChannel(ChannelPtr _channel) // global addEmotes(*globalChannel, *twitchChannel->globalBttv().emotes(), "BetterTTV"); - addEmotes(*globalChannel, *twitchChannel->globalBttv().emotes(), + addEmotes(*globalChannel, *twitchChannel->globalFfz().emotes(), "FrankerFaceZ"); // channel From f6414c9d7e90fb17f10dad1fe112210889b142be Mon Sep 17 00:00:00 2001 From: fourtf Date: Sun, 12 Aug 2018 12:56:28 +0200 Subject: [PATCH 05/14] remove settings and paths from Application --- src/Application.cpp | 4 +-- src/Application.hpp | 2 -- src/RunGui.cpp | 2 +- src/common/NetworkData.cpp | 2 +- src/common/NetworkRequest.cpp | 2 +- src/controllers/highlights/HighlightModel.cpp | 21 ++++++------- .../taggedusers/TaggedUsersModel.cpp | 12 +++---- src/messages/MessageElement.cpp | 6 ++-- src/messages/layouts/MessageLayout.cpp | 8 ++--- .../layouts/MessageLayoutContainer.cpp | 4 +-- src/providers/emoji/Emojis.cpp | 2 +- src/providers/twitch/IrcMessageHandler.cpp | 2 +- src/providers/twitch/TwitchMessageBuilder.cpp | 16 +++++----- src/singletons/Fonts.cpp | 4 +-- src/singletons/Paths.hpp | 2 +- src/singletons/WindowManager.cpp | 4 +-- src/singletons/helper/GifTimer.cpp | 2 +- src/singletons/helper/LoggingChannel.cpp | 4 +-- src/util/StreamLink.cpp | 12 +++---- src/widgets/BaseWindow.cpp | 16 +++++----- src/widgets/Notebook.cpp | 8 ++--- src/widgets/Window.cpp | 18 +++++------ src/widgets/dialogs/SettingsDialog.cpp | 4 +-- src/widgets/helper/ChannelView.cpp | 31 ++++++------------- src/widgets/helper/NotebookTab.cpp | 8 ++--- src/widgets/settingspages/CommandPage.cpp | 2 +- .../settingspages/ExternalToolsPage.cpp | 10 +++--- src/widgets/settingspages/FeelPage.cpp | 20 ++++++------ .../settingspages/HighlightingPage.cpp | 8 ++--- src/widgets/settingspages/IgnoresPage.cpp | 2 +- src/widgets/settingspages/LogsPage.cpp | 4 +-- src/widgets/settingspages/LookPage.cpp | 10 +++--- src/widgets/settingspages/ModerationPage.cpp | 21 ++++++------- .../settingspages/SpecialChannelsPage.cpp | 2 -- src/widgets/splits/SplitInput.cpp | 2 +- 35 files changed, 125 insertions(+), 152 deletions(-) diff --git a/src/Application.cpp b/src/Application.cpp index 22ae0c34b..b53940702 100644 --- a/src/Application.cpp +++ b/src/Application.cpp @@ -38,9 +38,7 @@ Application *Application::instance = nullptr; // to each other Application::Application(Settings &_settings, Paths &_paths) - : settings(&_settings) - , paths(&_paths) - , resources(&this->emplace()) + : resources(&this->emplace()) , themes(&this->emplace()) , fonts(&this->emplace()) diff --git a/src/Application.hpp b/src/Application.hpp index e32f29bdd..6089aef43 100644 --- a/src/Application.hpp +++ b/src/Application.hpp @@ -46,8 +46,6 @@ public: friend void test(); - Settings *const settings{}; - Paths *const paths{}; Resources2 *const resources; Theme *const themes{}; diff --git a/src/RunGui.cpp b/src/RunGui.cpp index 9fdcdb20c..7ed61be87 100644 --- a/src/RunGui.cpp +++ b/src/RunGui.cpp @@ -107,7 +107,7 @@ void runGui(QApplication &a, Paths &paths, Settings &settings) chatterino::Updates::getInstance().checkForUpdates(); #ifdef C_USE_BREAKPAD - QBreakpadInstance.setDumpPath(app->paths->settingsFolderPath + "/Crashes"); + QBreakpadInstance.setDumpPath(getPaths()->settingsFolderPath + "/Crashes"); #endif // Running file diff --git a/src/common/NetworkData.cpp b/src/common/NetworkData.cpp index ad8fe40b2..d3434576e 100644 --- a/src/common/NetworkData.cpp +++ b/src/common/NetworkData.cpp @@ -44,7 +44,7 @@ void NetworkData::writeToCache(const QByteArray &bytes) if (this->useQuickLoadCache_) { auto app = getApp(); - QFile cachedFile(app->paths->cacheDirectory + "/" + this->getHash()); + QFile cachedFile(getPaths()->cacheDirectory + "/" + this->getHash()); if (cachedFile.open(QIODevice::WriteOnly)) { cachedFile.write(bytes); diff --git a/src/common/NetworkRequest.cpp b/src/common/NetworkRequest.cpp index 0a2e45533..af27394de 100644 --- a/src/common/NetworkRequest.cpp +++ b/src/common/NetworkRequest.cpp @@ -147,7 +147,7 @@ Outcome NetworkRequest::tryLoadCachedFile() { auto app = getApp(); - QFile cachedFile(app->paths->cacheDirectory + "/" + this->data->getHash()); + QFile cachedFile(getPaths()->cacheDirectory + "/" + this->data->getHash()); if (!cachedFile.exists()) { // File didn't exist diff --git a/src/controllers/highlights/HighlightModel.cpp b/src/controllers/highlights/HighlightModel.cpp index cad2fd006..827e23a4a 100644 --- a/src/controllers/highlights/HighlightModel.cpp +++ b/src/controllers/highlights/HighlightModel.cpp @@ -37,13 +37,13 @@ void HighlightModel::getRowFromItem(const HighlightPhrase &item, void HighlightModel::afterInit() { std::vector row = this->createRow(); - setBoolItem(row[0], getApp()->settings->enableHighlightsSelf.getValue(), - true, false); + setBoolItem(row[0], getSettings()->enableHighlightsSelf.getValue(), true, + false); row[0]->setData("Your username (automatic)", Qt::DisplayRole); - setBoolItem(row[1], getApp()->settings->enableHighlightTaskbar.getValue(), - true, false); - setBoolItem(row[2], getApp()->settings->enableHighlightSound.getValue(), - true, false); + setBoolItem(row[1], getSettings()->enableHighlightTaskbar.getValue(), true, + false); + setBoolItem(row[2], getSettings()->enableHighlightSound.getValue(), true, + false); row[3]->setFlags(0); this->insertCustomRow(row, 0); } @@ -55,20 +55,17 @@ void HighlightModel::customRowSetData(const std::vector &row, switch (column) { case 0: { if (role == Qt::CheckStateRole) { - getApp()->settings->enableHighlightsSelf.setValue( - value.toBool()); + getSettings()->enableHighlightsSelf.setValue(value.toBool()); } } break; case 1: { if (role == Qt::CheckStateRole) { - getApp()->settings->enableHighlightTaskbar.setValue( - value.toBool()); + getSettings()->enableHighlightTaskbar.setValue(value.toBool()); } } break; case 2: { if (role == Qt::CheckStateRole) { - getApp()->settings->enableHighlightSound.setValue( - value.toBool()); + getSettings()->enableHighlightSound.setValue(value.toBool()); } } break; case 3: { diff --git a/src/controllers/taggedusers/TaggedUsersModel.cpp b/src/controllers/taggedusers/TaggedUsersModel.cpp index e3225888c..037b4ae63 100644 --- a/src/controllers/taggedusers/TaggedUsersModel.cpp +++ b/src/controllers/taggedusers/TaggedUsersModel.cpp @@ -29,12 +29,12 @@ void TaggedUsersModel::afterInit() { // std::vector row = this->createRow(); // setBoolItem(row[0], - // getApp()->settings->enableHighlightsSelf.getValue(), true, false); + // getSettings()->enableHighlightsSelf.getValue(), true, false); // row[0]->setData("Your username (automatic)", Qt::DisplayRole); // setBoolItem(row[1], - // getApp()->settings->enableHighlightTaskbar.getValue(), true, false); + // getSettings()->enableHighlightTaskbar.getValue(), true, false); // setBoolItem(row[2], - // getApp()->settings->enableHighlightSound.getValue(), true, false); + // getSettings()->enableHighlightSound.getValue(), true, false); // row[3]->setFlags(0); this->insertCustomRow(row, 0); } @@ -45,17 +45,17 @@ void TaggedUsersModel::afterInit() // switch (column) { // case 0: { // if (role == Qt::CheckStateRole) { -// getApp()->settings->enableHighlightsSelf.setValue(value.toBool()); +// getSettings()->enableHighlightsSelf.setValue(value.toBool()); // } // } break; // case 1: { // if (role == Qt::CheckStateRole) { -// getApp()->settings->enableHighlightTaskbar.setValue(value.toBool()); +// getSettings()->enableHighlightTaskbar.setValue(value.toBool()); // } // } break; // case 2: { // if (role == Qt::CheckStateRole) { -// getApp()->settings->enableHighlightSound.setValue(value.toBool()); +// getSettings()->enableHighlightSound.setValue(value.toBool()); // } // } break; // case 3: { diff --git a/src/messages/MessageElement.cpp b/src/messages/MessageElement.cpp index 24b526c29..b9271d2ed 100644 --- a/src/messages/MessageElement.cpp +++ b/src/messages/MessageElement.cpp @@ -225,8 +225,8 @@ void TimestampElement::addToContainer(MessageLayoutContainer &container, { if (flags.hasAny(this->getFlags())) { auto app = getApp(); - if (app->settings->timestampFormat != this->format_) { - this->format_ = app->settings->timestampFormat.getValue(); + if (getSettings()->timestampFormat != this->format_) { + this->format_ = getSettings()->timestampFormat.getValue(); this->element_.reset(this->formatTime(this->time_)); } @@ -238,7 +238,7 @@ TextElement *TimestampElement::formatTime(const QTime &time) { static QLocale locale("en_US"); - QString format = locale.toString(time, getApp()->settings->timestampFormat); + QString format = locale.toString(time, getSettings()->timestampFormat); return new TextElement(format, MessageElementFlag::Timestamp, MessageColor::System, FontStyle::ChatMedium); diff --git a/src/messages/layouts/MessageLayout.cpp b/src/messages/layouts/MessageLayout.cpp index c077ac4fb..c7ff02af9 100644 --- a/src/messages/layouts/MessageLayout.cpp +++ b/src/messages/layouts/MessageLayout.cpp @@ -73,7 +73,7 @@ bool MessageLayout::layout(int width, float scale, MessageElementFlags flags) // check if work mask changed layoutRequired |= this->currentWordFlags_ != flags; - this->currentWordFlags_ = flags; // app->settings->getWordTypeMask(); + this->currentWordFlags_ = flags; // getSettings()->getWordTypeMask(); // check if layout was requested manually layoutRequired |= this->flags.has(MessageLayoutFlag::RequiresLayout); @@ -177,7 +177,7 @@ void MessageLayout::paint(QPainter &painter, int width, int y, int messageIndex, } // draw message seperation line - if (app->settings->separateMessages.getValue()) { + if (getSettings()->separateMessages.getValue()) { painter.fillRect(0, y, this->container_->getWidth(), 1, app->themes->splits.messageSeperator); } @@ -190,7 +190,7 @@ void MessageLayout::paint(QPainter &painter, int width, int y, int messageIndex, : app->themes->tabs.selected.backgrounds.unfocused.color(); QBrush brush(color, static_cast( - app->settings->lastMessagePattern.getValue())); + getSettings()->lastMessagePattern.getValue())); painter.fillRect(0, y + this->container_->getHeight() - 1, pixmap->width(), 1, brush); @@ -214,7 +214,7 @@ void MessageLayout::updateBuffer(QPixmap *buffer, int /*messageIndex*/, backgroundColor = app->themes->messages.backgrounds.highlighted; } else if (this->message_->flags.has(MessageFlag::Subscription)) { backgroundColor = app->themes->messages.backgrounds.subscription; - } else if (app->settings->alternateMessageBackground.getValue() && + } else if (getSettings()->alternateMessageBackground.getValue() && this->flags.has(MessageLayoutFlag::AlternateBackground)) { backgroundColor = app->themes->messages.backgrounds.alternate; } else { diff --git a/src/messages/layouts/MessageLayoutContainer.cpp b/src/messages/layouts/MessageLayoutContainer.cpp index 2092524c9..008a02d05 100644 --- a/src/messages/layouts/MessageLayoutContainer.cpp +++ b/src/messages/layouts/MessageLayoutContainer.cpp @@ -14,7 +14,7 @@ #define COMPACT_EMOTES_OFFSET 6 #define MAX_UNCOLLAPSED_LINES \ - (getApp()->settings->collpseMessagesMinLines.getValue()) + (getSettings()->collpseMessagesMinLines.getValue()) namespace chatterino { @@ -235,7 +235,7 @@ void MessageLayoutContainer::end() bool MessageLayoutContainer::canCollapse() { - return getApp()->settings->collpseMessagesMinLines.getValue() > 0 && + return getSettings()->collpseMessagesMinLines.getValue() > 0 && this->flags_.has(MessageFlag::Collapsed); } diff --git a/src/providers/emoji/Emojis.cpp b/src/providers/emoji/Emojis.cpp index 18ce18139..5140d2fe1 100644 --- a/src/providers/emoji/Emojis.cpp +++ b/src/providers/emoji/Emojis.cpp @@ -217,7 +217,7 @@ void Emojis::loadEmojiSet() { auto app = getApp(); - app->settings->emojiSet.connect([=](const auto &emojiSet, auto) { + getSettings()->emojiSet.connect([=](const auto &emojiSet, auto) { log("Using emoji set {}", emojiSet); this->emojis.each([=](const auto &name, std::shared_ptr &emoji) { diff --git a/src/providers/twitch/IrcMessageHandler.cpp b/src/providers/twitch/IrcMessageHandler.cpp index 1679884b8..9aabbc91d 100644 --- a/src/providers/twitch/IrcMessageHandler.cpp +++ b/src/providers/twitch/IrcMessageHandler.cpp @@ -231,7 +231,7 @@ void IrcMessageHandler::handleWhisperMessage(Communi::IrcMessage *message) c->addMessage(_message); - if (app->settings->inlineWhispers) { + if (getSettings()->inlineWhispers) { app->twitch.server->forEachChannel([_message](ChannelPtr channel) { channel->addMessage(_message); // }); diff --git a/src/providers/twitch/TwitchMessageBuilder.cpp b/src/providers/twitch/TwitchMessageBuilder.cpp index 5b4cef199..7f8c2aa3d 100644 --- a/src/providers/twitch/TwitchMessageBuilder.cpp +++ b/src/providers/twitch/TwitchMessageBuilder.cpp @@ -63,7 +63,7 @@ bool TwitchMessageBuilder::isIgnored() const } } - if (app->settings->enableTwitchIgnoredUsers && + if (getSettings()->enableTwitchIgnoredUsers && this->tags.contains("user-id")) { auto sourceUserID = this->tags.value("user-id").toString(); @@ -289,7 +289,7 @@ void TwitchMessageBuilder::addTextOrEmoji(const QString &string_) } // if (!linkString.isEmpty()) { - // if (getApp()->settings->lowercaseLink) { + // if (getSettings()->lowercaseLink) { // QRegularExpression httpRegex("\\bhttps?://", // QRegularExpression::CaseInsensitiveOption); QRegularExpression // ftpRegex("\\bftps?://", @@ -499,9 +499,9 @@ void TwitchMessageBuilder::parseHighlights(bool isPastMsg) // update the media player url if necessary QUrl highlightSoundUrl; - if (app->settings->customHighlightSound) { + if (getSettings()->customHighlightSound) { highlightSoundUrl = - QUrl::fromLocalFile(app->settings->pathHighlightSound.getValue()); + QUrl::fromLocalFile(getSettings()->pathHighlightSound.getValue()); } else { highlightSoundUrl = QUrl("qrc:/sounds/ping2.wav"); } @@ -519,10 +519,10 @@ void TwitchMessageBuilder::parseHighlights(bool isPastMsg) std::vector userHighlights = app->highlights->highlightedUsers.getVector(); - if (app->settings->enableHighlightsSelf && currentUsername.size() > 0) { + if (getSettings()->enableHighlightsSelf && currentUsername.size() > 0) { HighlightPhrase selfHighlight( - currentUsername, app->settings->enableHighlightTaskbar, - app->settings->enableHighlightSound, false); + currentUsername, getSettings()->enableHighlightTaskbar, + getSettings()->enableHighlightSound, false); activeHighlights.emplace_back(std::move(selfHighlight)); } @@ -581,7 +581,7 @@ void TwitchMessageBuilder::parseHighlights(bool isPastMsg) if (!isPastMsg) { if (playSound && - (!hasFocus || app->settings->highlightAlwaysPlaySound)) { + (!hasFocus || getSettings()->highlightAlwaysPlaySound)) { player->play(); } diff --git a/src/singletons/Fonts.cpp b/src/singletons/Fonts.cpp index 3c9efa79e..cc2f00727 100644 --- a/src/singletons/Fonts.cpp +++ b/src/singletons/Fonts.cpp @@ -105,13 +105,13 @@ Fonts::FontData Fonts::createFontData(FontStyle type, float scale) {FontStyle::ChatMedium, {1, false, QFont::Normal}}, {FontStyle::ChatMediumBold, {1, false, - QFont::Weight(getApp()->settings->boldScale.getValue())}}, + QFont::Weight(getSettings()->boldScale.getValue())}}, {FontStyle::ChatMediumItalic, {1, true, QFont::Normal}}, {FontStyle::ChatLarge, {1.2f, false, QFont::Normal}}, {FontStyle::ChatVeryLarge, {1.4f, false, QFont::Normal}}, }; sizeScale[FontStyle::ChatMediumBold] = { - 1, false, QFont::Weight(getApp()->settings->boldScale.getValue())}; + 1, false, QFont::Weight(getSettings()->boldScale.getValue())}; auto data = sizeScale[type]; return FontData( QFont(QString::fromStdString(this->chatFontFamily.getValue()), diff --git a/src/singletons/Paths.hpp b/src/singletons/Paths.hpp index 071feb737..70ab2642f 100644 --- a/src/singletons/Paths.hpp +++ b/src/singletons/Paths.hpp @@ -43,6 +43,6 @@ private: boost::optional portable_; }; -[[deprecated]] Paths *getPaths(); +Paths *getPaths(); } // namespace chatterino diff --git a/src/singletons/WindowManager.cpp b/src/singletons/WindowManager.cpp index 17bf1ea83..02b711f7b 100644 --- a/src/singletons/WindowManager.cpp +++ b/src/singletons/WindowManager.cpp @@ -406,7 +406,7 @@ void WindowManager::save() document.setObject(obj); // save file - QString settingsPath = app->paths->settingsDirectory + SETTINGS_FILENAME; + QString settingsPath = getPaths()->settingsDirectory + SETTINGS_FILENAME; QFile file(settingsPath); file.open(QIODevice::WriteOnly | QIODevice::Truncate); @@ -518,7 +518,7 @@ int WindowManager::clampUiScale(int scale) float WindowManager::getUiScaleValue() { - return getUiScaleValue(getApp()->settings->uiScale.getValue()); + return getUiScaleValue(getSettings()->uiScale.getValue()); } float WindowManager::getUiScaleValue(int scale) diff --git a/src/singletons/helper/GifTimer.cpp b/src/singletons/helper/GifTimer.cpp index 49fbd98bf..8ef657e7a 100644 --- a/src/singletons/helper/GifTimer.cpp +++ b/src/singletons/helper/GifTimer.cpp @@ -10,7 +10,7 @@ void GIFTimer::initialize() { this->timer.setInterval(30); - getApp()->settings->enableGifAnimations.connect([this](bool enabled, auto) { + getSettings()->enableGifAnimations.connect([this](bool enabled, auto) { if (enabled) { this->timer.start(); } else { diff --git a/src/singletons/helper/LoggingChannel.cpp b/src/singletons/helper/LoggingChannel.cpp index d70344448..c9081d2a6 100644 --- a/src/singletons/helper/LoggingChannel.cpp +++ b/src/singletons/helper/LoggingChannel.cpp @@ -30,11 +30,11 @@ LoggingChannel::LoggingChannel(const QString &_channelName) auto app = getApp(); - app->settings->logPath.connect([this](const QString &logPath, auto) { + getSettings()->logPath.connect([this](const QString &logPath, auto) { auto app = getApp(); if (logPath.isEmpty()) { - this->baseDirectory = app->paths->messageLogDirectory; + this->baseDirectory = getPaths()->messageLogDirectory; } else { this->baseDirectory = logPath; } diff --git a/src/util/StreamLink.cpp b/src/util/StreamLink.cpp index 2fd2ef0a3..aa2db55c0 100644 --- a/src/util/StreamLink.cpp +++ b/src/util/StreamLink.cpp @@ -37,8 +37,8 @@ QString getStreamlinkProgram() { auto app = getApp(); - if (app->settings->streamlinkUseCustomPath) { - return app->settings->streamlinkPath + "/" + getBinaryName(); + if (getSettings()->streamlinkUseCustomPath) { + return getSettings()->streamlinkPath + "/" + getBinaryName(); } else { return getBinaryName(); } @@ -62,7 +62,7 @@ void showStreamlinkNotFoundError() static QErrorMessage *msg = new QErrorMessage; auto app = getApp(); - if (app->settings->streamlinkUseCustomPath) { + if (getSettings()->streamlinkUseCustomPath) { msg->showMessage( "Unable to find Streamlink executable\nMake sure your custom path " "is pointing " @@ -146,9 +146,9 @@ void openStreamlink(const QString &channelURL, const QString &quality, QStringList arguments; - QString additionalOptions = app->settings->streamlinkOpts.getValue(); + QString additionalOptions = getSettings()->streamlinkOpts.getValue(); if (!additionalOptions.isEmpty()) { - arguments << app->settings->streamlinkOpts; + arguments << getSettings()->streamlinkOpts; } arguments.append(extraArguments); @@ -173,7 +173,7 @@ void openStreamlinkForChannel(const QString &channel) QString channelURL = "twitch.tv/" + channel; - QString preferredQuality = app->settings->preferredQuality; + QString preferredQuality = getSettings()->preferredQuality; preferredQuality = preferredQuality.toLower(); if (preferredQuality == "choose") { diff --git a/src/widgets/BaseWindow.cpp b/src/widgets/BaseWindow.cpp index 5c80bc9a7..32d470805 100644 --- a/src/widgets/BaseWindow.cpp +++ b/src/widgets/BaseWindow.cpp @@ -56,13 +56,13 @@ BaseWindow::BaseWindow(QWidget *parent, Flags _flags) this->init(); this->connections_.managedConnect( - getApp()->settings->uiScale.getValueChangedSignal(), + getSettings()->uiScale.getValueChangedSignal(), [this](auto, auto) { postToThread([this] { this->updateScale(); }); }); this->updateScale(); createWindowShortcut(this, "CTRL+0", - [] { getApp()->settings->uiScale.setValue(0); }); + [] { getSettings()->uiScale.setValue(0); }); // QTimer::this->scaleChangedEvent(this->getScale()); } @@ -163,7 +163,7 @@ void BaseWindow::init() // fourtf: don't ask me why we need to delay this if (!(this->flags_ & Flags::TopMost)) { QTimer::singleShot(1, this, [this] { - getApp()->settings->windowTopMost.connect( + getSettings()->windowTopMost.connect( [this](bool topMost, auto) { ::SetWindowPos(HWND(this->winId()), topMost ? HWND_TOPMOST : HWND_NOTOPMOST, 0, @@ -174,7 +174,7 @@ void BaseWindow::init() }); } #else -// if (getApp()->settings->windowTopMost.getValue()) { +// if (getSettings()->windowTopMost.getValue()) { // this->setWindowFlag(Qt::WindowStaysOnTopHint); // } #endif @@ -267,11 +267,11 @@ void BaseWindow::wheelEvent(QWheelEvent *event) if (event->modifiers() & Qt::ControlModifier) { if (event->delta() > 0) { - getApp()->settings->uiScale.setValue(WindowManager::clampUiScale( - getApp()->settings->uiScale.getValue() + 1)); + getSettings()->uiScale.setValue(WindowManager::clampUiScale( + getSettings()->uiScale.getValue() + 1)); } else { - getApp()->settings->uiScale.setValue(WindowManager::clampUiScale( - getApp()->settings->uiScale.getValue() - 1)); + getSettings()->uiScale.setValue(WindowManager::clampUiScale( + getSettings()->uiScale.getValue() - 1)); } } } diff --git a/src/widgets/Notebook.cpp b/src/widgets/Notebook.cpp index 8cd5a6075..04ecd0840 100644 --- a/src/widgets/Notebook.cpp +++ b/src/widgets/Notebook.cpp @@ -434,9 +434,9 @@ void SplitNotebook::addCustomButtons() auto settingsBtn = this->addCustomButton(); settingsBtn->setVisible( - !getApp()->settings->hidePreferencesButton.getValue()); + !getSettings()->hidePreferencesButton.getValue()); - getApp()->settings->hidePreferencesButton.connect( + getSettings()->hidePreferencesButton.connect( [settingsBtn](bool hide, auto) { settingsBtn->setVisible(!hide); }, this->connections_); @@ -447,8 +447,8 @@ void SplitNotebook::addCustomButtons() // account auto userBtn = this->addCustomButton(); - userBtn->setVisible(!getApp()->settings->hideUserButton.getValue()); - getApp()->settings->hideUserButton.connect( + userBtn->setVisible(!getSettings()->hideUserButton.getValue()); + getSettings()->hideUserButton.connect( [userBtn](bool hide, auto) { userBtn->setVisible(!hide); }, this->connections_); diff --git a/src/widgets/Window.cpp b/src/widgets/Window.cpp index 876f2a078..6df88b402 100644 --- a/src/widgets/Window.cpp +++ b/src/widgets/Window.cpp @@ -105,8 +105,8 @@ bool Window::event(QEvent *event) void Window::showEvent(QShowEvent *event) { // Startup notification - if (getApp()->settings->startUpNotification.getValue() < 1) { - getApp()->settings->startUpNotification = 1; + if (getSettings()->startUpNotification.getValue() < 1) { + getSettings()->startUpNotification = 1; auto box = new QMessageBox( QMessageBox::Information, "Chatterino 2 Beta", @@ -118,8 +118,8 @@ void Window::showEvent(QShowEvent *event) } // Show changelog - if (getApp()->settings->currentVersion.getValue() != "" && - getApp()->settings->currentVersion.getValue() != CHATTERINO_VERSION) { + if (getSettings()->currentVersion.getValue() != "" && + getSettings()->currentVersion.getValue() != CHATTERINO_VERSION) { auto box = new QMessageBox(QMessageBox::Information, "Chatterino 2 Beta", "Show changelog?", QMessageBox::Yes | QMessageBox::No); @@ -130,7 +130,7 @@ void Window::showEvent(QShowEvent *event) } } - getApp()->settings->currentVersion.setValue(CHATTERINO_VERSION); + getSettings()->currentVersion.setValue(CHATTERINO_VERSION); // -- BaseWindow::showEvent(event); @@ -281,8 +281,8 @@ void Window::addShortcuts() auto s = new QShortcut(QKeySequence::ZoomIn, this); s->setContext(Qt::WindowShortcut); QObject::connect(s, &QShortcut::activated, this, [] { - getApp()->settings->uiScale.setValue(WindowManager::clampUiScale( - getApp()->settings->uiScale.getValue() + 1)); + getSettings()->uiScale.setValue(WindowManager::clampUiScale( + getSettings()->uiScale.getValue() + 1)); }); } @@ -291,8 +291,8 @@ void Window::addShortcuts() auto s = new QShortcut(QKeySequence::ZoomOut, this); s->setContext(Qt::WindowShortcut); QObject::connect(s, &QShortcut::activated, this, [] { - getApp()->settings->uiScale.setValue(WindowManager::clampUiScale( - getApp()->settings->uiScale.getValue() - 1)); + getSettings()->uiScale.setValue(WindowManager::clampUiScale( + getSettings()->uiScale.getValue() - 1)); }); } diff --git a/src/widgets/dialogs/SettingsDialog.cpp b/src/widgets/dialogs/SettingsDialog.cpp index 8f0746ccb..1c89344f4 100644 --- a/src/widgets/dialogs/SettingsDialog.cpp +++ b/src/widgets/dialogs/SettingsDialog.cpp @@ -154,7 +154,7 @@ void SettingsDialog::showDialog(PreferredTab preferredTab) void SettingsDialog::refresh() { - getApp()->settings->saveSnapshot(); + getSettings()->saveSnapshot(); for (auto *tab : this->tabs_) { tab->getSettingsPage()->onShow(); @@ -199,7 +199,7 @@ void SettingsDialog::onCancelClicked() tab->getSettingsPage()->cancel(); } - getApp()->settings->restoreSnapshot(); + getSettings()->restoreSnapshot(); this->close(); } diff --git a/src/widgets/helper/ChannelView.cpp b/src/widgets/helper/ChannelView.cpp index 45bc7b677..467d34630 100644 --- a/src/widgets/helper/ChannelView.cpp +++ b/src/widgets/helper/ChannelView.cpp @@ -131,8 +131,7 @@ void ChannelView::initializeLayout() QObject::connect(this->goToBottom_, &EffectLabel::clicked, this, [=] { QTimer::singleShot(180, [=] { this->scrollBar_->scrollToBottom( - getApp() - ->settings->enableSmoothScrollingNewMessages.getValue()); + getSettings()->enableSmoothScrollingNewMessages.getValue()); }); }); } @@ -162,7 +161,7 @@ void ChannelView::initializeSignals() this->update(); })); - getApp()->settings->showLastMessageIndicator.connect( + getSettings()->showLastMessageIndicator.connect( [this](auto, auto) { this->update(); }, this->connections_); connections_.push_back( @@ -213,8 +212,6 @@ void ChannelView::actuallyLayoutMessages(bool causedByScrollbar) { // BenchmarkGuard benchmark("layout"); - auto app = getApp(); - auto messagesSnapshot = this->getMessagesSnapshot(); if (messagesSnapshot.getLength() == 0) { @@ -293,7 +290,7 @@ void ChannelView::actuallyLayoutMessages(bool causedByScrollbar) if (!this->isPaused()) { this->scrollBar_->scrollToBottom( // this->messageWasAdded && - app->settings->enableSmoothScrollingNewMessages.getValue()); + getSettings()->enableSmoothScrollingNewMessages.getValue()); } this->messageWasAdded_ = false; } @@ -654,8 +651,6 @@ void ChannelView::paintEvent(QPaintEvent * /*event*/) // such as the grey overlay when a message is disabled void ChannelView::drawMessages(QPainter &painter) { - auto app = getApp(); - auto messagesSnapshot = this->getMessagesSnapshot(); size_t start = size_t(this->scrollBar_->getCurrentValue()); @@ -674,7 +669,7 @@ void ChannelView::drawMessages(QPainter &painter) MessageLayout *layout = messagesSnapshot[i].get(); bool isLastMessage = false; - if (app->settings->showLastMessageIndicator) { + if (getSettings()->showLastMessageIndicator) { isLastMessage = this->lastReadMessage_.get() == layout; } @@ -737,9 +732,7 @@ void ChannelView::wheelEvent(QWheelEvent *event) } if (this->scrollBar_->isVisible()) { - auto app = getApp(); - - float mouseMultiplier = app->settings->mouseScrollMultiplier; + float mouseMultiplier = getSettings()->mouseScrollMultiplier; qreal desired = this->scrollBar_->getDesiredValue(); qreal delta = event->delta() * qreal(1.5) * mouseMultiplier; @@ -824,9 +817,7 @@ void ChannelView::mouseMoveEvent(QMouseEvent *event) return; } - auto app = getApp(); - - if (app->settings->pauseChatHover.getValue()) { + if (getSettings()->pauseChatHover.getValue()) { this->pause(CHAT_HOVER_PAUSE_DURATION); } @@ -891,8 +882,6 @@ void ChannelView::mouseMoveEvent(QMouseEvent *event) void ChannelView::mousePressEvent(QMouseEvent *event) { - auto app = getApp(); - this->mouseDown.invoke(event); std::shared_ptr layout; @@ -929,7 +918,7 @@ void ChannelView::mousePressEvent(QMouseEvent *event) return; } - if (app->settings->linksDoubleClickOnly.getValue()) { + if (getSettings()->linksDoubleClickOnly.getValue()) { this->pause(200); } @@ -1034,7 +1023,7 @@ void ChannelView::handleMouseClick(QMouseEvent *event, } auto &link = hoveredElement->getLink(); - if (!getApp()->settings->linksDoubleClickOnly) { + if (!getSettings()->linksDoubleClickOnly) { this->handleLinkClick(event, link, layout); this->linkClicked.invoke(link); @@ -1119,9 +1108,7 @@ void ChannelView::addContextMenuItems( void ChannelView::mouseDoubleClickEvent(QMouseEvent *event) { - auto app = getApp(); - - if (app->settings->linksDoubleClickOnly) { + if (getSettings()->linksDoubleClickOnly) { std::shared_ptr layout; QPoint relativePos; int messageIndex; diff --git a/src/widgets/helper/NotebookTab.cpp b/src/widgets/helper/NotebookTab.cpp index 865eb6048..15388e34c 100644 --- a/src/widgets/helper/NotebookTab.cpp +++ b/src/widgets/helper/NotebookTab.cpp @@ -35,7 +35,7 @@ NotebookTab::NotebookTab(Notebook *notebook) this->positionChangedAnimation_.setEasingCurve( QEasingCurve(QEasingCurve::InCubic)); - app->settings->showTabCloseButton.connect( + getSettings()->showTabCloseButton.connect( boost::bind(&NotebookTab::hideTabXChanged, this, _1), this->managedConnections_); @@ -286,7 +286,7 @@ void NotebookTab::paintEvent(QPaintEvent *) painter.setPen(colors.text); // set area for text - int rectW = (!app->settings->showTabCloseButton ? 0 : int(16 * scale)); + int rectW = (!getSettings()->showTabCloseButton ? 0 : int(16 * scale)); QRect rect(0, 0, this->width() - rectW, height); // draw text @@ -341,7 +341,7 @@ void NotebookTab::paintEvent(QPaintEvent *) bool NotebookTab::hasXButton() { - return getApp()->settings->showTabCloseButton && + return getSettings()->showTabCloseButton && this->notebook_->getAllowUserTabManagement(); } @@ -434,7 +434,7 @@ void NotebookTab::mouseMoveEvent(QMouseEvent *event) { auto app = getApp(); - if (app->settings->showTabCloseButton && + if (getSettings()->showTabCloseButton && this->notebook_->getAllowUserTabManagement()) // { bool overX = this->getXRect().contains(event->pos()); diff --git a/src/widgets/settingspages/CommandPage.cpp b/src/widgets/settingspages/CommandPage.cpp index bb3a60c59..b06988a57 100644 --- a/src/widgets/settingspages/CommandPage.cpp +++ b/src/widgets/settingspages/CommandPage.cpp @@ -47,7 +47,7 @@ CommandPage::CommandPage() layout.append( this->createCheckBox("Also match the trigger at the end of the message", - app->settings->allowCommandsAtEnd)); + getSettings()->allowCommandsAtEnd)); QLabel *text = layout.emplace(TEXT).getElement(); text->setWordWrap(true); diff --git a/src/widgets/settingspages/ExternalToolsPage.cpp b/src/widgets/settingspages/ExternalToolsPage.cpp index 0f47e37a1..bdb164e36 100644 --- a/src/widgets/settingspages/ExternalToolsPage.cpp +++ b/src/widgets/settingspages/ExternalToolsPage.cpp @@ -57,22 +57,22 @@ ExternalToolsPage::ExternalToolsPage() auto customPathCb = this->createCheckBox("Use custom path (Enable if using " "non-standard streamlink installation path)", - app->settings->streamlinkUseCustomPath); + getSettings()->streamlinkUseCustomPath); groupLayout->setWidget(2, QFormLayout::SpanningRole, customPathCb); - auto customPath = this->createLineEdit(app->settings->streamlinkPath); + auto customPath = this->createLineEdit(getSettings()->streamlinkPath); customPath->setPlaceholderText( "Path to folder where Streamlink executable can be found"); groupLayout->addRow("Custom streamlink path:", customPath); groupLayout->addRow( "Preferred quality:", this->createComboBox({STREAMLINK_QUALITY}, - app->settings->preferredQuality)); + getSettings()->preferredQuality)); groupLayout->addRow( "Additional options:", - this->createLineEdit(app->settings->streamlinkOpts)); + this->createLineEdit(getSettings()->streamlinkOpts)); - app->settings->streamlinkUseCustomPath.connect( + getSettings()->streamlinkUseCustomPath.connect( [=](const auto &value, auto) { customPath->setEnabled(value); // }, diff --git a/src/widgets/settingspages/FeelPage.cpp b/src/widgets/settingspages/FeelPage.cpp index d20c859c7..78b41c45d 100644 --- a/src/widgets/settingspages/FeelPage.cpp +++ b/src/widgets/settingspages/FeelPage.cpp @@ -20,7 +20,6 @@ namespace chatterino { FeelPage::FeelPage() : SettingsPage("Feel", ":/settings/behave.svg") { - auto app = getApp(); LayoutCreator layoutCreator(this); auto layout = layoutCreator.setLayoutType(); @@ -37,20 +36,20 @@ FeelPage::FeelPage() form->addRow( "", this->createCheckBox( "Show which users joined the channel (up to 1000 chatters)", - app->settings->showJoins)); + getSettings()->showJoins)); form->addRow( "", this->createCheckBox( "Show which users parted the channel (up to 1000 chatters)", - app->settings->showParts)); + getSettings()->showParts)); form->addRow("Pause chat:", this->createCheckBox(PAUSE_HOVERING, - app->settings->pauseChatHover)); + getSettings()->pauseChatHover)); form->addRow("Mouse scroll speed:", this->createMouseScrollSlider()); form->addRow("Links:", this->createCheckBox("Open links only on double click", - app->settings->linksDoubleClickOnly)); + getSettings()->linksDoubleClickOnly)); } layout->addSpacing(16); @@ -61,11 +60,11 @@ FeelPage::FeelPage() groupLayout->addRow( LIMIT_CHATTERS_FOR_SMALLER_STREAMERS, this->createCheckBox( - "", app->settings->onlyFetchChattersForSmallerStreamers)); + "", getSettings()->onlyFetchChattersForSmallerStreamers)); groupLayout->addRow( "What viewer count counts as a \"smaller streamer\"", - this->createSpinBox(app->settings->smallStreamerLimit, 10, 50000)); + this->createSpinBox(getSettings()->smallStreamerLimit, 10, 50000)); } { @@ -73,7 +72,7 @@ FeelPage::FeelPage() auto groupLayout = group.setLayoutType(); groupLayout.append(this->createCheckBox("Show whispers inline", - app->settings->inlineWhispers)); + getSettings()->inlineWhispers)); } layout->addStretch(1); @@ -81,17 +80,16 @@ FeelPage::FeelPage() QSlider *FeelPage::createMouseScrollSlider() { - auto app = getApp(); auto slider = new QSlider(Qt::Horizontal); - float currentValue = app->settings->mouseScrollMultiplier; + float currentValue = getSettings()->mouseScrollMultiplier; int sliderValue = int(((currentValue - 0.1f) / 2.f) * 99.f); slider->setValue(sliderValue); QObject::connect(slider, &QSlider::valueChanged, [=](int newValue) { float mul = static_cast(newValue) / 99.f; float newSliderValue = (mul * 2.1f) + 0.1f; - app->settings->mouseScrollMultiplier = newSliderValue; + getSettings()->mouseScrollMultiplier = newSliderValue; }); return slider; diff --git a/src/widgets/settingspages/HighlightingPage.cpp b/src/widgets/settingspages/HighlightingPage.cpp index 455c0d377..be394b3c2 100644 --- a/src/widgets/settingspages/HighlightingPage.cpp +++ b/src/widgets/settingspages/HighlightingPage.cpp @@ -39,7 +39,7 @@ HighlightingPage::HighlightingPage() { // GENERAL // layout.append(this->createCheckBox(ENABLE_HIGHLIGHTS, - // app->settings->enableHighlights)); + // getSettings()->enableHighlights)); // TABS auto tabs = layout.emplace(); @@ -135,7 +135,7 @@ HighlightingPage::HighlightingPage() auto customSound = layout.emplace().withoutMargin(); { customSound.append(this->createCheckBox( - "Custom sound", app->settings->customHighlightSound)); + "Custom sound", getSettings()->customHighlightSound)); auto selectFile = customSound.emplace("Select custom sound file"); QObject::connect(selectFile.getElement(), &QPushButton::clicked, @@ -143,12 +143,12 @@ HighlightingPage::HighlightingPage() auto fileName = QFileDialog::getOpenFileName( this, tr("Open Sound"), "", tr("Audio Files (*.mp3 *.wav)")); - app->settings->pathHighlightSound = fileName; + getSettings()->pathHighlightSound = fileName; }); } layout.append(createCheckBox(ALWAYS_PLAY, - app->settings->highlightAlwaysPlaySound)); + getSettings()->highlightAlwaysPlaySound)); } // ---- misc diff --git a/src/widgets/settingspages/IgnoresPage.cpp b/src/widgets/settingspages/IgnoresPage.cpp index b23ecbb89..8aa6c5c4a 100644 --- a/src/widgets/settingspages/IgnoresPage.cpp +++ b/src/widgets/settingspages/IgnoresPage.cpp @@ -71,7 +71,7 @@ void addUsersTab(IgnoresPage &page, LayoutCreator users, { users.append( page.createCheckBox("Enable twitch ignored users", - getApp()->settings->enableTwitchIgnoredUsers)); + getSettings()->enableTwitchIgnoredUsers)); auto anyways = users.emplace().withoutMargin(); { diff --git a/src/widgets/settingspages/LogsPage.cpp b/src/widgets/settingspages/LogsPage.cpp index 8cf1fbcc1..2be6c2144 100644 --- a/src/widgets/settingspages/LogsPage.cpp +++ b/src/widgets/settingspages/LogsPage.cpp @@ -33,7 +33,7 @@ // LayoutCreator layoutCreator(this); // auto layout = layoutCreator.emplace().withoutMargin(); -// auto logPath = app->paths->logsFolderPath; +// auto logPath = getPaths()->logsFolderPath; // auto created = layout.emplace(); // created->setText("Logs are saved to " + CreateLink(logPath, true)); @@ -43,7 +43,7 @@ // Qt::LinksAccessibleByKeyboard); // created->setOpenExternalLinks(true); // layout.append(this->createCheckBox("Enable logging", -// app->settings->enableLogging)); +// getSettings()->enableLogging)); // layout->addStretch(1); //} diff --git a/src/widgets/settingspages/LookPage.cpp b/src/widgets/settingspages/LookPage.cpp index 08a6ec77a..5daec0464 100644 --- a/src/widgets/settingspages/LookPage.cpp +++ b/src/widgets/settingspages/LookPage.cpp @@ -208,13 +208,13 @@ void LookPage::addEmoteTab(LayoutCreator layout) /* emotes.append( this->createCheckBox("Enable Twitch emotes", - app->settings->enableTwitchEmotes)); + getSettings()->enableTwitchEmotes)); emotes.append(this->createCheckBox("Enable BetterTTV emotes for Twitch", - app->settings->enableBttvEmotes)); + getSettings()->enableBttvEmotes)); emotes.append(this->createCheckBox("Enable FrankerFaceZ emotes for Twitch", - app->settings->enableFfzEmotes)); + getSettings()->enableFfzEmotes)); emotes.append(this->createCheckBox("Enable emojis", - app->settings->enableEmojis)); + getSettings()->enableEmojis)); */ layout.append( this->createCheckBox("Animations", getSettings()->enableGifAnimations)); @@ -285,7 +285,7 @@ void LookPage::addLastReadMessageIndicatorPatternSelector( combo->addItems({"Dotted line", "Solid line"}); const auto currentIndex = []() -> int { - switch (getApp()->settings->lastMessagePattern.getValue()) { + switch (getSettings()->lastMessagePattern.getValue()) { case Qt::SolidLine: return 1; case Qt::VerPattern: diff --git a/src/widgets/settingspages/ModerationPage.cpp b/src/widgets/settingspages/ModerationPage.cpp index fdb6df89f..28e0f7419 100644 --- a/src/widgets/settingspages/ModerationPage.cpp +++ b/src/widgets/settingspages/ModerationPage.cpp @@ -69,12 +69,11 @@ QString formatSize(qint64 size) QString fetchLogDirectorySize() { - auto app = getApp(); QString logPathDirectory; - if (app->settings->logPath == "") { - logPathDirectory = app->paths->messageLogDirectory; + if (getSettings()->logPath == "") { + logPathDirectory = getPaths()->messageLogDirectory; } else { - logPathDirectory = app->settings->logPath; + logPathDirectory = getSettings()->logPath; } qint64 logsSize = dirSize(logPathDirectory); QString logsSizeLabel = "Your logs currently take up "; @@ -101,12 +100,12 @@ ModerationPage::ModerationPage() QtConcurrent::run([] { return fetchLogDirectorySize(); })); // Logs (copied from LoggingMananger) - app->settings->logPath.connect( + getSettings()->logPath.connect( [app, logsPathLabel](const QString &logPath, auto) mutable { QString pathOriginal; if (logPath == "") { - pathOriginal = app->paths->messageLogDirectory; + pathOriginal = getPaths()->messageLogDirectory; } else { pathOriginal = logPath; } @@ -136,7 +135,7 @@ ModerationPage::ModerationPage() Qt::LinksAccessibleByKeyboard); logsPathLabel->setOpenExternalLinks(true); logs.append(this->createCheckBox("Enable logging", - app->settings->enableLogging)); + getSettings()->enableLogging)); logs->addStretch(1); auto selectDir = logs.emplace("Set custom logpath"); @@ -145,10 +144,9 @@ ModerationPage::ModerationPage() QObject::connect( selectDir.getElement(), &QPushButton::clicked, this, [this, logsPathSizeLabel]() mutable { - auto app = getApp(); auto dirName = QFileDialog::getExistingDirectory(this); - app->settings->logPath = dirName; + getSettings()->logPath = dirName; // Refresh: Show how big (size-wise) the logs are logsPathSizeLabel->setText( @@ -159,8 +157,7 @@ ModerationPage::ModerationPage() auto resetDir = logs.emplace("Reset logpath"); QObject::connect(resetDir.getElement(), &QPushButton::clicked, this, [logsPathSizeLabel]() mutable { - auto app = getApp(); - app->settings->logPath = ""; + getSettings()->logPath = ""; // Refresh: Show how big (size-wise) the logs are logsPathSizeLabel->setText(QtConcurrent::run( @@ -183,7 +180,7 @@ ModerationPage::ModerationPage() // form->addRow("Action on timed out messages // (unimplemented):", // this->createComboBox({"Disable", "Hide"}, - // app->settings->timeoutAction)); + // getSettings()->timeoutAction)); // } EditableModelView *view = diff --git a/src/widgets/settingspages/SpecialChannelsPage.cpp b/src/widgets/settingspages/SpecialChannelsPage.cpp index cdd016dea..5ccb904c0 100644 --- a/src/widgets/settingspages/SpecialChannelsPage.cpp +++ b/src/widgets/settingspages/SpecialChannelsPage.cpp @@ -13,8 +13,6 @@ namespace chatterino { SpecialChannelsPage::SpecialChannelsPage() : SettingsPage("Special channels", "") { - auto app = getApp(); - LayoutCreator layoutCreator(this); auto layout = layoutCreator.setLayoutType(); diff --git a/src/widgets/splits/SplitInput.cpp b/src/widgets/splits/SplitInput.cpp index 8fbc62f02..f6a66e7f4 100644 --- a/src/widgets/splits/SplitInput.cpp +++ b/src/widgets/splits/SplitInput.cpp @@ -109,7 +109,7 @@ void SplitInput::initLayout() }); // textEditLength visibility - app->settings->showMessageLength.connect( + getSettings()->showMessageLength.connect( [this](const bool &value, auto) { this->ui_.textEditLength->setHidden(!value); }, From f6e110b7fb8f8d9e75d4146772c19d3fd094f983 Mon Sep 17 00:00:00 2001 From: fourtf Date: Mon, 13 Aug 2018 13:54:39 +0200 Subject: [PATCH 06/14] fixed and optimized the autocompletion --- chatterino.pro | 6 +- src/common/Channel.hpp | 2 +- src/common/CompletionModel.cpp | 152 +++++++++--------- src/common/CompletionModel.hpp | 2 +- src/common/UsernameSet.cpp | 110 +++++++++++++ src/common/UsernameSet.hpp | 73 +++++++++ src/providers/twitch/TwitchChannel.cpp | 74 +++++---- src/providers/twitch/TwitchChannel.hpp | 83 +++++----- src/providers/twitch/TwitchEmotes.hpp | 16 +- src/providers/twitch/TwitchMessageBuilder.cpp | 4 +- src/providers/twitch/TwitchServer.cpp | 2 +- src/widgets/helper/ResizingTextEdit.cpp | 2 +- 12 files changed, 362 insertions(+), 164 deletions(-) create mode 100644 src/common/UsernameSet.cpp create mode 100644 src/common/UsernameSet.hpp diff --git a/chatterino.pro b/chatterino.pro index 7ddf1fd34..522dea930 100644 --- a/chatterino.pro +++ b/chatterino.pro @@ -250,7 +250,8 @@ SOURCES += \ src/widgets/helper/EffectLabel.cpp \ src/widgets/helper/Button.cpp \ src/messages/MessageContainer.cpp \ - src/debug/Benchmark.cpp + src/debug/Benchmark.cpp \ + src/common/UsernameSet.cpp HEADERS += \ src/Application.hpp \ @@ -445,7 +446,8 @@ HEADERS += \ src/widgets/helper/EffectLabel.hpp \ src/util/LayoutHelper.hpp \ src/widgets/helper/Button.hpp \ - src/messages/MessageContainer.hpp + src/messages/MessageContainer.hpp \ + src/common/UsernameSet.hpp RESOURCES += \ resources/resources.qrc \ diff --git a/src/common/Channel.hpp b/src/common/Channel.hpp index c1dd06651..f265f4b70 100644 --- a/src/common/Channel.hpp +++ b/src/common/Channel.hpp @@ -51,7 +51,6 @@ public: void addOrReplaceTimeout(MessagePtr message); void disableAllMessages(); void replaceMessage(MessagePtr message, MessagePtr replacement); - virtual void addRecentChatter(const MessagePtr &message); QStringList modList; @@ -67,6 +66,7 @@ public: protected: virtual void onConnected(); + virtual void addRecentChatter(const MessagePtr &message); private: const QString name_; diff --git a/src/common/CompletionModel.cpp b/src/common/CompletionModel.cpp index 04425a624..69e7ffe70 100644 --- a/src/common/CompletionModel.cpp +++ b/src/common/CompletionModel.cpp @@ -2,8 +2,10 @@ #include "Application.hpp" #include "common/Common.hpp" +#include "common/UsernameSet.hpp" #include "controllers/accounts/AccountController.hpp" #include "controllers/commands/CommandController.hpp" +#include "debug/Benchmark.hpp" #include "debug/Log.hpp" #include "providers/twitch/TwitchChannel.hpp" #include "providers/twitch/TwitchServer.hpp" @@ -103,88 +105,81 @@ int CompletionModel::rowCount(const QModelIndex &) const return this->emotes_.size(); } -void CompletionModel::refresh() +void CompletionModel::refresh(const QString &prefix) { - log("[CompletionModel:{}] Refreshing...]", this->channelName_); + { + std::lock_guard guard(this->emotesMutex_); + this->emotes_.clear(); + } - auto app = getApp(); + if (prefix.length() < 2) return; - // User-specific: Twitch Emotes - if (auto account = app->accounts->twitch.getCurrent()) { - for (const auto &emote : account->accessEmotes()->allEmoteNames) { - // XXX: No way to discern between a twitch global emote and sub - // emote right now - this->addString(emote.string, - TaggedString::Type::TwitchGlobalEmote); + BenchmarkGuard guard("CompletionModel::refresh"); + + auto addString = [&](const QString &str, TaggedString::Type type) { + if (str.startsWith(prefix)) this->emotes_.emplace(str + " ", type); + }; + + auto _channel = getApp()->twitch2->getChannelOrEmpty(this->channelName_); + + if (auto channel = dynamic_cast(_channel.get())) { + // account emotes + if (auto account = getApp()->accounts->twitch.getCurrent()) { + for (const auto &emote : account->accessEmotes()->allEmoteNames) { + // XXX: No way to discern between a twitch global emote and sub + // emote right now + addString(emote.string, TaggedString::Type::TwitchGlobalEmote); + } + } + + // Usernames + if (prefix.length() >= UsernameSet::PrefixLength) { + auto usernames = channel->accessChatters(); + + for (const auto &name : usernames->subrange(Prefix(prefix))) { + addString(name, TaggedString::Type::Username); + addString("@" + name, TaggedString::Type::Username); + } + } + + // Bttv Global + for (auto &emote : *channel->globalBttv().emotes()) { + addString(emote.first.string, TaggedString::Type::BTTVChannelEmote); + } + + // Ffz Global + for (auto &emote : *channel->globalFfz().emotes()) { + addString(emote.first.string, TaggedString::Type::FFZChannelEmote); + } + + // Bttv Channel + for (auto &emote : *channel->bttvEmotes()) { + addString(emote.first.string, TaggedString::Type::BTTVGlobalEmote); + } + + // Ffz Channel + for (auto &emote : *channel->ffzEmotes()) { + addString(emote.first.string, TaggedString::Type::BTTVGlobalEmote); + } + + // Emojis + if (prefix.startsWith(":")) { + const auto &emojiShortCodes = getApp()->emotes->emojis.shortCodes; + for (auto &m : emojiShortCodes) { + addString(":" + m + ":", TaggedString::Type::Emoji); + } + } + + // Commands + for (auto &command : getApp()->commands->items.getVector()) { + addString(command.name, TaggedString::Command); + } + + for (auto &command : + getApp()->commands->getDefaultTwitchCommandList()) { + addString(command, TaggedString::Command); } } - - // // Global: BTTV Global Emotes - // std::vector &bttvGlobalEmoteCodes = - // app->emotes->bttv.globalEmoteNames_; for (const auto &m : - // bttvGlobalEmoteCodes) { - // this->addString(m, TaggedString::Type::BTTVGlobalEmote); - // } - - // // Global: FFZ Global Emotes - // std::vector &ffzGlobalEmoteCodes = - // app->emotes->ffz.globalEmoteCodes; for (const auto &m : - // ffzGlobalEmoteCodes) { - // this->addString(m, TaggedString::Type::FFZGlobalEmote); - // } - - // Channel emotes - if (auto channel = dynamic_cast( - getApp() - ->twitch2->getChannelOrEmptyByID(this->channelName_) - .get())) { - auto bttv = channel->bttvEmotes(); - // auto it = bttv->begin(); - // for (const auto &emote : *bttv) { - // } - // std::vector &bttvChannelEmoteCodes = - // app->emotes->bttv.channelEmoteName_[this->channelName_]; - // for (const auto &m : bttvChannelEmoteCodes) { - // this->addString(m, TaggedString::Type::BTTVChannelEmote); - // } - - // Channel-specific: FFZ Channel Emotes - for (const auto &emote : *channel->ffzEmotes()) { - this->addString(emote.second->name.string, - TaggedString::Type::FFZChannelEmote); - } - } - - // Emojis - const auto &emojiShortCodes = app->emotes->emojis.shortCodes; - for (const auto &m : emojiShortCodes) { - this->addString(":" + m + ":", TaggedString::Type::Emoji); - } - - // Commands - for (auto &command : app->commands->items.getVector()) { - this->addString(command.name, TaggedString::Command); - } - - for (auto &command : app->commands->getDefaultTwitchCommandList()) { - this->addString(command, TaggedString::Command); - } - - // Channel-specific: Usernames - // fourtf: only works with twitch chat - // auto c = - // ChannelManager::getInstance().getTwitchChannel(this->channelName); - // auto usernames = c->getUsernamesForCompletions(); - // for (const auto &name : usernames) { - // assert(!name.displayName.isEmpty()); - // this->addString(name.displayName); - // this->addString('@' + name.displayName); - - // if (!name.localizedName.isEmpty()) { - // this->addString(name.localizedName); - // this->addString('@' + name.localizedName); - // } - // } } void CompletionModel::addString(const QString &str, TaggedString::Type type) @@ -200,8 +195,7 @@ void CompletionModel::addUser(const QString &username) auto add = [this](const QString &str) { auto ts = this->createUser(str + " "); // Always add a space at the end of completions - std::pair::iterator, bool> p = - this->emotes_.insert(ts); + auto p = this->emotes_.insert(ts); if (!p.second) { // No inseration was made, figure out if we need to replace the // username. diff --git a/src/common/CompletionModel.hpp b/src/common/CompletionModel.hpp index 977768474..d0a5e3a06 100644 --- a/src/common/CompletionModel.hpp +++ b/src/common/CompletionModel.hpp @@ -51,7 +51,7 @@ public: virtual QVariant data(const QModelIndex &index, int) const override; virtual int rowCount(const QModelIndex &) const override; - void refresh(); + void refresh(const QString &prefix); void addString(const QString &str, TaggedString::Type type); void addUser(const QString &str); diff --git a/src/common/UsernameSet.cpp b/src/common/UsernameSet.cpp new file mode 100644 index 000000000..4356772a9 --- /dev/null +++ b/src/common/UsernameSet.cpp @@ -0,0 +1,110 @@ +#include "UsernameSet.hpp" + +#include + +namespace chatterino { + +// +// UsernameSet +// + +UsernameSet::ConstIterator UsernameSet::begin() const +{ + return this->items.begin(); +} + +UsernameSet::ConstIterator UsernameSet::end() const +{ + return this->items.end(); +} + +UsernameSet::Range UsernameSet::subrange(const Prefix &prefix) const +{ + auto it = this->firstKeyForPrefix.find(prefix); + if (it != this->firstKeyForPrefix.end()) { + auto start = this->items.find(it->second); + auto end = start; + + while (end != this->items.end() && prefix.isStartOf(*end)) { + end++; + } + return {start, end}; + } + + return {this->items.end(), this->items.end()}; +} + +std::set::size_type UsernameSet::size() const +{ + return this->items.size(); +} + +std::pair UsernameSet::insert(const QString &value) +{ + this->insertPrefix(value); + + return this->items.insert(value); +} + +std::pair UsernameSet::insert(QString &&value) +{ + this->insertPrefix(value); + + return this->items.insert(std::move(value)); +} + +void UsernameSet::insertPrefix(const QString &value) +{ + auto &string = this->firstKeyForPrefix[Prefix(value)]; + + if (string.isNull() || value < string) string = value; +} + +// +// Range +// + +UsernameSet::Range::Range(ConstIterator start, ConstIterator end) + : start_(start) + , end_(end) +{ +} + +UsernameSet::ConstIterator UsernameSet::Range::begin() +{ + return this->start_; +} + +UsernameSet::ConstIterator UsernameSet::Range::end() +{ + return this->end_; +} + +// +// Prefix +// + +Prefix::Prefix(const QString &string) + : first(string.size() >= 1 ? string[0] : '\0') + , second(string.size() >= 2 ? string[1] : '\0') +{ +} + +bool Prefix::operator==(const Prefix &other) const +{ + return std::tie(this->first, this->second) == + std::tie(other.first, other.second); +} + +bool Prefix::isStartOf(const QString &string) const +{ + if (string.size() == 0) { + return this->first == QChar('\0') && this->second == QChar('\0'); + } else if (string.size() == 1) { + return this->first == string[0] && this->second == QChar('\0'); + } else { + return this->first == string[0] && this->second == string[1]; + } +} + +} // namespace chatterino diff --git a/src/common/UsernameSet.hpp b/src/common/UsernameSet.hpp new file mode 100644 index 000000000..d71bcdaf6 --- /dev/null +++ b/src/common/UsernameSet.hpp @@ -0,0 +1,73 @@ +#pragma once + +#include +#include +#include +#include + +namespace chatterino { +class Prefix +{ +public: + Prefix(const QString &string); + bool operator==(const Prefix &other) const; + bool isStartOf(const QString &string) const; + +private: + QChar first; + QChar second; + + friend struct std::hash; +}; +} // namespace chatterino + +namespace std { +template <> +struct hash { + size_t operator()(const chatterino::Prefix &prefix) const + { + return (size_t(prefix.first.unicode()) << 16) | + size_t(prefix.second.unicode()); + } +}; +} // namespace std + +namespace chatterino { +class UsernameSet +{ +public: + static constexpr int PrefixLength = 2; + + using Iterator = std::set::iterator; + using ConstIterator = std::set::const_iterator; + + class Range + { + public: + Range(ConstIterator start, ConstIterator end); + + ConstIterator begin(); + ConstIterator end(); + + private: + ConstIterator start_; + ConstIterator end_; + }; + + ConstIterator begin() const; + ConstIterator end() const; + Range subrange(const Prefix &prefix) const; + + std::set::size_type size() const; + + std::pair insert(const QString &value); + std::pair insert(QString &&value); + +private: + void insertPrefix(const QString &string); + + std::set items; + std::unordered_map firstKeyForPrefix; +}; + +} // namespace chatterino diff --git a/src/providers/twitch/TwitchChannel.cpp b/src/providers/twitch/TwitchChannel.cpp index 6413629f6..ad3cdc94a 100644 --- a/src/providers/twitch/TwitchChannel.cpp +++ b/src/providers/twitch/TwitchChannel.cpp @@ -49,6 +49,24 @@ auto parseRecentMessages(const QJsonObject &jsonRoot, TwitchChannel &channel) return messages; } +std::pair parseChatters(const QJsonObject &jsonRoot) +{ + static QStringList categories = {"moderators", "staff", "admins", + "global_mods", "viewers"}; + + auto usernames = UsernameSet(); + + // parse json + QJsonObject jsonCategories = jsonRoot.value("chatters").toObject(); + + for (const auto &category : categories) { + for (auto jsonCategory : jsonCategories.value(category).toArray()) { + usernames.insert(jsonCategory.toString()); + } + } + + return {Success, std::move(usernames)}; +} } // namespace TwitchChannel::TwitchChannel(const QString &name, BttvEmotes &bttv, @@ -72,22 +90,22 @@ TwitchChannel::TwitchChannel(const QString &name, BttvEmotes &bttv, [=] { this->setMod(false); }); // pubsub - this->userStateChanged.connect([=] { this->refreshPubsub(); }); this->managedConnect(getApp()->accounts->twitch.currentUserChanged, [=] { this->refreshPubsub(); }); this->refreshPubsub(); + this->userStateChanged.connect([this] { this->refreshPubsub(); }); // room id loaded -> refresh live status this->roomIdChanged.connect([this]() { this->refreshPubsub(); this->refreshLiveStatus(); - this->loadBadges(); - this->loadCheerEmotes(); + this->refreshBadges(); + this->refreshCheerEmotes(); }); // timers QObject::connect(&this->chattersListTimer_, &QTimer::timeout, - [=] { this->refreshViewerList(); }); + [=] { this->refreshChatters(); }); this->chattersListTimer_.start(5 * 60 * 1000); QObject::connect(&this->liveStatusTimer_, &QTimer::timeout, @@ -101,11 +119,17 @@ TwitchChannel::TwitchChannel(const QString &name, BttvEmotes &bttv, // debugging #if 0 for (int i = 0; i < 1000; i++) { - this->addMessage(makeSystemMessage("asdf")); + this->addMessage(makeSystemMessage("asef")); } #endif } +void TwitchChannel::initialize() +{ + this->refreshChatters(); + this->refreshChannelEmotes(); +} + bool TwitchChannel::isEmpty() const { return this->getName().isEmpty(); @@ -293,6 +317,11 @@ TwitchChannel::accessStreamStatus() const return this->streamStatus_.accessConst(); } +AccessGuard TwitchChannel::accessChatters() const +{ + return this->chatters_.accessConst(); +} + const BttvEmotes &TwitchChannel::globalBttv() const { return this->globalBttv_; @@ -314,7 +343,7 @@ boost::optional TwitchChannel::bttvEmote(const EmoteName &name) const boost::optional TwitchChannel::ffzEmote(const EmoteName &name) const { - auto emotes = this->bttvEmotes_.get(); + auto emotes = this->ffzEmotes_.get(); auto it = emotes->find(name); if (it == emotes->end()) return boost::none; @@ -508,7 +537,7 @@ void TwitchChannel::refreshPubsub() account); } -void TwitchChannel::refreshViewerList() +void TwitchChannel::refreshChatters() { // setting? const auto streamStatus = this->accessStreamStatus(); @@ -531,31 +560,18 @@ void TwitchChannel::refreshViewerList() auto shared = weak.lock(); if (!shared) return Failure; - return this->parseViewerList(result.parseJson()); + auto pair = parseChatters(result.parseJson()); + if (pair.first) { + *this->chatters_.access() = std::move(pair.second); + } + + return pair.first; }); request.execute(); } -Outcome TwitchChannel::parseViewerList(const QJsonObject &jsonRoot) -{ - static QStringList categories = {"moderators", "staff", "admins", - "global_mods", "viewers"}; - - // parse json - QJsonObject jsonCategories = jsonRoot.value("chatters").toObject(); - - for (const auto &category : categories) { - for (const auto jsonCategory : - jsonCategories.value(category).toArray()) { - this->completionModel.addUser(jsonCategory.toString()); - } - } - - return Success; -} - -void TwitchChannel::loadBadges() +void TwitchChannel::refreshBadges() { auto url = Url{"https://badges.twitch.tv/v1/badges/channels/" + this->roomId() + "/display?language=en"}; @@ -600,7 +616,7 @@ void TwitchChannel::loadBadges() req.execute(); } -void TwitchChannel::loadCheerEmotes() +void TwitchChannel::refreshCheerEmotes() { /*auto url = Url{"https://api.twitch.tv/kraken/bits/actions?channel_id=" + this->getRoomId()}; @@ -664,7 +680,7 @@ void TwitchChannel::loadCheerEmotes() */ } -boost::optional TwitchChannel::getTwitchBadge( +boost::optional TwitchChannel::twitchBadge( const QString &set, const QString &version) const { auto badgeSets = this->badgeSets_.access(); diff --git a/src/providers/twitch/TwitchChannel.hpp b/src/providers/twitch/TwitchChannel.hpp index a444d26e2..ea95c0df3 100644 --- a/src/providers/twitch/TwitchChannel.hpp +++ b/src/providers/twitch/TwitchChannel.hpp @@ -1,13 +1,17 @@ #pragma once -#include - #include "common/Aliases.hpp" #include "common/Atomic.hpp" #include "common/Channel.hpp" #include "common/Outcome.hpp" #include "common/UniqueAccess.hpp" +#include "common/UsernameSet.hpp" +#include "providers/twitch/TwitchEmotes.hpp" +#include +#include +#include +#include #include #include #include @@ -37,11 +41,6 @@ public: QString streamType; }; - struct UserState { - bool mod; - bool broadcaster; - }; - struct RoomModes { bool submode = false; bool r9k = false; @@ -51,32 +50,24 @@ public: QString broadcasterLang; }; - void refreshChannelEmotes(); + void initialize(); // Channel methods virtual bool isEmpty() const override; virtual bool canSendMessage() const override; virtual void sendMessage(const QString &message) override; - - // Auto completion - void addRecentChatter(const MessagePtr &message) final; - void addJoinedUser(const QString &user); - void addPartedUser(const QString &user); - - bool isLive() const; virtual bool isMod() const override; - void setMod(bool value); virtual bool isBroadcaster() const override; // Data const QString &subscriptionUrl(); const QString &channelUrl(); const QString &popoutPlayerUrl(); + bool isLive() const; QString roomId() const; - void setRoomId(const QString &id); AccessGuard accessRoomModes() const; - void setRoomModes(const RoomModes &roomModes_); AccessGuard accessStreamStatus() const; + AccessGuard accessChatters() const; // Emotes const BttvEmotes &globalBttv() const; @@ -86,58 +77,53 @@ public: std::shared_ptr bttvEmotes() const; std::shared_ptr ffzEmotes() const; - boost::optional getTwitchBadge(const QString &set, - const QString &version) const; + void refreshChannelEmotes(); + + // Badges + boost::optional twitchBadge(const QString &set, + const QString &version) const; // Signals pajlada::Signals::NoArgSignal roomIdChanged; - pajlada::Signals::NoArgSignal liveStatusChanged; pajlada::Signals::NoArgSignal userStateChanged; + pajlada::Signals::NoArgSignal liveStatusChanged; pajlada::Signals::NoArgSignal roomModesChanged; +protected: + void addRecentChatter(const MessagePtr &message) override; + private: struct NameOptions { QString displayName; QString localizedName; }; - struct CheerEmote { - // a Cheermote indicates one tier - QColor color; - int minBits; - - EmotePtr animatedEmote; - EmotePtr staticEmote; - }; - - struct CheerEmoteSet { - QRegularExpression regex; - std::vector cheerEmotes; - }; - - explicit TwitchChannel(const QString &channelName, BttvEmotes &bttv, - FfzEmotes &ffz); + explicit TwitchChannel(const QString &channelName, BttvEmotes &globalBttv, + FfzEmotes &globalFfz); // Methods void refreshLiveStatus(); Outcome parseLiveStatus(const rapidjson::Document &document); void refreshPubsub(); - void refreshViewerList(); - Outcome parseViewerList(const QJsonObject &jsonRoot); + void refreshChatters(); + void refreshBadges(); + void refreshCheerEmotes(); void loadRecentMessages(); + void addJoinedUser(const QString &user); + void addPartedUser(const QString &user); void setLive(bool newLiveStatus); - - void loadBadges(); - void loadCheerEmotes(); + void setMod(bool value); + void setRoomId(const QString &id); + void setRoomModes(const RoomModes &roomModes_); // Data const QString subscriptionUrl_; const QString channelUrl_; const QString popoutPlayerUrl_; UniqueAccess streamStatus_; - UniqueAccess userState_; UniqueAccess roomModes_; + UniqueAccess chatters_; // maps 2 char prefix to set of names // Emotes BttvEmotes &globalBttv_; @@ -145,6 +131,11 @@ private: Atomic> bttvEmotes_; Atomic> ffzEmotes_; + // Badges + UniqueAccess>> + badgeSets_; // "subscribers": { "0": ... "3": ... "6": ... + UniqueAccess> cheerEmoteSets_; + bool mod_ = false; UniqueAccess roomID_; @@ -153,10 +144,6 @@ private: UniqueAccess partedUsers_; bool partedUsersMergeQueued_ = false; - // "subscribers": { "0": ... "3": ... "6": ... - UniqueAccess>> badgeSets_; - UniqueAccess> cheerEmoteSets_; - // -- QByteArray messageSuffix_; QString lastSentMessage_; @@ -165,6 +152,8 @@ private: QTimer chattersListTimer_; friend class TwitchServer; + friend class TwitchMessageBuilder; + friend class IrcMessageHandler; }; } // namespace chatterino diff --git a/src/providers/twitch/TwitchEmotes.hpp b/src/providers/twitch/TwitchEmotes.hpp index 90cafe440..1c1b0b216 100644 --- a/src/providers/twitch/TwitchEmotes.hpp +++ b/src/providers/twitch/TwitchEmotes.hpp @@ -1,5 +1,7 @@ #pragma once +#include +#include #include #include @@ -11,10 +13,22 @@ "https://static-cdn.jtvnw.net/emoticons/v1/{id}/{scale}" namespace chatterino { - struct Emote; using EmotePtr = std::shared_ptr; +struct CheerEmote { + QColor color; + int minBits; + + EmotePtr animatedEmote; + EmotePtr staticEmote; +}; + +struct CheerEmoteSet { + QRegularExpression regex; + std::vector cheerEmotes; +}; + class TwitchEmotes { public: diff --git a/src/providers/twitch/TwitchMessageBuilder.cpp b/src/providers/twitch/TwitchMessageBuilder.cpp index 7f8c2aa3d..97b41561a 100644 --- a/src/providers/twitch/TwitchMessageBuilder.cpp +++ b/src/providers/twitch/TwitchMessageBuilder.cpp @@ -646,7 +646,7 @@ Outcome TwitchMessageBuilder::tryAppendEmote(const EmoteName &name) flags = MessageElementFlag::BttvEmote; } else if ((emote = this->twitchChannel->globalFfz().emote(name))) { flags = MessageElementFlag::FfzEmote; - } else if (twitchChannel && (emote = this->twitchChannel->ffzEmote(name))) { + } else if ((emote = this->twitchChannel->ffzEmote(name))) { flags = MessageElementFlag::FfzEmote; } @@ -691,7 +691,7 @@ void TwitchMessageBuilder::appendTwitchBadges() // Try to fetch channel-specific bit badge try { if (twitchChannel) - if (const auto &badge = this->twitchChannel->getTwitchBadge( + if (const auto &badge = this->twitchChannel->twitchBadge( "bits", cheerAmount)) { this->emplace( badge.get(), MessageElementFlag::BadgeVanity) diff --git a/src/providers/twitch/TwitchServer.cpp b/src/providers/twitch/TwitchServer.cpp index bb7b16fd9..465fe3315 100644 --- a/src/providers/twitch/TwitchServer.cpp +++ b/src/providers/twitch/TwitchServer.cpp @@ -85,7 +85,7 @@ std::shared_ptr TwitchServer::createChannel(const QString &channelName) { auto channel = std::shared_ptr( new TwitchChannel(channelName, this->bttv, this->ffz)); - channel->refreshChannelEmotes(); + channel->initialize(); channel->sendMessageSignal.connect( [this, channel = channel.get()](auto &chan, auto &msg, bool &sent) { diff --git a/src/widgets/helper/ResizingTextEdit.cpp b/src/widgets/helper/ResizingTextEdit.cpp index 731bed53b..1a06b1868 100644 --- a/src/widgets/helper/ResizingTextEdit.cpp +++ b/src/widgets/helper/ResizingTextEdit.cpp @@ -102,7 +102,7 @@ void ResizingTextEdit::keyPressEvent(QKeyEvent *event) // First type pressing tab after modifying a message, we refresh our // completion model this->completer_->setModel(completionModel); - completionModel->refresh(); + completionModel->refresh(currentCompletionPrefix); this->completionInProgress_ = true; this->completer_->setCompletionPrefix(currentCompletionPrefix); this->completer_->complete(); From 2448f6f5384eb50dc882aef01985e8006a15022e Mon Sep 17 00:00:00 2001 From: fourtf Date: Mon, 13 Aug 2018 14:38:03 +0200 Subject: [PATCH 07/14] cleaned up CompletionModel --- src/common/Channel.cpp | 7 +- src/common/CompletionModel.cpp | 143 +++++-------------------- src/common/CompletionModel.hpp | 23 ++-- src/providers/twitch/TwitchChannel.cpp | 7 +- src/providers/twitch/TwitchServer.hpp | 2 +- 5 files changed, 35 insertions(+), 147 deletions(-) diff --git a/src/common/Channel.cpp b/src/common/Channel.cpp index d7f1659f4..9c1967f60 100644 --- a/src/common/Channel.cpp +++ b/src/common/Channel.cpp @@ -22,15 +22,10 @@ namespace chatterino { // Channel // Channel::Channel(const QString &name, Type type) - : completionModel(name) + : completionModel(*this) , name_(name) , type_(type) { - QObject::connect(&this->clearCompletionModelTimer_, &QTimer::timeout, - [this]() { - this->completionModel.clearExpiredStrings(); // - }); - this->clearCompletionModelTimer_.start(60 * 1000); } Channel::~Channel() diff --git a/src/common/CompletionModel.cpp b/src/common/CompletionModel.cpp index 69e7ffe70..ce07b25f6 100644 --- a/src/common/CompletionModel.cpp +++ b/src/common/CompletionModel.cpp @@ -12,38 +12,20 @@ #include "singletons/Emotes.hpp" #include - #include namespace chatterino { -// -- TaggedString +// +// TaggedString +// -CompletionModel::TaggedString::TaggedString(const QString &_str, Type _type) - : str(_str) +CompletionModel::TaggedString::TaggedString(const QString &_string, Type _type) + : string(_string) , type(_type) - , timeAdded(std::chrono::steady_clock::now()) { } -bool CompletionModel::TaggedString::isExpired( - const std::chrono::steady_clock::time_point &now) const -{ - switch (this->type) { - case Type::Username: { - static std::chrono::minutes expirationTimer(10); - - return (this->timeAdded + expirationTimer < now); - } break; - - default: { - return false; - } break; - } - - return false; -} - bool CompletionModel::TaggedString::isEmote() const { return this->type > Type::EmoteStart && this->type < Type::EmoteEnd; @@ -51,35 +33,23 @@ bool CompletionModel::TaggedString::isEmote() const bool CompletionModel::TaggedString::operator<(const TaggedString &that) const { - if (this->isEmote()) { - if (that.isEmote()) { - int k = QString::compare(this->str, that.str, Qt::CaseInsensitive); - if (k == 0) { - return this->str > that.str; - } - - return k < 0; - } - - return true; + if (this->isEmote() != that.isEmote()) { + return this->isEmote(); } - if (that.isEmote()) { - return false; - } - - int k = QString::compare(this->str, that.str, Qt::CaseInsensitive); - if (k == 0) { - return false; - } + // try comparing insensitively, if they are the same then senstively + // (fixes order of LuL and LUL) + int k = QString::compare(this->string, that.string, Qt::CaseInsensitive); + if (k == 0) return this->string > that.string; return k < 0; } -// -- CompletionModel - -CompletionModel::CompletionModel(const QString &channelName) - : channelName_(channelName) +// +// CompletionModel +// +CompletionModel::CompletionModel(Channel &channel) + : channel_(channel) { } @@ -90,39 +60,32 @@ int CompletionModel::columnCount(const QModelIndex &) const QVariant CompletionModel::data(const QModelIndex &index, int) const { - std::lock_guard lock(this->emotesMutex_); + std::lock_guard lock(this->itemsMutex_); - // TODO: Implement more safely - auto it = this->emotes_.begin(); + auto it = this->items_.begin(); std::advance(it, index.row()); - return QVariant(it->str); + return QVariant(it->string); } int CompletionModel::rowCount(const QModelIndex &) const { - std::lock_guard lock(this->emotesMutex_); + std::lock_guard lock(this->itemsMutex_); - return this->emotes_.size(); + return this->items_.size(); } void CompletionModel::refresh(const QString &prefix) { - { - std::lock_guard guard(this->emotesMutex_); - this->emotes_.clear(); - } + std::lock_guard guard(this->itemsMutex_); + this->items_.clear(); if (prefix.length() < 2) return; - BenchmarkGuard guard("CompletionModel::refresh"); - auto addString = [&](const QString &str, TaggedString::Type type) { - if (str.startsWith(prefix)) this->emotes_.emplace(str + " ", type); + if (str.startsWith(prefix)) this->items_.emplace(str + " ", type); }; - auto _channel = getApp()->twitch2->getChannelOrEmpty(this->channelName_); - - if (auto channel = dynamic_cast(_channel.get())) { + if (auto channel = dynamic_cast(&this->channel_)) { // account emotes if (auto account = getApp()->accounts->twitch.getCurrent()) { for (const auto &emote : account->accessEmotes()->allEmoteNames) { @@ -182,60 +145,4 @@ void CompletionModel::refresh(const QString &prefix) } } -void CompletionModel::addString(const QString &str, TaggedString::Type type) -{ - std::lock_guard lock(this->emotesMutex_); - - // Always add a space at the end of completions - this->emotes_.insert({str + " ", type}); -} - -void CompletionModel::addUser(const QString &username) -{ - auto add = [this](const QString &str) { - auto ts = this->createUser(str + " "); - // Always add a space at the end of completions - auto p = this->emotes_.insert(ts); - if (!p.second) { - // No inseration was made, figure out if we need to replace the - // username. - - if (p.first->str > ts.str) { - // Replace lowercase version of name with mixed-case version - this->emotes_.erase(p.first); - auto result2 = this->emotes_.insert(ts); - assert(result2.second); - } else { - p.first->timeAdded = std::chrono::steady_clock::now(); - } - } - }; - - add(username); - add("@" + username); -} - -void CompletionModel::clearExpiredStrings() -{ - std::lock_guard lock(this->emotesMutex_); - - auto now = std::chrono::steady_clock::now(); - - for (auto it = this->emotes_.begin(); it != this->emotes_.end();) { - const auto &taggedString = *it; - - if (taggedString.isExpired(now)) { - // Log("String {} expired", taggedString.str); - it = this->emotes_.erase(it); - } else { - ++it; - } - } -} - -CompletionModel::TaggedString CompletionModel::createUser(const QString &str) -{ - return TaggedString{str, TaggedString::Type::Username}; -} - } // namespace chatterino diff --git a/src/common/CompletionModel.hpp b/src/common/CompletionModel.hpp index d0a5e3a06..f4f216cd1 100644 --- a/src/common/CompletionModel.hpp +++ b/src/common/CompletionModel.hpp @@ -8,7 +8,7 @@ namespace chatterino { -class TwitchChannel; +class Channel; class CompletionModel : public QAbstractListModel { @@ -31,39 +31,30 @@ class CompletionModel : public QAbstractListModel Command, }; - TaggedString(const QString &_str, Type _type); + TaggedString(const QString &string, Type type); - bool isExpired(const std::chrono::steady_clock::time_point &now) const; bool isEmote() const; bool operator<(const TaggedString &that) const; - QString str; - // Type will help decide the lifetime of the tagged strings + QString string; Type type; - - mutable std::chrono::steady_clock::time_point timeAdded; }; public: - CompletionModel(const QString &channelName); + CompletionModel(Channel &channel); virtual int columnCount(const QModelIndex &) const override; virtual QVariant data(const QModelIndex &index, int) const override; virtual int rowCount(const QModelIndex &) const override; void refresh(const QString &prefix); - void addString(const QString &str, TaggedString::Type type); - void addUser(const QString &str); - - void clearExpiredStrings(); private: TaggedString createUser(const QString &str); - mutable std::mutex emotesMutex_; - std::set emotes_; - - QString channelName_; + std::set items_; + mutable std::mutex itemsMutex_; + Channel &channel_; }; } // namespace chatterino diff --git a/src/providers/twitch/TwitchChannel.cpp b/src/providers/twitch/TwitchChannel.cpp index ad3cdc94a..da7a508d9 100644 --- a/src/providers/twitch/TwitchChannel.cpp +++ b/src/providers/twitch/TwitchChannel.cpp @@ -83,9 +83,6 @@ TwitchChannel::TwitchChannel(const QString &name, BttvEmotes &bttv, { log("[TwitchChannel:{}] Opened", name); - // this->refreshChannelEmotes(); - // this->refreshViewerList(); - this->managedConnect(getApp()->accounts->twitch.currentUserChanged, [=] { this->setMod(false); }); @@ -220,9 +217,7 @@ bool TwitchChannel::isBroadcaster() const void TwitchChannel::addRecentChatter(const MessagePtr &message) { - assert(!message->loginName.isEmpty()); - - this->completionModel.addUser(message->displayName); + this->chatters_.access()->insert(message->displayName); } void TwitchChannel::addJoinedUser(const QString &user) diff --git a/src/providers/twitch/TwitchServer.hpp b/src/providers/twitch/TwitchServer.hpp index 127c2f62b..e097cc365 100644 --- a/src/providers/twitch/TwitchServer.hpp +++ b/src/providers/twitch/TwitchServer.hpp @@ -16,8 +16,8 @@ namespace chatterino { class Settings; class Paths; - class PubSub; +class TwitchChannel; class TwitchServer final : public AbstractIrcServer, public Singleton { From c4e3bf1a8c058d3407d03634303485ea9806dd1e Mon Sep 17 00:00:00 2001 From: Daniel Pasch Date: Mon, 13 Aug 2018 20:10:32 +0200 Subject: [PATCH 08/14] Fix compiling on macOS High Sierra (#665) * mac docs update relating to qt give a little more detailed installation guide for the qt installation * Fix compiling on clang, now compiles on macOS High Sierra --- chatterino.pro | 4 +++- src/providers/twitch/PubsubHelpers.hpp | 2 +- src/providers/twitch/TwitchChannel.cpp | 4 ++-- src/widgets/BaseWindow.cpp | 4 ++-- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/chatterino.pro b/chatterino.pro index 522dea930..dd97cb271 100644 --- a/chatterino.pro +++ b/chatterino.pro @@ -33,7 +33,7 @@ equals(QMAKE_CXX, "clang++")|equals(QMAKE_CXX, "g++") { } # Icons -macx:ICON = resources/images/chatterino2.icns +#macx:ICON = resources/images/chatterino2.icns win32:RC_FILE = resources/windows.rc @@ -71,6 +71,8 @@ win32 { # OSX include directory macx { INCLUDEPATH += /usr/local/include + INCLUDEPATH += /usr/local/opt/openssl/include + LIBS += -L/usr/local/opt/openssl/lib } # Optional dependency on Windows SDK 7 diff --git a/src/providers/twitch/PubsubHelpers.hpp b/src/providers/twitch/PubsubHelpers.hpp index 3e92e332c..f9bc28a05 100644 --- a/src/providers/twitch/PubsubHelpers.hpp +++ b/src/providers/twitch/PubsubHelpers.hpp @@ -1,7 +1,7 @@ #pragma once #include "util/RapidjsonHelpers.hpp" - +#include "debug/Log.hpp" #include #include #include diff --git a/src/providers/twitch/TwitchChannel.cpp b/src/providers/twitch/TwitchChannel.cpp index da7a508d9..346ed1476 100644 --- a/src/providers/twitch/TwitchChannel.cpp +++ b/src/providers/twitch/TwitchChannel.cpp @@ -409,7 +409,7 @@ void TwitchChannel::refreshLiveStatus() //>>>>>>> 9bfbdefd2f0972a738230d5b95a009f73b1dd933 request.onSuccess( - [this, weak = this->weak_from_this()](auto result) -> Outcome { + [this, weak = weakOf(this)](auto result) -> Outcome { ChannelPtr shared = weak.lock(); if (!shared) return Failure; @@ -550,7 +550,7 @@ void TwitchChannel::refreshChatters() request.setCaller(QThread::currentThread()); request.onSuccess( - [this, weak = this->weak_from_this()](auto result) -> Outcome { + [this, weak = weakOf(this)](auto result) -> Outcome { // channel still exists? auto shared = weak.lock(); if (!shared) return Failure; diff --git a/src/widgets/BaseWindow.cpp b/src/widgets/BaseWindow.cpp index 32d470805..af97b224b 100644 --- a/src/widgets/BaseWindow.cpp +++ b/src/widgets/BaseWindow.cpp @@ -316,7 +316,7 @@ void BaseWindow::mousePressEvent(QMouseEvent *event) }; if (!recursiveCheckMouseTracking(widget)) { - Log("Start moving"); + log("Start moving"); this->moving = true; } } @@ -331,7 +331,7 @@ void BaseWindow::mouseReleaseEvent(QMouseEvent *event) #ifndef Q_OS_WIN if (this->flags_ & FramelessDraggable) { if (this->moving) { - Log("Stop moving"); + log("Stop moving"); this->moving = false; } } From 902fe684c0a8a19bccbc19813b0a436fc8554f05 Mon Sep 17 00:00:00 2001 From: fourtf Date: Tue, 14 Aug 2018 17:34:45 +0200 Subject: [PATCH 09/14] Fixes #666 --- src/common/CompletionModel.cpp | 3 ++- src/common/UsernameSet.cpp | 10 ++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/common/CompletionModel.cpp b/src/common/CompletionModel.cpp index ce07b25f6..8ccafb8e5 100644 --- a/src/common/CompletionModel.cpp +++ b/src/common/CompletionModel.cpp @@ -82,7 +82,8 @@ void CompletionModel::refresh(const QString &prefix) if (prefix.length() < 2) return; auto addString = [&](const QString &str, TaggedString::Type type) { - if (str.startsWith(prefix)) this->items_.emplace(str + " ", type); + if (str.startsWith(prefix, Qt::CaseInsensitive)) + this->items_.emplace(str + " ", type); }; if (auto channel = dynamic_cast(&this->channel_)) { diff --git a/src/common/UsernameSet.cpp b/src/common/UsernameSet.cpp index 4356772a9..064b6cf54 100644 --- a/src/common/UsernameSet.cpp +++ b/src/common/UsernameSet.cpp @@ -85,8 +85,8 @@ UsernameSet::ConstIterator UsernameSet::Range::end() // Prefix::Prefix(const QString &string) - : first(string.size() >= 1 ? string[0] : '\0') - , second(string.size() >= 2 ? string[1] : '\0') + : first(string.size() >= 1 ? string[0].toLower() : '\0') + , second(string.size() >= 2 ? string[1].toLower() : '\0') { } @@ -101,9 +101,11 @@ bool Prefix::isStartOf(const QString &string) const if (string.size() == 0) { return this->first == QChar('\0') && this->second == QChar('\0'); } else if (string.size() == 1) { - return this->first == string[0] && this->second == QChar('\0'); + return this->first == string[0].toLower() && + this->second == QChar('\0'); } else { - return this->first == string[0] && this->second == string[1]; + return this->first == string[0].toLower() && + this->second == string[1].toLower(); } } From d7566665d88bdc46df532d9ca4dffe5f6173be69 Mon Sep 17 00:00:00 2001 From: Confuseh Date: Tue, 14 Aug 2018 16:36:20 +0100 Subject: [PATCH 10/14] minor streamlink quality option fix (#664) --- src/util/StreamLink.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/util/StreamLink.cpp b/src/util/StreamLink.cpp index aa2db55c0..3cf639b6c 100644 --- a/src/util/StreamLink.cpp +++ b/src/util/StreamLink.cpp @@ -4,6 +4,7 @@ #include "Helpers.hpp" #include "singletons/Settings.hpp" #include "widgets/dialogs/QualityPopup.hpp" +#include "debug/Log.hpp" #include #include @@ -83,7 +84,7 @@ QProcess *createStreamlinkProcess() if (err == QProcess::FailedToStart) { showStreamlinkNotFoundError(); } else { - qDebug() << "Error occured: " << err; // + log("Error occured {}", err); } p->deleteLater(); @@ -109,7 +110,7 @@ void getStreamQualities(const QString &channelURL, p, static_cast(&QProcess::finished), [=](int res) { if (res != 0) { - qDebug() << "Got error code" << res; + log("Got error code {}", res); // return; } QString lastLine = QString(p->readAllStandardOutput()); @@ -121,7 +122,15 @@ void getStreamQualities(const QString &channelURL, for (int i = split.length() - 1; i >= 0; i--) { QString option = split.at(i); - if (option.endsWith(" (worst)")) { + if (option == "best)") { + // As it turns out, sometimes, one quality option can + // be the best and worst quality at the same time. + // Since we start loop from the end, we can check + // that and act accordingly + option = split.at(--i); + // "900p60 (worst" + options << option.left(option.length() - 7); + } else if (option.endsWith(" (worst)")) { options << option.left(option.length() - 8); } else if (option.endsWith(" (best)")) { options << option.left(option.length() - 7); From 44c16f1b3a5a514df1bb8e3a2a8ddcdce721e615 Mon Sep 17 00:00:00 2001 From: fourtf Date: Tue, 14 Aug 2018 17:45:17 +0200 Subject: [PATCH 11/14] badges --- src/common/Channel.cpp | 7 +- src/providers/twitch/PubsubHelpers.hpp | 1 + src/providers/twitch/TwitchBadges.cpp | 57 ++++--- src/providers/twitch/TwitchBadges.hpp | 16 +- src/providers/twitch/TwitchChannel.cpp | 9 +- src/providers/twitch/TwitchChannel.hpp | 8 +- src/providers/twitch/TwitchMessageBuilder.cpp | 143 ++++-------------- src/providers/twitch/TwitchServer.cpp | 6 +- src/providers/twitch/TwitchServer.hpp | 2 + src/widgets/splits/SplitHeader.cpp | 4 +- 10 files changed, 100 insertions(+), 153 deletions(-) diff --git a/src/common/Channel.cpp b/src/common/Channel.cpp index 9c1967f60..f9ac3ac50 100644 --- a/src/common/Channel.cpp +++ b/src/common/Channel.cpp @@ -160,13 +160,14 @@ void Channel::disableAllMessages() LimitedQueueSnapshot snapshot = this->getMessageSnapshot(); int snapshotLength = snapshot.getLength(); for (int i = 0; i < snapshotLength; i++) { - auto &s = snapshot[i]; - if (s->flags.hasAny({MessageFlag::System, MessageFlag::Timeout})) { + auto &message = snapshot[i]; + if (message->flags.hasAny( + {MessageFlag::System, MessageFlag::Timeout})) { continue; } // FOURTF: disabled for now - // s->flags.EnableFlag(MessageFlag::Disabled); + const_cast(message.get())->flags.set(MessageFlag::Disabled); } } diff --git a/src/providers/twitch/PubsubHelpers.hpp b/src/providers/twitch/PubsubHelpers.hpp index f9bc28a05..fe7056dc8 100644 --- a/src/providers/twitch/PubsubHelpers.hpp +++ b/src/providers/twitch/PubsubHelpers.hpp @@ -1,5 +1,6 @@ #pragma once +#include "debug/Log.hpp" #include "util/RapidjsonHelpers.hpp" #include "debug/Log.hpp" #include diff --git a/src/providers/twitch/TwitchBadges.cpp b/src/providers/twitch/TwitchBadges.cpp index 8853f1add..0e515d627 100644 --- a/src/providers/twitch/TwitchBadges.cpp +++ b/src/providers/twitch/TwitchBadges.cpp @@ -4,21 +4,14 @@ #include #include #include + #include "common/NetworkRequest.hpp" #include "common/Outcome.hpp" +#include "debug/Log.hpp" #include "messages/Emote.hpp" namespace chatterino { -TwitchBadges::TwitchBadges() -{ -} - -void TwitchBadges::initialize(Settings &settings, Paths &paths) -{ - this->loadTwitchBadges(); -} - void TwitchBadges::loadTwitchBadges() { static QString url( @@ -28,32 +21,34 @@ void TwitchBadges::loadTwitchBadges() req.setCaller(QThread::currentThread()); req.onSuccess([this](auto result) -> Outcome { auto root = result.parseJson(); - QJsonObject sets = root.value("badge_sets").toObject(); + auto badgeSets = this->badgeSets_.access(); - for (QJsonObject::iterator it = sets.begin(); it != sets.end(); ++it) { - QJsonObject versions = - it.value().toObject().value("versions").toObject(); + auto jsonSets = root.value("badge_sets").toObject(); + for (auto sIt = jsonSets.begin(); sIt != jsonSets.end(); ++sIt) { + auto key = sIt.key(); + auto versions = sIt.value().toObject().value("versions").toObject(); + + for (auto vIt = versions.begin(); vIt != versions.end(); ++vIt) { + auto versionObj = vIt.value().toObject(); - for (auto versionIt = std::begin(versions); - versionIt != std::end(versions); ++versionIt) { auto emote = Emote{ {""}, ImageSet{ - Image::fromUrl({root.value("image_url_1x").toString()}, - 1), - Image::fromUrl({root.value("image_url_2x").toString()}, - 0.5), - Image::fromUrl({root.value("image_url_4x").toString()}, - 0.25), + Image::fromUrl( + {versionObj.value("image_url_1x").toString()}, 1), + Image::fromUrl( + {versionObj.value("image_url_2x").toString()}, .5), + Image::fromUrl( + {versionObj.value("image_url_4x").toString()}, .25), }, Tooltip{root.value("description").toString()}, Url{root.value("clickURL").toString()}}; // "title" // "clickAction" - QJsonObject versionObj = versionIt.value().toObject(); - this->badges.emplace(versionIt.key(), - std::make_shared(emote)); + log("{} {}", key, vIt.key()); + + (*badgeSets)[key][vIt.key()] = std::make_shared(emote); } } @@ -63,4 +58,18 @@ void TwitchBadges::loadTwitchBadges() req.execute(); } +boost::optional TwitchBadges::badge(const QString &set, + const QString &version) const +{ + auto badgeSets = this->badgeSets_.access(); + auto it = badgeSets->find(set); + if (it != badgeSets->end()) { + auto it2 = it->second.find(version); + if (it2 != it->second.end()) { + return it2->second; + } + } + return boost::none; +} + } // namespace chatterino diff --git a/src/providers/twitch/TwitchBadges.hpp b/src/providers/twitch/TwitchBadges.hpp index 62196f8d8..d9023855d 100644 --- a/src/providers/twitch/TwitchBadges.hpp +++ b/src/providers/twitch/TwitchBadges.hpp @@ -1,7 +1,10 @@ #pragma once #include +#include #include + +#include "common/UniqueAccess.hpp" #include "util/QStringHash.hpp" namespace chatterino { @@ -15,14 +18,15 @@ class Paths; class TwitchBadges { public: - TwitchBadges(); - - void initialize(Settings &settings, Paths &paths); - -private: void loadTwitchBadges(); - std::unordered_map badges; + boost::optional badge(const QString &set, + const QString &version) const; + +private: + UniqueAccess< + std::unordered_map>> + badgeSets_; // "bits": { "100": ... "500": ... }; } // namespace chatterino diff --git a/src/providers/twitch/TwitchChannel.cpp b/src/providers/twitch/TwitchChannel.cpp index 346ed1476..06ed13739 100644 --- a/src/providers/twitch/TwitchChannel.cpp +++ b/src/providers/twitch/TwitchChannel.cpp @@ -69,12 +69,14 @@ std::pair parseChatters(const QJsonObject &jsonRoot) } } // namespace -TwitchChannel::TwitchChannel(const QString &name, BttvEmotes &bttv, +TwitchChannel::TwitchChannel(const QString &name, + TwitchBadges &globalTwitchBadges, BttvEmotes &bttv, FfzEmotes &ffz) : Channel(name, Channel::Type::Twitch) , subscriptionUrl_("https://www.twitch.tv/subs/" + name) , channelUrl_("https://twitch.tv/" + name) , popoutPlayerUrl_("https://player.twitch.tv/?channel=" + name) + , globalTwitchBadges_(globalTwitchBadges) , globalBttv_(bttv) , globalFfz_(ffz) , bttvEmotes_(std::make_shared()) @@ -317,6 +319,11 @@ AccessGuard TwitchChannel::accessChatters() const return this->chatters_.accessConst(); } +const TwitchBadges &TwitchChannel::globalTwitchBadges() const +{ + return this->globalTwitchBadges_; +} + const BttvEmotes &TwitchChannel::globalBttv() const { return this->globalBttv_; diff --git a/src/providers/twitch/TwitchChannel.hpp b/src/providers/twitch/TwitchChannel.hpp index ea95c0df3..82ae58d40 100644 --- a/src/providers/twitch/TwitchChannel.hpp +++ b/src/providers/twitch/TwitchChannel.hpp @@ -23,6 +23,7 @@ struct Emote; using EmotePtr = std::shared_ptr; class EmoteMap; +class TwitchBadges; class FfzEmotes; class BttvEmotes; @@ -70,6 +71,7 @@ public: AccessGuard accessChatters() const; // Emotes + const TwitchBadges &globalTwitchBadges() const; const BttvEmotes &globalBttv() const; const FfzEmotes &globalFfz() const; boost::optional bttvEmote(const EmoteName &name) const; @@ -98,8 +100,9 @@ private: QString localizedName; }; - explicit TwitchChannel(const QString &channelName, BttvEmotes &globalBttv, - FfzEmotes &globalFfz); + explicit TwitchChannel(const QString &channelName, + TwitchBadges &globalTwitchBadges, + BttvEmotes &globalBttv, FfzEmotes &globalFfz); // Methods void refreshLiveStatus(); @@ -126,6 +129,7 @@ private: UniqueAccess chatters_; // maps 2 char prefix to set of names // Emotes + TwitchBadges &globalTwitchBadges_; BttvEmotes &globalBttv_; FfzEmotes &globalFfz_; Atomic> bttvEmotes_; diff --git a/src/providers/twitch/TwitchMessageBuilder.cpp b/src/providers/twitch/TwitchMessageBuilder.cpp index 97b41561a..26ea07dec 100644 --- a/src/providers/twitch/TwitchMessageBuilder.cpp +++ b/src/providers/twitch/TwitchMessageBuilder.cpp @@ -6,6 +6,7 @@ #include "controllers/ignores/IgnoreController.hpp" #include "debug/Log.hpp" #include "messages/Message.hpp" +#include "providers/twitch/TwitchBadges.hpp" #include "providers/twitch/TwitchChannel.hpp" #include "singletons/Emotes.hpp" #include "singletons/Resources.hpp" @@ -91,13 +92,6 @@ MessagePtr TwitchMessageBuilder::build() this->senderIsBroadcaster = true; } - //#ifdef XD - // if (this->originalMessage.length() > 100) { - // this->message->flags.has(MessageFlag::Collapsed); - // this->emplace(getApp()->resources->badgeCollapsed, - // MessageElementFlag::Collapsed); - // } - //#endif this->message().flags.has(MessageFlag::Collapsed); // PARSING @@ -203,11 +197,7 @@ void TwitchMessageBuilder::addWords( // split words for (auto &variant : getApp()->emotes->emojis.parse(word)) { - boost::apply_visitor(/*overloaded{[&](EmotePtr arg) { - this->addTextOrEmoji(arg); }, - [&](const QString &arg) { - this->addTextOrEmoji(arg); }}*/ - [&](auto &&arg) { this->addTextOrEmoji(arg); }, + boost::apply_visitor([&](auto &&arg) { this->addTextOrEmoji(arg); }, variant); } @@ -659,32 +649,15 @@ Outcome TwitchMessageBuilder::tryAppendEmote(const EmoteName &name) } // fourtf: this is ugly -// maybe put the individual badges into a map instead of this -// mess void TwitchMessageBuilder::appendTwitchBadges() { auto app = getApp(); auto iterator = this->tags.find("badges"); + if (iterator == this->tags.end()) return; - if (iterator == this->tags.end()) { - // No badges in this message - return; - } - - QStringList badges = iterator.value().toString().split(','); - - for (QString badge : badges) { - if (badge.isEmpty()) { - continue; - } - + for (QString badge : iterator.value().toString().split(',')) { if (badge.startsWith("bits/")) { - // if (!app->resources->dynamicBadgesLoaded) { - // // Do nothing - // continue; - // } - QString cheerAmount = badge.mid(5); QString tooltip = QString("Twitch cheer ") + cheerAmount; @@ -703,16 +676,12 @@ void TwitchMessageBuilder::appendTwitchBadges() } // Use default bit badge - // try { - // const auto &badge = - // app->resources->badgeSets.at("bits").versions.at(cheerAmount); - // this->emplace(badge.badgeImage1x, - // MessageElementFlag::BadgeVanity) - // ->setTooltip(tooltip); - //} catch (const std::out_of_range &) { - // Log("No default bit badge for version {} found", cheerAmount); - // continue; - //} + if (auto badge = this->twitchChannel->globalTwitchBadges().badge( + "bits", cheerAmount)) { + this->emplace(badge.get(), + MessageElementFlag::BadgeVanity) + ->setTooltip(tooltip); + } } else if (badge == "staff/1") { this->emplace( Image::fromPixmap(app->resources->twitch.staff), @@ -766,80 +735,30 @@ void TwitchMessageBuilder::appendTwitchBadges() } break; } } else if (badge.startsWith("subscriber/")) { - // if (channelResources.loaded == false) { - // // qDebug() << "Channel resources are not loaded, - // can't add the subscriber - // // badge"; - // continue; - // } + if (auto badgeEmote = this->twitchChannel->twitchBadge( + "subscriber", badge.mid(11))) { + this->emplace( + badgeEmote.get(), MessageElementFlag::BadgeSubscription) + ->setTooltip((*badgeEmote)->tooltip.string); + continue; + } - // auto badgeSetIt = channelResources.badgeSets.find("subscriber"); - // if (badgeSetIt == channelResources.badgeSets.end()) { - // // Fall back to default badge - // this->emplace(app->resources->badgeSubscriber, - // MessageElementFlag::BadgeSubscription) - // ->setTooltip("Twitch Subscriber"); - // continue; - //} - - // const auto &badgeSet = badgeSetIt->second; - - // std::string versionKey = badge.mid(11).toStdString(); - - // auto badgeVersionIt = badgeSet.versions.find(versionKey); - - // if (badgeVersionIt == badgeSet.versions.end()) { - // // Fall back to default badge - // this->emplace(app->resources->badgeSubscriber, - // MessageElementFlag::BadgeSubscription) - // ->setTooltip("Twitch Subscriber"); - // continue; - //} - - // auto &badgeVersion = badgeVersionIt->second; - - // this->emplace(badgeVersion.badgeImage1x, - // MessageElementFlag::BadgeSubscription) - // ->setTooltip("Twitch " + - // QString::fromStdString(badgeVersion.title)); + // use default subscriber badge if custom one not found + this->emplace( + Image::fromPixmap(app->resources->twitch.subscriber, 0.25), + MessageElementFlag::BadgeSubscription) + ->setTooltip("Twitch Subscriber"); } else { - // if (!app->resources->dynamicBadgesLoaded) { - // // Do nothing - // continue; - //} + auto splits = badge.split('/'); + if (splits.size() != 2) continue; - // QStringList parts = badge.split('/'); - - // if (parts.length() != 2) { - // qDebug() << "Bad number of parts: " << parts.length() << " in - // " << parts; continue; - //} - - // MessageElementFlags badgeType = - // MessageElementFlag::BadgeVanity; - - // std::string badgeSetKey = parts[0].toStdString(); - // std::string versionKey = parts[1].toStdString(); - - // try { - // auto &badgeSet = app->resources->badgeSets.at(badgeSetKey); - - // try { - // auto &badgeVersion = badgeSet.versions.at(versionKey); - - // this->emplace(badgeVersion.badgeImage1x, - // badgeType) - // ->setTooltip("Twitch " + - // QString::fromStdString(badgeVersion.title)); - // } catch (const std::exception &e) { - // qDebug() << "Exception caught:" << e.what() - // << "when trying to fetch badge version " << - // versionKey.c_str(); - // } - //} catch (const std::exception &e) { - // qDebug() << "No badge set with key" << badgeSetKey.c_str() - // << ". Exception: " << e.what(); - //} + if (auto badgeEmote = + this->twitchChannel->twitchBadge(splits[0], splits[1])) { + this->emplace(badgeEmote.get(), + MessageElementFlag::BadgeVanity) + ->setTooltip((*badgeEmote)->tooltip.string); + continue; + } } } } diff --git a/src/providers/twitch/TwitchServer.cpp b/src/providers/twitch/TwitchServer.cpp index 465fe3315..d1e03b63b 100644 --- a/src/providers/twitch/TwitchServer.cpp +++ b/src/providers/twitch/TwitchServer.cpp @@ -13,7 +13,6 @@ #include "util/PostToThread.hpp" #include - #include // using namespace Communi; @@ -41,6 +40,7 @@ void TwitchServer::initialize(Settings &settings, Paths &paths) getApp()->accounts->twitch.currentUserChanged.connect( [this]() { postToThread([this] { this->connect(); }); }); + this->twitchBadges.loadTwitchBadges(); this->bttv.loadEmotes(); this->ffz.loadEmotes(); } @@ -83,8 +83,8 @@ void TwitchServer::initializeConnection(IrcConnection *connection, bool isRead, std::shared_ptr TwitchServer::createChannel(const QString &channelName) { - auto channel = std::shared_ptr( - new TwitchChannel(channelName, this->bttv, this->ffz)); + auto channel = std::shared_ptr(new TwitchChannel( + channelName, this->twitchBadges, this->bttv, this->ffz)); channel->initialize(); channel->sendMessageSignal.connect( diff --git a/src/providers/twitch/TwitchServer.hpp b/src/providers/twitch/TwitchServer.hpp index e097cc365..60026a142 100644 --- a/src/providers/twitch/TwitchServer.hpp +++ b/src/providers/twitch/TwitchServer.hpp @@ -7,6 +7,7 @@ #include "providers/bttv/BttvEmotes.hpp" #include "providers/ffz/FfzEmotes.hpp" #include "providers/irc/AbstractIrcServer.hpp" +#include "providers/twitch/TwitchBadges.hpp" #include #include @@ -68,6 +69,7 @@ private: std::chrono::steady_clock::time_point lastErrorTimeAmount_; bool singleConnection_ = false; + TwitchBadges twitchBadges; BttvEmotes bttv; FfzEmotes ffz; diff --git a/src/widgets/splits/SplitHeader.cpp b/src/widgets/splits/SplitHeader.cpp index d99448221..0c713c996 100644 --- a/src/widgets/splits/SplitHeader.cpp +++ b/src/widgets/splits/SplitHeader.cpp @@ -92,10 +92,10 @@ auto formatTitle(const TwitchChannel::StreamStatus &s, Settings &settings) // description if (settings.showViewerCount) - title += " - " + QString::number(s.viewerCount) + " viewers"; + title += " - " + QString::number(s.viewerCount); if (settings.showTitle) title += " - " + s.title; if (settings.showGame) title += " - " + s.game; - if (settings.showUptime) title += " - uptime: " + s.uptime; + if (settings.showUptime) title += " - " + s.uptime; return title; } From af7b742a234efa0c34ca352ad0d56c001d5ec96b Mon Sep 17 00:00:00 2001 From: fourtf Date: Wed, 15 Aug 2018 22:46:20 +0200 Subject: [PATCH 12/14] changed .clang-format --- .clang-format | 3 + src/Application.cpp | 10 +- src/BrowserExtension.cpp | 42 +-- src/PrecompiledHeader.hpp | 326 ++++++++-------- src/RunGui.cpp | 138 +++---- src/common/Version.hpp | 6 +- .../highlights/HighlightBlacklistUser.hpp | 52 +-- .../highlights/HighlightPhrase.hpp | 64 ++-- src/controllers/ignores/IgnorePhrase.hpp | 50 +-- .../moderationactions/ModerationAction.hpp | 44 +-- src/messages/Image.cpp | 272 +++++++------- src/messages/Image.hpp | 42 +-- src/messages/MessageParseArgs.hpp | 1 - src/providers/bttv/BttvEmotes.cpp | 121 +++--- src/providers/emoji/Emojis.cpp | 133 ++++--- src/providers/ffz/FfzEmotes.cpp | 167 +++++---- src/providers/twitch/PubsubClient.cpp | 254 ++++++------- src/providers/twitch/PubsubClient.hpp | 53 +-- src/providers/twitch/PubsubHelpers.hpp | 5 +- src/providers/twitch/TwitchAccount.cpp | 46 +-- src/providers/twitch/TwitchChannel.cpp | 67 ++-- .../twitch/TwitchParseCheerEmotes.cpp | 354 +++++++++--------- src/providers/twitch/TwitchUser.hpp | 66 ++-- src/singletons/Fonts.cpp | 21 +- src/singletons/NativeMessaging.cpp | 8 +- src/singletons/Theme.cpp | 24 +- src/util/FormatTime.cpp | 10 +- src/util/InitUpdateButton.hpp | 2 +- src/util/RapidJsonSerializeQString.hpp | 58 +-- src/util/RapidjsonHelpers.cpp | 36 +- src/util/RapidjsonHelpers.hpp | 150 ++++---- src/util/StreamLink.cpp | 137 +++---- src/util/WindowsHelper.hpp | 4 +- src/widgets/AttachedWindow.cpp | 8 +- src/widgets/BaseWindow.cpp | 26 +- src/widgets/Notebook.cpp | 3 +- src/widgets/StreamView.cpp | 2 +- src/widgets/TooltipWidget.cpp | 2 +- src/widgets/dialogs/EmotePopup.cpp | 82 ++-- src/widgets/dialogs/LoginDialog.cpp | 94 ++--- src/widgets/helper/ChannelView.cpp | 98 ++--- .../settingspages/ExternalToolsPage.cpp | 18 +- src/widgets/settingspages/IgnoresPage.cpp | 5 +- src/widgets/settingspages/LookPage.cpp | 4 +- src/widgets/settingspages/ModerationPage.cpp | 2 +- src/widgets/splits/SplitHeader.cpp | 137 +++---- 46 files changed, 1636 insertions(+), 1611 deletions(-) diff --git a/.clang-format b/.clang-format index bd3f2c430..eeb9eb929 100644 --- a/.clang-format +++ b/.clang-format @@ -25,6 +25,9 @@ DerivePointerBinding: false FixNamespaceComments: true IndentCaseLabels: true IndentWidth: 4 +IndentWrappedFunctionNames: true +IndentPPDirectives: AfterHash +NamespaceIndentation: Inner PointerBindsToType: false SpacesBeforeTrailingComments: 2 Standard: Auto diff --git a/src/Application.cpp b/src/Application.cpp index b53940702..68ccc78f8 100644 --- a/src/Application.cpp +++ b/src/Application.cpp @@ -99,15 +99,15 @@ void Application::save() void Application::initNm() { #ifdef Q_OS_WIN -#ifdef QT_DEBUG -#ifdef C_DEBUG_NM +# ifdef QT_DEBUG +# ifdef C_DEBUG_NM this->nativeMessaging->registerHost(); this->nativeMessaging->openGuiMessageQueue(); -#endif -#else +# endif +# else this->nativeMessaging->registerHost(); this->nativeMessaging->openGuiMessageQueue(); -#endif +# endif #endif } diff --git a/src/BrowserExtension.cpp b/src/BrowserExtension.cpp index 5275e0648..f12d19b5e 100644 --- a/src/BrowserExtension.cpp +++ b/src/BrowserExtension.cpp @@ -9,31 +9,31 @@ #include #ifdef Q_OS_WIN -#include -#include -#include +# include +# include +# include #endif namespace chatterino { namespace { -void initFileMode() -{ + void initFileMode() + { #ifdef Q_OS_WIN - _setmode(_fileno(stdin), _O_BINARY); - _setmode(_fileno(stdout), _O_BINARY); + _setmode(_fileno(stdin), _O_BINARY); + _setmode(_fileno(stdout), _O_BINARY); #endif -} + } -void runLoop(NativeMessagingClient &client) -{ - while (true) { - char size_c[4]; - std::cin.read(size_c, 4); + void runLoop(NativeMessagingClient &client) + { + while (true) { + char size_c[4]; + std::cin.read(size_c, 4); - if (std::cin.eof()) break; + if (std::cin.eof()) break; - auto size = *reinterpret_cast(size_c); + auto size = *reinterpret_cast(size_c); #if 0 bool bigEndian = isBigEndian(); @@ -48,14 +48,14 @@ void runLoop(NativeMessagingClient &client) } #endif - std::unique_ptr buffer(new char[size + 1]); - std::cin.read(buffer.get(), size); - *(buffer.get() + size) = '\0'; + std::unique_ptr buffer(new char[size + 1]); + std::cin.read(buffer.get(), size); + *(buffer.get() + size) = '\0'; - client.sendMessage( - QByteArray::fromRawData(buffer.get(), static_cast(size))); + client.sendMessage(QByteArray::fromRawData( + buffer.get(), static_cast(size))); + } } -} } // namespace bool shouldRunBrowserExtensionHost(const QStringList &args) diff --git a/src/PrecompiledHeader.hpp b/src/PrecompiledHeader.hpp index 6eec78c8e..10dfcd418 100644 --- a/src/PrecompiledHeader.hpp +++ b/src/PrecompiledHeader.hpp @@ -1,168 +1,168 @@ #ifdef __cplusplus -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include -#ifndef UNUSED -#define UNUSED(x) (void)(x) -#endif +# ifndef UNUSED +# define UNUSED(x) (void)(x) +# endif -#ifndef ATTR_UNUSED -#ifdef Q_OS_WIN -#define ATTR_UNUSED -#else -#define ATTR_UNUSED __attribute__((unused)) -#endif -#endif +# ifndef ATTR_UNUSED +# ifdef Q_OS_WIN +# define ATTR_UNUSED +# else +# define ATTR_UNUSED __attribute__((unused)) +# endif +# endif #endif diff --git a/src/RunGui.cpp b/src/RunGui.cpp index 7ed61be87..e342ca7c1 100644 --- a/src/RunGui.cpp +++ b/src/RunGui.cpp @@ -12,7 +12,7 @@ #include "widgets/dialogs/LastRunCrashDialog.hpp" #ifdef C_USE_BREAKPAD -#include +# include #endif // void initQt(); @@ -23,80 +23,82 @@ namespace chatterino { namespace { -void installCustomPalette() -{ - // borrowed from - // https://stackoverflow.com/questions/15035767/is-the-qt-5-dark-fusion-theme-available-for-windows - auto dark = qApp->palette(); + void installCustomPalette() + { + // borrowed from + // https://stackoverflow.com/questions/15035767/is-the-qt-5-dark-fusion-theme-available-for-windows + auto dark = qApp->palette(); - dark.setColor(QPalette::Window, QColor(22, 22, 22)); - dark.setColor(QPalette::WindowText, Qt::white); - dark.setColor(QPalette::Text, Qt::white); - dark.setColor(QPalette::Disabled, QPalette::WindowText, - QColor(127, 127, 127)); - dark.setColor(QPalette::Base, QColor("#333")); - dark.setColor(QPalette::AlternateBase, QColor("#444")); - dark.setColor(QPalette::ToolTipBase, Qt::white); - dark.setColor(QPalette::ToolTipText, Qt::white); - dark.setColor(QPalette::Disabled, QPalette::Text, QColor(127, 127, 127)); - dark.setColor(QPalette::Dark, QColor(35, 35, 35)); - dark.setColor(QPalette::Shadow, QColor(20, 20, 20)); - dark.setColor(QPalette::Button, QColor(70, 70, 70)); - dark.setColor(QPalette::ButtonText, Qt::white); - dark.setColor(QPalette::Disabled, QPalette::ButtonText, - QColor(127, 127, 127)); - dark.setColor(QPalette::BrightText, Qt::red); - dark.setColor(QPalette::Link, QColor(42, 130, 218)); - dark.setColor(QPalette::Highlight, QColor(42, 130, 218)); - dark.setColor(QPalette::Disabled, QPalette::Highlight, QColor(80, 80, 80)); - dark.setColor(QPalette::HighlightedText, Qt::white); - dark.setColor(QPalette::Disabled, QPalette::HighlightedText, - QColor(127, 127, 127)); + dark.setColor(QPalette::Window, QColor(22, 22, 22)); + dark.setColor(QPalette::WindowText, Qt::white); + dark.setColor(QPalette::Text, Qt::white); + dark.setColor(QPalette::Disabled, QPalette::WindowText, + QColor(127, 127, 127)); + dark.setColor(QPalette::Base, QColor("#333")); + dark.setColor(QPalette::AlternateBase, QColor("#444")); + dark.setColor(QPalette::ToolTipBase, Qt::white); + dark.setColor(QPalette::ToolTipText, Qt::white); + dark.setColor(QPalette::Disabled, QPalette::Text, + QColor(127, 127, 127)); + dark.setColor(QPalette::Dark, QColor(35, 35, 35)); + dark.setColor(QPalette::Shadow, QColor(20, 20, 20)); + dark.setColor(QPalette::Button, QColor(70, 70, 70)); + dark.setColor(QPalette::ButtonText, Qt::white); + dark.setColor(QPalette::Disabled, QPalette::ButtonText, + QColor(127, 127, 127)); + dark.setColor(QPalette::BrightText, Qt::red); + dark.setColor(QPalette::Link, QColor(42, 130, 218)); + dark.setColor(QPalette::Highlight, QColor(42, 130, 218)); + dark.setColor(QPalette::Disabled, QPalette::Highlight, + QColor(80, 80, 80)); + dark.setColor(QPalette::HighlightedText, Qt::white); + dark.setColor(QPalette::Disabled, QPalette::HighlightedText, + QColor(127, 127, 127)); - qApp->setPalette(dark); -} - -void initQt() -{ - // set up the QApplication flags - QApplication::setAttribute(Qt::AA_Use96Dpi, true); -#ifdef Q_OS_WIN32 - QApplication::setAttribute(Qt::AA_DisableHighDpiScaling, true); -#endif - - QApplication::setStyle(QStyleFactory::create("Fusion")); - - installCustomPalette(); -} - -void showLastCrashDialog() -{ -#ifndef C_DISABLE_CRASH_DIALOG - LastRunCrashDialog dialog; - - switch (dialog.exec()) { - case QDialog::Accepted: { - }; break; - default: { - _exit(0); - } + qApp->setPalette(dark); } + + void initQt() + { + // set up the QApplication flags + QApplication::setAttribute(Qt::AA_Use96Dpi, true); +#ifdef Q_OS_WIN32 + QApplication::setAttribute(Qt::AA_DisableHighDpiScaling, true); #endif -} -void createRunningFile(const QString &path) -{ - QFile runningFile(path); + QApplication::setStyle(QStyleFactory::create("Fusion")); - runningFile.open(QIODevice::WriteOnly | QIODevice::Truncate); - runningFile.flush(); - runningFile.close(); -} + installCustomPalette(); + } -void removeRunningFile(const QString &path) -{ - QFile::remove(path); -} + void showLastCrashDialog() + { +#ifndef C_DISABLE_CRASH_DIALOG + LastRunCrashDialog dialog; + + switch (dialog.exec()) { + case QDialog::Accepted: { + }; break; + default: { + _exit(0); + } + } +#endif + } + + void createRunningFile(const QString &path) + { + QFile runningFile(path); + + runningFile.open(QIODevice::WriteOnly | QIODevice::Truncate); + runningFile.flush(); + runningFile.close(); + } + + void removeRunningFile(const QString &path) + { + QFile::remove(path); + } } // namespace void runGui(QApplication &a, Paths &paths, Settings &settings) diff --git a/src/common/Version.hpp b/src/common/Version.hpp index 2b1b51b39..4101f3a56 100644 --- a/src/common/Version.hpp +++ b/src/common/Version.hpp @@ -5,9 +5,9 @@ #define CHATTERINO_VERSION "2.0.4" #if defined(Q_OS_WIN) -#define CHATTERINO_OS "win" +# define CHATTERINO_OS "win" #elif defined(Q_OS_MACOS) -#define CHATTERINO_OS "macos" +# define CHATTERINO_OS "macos" #elif defined(Q_OS_LINUX) -#define CHATTERINO_OS "linux" +# define CHATTERINO_OS "linux" #endif diff --git a/src/controllers/highlights/HighlightBlacklistUser.hpp b/src/controllers/highlights/HighlightBlacklistUser.hpp index 4ce8683d0..b2e3e4a06 100644 --- a/src/controllers/highlights/HighlightBlacklistUser.hpp +++ b/src/controllers/highlights/HighlightBlacklistUser.hpp @@ -68,37 +68,39 @@ private: namespace pajlada { namespace Settings { -template <> -struct Serialize { - static rapidjson::Value get(const chatterino::HighlightBlacklistUser &value, - rapidjson::Document::AllocatorType &a) - { - rapidjson::Value ret(rapidjson::kObjectType); + template <> + struct Serialize { + static rapidjson::Value get( + const chatterino::HighlightBlacklistUser &value, + rapidjson::Document::AllocatorType &a) + { + rapidjson::Value ret(rapidjson::kObjectType); - AddMember(ret, "pattern", value.getPattern(), a); - AddMember(ret, "regex", value.isRegex(), a); + AddMember(ret, "pattern", value.getPattern(), a); + AddMember(ret, "regex", value.isRegex(), a); - return ret; - } -}; + return ret; + } + }; -template <> -struct Deserialize { - static chatterino::HighlightBlacklistUser get(const rapidjson::Value &value) - { - QString pattern; - bool isRegex = false; + template <> + struct Deserialize { + static chatterino::HighlightBlacklistUser get( + const rapidjson::Value &value) + { + QString pattern; + bool isRegex = false; + + if (!value.IsObject()) { + return chatterino::HighlightBlacklistUser(pattern, isRegex); + } + + chatterino::rj::getSafe(value, "pattern", pattern); + chatterino::rj::getSafe(value, "regex", isRegex); - if (!value.IsObject()) { return chatterino::HighlightBlacklistUser(pattern, isRegex); } - - chatterino::rj::getSafe(value, "pattern", pattern); - chatterino::rj::getSafe(value, "regex", isRegex); - - return chatterino::HighlightBlacklistUser(pattern, isRegex); - } -}; + }; } // namespace Settings } // namespace pajlada diff --git a/src/controllers/highlights/HighlightPhrase.hpp b/src/controllers/highlights/HighlightPhrase.hpp index 91abaadce..cfbee6588 100644 --- a/src/controllers/highlights/HighlightPhrase.hpp +++ b/src/controllers/highlights/HighlightPhrase.hpp @@ -72,43 +72,45 @@ private: namespace pajlada { namespace Settings { -template <> -struct Serialize { - static rapidjson::Value get(const chatterino::HighlightPhrase &value, - rapidjson::Document::AllocatorType &a) - { - rapidjson::Value ret(rapidjson::kObjectType); + template <> + struct Serialize { + static rapidjson::Value get(const chatterino::HighlightPhrase &value, + rapidjson::Document::AllocatorType &a) + { + rapidjson::Value ret(rapidjson::kObjectType); - AddMember(ret, "pattern", value.getPattern(), a); - AddMember(ret, "alert", value.getAlert(), a); - AddMember(ret, "sound", value.getSound(), a); - AddMember(ret, "regex", value.isRegex(), 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; - } -}; - -template <> -struct Deserialize { - static chatterino::HighlightPhrase get(const rapidjson::Value &value) - { - if (!value.IsObject()) { - return chatterino::HighlightPhrase(QString(), true, false, false); + return ret; } + }; - QString _pattern; - bool _alert = true; - bool _sound = false; - bool _isRegex = false; + template <> + struct Deserialize { + static chatterino::HighlightPhrase get(const rapidjson::Value &value) + { + if (!value.IsObject()) { + return chatterino::HighlightPhrase(QString(), true, false, + false); + } - chatterino::rj::getSafe(value, "pattern", _pattern); - chatterino::rj::getSafe(value, "alert", _alert); - chatterino::rj::getSafe(value, "sound", _sound); - chatterino::rj::getSafe(value, "regex", _isRegex); + QString _pattern; + bool _alert = true; + bool _sound = false; + bool _isRegex = false; - return chatterino::HighlightPhrase(_pattern, _alert, _sound, _isRegex); - } -}; + chatterino::rj::getSafe(value, "pattern", _pattern); + chatterino::rj::getSafe(value, "alert", _alert); + chatterino::rj::getSafe(value, "sound", _sound); + chatterino::rj::getSafe(value, "regex", _isRegex); + + return chatterino::HighlightPhrase(_pattern, _alert, _sound, + _isRegex); + } + }; } // namespace Settings } // namespace pajlada diff --git a/src/controllers/ignores/IgnorePhrase.hpp b/src/controllers/ignores/IgnorePhrase.hpp index 81eb83a87..16601708a 100644 --- a/src/controllers/ignores/IgnorePhrase.hpp +++ b/src/controllers/ignores/IgnorePhrase.hpp @@ -59,37 +59,37 @@ private: namespace pajlada { namespace Settings { -template <> -struct Serialize { - static rapidjson::Value get(const chatterino::IgnorePhrase &value, - rapidjson::Document::AllocatorType &a) - { - rapidjson::Value ret(rapidjson::kObjectType); + template <> + struct Serialize { + static rapidjson::Value get(const chatterino::IgnorePhrase &value, + rapidjson::Document::AllocatorType &a) + { + rapidjson::Value ret(rapidjson::kObjectType); - AddMember(ret, "pattern", value.getPattern(), a); - AddMember(ret, "regex", value.isRegex(), a); + AddMember(ret, "pattern", value.getPattern(), a); + AddMember(ret, "regex", value.isRegex(), a); - return ret; - } -}; - -template <> -struct Deserialize { - static chatterino::IgnorePhrase get(const rapidjson::Value &value) - { - if (!value.IsObject()) { - return chatterino::IgnorePhrase(QString(), false); + return ret; } + }; - QString _pattern; - bool _isRegex = false; + template <> + struct Deserialize { + static chatterino::IgnorePhrase get(const rapidjson::Value &value) + { + if (!value.IsObject()) { + return chatterino::IgnorePhrase(QString(), false); + } - chatterino::rj::getSafe(value, "pattern", _pattern); - chatterino::rj::getSafe(value, "regex", _isRegex); + QString _pattern; + bool _isRegex = false; - return chatterino::IgnorePhrase(_pattern, _isRegex); - } -}; + chatterino::rj::getSafe(value, "pattern", _pattern); + chatterino::rj::getSafe(value, "regex", _isRegex); + + return chatterino::IgnorePhrase(_pattern, _isRegex); + } + }; } // namespace Settings } // namespace pajlada diff --git a/src/controllers/moderationactions/ModerationAction.hpp b/src/controllers/moderationactions/ModerationAction.hpp index 6a36157df..8dbdba93f 100644 --- a/src/controllers/moderationactions/ModerationAction.hpp +++ b/src/controllers/moderationactions/ModerationAction.hpp @@ -36,34 +36,34 @@ private: namespace pajlada { namespace Settings { -template <> -struct Serialize { - static rapidjson::Value get(const chatterino::ModerationAction &value, - rapidjson::Document::AllocatorType &a) - { - rapidjson::Value ret(rapidjson::kObjectType); + template <> + struct Serialize { + static rapidjson::Value get(const chatterino::ModerationAction &value, + rapidjson::Document::AllocatorType &a) + { + rapidjson::Value ret(rapidjson::kObjectType); - AddMember(ret, "pattern", value.getAction(), a); + AddMember(ret, "pattern", value.getAction(), a); - return ret; - } -}; - -template <> -struct Deserialize { - static chatterino::ModerationAction get(const rapidjson::Value &value) - { - if (!value.IsObject()) { - return chatterino::ModerationAction(QString()); + return ret; } + }; - QString pattern; + template <> + struct Deserialize { + static chatterino::ModerationAction get(const rapidjson::Value &value) + { + if (!value.IsObject()) { + return chatterino::ModerationAction(QString()); + } - chatterino::rj::getSafe(value, "pattern", pattern); + QString pattern; - return chatterino::ModerationAction(pattern); - } -}; + chatterino::rj::getSafe(value, "pattern", pattern); + + return chatterino::ModerationAction(pattern); + } + }; } // namespace Settings } // namespace pajlada diff --git a/src/messages/Image.cpp b/src/messages/Image.cpp index b48234536..e6dcfbc8b 100644 --- a/src/messages/Image.cpp +++ b/src/messages/Image.cpp @@ -22,157 +22,163 @@ namespace chatterino { namespace { -// Frames -Frames::Frames() -{ - DebugCount::increase("images"); -} - -Frames::Frames(const QVector> &frames) - : items_(frames) -{ - assertInGuiThread(); - DebugCount::increase("images"); - - if (this->animated()) { - DebugCount::increase("animated images"); - - this->gifTimerConnection_ = getApp()->emotes->gifTimer.signal.connect( - [this] { this->advance(); }); - } -} - -Frames::~Frames() -{ - assertInGuiThread(); - DebugCount::decrease("images"); - - if (this->animated()) { - DebugCount::decrease("animated images"); + // Frames + Frames::Frames() + { + DebugCount::increase("images"); } - this->gifTimerConnection_.disconnect(); -} + Frames::Frames(const QVector> &frames) + : items_(frames) + { + assertInGuiThread(); + DebugCount::increase("images"); -void Frames::advance() -{ - this->durationOffset_ += GIF_FRAME_LENGTH; + if (this->animated()) { + DebugCount::increase("animated images"); - while (true) { - this->index_ %= this->items_.size(); - - if (this->index_ >= this->items_.size()) { - this->index_ = this->index_; - } - - if (this->durationOffset_ > this->items_[this->index_].duration) { - this->durationOffset_ -= this->items_[this->index_].duration; - this->index_ = (this->index_ + 1) % this->items_.size(); - } else { - break; + this->gifTimerConnection_ = + getApp()->emotes->gifTimer.signal.connect( + [this] { this->advance(); }); } } -} -bool Frames::animated() const -{ - return this->items_.size() > 1; -} + Frames::~Frames() + { + assertInGuiThread(); + DebugCount::decrease("images"); -boost::optional Frames::current() const -{ - if (this->items_.size() == 0) return boost::none; - return this->items_[this->index_].image; -} + if (this->animated()) { + DebugCount::decrease("animated images"); + } -boost::optional Frames::first() const -{ - if (this->items_.size() == 0) return boost::none; - return this->items_.front().image; -} + this->gifTimerConnection_.disconnect(); + } -// functions -QVector> readFrames(QImageReader &reader, const Url &url) -{ - QVector> frames; + void Frames::advance() + { + this->durationOffset_ += GIF_FRAME_LENGTH; + + while (true) { + this->index_ %= this->items_.size(); + + if (this->index_ >= this->items_.size()) { + this->index_ = this->index_; + } + + if (this->durationOffset_ > this->items_[this->index_].duration) { + this->durationOffset_ -= this->items_[this->index_].duration; + this->index_ = (this->index_ + 1) % this->items_.size(); + } else { + break; + } + } + } + + bool Frames::animated() const + { + return this->items_.size() > 1; + } + + boost::optional Frames::current() const + { + if (this->items_.size() == 0) return boost::none; + return this->items_[this->index_].image; + } + + boost::optional Frames::first() const + { + if (this->items_.size() == 0) return boost::none; + return this->items_.front().image; + } + + // functions + QVector> readFrames(QImageReader &reader, const Url &url) + { + QVector> frames; + + if (reader.imageCount() == 0) { + log("Error while reading image {}: '{}'", url.string, + reader.errorString()); + return frames; + } + + QImage image; + for (int index = 0; index < reader.imageCount(); ++index) { + if (reader.read(&image)) { + QPixmap::fromImage(image); + + int duration = std::max(20, reader.nextImageDelay()); + frames.push_back(Frame{image, duration}); + } + } + + if (frames.size() == 0) { + log("Error while reading image {}: '{}'", url.string, + reader.errorString()); + } - if (reader.imageCount() == 0) { - log("Error while reading image {}: '{}'", url.string, - reader.errorString()); return frames; } - QImage image; - for (int index = 0; index < reader.imageCount(); ++index) { - if (reader.read(&image)) { - QPixmap::fromImage(image); - - int duration = std::max(20, reader.nextImageDelay()); - frames.push_back(Frame{image, duration}); - } - } - - if (frames.size() == 0) { - log("Error while reading image {}: '{}'", url.string, - reader.errorString()); - } - - return frames; -} - -// parsed -template -void assignDelayed( - std::queue>>> &queued, - std::mutex &mutex, std::atomic_bool &loadedEventQueued) -{ - std::lock_guard lock(mutex); - int i = 0; - - while (!queued.empty()) { - queued.front().first(queued.front().second); - queued.pop(); - - if (++i > 50) { - QTimer::singleShot( - 3, [&] { assignDelayed(queued, mutex, loadedEventQueued); }); - return; - } - } - - getApp()->windows->forceLayoutChannelViews(); - loadedEventQueued = false; -} - -template -auto makeConvertCallback(const QVector> &parsed, Assign assign) -{ - return [parsed, assign] { - // convert to pixmap - auto frames = QVector>(); - std::transform(parsed.begin(), parsed.end(), std::back_inserter(frames), - [](auto &frame) { - return Frame{ - QPixmap::fromImage(frame.image), frame.duration}; - }); - - // put into stack - static std::queue>>> queued; - static std::mutex mutex; - + // parsed + template + void assignDelayed( + std::queue>>> &queued, + std::mutex &mutex, std::atomic_bool &loadedEventQueued) + { std::lock_guard lock(mutex); - queued.emplace(assign, frames); + int i = 0; - static std::atomic_bool loadedEventQueued{false}; + while (!queued.empty()) { + queued.front().first(queued.front().second); + queued.pop(); - if (!loadedEventQueued) { - loadedEventQueued = true; - - QTimer::singleShot( - 100, [=] { assignDelayed(queued, mutex, loadedEventQueued); }); + if (++i > 50) { + QTimer::singleShot(3, [&] { + assignDelayed(queued, mutex, loadedEventQueued); + }); + return; + } } - }; -} + + getApp()->windows->forceLayoutChannelViews(); + loadedEventQueued = false; + } + + template + auto makeConvertCallback(const QVector> &parsed, + Assign assign) + { + return [parsed, assign] { + // convert to pixmap + auto frames = QVector>(); + std::transform(parsed.begin(), parsed.end(), + std::back_inserter(frames), [](auto &frame) { + return Frame{ + QPixmap::fromImage(frame.image), + frame.duration}; + }); + + // put into stack + static std::queue>>> + queued; + static std::mutex mutex; + + std::lock_guard lock(mutex); + queued.emplace(assign, frames); + + static std::atomic_bool loadedEventQueued{false}; + + if (!loadedEventQueued) { + loadedEventQueued = true; + + QTimer::singleShot(100, [=] { + assignDelayed(queued, mutex, loadedEventQueued); + }); + } + }; + } } // namespace // IMAGE2 diff --git a/src/messages/Image.hpp b/src/messages/Image.hpp index 68b96392b..678af25ce 100644 --- a/src/messages/Image.hpp +++ b/src/messages/Image.hpp @@ -17,29 +17,29 @@ namespace chatterino { namespace { -template -struct Frame { - Image image; - int duration; -}; -class Frames : boost::noncopyable -{ -public: - Frames(); - Frames(const QVector> &frames); - ~Frames(); + template + struct Frame { + Image image; + int duration; + }; + class Frames : boost::noncopyable + { + public: + Frames(); + Frames(const QVector> &frames); + ~Frames(); - bool animated() const; - void advance(); - boost::optional current() const; - boost::optional first() const; + bool animated() const; + void advance(); + boost::optional current() const; + boost::optional first() const; -private: - QVector> items_; - int index_{0}; - int durationOffset_{0}; - pajlada::Signals::Connection gifTimerConnection_; -}; + private: + QVector> items_; + int index_{0}; + int durationOffset_{0}; + pajlada::Signals::Connection gifTimerConnection_; + }; } // namespace class Image; diff --git a/src/messages/MessageParseArgs.hpp b/src/messages/MessageParseArgs.hpp index 519262dc1..471d1d648 100644 --- a/src/messages/MessageParseArgs.hpp +++ b/src/messages/MessageParseArgs.hpp @@ -2,5 +2,4 @@ namespace chatterino { - } // namespace chatterino diff --git a/src/providers/bttv/BttvEmotes.cpp b/src/providers/bttv/BttvEmotes.cpp index cf32bd414..2efe00d64 100644 --- a/src/providers/bttv/BttvEmotes.cpp +++ b/src/providers/bttv/BttvEmotes.cpp @@ -13,73 +13,76 @@ namespace chatterino { namespace { -Url getEmoteLink(QString urlTemplate, const EmoteId &id, - const QString &emoteScale) -{ - urlTemplate.detach(); + Url getEmoteLink(QString urlTemplate, const EmoteId &id, + const QString &emoteScale) + { + urlTemplate.detach(); - return {urlTemplate.replace("{{id}}", id.string) - .replace("{{image}}", emoteScale)}; -} -std::pair parseGlobalEmotes(const QJsonObject &jsonRoot, - const EmoteMap ¤tEmotes) -{ - auto emotes = EmoteMap(); - auto jsonEmotes = jsonRoot.value("emotes").toArray(); - auto urlTemplate = qS("https:") + jsonRoot.value("urlTemplate").toString(); - - for (auto jsonEmote : jsonEmotes) { - auto id = EmoteId{jsonEmote.toObject().value("id").toString()}; - auto name = EmoteName{jsonEmote.toObject().value("code").toString()}; - - auto emote = Emote( - {name, - ImageSet{ - Image::fromUrl(getEmoteLink(urlTemplate, id, "1x"), 1), - Image::fromUrl(getEmoteLink(urlTemplate, id, "2x"), 0.5), - Image::fromUrl(getEmoteLink(urlTemplate, id, "3x"), 0.25)}, - Tooltip{name.string + "
Global Bttv Emote"}, - Url{"https://manage.betterttv.net/emotes/" + id.string}}); - - emotes[name] = cachedOrMakeEmotePtr(std::move(emote), currentEmotes); + return {urlTemplate.replace("{{id}}", id.string) + .replace("{{image}}", emoteScale)}; } + std::pair parseGlobalEmotes( + const QJsonObject &jsonRoot, const EmoteMap ¤tEmotes) + { + auto emotes = EmoteMap(); + auto jsonEmotes = jsonRoot.value("emotes").toArray(); + auto urlTemplate = + qS("https:") + jsonRoot.value("urlTemplate").toString(); - return {Success, std::move(emotes)}; -} -EmotePtr cachedOrMake(Emote &&emote, const EmoteId &id) -{ - static std::unordered_map> cache; - static std::mutex mutex; + for (auto jsonEmote : jsonEmotes) { + auto id = EmoteId{jsonEmote.toObject().value("id").toString()}; + auto name = + EmoteName{jsonEmote.toObject().value("code").toString()}; - return cachedOrMakeEmotePtr(std::move(emote), cache, mutex, id); -} -std::pair parseChannelEmotes(const QJsonObject &jsonRoot) -{ - auto emotes = EmoteMap(); - auto jsonEmotes = jsonRoot.value("emotes").toArray(); - auto urlTemplate = "https:" + jsonRoot.value("urlTemplate").toString(); + auto emote = Emote( + {name, + ImageSet{ + Image::fromUrl(getEmoteLink(urlTemplate, id, "1x"), 1), + Image::fromUrl(getEmoteLink(urlTemplate, id, "2x"), 0.5), + Image::fromUrl(getEmoteLink(urlTemplate, id, "3x"), 0.25)}, + Tooltip{name.string + "
Global Bttv Emote"}, + Url{"https://manage.betterttv.net/emotes/" + id.string}}); - for (auto jsonEmote_ : jsonEmotes) { - auto jsonEmote = jsonEmote_.toObject(); + emotes[name] = + cachedOrMakeEmotePtr(std::move(emote), currentEmotes); + } - auto id = EmoteId{jsonEmote.value("id").toString()}; - auto name = EmoteName{jsonEmote.value("code").toString()}; - // emoteObject.value("imageType").toString(); - - auto emote = Emote( - {name, - ImageSet{ - Image::fromUrl(getEmoteLink(urlTemplate, id, "1x"), 1), - Image::fromUrl(getEmoteLink(urlTemplate, id, "2x"), 0.5), - Image::fromUrl(getEmoteLink(urlTemplate, id, "3x"), 0.25)}, - Tooltip{name.string + "
Channel Bttv Emote"}, - Url{"https://manage.betterttv.net/emotes/" + id.string}}); - - emotes[name] = cachedOrMake(std::move(emote), id); + return {Success, std::move(emotes)}; } + EmotePtr cachedOrMake(Emote &&emote, const EmoteId &id) + { + static std::unordered_map> cache; + static std::mutex mutex; - return {Success, std::move(emotes)}; -} + return cachedOrMakeEmotePtr(std::move(emote), cache, mutex, id); + } + std::pair parseChannelEmotes(const QJsonObject &jsonRoot) + { + auto emotes = EmoteMap(); + auto jsonEmotes = jsonRoot.value("emotes").toArray(); + auto urlTemplate = "https:" + jsonRoot.value("urlTemplate").toString(); + + for (auto jsonEmote_ : jsonEmotes) { + auto jsonEmote = jsonEmote_.toObject(); + + auto id = EmoteId{jsonEmote.value("id").toString()}; + auto name = EmoteName{jsonEmote.value("code").toString()}; + // emoteObject.value("imageType").toString(); + + auto emote = Emote( + {name, + ImageSet{ + Image::fromUrl(getEmoteLink(urlTemplate, id, "1x"), 1), + Image::fromUrl(getEmoteLink(urlTemplate, id, "2x"), 0.5), + Image::fromUrl(getEmoteLink(urlTemplate, id, "3x"), 0.25)}, + Tooltip{name.string + "
Channel Bttv Emote"}, + Url{"https://manage.betterttv.net/emotes/" + id.string}}); + + emotes[name] = cachedOrMake(std::move(emote), id); + } + + return {Success, std::move(emotes)}; + } } // namespace // diff --git a/src/providers/emoji/Emojis.cpp b/src/providers/emoji/Emojis.cpp index 5140d2fe1..809b7c3d5 100644 --- a/src/providers/emoji/Emojis.cpp +++ b/src/providers/emoji/Emojis.cpp @@ -13,82 +13,81 @@ #include namespace chatterino { - namespace { + void parseEmoji(const std::shared_ptr &emojiData, + const rapidjson::Value &unparsedEmoji, + QString shortCode = QString()) + { + static uint unicodeBytes[4]; -void parseEmoji(const std::shared_ptr &emojiData, - const rapidjson::Value &unparsedEmoji, - QString shortCode = QString()) -{ - static uint unicodeBytes[4]; + struct { + bool apple; + bool google; + bool twitter; + bool emojione; + bool facebook; + bool messenger; + } capabilities; - struct { - bool apple; - bool google; - bool twitter; - bool emojione; - bool facebook; - bool messenger; - } capabilities; - - if (!shortCode.isEmpty()) { - emojiData->shortCodes.push_back(shortCode); - } else { - const auto &shortCodes = unparsedEmoji["short_names"]; - for (const auto &shortCode : shortCodes.GetArray()) { - emojiData->shortCodes.emplace_back(shortCode.GetString()); + if (!shortCode.isEmpty()) { + emojiData->shortCodes.push_back(shortCode); + } else { + const auto &shortCodes = unparsedEmoji["short_names"]; + for (const auto &shortCode : shortCodes.GetArray()) { + emojiData->shortCodes.emplace_back(shortCode.GetString()); + } } - } - rj::getSafe(unparsedEmoji, "non_qualified", emojiData->nonQualifiedCode); - rj::getSafe(unparsedEmoji, "unified", emojiData->unifiedCode); + rj::getSafe(unparsedEmoji, "non_qualified", + emojiData->nonQualifiedCode); + rj::getSafe(unparsedEmoji, "unified", emojiData->unifiedCode); - rj::getSafe(unparsedEmoji, "has_img_apple", capabilities.apple); - rj::getSafe(unparsedEmoji, "has_img_google", capabilities.google); - rj::getSafe(unparsedEmoji, "has_img_twitter", capabilities.twitter); - rj::getSafe(unparsedEmoji, "has_img_emojione", capabilities.emojione); - rj::getSafe(unparsedEmoji, "has_img_facebook", capabilities.facebook); - rj::getSafe(unparsedEmoji, "has_img_messenger", capabilities.messenger); + rj::getSafe(unparsedEmoji, "has_img_apple", capabilities.apple); + rj::getSafe(unparsedEmoji, "has_img_google", capabilities.google); + rj::getSafe(unparsedEmoji, "has_img_twitter", capabilities.twitter); + rj::getSafe(unparsedEmoji, "has_img_emojione", capabilities.emojione); + rj::getSafe(unparsedEmoji, "has_img_facebook", capabilities.facebook); + rj::getSafe(unparsedEmoji, "has_img_messenger", capabilities.messenger); - if (capabilities.apple) { - emojiData->capabilities.insert("Apple"); - } - if (capabilities.google) { - emojiData->capabilities.insert("Google"); - } - if (capabilities.twitter) { - emojiData->capabilities.insert("Twitter"); - } - if (capabilities.emojione) { - emojiData->capabilities.insert("EmojiOne 3"); - } - if (capabilities.facebook) { - emojiData->capabilities.insert("Facebook"); - } - if (capabilities.messenger) { - emojiData->capabilities.insert("Messenger"); - } + if (capabilities.apple) { + emojiData->capabilities.insert("Apple"); + } + if (capabilities.google) { + emojiData->capabilities.insert("Google"); + } + if (capabilities.twitter) { + emojiData->capabilities.insert("Twitter"); + } + if (capabilities.emojione) { + emojiData->capabilities.insert("EmojiOne 3"); + } + if (capabilities.facebook) { + emojiData->capabilities.insert("Facebook"); + } + if (capabilities.messenger) { + emojiData->capabilities.insert("Messenger"); + } - QStringList unicodeCharacters; - if (!emojiData->nonQualifiedCode.isEmpty()) { - unicodeCharacters = emojiData->nonQualifiedCode.toLower().split('-'); - } else { - unicodeCharacters = emojiData->unifiedCode.toLower().split('-'); + QStringList unicodeCharacters; + if (!emojiData->nonQualifiedCode.isEmpty()) { + unicodeCharacters = + emojiData->nonQualifiedCode.toLower().split('-'); + } else { + unicodeCharacters = emojiData->unifiedCode.toLower().split('-'); + } + if (unicodeCharacters.length() < 1) { + return; + } + + int numUnicodeBytes = 0; + + for (const QString &unicodeCharacter : unicodeCharacters) { + unicodeBytes[numUnicodeBytes++] = + QString(unicodeCharacter).toUInt(nullptr, 16); + } + + emojiData->value = QString::fromUcs4(unicodeBytes, numUnicodeBytes); } - if (unicodeCharacters.length() < 1) { - return; - } - - int numUnicodeBytes = 0; - - for (const QString &unicodeCharacter : unicodeCharacters) { - unicodeBytes[numUnicodeBytes++] = - QString(unicodeCharacter).toUInt(nullptr, 16); - } - - emojiData->value = QString::fromUcs4(unicodeBytes, numUnicodeBytes); -} - } // namespace void Emojis::load() diff --git a/src/providers/ffz/FfzEmotes.cpp b/src/providers/ffz/FfzEmotes.cpp index f8be4baa0..eb6912ff7 100644 --- a/src/providers/ffz/FfzEmotes.cpp +++ b/src/providers/ffz/FfzEmotes.cpp @@ -10,99 +10,100 @@ namespace chatterino { namespace { -Url getEmoteLink(const QJsonObject &urls, const QString &emoteScale) -{ - auto emote = urls.value(emoteScale); - if (emote.isUndefined()) { - return {""}; - } - - assert(emote.isString()); - - return {"https:" + emote.toString()}; -} -void fillInEmoteData(const QJsonObject &urls, const EmoteName &name, - const QString &tooltip, Emote &emoteData) -{ - auto url1x = getEmoteLink(urls, "1"); - auto url2x = getEmoteLink(urls, "2"); - auto url3x = getEmoteLink(urls, "4"); - - //, code, tooltip - emoteData.name = name; - emoteData.images = - ImageSet{Image::fromUrl(url1x, 1), Image::fromUrl(url2x, 0.5), - Image::fromUrl(url3x, 0.25)}; - emoteData.tooltip = {tooltip}; -} -EmotePtr cachedOrMake(Emote &&emote, const EmoteId &id) -{ - static std::unordered_map> cache; - static std::mutex mutex; - - return cachedOrMakeEmotePtr(std::move(emote), cache, mutex, id); -} -std::pair parseGlobalEmotes(const QJsonObject &jsonRoot, - const EmoteMap ¤tEmotes) -{ - auto jsonSets = jsonRoot.value("sets").toObject(); - auto emotes = EmoteMap(); - - for (auto jsonSet : jsonSets) { - auto jsonEmotes = jsonSet.toObject().value("emoticons").toArray(); - - for (auto jsonEmoteValue : jsonEmotes) { - auto jsonEmote = jsonEmoteValue.toObject(); - - auto name = EmoteName{jsonEmote.value("name").toString()}; - auto id = EmoteId{jsonEmote.value("id").toString()}; - auto urls = jsonEmote.value("urls").toObject(); - - auto emote = Emote(); - fillInEmoteData(urls, name, name.string + "
Global FFZ Emote", - emote); - emote.homePage = - Url{QString("https://www.frankerfacez.com/emoticon/%1-%2") - .arg(id.string) - .arg(name.string)}; - - emotes[name] = - cachedOrMakeEmotePtr(std::move(emote), currentEmotes); + Url getEmoteLink(const QJsonObject &urls, const QString &emoteScale) + { + auto emote = urls.value(emoteScale); + if (emote.isUndefined()) { + return {""}; } + + assert(emote.isString()); + + return {"https:" + emote.toString()}; } + void fillInEmoteData(const QJsonObject &urls, const EmoteName &name, + const QString &tooltip, Emote &emoteData) + { + auto url1x = getEmoteLink(urls, "1"); + auto url2x = getEmoteLink(urls, "2"); + auto url3x = getEmoteLink(urls, "4"); - return {Success, std::move(emotes)}; -} -std::pair parseChannelEmotes(const QJsonObject &jsonRoot) -{ - auto jsonSets = jsonRoot.value("sets").toObject(); - auto emotes = EmoteMap(); + //, code, tooltip + emoteData.name = name; + emoteData.images = + ImageSet{Image::fromUrl(url1x, 1), Image::fromUrl(url2x, 0.5), + Image::fromUrl(url3x, 0.25)}; + emoteData.tooltip = {tooltip}; + } + EmotePtr cachedOrMake(Emote &&emote, const EmoteId &id) + { + static std::unordered_map> cache; + static std::mutex mutex; - for (auto jsonSet : jsonSets) { - auto jsonEmotes = jsonSet.toObject().value("emoticons").toArray(); + return cachedOrMakeEmotePtr(std::move(emote), cache, mutex, id); + } + std::pair parseGlobalEmotes( + const QJsonObject &jsonRoot, const EmoteMap ¤tEmotes) + { + auto jsonSets = jsonRoot.value("sets").toObject(); + auto emotes = EmoteMap(); - for (auto _jsonEmote : jsonEmotes) { - auto jsonEmote = _jsonEmote.toObject(); + for (auto jsonSet : jsonSets) { + auto jsonEmotes = jsonSet.toObject().value("emoticons").toArray(); - // margins - auto id = EmoteId{QString::number(jsonEmote.value("id").toInt())}; - auto name = EmoteName{jsonEmote.value("name").toString()}; - auto urls = jsonEmote.value("urls").toObject(); + for (auto jsonEmoteValue : jsonEmotes) { + auto jsonEmote = jsonEmoteValue.toObject(); - Emote emote; - fillInEmoteData(urls, name, name.string + "
Channel FFZ Emote", - emote); - emote.homePage = - Url{QString("https://www.frankerfacez.com/emoticon/%1-%2") - .arg(id.string) - .arg(name.string)}; + auto name = EmoteName{jsonEmote.value("name").toString()}; + auto id = EmoteId{jsonEmote.value("id").toString()}; + auto urls = jsonEmote.value("urls").toObject(); - emotes[name] = cachedOrMake(std::move(emote), id); + auto emote = Emote(); + fillInEmoteData(urls, name, + name.string + "
Global FFZ Emote", emote); + emote.homePage = + Url{QString("https://www.frankerfacez.com/emoticon/%1-%2") + .arg(id.string) + .arg(name.string)}; + + emotes[name] = + cachedOrMakeEmotePtr(std::move(emote), currentEmotes); + } } - } - return {Success, std::move(emotes)}; -} + return {Success, std::move(emotes)}; + } + std::pair parseChannelEmotes(const QJsonObject &jsonRoot) + { + auto jsonSets = jsonRoot.value("sets").toObject(); + auto emotes = EmoteMap(); + + for (auto jsonSet : jsonSets) { + auto jsonEmotes = jsonSet.toObject().value("emoticons").toArray(); + + for (auto _jsonEmote : jsonEmotes) { + auto jsonEmote = _jsonEmote.toObject(); + + // margins + auto id = + EmoteId{QString::number(jsonEmote.value("id").toInt())}; + auto name = EmoteName{jsonEmote.value("name").toString()}; + auto urls = jsonEmote.value("urls").toObject(); + + Emote emote; + fillInEmoteData(urls, name, + name.string + "
Channel FFZ Emote", emote); + emote.homePage = + Url{QString("https://www.frankerfacez.com/emoticon/%1-%2") + .arg(id.string) + .arg(name.string)}; + + emotes[name] = cachedOrMake(std::move(emote), id); + } + } + + return {Success, std::move(emotes)}; + } } // namespace FfzEmotes::FfzEmotes() diff --git a/src/providers/twitch/PubsubClient.cpp b/src/providers/twitch/PubsubClient.cpp index 7f591aebc..77b6ba1d4 100644 --- a/src/providers/twitch/PubsubClient.cpp +++ b/src/providers/twitch/PubsubClient.cpp @@ -24,157 +24,159 @@ static std::map sentMessages; namespace detail { -PubSubClient::PubSubClient(WebsocketClient &websocketClient, - WebsocketHandle handle) - : websocketClient_(websocketClient) - , handle_(handle) -{ -} - -void PubSubClient::start() -{ - assert(!this->started_); - - this->started_ = true; - - this->ping(); -} - -void PubSubClient::stop() -{ - assert(this->started_); - - this->started_ = false; -} - -bool PubSubClient::listen(rapidjson::Document &message) -{ - int numRequestedListens = message["data"]["topics"].Size(); - - if (this->numListens_ + numRequestedListens > MAX_PUBSUB_LISTENS) { - // This PubSubClient is already at its peak listens - return false; + PubSubClient::PubSubClient(WebsocketClient &websocketClient, + WebsocketHandle handle) + : websocketClient_(websocketClient) + , handle_(handle) + { } - this->numListens_ += numRequestedListens; + void PubSubClient::start() + { + assert(!this->started_); - for (const auto &topic : message["data"]["topics"].GetArray()) { - this->listeners_.emplace_back( - Listener{topic.GetString(), false, false, false}); + this->started_ = true; + + this->ping(); } - auto uuid = CreateUUID(); + void PubSubClient::stop() + { + assert(this->started_); - rj::set(message, "nonce", uuid); + this->started_ = false; + } - std::string payload = rj::stringify(message); - sentMessages[uuid] = payload; + bool PubSubClient::listen(rapidjson::Document &message) + { + int numRequestedListens = message["data"]["topics"].Size(); - this->send(payload.c_str()); - - return true; -} - -void PubSubClient::unlistenPrefix(const std::string &prefix) -{ - std::vector topics; - - for (auto it = this->listeners_.begin(); it != this->listeners_.end();) { - const auto &listener = *it; - if (listener.topic.find(prefix) == 0) { - topics.push_back(listener.topic); - it = this->listeners_.erase(it); - } else { - ++it; + if (this->numListens_ + numRequestedListens > MAX_PUBSUB_LISTENS) { + // This PubSubClient is already at its peak listens + return false; } - } - if (topics.empty()) { - return; - } + this->numListens_ += numRequestedListens; - auto message = createUnlistenMessage(topics); - - auto uuid = CreateUUID(); - - rj::set(message, "nonce", CreateUUID()); - - std::string payload = rj::stringify(message); - sentMessages[uuid] = payload; - - this->send(payload.c_str()); -} - -void PubSubClient::handlePong() -{ - assert(this->awaitingPong_); - - log("Got pong!"); - - this->awaitingPong_ = false; -} - -bool PubSubClient::isListeningToTopic(const std::string &payload) -{ - for (const auto &listener : this->listeners_) { - if (listener.topic == payload) { - return true; + for (const auto &topic : message["data"]["topics"].GetArray()) { + this->listeners_.emplace_back( + Listener{topic.GetString(), false, false, false}); } + + auto uuid = CreateUUID(); + + rj::set(message, "nonce", uuid); + + std::string payload = rj::stringify(message); + sentMessages[uuid] = payload; + + this->send(payload.c_str()); + + return true; } - return false; -} + void PubSubClient::unlistenPrefix(const std::string &prefix) + { + std::vector topics; -void PubSubClient::ping() -{ - assert(this->started_); + for (auto it = this->listeners_.begin(); + it != this->listeners_.end();) { + const auto &listener = *it; + if (listener.topic.find(prefix) == 0) { + topics.push_back(listener.topic); + it = this->listeners_.erase(it); + } else { + ++it; + } + } - if (!this->send(pingPayload)) { - return; + if (topics.empty()) { + return; + } + + auto message = createUnlistenMessage(topics); + + auto uuid = CreateUUID(); + + rj::set(message, "nonce", CreateUUID()); + + std::string payload = rj::stringify(message); + sentMessages[uuid] = payload; + + this->send(payload.c_str()); } - this->awaitingPong_ = true; + void PubSubClient::handlePong() + { + assert(this->awaitingPong_); - auto self = this->shared_from_this(); + log("Got pong!"); - runAfter(this->websocketClient_.get_io_service(), std::chrono::seconds(15), - [self](auto timer) { - if (!self->started_) { - return; - } + this->awaitingPong_ = false; + } - if (self->awaitingPong_) { - log("No pong respnose, disconnect!"); - // TODO(pajlada): Label this connection as "disconnect me" - } - }); - - runAfter(this->websocketClient_.get_io_service(), std::chrono::minutes(5), - [self](auto timer) { - if (!self->started_) { - return; - } - - self->ping(); // - }); -} - -bool PubSubClient::send(const char *payload) -{ - WebsocketErrorCode ec; - this->websocketClient_.send(this->handle_, payload, - websocketpp::frame::opcode::text, ec); - - if (ec) { - log("Error sending message {}: {}", payload, ec.message()); - // TODO(pajlada): Check which error code happened and maybe gracefully - // handle it + bool PubSubClient::isListeningToTopic(const std::string &payload) + { + for (const auto &listener : this->listeners_) { + if (listener.topic == payload) { + return true; + } + } return false; } - return true; -} + void PubSubClient::ping() + { + assert(this->started_); + + if (!this->send(pingPayload)) { + return; + } + + this->awaitingPong_ = true; + + auto self = this->shared_from_this(); + + runAfter(this->websocketClient_.get_io_service(), + std::chrono::seconds(15), [self](auto timer) { + if (!self->started_) { + return; + } + + if (self->awaitingPong_) { + log("No pong respnose, disconnect!"); + // TODO(pajlada): Label this connection as "disconnect + // me" + } + }); + + runAfter(this->websocketClient_.get_io_service(), + std::chrono::minutes(5), [self](auto timer) { + if (!self->started_) { + return; + } + + self->ping(); // + }); + } + + bool PubSubClient::send(const char *payload) + { + WebsocketErrorCode ec; + this->websocketClient_.send(this->handle_, payload, + websocketpp::frame::opcode::text, ec); + + if (ec) { + log("Error sending message {}: {}", payload, ec.message()); + // TODO(pajlada): Check which error code happened and maybe + // gracefully handle it + + return false; + } + + return true; + } } // namespace detail diff --git a/src/providers/twitch/PubsubClient.hpp b/src/providers/twitch/PubsubClient.hpp index 211502176..f3cc10f15 100644 --- a/src/providers/twitch/PubsubClient.hpp +++ b/src/providers/twitch/PubsubClient.hpp @@ -32,41 +32,42 @@ using WebsocketErrorCode = websocketpp::lib::error_code; namespace detail { -struct Listener { - std::string topic; - bool authed; - bool persistent; - bool confirmed = false; -}; + struct Listener { + std::string topic; + bool authed; + bool persistent; + bool confirmed = false; + }; -class PubSubClient : public std::enable_shared_from_this -{ -public: - PubSubClient(WebsocketClient &_websocketClient, WebsocketHandle _handle); + class PubSubClient : public std::enable_shared_from_this + { + public: + PubSubClient(WebsocketClient &_websocketClient, + WebsocketHandle _handle); - void start(); - void stop(); + void start(); + void stop(); - bool listen(rapidjson::Document &message); - void unlistenPrefix(const std::string &prefix); + bool listen(rapidjson::Document &message); + void unlistenPrefix(const std::string &prefix); - void handlePong(); + void handlePong(); - bool isListeningToTopic(const std::string &topic); + bool isListeningToTopic(const std::string &topic); -private: - void ping(); - bool send(const char *payload); + private: + void ping(); + bool send(const char *payload); - WebsocketClient &websocketClient_; - WebsocketHandle handle_; - uint16_t numListens_ = 0; + WebsocketClient &websocketClient_; + WebsocketHandle handle_; + uint16_t numListens_ = 0; - std::vector listeners_; + std::vector listeners_; - std::atomic awaitingPong_{false}; - std::atomic started_{false}; -}; + std::atomic awaitingPong_{false}; + std::atomic started_{false}; + }; } // namespace detail diff --git a/src/providers/twitch/PubsubHelpers.hpp b/src/providers/twitch/PubsubHelpers.hpp index fe7056dc8..c478ed437 100644 --- a/src/providers/twitch/PubsubHelpers.hpp +++ b/src/providers/twitch/PubsubHelpers.hpp @@ -1,11 +1,10 @@ #pragma once -#include "debug/Log.hpp" -#include "util/RapidjsonHelpers.hpp" -#include "debug/Log.hpp" #include #include #include +#include "debug/Log.hpp" +#include "util/RapidjsonHelpers.hpp" namespace chatterino { diff --git a/src/providers/twitch/TwitchAccount.cpp b/src/providers/twitch/TwitchAccount.cpp index 238d9a6be..3e7ea237d 100644 --- a/src/providers/twitch/TwitchAccount.cpp +++ b/src/providers/twitch/TwitchAccount.cpp @@ -15,32 +15,32 @@ namespace chatterino { namespace { -EmoteName cleanUpCode(const EmoteName &dirtyEmoteCode) -{ - auto cleanCode = dirtyEmoteCode.string; - cleanCode.detach(); + EmoteName cleanUpCode(const EmoteName &dirtyEmoteCode) + { + auto cleanCode = dirtyEmoteCode.string; + cleanCode.detach(); - static QMap emoteNameReplacements{ - {"[oO](_|\\.)[oO]", "O_o"}, {"\\>\\;\\(", ">("}, - {"\\<\\;3", "<3"}, {"\\:-?(o|O)", ":O"}, - {"\\:-?(p|P)", ":P"}, {"\\:-?[\\\\/]", ":/"}, - {"\\:-?[z|Z|\\|]", ":Z"}, {"\\:-?\\(", ":("}, - {"\\:-?\\)", ":)"}, {"\\:-?D", ":D"}, - {"\\;-?(p|P)", ";P"}, {"\\;-?\\)", ";)"}, - {"R-?\\)", "R)"}, {"B-?\\)", "B)"}, - }; + static QMap emoteNameReplacements{ + {"[oO](_|\\.)[oO]", "O_o"}, {"\\>\\;\\(", ">("}, + {"\\<\\;3", "<3"}, {"\\:-?(o|O)", ":O"}, + {"\\:-?(p|P)", ":P"}, {"\\:-?[\\\\/]", ":/"}, + {"\\:-?[z|Z|\\|]", ":Z"}, {"\\:-?\\(", ":("}, + {"\\:-?\\)", ":)"}, {"\\:-?D", ":D"}, + {"\\;-?(p|P)", ";P"}, {"\\;-?\\)", ";)"}, + {"R-?\\)", "R)"}, {"B-?\\)", "B)"}, + }; - auto it = emoteNameReplacements.find(dirtyEmoteCode.string); - if (it != emoteNameReplacements.end()) { - cleanCode = it.value(); + auto it = emoteNameReplacements.find(dirtyEmoteCode.string); + if (it != emoteNameReplacements.end()) { + cleanCode = it.value(); + } + + cleanCode.replace("<", "<"); + cleanCode.replace(">", ">"); + + return {cleanCode}; } - cleanCode.replace("<", "<"); - cleanCode.replace(">", ">"); - - return {cleanCode}; -} - } // namespace TwitchAccount::TwitchAccount(const QString &username, const QString &oauthToken, @@ -417,7 +417,7 @@ void TwitchAccount::loadEmotes() } AccessGuard -TwitchAccount::accessEmotes() const + TwitchAccount::accessEmotes() const { return this->emotes_.accessConst(); } diff --git a/src/providers/twitch/TwitchChannel.cpp b/src/providers/twitch/TwitchChannel.cpp index 06ed13739..d6c55d224 100644 --- a/src/providers/twitch/TwitchChannel.cpp +++ b/src/providers/twitch/TwitchChannel.cpp @@ -25,48 +25,49 @@ namespace chatterino { namespace { -auto parseRecentMessages(const QJsonObject &jsonRoot, TwitchChannel &channel) -{ - QJsonArray jsonMessages = jsonRoot.value("messages").toArray(); - std::vector messages; + auto parseRecentMessages(const QJsonObject &jsonRoot, + TwitchChannel &channel) + { + QJsonArray jsonMessages = jsonRoot.value("messages").toArray(); + std::vector messages; - if (jsonMessages.empty()) return messages; + if (jsonMessages.empty()) return messages; - for (const auto jsonMessage : jsonMessages) { - auto content = jsonMessage.toString().toUtf8(); - // passing nullptr as the channel makes the message invalid but we don't - // check for that anyways - auto message = Communi::IrcMessage::fromData(content, nullptr); - auto privMsg = dynamic_cast(message); - assert(privMsg); + for (const auto jsonMessage : jsonMessages) { + auto content = jsonMessage.toString().toUtf8(); + // passing nullptr as the channel makes the message invalid but we + // don't check for that anyways + auto message = Communi::IrcMessage::fromData(content, nullptr); + auto privMsg = dynamic_cast(message); + assert(privMsg); - MessageParseArgs args; - TwitchMessageBuilder builder(&channel, privMsg, args); - if (!builder.isIgnored()) { - messages.push_back(builder.build()); + MessageParseArgs args; + TwitchMessageBuilder builder(&channel, privMsg, args); + if (!builder.isIgnored()) { + messages.push_back(builder.build()); + } } + + return messages; } + std::pair parseChatters(const QJsonObject &jsonRoot) + { + static QStringList categories = {"moderators", "staff", "admins", + "global_mods", "viewers"}; - return messages; -} -std::pair parseChatters(const QJsonObject &jsonRoot) -{ - static QStringList categories = {"moderators", "staff", "admins", - "global_mods", "viewers"}; + auto usernames = UsernameSet(); - auto usernames = UsernameSet(); + // parse json + QJsonObject jsonCategories = jsonRoot.value("chatters").toObject(); - // parse json - QJsonObject jsonCategories = jsonRoot.value("chatters").toObject(); - - for (const auto &category : categories) { - for (auto jsonCategory : jsonCategories.value(category).toArray()) { - usernames.insert(jsonCategory.toString()); + for (const auto &category : categories) { + for (auto jsonCategory : jsonCategories.value(category).toArray()) { + usernames.insert(jsonCategory.toString()); + } } - } - return {Success, std::move(usernames)}; -} + return {Success, std::move(usernames)}; + } } // namespace TwitchChannel::TwitchChannel(const QString &name, @@ -309,7 +310,7 @@ bool TwitchChannel::isLive() const } AccessGuard -TwitchChannel::accessStreamStatus() const + TwitchChannel::accessStreamStatus() const { return this->streamStatus_.accessConst(); } diff --git a/src/providers/twitch/TwitchParseCheerEmotes.cpp b/src/providers/twitch/TwitchParseCheerEmotes.cpp index 47d6427f8..65eca1fa3 100644 --- a/src/providers/twitch/TwitchParseCheerEmotes.cpp +++ b/src/providers/twitch/TwitchParseCheerEmotes.cpp @@ -8,235 +8,235 @@ namespace chatterino { namespace { -template -inline bool ReadValue(const rapidjson::Value &object, const char *key, - Type &out) -{ - if (!object.HasMember(key)) { - return false; - } - - const auto &value = object[key]; - - if (!value.Is()) { - return false; - } - - out = value.Get(); - - return true; -} - -template <> -inline bool ReadValue(const rapidjson::Value &object, const char *key, - QString &out) -{ - if (!object.HasMember(key)) { - return false; - } - - const auto &value = object[key]; - - if (!value.IsString()) { - return false; - } - - out = value.GetString(); - - return true; -} - -template <> -inline bool ReadValue>(const rapidjson::Value &object, - const char *key, - std::vector &out) -{ - if (!object.HasMember(key)) { - return false; - } - - const auto &value = object[key]; - - if (!value.IsArray()) { - return false; - } - - for (const rapidjson::Value &innerValue : value.GetArray()) { - if (!innerValue.IsString()) { + template + inline bool ReadValue(const rapidjson::Value &object, const char *key, + Type &out) + { + if (!object.HasMember(key)) { return false; } - out.emplace_back(innerValue.GetString()); - } + const auto &value = object[key]; - return true; -} - -// Parse a single cheermote set (or "action") from the twitch api -inline bool ParseSingleCheermoteSet(JSONCheermoteSet &set, - const rapidjson::Value &action) -{ - if (!action.IsObject()) { - return false; - } - - if (!ReadValue(action, "prefix", set.prefix)) { - return false; - } - - if (!ReadValue(action, "scales", set.scales)) { - return false; - } - - if (!ReadValue(action, "backgrounds", set.backgrounds)) { - return false; - } - - if (!ReadValue(action, "states", set.states)) { - return false; - } - - if (!ReadValue(action, "type", set.type)) { - return false; - } - - if (!ReadValue(action, "updated_at", set.updatedAt)) { - return false; - } - - if (!ReadValue(action, "priority", set.priority)) { - return false; - } - - // Tiers - if (!action.HasMember("tiers")) { - return false; - } - - const auto &tiersValue = action["tiers"]; - - if (!tiersValue.IsArray()) { - return false; - } - - for (const rapidjson::Value &tierValue : tiersValue.GetArray()) { - JSONCheermoteSet::CheermoteTier tier; - - if (!tierValue.IsObject()) { + if (!value.Is()) { return false; } - if (!ReadValue(tierValue, "min_bits", tier.minBits)) { + out = value.Get(); + + return true; + } + + template <> + inline bool ReadValue(const rapidjson::Value &object, + const char *key, QString &out) + { + if (!object.HasMember(key)) { return false; } - if (!ReadValue(tierValue, "id", tier.id)) { + const auto &value = object[key]; + + if (!value.IsString()) { return false; } - if (!ReadValue(tierValue, "color", tier.color)) { + out = value.GetString(); + + return true; + } + + template <> + inline bool ReadValue>(const rapidjson::Value &object, + const char *key, + std::vector &out) + { + if (!object.HasMember(key)) { return false; } - // Images - if (!tierValue.HasMember("images")) { + const auto &value = object[key]; + + if (!value.IsArray()) { return false; } - const auto &imagesValue = tierValue["images"]; - - if (!imagesValue.IsObject()) { - return false; - } - - // Read images object - for (const auto &imageBackgroundValue : imagesValue.GetObject()) { - QString background = imageBackgroundValue.name.GetString(); - bool backgroundExists = false; - for (const auto &bg : set.backgrounds) { - if (background == bg) { - backgroundExists = true; - break; - } + for (const rapidjson::Value &innerValue : value.GetArray()) { + if (!innerValue.IsString()) { + return false; } - if (!backgroundExists) { - continue; + out.emplace_back(innerValue.GetString()); + } + + return true; + } + + // Parse a single cheermote set (or "action") from the twitch api + inline bool ParseSingleCheermoteSet(JSONCheermoteSet &set, + const rapidjson::Value &action) + { + if (!action.IsObject()) { + return false; + } + + if (!ReadValue(action, "prefix", set.prefix)) { + return false; + } + + if (!ReadValue(action, "scales", set.scales)) { + return false; + } + + if (!ReadValue(action, "backgrounds", set.backgrounds)) { + return false; + } + + if (!ReadValue(action, "states", set.states)) { + return false; + } + + if (!ReadValue(action, "type", set.type)) { + return false; + } + + if (!ReadValue(action, "updated_at", set.updatedAt)) { + return false; + } + + if (!ReadValue(action, "priority", set.priority)) { + return false; + } + + // Tiers + if (!action.HasMember("tiers")) { + return false; + } + + const auto &tiersValue = action["tiers"]; + + if (!tiersValue.IsArray()) { + return false; + } + + for (const rapidjson::Value &tierValue : tiersValue.GetArray()) { + JSONCheermoteSet::CheermoteTier tier; + + if (!tierValue.IsObject()) { + return false; } - const rapidjson::Value &imageBackgroundStates = - imageBackgroundValue.value; - if (!imageBackgroundStates.IsObject()) { - continue; + if (!ReadValue(tierValue, "min_bits", tier.minBits)) { + return false; } - // Read each key which represents a background - for (const auto &imageBackgroundState : - imageBackgroundStates.GetObject()) { - QString state = imageBackgroundState.name.GetString(); - bool stateExists = false; - for (const auto &_state : set.states) { - if (state == _state) { - stateExists = true; + if (!ReadValue(tierValue, "id", tier.id)) { + return false; + } + + if (!ReadValue(tierValue, "color", tier.color)) { + return false; + } + + // Images + if (!tierValue.HasMember("images")) { + return false; + } + + const auto &imagesValue = tierValue["images"]; + + if (!imagesValue.IsObject()) { + return false; + } + + // Read images object + for (const auto &imageBackgroundValue : imagesValue.GetObject()) { + QString background = imageBackgroundValue.name.GetString(); + bool backgroundExists = false; + for (const auto &bg : set.backgrounds) { + if (background == bg) { + backgroundExists = true; break; } } - if (!stateExists) { + if (!backgroundExists) { continue; } - const rapidjson::Value &imageScalesValue = - imageBackgroundState.value; - if (!imageScalesValue.IsObject()) { + const rapidjson::Value &imageBackgroundStates = + imageBackgroundValue.value; + if (!imageBackgroundStates.IsObject()) { continue; } - // Read each key which represents a scale - for (const auto &imageScaleValue : - imageScalesValue.GetObject()) { - QString scale = imageScaleValue.name.GetString(); - bool scaleExists = false; - for (const auto &_scale : set.scales) { - if (scale == _scale) { - scaleExists = true; + // Read each key which represents a background + for (const auto &imageBackgroundState : + imageBackgroundStates.GetObject()) { + QString state = imageBackgroundState.name.GetString(); + bool stateExists = false; + for (const auto &_state : set.states) { + if (state == _state) { + stateExists = true; break; } } - if (!scaleExists) { + if (!stateExists) { continue; } - const rapidjson::Value &imageScaleURLValue = - imageScaleValue.value; - if (!imageScaleURLValue.IsString()) { + const rapidjson::Value &imageScalesValue = + imageBackgroundState.value; + if (!imageScalesValue.IsObject()) { continue; } - QString url = imageScaleURLValue.GetString(); + // Read each key which represents a scale + for (const auto &imageScaleValue : + imageScalesValue.GetObject()) { + QString scale = imageScaleValue.name.GetString(); + bool scaleExists = false; + for (const auto &_scale : set.scales) { + if (scale == _scale) { + scaleExists = true; + break; + } + } - bool ok = false; - qreal scaleNumber = scale.toFloat(&ok); - if (!ok) { - continue; + if (!scaleExists) { + continue; + } + + const rapidjson::Value &imageScaleURLValue = + imageScaleValue.value; + if (!imageScaleURLValue.IsString()) { + continue; + } + + QString url = imageScaleURLValue.GetString(); + + bool ok = false; + qreal scaleNumber = scale.toFloat(&ok); + if (!ok) { + continue; + } + + qreal chatterinoScale = 1 / scaleNumber; + + auto image = Image::fromUrl({url}, chatterinoScale); + + // TODO(pajlada): Fill in name and tooltip + tier.images[background][state][scale] = image; } - - qreal chatterinoScale = 1 / scaleNumber; - - auto image = Image::fromUrl({url}, chatterinoScale); - - // TODO(pajlada): Fill in name and tooltip - tier.images[background][state][scale] = image; } } + + set.tiers.emplace_back(tier); } - set.tiers.emplace_back(tier); + return true; } - - return true; -} } // namespace // Look through the results of diff --git a/src/providers/twitch/TwitchUser.hpp b/src/providers/twitch/TwitchUser.hpp index 74a9c1252..27539386d 100644 --- a/src/providers/twitch/TwitchUser.hpp +++ b/src/providers/twitch/TwitchUser.hpp @@ -34,43 +34,43 @@ struct TwitchUser { namespace pajlada { namespace Settings { -template <> -struct Deserialize { - static chatterino::TwitchUser get(const rapidjson::Value &value, - bool *error = nullptr) - { - using namespace chatterino; + template <> + struct Deserialize { + static chatterino::TwitchUser get(const rapidjson::Value &value, + bool *error = nullptr) + { + using namespace chatterino; - TwitchUser user; + TwitchUser user; + + if (!value.IsObject()) { + PAJLADA_REPORT_ERROR(error) + PAJLADA_THROW_EXCEPTION( + "Deserialized rapidjson::Value is wrong type"); + return user; + } + + if (!rj::getSafe(value, "_id", user.id)) { + PAJLADA_REPORT_ERROR(error) + PAJLADA_THROW_EXCEPTION("Missing ID key"); + return user; + } + + if (!rj::getSafe(value, "name", user.name)) { + PAJLADA_REPORT_ERROR(error) + PAJLADA_THROW_EXCEPTION("Missing name key"); + return user; + } + + if (!rj::getSafe(value, "display_name", user.displayName)) { + PAJLADA_REPORT_ERROR(error) + PAJLADA_THROW_EXCEPTION("Missing display name key"); + return user; + } - if (!value.IsObject()) { - PAJLADA_REPORT_ERROR(error) - PAJLADA_THROW_EXCEPTION( - "Deserialized rapidjson::Value is wrong type"); return user; } - - if (!rj::getSafe(value, "_id", user.id)) { - PAJLADA_REPORT_ERROR(error) - PAJLADA_THROW_EXCEPTION("Missing ID key"); - return user; - } - - if (!rj::getSafe(value, "name", user.name)) { - PAJLADA_REPORT_ERROR(error) - PAJLADA_THROW_EXCEPTION("Missing name key"); - return user; - } - - if (!rj::getSafe(value, "display_name", user.displayName)) { - PAJLADA_REPORT_ERROR(error) - PAJLADA_THROW_EXCEPTION("Missing display name key"); - return user; - } - - return user; - } -}; + }; } // namespace Settings } // namespace pajlada diff --git a/src/singletons/Fonts.cpp b/src/singletons/Fonts.cpp index cc2f00727..991646acd 100644 --- a/src/singletons/Fonts.cpp +++ b/src/singletons/Fonts.cpp @@ -9,16 +9,16 @@ #include #ifdef Q_OS_WIN32 -#define DEFAULT_FONT_FAMILY "Segoe UI" -#define DEFAULT_FONT_SIZE 10 +# define DEFAULT_FONT_FAMILY "Segoe UI" +# define DEFAULT_FONT_SIZE 10 #else -#ifdef Q_OS_MACOS -#define DEFAULT_FONT_FAMILY "Helvetica Neue" -#define DEFAULT_FONT_SIZE 12 -#else -#define DEFAULT_FONT_FAMILY "Arial" -#define DEFAULT_FONT_SIZE 11 -#endif +# ifdef Q_OS_MACOS +# define DEFAULT_FONT_FAMILY "Helvetica Neue" +# define DEFAULT_FONT_SIZE 12 +# else +# define DEFAULT_FONT_FAMILY "Arial" +# define DEFAULT_FONT_SIZE 11 +# endif #endif namespace chatterino { @@ -104,8 +104,7 @@ Fonts::FontData Fonts::createFontData(FontStyle type, float scale) {FontStyle::ChatMediumSmall, {0.8f, false, QFont::Normal}}, {FontStyle::ChatMedium, {1, false, QFont::Normal}}, {FontStyle::ChatMediumBold, - {1, false, - QFont::Weight(getSettings()->boldScale.getValue())}}, + {1, false, QFont::Weight(getSettings()->boldScale.getValue())}}, {FontStyle::ChatMediumItalic, {1, true, QFont::Normal}}, {FontStyle::ChatLarge, {1.2f, false, QFont::Normal}}, {FontStyle::ChatVeryLarge, {1.4f, false, QFont::Normal}}, diff --git a/src/singletons/NativeMessaging.cpp b/src/singletons/NativeMessaging.cpp index cd80f8021..ed113f716 100644 --- a/src/singletons/NativeMessaging.cpp +++ b/src/singletons/NativeMessaging.cpp @@ -17,11 +17,11 @@ namespace ipc = boost::interprocess; #ifdef Q_OS_WIN -#include +# include -#include -#include "singletons/WindowManager.hpp" -#include "widgets/AttachedWindow.hpp" +# include +# include "singletons/WindowManager.hpp" +# include "widgets/AttachedWindow.hpp" #endif #include diff --git a/src/singletons/Theme.cpp b/src/singletons/Theme.cpp index c5aa16b71..e39a6c873 100644 --- a/src/singletons/Theme.cpp +++ b/src/singletons/Theme.cpp @@ -10,21 +10,21 @@ namespace chatterino { namespace detail { -double getMultiplierByTheme(const QString &themeName) -{ - if (themeName == "Light") { - return 0.8; - } else if (themeName == "White") { - return 1.0; - } else if (themeName == "Black") { - return -1.0; - } else if (themeName == "Dark") { + double getMultiplierByTheme(const QString &themeName) + { + if (themeName == "Light") { + return 0.8; + } else if (themeName == "White") { + return 1.0; + } else if (themeName == "Black") { + return -1.0; + } else if (themeName == "Dark") { + return -0.8; + } + return -0.8; } - return -0.8; -} - } // namespace detail Theme::Theme() diff --git a/src/util/FormatTime.cpp b/src/util/FormatTime.cpp index 2eccca901..63b2e3c6b 100644 --- a/src/util/FormatTime.cpp +++ b/src/util/FormatTime.cpp @@ -2,11 +2,11 @@ namespace chatterino { namespace { -void appendDuration(int count, QChar &&order, QString &outString) -{ - outString.append(QString::number(count)); - outString.append(order); -} + void appendDuration(int count, QChar &&order, QString &outString) + { + outString.append(QString::number(count)); + outString.append(order); + } } // namespace QString formatTime(int totalSeconds) diff --git a/src/util/InitUpdateButton.hpp b/src/util/InitUpdateButton.hpp index 9a88382a2..c8caaf204 100644 --- a/src/util/InitUpdateButton.hpp +++ b/src/util/InitUpdateButton.hpp @@ -4,7 +4,7 @@ namespace pajlada { namespace Signals { -class SignalHolder; + class SignalHolder; } } // namespace pajlada diff --git a/src/util/RapidJsonSerializeQString.hpp b/src/util/RapidJsonSerializeQString.hpp index 754cbf115..0d34a256b 100644 --- a/src/util/RapidJsonSerializeQString.hpp +++ b/src/util/RapidJsonSerializeQString.hpp @@ -6,38 +6,38 @@ namespace pajlada { namespace Settings { -template <> -struct Serialize { - static rapidjson::Value get(const QString &value, - rapidjson::Document::AllocatorType &a) - { - return rapidjson::Value(value.toUtf8(), a); - } -}; + template <> + struct Serialize { + static rapidjson::Value get(const QString &value, + rapidjson::Document::AllocatorType &a) + { + return rapidjson::Value(value.toUtf8(), a); + } + }; + + template <> + struct Deserialize { + static QString get(const rapidjson::Value &value, bool *error = nullptr) + { + if (!value.IsString()) { + PAJLADA_REPORT_ERROR(error) + PAJLADA_THROW_EXCEPTION( + "Deserialized rapidjson::Value is not a string"); + return QString{}; + } + + try { + return QString::fromUtf8(value.GetString(), + value.GetStringLength()); + } catch (const std::exception &) { + // int x = 5; + } catch (...) { + // int y = 5; + } -template <> -struct Deserialize { - static QString get(const rapidjson::Value &value, bool *error = nullptr) - { - if (!value.IsString()) { - PAJLADA_REPORT_ERROR(error) - PAJLADA_THROW_EXCEPTION( - "Deserialized rapidjson::Value is not a string"); return QString{}; } - - try { - return QString::fromUtf8(value.GetString(), - value.GetStringLength()); - } catch (const std::exception &) { - // int x = 5; - } catch (...) { - // int y = 5; - } - - return QString{}; - } -}; + }; } // namespace Settings } // namespace pajlada diff --git a/src/util/RapidjsonHelpers.cpp b/src/util/RapidjsonHelpers.cpp index 78256b4a2..2a9742df2 100644 --- a/src/util/RapidjsonHelpers.cpp +++ b/src/util/RapidjsonHelpers.cpp @@ -5,26 +5,28 @@ namespace chatterino { namespace rj { -void addMember(rapidjson::Value &obj, const char *key, rapidjson::Value &&value, - rapidjson::Document::AllocatorType &a) -{ - obj.AddMember(rapidjson::Value(key, a).Move(), value, a); -} + void addMember(rapidjson::Value &obj, const char *key, + rapidjson::Value &&value, + rapidjson::Document::AllocatorType &a) + { + obj.AddMember(rapidjson::Value(key, a).Move(), value, a); + } -void addMember(rapidjson::Value &obj, const char *key, rapidjson::Value &value, - rapidjson::Document::AllocatorType &a) -{ - obj.AddMember(rapidjson::Value(key, a).Move(), value.Move(), a); -} + void addMember(rapidjson::Value &obj, const char *key, + rapidjson::Value &value, + rapidjson::Document::AllocatorType &a) + { + obj.AddMember(rapidjson::Value(key, a).Move(), value.Move(), a); + } -std::string stringify(const rapidjson::Value &value) -{ - rapidjson::StringBuffer buffer; - rapidjson::Writer writer(buffer); - value.Accept(writer); + std::string stringify(const rapidjson::Value &value) + { + rapidjson::StringBuffer buffer; + rapidjson::Writer writer(buffer); + value.Accept(writer); - return std::string(buffer.GetString()); -} + return std::string(buffer.GetString()); + } } // namespace rj } // namespace chatterino diff --git a/src/util/RapidjsonHelpers.hpp b/src/util/RapidjsonHelpers.hpp index 8dbfe07a2..d3e73e8f9 100644 --- a/src/util/RapidjsonHelpers.hpp +++ b/src/util/RapidjsonHelpers.hpp @@ -11,91 +11,95 @@ namespace chatterino { namespace rj { -void addMember(rapidjson::Value &obj, const char *key, rapidjson::Value &&value, - rapidjson::Document::AllocatorType &a); -void addMember(rapidjson::Value &obj, const char *key, rapidjson::Value &value, - rapidjson::Document::AllocatorType &a); + void addMember(rapidjson::Value &obj, const char *key, + rapidjson::Value &&value, + rapidjson::Document::AllocatorType &a); + void addMember(rapidjson::Value &obj, const char *key, + rapidjson::Value &value, + rapidjson::Document::AllocatorType &a); -template -void set(rapidjson::Value &obj, const char *key, const Type &value, - rapidjson::Document::AllocatorType &a) -{ - assert(obj.IsObject()); + template + void set(rapidjson::Value &obj, const char *key, const Type &value, + rapidjson::Document::AllocatorType &a) + { + assert(obj.IsObject()); - addMember(obj, key, pajlada::Settings::Serialize::get(value, a), a); -} - -template <> -inline void set(rapidjson::Value &obj, const char *key, - const rapidjson::Value &value, - rapidjson::Document::AllocatorType &a) -{ - assert(obj.IsObject()); - - addMember(obj, key, const_cast(value), a); -} - -template -void set(rapidjson::Document &obj, const char *key, const Type &value) -{ - assert(obj.IsObject()); - - auto &a = obj.GetAllocator(); - - addMember(obj, key, pajlada::Settings::Serialize::get(value, a), a); -} - -template <> -inline void set(rapidjson::Document &obj, const char *key, - const rapidjson::Value &value) -{ - assert(obj.IsObject()); - - auto &a = obj.GetAllocator(); - - addMember(obj, key, const_cast(value), a); -} - -template -void add(rapidjson::Value &arr, const Type &value, - rapidjson::Document::AllocatorType &a) -{ - assert(arr.IsArray()); - - arr.PushBack(pajlada::Settings::Serialize::get(value, a), a); -} - -template -bool getSafe(const rapidjson::Value &obj, const char *key, Type &out) -{ - if (!obj.IsObject()) { - return false; + addMember(obj, key, pajlada::Settings::Serialize::get(value, a), + a); } - if (!obj.HasMember(key)) { - return false; + template <> + inline void set(rapidjson::Value &obj, const char *key, + const rapidjson::Value &value, + rapidjson::Document::AllocatorType &a) + { + assert(obj.IsObject()); + + addMember(obj, key, const_cast(value), a); } - if (obj.IsNull()) { - return false; + template + void set(rapidjson::Document &obj, const char *key, const Type &value) + { + assert(obj.IsObject()); + + auto &a = obj.GetAllocator(); + + addMember(obj, key, pajlada::Settings::Serialize::get(value, a), + a); } - bool error = false; - out = pajlada::Settings::Deserialize::get(obj[key], &error); + template <> + inline void set(rapidjson::Document &obj, const char *key, + const rapidjson::Value &value) + { + assert(obj.IsObject()); - return !error; -} + auto &a = obj.GetAllocator(); -template -bool getSafe(const rapidjson::Value &value, Type &out) -{ - bool error = false; - out = pajlada::Settings::Deserialize::get(value, &error); + addMember(obj, key, const_cast(value), a); + } - return !error; -} + template + void add(rapidjson::Value &arr, const Type &value, + rapidjson::Document::AllocatorType &a) + { + assert(arr.IsArray()); -std::string stringify(const rapidjson::Value &value); + arr.PushBack(pajlada::Settings::Serialize::get(value, a), a); + } + + template + bool getSafe(const rapidjson::Value &obj, const char *key, Type &out) + { + if (!obj.IsObject()) { + return false; + } + + if (!obj.HasMember(key)) { + return false; + } + + if (obj.IsNull()) { + return false; + } + + bool error = false; + out = pajlada::Settings::Deserialize::get(obj[key], &error); + + return !error; + } + + template + bool getSafe(const rapidjson::Value &value, Type &out) + { + bool error = false; + out = pajlada::Settings::Deserialize::get(value, &error); + + return !error; + } + + std::string stringify(const rapidjson::Value &value); } // namespace rj } // namespace chatterino diff --git a/src/util/StreamLink.cpp b/src/util/StreamLink.cpp index 3cf639b6c..972c47f59 100644 --- a/src/util/StreamLink.cpp +++ b/src/util/StreamLink.cpp @@ -2,9 +2,9 @@ #include "Application.hpp" #include "Helpers.hpp" +#include "debug/Log.hpp" #include "singletons/Settings.hpp" #include "widgets/dialogs/QualityPopup.hpp" -#include "debug/Log.hpp" #include #include @@ -16,88 +16,89 @@ namespace chatterino { namespace { -const char *getBinaryName() -{ + const char *getBinaryName() + { #ifdef _WIN32 - return "streamlink.exe"; + return "streamlink.exe"; #else - return "streamlink"; + return "streamlink"; #endif -} + } -const char *getDefaultBinaryPath() -{ + const char *getDefaultBinaryPath() + { #ifdef _WIN32 - return "C:\\Program Files (x86)\\Streamlink\\bin\\streamlink.exe"; + return "C:\\Program Files (x86)\\Streamlink\\bin\\streamlink.exe"; #else - return "/usr/bin/streamlink"; + return "/usr/bin/streamlink"; #endif -} - -QString getStreamlinkProgram() -{ - auto app = getApp(); - - if (getSettings()->streamlinkUseCustomPath) { - return getSettings()->streamlinkPath + "/" + getBinaryName(); - } else { - return getBinaryName(); - } -} - -bool checkStreamlinkPath(const QString &path) -{ - QFileInfo fileinfo(path); - - if (!fileinfo.exists()) { - return false; - // throw Exception(fS("Streamlink path ({}) is invalid, file does not - // exist", path)); } - return fileinfo.isExecutable(); -} + QString getStreamlinkProgram() + { + auto app = getApp(); -void showStreamlinkNotFoundError() -{ - static QErrorMessage *msg = new QErrorMessage; - - auto app = getApp(); - if (getSettings()->streamlinkUseCustomPath) { - msg->showMessage( - "Unable to find Streamlink executable\nMake sure your custom path " - "is pointing " - "to the DIRECTORY where the streamlink executable is located"); - } else { - msg->showMessage( - "Unable to find Streamlink executable.\nIf you have Streamlink " - "installed, you might need to enable the custom path option"); - } -} - -QProcess *createStreamlinkProcess() -{ - auto p = new QProcess; - p->setProgram(getStreamlinkProgram()); - - QObject::connect(p, &QProcess::errorOccurred, [=](auto err) { - if (err == QProcess::FailedToStart) { - showStreamlinkNotFoundError(); + if (getSettings()->streamlinkUseCustomPath) { + return getSettings()->streamlinkPath + "/" + getBinaryName(); } else { - log("Error occured {}", err); + return getBinaryName(); + } + } + + bool checkStreamlinkPath(const QString &path) + { + QFileInfo fileinfo(path); + + if (!fileinfo.exists()) { + return false; + // throw Exception(fS("Streamlink path ({}) is invalid, file does + // not exist", path)); } - p->deleteLater(); - }); + return fileinfo.isExecutable(); + } - QObject::connect(p, - static_cast(&QProcess::finished), - [=](int res) { - p->deleteLater(); // - }); + void showStreamlinkNotFoundError() + { + static QErrorMessage *msg = new QErrorMessage; - return p; -} + auto app = getApp(); + if (getSettings()->streamlinkUseCustomPath) { + msg->showMessage( + "Unable to find Streamlink executable\nMake sure your custom " + "path " + "is pointing " + "to the DIRECTORY where the streamlink executable is located"); + } else { + msg->showMessage( + "Unable to find Streamlink executable.\nIf you have Streamlink " + "installed, you might need to enable the custom path option"); + } + } + + QProcess *createStreamlinkProcess() + { + auto p = new QProcess; + p->setProgram(getStreamlinkProgram()); + + QObject::connect(p, &QProcess::errorOccurred, [=](auto err) { + if (err == QProcess::FailedToStart) { + showStreamlinkNotFoundError(); + } else { + log("Error occured {}", err); + } + + p->deleteLater(); + }); + + QObject::connect( + p, static_cast(&QProcess::finished), + [=](int res) { + p->deleteLater(); // + }); + + return p; + } } // namespace diff --git a/src/util/WindowsHelper.hpp b/src/util/WindowsHelper.hpp index fdbafa9c2..f02bb1362 100644 --- a/src/util/WindowsHelper.hpp +++ b/src/util/WindowsHelper.hpp @@ -2,8 +2,8 @@ #ifdef USEWINSDK -#include -#include +# include +# include namespace chatterino { diff --git a/src/widgets/AttachedWindow.cpp b/src/widgets/AttachedWindow.cpp index b247129b6..fee940591 100644 --- a/src/widgets/AttachedWindow.cpp +++ b/src/widgets/AttachedWindow.cpp @@ -8,12 +8,12 @@ #include #ifdef USEWINSDK -#include "util/WindowsHelper.hpp" +# include "util/WindowsHelper.hpp" -#include "Windows.h" +# include "Windows.h" // don't even think about reordering these -#include "Psapi.h" -#pragma comment(lib, "Dwmapi.lib") +# include "Psapi.h" +# pragma comment(lib, "Dwmapi.lib") #endif namespace chatterino { diff --git a/src/widgets/BaseWindow.cpp b/src/widgets/BaseWindow.cpp index af97b224b..6394284e0 100644 --- a/src/widgets/BaseWindow.cpp +++ b/src/widgets/BaseWindow.cpp @@ -20,20 +20,20 @@ #include #ifdef USEWINSDK -#include -#include -#include -#include -#include -#include +# include +# include +# include +# include +# include +# include //#include -#pragma comment(lib, "Dwmapi.lib") +# pragma comment(lib, "Dwmapi.lib") -#include -#include +# include +# include -#define WM_DPICHANGED 0x02E0 +# define WM_DPICHANGED 0x02E0 #endif #include "widgets/helper/TitlebarButton.hpp" @@ -460,11 +460,11 @@ bool BaseWindow::nativeEvent(const QByteArray &eventType, void *message, long *result) { #ifdef USEWINSDK -#if (QT_VERSION == QT_VERSION_CHECK(5, 11, 1)) +# if (QT_VERSION == QT_VERSION_CHECK(5, 11, 1)) MSG *msg = *reinterpret_cast(message); -#else +# else MSG *msg = reinterpret_cast(message); -#endif +# endif bool returnValue = false; diff --git a/src/widgets/Notebook.cpp b/src/widgets/Notebook.cpp index 04ecd0840..c56fba8b5 100644 --- a/src/widgets/Notebook.cpp +++ b/src/widgets/Notebook.cpp @@ -433,8 +433,7 @@ void SplitNotebook::addCustomButtons() // settings auto settingsBtn = this->addCustomButton(); - settingsBtn->setVisible( - !getSettings()->hidePreferencesButton.getValue()); + settingsBtn->setVisible(!getSettings()->hidePreferencesButton.getValue()); getSettings()->hidePreferencesButton.connect( [settingsBtn](bool hide, auto) { settingsBtn->setVisible(!hide); }, diff --git a/src/widgets/StreamView.cpp b/src/widgets/StreamView.cpp index 9277ba825..f548deceb 100644 --- a/src/widgets/StreamView.cpp +++ b/src/widgets/StreamView.cpp @@ -7,7 +7,7 @@ #include "widgets/splits/Split.hpp" #ifdef USEWEBENGINE -#include +# include #endif namespace chatterino { diff --git a/src/widgets/TooltipWidget.cpp b/src/widgets/TooltipWidget.cpp index 3479826b8..084f729ac 100644 --- a/src/widgets/TooltipWidget.cpp +++ b/src/widgets/TooltipWidget.cpp @@ -10,7 +10,7 @@ #include #ifdef USEWINSDK -#include +# include #endif namespace chatterino { diff --git a/src/widgets/dialogs/EmotePopup.cpp b/src/widgets/dialogs/EmotePopup.cpp index 735d68f63..2fe6bb28a 100644 --- a/src/widgets/dialogs/EmotePopup.cpp +++ b/src/widgets/dialogs/EmotePopup.cpp @@ -16,55 +16,57 @@ namespace chatterino { namespace { -auto makeTitleMessage(const QString &title) -{ - MessageBuilder builder; - builder.emplace(title, MessageElementFlag::Text); - builder->flags.set(MessageFlag::Centered); - return builder.release(); -} -auto makeEmoteMessage(const EmoteMap &map) -{ - MessageBuilder builder; - builder->flags.set(MessageFlag::Centered); - builder->flags.set(MessageFlag::DisableCompactEmotes); - - for (const auto &emote : map) { - builder - .emplace(emote.second, MessageElementFlag::AlwaysShow) - ->setLink(Link(Link::InsertText, emote.first.string)); + auto makeTitleMessage(const QString &title) + { + MessageBuilder builder; + builder.emplace(title, MessageElementFlag::Text); + builder->flags.set(MessageFlag::Centered); + return builder.release(); } - - return builder.release(); -} -void addEmoteSets(std::vector> sets, - Channel &globalChannel, Channel &subChannel) -{ - for (const auto &set : sets) { - auto &channel = set->key == "0" ? globalChannel : subChannel; - - // TITLE - auto text = - set->key == "0" || set->text.isEmpty() ? "Twitch" : set->text; - channel.addMessage(makeTitleMessage(text)); - - // EMOTES + auto makeEmoteMessage(const EmoteMap &map) + { MessageBuilder builder; builder->flags.set(MessageFlag::Centered); builder->flags.set(MessageFlag::DisableCompactEmotes); - for (const auto &emote : set->emotes) { + for (const auto &emote : map) { builder - .emplace( - getApp()->emotes->twitch.getOrCreateEmote(emote.id, - emote.name), - MessageElementFlag::AlwaysShow) - ->setLink(Link(Link::InsertText, emote.name.string)); + .emplace(emote.second, + MessageElementFlag::AlwaysShow) + ->setLink(Link(Link::InsertText, emote.first.string)); } - channel.addMessage(builder.release()); + return builder.release(); + } + void addEmoteSets( + std::vector> sets, + Channel &globalChannel, Channel &subChannel) + { + for (const auto &set : sets) { + auto &channel = set->key == "0" ? globalChannel : subChannel; + + // TITLE + auto text = + set->key == "0" || set->text.isEmpty() ? "Twitch" : set->text; + channel.addMessage(makeTitleMessage(text)); + + // EMOTES + MessageBuilder builder; + builder->flags.set(MessageFlag::Centered); + builder->flags.set(MessageFlag::DisableCompactEmotes); + + for (const auto &emote : set->emotes) { + builder + .emplace( + getApp()->emotes->twitch.getOrCreateEmote(emote.id, + emote.name), + MessageElementFlag::AlwaysShow) + ->setLink(Link(Link::InsertText, emote.name.string)); + } + + channel.addMessage(builder.release()); + } } -} } // namespace EmotePopup::EmotePopup() diff --git a/src/widgets/dialogs/LoginDialog.cpp b/src/widgets/dialogs/LoginDialog.cpp index daf3c201e..35c18c7d6 100644 --- a/src/widgets/dialogs/LoginDialog.cpp +++ b/src/widgets/dialogs/LoginDialog.cpp @@ -7,7 +7,7 @@ #include "providers/twitch/PartialTwitchUser.hpp" #ifdef USEWINSDK -#include +# include #endif #include @@ -21,54 +21,54 @@ namespace chatterino { namespace { -void LogInWithCredentials(const std::string &userID, - const std::string &username, - const std::string &clientID, - const std::string &oauthToken) -{ - QStringList errors; + void LogInWithCredentials(const std::string &userID, + const std::string &username, + const std::string &clientID, + const std::string &oauthToken) + { + QStringList errors; - if (userID.empty()) { - errors.append("Missing user ID"); + if (userID.empty()) { + errors.append("Missing user ID"); + } + if (username.empty()) { + errors.append("Missing username"); + } + if (clientID.empty()) { + errors.append("Missing Client ID"); + } + if (oauthToken.empty()) { + errors.append("Missing OAuth Token"); + } + + if (errors.length() > 0) { + QMessageBox messageBox; + messageBox.setIcon(QMessageBox::Critical); + messageBox.setText(errors.join("
")); + messageBox.setStandardButtons(QMessageBox::Ok); + messageBox.exec(); + return; + } + + // QMessageBox messageBox; + // messageBox.setIcon(QMessageBox::Information); + // messageBox.setText("Successfully logged in with user " + + // qS(username) + "!"); + pajlada::Settings::Setting::set( + "/accounts/uid" + userID + "/username", username); + pajlada::Settings::Setting::set( + "/accounts/uid" + userID + "/userID", userID); + pajlada::Settings::Setting::set( + "/accounts/uid" + userID + "/clientID", clientID); + pajlada::Settings::Setting::set( + "/accounts/uid" + userID + "/oauthToken", oauthToken); + + getApp()->accounts->twitch.reloadUsers(); + + // messageBox.exec(); + + getApp()->accounts->twitch.currentUsername = username; } - if (username.empty()) { - errors.append("Missing username"); - } - if (clientID.empty()) { - errors.append("Missing Client ID"); - } - if (oauthToken.empty()) { - errors.append("Missing OAuth Token"); - } - - if (errors.length() > 0) { - QMessageBox messageBox; - messageBox.setIcon(QMessageBox::Critical); - messageBox.setText(errors.join("
")); - messageBox.setStandardButtons(QMessageBox::Ok); - messageBox.exec(); - return; - } - - // QMessageBox messageBox; - // messageBox.setIcon(QMessageBox::Information); - // messageBox.setText("Successfully logged in with user " + - // qS(username) + "!"); - pajlada::Settings::Setting::set( - "/accounts/uid" + userID + "/username", username); - pajlada::Settings::Setting::set( - "/accounts/uid" + userID + "/userID", userID); - pajlada::Settings::Setting::set( - "/accounts/uid" + userID + "/clientID", clientID); - pajlada::Settings::Setting::set( - "/accounts/uid" + userID + "/oauthToken", oauthToken); - - getApp()->accounts->twitch.reloadUsers(); - - // messageBox.exec(); - - getApp()->accounts->twitch.currentUsername = username; -} } // namespace diff --git a/src/widgets/helper/ChannelView.cpp b/src/widgets/helper/ChannelView.cpp index 467d34630..18139219e 100644 --- a/src/widgets/helper/ChannelView.cpp +++ b/src/widgets/helper/ChannelView.cpp @@ -39,62 +39,62 @@ namespace chatterino { namespace { -void addEmoteContextMenuItems(const Emote &emote, - MessageElementFlags creatorFlags, QMenu &menu) -{ - auto openAction = menu.addAction("Open"); - auto openMenu = new QMenu; - openAction->setMenu(openMenu); + void addEmoteContextMenuItems(const Emote &emote, + MessageElementFlags creatorFlags, QMenu &menu) + { + auto openAction = menu.addAction("Open"); + auto openMenu = new QMenu; + openAction->setMenu(openMenu); - auto copyAction = menu.addAction("Copy"); - auto copyMenu = new QMenu; - copyAction->setMenu(copyMenu); + auto copyAction = menu.addAction("Copy"); + auto copyMenu = new QMenu; + copyAction->setMenu(copyMenu); - // see if the QMenu actually gets destroyed - QObject::connect(openMenu, &QMenu::destroyed, [] { - QMessageBox(QMessageBox::Information, "xD", "the menu got deleted") - .exec(); - }); + // see if the QMenu actually gets destroyed + QObject::connect(openMenu, &QMenu::destroyed, [] { + QMessageBox(QMessageBox::Information, "xD", "the menu got deleted") + .exec(); + }); + + // Add copy and open links for 1x, 2x, 3x + auto addImageLink = [&](const ImagePtr &image, char scale) { + if (!image->isEmpty()) { + copyMenu->addAction( + QString(scale) + "x link", [url = image->url()] { + QApplication::clipboard()->setText(url.string); + }); + openMenu->addAction( + QString(scale) + "x link", [url = image->url()] { + QDesktopServices::openUrl(QUrl(url.string)); + }); + } + }; + + addImageLink(emote.images.getImage1(), '1'); + addImageLink(emote.images.getImage2(), '2'); + addImageLink(emote.images.getImage3(), '3'); + + // Copy and open emote page link + auto addPageLink = [&](const QString &name) { + copyMenu->addSeparator(); + openMenu->addSeparator(); - // Add copy and open links for 1x, 2x, 3x - auto addImageLink = [&](const ImagePtr &image, char scale) { - if (!image->isEmpty()) { copyMenu->addAction( - QString(scale) + "x link", [url = image->url()] { - QApplication::clipboard()->setText(url.string); + "Copy " + name + " emote link", [url = emote.homePage] { + QApplication::clipboard()->setText(url.string); // }); - openMenu->addAction(QString(scale) + "x link", - [url = image->url()] { - QDesktopServices::openUrl(QUrl(url.string)); - }); + openMenu->addAction( + "Open " + name + " emote link", [url = emote.homePage] { + QDesktopServices::openUrl(QUrl(url.string)); // + }); + }; + + if (creatorFlags.has(MessageElementFlag::BttvEmote)) { + addPageLink("BTTV"); + } else if (creatorFlags.has(MessageElementFlag::FfzEmote)) { + addPageLink("FFZ"); } - }; - - addImageLink(emote.images.getImage1(), '1'); - addImageLink(emote.images.getImage2(), '2'); - addImageLink(emote.images.getImage3(), '3'); - - // Copy and open emote page link - auto addPageLink = [&](const QString &name) { - copyMenu->addSeparator(); - openMenu->addSeparator(); - - copyMenu->addAction( - "Copy " + name + " emote link", [url = emote.homePage] { - QApplication::clipboard()->setText(url.string); // - }); - openMenu->addAction("Open " + name + " emote link", - [url = emote.homePage] { - QDesktopServices::openUrl(QUrl(url.string)); // - }); - }; - - if (creatorFlags.has(MessageElementFlag::BttvEmote)) { - addPageLink("BTTV"); - } else if (creatorFlags.has(MessageElementFlag::FfzEmote)) { - addPageLink("FFZ"); } -} } // namespace ChannelView::ChannelView(BaseWidget *parent) diff --git a/src/widgets/settingspages/ExternalToolsPage.cpp b/src/widgets/settingspages/ExternalToolsPage.cpp index bdb164e36..49204d9cb 100644 --- a/src/widgets/settingspages/ExternalToolsPage.cpp +++ b/src/widgets/settingspages/ExternalToolsPage.cpp @@ -9,15 +9,13 @@ "Choose", "Source", "High", "Medium", "Low", "Audio only" namespace chatterino { - namespace { - -QString CreateLink(const QString &url, const QString &name) -{ - return QString("" + - name + ""); -} - + QString createLink(const QString &url, const QString &name) + { + return QString("" + name + + ""); + } } // namespace ExternalToolsPage::ExternalToolsPage() @@ -41,8 +39,8 @@ ExternalToolsPage::ExternalToolsPage() description->setStyleSheet("color: #bbb"); auto links = new QLabel( - CreateLink("https://streamlink.github.io/", "Website") + " " + - CreateLink( + createLink("https://streamlink.github.io/", "Website") + " " + + createLink( "https://github.com/streamlink/streamlink/releases/latest", "Download")); links->setTextFormat(Qt::RichText); diff --git a/src/widgets/settingspages/IgnoresPage.cpp b/src/widgets/settingspages/IgnoresPage.cpp index 8aa6c5c4a..6691ee625 100644 --- a/src/widgets/settingspages/IgnoresPage.cpp +++ b/src/widgets/settingspages/IgnoresPage.cpp @@ -69,9 +69,8 @@ void addPhrasesTab(LayoutCreator layout) void addUsersTab(IgnoresPage &page, LayoutCreator users, QStringListModel &userModel) { - users.append( - page.createCheckBox("Enable twitch ignored users", - getSettings()->enableTwitchIgnoredUsers)); + users.append(page.createCheckBox("Enable twitch ignored users", + getSettings()->enableTwitchIgnoredUsers)); auto anyways = users.emplace().withoutMargin(); { diff --git a/src/widgets/settingspages/LookPage.cpp b/src/widgets/settingspages/LookPage.cpp index 5daec0464..4db671499 100644 --- a/src/widgets/settingspages/LookPage.cpp +++ b/src/widgets/settingspages/LookPage.cpp @@ -31,9 +31,9 @@ // clang-format on #ifdef USEWINSDK -#define WINDOW_TOPMOST "Window always on top" +# define WINDOW_TOPMOST "Window always on top" #else -#define WINDOW_TOPMOST "Window always on top (requires restart)" +# define WINDOW_TOPMOST "Window always on top (requires restart)" #endif #define INPUT_EMPTY "Show input box when empty" #define LAST_MSG "Mark the last message you read" diff --git a/src/widgets/settingspages/ModerationPage.cpp b/src/widgets/settingspages/ModerationPage.cpp index 28e0f7419..89d6b2411 100644 --- a/src/widgets/settingspages/ModerationPage.cpp +++ b/src/widgets/settingspages/ModerationPage.cpp @@ -25,7 +25,7 @@ namespace chatterino { -inline QString CreateLink(const QString &url, bool file = false) +inline QString createLink(const QString &url, bool file = false) { if (file) { return QString(" #ifdef USEWEBENGINE -#include "widgets/StreamView.hpp" +# include "widgets/StreamView.hpp" #endif namespace chatterino { namespace { -auto formatRoomMode(TwitchChannel &channel) -> QString -{ - QString text; - + auto formatRoomMode(TwitchChannel &channel) -> QString { - auto modes = channel.accessRoomModes(); + QString text; - if (modes->r9k) text += "r9k, "; - if (modes->slowMode) - text += QString("slow(%1), ").arg(QString::number(modes->slowMode)); - if (modes->emoteOnly) text += "emote, "; - if (modes->submode) text += "sub, "; + { + auto modes = channel.accessRoomModes(); + + if (modes->r9k) text += "r9k, "; + if (modes->slowMode) + text += + QString("slow(%1), ").arg(QString::number(modes->slowMode)); + if (modes->emoteOnly) text += "emote, "; + if (modes->submode) text += "sub, "; + } + + if (text.length() > 2) { + text = text.mid(0, text.size() - 2); + } + + if (!text.isEmpty()) { + static QRegularExpression commaReplacement("^(.+?, .+?,) (.+)$"); + + auto match = commaReplacement.match(text); + if (match.hasMatch()) + text = match.captured(1) + '\n' + match.captured(2); + } + + if (text.isEmpty() && channel.hasModRights()) return "none"; + + return text; } - - if (text.length() > 2) { - text = text.mid(0, text.size() - 2); + auto formatTooltip(const TwitchChannel::StreamStatus &s) + { + return QStringList{"", + "

", + s.title, + "

", + s.game, + "
", + s.rerun ? "Vod-casting" : "Live", + " for ", + s.uptime, + " with ", + QString::number(s.viewerCount), + " viewers", + "

"} + .join(""); } + auto formatTitle(const TwitchChannel::StreamStatus &s, Settings &settings) + { + auto title = QString(); - if (!text.isEmpty()) { - static QRegularExpression commaReplacement("^(.+?, .+?,) (.+)$"); + // live + if (s.rerun) + title += " (rerun)"; + else if (s.streamType.isEmpty()) + title += " (" + s.streamType + ")"; + else + title += " (live)"; - auto match = commaReplacement.match(text); - if (match.hasMatch()) - text = match.captured(1) + '\n' + match.captured(2); + // description + if (settings.showViewerCount) + title += " - " + QString::number(s.viewerCount); + if (settings.showTitle) title += " - " + s.title; + if (settings.showGame) title += " - " + s.game; + if (settings.showUptime) title += " - " + s.uptime; + + return title; } + auto distance(QPoint a, QPoint b) + { + auto x = std::abs(a.x() - b.x()); + auto y = std::abs(a.y() - b.y()); - if (text.isEmpty() && channel.hasModRights()) return "none"; - - return text; -} -auto formatTooltip(const TwitchChannel::StreamStatus &s) -{ - return QStringList{"", - "

", - s.title, - "

", - s.game, - "
", - s.rerun ? "Vod-casting" : "Live", - " for ", - s.uptime, - " with ", - QString::number(s.viewerCount), - " viewers", - "

"} - .join(""); -} -auto formatTitle(const TwitchChannel::StreamStatus &s, Settings &settings) -{ - auto title = QString(); - - // live - if (s.rerun) - title += " (rerun)"; - else if (s.streamType.isEmpty()) - title += " (" + s.streamType + ")"; - else - title += " (live)"; - - // description - if (settings.showViewerCount) - title += " - " + QString::number(s.viewerCount); - if (settings.showTitle) title += " - " + s.title; - if (settings.showGame) title += " - " + s.game; - if (settings.showUptime) title += " - " + s.uptime; - - return title; -} -auto distance(QPoint a, QPoint b) -{ - auto x = std::abs(a.x() - b.x()); - auto y = std::abs(a.y() - b.y()); - - return std::sqrt(x * x + y * y); -} + return std::sqrt(x * x + y * y); + } } // namespace SplitHeader::SplitHeader(Split *_split) From 5068c9a64e0e1ab0e7397808123bf263e9ed9f91 Mon Sep 17 00:00:00 2001 From: fourtf Date: Wed, 15 Aug 2018 23:48:16 +0200 Subject: [PATCH 13/14] Fixes #161 --- src/singletons/Settings.hpp | 2 ++ src/singletons/helper/GifTimer.cpp | 13 +++++++------ src/widgets/settingspages/LookPage.cpp | 3 +++ 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/singletons/Settings.hpp b/src/singletons/Settings.hpp index 28d0e43d3..8337786dc 100644 --- a/src/singletons/Settings.hpp +++ b/src/singletons/Settings.hpp @@ -25,6 +25,8 @@ public: /// Appearance BoolSetting showTimestamps = {"/appearance/messages/showTimestamps", true}; + BoolSetting enableAnimationsWhenFocused = { + "/appearance/enableAnimationsWhenFocused", false}; QStringSetting timestampFormat = {"/appearance/messages/timestampFormat", "h:mm"}; BoolSetting showBadges = {"/appearance/messages/showBadges", true}; diff --git a/src/singletons/helper/GifTimer.cpp b/src/singletons/helper/GifTimer.cpp index 8ef657e7a..8f3624523 100644 --- a/src/singletons/helper/GifTimer.cpp +++ b/src/singletons/helper/GifTimer.cpp @@ -11,18 +11,19 @@ void GIFTimer::initialize() this->timer.setInterval(30); getSettings()->enableGifAnimations.connect([this](bool enabled, auto) { - if (enabled) { + if (enabled) this->timer.start(); - } else { + else this->timer.stop(); - } }); QObject::connect(&this->timer, &QTimer::timeout, [this] { + if (getSettings()->enableAnimationsWhenFocused && + qApp->activeWindow() == nullptr) + return; + this->signal.invoke(); - // fourtf: - auto app = getApp(); - app->windows->repaintGifEmotes(); + getApp()->windows->repaintGifEmotes(); }); } diff --git a/src/widgets/settingspages/LookPage.cpp b/src/widgets/settingspages/LookPage.cpp index 4db671499..eb2a9ff1c 100644 --- a/src/widgets/settingspages/LookPage.cpp +++ b/src/widgets/settingspages/LookPage.cpp @@ -218,6 +218,9 @@ void LookPage::addEmoteTab(LayoutCreator layout) */ layout.append( this->createCheckBox("Animations", getSettings()->enableGifAnimations)); + layout.append( + this->createCheckBox("Animations only when chatterino has focus", + getSettings()->enableAnimationsWhenFocused)); auto scaleBox = layout.emplace().withoutMargin(); { From 8bcc9c487bfaf9de9ffa8c037e881adcc0e27d3c Mon Sep 17 00:00:00 2001 From: fourtf Date: Thu, 16 Aug 2018 00:16:33 +0200 Subject: [PATCH 14/14] Fixes #411, #516 --- src/common/Common.hpp | 5 ++++ src/messages/layouts/MessageLayout.cpp | 5 ++-- src/messages/layouts/MessageLayout.hpp | 4 ++- .../layouts/MessageLayoutContainer.cpp | 28 ++++++++++++------- .../layouts/MessageLayoutContainer.hpp | 3 +- src/providers/twitch/TwitchMessageBuilder.cpp | 10 +++---- src/widgets/helper/ChannelView.cpp | 13 +++++---- 7 files changed, 42 insertions(+), 26 deletions(-) diff --git a/src/common/Common.hpp b/src/common/Common.hpp index 46de4a7cb..7f22bf27d 100644 --- a/src/common/Common.hpp +++ b/src/common/Common.hpp @@ -41,4 +41,9 @@ std::weak_ptr weakOf(T *element) struct Message; using MessagePtr = std::shared_ptr; +enum class CopyMode { + Everything, + OnlyTextAndEmotes, +}; + } // namespace chatterino diff --git a/src/messages/layouts/MessageLayout.cpp b/src/messages/layouts/MessageLayout.cpp index c7ff02af9..5fbbe0bfa 100644 --- a/src/messages/layouts/MessageLayout.cpp +++ b/src/messages/layouts/MessageLayout.cpp @@ -284,9 +284,10 @@ int MessageLayout::getSelectionIndex(QPoint position) return this->container_->getSelectionIndex(position); } -void MessageLayout::addSelectionText(QString &str, int from, int to) +void MessageLayout::addSelectionText(QString &str, int from, int to, + CopyMode copymode) { - this->container_->addSelectionText(str, from, to); + this->container_->addSelectionText(str, from, to, copymode); } } // namespace chatterino diff --git a/src/messages/layouts/MessageLayout.hpp b/src/messages/layouts/MessageLayout.hpp index 2ab015856..671d30668 100644 --- a/src/messages/layouts/MessageLayout.hpp +++ b/src/messages/layouts/MessageLayout.hpp @@ -1,5 +1,6 @@ #pragma once +#include "common/Common.hpp" #include "common/FlagsEnum.hpp" #include @@ -54,7 +55,8 @@ public: const MessageLayoutElement *getElementAt(QPoint point); int getLastCharacterIndex() const; int getSelectionIndex(QPoint position); - void addSelectionText(QString &str, int from = 0, int to = INT_MAX); + void addSelectionText(QString &str, int from = 0, int to = INT_MAX, + CopyMode copymode = CopyMode::Everything); // Misc bool isDisabled() const; diff --git a/src/messages/layouts/MessageLayoutContainer.cpp b/src/messages/layouts/MessageLayoutContainer.cpp index 008a02d05..0aef73c6b 100644 --- a/src/messages/layouts/MessageLayoutContainer.cpp +++ b/src/messages/layouts/MessageLayoutContainer.cpp @@ -505,33 +505,41 @@ int MessageLayoutContainer::getLastCharacterIndex() const return this->lines_.back().endCharIndex; } -void MessageLayoutContainer::addSelectionText(QString &str, int from, int to) +void MessageLayoutContainer::addSelectionText(QString &str, int from, int to, + CopyMode copymode) { int index = 0; bool first = true; - for (std::unique_ptr &ele : this->elements_) { - int c = ele->getSelectionIndexCount(); + for (auto &element : this->elements_) { + if (copymode == CopyMode::OnlyTextAndEmotes) { + if (element->getCreator().getFlags().hasAny( + {MessageElementFlag::Timestamp, + MessageElementFlag::Username, MessageElementFlag::Badges})) + continue; + } + + auto indexCount = element->getSelectionIndexCount(); if (first) { - if (index + c > from) { - ele->addCopyTextToString(str, from - index, to - index); + if (index + indexCount > from) { + element->addCopyTextToString(str, from - index, to - index); first = false; - if (index + c > to) { + if (index + indexCount > to) { break; } } } else { - if (index + c > to) { - ele->addCopyTextToString(str, 0, to - index); + if (index + indexCount > to) { + element->addCopyTextToString(str, 0, to - index); break; } else { - ele->addCopyTextToString(str); + element->addCopyTextToString(str); } } - index += c; + index += indexCount; } } diff --git a/src/messages/layouts/MessageLayoutContainer.hpp b/src/messages/layouts/MessageLayoutContainer.hpp index cab849ed0..669986196 100644 --- a/src/messages/layouts/MessageLayoutContainer.hpp +++ b/src/messages/layouts/MessageLayoutContainer.hpp @@ -5,6 +5,7 @@ #include #include +#include "common/Common.hpp" #include "common/FlagsEnum.hpp" #include "messages/Selection.hpp" #include "messages/layouts/MessageLayoutElement.hpp" @@ -74,7 +75,7 @@ struct MessageLayoutContainer { // selection int getSelectionIndex(QPoint point); int getLastCharacterIndex() const; - void addSelectionText(QString &str, int from, int to); + void addSelectionText(QString &str, int from, int to, CopyMode copymode); bool isCollapsed(); diff --git a/src/providers/twitch/TwitchMessageBuilder.cpp b/src/providers/twitch/TwitchMessageBuilder.cpp index 26ea07dec..ca04e7e86 100644 --- a/src/providers/twitch/TwitchMessageBuilder.cpp +++ b/src/providers/twitch/TwitchMessageBuilder.cpp @@ -83,8 +83,6 @@ bool TwitchMessageBuilder::isIgnored() const MessagePtr TwitchMessageBuilder::build() { - auto app = getApp(); - // PARSING this->parseUsername(); @@ -437,7 +435,7 @@ void TwitchMessageBuilder::appendUsername() // IrcManager::getInstance().getUser().getUserName(); } else if (this->args.isReceivedWhisper) { // Sender username - this->emplace(usernameText, MessageElementFlag::Text, + this->emplace(usernameText, MessageElementFlag::Username, this->usernameColor_, FontStyle::ChatMediumBold) ->setLink({Link::UserInfo, this->userName}); @@ -445,7 +443,7 @@ void TwitchMessageBuilder::appendUsername() auto currentUser = app->accounts->twitch.getCurrent(); // Separator - this->emplace("->", MessageElementFlag::Text, + this->emplace("->", MessageElementFlag::Username, app->themes->messages.textColors.system, FontStyle::ChatMedium); @@ -456,14 +454,14 @@ void TwitchMessageBuilder::appendUsername() // Your own username this->emplace(currentUser->getUserName() + ":", - MessageElementFlag::Text, selfColor, + MessageElementFlag::Username, selfColor, FontStyle::ChatMediumBold); } else { if (!this->action_) { usernameText += ":"; } - this->emplace(usernameText, MessageElementFlag::Text, + this->emplace(usernameText, MessageElementFlag::Username, this->usernameColor_, FontStyle::ChatMediumBold) ->setLink({Link::UserInfo, this->userName}); diff --git a/src/widgets/helper/ChannelView.cpp b/src/widgets/helper/ChannelView.cpp index 18139219e..2afc42e75 100644 --- a/src/widgets/helper/ChannelView.cpp +++ b/src/widgets/helper/ChannelView.cpp @@ -1088,17 +1088,18 @@ void ChannelView::addContextMenuItems( menu->addAction("Copy message", [layout] { QString copyString; - layout->addSelectionText(copyString); + layout->addSelectionText(copyString, 0, INT_MAX, + CopyMode::OnlyTextAndEmotes); QGuiApplication::clipboard()->setText(copyString); }); - // menu->addAction("Quote message", [layout] { - // QString copyString; - // layout->addSelectionText(copyString); + menu->addAction("Copy full message", [layout] { + QString copyString; + layout->addSelectionText(copyString); - // // insert into input - // }); + QGuiApplication::clipboard()->setText(copyString); + }); menu->popup(QCursor::pos()); menu->raise();