From ae26b835b6476ee720f273bba4f4f7fbc7d353ea Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Fri, 27 Apr 2018 22:11:19 +0200 Subject: [PATCH] Perform initial refactoring work Things that were once singletons are no longer singletons, but are instead stored in the "Application" singleton Some singletons still remain, and some renaming/renamespacing is left --- src/application.cpp | 176 ++++++++++++++---- src/application.hpp | 49 ++++- src/channel.cpp | 5 +- src/main.cpp | 90 ++------- src/messages/image.cpp | 9 +- src/messages/layouts/messagelayout.cpp | 32 ++-- .../layouts/messagelayoutcontainer.cpp | 5 +- src/messages/layouts/messagelayoutelement.cpp | 5 +- src/messages/messageelement.cpp | 23 +-- src/providers/twitch/ircmessagehandler.cpp | 8 +- src/providers/twitch/twitchchannel.cpp | 37 ++-- src/providers/twitch/twitchmessagebuilder.cpp | 68 ++++--- src/providers/twitch/twitchserver.cpp | 5 +- src/singletons/accountmanager.cpp | 25 --- src/singletons/accountmanager.hpp | 5 +- src/singletons/commandmanager.cpp | 18 +- src/singletons/commandmanager.hpp | 6 +- src/singletons/emotemanager.cpp | 26 ++- src/singletons/emotemanager.hpp | 5 +- src/singletons/helper/pubsubhelpers.cpp | 2 - src/singletons/loggingmanager.cpp | 26 ++- src/singletons/loggingmanager.hpp | 13 +- src/singletons/nativemessagingmanager.cpp | 14 +- src/singletons/nativemessagingmanager.hpp | 3 +- src/singletons/pathmanager.cpp | 42 +---- src/singletons/pathmanager.hpp | 7 +- src/singletons/pubsubmanager.cpp | 6 - src/singletons/pubsubmanager.hpp | 5 +- src/singletons/settingsmanager.cpp | 16 +- src/singletons/settingsmanager.hpp | 20 +- src/singletons/thememanager.cpp | 10 +- src/singletons/thememanager.hpp | 3 +- src/singletons/windowmanager.cpp | 23 ++- src/singletons/windowmanager.hpp | 9 +- src/util/completionmodel.cpp | 15 +- src/util/networkrequest.cpp | 6 +- src/util/networkrequest.hpp | 5 +- src/util/streamlink.cpp | 18 +- src/util/urlfetch.hpp | 6 +- src/widgets/accountpopup.cpp | 31 ++- src/widgets/accountswitchwidget.cpp | 20 +- src/widgets/attachedwindow.cpp | 4 +- src/widgets/basewidget.cpp | 17 +- src/widgets/basewidget.hpp | 8 +- src/widgets/basewindow.cpp | 34 ++-- src/widgets/basewindow.hpp | 3 - src/widgets/emotepopup.cpp | 23 +-- src/widgets/emotepopup.hpp | 2 +- src/widgets/helper/channelview.cpp | 75 +++++--- src/widgets/helper/droppreview.cpp | 2 +- src/widgets/helper/notebookbutton.cpp | 10 +- src/widgets/helper/notebooktab.cpp | 68 ++++--- src/widgets/helper/rippleeffectbutton.cpp | 2 +- src/widgets/helper/splitheader.cpp | 6 +- src/widgets/helper/splitinput.cpp | 31 +-- src/widgets/helper/titlebarbutton.cpp | 6 +- src/widgets/logindialog.cpp | 2 +- src/widgets/notebook.cpp | 36 ++-- src/widgets/scrollbar.cpp | 21 ++- src/widgets/scrollbar.hpp | 2 - src/widgets/selectchanneldialog.cpp | 2 +- src/widgets/settingsdialog.cpp | 8 +- src/widgets/settingspages/accountspage.cpp | 9 +- src/widgets/settingspages/appearancepage.cpp | 54 +++--- src/widgets/settingspages/behaviourpage.cpp | 30 +-- src/widgets/settingspages/commandpage.cpp | 19 +- .../settingspages/externaltoolspage.cpp | 15 +- .../settingspages/highlightingpage.cpp | 85 ++++----- .../settingspages/ignoremessagespage.cpp | 9 +- src/widgets/settingspages/ignoreuserspage.cpp | 8 +- src/widgets/settingspages/logspage.cpp | 10 +- src/widgets/settingspages/moderationpage.cpp | 22 +-- .../settingspages/specialchannelspage.cpp | 4 +- src/widgets/split.cpp | 37 ++-- src/widgets/split.hpp | 6 +- src/widgets/splitcontainer.cpp | 12 +- src/widgets/window.cpp | 42 +++-- src/widgets/window.hpp | 2 +- 78 files changed, 850 insertions(+), 773 deletions(-) diff --git a/src/application.cpp b/src/application.cpp index 370a1e32d..9ace0cd32 100644 --- a/src/application.cpp +++ b/src/application.cpp @@ -1,4 +1,5 @@ #include "application.hpp" + #include "providers/twitch/twitchserver.hpp" #include "singletons/accountmanager.hpp" #include "singletons/commandmanager.hpp" @@ -12,60 +13,114 @@ #include "singletons/windowmanager.hpp" #include "util/posttothread.hpp" +#include + +#ifdef Q_OS_WIN +#include +#include +#include +#endif + using namespace chatterino::singletons; namespace chatterino { +namespace { + +bool isBigEndian() +{ + int test = 1; + char *p = (char *)&test; + + return p[0] == 0; +} + +} // namespace + +static std::atomic isAppConstructed{false}; +static std::atomic isAppInitialized{false}; + +static Application *staticApp = nullptr; + // this class is responsible for handling the workflow of Chatterino // It will create the instances of the major classes, and connect their signals to each other -Application::Application() +Application::Application(int _argc, char **_argv) + : argc(_argc) + , argv(_argv) { - singletons::NativeMessagingManager::getInstance().registerHost(); +} - singletons::WindowManager::getInstance(); +void Application::construct() +{ + assert(isAppConstructed == false); + isAppConstructed = true; - singletons::LoggingManager::getInstance(); + // 1. Instantiate all classes + this->paths = new singletons::PathManager(argc, argv); + this->themes = new singletons::ThemeManager; + this->windows = new singletons::WindowManager; + this->logging = new singletons::LoggingManager; + this->commands = new singletons::CommandManager; + this->accounts = new singletons::AccountManager; + this->emotes = new singletons::EmoteManager; + this->pubsub = new singletons::PubSubManager; + this->settings = new singletons::SettingManager; +} - singletons::SettingManager::getInstance().initialize(); - singletons::CommandManager::getInstance().loadCommands(); +void Application::instantiate(int argc, char **argv) +{ + assert(staticApp == nullptr); - singletons::WindowManager::getInstance().initialize(); + staticApp = new Application(argc, argv); +} + +void Application::initialize() +{ + assert(isAppInitialized == false); + isAppInitialized = true; + + // 2. Initialize/load classes + this->windows->initialize(); + + this->nativeMessaging->registerHost(); + + this->settings->initialize(); + this->commands->loadCommands(); // Initialize everything we need - singletons::EmoteManager::getInstance().loadGlobalEmotes(); + this->emotes->loadGlobalEmotes(); - singletons::AccountManager::getInstance().load(); + this->accounts->load(); // XXX - singletons::SettingManager::getInstance().updateWordTypeMask(); + this->settings->updateWordTypeMask(); - singletons::NativeMessagingManager::getInstance().openGuiMessageQueue(); - auto &pubsub = singletons::PubSubManager::getInstance(); + this->nativeMessaging->openGuiMessageQueue(); - pubsub.sig.whisper.sent.connect([](const auto &msg) { + this->pubsub->sig.whisper.sent.connect([](const auto &msg) { debug::Log("WHISPER SENT LOL"); // }); - pubsub.sig.whisper.received.connect([](const auto &msg) { + this->pubsub->sig.whisper.received.connect([](const auto &msg) { debug::Log("WHISPER RECEIVED LOL"); // }); - pubsub.sig.moderation.chatCleared.connect([&](const auto &action) { + this->pubsub->sig.moderation.chatCleared.connect([&](const auto &action) { debug::Log("Chat cleared by {}", action.source.name); // }); - pubsub.sig.moderation.modeChanged.connect([&](const auto &action) { + this->pubsub->sig.moderation.modeChanged.connect([&](const auto &action) { debug::Log("Mode {} was turned {} by {} (duration {})", (int &)action.mode, (bool &)action.state, action.source.name, action.args.duration); }); - pubsub.sig.moderation.moderationStateChanged.connect([&](const auto &action) { + this->pubsub->sig.moderation.moderationStateChanged.connect([&](const auto &action) { debug::Log("User {} was {} by {}", action.target.id, action.modded ? "modded" : "unmodded", action.source.name); }); - pubsub.sig.moderation.userBanned.connect([&](const auto &action) { + this->pubsub->sig.moderation.userBanned.connect([&](const auto &action) { auto &server = providers::twitch::TwitchServer::getInstance(); auto chan = server.getChannelOrEmptyByID(action.roomID); @@ -78,7 +133,7 @@ Application::Application() util::postToThread([chan, msg] { chan->addMessage(msg); }); }); - pubsub.sig.moderation.userUnbanned.connect([&](const auto &action) { + this->pubsub->sig.moderation.userUnbanned.connect([&](const auto &action) { auto &server = providers::twitch::TwitchServer::getInstance(); auto chan = server.getChannelOrEmptyByID(action.roomID); @@ -91,44 +146,95 @@ Application::Application() util::postToThread([chan, msg] { chan->addMessage(msg); }); }); - auto &accountManager = singletons::AccountManager::getInstance(); + this->pubsub->Start(); - pubsub.Start(); - - auto RequestModerationActions = [&]() { - pubsub.UnlistenAllModerationActions(); + auto RequestModerationActions = [=]() { + this->pubsub->UnlistenAllModerationActions(); // TODO(pajlada): Unlisten to all authed topics instead of only moderation topics - // pubsub.UnlistenAllAuthedTopics(); + // this->pubsub->UnlistenAllAuthedTopics(); - pubsub.ListenToWhispers(singletons::AccountManager::getInstance().Twitch.getCurrent()); // + this->pubsub->ListenToWhispers(this->accounts->Twitch.getCurrent()); // }; - accountManager.Twitch.userChanged.connect(RequestModerationActions); + this->accounts->Twitch.userChanged.connect(RequestModerationActions); RequestModerationActions(); } -Application::~Application() -{ - this->save(); -} - int Application::run(QApplication &qtApp) { // Start connecting to the IRC Servers (Twitch only for now) providers::twitch::TwitchServer::getInstance().connect(); // Show main window - singletons::WindowManager::getInstance().getMainWindow().show(); + this->windows->getMainWindow().show(); return qtApp.exec(); } void Application::save() { - singletons::WindowManager::getInstance().save(); + this->windows->save(); - singletons::CommandManager::getInstance().saveCommands(); + this->commands->saveCommands(); +} + +void Application::runNativeMessagingHost() +{ + auto app = getApp(); + + app->nativeMessaging = new singletons::NativeMessagingManager; + +#ifdef Q_OS_WIN + _setmode(_fileno(stdin), _O_BINARY); + _setmode(_fileno(stdout), _O_BINARY); +#endif + +#if 0 + bool bigEndian = isBigEndian(); +#endif + + while (true) { + char size_c[4]; + std::cin.read(size_c, 4); + + if (std::cin.eof()) { + break; + } + + uint32_t size = *reinterpret_cast(size_c); +#if 0 + // To avoid breaking strict-aliasing rules and potentially inducing undefined behaviour, the following code can be run instead + uint32_t size = 0; + if (bigEndian) { + size = size_c[3] | static_cast(size_c[2]) << 8 | + static_cast(size_c[1]) << 16 | static_cast(size_c[0]) << 24; + } else { + size = size_c[0] | static_cast(size_c[1]) << 8 | + static_cast(size_c[2]) << 16 | static_cast(size_c[3]) << 24; + } +#endif + + char *b = (char *)malloc(size + 1); + std::cin.read(b, size); + *(b + size) = '\0'; + + app->nativeMessaging->sendToGuiProcess(QByteArray(b, size)); + + free(b); + } +} + +Application *getApp() +{ + assert(staticApp != nullptr); + + return staticApp; +} + +bool appInitialized() +{ + return isAppInitialized; } } // namespace chatterino diff --git a/src/application.hpp b/src/application.hpp index 66c9c0135..17767dc27 100644 --- a/src/application.hpp +++ b/src/application.hpp @@ -7,16 +7,59 @@ namespace chatterino { +namespace singletons { + +class ThemeManager; +class WindowManager; +class LoggingManager; +class PathManager; +class CommandManager; +class AccountManager; +class EmoteManager; +class PubSubManager; +class NativeMessagingManager; +class SettingManager; + +} // namespace singletons + class Application { + Application(int _argc, char **_argv); + public: - Application(); - ~Application(); + static void instantiate(int argc, char **argv); + + ~Application() = delete; + + void construct(); + void initialize(); + void load(); int run(QApplication &qtApp); -private: + singletons::PathManager *paths = nullptr; + singletons::ThemeManager *themes = nullptr; + singletons::WindowManager *windows = nullptr; + singletons::LoggingManager *logging = nullptr; + singletons::CommandManager *commands = nullptr; + singletons::AccountManager *accounts = nullptr; + singletons::EmoteManager *emotes = nullptr; + singletons::PubSubManager *pubsub = nullptr; + singletons::NativeMessagingManager *nativeMessaging = nullptr; + singletons::SettingManager *settings = nullptr; + void save(); + + // Special application mode that only initializes the native messaging host + static void runNativeMessagingHost(); + +private: + int argc; + char **argv; }; +Application *getApp(); + +bool appInitialized(); + } // namespace chatterino diff --git a/src/channel.cpp b/src/channel.cpp index be679a9f7..c98ed6e13 100644 --- a/src/channel.cpp +++ b/src/channel.cpp @@ -1,4 +1,6 @@ #include "channel.hpp" + +#include "application.hpp" #include "debug/log.hpp" #include "messages/message.hpp" #include "singletons/emotemanager.hpp" @@ -55,6 +57,7 @@ messages::LimitedQueueSnapshot Channel::getMessageSnapshot void Channel::addMessage(MessagePtr message) { + auto app = getApp(); MessagePtr deleted; bool isTimeout = (message->flags & Message::Timeout) != 0; @@ -67,7 +70,7 @@ void Channel::addMessage(MessagePtr message) } } - singletons::LoggingManager::getInstance().addMessage(this->name, message); + app->logging->addMessage(this->name, message); if (isTimeout) { LimitedQueueSnapshot snapshot = this->getMessageSnapshot(); diff --git a/src/main.cpp b/src/main.cpp index fb9fd648a..3c372094f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -17,21 +17,6 @@ #include #include -#ifdef Q_OS_WIN -#include -#include -#include -#endif - -bool isBigEndian() -{ - int test = 1; - char *p = (char *)&test; - - return p[0] == 0; -} - -void runNativeMessagingHost(); int runGui(int argc, char *argv[]); int main(int argc, char *argv[]) @@ -45,7 +30,7 @@ int main(int argc, char *argv[]) // TODO: can be any argument if (args.size() > 0 && args[0].startsWith("chrome-extension://")) { - runNativeMessagingHost(); + chatterino::Application::runNativeMessagingHost(); return 0; } @@ -67,18 +52,17 @@ int runGui(int argc, char *argv[]) a.installNativeEventFilter(new chatterino::util::DpiNativeEventFilter); #endif - // Initialize settings - bool success = chatterino::singletons::PathManager::getInstance().init(argc, argv); - if (!success) { - printf("Error initializing paths\n"); - return 1; - } - // Initialize NetworkManager chatterino::util::NetworkManager::init(); + // Initialize application + chatterino::Application::instantiate(argc, argv); + auto app = chatterino::getApp(); + + app->construct(); + + auto &pathMan = *app->paths; // Running file - auto &pathMan = chatterino::singletons::PathManager::getInstance(); auto runningPath = pathMan.settingsFolderPath + "/running_" + pathMan.appPathHash; if (QFile::exists(runningPath)) { @@ -94,16 +78,14 @@ int runGui(int argc, char *argv[]) runningFile.close(); } - // Application - { - // Initialize application - chatterino::Application app; + app->initialize(); - // Start the application - app.run(a); + // Start the application + // This is a blocking call + app->run(a); - // Application will go out of scope here and deinitialize itself - } + // We have finished our application, make sure we save stuff + app->save(); // Running file QFile::remove(runningPath); @@ -116,47 +98,3 @@ int runGui(int argc, char *argv[]) _exit(0); } - -void runNativeMessagingHost() -{ -#ifdef Q_OS_WIN - _setmode(_fileno(stdin), _O_BINARY); - _setmode(_fileno(stdout), _O_BINARY); -#endif - - auto &nmm = chatterino::singletons::NativeMessagingManager::getInstance(); - -#if 0 - bool bigEndian = isBigEndian(); -#endif - - while (true) { - char size_c[4]; - std::cin.read(size_c, 4); - - if (std::cin.eof()) { - break; - } - - uint32_t size = *reinterpret_cast(size_c); -#if 0 - // To avoid breaking strict-aliasing rules and potentially inducing undefined behaviour, the following code can be run instead - uint32_t size = 0; - if (bigEndian) { - size = size_c[3] | static_cast(size_c[2]) << 8 | - static_cast(size_c[1]) << 16 | static_cast(size_c[0]) << 24; - } else { - size = size_c[0] | static_cast(size_c[1]) << 8 | - static_cast(size_c[2]) << 16 | static_cast(size_c[3]) << 24; - } -#endif - - char *b = (char *)malloc(size + 1); - std::cin.read(b, size); - *(b + size) = '\0'; - - nmm.sendToGuiProcess(QByteArray(b, size)); - - free(b); - } -} diff --git a/src/messages/image.cpp b/src/messages/image.cpp index d12e2eaff..aec60a572 100644 --- a/src/messages/image.cpp +++ b/src/messages/image.cpp @@ -1,4 +1,6 @@ #include "messages/image.hpp" + +#include "application.hpp" #include "singletons/emotemanager.hpp" #include "singletons/ircmanager.hpp" #include "singletons/windowmanager.hpp" @@ -123,7 +125,7 @@ void Image::loadImage() if (this->allFrames.size() > 1) { if (!this->animated) { util::postToThread([this] { - singletons::EmoteManager::getInstance().getGifUpdateSignal().connect([=]() { + getApp()->emotes->getGifUpdateSignal().connect([=]() { this->gifUpdateTimout(); }); // For some reason when Boost signal is in // thread scope and thread deletes the signal @@ -145,9 +147,10 @@ void Image::loadImage() loadedEventQueued = true; QTimer::singleShot(500, [] { - singletons::EmoteManager::getInstance().incGeneration(); + getApp()->emotes->incGeneration(); - singletons::WindowManager::getInstance().layoutVisibleChatWidgets(); + auto app = getApp(); + app->windows->layoutVisibleChatWidgets(); loadedEventQueued = false; }); } diff --git a/src/messages/layouts/messagelayout.cpp b/src/messages/layouts/messagelayout.cpp index 025ffaea6..06d95c904 100644 --- a/src/messages/layouts/messagelayout.cpp +++ b/src/messages/layouts/messagelayout.cpp @@ -1,4 +1,6 @@ #include "messages/layouts/messagelayout.hpp" + +#include "application.hpp" #include "singletons/emotemanager.hpp" #include "singletons/settingsmanager.hpp" @@ -45,7 +47,7 @@ int MessageLayout::getHeight() const // return true if redraw is required bool MessageLayout::layout(int width, float scale, MessageElement::Flags flags) { - auto &emoteManager = singletons::EmoteManager::getInstance(); + auto app = getApp(); bool layoutRequired = false; @@ -55,9 +57,9 @@ bool MessageLayout::layout(int width, float scale, MessageElement::Flags flags) this->currentLayoutWidth = width; // check if emotes changed - bool imagesChanged = this->emoteGeneration != emoteManager.getGeneration(); + bool imagesChanged = this->emoteGeneration != app->emotes->getGeneration(); layoutRequired |= imagesChanged; - this->emoteGeneration = emoteManager.getGeneration(); + this->emoteGeneration = app->emotes->getGeneration(); // check if text changed bool textChanged = @@ -66,14 +68,12 @@ bool MessageLayout::layout(int width, float scale, MessageElement::Flags flags) this->fontGeneration = singletons::FontManager::getInstance().getGeneration(); // check if work mask changed - bool wordMaskChanged = this->currentWordFlags != - flags; // singletons::SettingManager::getInstance().getWordTypeMask(); + bool wordMaskChanged = this->currentWordFlags != flags; // app->settings->getWordTypeMask(); layoutRequired |= wordMaskChanged; - this->currentWordFlags = flags; // singletons::SettingManager::getInstance().getWordTypeMask(); + this->currentWordFlags = flags; // app->settings->getWordTypeMask(); // check if timestamp format changed - bool timestampFormatChanged = - this->timestampFormat != singletons::SettingManager::getInstance().timestampFormat; + bool timestampFormatChanged = this->timestampFormat != app->settings->timestampFormat; layoutRequired |= timestampFormatChanged; @@ -128,8 +128,8 @@ void MessageLayout::actuallyLayout(int width, MessageElement::Flags flags) void MessageLayout::paint(QPainter &painter, int y, int messageIndex, Selection &selection, bool isLastReadMessage, bool isWindowFocused) { + auto app = getApp(); QPixmap *pixmap = this->buffer.get(); - singletons::ThemeManager &themeManager = singletons::ThemeManager::getInstance(); // create new buffer if required if (!pixmap) { @@ -160,7 +160,8 @@ void MessageLayout::paint(QPainter &painter, int y, int messageIndex, Selection // draw disabled if (this->message->flags.HasFlag(Message::Disabled)) { - painter.fillRect(0, y, pixmap->width(), pixmap->height(), themeManager.messages.disabled); + painter.fillRect(0, y, pixmap->width(), pixmap->height(), + app->themes->messages.disabled); } // draw selection @@ -170,8 +171,9 @@ void MessageLayout::paint(QPainter &painter, int y, int messageIndex, Selection // draw last read message line if (isLastReadMessage) { - QColor color = isWindowFocused ? themeManager.tabs.selected.backgrounds.regular.color() - : themeManager.tabs.selected.backgrounds.unfocused.color(); + QColor color = isWindowFocused + ? app->themes->tabs.selected.backgrounds.regular.color() + : app->themes->tabs.selected.backgrounds.unfocused.color(); QBrush brush(color, Qt::VerPattern); @@ -184,7 +186,7 @@ void MessageLayout::paint(QPainter &painter, int y, int messageIndex, Selection void MessageLayout::updateBuffer(QPixmap *buffer, int messageIndex, Selection &selection) { - singletons::ThemeManager &themeManager = singletons::ThemeManager::getInstance(); + auto app = getApp(); QPainter painter(buffer); @@ -192,8 +194,8 @@ void MessageLayout::updateBuffer(QPixmap *buffer, int messageIndex, Selection &s // draw background painter.fillRect(buffer->rect(), this->message->flags & Message::Highlighted - ? themeManager.messages.backgrounds.highlighted - : themeManager.messages.backgrounds.regular); + ? app->themes->messages.backgrounds.highlighted + : app->themes->messages.backgrounds.regular); // draw message this->container.paintElements(painter); diff --git a/src/messages/layouts/messagelayoutcontainer.cpp b/src/messages/layouts/messagelayoutcontainer.cpp index 52fd29323..dbb1ee9c1 100644 --- a/src/messages/layouts/messagelayoutcontainer.cpp +++ b/src/messages/layouts/messagelayoutcontainer.cpp @@ -1,5 +1,6 @@ #include "messagelayoutcontainer.hpp" +#include "application.hpp" #include "messagelayoutelement.hpp" #include "messages/selection.hpp" #include "singletons/settingsmanager.hpp" @@ -210,8 +211,8 @@ void MessageLayoutContainer::paintAnimatedElements(QPainter &painter, int yOffse void MessageLayoutContainer::paintSelection(QPainter &painter, int messageIndex, Selection &selection, int yOffset) { - singletons::ThemeManager &themeManager = singletons::ThemeManager::getInstance(); - QColor selectionColor = themeManager.messages.selection; + auto app = getApp(); + QColor selectionColor = app->themes->messages.selection; // don't draw anything if (selection.selectionMin.messageIndex > messageIndex || diff --git a/src/messages/layouts/messagelayoutelement.cpp b/src/messages/layouts/messagelayoutelement.cpp index 61b501176..5f9f5a2b0 100644 --- a/src/messages/layouts/messagelayoutelement.cpp +++ b/src/messages/layouts/messagelayoutelement.cpp @@ -1,4 +1,5 @@ #include "messages/layouts/messagelayoutelement.hpp" +#include "application.hpp" #include "messages/messageelement.hpp" #include "util/debugcount.hpp" @@ -239,9 +240,11 @@ int TextIconLayoutElement::getSelectionIndexCount() void TextIconLayoutElement::paint(QPainter &painter) { + auto app = getApp(); + QFont font = singletons::FontManager::getInstance().getFont(FontStyle::Tiny, this->scale); - painter.setPen(singletons::ThemeManager::getInstance().messages.textColors.system); + painter.setPen(app->themes->messages.textColors.system); painter.setFont(font); QTextOption option; diff --git a/src/messages/messageelement.cpp b/src/messages/messageelement.cpp index f101738f0..63c8281d1 100644 --- a/src/messages/messageelement.cpp +++ b/src/messages/messageelement.cpp @@ -1,4 +1,6 @@ #include "messages/messageelement.hpp" + +#include "application.hpp" #include "messages/layouts/messagelayoutcontainer.hpp" #include "messages/layouts/messagelayoutelement.hpp" #include "singletons/settingsmanager.hpp" @@ -95,7 +97,7 @@ void EmoteElement::addToContainer(MessageLayoutContainer &container, MessageElem return; } - int quality = singletons::SettingManager::getInstance().preferredEmoteQuality; + int quality = getApp()->settings->preferredEmoteQuality; Image *_image; if (quality == 3 && this->data.image3x != nullptr) { @@ -134,16 +136,16 @@ TextElement::TextElement(const QString &text, MessageElement::Flags flags, void TextElement::addToContainer(MessageLayoutContainer &container, MessageElement::Flags _flags) { + auto app = getApp(); + if (_flags & this->getFlags()) { QFontMetrics &metrics = singletons::FontManager::getInstance().getFontMetrics( this->style, container.getScale()); - singletons::ThemeManager &themeManager = - singletons::ThemeManager::ThemeManager::getInstance(); for (Word &word : this->words) { auto getTextLayoutElement = [&](QString text, int width, bool trailingSpace) { - QColor color = this->color.getColor(themeManager); - themeManager.normalizeColor(color); + QColor color = this->color.getColor(*app->themes); + app->themes->normalizeColor(color); auto e = (new TextLayoutElement(*this, text, QSize(width, metrics.height()), color, this->style, container.getScale())) @@ -225,8 +227,9 @@ void TimestampElement::addToContainer(MessageLayoutContainer &container, MessageElement::Flags _flags) { if (_flags & this->getFlags()) { - if (singletons::SettingManager::getInstance().timestampFormat != this->format) { - this->format = singletons::SettingManager::getInstance().timestampFormat.getValue(); + auto app = getApp(); + if (app->settings->timestampFormat != this->format) { + this->format = app->settings->timestampFormat.getValue(); this->element.reset(this->formatTime(this->time)); } @@ -238,8 +241,7 @@ TextElement *TimestampElement::formatTime(const QTime &time) { static QLocale locale("en_US"); - QString format = - locale.toString(time, singletons::SettingManager::getInstance().timestampFormat); + QString format = locale.toString(time, getApp()->settings->timestampFormat); return new TextElement(format, Flags::Timestamp, MessageColor::System, FontStyle::Medium); } @@ -256,8 +258,7 @@ void TwitchModerationElement::addToContainer(MessageLayoutContainer &container, if (_flags & MessageElement::ModeratorTools) { QSize size((int)(container.getScale() * 16), (int)(container.getScale() * 16)); - for (const singletons::ModerationAction &m : - singletons::SettingManager::getInstance().getModerationActions()) { + for (const singletons::ModerationAction &m : getApp()->settings->getModerationActions()) { if (m.isImage()) { container.addElement((new ImageLayoutElement(*this, m.getImage(), size)) ->setLink(Link(Link::UserAction, m.getAction()))); diff --git a/src/providers/twitch/ircmessagehandler.cpp b/src/providers/twitch/ircmessagehandler.cpp index bcb7f6e19..be8ae18a2 100644 --- a/src/providers/twitch/ircmessagehandler.cpp +++ b/src/providers/twitch/ircmessagehandler.cpp @@ -1,5 +1,6 @@ #include "ircmessagehandler.hpp" +#include "application.hpp" #include "debug/log.hpp" #include "messages/limitedqueue.hpp" #include "messages/message.hpp" @@ -124,8 +125,10 @@ void IrcMessageHandler::handleClearChatMessage(Communi::IrcMessage *message) } } + auto app = getApp(); + // refresh all - WindowManager::getInstance().repaintVisibleChatWidgets(chan.get()); + app->windows->repaintVisibleChatWidgets(chan.get()); } void IrcMessageHandler::handleUserStateMessage(Communi::IrcMessage *message) @@ -152,6 +155,7 @@ void IrcMessageHandler::handleUserStateMessage(Communi::IrcMessage *message) void IrcMessageHandler::handleWhisperMessage(Communi::IrcMessage *message) { + auto app = getApp(); debug::Log("Received whisper!"); messages::MessageParseArgs args; @@ -171,7 +175,7 @@ void IrcMessageHandler::handleWhisperMessage(Communi::IrcMessage *message) c->addMessage(_message); - if (SettingManager::getInstance().inlineWhispers) { + if (app->settings->inlineWhispers) { TwitchServer::getInstance().forEachChannel([_message](ChannelPtr channel) { channel->addMessage(_message); // }); diff --git a/src/providers/twitch/twitchchannel.cpp b/src/providers/twitch/twitchchannel.cpp index 8e0d94dec..859056945 100644 --- a/src/providers/twitch/twitchchannel.cpp +++ b/src/providers/twitch/twitchchannel.cpp @@ -31,6 +31,7 @@ TwitchChannel::TwitchChannel(const QString &channelName, Communi::IrcConnection { debug::Log("[TwitchChannel:{}] Opened", this->name); + auto app = getApp(); this->reloadChannelEmotes(); this->liveStatusTimer = new QTimer; @@ -43,11 +44,9 @@ TwitchChannel::TwitchChannel(const QString &channelName, Communi::IrcConnection this->refreshLiveStatus(); // }); - this->managedConnect(singletons::AccountManager::getInstance().Twitch.userChanged, - [this]() { this->setMod(false); }); + this->managedConnect(app->accounts->Twitch.userChanged, [this]() { this->setMod(false); }); - auto refreshPubSubState = [this]() { - const auto &x = this; + auto refreshPubSubState = [=]() { if (!this->hasModRights()) { return; } @@ -56,17 +55,15 @@ TwitchChannel::TwitchChannel(const QString &channelName, Communi::IrcConnection return; } - auto account = singletons::AccountManager::getInstance().Twitch.getCurrent(); + auto account = app->accounts->Twitch.getCurrent(); if (account && !account->getUserId().isEmpty()) { - singletons::PubSubManager::getInstance().ListenToChannelModerationActions(this->roomID, - account); + app->pubsub->ListenToChannelModerationActions(this->roomID, account); } }; this->userStateChanged.connect(refreshPubSubState); this->roomIDchanged.connect(refreshPubSubState); - this->managedConnect(singletons::AccountManager::getInstance().Twitch.userChanged, - refreshPubSubState); + this->managedConnect(app->accounts->Twitch.userChanged, refreshPubSubState); refreshPubSubState(); this->fetchMessages.connect([this] { @@ -89,9 +86,8 @@ TwitchChannel::TwitchChannel(const QString &channelName, Communi::IrcConnection auto doRefreshChatters = [=]() { const auto streamStatus = this->GetStreamStatus(); - auto &settingManager = singletons::SettingManager::getInstance(); - if (settingManager.onlyFetchChattersForSmallerStreamers) { - if (streamStatus.live && streamStatus.viewerCount > settingManager.smallStreamerLimit) { + if (app->settings->onlyFetchChattersForSmallerStreamers) { + if (streamStatus.live && streamStatus.viewerCount > app->settings->smallStreamerLimit) { return; } } @@ -135,22 +131,22 @@ void TwitchChannel::setRoomID(const QString &_roomID) void TwitchChannel::reloadChannelEmotes() { - auto &emoteManager = singletons::EmoteManager::getInstance(); + auto app = getApp(); debug::Log("[TwitchChannel:{}] Reloading channel emotes", this->name); - emoteManager.reloadBTTVChannelEmotes(this->name, this->bttvChannelEmotes); - emoteManager.reloadFFZChannelEmotes(this->name, this->ffzChannelEmotes); + app->emotes->reloadBTTVChannelEmotes(this->name, this->bttvChannelEmotes); + app->emotes->reloadFFZChannelEmotes(this->name, this->ffzChannelEmotes); } void TwitchChannel::sendMessage(const QString &message) { - auto &emoteManager = singletons::EmoteManager::getInstance(); + auto app = getApp(); debug::Log("[TwitchChannel:{}] Send message: {}", this->name, message); // Do last message processing - QString parsedMessage = emoteManager.replaceShortCodes(message); + QString parsedMessage = app->emotes->replaceShortCodes(message); parsedMessage = parsedMessage.trimmed(); @@ -158,7 +154,7 @@ void TwitchChannel::sendMessage(const QString &message) return; } - if (singletons::SettingManager::getInstance().allowDuplicateMessages) { + if (app->settings->allowDuplicateMessages) { if (parsedMessage == this->lastSentMessage) { parsedMessage.append(this->messageSuffix); @@ -187,8 +183,9 @@ void TwitchChannel::setMod(bool value) bool TwitchChannel::isBroadcaster() { - return this->name == - singletons::AccountManager::getInstance().Twitch.getCurrent()->getUserName(); + auto app = getApp(); + + return this->name == app->accounts->Twitch.getCurrent()->getUserName(); } bool TwitchChannel::hasModRights() diff --git a/src/providers/twitch/twitchmessagebuilder.cpp b/src/providers/twitch/twitchmessagebuilder.cpp index 8e6e5a330..069660cdd 100644 --- a/src/providers/twitch/twitchmessagebuilder.cpp +++ b/src/providers/twitch/twitchmessagebuilder.cpp @@ -1,4 +1,6 @@ #include "providers/twitch/twitchmessagebuilder.hpp" + +#include "application.hpp" #include "debug/log.hpp" #include "providers/twitch/twitchchannel.hpp" #include "singletons/accountmanager.hpp" @@ -27,10 +29,11 @@ TwitchMessageBuilder::TwitchMessageBuilder(Channel *_channel, , ircMessage(_ircMessage) , args(_args) , tags(this->ircMessage->tags()) - , usernameColor(singletons::ThemeManager::getInstance().messages.textColors.system) , originalMessage(_ircMessage->content()) , action(_ircMessage->isAction()) { + auto app = getApp(); + this->usernameColor = app->themes->messages.textColors.system; } TwitchMessageBuilder::TwitchMessageBuilder(Channel *_channel, @@ -41,15 +44,16 @@ TwitchMessageBuilder::TwitchMessageBuilder(Channel *_channel, , ircMessage(_ircMessage) , args(_args) , tags(this->ircMessage->tags()) - , usernameColor(singletons::ThemeManager::getInstance().messages.textColors.system) , originalMessage(content) { + auto app = getApp(); + this->usernameColor = app->themes->messages.textColors.system; } bool TwitchMessageBuilder::isIgnored() const { - singletons::SettingManager &settings = singletons::SettingManager::getInstance(); - std::shared_ptr> ignoredKeywords = settings.getIgnoredKeywords(); + auto app = getApp(); + std::shared_ptr> ignoredKeywords = app->settings->getIgnoredKeywords(); for (const QString &keyword : *ignoredKeywords) { if (this->originalMessage.contains(keyword, Qt::CaseInsensitive)) { @@ -62,8 +66,7 @@ bool TwitchMessageBuilder::isIgnored() const MessagePtr TwitchMessageBuilder::build() { - singletons::SettingManager &settings = singletons::SettingManager::getInstance(); - singletons::EmoteManager &emoteManager = singletons::EmoteManager::getInstance(); + auto app = getApp(); // PARSING this->parseUsername(); @@ -103,7 +106,7 @@ MessagePtr TwitchMessageBuilder::build() this->appendUsername(); // highlights - if (settings.enableHighlights && !isPastMsg) { + if (app->settings->enableHighlights && !isPastMsg) { this->parseHighlights(); } @@ -162,7 +165,7 @@ MessagePtr TwitchMessageBuilder::build() std::vector> parsed; // Parse emojis and take all non-emojis and put them in parsed as full text-words - emoteManager.parseEmojis(parsed, split); + app->emotes->parseEmojis(parsed, split); for (const auto &tuple : parsed) { const util::EmoteData &emoteData = std::get<0>(tuple); @@ -274,6 +277,8 @@ void TwitchMessageBuilder::parseUsername() void TwitchMessageBuilder::appendUsername() { + auto app = getApp(); + QString username = this->userName; this->message->loginName = username; QString localizedName; @@ -334,16 +339,16 @@ void TwitchMessageBuilder::appendUsername() FontStyle::MediumBold) ->setLink({Link::UserInfo, this->userName}); - auto currentUser = singletons::AccountManager::getInstance().Twitch.getCurrent(); + auto currentUser = app->accounts->Twitch.getCurrent(); // Separator - this->emplace( - "->", MessageElement::Text, - singletons::ThemeManager::getInstance().messages.textColors.system, FontStyle::Medium); + this->emplace("->", MessageElement::Text, + app->themes->messages.textColors.system, + FontStyle::Medium); QColor selfColor = currentUser->color; if (!selfColor.isValid()) { - selfColor = singletons::ThemeManager::getInstance().messages.textColors.system; + selfColor = app->themes->messages.textColors.system; } // Your own username @@ -364,8 +369,10 @@ void TwitchMessageBuilder::parseHighlights() { static auto player = new QMediaPlayer; static QUrl currentPlayerUrl; - singletons::SettingManager &settings = singletons::SettingManager::getInstance(); - auto currentUser = singletons::AccountManager::getInstance().Twitch.getCurrent(); + + auto app = getApp(); + + auto currentUser = app->accounts->Twitch.getCurrent(); QString currentUsername = currentUser->getUserName(); @@ -377,8 +384,8 @@ void TwitchMessageBuilder::parseHighlights() // update the media player url if necessary QUrl highlightSoundUrl; - if (settings.customHighlightSound) { - highlightSoundUrl = QUrl(settings.pathHighlightSound.getValue()); + if (app->settings->customHighlightSound) { + highlightSoundUrl = QUrl(app->settings->pathHighlightSound.getValue()); } else { highlightSoundUrl = QUrl("qrc:/sounds/ping2.wav"); } @@ -390,16 +397,16 @@ void TwitchMessageBuilder::parseHighlights() } QStringList blackList = - settings.highlightUserBlacklist.getValue().split("\n", QString::SkipEmptyParts); + app->settings->highlightUserBlacklist.getValue().split("\n", QString::SkipEmptyParts); // TODO: This vector should only be rebuilt upon highlights being changed - auto activeHighlights = settings.highlightProperties.getValue(); + auto activeHighlights = app->settings->highlightProperties.getValue(); - if (settings.enableHighlightsSelf && currentUsername.size() > 0) { + if (app->settings->enableHighlightsSelf && currentUsername.size() > 0) { messages::HighlightPhrase selfHighlight; selfHighlight.key = currentUsername; - selfHighlight.sound = settings.enableHighlightSound; - selfHighlight.alert = settings.enableHighlightTaskbar; + selfHighlight.sound = app->settings->enableHighlightSound; + selfHighlight.alert = app->settings->enableHighlightTaskbar; activeHighlights.emplace_back(std::move(selfHighlight)); } @@ -443,13 +450,12 @@ void TwitchMessageBuilder::parseHighlights() this->setHighlight(doHighlight); - if (playSound && (!hasFocus || settings.highlightAlwaysPlaySound)) { + if (playSound && (!hasFocus || app->settings->highlightAlwaysPlaySound)) { player->play(); } if (doAlert) { - QApplication::alert(singletons::WindowManager::getInstance().getMainWindow().window(), - 2500); + QApplication::alert(getApp()->windows->getMainWindow().window(), 2500); } if (doHighlight) { @@ -462,7 +468,7 @@ void TwitchMessageBuilder::appendTwitchEmote(const Communi::IrcMessage *ircMessa const QString &emote, std::vector> &vec) { - singletons::EmoteManager &emoteManager = singletons::EmoteManager::getInstance(); + auto app = getApp(); if (!emote.contains(':')) { return; } @@ -494,13 +500,13 @@ void TwitchMessageBuilder::appendTwitchEmote(const Communi::IrcMessage *ircMessa QString name = this->originalMessage.mid(start, end - start + 1); vec.push_back( - std::pair(start, emoteManager.getTwitchEmoteById(id, name))); + std::pair(start, app->emotes->getTwitchEmoteById(id, name))); } } bool TwitchMessageBuilder::tryAppendEmote(QString &emoteString) { - singletons::EmoteManager &emoteManager = singletons::EmoteManager::getInstance(); + auto app = getApp(); util::EmoteData emoteData; auto appendEmote = [&](MessageElement::Flags flags) { @@ -508,21 +514,21 @@ bool TwitchMessageBuilder::tryAppendEmote(QString &emoteString) return true; }; - if (emoteManager.bttvGlobalEmotes.tryGet(emoteString, emoteData)) { + if (app->emotes->bttvGlobalEmotes.tryGet(emoteString, emoteData)) { // BTTV Global Emote return appendEmote(MessageElement::BttvEmote); } else if (this->twitchChannel != nullptr && this->twitchChannel->bttvChannelEmotes->tryGet(emoteString, emoteData)) { // BTTV Channel Emote return appendEmote(MessageElement::BttvEmote); - } else if (emoteManager.ffzGlobalEmotes.tryGet(emoteString, emoteData)) { + } else if (app->emotes->ffzGlobalEmotes.tryGet(emoteString, emoteData)) { // FFZ Global Emote return appendEmote(MessageElement::FfzEmote); } else if (this->twitchChannel != nullptr && this->twitchChannel->ffzChannelEmotes->tryGet(emoteString, emoteData)) { // FFZ Channel Emote return appendEmote(MessageElement::FfzEmote); - } else if (emoteManager.getChatterinoEmotes().tryGet(emoteString, emoteData)) { + } else if (app->emotes->getChatterinoEmotes().tryGet(emoteString, emoteData)) { // Chatterino Emote return appendEmote(MessageElement::Misc); } diff --git a/src/providers/twitch/twitchserver.cpp b/src/providers/twitch/twitchserver.cpp index db084de7c..b456c1032 100644 --- a/src/providers/twitch/twitchserver.cpp +++ b/src/providers/twitch/twitchserver.cpp @@ -1,5 +1,6 @@ #include "twitchserver.hpp" +#include "application.hpp" #include "providers/twitch/ircmessagehandler.hpp" #include "providers/twitch/twitchaccount.hpp" #include "providers/twitch/twitchhelpers.hpp" @@ -23,7 +24,7 @@ TwitchServer::TwitchServer() { qDebug() << "init TwitchServer"; - AccountManager::getInstance().Twitch.userChanged.connect( + getApp()->accounts->Twitch.userChanged.connect( [this]() { util::postToThread([this] { this->connect(); }); }); } @@ -35,7 +36,7 @@ TwitchServer &TwitchServer::getInstance() void TwitchServer::initializeConnection(IrcConnection *connection, bool isRead, bool isWrite) { - std::shared_ptr account = AccountManager::getInstance().Twitch.getCurrent(); + std::shared_ptr account = getApp()->accounts->Twitch.getCurrent(); qDebug() << "logging in as" << account->getUserName(); diff --git a/src/singletons/accountmanager.cpp b/src/singletons/accountmanager.cpp index 236aea1dd..65dc2a08c 100644 --- a/src/singletons/accountmanager.cpp +++ b/src/singletons/accountmanager.cpp @@ -3,31 +3,6 @@ namespace chatterino { namespace singletons { -namespace { - -inline QString getEnvString(const char *target) -{ - char *val = std::getenv(target); - if (val == nullptr) { - return QString(); - } - - return QString(val); -} - -} // namespace - -AccountManager::AccountManager() -{ - qDebug() << "init AccountManager"; -} - -AccountManager &AccountManager::getInstance() -{ - static AccountManager instance; - return instance; -} - void AccountManager::load() { this->Twitch.load(); diff --git a/src/singletons/accountmanager.hpp b/src/singletons/accountmanager.hpp index 774ebb6fc..36573a8e2 100644 --- a/src/singletons/accountmanager.hpp +++ b/src/singletons/accountmanager.hpp @@ -7,10 +7,11 @@ namespace singletons { class AccountManager { - AccountManager(); + AccountManager() = default; + friend class Application; public: - static AccountManager &getInstance(); + ~AccountManager() = delete; void load(); diff --git a/src/singletons/commandmanager.cpp b/src/singletons/commandmanager.cpp index 3818e6dd4..d3a22fed0 100644 --- a/src/singletons/commandmanager.cpp +++ b/src/singletons/commandmanager.cpp @@ -1,4 +1,6 @@ #include "singletons/commandmanager.hpp" + +#include "application.hpp" #include "debug/log.hpp" #include "messages/messagebuilder.hpp" #include "providers/twitch/twitchserver.hpp" @@ -17,20 +19,10 @@ using namespace chatterino::providers::twitch; namespace chatterino { namespace singletons { -CommandManager::CommandManager() -{ - qDebug() << "init CommandManager"; -} - -CommandManager &CommandManager::getInstance() -{ - static CommandManager instance; - return instance; -} - void CommandManager::loadCommands() { - this->filePath = PathManager::getInstance().customFolderPath + "/Commands.txt"; + auto app = getApp(); + this->filePath = app->paths->customFolderPath + "/Commands.txt"; QFile textFile(this->filePath); if (!textFile.open(QIODevice::ReadOnly)) { @@ -162,7 +154,7 @@ QString CommandManager::execCommand(const QString &text, ChannelPtr channel, boo messages::MessageBuilder b; b.emplace( - singletons::AccountManager::getInstance().Twitch.getCurrent()->getUserName(), + getApp()->accounts->Twitch.getCurrent()->getUserName(), messages::MessageElement::Text); b.emplace("->", messages::MessageElement::Text); b.emplace(words[1], messages::MessageElement::Text); diff --git a/src/singletons/commandmanager.hpp b/src/singletons/commandmanager.hpp index 4904bb656..c1ea7cbc8 100644 --- a/src/singletons/commandmanager.hpp +++ b/src/singletons/commandmanager.hpp @@ -2,6 +2,7 @@ #include #include + #include #include @@ -16,11 +17,10 @@ namespace singletons { class CommandManager { - CommandManager(); + CommandManager() = default; + friend class Application; public: - static CommandManager &getInstance(); - QString execCommand(const QString &text, std::shared_ptr channel, bool dryRun); void loadCommands(); diff --git a/src/singletons/emotemanager.cpp b/src/singletons/emotemanager.cpp index 98c6f92d7..d3c22232f 100644 --- a/src/singletons/emotemanager.cpp +++ b/src/singletons/emotemanager.cpp @@ -1,4 +1,6 @@ #include "emotemanager.hpp" + +#include "application.hpp" #include "common.hpp" #include "singletons/settingsmanager.hpp" #include "singletons/windowmanager.hpp" @@ -80,21 +82,17 @@ EmoteManager::EmoteManager() : findShortCodesRegex(":([-+\\w]+):") { qDebug() << "init EmoteManager"; - auto &accountManager = AccountManager::getInstance(); +} - accountManager.Twitch.userChanged.connect([this] { - auto currentUser = AccountManager::getInstance().Twitch.getCurrent(); +void EmoteManager::initialize() +{ + getApp()->accounts->Twitch.userChanged.connect([this] { + auto currentUser = getApp()->accounts->Twitch.getCurrent(); assert(currentUser); this->refreshTwitchEmotes(currentUser); }); } -EmoteManager &EmoteManager::getInstance() -{ - static EmoteManager instance; - return instance; -} - void EmoteManager::loadGlobalEmotes() { this->loadEmojis(); @@ -558,14 +556,14 @@ util::EmoteData EmoteManager::getCheerImage(long long amount, bool animated) pajlada::Signals::NoArgSignal &EmoteManager::getGifUpdateSignal() { if (!this->gifUpdateTimerInitiated) { + auto app = getApp(); + this->gifUpdateTimerInitiated = true; this->gifUpdateTimer.setInterval(30); this->gifUpdateTimer.start(); - auto &settingManager = singletons::SettingManager::getInstance(); - - settingManager.enableGifAnimations.connect([this](bool enabled, auto) { + app->settings->enableGifAnimations.connect([this](bool enabled, auto) { if (enabled) { this->gifUpdateTimer.start(); } else { @@ -576,8 +574,8 @@ pajlada::Signals::NoArgSignal &EmoteManager::getGifUpdateSignal() QObject::connect(&this->gifUpdateTimer, &QTimer::timeout, [this] { this->gifUpdateTimerSignal.invoke(); // fourtf: - auto &windowManager = singletons::WindowManager::getInstance(); - windowManager.repaintGifEmotes(); + auto app = getApp(); + app->windows->repaintGifEmotes(); }); } diff --git a/src/singletons/emotemanager.hpp b/src/singletons/emotemanager.hpp index b714dfb9f..21f785610 100644 --- a/src/singletons/emotemanager.hpp +++ b/src/singletons/emotemanager.hpp @@ -23,9 +23,12 @@ namespace singletons { class EmoteManager { EmoteManager(); + friend class Application; public: - static EmoteManager &getInstance(); + ~EmoteManager() = delete; + + void initialize(); void loadGlobalEmotes(); diff --git a/src/singletons/helper/pubsubhelpers.cpp b/src/singletons/helper/pubsubhelpers.cpp index e4e9ad076..d7b79adac 100644 --- a/src/singletons/helper/pubsubhelpers.cpp +++ b/src/singletons/helper/pubsubhelpers.cpp @@ -71,8 +71,6 @@ rapidjson::Document CreateUnlistenMessage(const std::vector &topics rj::set(msg, "type", "UNLISTEN"); - auto &accountManager = AccountManager::getInstance(); - rapidjson::Value data(rapidjson::kObjectType); rapidjson::Value topics(rapidjson::kArrayType); diff --git a/src/singletons/loggingmanager.cpp b/src/singletons/loggingmanager.cpp index d25a9ace5..c03009702 100644 --- a/src/singletons/loggingmanager.cpp +++ b/src/singletons/loggingmanager.cpp @@ -1,4 +1,6 @@ #include "singletons/loggingmanager.hpp" + +#include "application.hpp" #include "debug/log.hpp" #include "singletons/pathmanager.hpp" #include "singletons/settingsmanager.hpp" @@ -11,23 +13,16 @@ namespace chatterino { namespace singletons { -LoggingManager::LoggingManager() - : pathManager(PathManager::getInstance()) +void LoggingManager::initialize() { - qDebug() << "init LoggingManager"; -} - -LoggingManager &LoggingManager::getInstance() -{ - static LoggingManager instance; - return instance; + this->pathManager = getApp()->paths; } void LoggingManager::addMessage(const QString &channelName, messages::MessagePtr message) { - const auto &settings = singletons::SettingManager::getInstance(); + auto app = getApp(); - if (!settings.enableLogging) { + if (!app->settings->enableLogging) { return; } @@ -45,13 +40,14 @@ void LoggingManager::addMessage(const QString &channelName, messages::MessagePtr QString LoggingManager::getDirectoryForChannel(const QString &channelName) { if (channelName.startsWith("/whispers")) { - return this->pathManager.whispersLogsFolderPath; + return this->pathManager->whispersLogsFolderPath; } else if (channelName.startsWith("/mentions")) { - return this->pathManager.mentionsLogsFolderPath; + return this->pathManager->mentionsLogsFolderPath; } else { - QString logPath(this->pathManager.channelsLogsFolderPath + QDir::separator() + channelName); + QString logPath(this->pathManager->channelsLogsFolderPath + QDir::separator() + + channelName); - if (!this->pathManager.createFolder(logPath)) { + if (!this->pathManager->createFolder(logPath)) { debug::Log("Error creating channel logs folder for channel {}", channelName); } diff --git a/src/singletons/loggingmanager.hpp b/src/singletons/loggingmanager.hpp index 8371db7e6..84602c9c0 100644 --- a/src/singletons/loggingmanager.hpp +++ b/src/singletons/loggingmanager.hpp @@ -3,8 +3,6 @@ #include "messages/message.hpp" #include "singletons/helper/loggingchannel.hpp" -#include - #include namespace chatterino { @@ -12,14 +10,17 @@ namespace singletons { class PathManager; -class LoggingManager : boost::noncopyable +class LoggingManager { - LoggingManager(); + LoggingManager() = default; + friend class Application; - PathManager &pathManager; + PathManager *pathManager = nullptr; public: - static LoggingManager &getInstance(); + ~LoggingManager() = delete; + + void initialize(); void addMessage(const QString &channelName, messages::MessagePtr message); diff --git a/src/singletons/nativemessagingmanager.cpp b/src/singletons/nativemessagingmanager.cpp index aaca038e9..7671959a0 100644 --- a/src/singletons/nativemessagingmanager.cpp +++ b/src/singletons/nativemessagingmanager.cpp @@ -1,5 +1,6 @@ #include "nativemessagingmanager.hpp" +#include "application.hpp" #include "providers/twitch/twitchserver.hpp" #include "singletons/pathmanager.hpp" #include "util/posttothread.hpp" @@ -17,7 +18,7 @@ namespace ipc = boost::interprocess; #ifdef Q_OS_WIN #include -#include +#include #include "singletons/windowmanager.hpp" #include "widgets/attachedwindow.hpp" #endif @@ -35,12 +36,6 @@ NativeMessagingManager::NativeMessagingManager() qDebug() << "init NativeMessagingManager"; } -NativeMessagingManager &NativeMessagingManager::getInstance() -{ - static NativeMessagingManager manager; - return manager; -} - void NativeMessagingManager::writeByteArray(QByteArray a) { char *data = a.data(); @@ -53,6 +48,8 @@ void NativeMessagingManager::writeByteArray(QByteArray a) void NativeMessagingManager::registerHost() { + auto app = getApp(); + // create manifest QJsonDocument document; QJsonObject root_obj; @@ -70,8 +67,7 @@ void NativeMessagingManager::registerHost() root_obj.insert("allowed_extensions", allowed_extensions); // save the manifest - QString manifestPath = - PathManager::getInstance().settingsFolderPath + "/native-messaging-manifest.json"; + QString manifestPath = app->paths->settingsFolderPath + "/native-messaging-manifest.json"; document.setObject(root_obj); diff --git a/src/singletons/nativemessagingmanager.hpp b/src/singletons/nativemessagingmanager.hpp index 0604caddb..f20e6758d 100644 --- a/src/singletons/nativemessagingmanager.hpp +++ b/src/singletons/nativemessagingmanager.hpp @@ -8,9 +8,10 @@ namespace singletons { class NativeMessagingManager { NativeMessagingManager(); + friend class Application; public: - static NativeMessagingManager &getInstance(); + ~NativeMessagingManager() = delete; class ReceiverThread : public QThread { diff --git a/src/singletons/pathmanager.cpp b/src/singletons/pathmanager.cpp index 0e893df34..07f5a43b8 100644 --- a/src/singletons/pathmanager.cpp +++ b/src/singletons/pathmanager.cpp @@ -8,18 +8,7 @@ namespace chatterino { namespace singletons { -PathManager::PathManager() -{ - qDebug() << "init PathManager"; -} - -PathManager &PathManager::getInstance() -{ - static PathManager instance; - return instance; -} - -bool PathManager::init(int argc, char **argv) +PathManager::PathManager(int argc, char **argv) { // hash of app path this->appPathHash = QCryptographicHash::hash(QCoreApplication::applicationFilePath().toUtf8(), @@ -50,64 +39,51 @@ bool PathManager::init(int argc, char **argv) // Get settings path rootPath.append(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)); if (rootPath.isEmpty()) { - printf("Error finding writable location for settings\n"); - return false; + throw std::runtime_error("Error finding writable location for settings"); } } this->settingsFolderPath = rootPath; if (!QDir().mkpath(this->settingsFolderPath)) { - printf("Error creating directory: %s\n", qPrintable(this->settingsFolderPath)); - return false; + throw std::runtime_error("Error creating settings folder"); } this->customFolderPath = rootPath + "/Custom"; if (!QDir().mkpath(this->customFolderPath)) { - printf("Error creating directory: %s\n", qPrintable(this->customFolderPath)); - return false; + throw std::runtime_error("Error creating custom folder"); } this->cacheFolderPath = rootPath + "/Cache"; if (!QDir().mkpath(this->cacheFolderPath)) { - printf("Error creating cache directory: %s\n", qPrintable(this->cacheFolderPath)); - return false; + throw std::runtime_error("Error creating cache folder"); } this->logsFolderPath = rootPath + "/Logs"; if (!QDir().mkpath(this->logsFolderPath)) { - printf("Error creating logs directory: %s\n", qPrintable(this->logsFolderPath)); - return false; + throw std::runtime_error("Error creating logs folder"); } this->channelsLogsFolderPath = this->logsFolderPath + "/Channels"; if (!QDir().mkpath(this->channelsLogsFolderPath)) { - printf("Error creating channelsLogs directory: %s\n", - qPrintable(this->channelsLogsFolderPath)); - return false; + throw std::runtime_error("Error creating channel logs folder"); } this->whispersLogsFolderPath = this->logsFolderPath + "/Whispers"; if (!QDir().mkpath(this->whispersLogsFolderPath)) { - printf("Error creating whispersLogs directory: %s\n", - qPrintable(this->whispersLogsFolderPath)); - return false; + throw std::runtime_error("Error creating whisper logs folder"); } this->mentionsLogsFolderPath = this->logsFolderPath + "/Mentions"; if (!QDir().mkpath(this->mentionsLogsFolderPath)) { - printf("Error creating mentionsLogs directory: %s\n", - qPrintable(this->mentionsLogsFolderPath)); - return false; + throw std::runtime_error("Error creating mentions logs folder"); } - - return true; } bool PathManager::createFolder(const QString &folderPath) diff --git a/src/singletons/pathmanager.hpp b/src/singletons/pathmanager.hpp index b0fb8243f..0019aaa85 100644 --- a/src/singletons/pathmanager.hpp +++ b/src/singletons/pathmanager.hpp @@ -7,13 +7,10 @@ namespace singletons { class PathManager { - PathManager(); + PathManager(int argc, char **argv); + friend class Application; public: - static PathManager &getInstance(); - - bool init(int argc, char **argv); - // %APPDATA%/chatterino or ExecutablePath for portable mode QString settingsFolderPath; diff --git a/src/singletons/pubsubmanager.cpp b/src/singletons/pubsubmanager.cpp index 38df480ac..17a8449a4 100644 --- a/src/singletons/pubsubmanager.cpp +++ b/src/singletons/pubsubmanager.cpp @@ -443,12 +443,6 @@ void PubSubManager::AddClient() this->websocketClient.connect(con); } -PubSubManager &PubSubManager::getInstance() -{ - static PubSubManager instance; - return instance; -} - void PubSubManager::Start() { this->mainThread.reset(new std::thread(std::bind(&PubSubManager::RunThread, this))); diff --git a/src/singletons/pubsubmanager.hpp b/src/singletons/pubsubmanager.hpp index ed3da54ff..84b26eba1 100644 --- a/src/singletons/pubsubmanager.hpp +++ b/src/singletons/pubsubmanager.hpp @@ -69,6 +69,7 @@ private: class PubSubManager { PubSubManager(); + friend class Application; using WebsocketMessagePtr = websocketpp::config::asio_tls_client::message_type::ptr; using WebsocketContextPtr = websocketpp::lib::shared_ptr; @@ -80,13 +81,13 @@ class PubSubManager std::unique_ptr mainThread; public: + ~PubSubManager() = delete; + enum class State { Connected, Disconnected, }; - static PubSubManager &getInstance(); - void Start(); bool IsConnected() const diff --git a/src/singletons/settingsmanager.cpp b/src/singletons/settingsmanager.cpp index 56ca824fe..6e706cb49 100644 --- a/src/singletons/settingsmanager.cpp +++ b/src/singletons/settingsmanager.cpp @@ -1,4 +1,6 @@ #include "singletons/settingsmanager.hpp" + +#include "application.hpp" #include "debug/log.hpp" #include "singletons/pathmanager.hpp" #include "singletons/resourcemanager.hpp" @@ -17,8 +19,7 @@ void _actuallyRegisterSetting(std::weak_ptr set } SettingManager::SettingManager() - : snapshot(nullptr) - , _ignoredKeywords(new std::vector) + : _ignoredKeywords(new std::vector) { qDebug() << "init SettingManager"; @@ -35,8 +36,10 @@ SettingManager::SettingManager() this->moderationActions.connect([this](auto, auto) { this->updateModerationActions(); }); this->ignoredKeywords.connect([this](auto, auto) { this->updateIgnoredKeywords(); }); - this->timestampFormat.connect( - [](auto, auto) { singletons::WindowManager::getInstance().layoutVisibleChatWidgets(); }); + this->timestampFormat.connect([](auto, auto) { + auto app = getApp(); + app->windows->layoutVisibleChatWidgets(); + }); } MessageElement::Flags SettingManager::getWordFlags() @@ -51,7 +54,8 @@ bool SettingManager::isIgnoredEmote(const QString &) void SettingManager::initialize() { - QString settingsPath = PathManager::getInstance().settingsFolderPath + "/settings.json"; + auto app = getApp(); + QString settingsPath = app->paths->settingsFolderPath + "/settings.json"; pajlada::Settings::SettingManager::load(qPrintable(settingsPath)); } @@ -88,7 +92,7 @@ void SettingManager::updateWordTypeMask() if (newMask != this->wordFlags) { this->wordFlags = newMask; - emit wordFlagsChanged(); + this->wordFlagsChanged.invoke(); } } diff --git a/src/singletons/settingsmanager.hpp b/src/singletons/settingsmanager.hpp index 7f59d8fee..c6d3f9f11 100644 --- a/src/singletons/settingsmanager.hpp +++ b/src/singletons/settingsmanager.hpp @@ -13,17 +13,20 @@ namespace singletons { void _actuallyRegisterSetting(std::weak_ptr setting); -class SettingManager : public QObject +class SettingManager { - Q_OBJECT - using BoolSetting = ChatterinoSetting; using FloatSetting = ChatterinoSetting; using IntSetting = ChatterinoSetting; using StringSetting = ChatterinoSetting; using QStringSetting = ChatterinoSetting; + SettingManager(); + friend class Application; + public: + ~SettingManager() = delete; + messages::MessageElement::Flags getWordFlags(); bool isIgnoredEmote(const QString &emote); @@ -112,11 +115,6 @@ public: BoolSetting inlineWhispers = {"/whispers/enableInlineWhispers", true}; - static SettingManager &getInstance() - { - static SettingManager instance; - return instance; - } void updateWordTypeMask(); void saveSnapshot(); @@ -124,17 +122,13 @@ public: std::vector getModerationActions() const; const std::shared_ptr> getIgnoredKeywords() const; - -signals: - void wordFlagsChanged(); + pajlada::Signals::NoArgSignal wordFlagsChanged; private: std::vector _moderationActions; std::unique_ptr snapshot; std::shared_ptr> _ignoredKeywords; - SettingManager(); - void updateModerationActions(); void updateIgnoredKeywords(); diff --git a/src/singletons/thememanager.cpp b/src/singletons/thememanager.cpp index 87329ccaa..c9d42c5fb 100644 --- a/src/singletons/thememanager.cpp +++ b/src/singletons/thememanager.cpp @@ -28,12 +28,6 @@ double getMultiplierByTheme(const QString &themeName) } // namespace detail -ThemeManager &ThemeManager::getInstance() -{ - static ThemeManager instance; - return instance; -} - ThemeManager::ThemeManager() : themeName("/appearance/theme/name", "Dark") , themeHue("/appearance/theme/hue", 0.0) @@ -42,8 +36,8 @@ ThemeManager::ThemeManager() this->update(); - this->themeName.connectSimple([this](auto) { this->update(); }); - this->themeHue.connectSimple([this](auto) { this->update(); }); + this->themeName.connectSimple([this](auto) { this->update(); }, false); + this->themeHue.connectSimple([this](auto) { this->update(); }, false); } void ThemeManager::update() diff --git a/src/singletons/thememanager.hpp b/src/singletons/thememanager.hpp index 6a384e0aa..2968f6e4c 100644 --- a/src/singletons/thememanager.hpp +++ b/src/singletons/thememanager.hpp @@ -14,9 +14,10 @@ class WindowManager; class ThemeManager { ThemeManager(); + friend class Application; public: - static ThemeManager &getInstance(); + ~ThemeManager() = delete; inline bool isLightTheme() const { diff --git a/src/singletons/windowmanager.cpp b/src/singletons/windowmanager.cpp index e5908aa7b..6573d17ef 100644 --- a/src/singletons/windowmanager.cpp +++ b/src/singletons/windowmanager.cpp @@ -1,4 +1,6 @@ #include "windowmanager.hpp" + +#include "application.hpp" #include "debug/log.hpp" #include "providers/twitch/twitchserver.hpp" #include "singletons/fontmanager.hpp" @@ -18,12 +20,6 @@ namespace chatterino { namespace singletons { -WindowManager &WindowManager::getInstance() -{ - static WindowManager instance(ThemeManager::getInstance()); - return instance; -} - void WindowManager::showSettingsDialog() { QTimer::singleShot(80, [] { widgets::SettingsDialog::showDialog(); }); @@ -53,11 +49,9 @@ void WindowManager::showAccountSelectPopup(QPoint point) w->setFocus(); } -WindowManager::WindowManager(ThemeManager &_themeManager) - : themeManager(_themeManager) +WindowManager::WindowManager() { qDebug() << "init WindowManager"; - _themeManager.repaintVisibleChatWidgets.connect([this] { this->repaintVisibleChatWidgets(); }); } void WindowManager::layoutVisibleChatWidgets(Channel *channel) @@ -102,7 +96,7 @@ widgets::Window &WindowManager::createWindow(widgets::Window::WindowType type) { util::assertInGuiThread(); - auto *window = new widgets::Window(this->themeManager, type); + auto *window = new widgets::Window(type); this->windows.push_back(window); window->show(); @@ -143,10 +137,14 @@ void WindowManager::initialize() { util::assertInGuiThread(); + auto app = getApp(); + app->themes->repaintVisibleChatWidgets.connect( + [this] { this->repaintVisibleChatWidgets(); }); + assert(!this->initialized); // load file - QString settingsPath = PathManager::getInstance().settingsFolderPath + SETTINGS_FILENAME; + QString settingsPath = app->paths->settingsFolderPath + SETTINGS_FILENAME; QFile file(settingsPath); file.open(QIODevice::ReadOnly); QByteArray data = file.readAll(); @@ -230,6 +228,7 @@ void WindowManager::initialize() void WindowManager::save() { util::assertInGuiThread(); + auto app = getApp(); QJsonDocument document; @@ -301,7 +300,7 @@ void WindowManager::save() document.setObject(obj); // save file - QString settingsPath = PathManager::getInstance().settingsFolderPath + SETTINGS_FILENAME; + QString settingsPath = app->paths->settingsFolderPath + SETTINGS_FILENAME; QFile file(settingsPath); file.open(QIODevice::WriteOnly | QIODevice::Truncate); file.write(document.toJson()); diff --git a/src/singletons/windowmanager.hpp b/src/singletons/windowmanager.hpp index 45af41e68..81d62f81d 100644 --- a/src/singletons/windowmanager.hpp +++ b/src/singletons/windowmanager.hpp @@ -5,14 +5,13 @@ namespace chatterino { namespace singletons { -class ThemeManager; - class WindowManager { - explicit WindowManager(ThemeManager &_themeManager); + WindowManager(); + friend class Application; public: - static WindowManager &getInstance(); + ~WindowManager() = delete; void showSettingsDialog(); void showAccountSelectPopup(QPoint point); @@ -37,8 +36,6 @@ public: pajlada::Signals::Signal layout; private: - ThemeManager &themeManager; - bool initialized = false; std::vector windows; diff --git a/src/util/completionmodel.cpp b/src/util/completionmodel.cpp index 1fa78bcf5..6cf8a0fa4 100644 --- a/src/util/completionmodel.cpp +++ b/src/util/completionmodel.cpp @@ -1,5 +1,6 @@ #include "util/completionmodel.hpp" +#include "application.hpp" #include "common.hpp" #include "debug/log.hpp" #include "singletons/emotemanager.hpp" @@ -19,11 +20,11 @@ void CompletionModel::refresh() { debug::Log("[CompletionModel:{}] Refreshing...]", this->channelName); - auto &emoteManager = singletons::EmoteManager::getInstance(); + auto app = getApp(); // User-specific: Twitch Emotes // TODO: Fix this so it properly updates with the proper api. oauth token needs proper scope - for (const auto &m : emoteManager.twitchAccountEmotes) { + for (const auto &m : app->emotes->twitchAccountEmotes) { for (const auto &emoteName : m.second.emoteCodes) { // XXX: No way to discern between a twitch global emote and sub emote right now this->addString(emoteName, TaggedString::Type::TwitchGlobalEmote); @@ -31,33 +32,33 @@ void CompletionModel::refresh() } // Global: BTTV Global Emotes - std::vector &bttvGlobalEmoteCodes = emoteManager.bttvGlobalEmoteCodes; + std::vector &bttvGlobalEmoteCodes = app->emotes->bttvGlobalEmoteCodes; for (const auto &m : bttvGlobalEmoteCodes) { this->addString(m, TaggedString::Type::BTTVGlobalEmote); } // Global: FFZ Global Emotes - std::vector &ffzGlobalEmoteCodes = emoteManager.ffzGlobalEmoteCodes; + std::vector &ffzGlobalEmoteCodes = app->emotes->ffzGlobalEmoteCodes; for (const auto &m : ffzGlobalEmoteCodes) { this->addString(m, TaggedString::Type::FFZGlobalEmote); } // Channel-specific: BTTV Channel Emotes std::vector &bttvChannelEmoteCodes = - emoteManager.bttvChannelEmoteCodes[this->channelName.toStdString()]; + app->emotes->bttvChannelEmoteCodes[this->channelName.toStdString()]; for (const auto &m : bttvChannelEmoteCodes) { this->addString(m, TaggedString::Type::BTTVChannelEmote); } // Channel-specific: FFZ Channel Emotes std::vector &ffzChannelEmoteCodes = - emoteManager.ffzChannelEmoteCodes[this->channelName.toStdString()]; + app->emotes->ffzChannelEmoteCodes[this->channelName.toStdString()]; for (const auto &m : ffzChannelEmoteCodes) { this->addString(m, TaggedString::Type::FFZChannelEmote); } // Global: Emojis - const auto &emojiShortCodes = emoteManager.emojiShortCodes; + const auto &emojiShortCodes = app->emotes->emojiShortCodes; for (const auto &m : emojiShortCodes) { this->addString(":" + m + ":", TaggedString::Type::Emoji); } diff --git a/src/util/networkrequest.cpp b/src/util/networkrequest.cpp index 7bdc040e5..f62361146 100644 --- a/src/util/networkrequest.cpp +++ b/src/util/networkrequest.cpp @@ -1,5 +1,7 @@ #include "util/networkrequest.hpp" +#include "application.hpp" + namespace chatterino { namespace util { @@ -26,9 +28,9 @@ void NetworkRequest::setUseQuickLoadCache(bool value) void NetworkRequest::Data::writeToCache(const QByteArray &bytes) { if (this->useQuickLoadCache) { - auto &pathManager = singletons::PathManager::getInstance(); + auto app = getApp(); - QFile cachedFile(pathManager.cacheFolderPath + "/" + this->getHash()); + QFile cachedFile(app->paths->cacheFolderPath + "/" + this->getHash()); if (cachedFile.open(QIODevice::WriteOnly)) { cachedFile.write(bytes); diff --git a/src/util/networkrequest.hpp b/src/util/networkrequest.hpp index 77c8fd8a1..247fe0c17 100644 --- a/src/util/networkrequest.hpp +++ b/src/util/networkrequest.hpp @@ -1,5 +1,6 @@ #pragma once +#include "application.hpp" #include "singletons/pathmanager.hpp" #include "util/networkmanager.hpp" #include "util/networkrequester.hpp" @@ -125,9 +126,9 @@ public: void get(FinishedCallback onFinished) { if (this->data.useQuickLoadCache) { - auto &pathManager = singletons::PathManager::getInstance(); + auto app = getApp(); - QFile cachedFile(pathManager.cacheFolderPath + "/" + this->data.getHash()); + QFile cachedFile(app->paths->cacheFolderPath + "/" + this->data.getHash()); if (cachedFile.exists()) { if (cachedFile.open(QIODevice::ReadOnly)) { diff --git a/src/util/streamlink.cpp b/src/util/streamlink.cpp index a54190643..fd8b37890 100644 --- a/src/util/streamlink.cpp +++ b/src/util/streamlink.cpp @@ -1,4 +1,6 @@ #include "util/streamlink.hpp" + +#include "application.hpp" #include "helpers.hpp" #include "singletons/settingsmanager.hpp" #include "widgets/qualitypopup.hpp" @@ -50,9 +52,9 @@ bool CheckStreamlinkPath(const QString &path) // TODO: Make streamlink binary finder smarter QString GetStreamlinkBinaryPath() { - singletons::SettingManager &settings = singletons::SettingManager::getInstance(); + auto app = getApp(); - QString settingPath = settings.streamlinkPath; + QString settingPath = app->settings->streamlinkPath; QStringList paths; paths << settingPath; @@ -111,15 +113,15 @@ void GetStreamQualities(const QString &channelURL, std::functionsettings->streamlinkOpts.getValue(); if (!additionalOptions.isEmpty()) { - arguments << settings.streamlinkOpts; + arguments << app->settings->streamlinkOpts; } arguments.append(extraArguments); @@ -135,11 +137,11 @@ void OpenStreamlink(const QString &channelURL, const QString &quality, QStringLi void Start(const QString &channel) { + auto app = getApp(); + QString channelURL = "twitch.tv/" + channel; - singletons::SettingManager &settings = singletons::SettingManager::getInstance(); - - QString preferredQuality = settings.preferredQuality; + QString preferredQuality = app->settings->preferredQuality; preferredQuality = preferredQuality.toLower(); if (preferredQuality == "choose") { diff --git a/src/util/urlfetch.hpp b/src/util/urlfetch.hpp index 5b730c08c..c4f1c31ba 100644 --- a/src/util/urlfetch.hpp +++ b/src/util/urlfetch.hpp @@ -100,8 +100,7 @@ static void put(QUrl url, std::function successCallback) { QNetworkRequest request(url); - auto &accountManager = singletons::AccountManager::getInstance(); - auto currentTwitchUser = accountManager.Twitch.getCurrent(); + auto currentTwitchUser = getApp()->accounts->Twitch.getCurrent(); QByteArray oauthToken; if (currentTwitchUser) { oauthToken = currentTwitchUser->getOAuthToken().toUtf8(); @@ -131,8 +130,7 @@ static void sendDelete(QUrl url, std::function successCallback) { QNetworkRequest request(url); - auto &accountManager = singletons::AccountManager::getInstance(); - auto currentTwitchUser = accountManager.Twitch.getCurrent(); + auto currentTwitchUser = getApp()->accounts->Twitch.getCurrent(); QByteArray oauthToken; if (currentTwitchUser) { oauthToken = currentTwitchUser->getOAuthToken().toUtf8(); diff --git a/src/widgets/accountpopup.cpp b/src/widgets/accountpopup.cpp index 7502a548a..df423f5f7 100644 --- a/src/widgets/accountpopup.cpp +++ b/src/widgets/accountpopup.cpp @@ -1,4 +1,6 @@ #include "widgets/accountpopup.hpp" + +#include "application.hpp" #include "channel.hpp" #include "credentials.hpp" #include "singletons/accountmanager.hpp" @@ -23,6 +25,8 @@ AccountPopupWidget::AccountPopupWidget(ChannelPtr _channel) , ui(new Ui::AccountPopup) , channel(_channel) { + auto app = getApp(); + this->ui->setupUi(this); this->setStayInScreenRect(true); @@ -33,15 +37,11 @@ AccountPopupWidget::AccountPopupWidget(ChannelPtr _channel) this->resize(0, 0); - auto &accountManager = singletons::AccountManager::getInstance(); - connect(this, &AccountPopupWidget::refreshButtons, this, &AccountPopupWidget::actuallyRefreshButtons, Qt::QueuedConnection); - accountManager.Twitch.userChanged.connect([this] { - singletons::AccountManager &accountManager = singletons::AccountManager::getInstance(); - - auto currentTwitchUser = accountManager.Twitch.getCurrent(); + app->accounts->Twitch.userChanged.connect([=] { + auto currentTwitchUser = app->accounts->Twitch.getCurrent(); if (!currentTwitchUser) { // No twitch user set (should never happen) return; @@ -53,8 +53,6 @@ AccountPopupWidget::AccountPopupWidget(ChannelPtr _channel) this->loggedInUser.refreshUserType(this->channel, true); }); - singletons::SettingManager &settings = singletons::SettingManager::getInstance(); - for (auto button : this->ui->profileLayout->findChildren()) { button->setFocusProxy(this); } @@ -129,19 +127,19 @@ AccountPopupWidget::AccountPopupWidget(ChannelPtr _channel) } }); - QObject::connect(this->ui->disableHighlights, &QPushButton::clicked, this, [=, &settings]() { - QString str = settings.highlightUserBlacklist; + QObject::connect(this->ui->disableHighlights, &QPushButton::clicked, this, [=]() { + QString str = app->settings->highlightUserBlacklist; str.append(this->ui->lblUsername->text() + "\n"); - settings.highlightUserBlacklist = str; + app->settings->highlightUserBlacklist = str; this->ui->disableHighlights->hide(); this->ui->enableHighlights->show(); }); - QObject::connect(this->ui->enableHighlights, &QPushButton::clicked, this, [=, &settings]() { - QString str = settings.highlightUserBlacklist; + QObject::connect(this->ui->enableHighlights, &QPushButton::clicked, this, [=]() { + QString str = app->settings->highlightUserBlacklist; QStringList list = str.split("\n"); list.removeAll(this->ui->lblUsername->text()); - settings.highlightUserBlacklist = list.join("\n"); + app->settings->highlightUserBlacklist = list.join("\n"); this->ui->enableHighlights->hide(); this->ui->disableHighlights->show(); }); @@ -279,8 +277,7 @@ void AccountPopupWidget::sendCommand(QPushButton *button, QString command) void AccountPopupWidget::refreshLayouts() { - singletons::AccountManager &accountManager = singletons::AccountManager::getInstance(); - auto currentTwitchUser = accountManager.Twitch.getCurrent(); + auto currentTwitchUser = getApp()->accounts->Twitch.getCurrent(); if (!currentTwitchUser) { // No twitch user set (should never happen) return; @@ -378,7 +375,7 @@ void AccountPopupWidget::showEvent(QShowEvent *) this->refreshLayouts(); - QString blacklisted = singletons::SettingManager::getInstance().highlightUserBlacklist; + QString blacklisted = getApp()->settings->highlightUserBlacklist; QStringList list = blacklisted.split("\n", QString::SkipEmptyParts); if (list.contains(this->ui->lblUsername->text(), Qt::CaseInsensitive)) { this->ui->disableHighlights->hide(); diff --git a/src/widgets/accountswitchwidget.cpp b/src/widgets/accountswitchwidget.cpp index ba4805185..39485b6e9 100644 --- a/src/widgets/accountswitchwidget.cpp +++ b/src/widgets/accountswitchwidget.cpp @@ -1,4 +1,6 @@ #include "accountswitchwidget.hpp" + +#include "application.hpp" #include "const.hpp" #include "singletons/accountmanager.hpp" @@ -8,22 +10,22 @@ namespace widgets { AccountSwitchWidget::AccountSwitchWidget(QWidget *parent) : QListWidget(parent) { - singletons::AccountManager &accountManager = singletons::AccountManager::getInstance(); + auto app = getApp(); this->addItem(ANONYMOUS_USERNAME_LABEL); - for (const auto &userName : accountManager.Twitch.getUsernames()) { + for (const auto &userName : app->accounts->Twitch.getUsernames()) { this->addItem(userName); } - accountManager.Twitch.userListUpdated.connect([this, &accountManager]() { + app->accounts->Twitch.userListUpdated.connect([=]() { this->blockSignals(true); this->clear(); this->addItem(ANONYMOUS_USERNAME_LABEL); - for (const auto &userName : accountManager.Twitch.getUsernames()) { + for (const auto &userName : app->accounts->Twitch.getUsernames()) { this->addItem(userName); } @@ -34,13 +36,13 @@ AccountSwitchWidget::AccountSwitchWidget(QWidget *parent) this->refreshSelection(); - QObject::connect(this, &QListWidget::clicked, [this, &accountManager] { + QObject::connect(this, &QListWidget::clicked, [=] { if (!this->selectedItems().isEmpty()) { QString newUsername = this->currentItem()->text(); if (newUsername.compare(ANONYMOUS_USERNAME_LABEL, Qt::CaseInsensitive) == 0) { - accountManager.Twitch.currentUsername = ""; + app->accounts->Twitch.currentUsername = ""; } else { - accountManager.Twitch.currentUsername = newUsername.toStdString(); + app->accounts->Twitch.currentUsername = newUsername.toStdString(); } } }); @@ -57,7 +59,9 @@ void AccountSwitchWidget::refreshSelection() // Select the currently logged in user if (this->count() > 0) { - auto currentUser = singletons::AccountManager::getInstance().Twitch.getCurrent(); + auto app = getApp(); + + auto currentUser = app->accounts->Twitch.getCurrent(); if (currentUser->isAnon()) { this->setCurrentRow(0); diff --git a/src/widgets/attachedwindow.cpp b/src/widgets/attachedwindow.cpp index a2f3f76f3..9e4c6b63c 100644 --- a/src/widgets/attachedwindow.cpp +++ b/src/widgets/attachedwindow.cpp @@ -1,5 +1,7 @@ #include "attachedwindow.hpp" +#include "application.hpp" + #include #include @@ -22,7 +24,7 @@ AttachedWindow::AttachedWindow(void *_target, int _yOffset) layout->setMargin(0); this->setLayout(layout); - auto *split = new Split(singletons::ThemeManager::getInstance(), this); + auto *split = new Split(this); this->ui.split = split; split->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::MinimumExpanding); layout->addWidget(split); diff --git a/src/widgets/basewidget.cpp b/src/widgets/basewidget.cpp index a33ec288a..74b548286 100644 --- a/src/widgets/basewidget.cpp +++ b/src/widgets/basewidget.cpp @@ -1,4 +1,6 @@ #include "widgets/basewidget.hpp" + +#include "application.hpp" #include "debug/log.hpp" #include "singletons/settingsmanager.hpp" #include "singletons/thememanager.hpp" @@ -12,16 +14,8 @@ namespace chatterino { namespace widgets { -BaseWidget::BaseWidget(singletons::ThemeManager &_themeManager, QWidget *parent, Qt::WindowFlags f) +BaseWidget::BaseWidget(QWidget *parent, Qt::WindowFlags f) : QWidget(parent, f) - , themeManager(_themeManager) -{ - this->init(); -} - -BaseWidget::BaseWidget(BaseWidget *parent, Qt::WindowFlags f) - : QWidget(parent, f) - , themeManager(singletons::ThemeManager::getInstance()) { this->init(); } @@ -87,7 +81,10 @@ void BaseWidget::setScaleIndependantHeight(int value) void BaseWidget::init() { - this->themeConnection = this->themeManager.updated.connect([this]() { + auto app = getApp(); + this->themeManager = app->themes; + + this->themeConnection = this->themeManager->updated.connect([this]() { this->themeRefreshEvent(); this->update(); diff --git a/src/widgets/basewidget.hpp b/src/widgets/basewidget.hpp index 068297e7c..998befca9 100644 --- a/src/widgets/basewidget.hpp +++ b/src/widgets/basewidget.hpp @@ -17,13 +17,9 @@ class BaseWidget : public QWidget Q_OBJECT public: - explicit BaseWidget(singletons::ThemeManager &_themeManager, QWidget *parent, - Qt::WindowFlags f = Qt::WindowFlags()); - explicit BaseWidget(BaseWidget *parent, Qt::WindowFlags f = Qt::WindowFlags()); + explicit BaseWidget(QWidget *parent, Qt::WindowFlags f = Qt::WindowFlags()); virtual ~BaseWidget(); - singletons::ThemeManager &themeManager; - float getScale() const; pajlada::Signals::Signal scaleChanged; @@ -45,6 +41,8 @@ protected: void setScale(float value); + singletons::ThemeManager *themeManager; + private: void init(); float scale = 1.f; diff --git a/src/widgets/basewindow.cpp b/src/widgets/basewindow.cpp index 49543900d..65408b5de 100644 --- a/src/widgets/basewindow.cpp +++ b/src/widgets/basewindow.cpp @@ -1,5 +1,6 @@ #include "basewindow.hpp" +#include "application.hpp" #include "debug/log.hpp" #include "singletons/settingsmanager.hpp" #include "util/nativeeventhelper.hpp" @@ -31,23 +32,8 @@ namespace chatterino { namespace widgets { -BaseWindow::BaseWindow(singletons::ThemeManager &_themeManager, QWidget *parent, - bool _enableCustomFrame) - : BaseWidget(_themeManager, parent, Qt::Window) - , enableCustomFrame(_enableCustomFrame) -{ - this->init(); -} - -BaseWindow::BaseWindow(BaseWidget *parent, bool _enableCustomFrame) - : BaseWidget(parent, Qt::Window) - , enableCustomFrame(_enableCustomFrame) -{ - this->init(); -} - BaseWindow::BaseWindow(QWidget *parent, bool _enableCustomFrame) - : BaseWidget(singletons::ThemeManager::getInstance(), parent, Qt::Window) + : BaseWidget(parent, Qt::Window) , enableCustomFrame(_enableCustomFrame) { this->init(); @@ -55,6 +41,8 @@ BaseWindow::BaseWindow(QWidget *parent, bool _enableCustomFrame) void BaseWindow::init() { + auto app = getApp(); + this->setWindowIcon(QIcon(":/images/icon.png")); #ifdef USEWINSDK @@ -127,7 +115,7 @@ void BaseWindow::init() } #endif - if (singletons::SettingManager::getInstance().windowTopMost.getValue()) { + if (app->settings->windowTopMost.getValue()) { this->setWindowFlags(this->windowFlags() | Qt::WindowStaysOnTopHint); } } @@ -167,21 +155,21 @@ void BaseWindow::themeRefreshEvent() if (this->hasCustomWindowFrame()) { QPalette palette; palette.setColor(QPalette::Background, QColor(0, 0, 0, 0)); - palette.setColor(QPalette::Foreground, this->themeManager.window.text); + palette.setColor(QPalette::Foreground, this->themeManager->window.text); this->setPalette(palette); QPalette palette_title; palette_title.setColor(QPalette::Foreground, - this->themeManager.isLightTheme() ? "#333" : "#ccc"); + this->themeManager->isLightTheme() ? "#333" : "#ccc"); this->ui.titleLabel->setPalette(palette_title); for (RippleEffectButton *button : this->ui.buttons) { - button->setMouseEffectColor(this->themeManager.window.text); + button->setMouseEffectColor(this->themeManager->window.text); } } else { QPalette palette; - palette.setColor(QPalette::Background, this->themeManager.window.background); - palette.setColor(QPalette::Foreground, this->themeManager.window.text); + palette.setColor(QPalette::Background, this->themeManager->window.background); + palette.setColor(QPalette::Foreground, this->themeManager->window.text); this->setPalette(palette); } } @@ -430,7 +418,7 @@ void BaseWindow::paintEvent(QPaintEvent *event) // bool windowFocused = this->window() == QApplication::activeWindow(); painter.fillRect(QRect(0, 1, this->width() - 0, this->height() - 0), - this->themeManager.window.background); + this->themeManager->window.background); } } diff --git a/src/widgets/basewindow.hpp b/src/widgets/basewindow.hpp index 171e2e1d9..c1a65afbc 100644 --- a/src/widgets/basewindow.hpp +++ b/src/widgets/basewindow.hpp @@ -19,9 +19,6 @@ class BaseWindow : public BaseWidget Q_OBJECT public: - explicit BaseWindow(singletons::ThemeManager &_themeManager, QWidget *parent, - bool enableCustomFrame = false); - explicit BaseWindow(BaseWidget *parent, bool enableCustomFrame = false); explicit BaseWindow(QWidget *parent = nullptr, bool enableCustomFrame = false); QWidget *getLayoutContainer(); diff --git a/src/widgets/emotepopup.cpp b/src/widgets/emotepopup.cpp index 134923d9d..854965789 100644 --- a/src/widgets/emotepopup.cpp +++ b/src/widgets/emotepopup.cpp @@ -1,21 +1,22 @@ #include "emotepopup.hpp" -#include -#include - +#include "application.hpp" #include "messages/messagebuilder.hpp" #include "providers/twitch/twitchchannel.hpp" #include "singletons/accountmanager.hpp" #include "widgets/notebook.hpp" +#include +#include + using namespace chatterino::providers::twitch; using namespace chatterino::messages; namespace chatterino { namespace widgets { -EmotePopup::EmotePopup(singletons::ThemeManager &themeManager) - : BaseWindow(themeManager, nullptr, true) +EmotePopup::EmotePopup() + : BaseWindow(nullptr, true) { this->viewEmotes = new ChannelView(); this->viewEmojis = new ChannelView(); @@ -80,16 +81,16 @@ void EmotePopup::loadChannel(ChannelPtr _channel) emoteChannel->addMessage(builder2.getMessage()); }; - singletons::EmoteManager &emoteManager = singletons::EmoteManager::getInstance(); + auto app = getApp(); - QString userID = singletons::AccountManager::getInstance().Twitch.getCurrent()->getUserId(); + QString userID = app->accounts->Twitch.getCurrent()->getUserId(); - addEmotes(emoteManager.twitchAccountEmotes[userID.toStdString()].emotes, + addEmotes(app->emotes->twitchAccountEmotes[userID.toStdString()].emotes, "Twitch Account Emotes", "Twitch Account Emote"); - addEmotes(emoteManager.bttvGlobalEmotes, "BetterTTV Global Emotes", "BetterTTV Global Emote"); + addEmotes(app->emotes->bttvGlobalEmotes, "BetterTTV Global Emotes", "BetterTTV Global Emote"); addEmotes(*channel->bttvChannelEmotes.get(), "BetterTTV Channel Emotes", "BetterTTV Channel Emote"); - addEmotes(emoteManager.ffzGlobalEmotes, "FrankerFaceZ Global Emotes", + addEmotes(app->emotes->ffzGlobalEmotes, "FrankerFaceZ Global Emotes", "FrankerFaceZ Global Emote"); addEmotes(*channel->ffzChannelEmotes.get(), "FrankerFaceZ Channel Emotes", "FrankerFaceZ Channel Emote"); @@ -99,7 +100,7 @@ void EmotePopup::loadChannel(ChannelPtr _channel) void EmotePopup::loadEmojis() { - auto &emojis = singletons::EmoteManager::getInstance().getEmojis(); + auto &emojis = getApp()->emotes->getEmojis(); ChannelPtr emojiChannel(new Channel("", Channel::None)); diff --git a/src/widgets/emotepopup.hpp b/src/widgets/emotepopup.hpp index 53fd9885d..67a805cb4 100644 --- a/src/widgets/emotepopup.hpp +++ b/src/widgets/emotepopup.hpp @@ -12,7 +12,7 @@ namespace widgets { class EmotePopup : public BaseWindow { public: - explicit EmotePopup(singletons::ThemeManager &); + EmotePopup(); void loadChannel(ChannelPtr channel); void loadEmojis(); diff --git a/src/widgets/helper/channelview.cpp b/src/widgets/helper/channelview.cpp index 628a2c0f2..4797f0d08 100644 --- a/src/widgets/helper/channelview.cpp +++ b/src/widgets/helper/channelview.cpp @@ -1,4 +1,6 @@ #include "channelview.hpp" + +#include "application.hpp" #include "debug/log.hpp" #include "messages/layouts/messagelayout.hpp" #include "messages/limitedqueuesnapshot.hpp" @@ -38,14 +40,17 @@ ChannelView::ChannelView(BaseWidget *parent) , scrollBar(this) , userPopupWidget(std::shared_ptr()) { + auto app = getApp(); + #ifndef Q_OS_MAC // this->setAttribute(Qt::WA_OpaquePaintEvent); #endif this->setMouseTracking(true); - QObject::connect(&singletons::SettingManager::getInstance(), - &singletons::SettingManager::wordFlagsChanged, this, - &ChannelView::wordFlagsChanged); + this->managedConnections.emplace_back(app->settings->wordFlagsChanged.connect([=] { + this->layoutMessages(); + this->update(); + })); this->scrollBar.getCurrentValueChanged().connect([this] { // Whenever the scrollbar value has been changed, re-render the ChatWidgetView @@ -56,10 +61,10 @@ ChannelView::ChannelView(BaseWidget *parent) this->queueUpdate(); }); - singletons::WindowManager &windowManager = singletons::WindowManager::getInstance(); - - this->repaintGifsConnection = windowManager.repaintGifs.connect([&] { this->queueUpdate(); }); - this->layoutConnection = windowManager.layout.connect([&](Channel *channel) { + this->repaintGifsConnection = app->windows->repaintGifs.connect([&] { + this->queueUpdate(); // + }); + this->layoutConnection = app->windows->layout.connect([&](Channel *channel) { if (channel == nullptr || this->channel.get() == channel) { this->layoutMessages(); } @@ -75,10 +80,10 @@ ChannelView::ChannelView(BaseWidget *parent) this->layoutMessages(); // })); - connect(goToBottom, &RippleEffectLabel::clicked, this, [this] { - QTimer::singleShot(180, [this] { - this->scrollBar.scrollToBottom(singletons::SettingManager::getInstance() - .enableSmoothScrollingNewMessages.getValue()); + connect(goToBottom, &RippleEffectLabel::clicked, this, [=] { + QTimer::singleShot(180, [=] { + this->scrollBar.scrollToBottom( + app->settings->enableSmoothScrollingNewMessages.getValue()); }); }); @@ -100,8 +105,11 @@ ChannelView::ChannelView(BaseWidget *parent) this->scrollBar.resize(this->scrollBar.width(), this->height() + 1); - singletons::SettingManager::getInstance().showLastMessageIndicator.connect( - [this](auto, auto) { this->update(); }, this->managedConnections); + app->settings->showLastMessageIndicator.connect( + [this](auto, auto) { + this->update(); // + }, + this->managedConnections); this->layoutCooldown = new QTimer(this); this->layoutCooldown->setSingleShot(true); @@ -117,9 +125,6 @@ ChannelView::ChannelView(BaseWidget *parent) ChannelView::~ChannelView() { - QObject::disconnect(&singletons::SettingManager::getInstance(), - &singletons::SettingManager::wordFlagsChanged, this, - &ChannelView::wordFlagsChanged); this->messageAppendedConnection.disconnect(); this->messageRemovedConnection.disconnect(); this->repaintGifsConnection.disconnect(); @@ -161,6 +166,8 @@ void ChannelView::layoutMessages() void ChannelView::actuallyLayoutMessages() { + auto app = getApp(); + // BENCH(timer) auto messagesSnapshot = this->getMessagesSnapshot(); @@ -238,9 +245,8 @@ void ChannelView::actuallyLayoutMessages() // Perhaps also if the user scrolled with the scrollwheel in this ChatWidget in the last 0.2 // seconds or something if (this->enableScrollingToBottom && this->showingLatestMessages && showScrollbar) { - this->scrollBar.scrollToBottom( - this->messageWasAdded && - singletons::SettingManager::getInstance().enableSmoothScrollingNewMessages.getValue()); + this->scrollBar.scrollToBottom(this->messageWasAdded && + app->settings->enableSmoothScrollingNewMessages.getValue()); this->messageWasAdded = false; } @@ -494,11 +500,13 @@ void ChannelView::setSelection(const SelectionItem &start, const SelectionItem & messages::MessageElement::Flags ChannelView::getFlags() const { + auto app = getApp(); + if (this->overrideFlags) { return this->overrideFlags.get(); } - MessageElement::Flags flags = singletons::SettingManager::getInstance().getWordFlags(); + MessageElement::Flags flags = app->settings->getWordFlags(); Split *split = dynamic_cast(this->parentWidget()); @@ -520,7 +528,7 @@ void ChannelView::paintEvent(QPaintEvent * /*event*/) QPainter painter(this); - painter.fillRect(rect(), this->themeManager.splits.background); + painter.fillRect(rect(), this->themeManager->splits.background); // draw messages this->drawMessages(painter); @@ -532,6 +540,8 @@ void ChannelView::paintEvent(QPaintEvent * /*event*/) // overlay when a message is disabled void ChannelView::drawMessages(QPainter &painter) { + auto app = getApp(); + auto messagesSnapshot = this->getMessagesSnapshot(); size_t start = this->scrollBar.getCurrentValue(); @@ -550,7 +560,7 @@ void ChannelView::drawMessages(QPainter &painter) messages::MessageLayout *layout = messagesSnapshot[i].get(); bool isLastMessage = false; - if (singletons::SettingManager::getInstance().showLastMessageIndicator) { + if (app->settings->showLastMessageIndicator) { isLastMessage = this->lastReadMessage.get() == layout; } @@ -599,7 +609,9 @@ void ChannelView::drawMessages(QPainter &painter) void ChannelView::wheelEvent(QWheelEvent *event) { if (this->scrollBar.isVisible()) { - float mouseMultiplier = singletons::SettingManager::getInstance().mouseScrollMultiplier; + auto app = getApp(); + + float mouseMultiplier = app->settings->mouseScrollMultiplier; float desired = this->scrollBar.getDesiredValue(); float delta = event->delta() * 1.5 * mouseMultiplier; @@ -677,7 +689,9 @@ void ChannelView::mouseMoveEvent(QMouseEvent *event) return; } - if (singletons::SettingManager::getInstance().pauseChatHover.getValue()) { + auto app = getApp(); + + if (app->settings->pauseChatHover.getValue()) { this->pause(300); } @@ -745,7 +759,9 @@ void ChannelView::mousePressEvent(QMouseEvent *event) return; } - if (singletons::SettingManager::getInstance().linksDoubleClickOnly.getValue()) { + auto app = getApp(); + + if (app->settings->linksDoubleClickOnly.getValue()) { this->pause(200); } @@ -808,6 +824,8 @@ void ChannelView::mouseReleaseEvent(QMouseEvent *event) return; } + auto app = getApp(); + if (this->selecting) { this->paused = false; } @@ -852,8 +870,7 @@ void ChannelView::mouseReleaseEvent(QMouseEvent *event) } auto &link = hoverLayoutElement->getLink(); - if (event->button() != Qt::LeftButton || - !singletons::SettingManager::getInstance().linksDoubleClickOnly) { + if (event->button() != Qt::LeftButton || !app->settings->linksDoubleClickOnly) { this->handleLinkClick(event, link, layout.get()); } @@ -862,7 +879,9 @@ void ChannelView::mouseReleaseEvent(QMouseEvent *event) void ChannelView::mouseDoubleClickEvent(QMouseEvent *event) { - if (singletons::SettingManager::getInstance().linksDoubleClickOnly) { + auto app = getApp(); + + if (app->settings->linksDoubleClickOnly) { std::shared_ptr layout; QPoint relativePos; int messageIndex; diff --git a/src/widgets/helper/droppreview.cpp b/src/widgets/helper/droppreview.cpp index 43e1d3ade..237c06199 100644 --- a/src/widgets/helper/droppreview.cpp +++ b/src/widgets/helper/droppreview.cpp @@ -20,7 +20,7 @@ void NotebookPageDropPreview::paintEvent(QPaintEvent *) QPainter painter(this); painter.fillRect(8, 8, this->width() - 17, this->height() - 17, - this->themeManager.splits.dropPreview); + this->themeManager->splits.dropPreview); } void NotebookPageDropPreview::hideEvent(QHideEvent *) diff --git a/src/widgets/helper/notebookbutton.cpp b/src/widgets/helper/notebookbutton.cpp index eb7bf6879..48d977164 100644 --- a/src/widgets/helper/notebookbutton.cpp +++ b/src/widgets/helper/notebookbutton.cpp @@ -22,7 +22,7 @@ NotebookButton::NotebookButton(BaseWidget *parent) void NotebookButton::themeRefreshEvent() { - this->setMouseEffectColor(this->themeManager.tabs.regular.text); + this->setMouseEffectColor(this->themeManager->tabs.regular.text); } void NotebookButton::paintEvent(QPaintEvent *) @@ -33,11 +33,11 @@ void NotebookButton::paintEvent(QPaintEvent *) QColor foreground; if (mouseDown || mouseOver) { - background = this->themeManager.tabs.regular.backgrounds.hover.color(); - foreground = this->themeManager.tabs.regular.text; + background = this->themeManager->tabs.regular.backgrounds.hover.color(); + foreground = this->themeManager->tabs.regular.text; } else { - background = this->themeManager.tabs.regular.backgrounds.regular.color(); - foreground = this->themeManager.tabs.regular.text; + background = this->themeManager->tabs.regular.backgrounds.regular.color(); + foreground = this->themeManager->tabs.regular.text; } painter.setPen(Qt::NoPen); diff --git a/src/widgets/helper/notebooktab.cpp b/src/widgets/helper/notebooktab.cpp index e65a9f388..633b691cb 100644 --- a/src/widgets/helper/notebooktab.cpp +++ b/src/widgets/helper/notebooktab.cpp @@ -1,4 +1,6 @@ #include "widgets/helper/notebooktab.hpp" + +#include "application.hpp" #include "common.hpp" #include "debug/log.hpp" #include "singletons/settingsmanager.hpp" @@ -23,12 +25,14 @@ NotebookTab2::NotebookTab2(Notebook2 *_notebook) , notebook(_notebook) , menu(this) { + auto app = getApp(); + this->setAcceptDrops(true); this->positionChangedAnimation.setEasingCurve(QEasingCurve(QEasingCurve::InCubic)); - singletons::SettingManager::getInstance().hideTabX.connect( - boost::bind(&NotebookTab2::hideTabXChanged, this, _1), this->managedConnections); + app->settings->hideTabX.connect(boost::bind(&NotebookTab2::hideTabXChanged, this, _1), + this->managedConnections); this->setMouseTracking(true); @@ -77,12 +81,13 @@ void NotebookTab2::themeRefreshEvent() void NotebookTab2::updateSize() { + auto app = getApp(); float scale = getScale(); int width; QFontMetrics metrics(this->font()); - if (singletons::SettingManager::getInstance().hideTabX) { + if (app->settings->hideTabX) { width = (int)((metrics.width(this->title) + 16 /*+ 16*/) * scale); } else { width = (int)((metrics.width(this->title) + 8 + 24 /*+ 16*/) * scale); @@ -173,7 +178,7 @@ void NotebookTab2::moveAnimated(QPoint pos, bool animated) void NotebookTab2::paintEvent(QPaintEvent *) { - singletons::SettingManager &settingManager = singletons::SettingManager::getInstance(); + auto app = getApp(); QPainter painter(this); float scale = this->getScale(); @@ -182,16 +187,16 @@ void NotebookTab2::paintEvent(QPaintEvent *) // select the right tab colors singletons::ThemeManager::TabColors colors; - singletons::ThemeManager::TabColors regular = this->themeManager.tabs.regular; + singletons::ThemeManager::TabColors regular = this->themeManager->tabs.regular; if (this->selected) { - colors = this->themeManager.tabs.selected; + colors = this->themeManager->tabs.selected; } else if (this->highlightState == HighlightState::Highlighted) { - colors = this->themeManager.tabs.highlighted; + colors = this->themeManager->tabs.highlighted; } else if (this->highlightState == HighlightState::NewMessage) { - colors = this->themeManager.tabs.newMessage; + colors = this->themeManager->tabs.newMessage; } else { - colors = this->themeManager.tabs.regular; + colors = this->themeManager->tabs.regular; } bool windowFocused = this->window() == QApplication::activeWindow(); @@ -248,7 +253,7 @@ void NotebookTab2::paintEvent(QPaintEvent *) painter.setPen(colors.text); // set area for text - int rectW = (settingManager.hideTabX ? 0 : static_cast(16) * scale); + int rectW = (app->settings->hideTabX ? 0 : static_cast(16) * scale); QRect rect(0, 0, this->width() - rectW, height); // draw text @@ -269,7 +274,7 @@ void NotebookTab2::paintEvent(QPaintEvent *) } // draw close x - if (!settingManager.hideTabX && (mouseOver || selected)) { + if (!app->settings->hideTabX && (mouseOver || selected)) { QRect xRect = this->getXRect(); if (!xRect.isNull()) { if (mouseOverX) { @@ -315,7 +320,7 @@ void NotebookTab2::mouseReleaseEvent(QMouseEvent *event) this->notebook->removePage(this->page); } } else { - if (!singletons::SettingManager::getInstance().hideTabX && this->mouseDownX && + if (!getApp()->settings->hideTabX && this->mouseDownX && this->getXRect().contains(event->pos())) { this->mouseDownX = false; @@ -350,8 +355,9 @@ void NotebookTab2::dragEnterEvent(QDragEnterEvent *) void NotebookTab2::mouseMoveEvent(QMouseEvent *event) { - if (!singletons::SettingManager::getInstance().hideTabX && - this->notebook->getAllowUserTabManagement()) // + auto app = getApp(); + + if (!app->settings->hideTabX && this->notebook->getAllowUserTabManagement()) // { bool overX = this->getXRect().contains(event->pos()); @@ -397,12 +403,14 @@ NotebookTab::NotebookTab(Notebook *_notebook) , notebook(_notebook) , menu(this) { + auto app = getApp(); + this->setAcceptDrops(true); this->positionChangedAnimation.setEasingCurve(QEasingCurve(QEasingCurve::InCubic)); - singletons::SettingManager::getInstance().hideTabX.connect( - boost::bind(&NotebookTab::hideTabXChanged, this, _1), this->managedConnections); + app->settings->hideTabX.connect(boost::bind(&NotebookTab::hideTabXChanged, this, _1), + this->managedConnections); this->setMouseTracking(true); @@ -449,11 +457,13 @@ void NotebookTab::themeRefreshEvent() void NotebookTab::updateSize() { + auto app = getApp(); + float scale = getScale(); int width; - if (singletons::SettingManager::getInstance().hideTabX) { + if (app->settings->hideTabX) { width = (int)((fontMetrics().width(this->title) + 16 /*+ 16*/) * scale); } else { width = (int)((fontMetrics().width(this->title) + 8 + 24 /*+ 16*/) * scale); @@ -544,7 +554,7 @@ void NotebookTab::moveAnimated(QPoint pos, bool animated) void NotebookTab::paintEvent(QPaintEvent *) { - singletons::SettingManager &settingManager = singletons::SettingManager::getInstance(); + auto app = getApp(); QPainter painter(this); float scale = this->getScale(); @@ -553,16 +563,16 @@ void NotebookTab::paintEvent(QPaintEvent *) // select the right tab colors singletons::ThemeManager::TabColors colors; - singletons::ThemeManager::TabColors regular = this->themeManager.tabs.regular; + singletons::ThemeManager::TabColors regular = this->themeManager->tabs.regular; if (this->selected) { - colors = this->themeManager.tabs.selected; + colors = this->themeManager->tabs.selected; } else if (this->highlightState == HighlightState::Highlighted) { - colors = this->themeManager.tabs.highlighted; + colors = this->themeManager->tabs.highlighted; } else if (this->highlightState == HighlightState::NewMessage) { - colors = this->themeManager.tabs.newMessage; + colors = this->themeManager->tabs.newMessage; } else { - colors = this->themeManager.tabs.regular; + colors = this->themeManager->tabs.regular; } bool windowFocused = this->window() == QApplication::activeWindow(); @@ -619,7 +629,7 @@ void NotebookTab::paintEvent(QPaintEvent *) painter.setPen(colors.text); // set area for text - int rectW = (settingManager.hideTabX ? 0 : static_cast(16) * scale); + int rectW = (app->settings->hideTabX ? 0 : static_cast(16) * scale); QRect rect(0, 0, this->width() - rectW, height); // draw text @@ -640,7 +650,7 @@ void NotebookTab::paintEvent(QPaintEvent *) } // draw close x - if (!settingManager.hideTabX && (mouseOver || selected)) { + if (!app->settings->hideTabX && (mouseOver || selected)) { QRect xRect = this->getXRect(); if (mouseOverX) { painter.fillRect(xRect, QColor(0, 0, 0, 64)); @@ -675,6 +685,8 @@ void NotebookTab::mousePressEvent(QMouseEvent *event) void NotebookTab::mouseReleaseEvent(QMouseEvent *event) { + auto app = getApp(); + this->mouseDown = false; if (event->button() == Qt::MiddleButton) { @@ -682,7 +694,7 @@ void NotebookTab::mouseReleaseEvent(QMouseEvent *event) this->notebook->removePage(this->page); } } else { - if (!singletons::SettingManager::getInstance().hideTabX && this->mouseDownX && + if (!app->settings->hideTabX && this->mouseDownX && this->getXRect().contains(event->pos())) { this->mouseDownX = false; @@ -715,7 +727,9 @@ void NotebookTab::dragEnterEvent(QDragEnterEvent *) void NotebookTab::mouseMoveEvent(QMouseEvent *event) { - if (!singletons::SettingManager::getInstance().hideTabX) { + auto app = getApp(); + + if (!app->settings->hideTabX) { bool overX = this->getXRect().contains(event->pos()); if (overX != this->mouseOverX) { diff --git a/src/widgets/helper/rippleeffectbutton.cpp b/src/widgets/helper/rippleeffectbutton.cpp index 9462cf118..78f80a4c1 100644 --- a/src/widgets/helper/rippleeffectbutton.cpp +++ b/src/widgets/helper/rippleeffectbutton.cpp @@ -64,7 +64,7 @@ void RippleEffectButton::fancyPaint(QPainter &painter) if (this->mouseEffectColor) { c = this->mouseEffectColor.get(); } else { - c = this->themeManager.isLightTheme() ? QColor(0, 0, 0) : QColor(255, 255, 255); + c = this->themeManager->isLightTheme() ? QColor(0, 0, 0) : QColor(255, 255, 255); } if (this->hoverMultiplier > 0) { diff --git a/src/widgets/helper/splitheader.cpp b/src/widgets/helper/splitheader.cpp index 1d1c35d33..e01b65b52 100644 --- a/src/widgets/helper/splitheader.cpp +++ b/src/widgets/helper/splitheader.cpp @@ -218,8 +218,8 @@ void SplitHeader::paintEvent(QPaintEvent *) { QPainter painter(this); - painter.fillRect(rect(), this->themeManager.splits.header.background); - painter.setPen(this->themeManager.splits.header.border); + painter.fillRect(rect(), this->themeManager->splits.header.background); + painter.setPen(this->themeManager->splits.header.border); painter.drawRect(0, 0, width() - 1, height() - 1); } @@ -268,7 +268,7 @@ void SplitHeader::rightButtonClicked() void SplitHeader::themeRefreshEvent() { QPalette palette; - palette.setColor(QPalette::Foreground, this->themeManager.splits.header.text); + palette.setColor(QPalette::Foreground, this->themeManager->splits.header.text); // this->dropdownButton->setPalette(palette); this->titleLabel->setPalette(palette); diff --git a/src/widgets/helper/splitinput.cpp b/src/widgets/helper/splitinput.cpp index 3569a0d4f..85272306f 100644 --- a/src/widgets/helper/splitinput.cpp +++ b/src/widgets/helper/splitinput.cpp @@ -1,4 +1,6 @@ #include "widgets/helper/splitinput.hpp" + +#include "application.hpp" #include "singletons/commandmanager.hpp" #include "singletons/ircmanager.hpp" #include "singletons/settingsmanager.hpp" @@ -36,6 +38,7 @@ SplitInput::SplitInput(Split *_chatWidget) void SplitInput::initLayout() { + auto app = getApp(); auto &fontManager = singletons::FontManager::getInstance(); util::LayoutCreator layoutCreator(this); @@ -73,7 +76,7 @@ void SplitInput::initLayout() // open emote popup QObject::connect(this->ui.emoteButton, &RippleEffectLabel::clicked, [this] { if (!this->emotePopup) { - this->emotePopup = std::make_unique(this->themeManager); + this->emotePopup = std::make_unique(); this->emotePopup->linkClicked.connect([this](const messages::Link &link) { if (link.type == messages::Link::InsertText) { this->insertText(link.value + " "); @@ -95,7 +98,7 @@ void SplitInput::initLayout() }); // textEditLength visibility - singletons::SettingManager::getInstance().showMessageLength.connect( + app->settings->showMessageLength.connect( [this](const bool &value, auto) { this->ui.textEditLength->setHidden(!value); }, this->managedConnections); } @@ -117,18 +120,20 @@ void SplitInput::themeRefreshEvent() { QPalette palette; - palette.setColor(QPalette::Foreground, this->themeManager.splits.input.text); + palette.setColor(QPalette::Foreground, this->themeManager->splits.input.text); this->ui.textEditLength->setPalette(palette); - this->ui.textEdit->setStyleSheet(this->themeManager.splits.input.styleSheet); + this->ui.textEdit->setStyleSheet(this->themeManager->splits.input.styleSheet); - this->ui.hbox->setMargin((this->themeManager.isLightTheme() ? 4 : 2) * this->getScale()); + this->ui.hbox->setMargin((this->themeManager->isLightTheme() ? 4 : 2) * this->getScale()); } void SplitInput::installKeyPressedEvent() { - this->ui.textEdit->keyPressed.connect([this](QKeyEvent *event) { + auto app = getApp(); + + this->ui.textEdit->keyPressed.connect([this, app](QKeyEvent *event) { if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return) { auto c = this->chatWidget->getChannel(); if (c == nullptr) { @@ -136,8 +141,7 @@ void SplitInput::installKeyPressedEvent() } QString message = ui.textEdit->toPlainText(); - QString sendMessage = - singletons::CommandManager::getInstance().execCommand(message, c, false); + QString sendMessage = app->commands->execCommand(message, c, false); sendMessage = sendMessage.replace('\n', ' '); c->sendMessage(sendMessage); @@ -278,6 +282,8 @@ void SplitInput::insertText(const QString &text) void SplitInput::editTextChanged() { + auto app = getApp(); + // set textLengthLabel value QString text = this->ui.textEdit->toPlainText(); @@ -287,8 +293,7 @@ void SplitInput::editTextChanged() static QRegularExpression spaceRegex("\\s\\s+"); text = text.replace(spaceRegex, " "); - text = singletons::CommandManager::getInstance().execCommand( - text, this->chatWidget->getChannel(), true); + text = app->commands->execCommand(text, this->chatWidget->getChannel(), true); QString labelText; @@ -305,10 +310,10 @@ void SplitInput::paintEvent(QPaintEvent *) { QPainter painter(this); - painter.fillRect(this->rect(), this->themeManager.splits.input.background); + painter.fillRect(this->rect(), this->themeManager->splits.input.background); - QPen pen(this->themeManager.splits.input.border); - if (this->themeManager.isLightTheme()) { + QPen pen(this->themeManager->splits.input.border); + if (this->themeManager->isLightTheme()) { pen.setWidth((int)(6 * this->getScale())); } painter.setPen(pen); diff --git a/src/widgets/helper/titlebarbutton.cpp b/src/widgets/helper/titlebarbutton.cpp index 1ff5f56a9..3caa4ec19 100644 --- a/src/widgets/helper/titlebarbutton.cpp +++ b/src/widgets/helper/titlebarbutton.cpp @@ -25,8 +25,8 @@ void TitleBarButton::paintEvent(QPaintEvent *) { QPainter painter(this); - QColor color = this->themeManager.window.text; - QColor background = this->themeManager.window.background; + QColor color = this->themeManager->window.text; + QColor background = this->themeManager->window.background; int xD = this->height() / 3; int centerX = this->width() / 2; @@ -49,7 +49,7 @@ void TitleBarButton::paintEvent(QPaintEvent *) painter.drawRect(centerX - xD / 2 + xD2, xD, xD3, xD3); painter.fillRect(centerX - xD / 2, xD + xD2, xD3, xD3, - this->themeManager.window.background); + this->themeManager->window.background); painter.drawRect(centerX - xD / 2, xD + xD2, xD3, xD3); break; } diff --git a/src/widgets/logindialog.cpp b/src/widgets/logindialog.cpp index ac27aa41f..741276689 100644 --- a/src/widgets/logindialog.cpp +++ b/src/widgets/logindialog.cpp @@ -50,7 +50,7 @@ void LogInWithCredentials(const std::string &userID, const std::string &username pajlada::Settings::Setting::set("/accounts/uid" + userID + "/oauthToken", oauthToken); - singletons::AccountManager::getInstance().Twitch.reloadUsers(); + getApp()->accounts->Twitch.reloadUsers(); messageBox.exec(); } diff --git a/src/widgets/notebook.cpp b/src/widgets/notebook.cpp index ed4f59cbf..06e21b798 100644 --- a/src/widgets/notebook.cpp +++ b/src/widgets/notebook.cpp @@ -1,4 +1,6 @@ #include "widgets/notebook.hpp" + +#include "application.hpp" #include "debug/log.hpp" #include "singletons/thememanager.hpp" #include "singletons/windowmanager.hpp" @@ -24,7 +26,7 @@ namespace chatterino { namespace widgets { Notebook2::Notebook2(QWidget *parent) - : BaseWidget(singletons::ThemeManager::getInstance(), parent) + : BaseWidget(parent) , addButton(this) { this->addButton.setHidden(true); @@ -258,7 +260,7 @@ void Notebook2::resizeEvent(QResizeEvent *) void Notebook2::performLayout(bool animated) { - singletons::SettingManager &settings = singletons::SettingManager::getInstance(); + auto app = getApp(); int xStart = (int)(2 * this->getScale()); @@ -269,13 +271,13 @@ void Notebook2::performLayout(bool animated) // bool customFrame = false; - // if (!this->showButtons || settings.hidePreferencesButton || customFrame) { + // if (!this->showButtons || app->settings->hidePreferencesButton || customFrame) { // this->settingsButton.hide(); // } else { // this->settingsButton.show(); // x += settingsButton.width(); // } - // if (!this->showButtons || settings.hideUserButton || customFrame) { + // if (!this->showButtons || app->settings->hideUserButton || customFrame) { // this->userButton.hide(); // } else { // this->userButton.move(x, 0); @@ -284,7 +286,7 @@ void Notebook2::performLayout(bool animated) // } // if (customFrame || !this->showButtons || - // (settings.hideUserButton && settings.hidePreferencesButton)) { + // (app->settings->hideUserButton && app->settings->hidePreferencesButton)) { // x += (int)(scale * 2); // } @@ -342,7 +344,7 @@ void Notebook2::paintEvent(QPaintEvent *event) QPainter painter(this); painter.fillRect(0, this->lineY, this->width(), (int)(1 * this->getScale()), - this->themeManager.tabs.bottomLine); + this->themeManager->tabs.bottomLine); } NotebookTab2 *Notebook2::getTabFromPage(QWidget *page) @@ -366,6 +368,8 @@ Notebook::Notebook(Window *parent, bool _showButtons) , showButtons(_showButtons) , closeConfirmDialog(this) { + auto app = getApp(); + this->connect(&this->settingsButton, SIGNAL(clicked()), this, SLOT(settingsButtonClicked())); this->connect(&this->userButton, SIGNAL(clicked()), this, SLOT(usersButtonClicked())); this->connect(&this->addButton, SIGNAL(clicked()), this, SLOT(addPageButtonClicked())); @@ -375,10 +379,8 @@ Notebook::Notebook(Window *parent, bool _showButtons) this->userButton.move(24, 0); this->userButton.icon = NotebookButton::IconUser; - auto &settingsManager = singletons::SettingManager::getInstance(); - - settingsManager.hidePreferencesButton.connectSimple([this](auto) { this->performLayout(); }); - settingsManager.hideUserButton.connectSimple([this](auto) { this->performLayout(); }); + app->settings->hidePreferencesButton.connectSimple([this](auto) { this->performLayout(); }); + app->settings->hideUserButton.connectSimple([this](auto) { this->performLayout(); }); closeConfirmDialog.setText("Are you sure you want to close this tab?"); closeConfirmDialog.setIcon(QMessageBox::Icon::Question); @@ -568,19 +570,19 @@ void Notebook::previousTab() void Notebook::performLayout(bool animated) { - singletons::SettingManager &settings = singletons::SettingManager::getInstance(); + auto app = getApp(); int x = 0, y = 0; float scale = this->getScale(); bool customFrame = this->parentWindow->hasCustomWindowFrame(); - if (!this->showButtons || settings.hidePreferencesButton || customFrame) { + if (!this->showButtons || app->settings->hidePreferencesButton || customFrame) { this->settingsButton.hide(); } else { this->settingsButton.show(); x += settingsButton.width(); } - if (!this->showButtons || settings.hideUserButton || customFrame) { + if (!this->showButtons || app->settings->hideUserButton || customFrame) { this->userButton.hide(); } else { this->userButton.move(x, 0); @@ -589,7 +591,7 @@ void Notebook::performLayout(bool animated) } if (customFrame || !this->showButtons || - (settings.hideUserButton && settings.hidePreferencesButton)) { + (app->settings->hideUserButton && app->settings->hidePreferencesButton)) { x += (int)(scale * 2); } @@ -654,12 +656,14 @@ void Notebook::scaleChangedEvent(float) void Notebook::settingsButtonClicked() { - singletons::WindowManager::getInstance().showSettingsDialog(); + auto app = getApp(); + app->windows->showSettingsDialog(); } void Notebook::usersButtonClicked() { - singletons::WindowManager::getInstance().showAccountSelectPopup( + auto app = getApp(); + app->windows->showAccountSelectPopup( this->mapToGlobal(this->userButton.rect().bottomRight())); } diff --git a/src/widgets/scrollbar.cpp b/src/widgets/scrollbar.cpp index 2525ddf89..01df63211 100644 --- a/src/widgets/scrollbar.cpp +++ b/src/widgets/scrollbar.cpp @@ -1,4 +1,6 @@ #include "widgets/scrollbar.hpp" + +#include "application.hpp" #include "singletons/thememanager.hpp" #include "widgets/helper/channelview.hpp" @@ -6,6 +8,7 @@ #include #include #include + #include #define MIN_THUMB_HEIGHT 10 @@ -16,7 +19,6 @@ namespace widgets { Scrollbar::Scrollbar(ChannelView *parent) : BaseWidget(parent) , currentValueAnimation(this, "currentValue") - , smoothScrollingSetting(singletons::SettingManager::getInstance().enableSmoothScrolling) { resize((int)(16 * this->getScale()), 100); this->currentValueAnimation.setDuration(150); @@ -92,7 +94,8 @@ void Scrollbar::setSmallChange(qreal value) void Scrollbar::setDesiredValue(qreal value, bool animated) { - animated &= this->smoothScrollingSetting.getValue(); + auto app = getApp(); + animated &= app->settings->enableSmoothScrolling.getValue(); value = std::max(this->minimum, std::min(this->maximum - this->largeChange, value)); if (this->desiredValue + this->smoothScrollingOffset != value) { @@ -197,23 +200,23 @@ void Scrollbar::paintEvent(QPaintEvent *) int xOffset = mouseOver ? 0 : width() - (int)(4 * this->getScale()); QPainter painter(this); - // painter.fillRect(rect(), this->themeManager.ScrollbarBG); + // painter.fillRect(rect(), this->themeManager->ScrollbarBG); // painter.fillRect(QRect(xOffset, 0, width(), this->buttonHeight), - // this->themeManager.ScrollbarArrow); + // this->themeManager->ScrollbarArrow); // painter.fillRect(QRect(xOffset, height() - this->buttonHeight, width(), // this->buttonHeight), - // this->themeManager.ScrollbarArrow); + // this->themeManager->ScrollbarArrow); this->thumbRect.setX(xOffset); // mouse over thumb if (this->mouseDownIndex == 2) { - painter.fillRect(this->thumbRect, this->themeManager.scrollbars.thumbSelected); + painter.fillRect(this->thumbRect, this->themeManager->scrollbars.thumbSelected); } // mouse not over thumb else { - painter.fillRect(this->thumbRect, this->themeManager.scrollbars.thumb); + painter.fillRect(this->thumbRect, this->themeManager->scrollbars.thumb); } // draw highlights @@ -235,10 +238,10 @@ void Scrollbar::paintEvent(QPaintEvent *) if (!highlight.isNull()) { if (highlight.getStyle() == ScrollbarHighlight::Default) { painter.fillRect(w / 8 * 3, (int)y, w / 4, highlightHeight, - this->themeManager.tabs.selected.backgrounds.regular.color()); + this->themeManager->tabs.selected.backgrounds.regular.color()); } else { painter.fillRect(0, (int)y, w, 1, - this->themeManager.tabs.selected.backgrounds.regular.color()); + this->themeManager->tabs.selected.backgrounds.regular.color()); } } diff --git a/src/widgets/scrollbar.hpp b/src/widgets/scrollbar.hpp index 9ce646592..6d5166837 100644 --- a/src/widgets/scrollbar.hpp +++ b/src/widgets/scrollbar.hpp @@ -88,8 +88,6 @@ private: pajlada::Signals::NoArgSignal currentValueChanged; - pajlada::Settings::Setting &smoothScrollingSetting; - void updateScroll(); }; diff --git a/src/widgets/selectchanneldialog.cpp b/src/widgets/selectchanneldialog.cpp index 7bce0fe4f..e0decf2e2 100644 --- a/src/widgets/selectchanneldialog.cpp +++ b/src/widgets/selectchanneldialog.cpp @@ -266,7 +266,7 @@ void SelectChannelDialog::themeRefreshEvent() { BaseWindow::themeRefreshEvent(); - if (this->themeManager.isLightTheme()) { + if (this->themeManager->isLightTheme()) { this->setStyleSheet("QRadioButton { color: #000 } QLabel { color: #000 }"); } else { this->setStyleSheet("QRadioButton { color: #fff } QLabel { color: #fff }"); diff --git a/src/widgets/settingsdialog.cpp b/src/widgets/settingsdialog.cpp index b34664a09..29fb8ba83 100644 --- a/src/widgets/settingsdialog.cpp +++ b/src/widgets/settingsdialog.cpp @@ -1,4 +1,6 @@ #include "widgets/settingsdialog.hpp" + +#include "application.hpp" #include "util/layoutcreator.hpp" #include "widgets/helper/settingsdialogtab.hpp" #include "widgets/settingspages/aboutpage.hpp" @@ -150,7 +152,7 @@ void SettingsDialog::refresh() { // this->ui.accountSwitchWidget->refresh(); - singletons::SettingManager::getInstance().saveSnapshot(); + getApp()->settings->saveSnapshot(); } void SettingsDialog::scaleChangedEvent(float newDpi) @@ -209,13 +211,11 @@ void SettingsDialog::okButtonClicked() void SettingsDialog::cancelButtonClicked() { - auto &settings = singletons::SettingManager::getInstance(); - for (auto &tab : this->tabs) { tab->getSettingsPage()->cancel(); } - settings.recallSnapshot(); + getApp()->settings->recallSnapshot(); this->close(); } diff --git a/src/widgets/settingspages/accountspage.cpp b/src/widgets/settingspages/accountspage.cpp index 28a9d71c9..a5493c814 100644 --- a/src/widgets/settingspages/accountspage.cpp +++ b/src/widgets/settingspages/accountspage.cpp @@ -1,13 +1,14 @@ #include "accountspage.hpp" -#include -#include - +#include "application.hpp" #include "const.hpp" #include "singletons/accountmanager.hpp" #include "util/layoutcreator.hpp" #include "widgets/logindialog.hpp" +#include +#include + namespace chatterino { namespace widgets { namespace settingspages { @@ -39,7 +40,7 @@ AccountsPage::AccountsPage() return; } - singletons::AccountManager::getInstance().Twitch.removeUser(selectedUser); + getApp()->accounts->Twitch.removeUser(selectedUser); }); } diff --git a/src/widgets/settingspages/appearancepage.cpp b/src/widgets/settingspages/appearancepage.cpp index e7cd3c163..fdbc74f4a 100644 --- a/src/widgets/settingspages/appearancepage.cpp +++ b/src/widgets/settingspages/appearancepage.cpp @@ -1,5 +1,9 @@ #include "appearancepage.hpp" +#include "application.hpp" +#include "util/layoutcreator.hpp" +#include "util/removescrollareabackground.hpp" + #include #include #include @@ -9,9 +13,6 @@ #include #include -#include "util/layoutcreator.hpp" -#include "util/removescrollareabackground.hpp" - #define THEME_ITEMS "White", "Light", "Dark", "Black" #define TAB_X "Show close button" @@ -34,7 +35,7 @@ namespace settingspages { AppearancePage::AppearancePage() : SettingsPage("Look", ":/images/theme.svg") { - singletons::SettingManager &settings = singletons::SettingManager::getInstance(); + auto app = getApp(); util::LayoutCreator layoutCreator(this); auto scroll = layoutCreator.emplace(); @@ -49,50 +50,52 @@ AppearancePage::AppearancePage() auto form = application.emplace(); // clang-format off - form->addRow("Theme:", this->createComboBox({THEME_ITEMS}, singletons::ThemeManager::getInstance().themeName)); + form->addRow("Theme:", this->createComboBox({THEME_ITEMS}, app->themes->themeName)); form->addRow("Theme color:", this->createThemeColorChanger()); form->addRow("Font:", this->createFontChanger()); - form->addRow("Tabs:", this->createCheckBox(TAB_X, settings.hideTabX)); + form->addRow("Tabs:", this->createCheckBox(TAB_X, app->settings->hideTabX)); #ifndef USEWINSDK - form->addRow("", this->createCheckBox(TAB_PREF, settings.hidePreferencesButton)); - form->addRow("", this->createCheckBox(TAB_USER, settings.hideUserButton)); + form->addRow("", this->createCheckBox(TAB_PREF, app->settings->hidePreferencesButton)); + form->addRow("", this->createCheckBox(TAB_USER, app->settings->hideUserButton)); #endif - form->addRow("Scrolling:", this->createCheckBox(SCROLL_SMOOTH, settings.enableSmoothScrolling)); - form->addRow("", this->createCheckBox(SCROLL_NEWMSG, settings.enableSmoothScrollingNewMessages)); + form->addRow("Scrolling:", this->createCheckBox(SCROLL_SMOOTH, app->settings->enableSmoothScrolling)); + form->addRow("", this->createCheckBox(SCROLL_NEWMSG, app->settings->enableSmoothScrollingNewMessages)); // clang-format on } auto messages = layout.emplace("Messages").emplace(); { - messages.append(this->createCheckBox("Show timestamp", settings.showTimestamps)); + messages.append(this->createCheckBox("Show timestamp", app->settings->showTimestamps)); auto tbox = messages.emplace().withoutMargin(); { tbox.emplace("timestamp format (a = am/pm):"); - tbox.append(this->createComboBox({TIMESTAMP_FORMATS}, settings.timestampFormat)); + tbox.append(this->createComboBox({TIMESTAMP_FORMATS}, app->settings->timestampFormat)); tbox->addStretch(1); } - messages.append(this->createCheckBox("Show badges", settings.showBadges)); - auto checkbox = this->createCheckBox("Seperate messages", settings.seperateMessages); + messages.append(this->createCheckBox("Show badges", app->settings->showBadges)); + auto checkbox = this->createCheckBox("Seperate messages", app->settings->seperateMessages); checkbox->setEnabled(false); messages.append(checkbox); - messages.append( - this->createCheckBox("Show message length while typing", settings.showMessageLength)); + messages.append(this->createCheckBox("Show message length while typing", + app->settings->showMessageLength)); - messages.append(this->createCheckBox(LAST_MSG, settings.showLastMessageIndicator)); + messages.append(this->createCheckBox(LAST_MSG, app->settings->showLastMessageIndicator)); } auto emotes = layout.emplace("Emotes").setLayoutType(); { - emotes.append(this->createCheckBox("Enable Twitch emotes", settings.enableTwitchEmotes)); emotes.append( - this->createCheckBox("Enable BetterTTV emotes for Twitch", settings.enableBttvEmotes)); + this->createCheckBox("Enable Twitch emotes", app->settings->enableTwitchEmotes)); + emotes.append(this->createCheckBox("Enable BetterTTV emotes for Twitch", + app->settings->enableBttvEmotes)); emotes.append(this->createCheckBox("Enable FrankerFaceZ emotes for Twitch", - settings.enableFfzEmotes)); - emotes.append(this->createCheckBox("Enable emojis", settings.enableEmojis)); - emotes.append(this->createCheckBox("Enable animations", settings.enableGifAnimations)); + app->settings->enableFfzEmotes)); + emotes.append(this->createCheckBox("Enable emojis", app->settings->enableEmojis)); + emotes.append( + this->createCheckBox("Enable animations", app->settings->enableGifAnimations)); } layout->addStretch(1); @@ -100,9 +103,10 @@ AppearancePage::AppearancePage() QLayout *AppearancePage::createThemeColorChanger() { + auto app = getApp(); QHBoxLayout *layout = new QHBoxLayout; - auto &themeHue = singletons::ThemeManager::getInstance().themeHue; + auto &themeHue = app->themes->themeHue; // SLIDER QSlider *slider = new QSlider(Qt::Horizontal); @@ -115,9 +119,9 @@ QLayout *AppearancePage::createThemeColorChanger() button->setFlat(true); button->setFixedWidth(64); - auto setButtonColor = [button](int value) mutable { + auto setButtonColor = [button, app](int value) mutable { double newValue = value / 100.0; - singletons::ThemeManager::getInstance().themeHue.setValue(newValue); + app->themes->themeHue.setValue(newValue); QPalette pal = button->palette(); QColor color; diff --git a/src/widgets/settingspages/behaviourpage.cpp b/src/widgets/settingspages/behaviourpage.cpp index 4b46d282c..e251d9ad5 100644 --- a/src/widgets/settingspages/behaviourpage.cpp +++ b/src/widgets/settingspages/behaviourpage.cpp @@ -1,12 +1,13 @@ #include "behaviourpage.hpp" +#include "application.hpp" +#include "util/layoutcreator.hpp" + #include #include #include #include -#include - #define WINDOW_TOPMOST "Window always on top (requires restart)" #define INPUT_EMPTY "Hide input box when empty" #define PAUSE_HOVERING "When hovering" @@ -20,20 +21,21 @@ namespace settingspages { BehaviourPage::BehaviourPage() : SettingsPage("Feel", ":/images/behave.svg") { - singletons::SettingManager &settings = singletons::SettingManager::getInstance(); + auto app = getApp(); util::LayoutCreator layoutCreator(this); auto layout = layoutCreator.setLayoutType(); auto form = layout.emplace().withoutMargin(); { - form->addRow("Window:", this->createCheckBox(WINDOW_TOPMOST, settings.windowTopMost)); - form->addRow("Messages:", this->createCheckBox(INPUT_EMPTY, settings.hideEmptyInput)); - form->addRow("Pause chat:", this->createCheckBox(PAUSE_HOVERING, settings.pauseChatHover)); + form->addRow("Window:", this->createCheckBox(WINDOW_TOPMOST, app->settings->windowTopMost)); + form->addRow("Messages:", this->createCheckBox(INPUT_EMPTY, app->settings->hideEmptyInput)); + form->addRow("Pause chat:", + this->createCheckBox(PAUSE_HOVERING, app->settings->pauseChatHover)); form->addRow("Mouse scroll speed:", this->createMouseScrollSlider()); form->addRow("Links:", this->createCheckBox("Open links only on double click", - settings.linksDoubleClickOnly)); + app->settings->linksDoubleClickOnly)); } layout->addSpacing(16); @@ -43,17 +45,18 @@ BehaviourPage::BehaviourPage() auto groupLayout = group.setLayoutType(); groupLayout->addRow( LIMIT_CHATTERS_FOR_SMALLER_STREAMERS, - this->createCheckBox("", settings.onlyFetchChattersForSmallerStreamers)); + this->createCheckBox("", app->settings->onlyFetchChattersForSmallerStreamers)); groupLayout->addRow("What viewer count counts as a \"smaller streamer\"", - this->createSpinBox(settings.smallStreamerLimit, 10, 50000)); + this->createSpinBox(app->settings->smallStreamerLimit, 10, 50000)); } { auto group = layout.emplace("Misc"); auto groupLayout = group.setLayoutType(); - groupLayout.append(this->createCheckBox("Show whispers inline", settings.inlineWhispers)); + groupLayout.append( + this->createCheckBox("Show whispers inline", app->settings->inlineWhispers)); } layout->addStretch(1); @@ -61,16 +64,17 @@ BehaviourPage::BehaviourPage() QSlider *BehaviourPage::createMouseScrollSlider() { + auto app = getApp(); auto slider = new QSlider(Qt::Horizontal); - float currentValue = singletons::SettingManager::getInstance().mouseScrollMultiplier; + float currentValue = app->settings->mouseScrollMultiplier; int sliderValue = ((currentValue - 0.1f) / 2.f) * 99.f; slider->setValue(sliderValue); - QObject::connect(slider, &QSlider::valueChanged, [](int newValue) { + QObject::connect(slider, &QSlider::valueChanged, [=](int newValue) { float mul = static_cast(newValue) / 99.f; float newSliderValue = (mul * 2.1f) + 0.1f; - singletons::SettingManager::getInstance().mouseScrollMultiplier = newSliderValue; + app->settings->mouseScrollMultiplier = newSliderValue; }); return slider; diff --git a/src/widgets/settingspages/commandpage.cpp b/src/widgets/settingspages/commandpage.cpp index ff18bd4b6..2bccbde57 100644 --- a/src/widgets/settingspages/commandpage.cpp +++ b/src/widgets/settingspages/commandpage.cpp @@ -1,11 +1,12 @@ #include "commandpage.hpp" +#include "application.hpp" +#include "singletons/commandmanager.hpp" +#include "util/layoutcreator.hpp" + #include #include -#include "singletons/commandmanager.hpp" -#include "util/layoutcreator.hpp" - // clang-format off #define TEXT "One command per line.\n"\ "\"/cmd example command\" will print \"example command\" when you type /cmd in chat.\n"\ @@ -34,27 +35,27 @@ CommandPage::CommandPage() QTextEdit *CommandPage::getCommandsTextEdit() { - singletons::CommandManager &commandManager = singletons::CommandManager::getInstance(); + auto app = getApp(); // cancel - QStringList currentCommands = commandManager.getCommands(); + QStringList currentCommands = app->commands->getCommands(); this->onCancel.connect( - [currentCommands, &commandManager] { commandManager.setCommands(currentCommands); }); + [currentCommands, app] { app->commands->setCommands(currentCommands); }); // create text edit QTextEdit *textEdit = new QTextEdit; - textEdit->setPlainText(QString(commandManager.getCommands().join('\n'))); + textEdit->setPlainText(QString(app->commands->getCommands().join('\n'))); QObject::connect(textEdit, &QTextEdit::textChanged, [this] { this->commandsEditTimer.start(200); }); - QObject::connect(&this->commandsEditTimer, &QTimer::timeout, [textEdit, &commandManager] { + QObject::connect(&this->commandsEditTimer, &QTimer::timeout, [textEdit, app] { QString text = textEdit->toPlainText(); QStringList lines = text.split(QRegularExpression("(\r?\n|\r\n?)")); - commandManager.setCommands(lines); + app->commands->setCommands(lines); }); return textEdit; diff --git a/src/widgets/settingspages/externaltoolspage.cpp b/src/widgets/settingspages/externaltoolspage.cpp index e131565a1..1f0f3eb7b 100644 --- a/src/widgets/settingspages/externaltoolspage.cpp +++ b/src/widgets/settingspages/externaltoolspage.cpp @@ -1,5 +1,6 @@ #include "externaltoolspage.hpp" +#include "application.hpp" #include "util/layoutcreator.hpp" #include @@ -13,17 +14,21 @@ namespace settingspages { ExternalToolsPage::ExternalToolsPage() : SettingsPage("External tools", "") { - singletons::SettingManager &settings = singletons::SettingManager::getInstance(); + auto app = getApp(); + util::LayoutCreator layoutCreator(this); auto layout = layoutCreator.setLayoutType(); { auto group = layout.emplace("Streamlink"); auto groupLayout = group.setLayoutType(); - groupLayout->addRow("Streamlink path:", this->createLineEdit(settings.streamlinkPath)); - groupLayout->addRow("Prefered quality:", - this->createComboBox({STREAMLINK_QUALITY}, settings.preferredQuality)); - groupLayout->addRow("Additional options:", this->createLineEdit(settings.streamlinkOpts)); + groupLayout->addRow("Streamlink path:", + this->createLineEdit(app->settings->streamlinkPath)); + groupLayout->addRow( + "Prefered quality:", + this->createComboBox({STREAMLINK_QUALITY}, app->settings->preferredQuality)); + groupLayout->addRow("Additional options:", + this->createLineEdit(app->settings->streamlinkOpts)); } layout->addStretch(1); diff --git a/src/widgets/settingspages/highlightingpage.cpp b/src/widgets/settingspages/highlightingpage.cpp index fd4ea856c..c1c210848 100644 --- a/src/widgets/settingspages/highlightingpage.cpp +++ b/src/widgets/settingspages/highlightingpage.cpp @@ -1,5 +1,11 @@ #include "highlightingpage.hpp" +#include "application.hpp" +#include "debug/log.hpp" +#include "singletons/settingsmanager.hpp" +#include "util/layoutcreator.hpp" +#include "util/standarditemhelper.hpp" + #include #include #include @@ -8,11 +14,6 @@ #include #include -#include "debug/log.hpp" -#include "singletons/settingsmanager.hpp" -#include "util/layoutcreator.hpp" -#include "util/standarditemhelper.hpp" - #define ENABLE_HIGHLIGHTS "Enable Highlighting" #define HIGHLIGHT_MSG "Highlight messages containing your name" #define PLAY_SOUND "Play sound when your name is mentioned" @@ -26,13 +27,13 @@ namespace settingspages { HighlightingPage::HighlightingPage() : SettingsPage("Highlights", ":/images/notifications.svg") { - singletons::SettingManager &settings = singletons::SettingManager::getInstance(); + auto app = getApp(); util::LayoutCreator layoutCreator(this); auto layout = layoutCreator.emplace().withoutMargin(); { // GENERAL - layout.append(this->createCheckBox(ENABLE_HIGHLIGHTS, settings.enableHighlights)); + layout.append(this->createCheckBox(ENABLE_HIGHLIGHTS, app->settings->enableHighlights)); // TABS auto tabs = layout.emplace(); @@ -56,17 +57,17 @@ HighlightingPage::HighlightingPage() yourName->setData(QBrush("#666"), Qt::ForegroundRole); yourName->setFlags(yourName->flags() | Qt::ItemIsUserCheckable | Qt::ItemIsUserCheckable); - yourName->setData(settings.enableHighlightsSelf ? 2 : 0, Qt::CheckStateRole); + yourName->setData(app->settings->enableHighlightsSelf ? 2 : 0, Qt::CheckStateRole); model->appendRow( {yourName, - util::boolItem(settings.enableHighlightTaskbar.getValue(), true, false), - util::boolItem(settings.enableHighlightSound.getValue(), true, false), + util::boolItem(app->settings->enableHighlightTaskbar.getValue(), true, false), + util::boolItem(app->settings->enableHighlightSound.getValue(), true, false), util::emptyItem()}); // highlight phrases // fourtf: could crash for (const messages::HighlightPhrase &phrase : - settings.highlightProperties.getValue()) { + app->settings->highlightProperties.getValue()) { model->appendRow({util::stringItem(phrase.key), util::boolItem(phrase.alert), util::boolItem(phrase.sound), util::boolItem(phrase.regex)}); } @@ -79,26 +80,26 @@ HighlightingPage::HighlightingPage() auto buttons = highlights.emplace(); - QObject::connect(model, &QStandardItemModel::dataChanged, - [model](const QModelIndex &topLeft, const QModelIndex &bottomRight, - const QVector &roles) { - std::vector phrases; - for (int i = 1; i < model->rowCount(); i++) { - phrases.push_back(messages::HighlightPhrase{ - model->item(i, 0)->data(Qt::DisplayRole).toString(), - model->item(i, 1)->data(Qt::CheckStateRole).toBool(), - model->item(i, 2)->data(Qt::CheckStateRole).toBool(), - model->item(i, 3)->data(Qt::CheckStateRole).toBool()}); - } - auto &settings = singletons::SettingManager::getInstance(); - settings.highlightProperties.setValue(phrases); - settings.enableHighlightsSelf.setValue( - model->item(0, 0)->data(Qt::CheckStateRole).toBool()); - settings.enableHighlightTaskbar.setValue( - model->item(0, 1)->data(Qt::CheckStateRole).toBool()); - settings.enableHighlightSound.setValue( - model->item(0, 2)->data(Qt::CheckStateRole).toBool()); - }); + QObject::connect( + model, &QStandardItemModel::dataChanged, + [model, app](const QModelIndex &topLeft, const QModelIndex &bottomRight, + const QVector &roles) { + std::vector phrases; + for (int i = 1; i < model->rowCount(); i++) { + phrases.push_back(messages::HighlightPhrase{ + model->item(i, 0)->data(Qt::DisplayRole).toString(), + model->item(i, 1)->data(Qt::CheckStateRole).toBool(), + model->item(i, 2)->data(Qt::CheckStateRole).toBool(), + model->item(i, 3)->data(Qt::CheckStateRole).toBool()}); + } + app->settings->highlightProperties.setValue(phrases); + app->settings->enableHighlightsSelf.setValue( + model->item(0, 0)->data(Qt::CheckStateRole).toBool()); + app->settings->enableHighlightTaskbar.setValue( + model->item(0, 1)->data(Qt::CheckStateRole).toBool()); + app->settings->enableHighlightSound.setValue( + model->item(0, 2)->data(Qt::CheckStateRole).toBool()); + }); auto add = buttons.emplace("Add"); QObject::connect(*add, &QPushButton::clicked, [model, view] { @@ -138,13 +139,13 @@ HighlightingPage::HighlightingPage() [this] { this->disabledUsersChangedTimer.start(200); }); QObject::connect( - &this->disabledUsersChangedTimer, &QTimer::timeout, this, [text, &settings]() { + &this->disabledUsersChangedTimer, &QTimer::timeout, this, [text, app]() { QStringList list = text->toPlainText().split("\n", QString::SkipEmptyParts); list.removeDuplicates(); - settings.highlightUserBlacklist = list.join("\n") + "\n"; + app->settings->highlightUserBlacklist = list.join("\n") + "\n"; }); - settings.highlightUserBlacklist.connect([=](const QString &str, auto) { + app->settings->highlightUserBlacklist.connect([=](const QString &str, auto) { text->setPlainText(str); // }); } @@ -153,17 +154,17 @@ HighlightingPage::HighlightingPage() // MISC auto customSound = layout.emplace().withoutMargin(); { - customSound.append(this->createCheckBox("Custom sound", settings.customHighlightSound)); + customSound.append( + this->createCheckBox("Custom sound", app->settings->customHighlightSound)); auto selectFile = customSound.emplace("Select custom sound file"); - QObject::connect(selectFile.getElement(), &QPushButton::clicked, this, - [&settings, this] { - auto fileName = QFileDialog::getOpenFileName( - this, tr("Open Sound"), "", tr("Audio Files (*.mp3 *.wav)")); - settings.pathHighlightSound = fileName; - }); + QObject::connect(selectFile.getElement(), &QPushButton::clicked, this, [this, app] { + auto fileName = QFileDialog::getOpenFileName(this, tr("Open Sound"), "", + tr("Audio Files (*.mp3 *.wav)")); + app->settings->pathHighlightSound = fileName; + }); } - layout.append(createCheckBox(ALWAYS_PLAY, settings.highlightAlwaysPlaySound)); + layout.append(createCheckBox(ALWAYS_PLAY, app->settings->highlightAlwaysPlaySound)); } // ---- misc diff --git a/src/widgets/settingspages/ignoremessagespage.cpp b/src/widgets/settingspages/ignoremessagespage.cpp index c4bba2c73..714ef3351 100644 --- a/src/widgets/settingspages/ignoremessagespage.cpp +++ b/src/widgets/settingspages/ignoremessagespage.cpp @@ -1,5 +1,6 @@ #include "ignoremessagespage.hpp" +#include "application.hpp" #include "util/layoutcreator.hpp" #include @@ -12,22 +13,22 @@ namespace settingspages { IgnoreMessagesPage::IgnoreMessagesPage() : SettingsPage("Ignore Messages", "") { - singletons::SettingManager &settings = singletons::SettingManager::getInstance(); + auto app = getApp(); util::LayoutCreator layoutCreator(this); auto layout = layoutCreator.setLayoutType(); layout.emplace("Ignored keywords:"); QTextEdit *textEdit = layout.emplace().getElement(); - textEdit->setPlainText(settings.ignoredKeywords); + textEdit->setPlainText(app->settings->ignoredKeywords); QObject::connect(textEdit, &QTextEdit::textChanged, [this] { this->keywordsUpdated.start(200); }); - QObject::connect(&this->keywordsUpdated, &QTimer::timeout, [textEdit, &settings] { + QObject::connect(&this->keywordsUpdated, &QTimer::timeout, [textEdit, app] { QString text = textEdit->toPlainText(); - settings.ignoredKeywords = text; + app->settings->ignoredKeywords = text; }); // ---- misc diff --git a/src/widgets/settingspages/ignoreuserspage.cpp b/src/widgets/settingspages/ignoreuserspage.cpp index 1c81d4a5c..09f943ce8 100644 --- a/src/widgets/settingspages/ignoreuserspage.cpp +++ b/src/widgets/settingspages/ignoreuserspage.cpp @@ -1,5 +1,6 @@ #include "ignoreuserspage.hpp" +#include "application.hpp" #include "singletons/settingsmanager.hpp" #include "util/layoutcreator.hpp" @@ -21,14 +22,15 @@ namespace settingspages { IgnoreUsersPage::IgnoreUsersPage() : SettingsPage("Ignores", "") { - singletons::SettingManager &settings = singletons::SettingManager::getInstance(); + auto app = getApp(); + util::LayoutCreator layoutCreator(this); auto layout = layoutCreator.setLayoutType(); auto group = layout.emplace("Ignored users").setLayoutType(); { - group.append( - this->createCheckBox("Enable twitch ignored users", settings.enableTwitchIgnoredUsers)); + group.append(this->createCheckBox("Enable twitch ignored users", + app->settings->enableTwitchIgnoredUsers)); auto anyways = group.emplace().withoutMargin(); { diff --git a/src/widgets/settingspages/logspage.cpp b/src/widgets/settingspages/logspage.cpp index 138df8e1e..04c5ebf7d 100644 --- a/src/widgets/settingspages/logspage.cpp +++ b/src/widgets/settingspages/logspage.cpp @@ -1,4 +1,6 @@ #include "logspage.hpp" + +#include "application.hpp" #include "singletons/pathmanager.hpp" #include @@ -23,12 +25,12 @@ inline QString CreateLink(const QString &url, bool file = false) LogsPage::LogsPage() : SettingsPage("Logs", "") { - singletons::SettingManager &settings = singletons::SettingManager::getInstance(); + auto app = getApp(); + util::LayoutCreator layoutCreator(this); auto layout = layoutCreator.emplace().withoutMargin(); - singletons::PathManager &pathManager = singletons::PathManager::getInstance(); - auto logPath = pathManager.logsFolderPath; + auto logPath = app->paths->logsFolderPath; auto created = layout.emplace(); created->setText("Logs are saved to " + CreateLink(logPath, true)); @@ -36,7 +38,7 @@ LogsPage::LogsPage() created->setTextInteractionFlags(Qt::TextBrowserInteraction | Qt::LinksAccessibleByKeyboard | Qt::LinksAccessibleByKeyboard); created->setOpenExternalLinks(true); - layout.append(this->createCheckBox("Enable logging", settings.enableLogging)); + layout.append(this->createCheckBox("Enable logging", app->settings->enableLogging)); layout->addStretch(1); } diff --git a/src/widgets/settingspages/moderationpage.cpp b/src/widgets/settingspages/moderationpage.cpp index a1587c35b..81faa01bd 100644 --- a/src/widgets/settingspages/moderationpage.cpp +++ b/src/widgets/settingspages/moderationpage.cpp @@ -1,5 +1,9 @@ #include "moderationpage.hpp" +#include "application.hpp" +#include "singletons/pathmanager.hpp" +#include "util/layoutcreator.hpp" + #include #include #include @@ -8,9 +12,6 @@ #include #include -#include "singletons/pathmanager.hpp" -#include "util/layoutcreator.hpp" - namespace chatterino { namespace widgets { namespace settingspages { @@ -28,14 +29,13 @@ inline QString CreateLink(const QString &url, bool file = false) ModerationPage::ModerationPage() : SettingsPage("Moderation", "") { - singletons::SettingManager &settings = singletons::SettingManager::getInstance(); - singletons::PathManager &pathManager = singletons::PathManager::getInstance(); + auto app = getApp(); util::LayoutCreator layoutCreator(this); auto layout = layoutCreator.setLayoutType(); { // Logs (copied from LoggingMananger) - auto logPath = pathManager.logsFolderPath; + auto logPath = app->paths->logsFolderPath; auto created = layout.emplace(); created->setText("Logs are saved to " + CreateLink(logPath, true)); @@ -44,7 +44,7 @@ ModerationPage::ModerationPage() Qt::LinksAccessibleByKeyboard | Qt::LinksAccessibleByKeyboard); created->setOpenExternalLinks(true); - layout.append(this->createCheckBox("Enable logging", settings.enableLogging)); + layout.append(this->createCheckBox("Enable logging", app->settings->enableLogging)); layout->addStretch(1); // Logs end @@ -58,7 +58,7 @@ ModerationPage::ModerationPage() auto form = layout.emplace(); { form->addRow("Action on timed out messages (unimplemented):", - this->createComboBox({"Disable", "Hide"}, settings.timeoutAction)); + this->createComboBox({"Disable", "Hide"}, app->settings->timeoutAction)); } auto modButtons = @@ -71,13 +71,13 @@ ModerationPage::ModerationPage() auto text = modButtons.emplace().getElement(); - text->setPlainText(settings.moderationActions); + text->setPlainText(app->settings->moderationActions); QObject::connect(text, &QTextEdit::textChanged, this, [this] { this->itemsChangedTimer.start(200); }); - QObject::connect(&this->itemsChangedTimer, &QTimer::timeout, this, [text, &settings]() { - settings.moderationActions = text->toPlainText(); + QObject::connect(&this->itemsChangedTimer, &QTimer::timeout, this, [text, app]() { + app->settings->moderationActions = text->toPlainText(); }); } } diff --git a/src/widgets/settingspages/specialchannelspage.cpp b/src/widgets/settingspages/specialchannelspage.cpp index 3a57c3cda..39e29770e 100644 --- a/src/widgets/settingspages/specialchannelspage.cpp +++ b/src/widgets/settingspages/specialchannelspage.cpp @@ -1,5 +1,6 @@ #include "specialchannelspage.hpp" +#include "application.hpp" #include "singletons/settingsmanager.hpp" #include "util/layoutcreator.hpp" @@ -14,7 +15,8 @@ namespace settingspages { SpecialChannelsPage::SpecialChannelsPage() : SettingsPage("Special channels", "") { - singletons::SettingManager &settings = singletons::SettingManager::getInstance(); + auto app = getApp(); + util::LayoutCreator layoutCreator(this); auto layout = layoutCreator.setLayoutType(); diff --git a/src/widgets/split.cpp b/src/widgets/split.cpp index ea20069e0..e8f495fc0 100644 --- a/src/widgets/split.cpp +++ b/src/widgets/split.cpp @@ -1,4 +1,6 @@ #include "widgets/split.hpp" + +#include "application.hpp" #include "providers/twitch/emotevalue.hpp" #include "providers/twitch/twitchchannel.hpp" #include "providers/twitch/twitchmessagebuilder.hpp" @@ -36,19 +38,8 @@ using namespace chatterino::messages; namespace chatterino { namespace widgets { -Split::Split(SplitContainer *parent) - : Split((BaseWidget *)parent) -{ - this->container = parent; -} - -Split::Split(BaseWidget *widget) - : Split(widget->themeManager, widget) -{ -} - -Split::Split(singletons::ThemeManager &manager, QWidget *parent) - : BaseWidget(manager, parent) +Split::Split(QWidget *parent) + : BaseWidget(parent) , container(nullptr) , channel(Channel::getEmpty()) , vbox(this) @@ -56,6 +47,8 @@ Split::Split(singletons::ThemeManager &manager, QWidget *parent) , view(this) , input(this) { + auto app = getApp(); + this->setMouseTracking(true); this->vbox.setSpacing(0); @@ -97,8 +90,8 @@ Split::Split(singletons::ThemeManager &manager, QWidget *parent) } }); - this->input.textChanged.connect([this](const QString &newText) { - if (!singletons::SettingManager::getInstance().hideEmptyInput) { + this->input.textChanged.connect([=](const QString &newText) { + if (!app->settings->hideEmptyInput) { return; } @@ -109,14 +102,15 @@ Split::Split(singletons::ThemeManager &manager, QWidget *parent) } }); - singletons::SettingManager::getInstance().hideEmptyInput.connect( + app->settings->hideEmptyInput.connect( [this](const bool &hideEmptyInput, auto) { if (hideEmptyInput && this->input.getInputText().length() == 0) { this->input.hide(); } else { this->input.show(); } - }); + }, + this->managedConnections); this->header.updateModerationModeIcon(); @@ -260,7 +254,7 @@ void Split::paintEvent(QPaintEvent *) // color the background of the chat QPainter painter(this); - painter.fillRect(this->rect(), this->themeManager.splits.background); + painter.fillRect(this->rect(), this->themeManager->splits.background); } void Split::mouseMoveEvent(QMouseEvent *event) @@ -328,7 +322,8 @@ void Split::doChangeChannel() void Split::doPopup() { - Window &window = singletons::WindowManager::getInstance().createWindow(Window::Popup); + auto app = getApp(); + Window &window = app->windows->createWindow(Window::Popup); Split *split = new Split(static_cast(window.getNotebook().getOrAddSelectedPage())); @@ -397,7 +392,7 @@ void Split::doOpenViewerList() QList labelList; for (auto &x : labels) { auto label = new QListWidgetItem(x); - label->setBackgroundColor(this->themeManager.splits.header.background); + label->setBackgroundColor(this->themeManager->splits.header.background); labelList.append(label); } auto loadingLabel = new QLabel("Loading..."); @@ -454,7 +449,7 @@ void Split::doOpenViewerList() dockVbox->addWidget(resultList); resultList->hide(); - multiWidget->setStyleSheet(this->themeManager.splits.input.styleSheet); + multiWidget->setStyleSheet(this->themeManager->splits.input.styleSheet); multiWidget->setLayout(dockVbox); viewerDock->setWidget(multiWidget); viewerDock->show(); diff --git a/src/widgets/split.hpp b/src/widgets/split.hpp index ae64db3a2..fb3244d3a 100644 --- a/src/widgets/split.hpp +++ b/src/widgets/split.hpp @@ -43,9 +43,7 @@ class Split : public BaseWidget Q_OBJECT public: - explicit Split(SplitContainer *parent); - explicit Split(BaseWidget *widget); - explicit Split(singletons::ThemeManager &manager, QWidget *parent); + explicit Split(QWidget *parent); ~Split() override; pajlada::Signals::NoArgSignal channelChanged; @@ -103,6 +101,8 @@ private: pajlada::Signals::Connection usermodeChangedConnection; pajlada::Signals::Connection indirectChannelChangedConnection; + std::vector managedConnections; + void doOpenAccountPopupWidget(AccountPopupWidget *widget, QString user); void channelNameUpdated(const QString &newChannelName); void handleModifiers(QEvent *event, Qt::KeyboardModifiers modifiers); diff --git a/src/widgets/splitcontainer.cpp b/src/widgets/splitcontainer.cpp index f398a1345..f1b3bbec5 100644 --- a/src/widgets/splitcontainer.cpp +++ b/src/widgets/splitcontainer.cpp @@ -27,7 +27,7 @@ Split *SplitContainer::draggingSplit = nullptr; std::pair SplitContainer::dropPosition = std::pair(-1, -1); SplitContainer::SplitContainer(Notebook *parent, NotebookTab *_tab) - : BaseWidget(parent->themeManager, parent) + : BaseWidget(parent) , tab(_tab) , dropPreview(this) { @@ -450,9 +450,9 @@ void SplitContainer::paintEvent(QPaintEvent *) QPainter painter(this); if (this->ui.hbox.count() == 0) { - painter.fillRect(rect(), this->themeManager.splits.background); + painter.fillRect(rect(), this->themeManager->splits.background); - painter.setPen(this->themeManager.splits.header.text); + painter.setPen(this->themeManager->splits.header.text); QString text = "Click to add a "; @@ -467,12 +467,12 @@ void SplitContainer::paintEvent(QPaintEvent *) painter.drawText(rect(), text, QTextOption(Qt::AlignCenter)); } else { - painter.fillRect(rect(), this->themeManager.splits.messageSeperator); + painter.fillRect(rect(), this->themeManager->splits.messageSeperator); } QBrush accentColor = (QApplication::activeWindow() == this->window() - ? this->themeManager.tabs.selected.backgrounds.regular - : this->themeManager.tabs.selected.backgrounds.unfocused); + ? this->themeManager->tabs.selected.backgrounds.regular + : this->themeManager->tabs.selected.backgrounds.unfocused); painter.fillRect(0, 0, width(), 1, accentColor); } diff --git a/src/widgets/window.cpp b/src/widgets/window.cpp index 974a3165d..19307787f 100644 --- a/src/widgets/window.cpp +++ b/src/widgets/window.cpp @@ -1,4 +1,6 @@ #include "widgets/window.hpp" + +#include "application.hpp" #include "singletons/accountmanager.hpp" #include "singletons/ircmanager.hpp" #include "singletons/settingsmanager.hpp" @@ -21,33 +23,32 @@ namespace chatterino { namespace widgets { -Window::Window(singletons::ThemeManager &_themeManager, WindowType _type) - : BaseWindow(_themeManager, nullptr, true) +Window::Window(WindowType _type) + : BaseWindow(nullptr, true) , type(_type) , dpi(this->getScale()) , notebook(this, !this->hasCustomWindowFrame()) { - singletons::AccountManager::getInstance().Twitch.currentUsername.connect( - [this](const std::string &newUsername, auto) { - if (newUsername.empty()) { - this->refreshWindowTitle("Not logged in"); - } else { - this->refreshWindowTitle(QString::fromStdString(newUsername)); - } - }); + auto app = getApp(); + + app->accounts->Twitch.currentUsername.connect([this](const std::string &newUsername, auto) { + if (newUsername.empty()) { + this->refreshWindowTitle("Not logged in"); + } else { + this->refreshWindowTitle(QString::fromStdString(newUsername)); + } + }); if (this->hasCustomWindowFrame() && _type == Window::Main) { - this->addTitleBarButton(TitleBarButton::Settings, [] { - singletons::WindowManager::getInstance().showSettingsDialog(); + this->addTitleBarButton(TitleBarButton::Settings, [app] { + app->windows->showSettingsDialog(); // }); - auto user = this->addTitleBarLabel([] { - singletons::WindowManager::getInstance().showAccountSelectPopup(QCursor::pos()); + auto user = this->addTitleBarLabel([app] { + app->windows->showAccountSelectPopup(QCursor::pos()); // }); - singletons::AccountManager::getInstance().Twitch.userChanged.connect([user] { - user->getLabel().setText( - singletons::AccountManager::getInstance().Twitch.getCurrent()->getUserName()); - }); + app->accounts->Twitch.userChanged.connect( + [=] { user->getLabel().setText(app->accounts->Twitch.getCurrent()->getUserName()); }); } if (_type == Window::Main) { @@ -161,8 +162,9 @@ bool Window::event(QEvent *e) void Window::closeEvent(QCloseEvent *event) { if (this->type == Window::Main) { - singletons::WindowManager::getInstance().save(); - singletons::WindowManager::getInstance().closeAll(); + auto app = getApp(); + app->windows->save(); + app->windows->closeAll(); } this->closed.invoke(); diff --git a/src/widgets/window.hpp b/src/widgets/window.hpp index 850fb06b3..5fa8eee12 100644 --- a/src/widgets/window.hpp +++ b/src/widgets/window.hpp @@ -25,7 +25,7 @@ class Window : public BaseWindow public: enum WindowType { Main, Popup, Attached }; - explicit Window(singletons::ThemeManager &_themeManager, WindowType type); + explicit Window(WindowType type); void repaintVisibleChatWidgets(Channel *channel = nullptr);