From 2f195891cdb82dd256feec6ab2a2e66b25ac10a8 Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Sat, 28 Apr 2018 15:20:18 +0200 Subject: [PATCH] Finish up singleton refactoring into one giant class --- src/application.cpp | 22 ++++++---- src/application.hpp | 19 +++++++++ src/messages/layouts/messagelayout.cpp | 13 +++--- src/messages/layouts/messagelayoutelement.cpp | 17 +++++--- src/messages/messageelement.cpp | 3 +- src/providers/twitch/ircmessagehandler.cpp | 35 +++++++++------- src/providers/twitch/twitchmessagebuilder.cpp | 41 ++++++++++--------- src/providers/twitch/twitchserver.cpp | 13 +++--- src/providers/twitch/twitchserver.hpp | 5 ++- src/singletons/accountmanager.hpp | 5 +-- src/singletons/commandmanager.cpp | 9 ++-- src/singletons/commandmanager.hpp | 5 +-- src/singletons/emotemanager.hpp | 5 +-- src/singletons/fontmanager.cpp | 7 +--- src/singletons/fontmanager.hpp | 11 +++-- src/singletons/loggingmanager.hpp | 5 +-- src/singletons/nativemessagingmanager.cpp | 11 ++--- src/singletons/nativemessagingmanager.hpp | 5 +-- src/singletons/pathmanager.hpp | 5 +-- src/singletons/pubsubmanager.hpp | 5 +-- src/singletons/resourcemanager.cpp | 9 ++-- src/singletons/resourcemanager.hpp | 6 ++- src/singletons/settingsmanager.cpp | 11 +++-- src/singletons/settingsmanager.hpp | 6 +-- src/singletons/thememanager.hpp | 5 +-- src/singletons/windowmanager.cpp | 11 ++--- src/singletons/windowmanager.hpp | 5 +-- src/widgets/helper/channelview.cpp | 9 ++-- src/widgets/helper/label.cpp | 26 +++++++----- src/widgets/helper/splitheader.cpp | 18 ++++---- src/widgets/helper/splitinput.cpp | 7 ++-- src/widgets/selectchanneldialog.cpp | 12 +++--- src/widgets/settingspages/appearancepage.cpp | 26 ++++++------ src/widgets/tooltipwidget.cpp | 13 ++++-- 34 files changed, 221 insertions(+), 184 deletions(-) diff --git a/src/application.cpp b/src/application.cpp index 9ace0cd32..eb3827d75 100644 --- a/src/application.cpp +++ b/src/application.cpp @@ -4,10 +4,12 @@ #include "singletons/accountmanager.hpp" #include "singletons/commandmanager.hpp" #include "singletons/emotemanager.hpp" +#include "singletons/fontmanager.hpp" #include "singletons/loggingmanager.hpp" #include "singletons/nativemessagingmanager.hpp" #include "singletons/pathmanager.hpp" #include "singletons/pubsubmanager.hpp" +#include "singletons/resourcemanager.hpp" #include "singletons/settingsmanager.hpp" #include "singletons/thememanager.hpp" #include "singletons/windowmanager.hpp" @@ -57,7 +59,7 @@ void Application::construct() isAppConstructed = true; // 1. Instantiate all classes - this->paths = new singletons::PathManager(argc, argv); + this->paths = new singletons::PathManager(this->argc, this->argv); this->themes = new singletons::ThemeManager; this->windows = new singletons::WindowManager; this->logging = new singletons::LoggingManager; @@ -66,6 +68,10 @@ void Application::construct() this->emotes = new singletons::EmoteManager; this->pubsub = new singletons::PubSubManager; this->settings = new singletons::SettingManager; + this->fonts = new singletons::FontManager; + this->resources = new singletons::ResourceManager; + + this->twitch.server = new providers::twitch::TwitchServer; } void Application::instantiate(int argc, char **argv) @@ -81,18 +87,20 @@ void Application::initialize() isAppInitialized = true; // 2. Initialize/load classes + this->settings->initialize(); this->windows->initialize(); this->nativeMessaging->registerHost(); - this->settings->initialize(); + this->settings->load(); this->commands->loadCommands(); - // Initialize everything we need this->emotes->loadGlobalEmotes(); this->accounts->load(); + this->twitch.server->initialize(); + // XXX this->settings->updateWordTypeMask(); @@ -121,8 +129,7 @@ void Application::initialize() }); this->pubsub->sig.moderation.userBanned.connect([&](const auto &action) { - auto &server = providers::twitch::TwitchServer::getInstance(); - auto chan = server.getChannelOrEmptyByID(action.roomID); + auto chan = this->twitch.server->getChannelOrEmptyByID(action.roomID); if (chan->isEmpty()) { return; @@ -134,8 +141,7 @@ void Application::initialize() }); this->pubsub->sig.moderation.userUnbanned.connect([&](const auto &action) { - auto &server = providers::twitch::TwitchServer::getInstance(); - auto chan = server.getChannelOrEmptyByID(action.roomID); + auto chan = this->twitch.server->getChannelOrEmptyByID(action.roomID); if (chan->isEmpty()) { return; @@ -164,7 +170,7 @@ void Application::initialize() int Application::run(QApplication &qtApp) { // Start connecting to the IRC Servers (Twitch only for now) - providers::twitch::TwitchServer::getInstance().connect(); + this->twitch.server->connect(); // Show main window this->windows->getMainWindow().show(); diff --git a/src/application.hpp b/src/application.hpp index 17767dc27..22aed68b2 100644 --- a/src/application.hpp +++ b/src/application.hpp @@ -7,6 +7,14 @@ namespace chatterino { +namespace providers { +namespace twitch { + +class TwitchServer; + +} // namespace twitch +} // namespace providers + namespace singletons { class ThemeManager; @@ -19,6 +27,8 @@ class EmoteManager; class PubSubManager; class NativeMessagingManager; class SettingManager; +class FontManager; +class ResourceManager; } // namespace singletons @@ -37,6 +47,8 @@ public: int run(QApplication &qtApp); + friend void test(); + singletons::PathManager *paths = nullptr; singletons::ThemeManager *themes = nullptr; singletons::WindowManager *windows = nullptr; @@ -47,6 +59,13 @@ public: singletons::PubSubManager *pubsub = nullptr; singletons::NativeMessagingManager *nativeMessaging = nullptr; singletons::SettingManager *settings = nullptr; + singletons::FontManager *fonts = nullptr; + singletons::ResourceManager *resources = nullptr; + + /// Provider-specific + struct { + providers::twitch::TwitchServer *server; + } twitch; void save(); diff --git a/src/messages/layouts/messagelayout.cpp b/src/messages/layouts/messagelayout.cpp index 06d95c904..1702b6e30 100644 --- a/src/messages/layouts/messagelayout.cpp +++ b/src/messages/layouts/messagelayout.cpp @@ -62,10 +62,9 @@ bool MessageLayout::layout(int width, float scale, MessageElement::Flags flags) this->emoteGeneration = app->emotes->getGeneration(); // check if text changed - bool textChanged = - this->fontGeneration != singletons::FontManager::getInstance().getGeneration(); + bool textChanged = this->fontGeneration != app->fonts->getGeneration(); layoutRequired |= textChanged; - this->fontGeneration = singletons::FontManager::getInstance().getGeneration(); + this->fontGeneration = app->fonts->getGeneration(); // check if work mask changed bool wordMaskChanged = this->currentWordFlags != flags; // app->settings->getWordTypeMask(); @@ -160,8 +159,7 @@ 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(), - app->themes->messages.disabled); + painter.fillRect(0, y, pixmap->width(), pixmap->height(), app->themes->messages.disabled); } // draw selection @@ -171,9 +169,8 @@ void MessageLayout::paint(QPainter &painter, int y, int messageIndex, Selection // draw last read message line if (isLastReadMessage) { - QColor color = isWindowFocused - ? app->themes->tabs.selected.backgrounds.regular.color() - : app->themes->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); diff --git a/src/messages/layouts/messagelayoutelement.cpp b/src/messages/layouts/messagelayoutelement.cpp index 5f9f5a2b0..d2c0d2ccc 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" @@ -165,9 +166,11 @@ int TextLayoutElement::getSelectionIndexCount() void TextLayoutElement::paint(QPainter &painter) { + auto app = getApp(); + painter.setPen(this->color); - painter.setFont(singletons::FontManager::getInstance().getFont(this->style, this->scale)); + painter.setFont(app->fonts->getFont(this->style, this->scale)); painter.drawText(QRectF(this->getRect().x(), this->getRect().y(), 10000, 10000), this->text, QTextOption(Qt::AlignLeft | Qt::AlignTop)); @@ -183,8 +186,9 @@ int TextLayoutElement::getMouseOverIndex(const QPoint &abs) return 0; } - QFontMetrics &metrics = - singletons::FontManager::getInstance().getFontMetrics(this->style, this->scale); + auto app = getApp(); + + QFontMetrics &metrics = app->fonts->getFontMetrics(this->style, this->scale); int x = this->getRect().left(); @@ -203,8 +207,9 @@ int TextLayoutElement::getMouseOverIndex(const QPoint &abs) int TextLayoutElement::getXFromIndex(int index) { - QFontMetrics &metrics = - singletons::FontManager::getInstance().getFontMetrics(this->style, this->scale); + auto app = getApp(); + + QFontMetrics &metrics = app->fonts->getFontMetrics(this->style, this->scale); if (index <= 0) { return this->getRect().left(); @@ -242,7 +247,7 @@ void TextIconLayoutElement::paint(QPainter &painter) { auto app = getApp(); - QFont font = singletons::FontManager::getInstance().getFont(FontStyle::Tiny, this->scale); + QFont font = app->fonts->getFont(FontStyle::Tiny, this->scale); painter.setPen(app->themes->messages.textColors.system); painter.setFont(font); diff --git a/src/messages/messageelement.cpp b/src/messages/messageelement.cpp index 63c8281d1..dc288ed3a 100644 --- a/src/messages/messageelement.cpp +++ b/src/messages/messageelement.cpp @@ -139,8 +139,7 @@ void TextElement::addToContainer(MessageLayoutContainer &container, MessageEleme auto app = getApp(); if (_flags & this->getFlags()) { - QFontMetrics &metrics = singletons::FontManager::getInstance().getFontMetrics( - this->style, container.getScale()); + QFontMetrics &metrics = app->fonts->getFontMetrics(this->style, container.getScale()); for (Word &word : this->words) { auto getTextLayoutElement = [&](QString text, int width, bool trailingSpace) { diff --git a/src/providers/twitch/ircmessagehandler.cpp b/src/providers/twitch/ircmessagehandler.cpp index be8ae18a2..865a31a44 100644 --- a/src/providers/twitch/ircmessagehandler.cpp +++ b/src/providers/twitch/ircmessagehandler.cpp @@ -35,12 +35,15 @@ void IrcMessageHandler::handleRoomStateMessage(Communi::IrcMessage *message) QStringList words = QString(message->toData()).split("#"); // ensure the format is valid - if (words.length() < 2) + if (words.length() < 2) { return; + } + + auto app = getApp(); QString channelName = words.at(1); - auto channel = TwitchServer::getInstance().getChannelOrEmpty(channelName); + auto channel = app->twitch.server->getChannelOrEmpty(channelName); if (channel->isEmpty()) { return; @@ -51,7 +54,7 @@ void IrcMessageHandler::handleRoomStateMessage(Communi::IrcMessage *message) twitchChannel->setRoomID(roomID); } - ResourceManager::getInstance().loadChannelData(roomID); + app->resources->loadChannelData(roomID); } } @@ -68,8 +71,10 @@ void IrcMessageHandler::handleClearChatMessage(Communi::IrcMessage *message) return; } + auto app = getApp(); + // get channel - auto chan = TwitchServer::getInstance().getChannelOrEmpty(chanName); + auto chan = app->twitch.server->getChannelOrEmpty(chanName); if (chan->isEmpty()) { debug::Log("[IrcMessageHandler:handleClearChatMessage] Twitch channel {} not found", @@ -125,8 +130,6 @@ void IrcMessageHandler::handleClearChatMessage(Communi::IrcMessage *message) } } - auto app = getApp(); - // refresh all app->windows->repaintVisibleChatWidgets(chan.get()); } @@ -136,12 +139,14 @@ void IrcMessageHandler::handleUserStateMessage(Communi::IrcMessage *message) QVariant _mod = message->tag("mod"); if (_mod.isValid()) { + auto app = getApp(); + QString channelName; if (!TrimChannelName(message->parameter(0), channelName)) { return; } - auto c = TwitchServer::getInstance().getChannelOrEmpty(channelName); + auto c = app->twitch.server->getChannelOrEmpty(channelName); if (c->isEmpty()) { return; } @@ -161,7 +166,7 @@ void IrcMessageHandler::handleWhisperMessage(Communi::IrcMessage *message) args.isReceivedWhisper = true; - auto c = TwitchServer::getInstance().whispersChannel.get(); + auto c = app->twitch.server->whispersChannel.get(); twitch::TwitchMessageBuilder builder(c, message, message->parameter(1), args); @@ -170,13 +175,13 @@ void IrcMessageHandler::handleWhisperMessage(Communi::IrcMessage *message) _message->flags |= messages::Message::DoNotTriggerNotification; if (_message->flags & messages::Message::Highlighted) { - TwitchServer::getInstance().mentionsChannel->addMessage(_message); + app->twitch.server->mentionsChannel->addMessage(_message); } c->addMessage(_message); if (app->settings->inlineWhispers) { - TwitchServer::getInstance().forEachChannel([_message](ChannelPtr channel) { + app->twitch.server->forEachChannel([_message](ChannelPtr channel) { channel->addMessage(_message); // }); } @@ -190,8 +195,9 @@ void IrcMessageHandler::handleUserNoticeMessage(Communi::IrcMessage *message) void IrcMessageHandler::handleModeMessage(Communi::IrcMessage *message) { - auto channel = - TwitchServer::getInstance().getChannelOrEmpty(message->parameter(0).remove(0, 1)); + auto app = getApp(); + + auto channel = app->twitch.server->getChannelOrEmpty(message->parameter(0).remove(0, 1)); if (channel->isEmpty()) { return; @@ -206,19 +212,20 @@ void IrcMessageHandler::handleModeMessage(Communi::IrcMessage *message) void IrcMessageHandler::handleNoticeMessage(Communi::IrcNoticeMessage *message) { + auto app = getApp(); MessagePtr msg = Message::createSystemMessage(message->content()); QString channelName; if (!TrimChannelName(message->target(), channelName)) { // Notice wasn't targeted at a single channel, send to all twitch channels - TwitchServer::getInstance().forEachChannelAndSpecialChannels([msg](const auto &c) { + app->twitch.server->forEachChannelAndSpecialChannels([msg](const auto &c) { c->addMessage(msg); // }); return; } - auto channel = TwitchServer::getInstance().getChannelOrEmpty(channelName); + auto channel = app->twitch.server->getChannelOrEmpty(channelName); if (channel->isEmpty()) { debug::Log("[IrcManager:handleNoticeMessage] Channel {} not found in channel manager", diff --git a/src/providers/twitch/twitchmessagebuilder.cpp b/src/providers/twitch/twitchmessagebuilder.cpp index c1cc20c7d..d4843986e 100644 --- a/src/providers/twitch/twitchmessagebuilder.cpp +++ b/src/providers/twitch/twitchmessagebuilder.cpp @@ -539,8 +539,9 @@ bool TwitchMessageBuilder::tryAppendEmote(QString &emoteString) // maybe put the individual badges into a map instead of this mess void TwitchMessageBuilder::appendTwitchBadges() { - singletons::ResourceManager &resourceManager = singletons::ResourceManager::getInstance(); - const auto &channelResources = resourceManager.channels[this->roomID]; + auto app = getApp(); + + const auto &channelResources = app->resources->channels[this->roomID]; auto iterator = this->tags.find("badges"); @@ -557,7 +558,7 @@ void TwitchMessageBuilder::appendTwitchBadges() } if (badge.startsWith("bits/")) { - if (!singletons::ResourceManager::getInstance().dynamicBadgesLoaded) { + if (!app->resources->dynamicBadgesLoaded) { // Do nothing continue; } @@ -576,45 +577,45 @@ void TwitchMessageBuilder::appendTwitchBadges() // Use default bit badge try { - const auto &badge = resourceManager.badgeSets.at("bits").versions.at(versionKey); + const auto &badge = app->resources->badgeSets.at("bits").versions.at(versionKey); this->emplace(badge.badgeImage1x, MessageElement::BadgeVanity); } catch (const std::out_of_range &) { debug::Log("No default bit badge for version {} found", versionKey); continue; } } else if (badge == "staff/1") { - this->emplace(resourceManager.badgeStaff, + this->emplace(app->resources->badgeStaff, MessageElement::BadgeGlobalAuthority) ->setTooltip("Twitch Staff"); } else if (badge == "admin/1") { - this->emplace(resourceManager.badgeAdmin, + this->emplace(app->resources->badgeAdmin, MessageElement::BadgeGlobalAuthority) ->setTooltip("Twitch Admin"); } else if (badge == "global_mod/1") { - this->emplace(resourceManager.badgeGlobalModerator, + this->emplace(app->resources->badgeGlobalModerator, MessageElement::BadgeGlobalAuthority) ->setTooltip("Twitch Global Moderator"); } else if (badge == "moderator/1") { // TODO: Implement custom FFZ moderator badge - this->emplace(resourceManager.badgeModerator, + this->emplace(app->resources->badgeModerator, MessageElement::BadgeChannelAuthority) ->setTooltip("Twitch Channel Moderator"); } else if (badge == "turbo/1") { - this->emplace(resourceManager.badgeTurbo, + this->emplace(app->resources->badgeTurbo, MessageElement::BadgeGlobalAuthority) ->setTooltip("Twitch Turbo Subscriber"); } else if (badge == "broadcaster/1") { - this->emplace(resourceManager.badgeBroadcaster, + this->emplace(app->resources->badgeBroadcaster, MessageElement::BadgeChannelAuthority) ->setTooltip("Twitch Broadcaster"); } else if (badge == "premium/1") { - this->emplace(resourceManager.badgePremium, MessageElement::BadgeVanity) + this->emplace(app->resources->badgePremium, MessageElement::BadgeVanity) ->setTooltip("Twitch Prime Subscriber"); } else if (badge.startsWith("partner/")) { int index = badge.midRef(8).toInt(); switch (index) { case 1: { - this->emplace(resourceManager.badgeVerified, + this->emplace(app->resources->badgeVerified, MessageElement::BadgeVanity) ->setTooltip("Twitch Verified"); } break; @@ -631,7 +632,7 @@ void TwitchMessageBuilder::appendTwitchBadges() auto badgeSetIt = channelResources.badgeSets.find("subscriber"); if (badgeSetIt == channelResources.badgeSets.end()) { // Fall back to default badge - this->emplace(resourceManager.badgeSubscriber, + this->emplace(app->resources->badgeSubscriber, MessageElement::BadgeSubscription) ->setTooltip("Twitch Subscriber"); continue; @@ -645,7 +646,7 @@ void TwitchMessageBuilder::appendTwitchBadges() if (badgeVersionIt == badgeSet.versions.end()) { // Fall back to default badge - this->emplace(resourceManager.badgeSubscriber, + this->emplace(app->resources->badgeSubscriber, MessageElement::BadgeSubscription) ->setTooltip("Twitch Subscriber"); continue; @@ -657,7 +658,7 @@ void TwitchMessageBuilder::appendTwitchBadges() MessageElement::BadgeSubscription) ->setTooltip("Twitch " + QString::fromStdString(badgeVersion.title)); } else { - if (!resourceManager.dynamicBadgesLoaded) { + if (!app->resources->dynamicBadgesLoaded) { // Do nothing continue; } @@ -675,7 +676,7 @@ void TwitchMessageBuilder::appendTwitchBadges() std::string versionKey = parts[1].toStdString(); try { - auto &badgeSet = resourceManager.badgeSets.at(badgeSetKey); + auto &badgeSet = app->resources->badgeSets.at(badgeSetKey); try { auto &badgeVersion = badgeSet.versions.at(versionKey); @@ -696,7 +697,9 @@ void TwitchMessageBuilder::appendTwitchBadges() void TwitchMessageBuilder::appendChatterinoBadges() { - auto &badges = singletons::ResourceManager::getInstance().chatterinoBadges; + auto app = getApp(); + + auto &badges = app->resources->chatterinoBadges; auto it = badges.find(this->userName.toStdString()); if (it == badges.end()) { @@ -711,9 +714,9 @@ void TwitchMessageBuilder::appendChatterinoBadges() bool TwitchMessageBuilder::tryParseCheermote(const QString &string) { + auto app = getApp(); // Try to parse custom cheermotes - const auto &channelResources = - singletons::ResourceManager::getInstance().channels[this->roomID]; + const auto &channelResources = app->resources->channels[this->roomID]; if (channelResources.loaded) { for (const auto &cheermoteSet : channelResources.cheermoteSets) { auto match = cheermoteSet.regex.match(string); diff --git a/src/providers/twitch/twitchserver.cpp b/src/providers/twitch/twitchserver.cpp index b456c1032..7c803f7b8 100644 --- a/src/providers/twitch/twitchserver.cpp +++ b/src/providers/twitch/twitchserver.cpp @@ -23,15 +23,12 @@ TwitchServer::TwitchServer() , watchingChannel(Channel::getEmpty(), Channel::TwitchWatching) { qDebug() << "init TwitchServer"; - - getApp()->accounts->Twitch.userChanged.connect( - [this]() { util::postToThread([this] { this->connect(); }); }); } -TwitchServer &TwitchServer::getInstance() +void TwitchServer::initialize() { - static TwitchServer s; - return s; + getApp()->accounts->Twitch.userChanged.connect( + [this]() { util::postToThread([this] { this->connect(); }); }); } void TwitchServer::initializeConnection(IrcConnection *connection, bool isRead, bool isWrite) @@ -85,7 +82,7 @@ void TwitchServer::privateMessageReceived(IrcPrivateMessage *message) } this->onPrivateMessage.invoke(message); - auto chan = TwitchServer::getInstance().getChannelOrEmpty(channelName); + auto chan = this->getChannelOrEmpty(channelName); if (chan->isEmpty()) { return; @@ -98,7 +95,7 @@ void TwitchServer::privateMessageReceived(IrcPrivateMessage *message) if (!builder.isIgnored()) { messages::MessagePtr _message = builder.build(); if (_message->flags & messages::Message::Highlighted) { - TwitchServer::getInstance().mentionsChannel->addMessage(_message); + this->mentionsChannel->addMessage(_message); } chan->addMessage(_message); diff --git a/src/providers/twitch/twitchserver.hpp b/src/providers/twitch/twitchserver.hpp index 69052dda1..8c0de271a 100644 --- a/src/providers/twitch/twitchserver.hpp +++ b/src/providers/twitch/twitchserver.hpp @@ -13,10 +13,11 @@ namespace twitch { class TwitchServer final : public irc::AbstractIrcServer { TwitchServer(); + friend class Application; + + void initialize(); public: - static TwitchServer &getInstance(); - // fourtf: ugh void forEachChannelAndSpecialChannels(std::function func); diff --git a/src/singletons/accountmanager.hpp b/src/singletons/accountmanager.hpp index 36573a8e2..de7a38abb 100644 --- a/src/singletons/accountmanager.hpp +++ b/src/singletons/accountmanager.hpp @@ -7,10 +7,9 @@ namespace singletons { class AccountManager { - AccountManager() = default; - friend class Application; - public: + AccountManager() = default; + ~AccountManager() = delete; void load(); diff --git a/src/singletons/commandmanager.cpp b/src/singletons/commandmanager.cpp index d3a22fed0..d11877f19 100644 --- a/src/singletons/commandmanager.cpp +++ b/src/singletons/commandmanager.cpp @@ -151,11 +151,12 @@ QString CommandManager::execCommand(const QString &text, ChannelPtr channel, boo return ""; } + auto app = getApp(); + messages::MessageBuilder b; - b.emplace( - getApp()->accounts->Twitch.getCurrent()->getUserName(), - messages::MessageElement::Text); + b.emplace(app->accounts->Twitch.getCurrent()->getUserName(), + messages::MessageElement::Text); b.emplace("->", messages::MessageElement::Text); b.emplace(words[1], messages::MessageElement::Text); @@ -167,7 +168,7 @@ QString CommandManager::execCommand(const QString &text, ChannelPtr channel, boo b.emplace(rest, messages::MessageElement::Text); - TwitchServer::getInstance().whispersChannel->addMessage(b.getMessage()); + app->twitch.server->whispersChannel->addMessage(b.getMessage()); } } diff --git a/src/singletons/commandmanager.hpp b/src/singletons/commandmanager.hpp index c1ea7cbc8..a139c5356 100644 --- a/src/singletons/commandmanager.hpp +++ b/src/singletons/commandmanager.hpp @@ -17,10 +17,9 @@ namespace singletons { class CommandManager { - CommandManager() = default; - friend class Application; - public: + CommandManager() = default; + QString execCommand(const QString &text, std::shared_ptr channel, bool dryRun); void loadCommands(); diff --git a/src/singletons/emotemanager.hpp b/src/singletons/emotemanager.hpp index 21f785610..98e316247 100644 --- a/src/singletons/emotemanager.hpp +++ b/src/singletons/emotemanager.hpp @@ -22,10 +22,9 @@ namespace singletons { class EmoteManager { - EmoteManager(); - friend class Application; - public: + EmoteManager(); + ~EmoteManager() = delete; void initialize(); diff --git a/src/singletons/fontmanager.cpp b/src/singletons/fontmanager.cpp index 61060cc10..59a5e874e 100644 --- a/src/singletons/fontmanager.cpp +++ b/src/singletons/fontmanager.cpp @@ -32,6 +32,7 @@ FontManager::FontManager() this->currentFontByScale.clear(); this->fontChanged.invoke(); }); + this->currentFontSize.connect([this](const int &newValue, auto) { this->incGeneration(); // this->currentFont.setSize(newValue); @@ -40,12 +41,6 @@ FontManager::FontManager() }); } -FontManager &FontManager::getInstance() -{ - static FontManager instance; - return instance; -} - QFont &FontManager::getFont(FontManager::Type type, float scale) { // return this->currentFont.getFont(type); diff --git a/src/singletons/fontmanager.hpp b/src/singletons/fontmanager.hpp index 454bafbb4..8f7d4eaab 100644 --- a/src/singletons/fontmanager.hpp +++ b/src/singletons/fontmanager.hpp @@ -11,11 +11,13 @@ namespace singletons { class FontManager { - FontManager(const FontManager &) = delete; - FontManager(FontManager &&) = delete; +public: FontManager(); -public: + FontManager(const FontManager &) = delete; + FontManager(FontManager &&) = delete; + ~FontManager() = delete; + enum Type : uint8_t { Tiny, Small, @@ -27,9 +29,6 @@ public: VeryLarge, }; - // FontManager is initialized only once, on first use - static FontManager &getInstance(); - QFont &getFont(Type type, float scale); QFontMetrics &getFontMetrics(Type type, float scale); diff --git a/src/singletons/loggingmanager.hpp b/src/singletons/loggingmanager.hpp index 84602c9c0..30681ce62 100644 --- a/src/singletons/loggingmanager.hpp +++ b/src/singletons/loggingmanager.hpp @@ -12,12 +12,11 @@ class PathManager; class LoggingManager { - LoggingManager() = default; - friend class Application; - PathManager *pathManager = nullptr; public: + LoggingManager() = default; + ~LoggingManager() = delete; void initialize(); diff --git a/src/singletons/nativemessagingmanager.cpp b/src/singletons/nativemessagingmanager.cpp index 7671959a0..fcccec231 100644 --- a/src/singletons/nativemessagingmanager.cpp +++ b/src/singletons/nativemessagingmanager.cpp @@ -130,6 +130,8 @@ void NativeMessagingManager::ReceiverThread::run() void NativeMessagingManager::ReceiverThread::handleMessage(const QJsonObject &root) { + auto app = getApp(); + QString action = root.value("action").toString(); if (action.isNull()) { @@ -151,16 +153,15 @@ void NativeMessagingManager::ReceiverThread::handleMessage(const QJsonObject &ro } if (_type == "twitch") { - util::postToThread([name, attach, winId, yOffset] { - auto &ts = providers::twitch::TwitchServer::getInstance(); - - ts.watchingChannel.update(ts.getOrAddChannel(name)); + util::postToThread([name, attach, winId, yOffset, app] { + app->twitch.server->watchingChannel.update( + app->twitch.server->getOrAddChannel(name)); if (attach) { #ifdef USEWINSDK auto *window = widgets::AttachedWindow::get(::GetForegroundWindow(), winId, yOffset); - window->setChannel(ts.getOrAddChannel(name)); + window->setChannel(app->twitch.server->getOrAddChannel(name)); window->show(); #endif } diff --git a/src/singletons/nativemessagingmanager.hpp b/src/singletons/nativemessagingmanager.hpp index f20e6758d..b4d17ab2b 100644 --- a/src/singletons/nativemessagingmanager.hpp +++ b/src/singletons/nativemessagingmanager.hpp @@ -7,10 +7,9 @@ namespace singletons { class NativeMessagingManager { - NativeMessagingManager(); - friend class Application; - public: + NativeMessagingManager(); + ~NativeMessagingManager() = delete; class ReceiverThread : public QThread diff --git a/src/singletons/pathmanager.hpp b/src/singletons/pathmanager.hpp index 0019aaa85..1c4dd888c 100644 --- a/src/singletons/pathmanager.hpp +++ b/src/singletons/pathmanager.hpp @@ -7,10 +7,9 @@ namespace singletons { class PathManager { - PathManager(int argc, char **argv); - friend class Application; - public: + PathManager(int argc, char **argv); + // %APPDATA%/chatterino or ExecutablePath for portable mode QString settingsFolderPath; diff --git a/src/singletons/pubsubmanager.hpp b/src/singletons/pubsubmanager.hpp index 84b26eba1..17095b0b2 100644 --- a/src/singletons/pubsubmanager.hpp +++ b/src/singletons/pubsubmanager.hpp @@ -68,9 +68,6 @@ private: class PubSubManager { - PubSubManager(); - friend class Application; - using WebsocketMessagePtr = websocketpp::config::asio_tls_client::message_type::ptr; using WebsocketContextPtr = websocketpp::lib::shared_ptr; @@ -81,6 +78,8 @@ class PubSubManager std::unique_ptr mainThread; public: + PubSubManager(); + ~PubSubManager() = delete; enum class State { diff --git a/src/singletons/resourcemanager.cpp b/src/singletons/resourcemanager.cpp index c394f8149..274b8ee86 100644 --- a/src/singletons/resourcemanager.cpp +++ b/src/singletons/resourcemanager.cpp @@ -289,18 +289,15 @@ ResourceManager::ResourceManager() , buttonTimeout(lli(":/images/button_timeout.png", 0.25)) { qDebug() << "init ResourceManager"; +} +void ResourceManager::initialize() +{ this->loadDynamicTwitchBadges(); this->loadChatterinoBadges(); } -ResourceManager &ResourceManager::getInstance() -{ - static ResourceManager instance; - return instance; -} - ResourceManager::BadgeVersion::BadgeVersion(QJsonObject &&root) : badgeImage1x(new messages::Image(root.value("image_url_1x").toString())) , badgeImage2x(new messages::Image(root.value("image_url_2x").toString())) diff --git a/src/singletons/resourcemanager.hpp b/src/singletons/resourcemanager.hpp index 981aade8f..17bb7f18a 100644 --- a/src/singletons/resourcemanager.hpp +++ b/src/singletons/resourcemanager.hpp @@ -13,10 +13,12 @@ namespace singletons { class ResourceManager { +public: ResourceManager(); -public: - static ResourceManager &getInstance(); + ~ResourceManager() = delete; + + void initialize(); messages::Image *badgeStaff; messages::Image *badgeAdmin; diff --git a/src/singletons/settingsmanager.cpp b/src/singletons/settingsmanager.cpp index 6e706cb49..2d70b769d 100644 --- a/src/singletons/settingsmanager.cpp +++ b/src/singletons/settingsmanager.cpp @@ -32,7 +32,10 @@ SettingManager::SettingManager() this->wordFlagsListener.cb = [this](auto) { this->updateWordTypeMask(); // }; +} +void SettingManager::initialize() +{ this->moderationActions.connect([this](auto, auto) { this->updateModerationActions(); }); this->ignoredKeywords.connect([this](auto, auto) { this->updateIgnoredKeywords(); }); @@ -52,7 +55,7 @@ bool SettingManager::isIgnoredEmote(const QString &) return false; } -void SettingManager::initialize() +void SettingManager::load() { auto app = getApp(); QString settingsPath = app->paths->settingsFolderPath + "/settings.json"; @@ -155,7 +158,7 @@ const std::shared_ptr> SettingManager::getIgnoredKeywords() void SettingManager::updateModerationActions() { - auto &resources = singletons::ResourceManager::getInstance(); + auto app = getApp(); this->_moderationActions.clear(); @@ -207,10 +210,10 @@ void SettingManager::updateModerationActions() this->_moderationActions.emplace_back(line1, line2, str); } else { - this->_moderationActions.emplace_back(resources.buttonTimeout, str); + this->_moderationActions.emplace_back(app->resources->buttonTimeout, str); } } else if (str.startsWith("/ban ")) { - this->_moderationActions.emplace_back(resources.buttonBan, str); + this->_moderationActions.emplace_back(app->resources->buttonBan, str); } else { QString xD = str; diff --git a/src/singletons/settingsmanager.hpp b/src/singletons/settingsmanager.hpp index ba086eea1..45fa4fd03 100644 --- a/src/singletons/settingsmanager.hpp +++ b/src/singletons/settingsmanager.hpp @@ -21,16 +21,16 @@ class SettingManager using StringSetting = ChatterinoSetting; using QStringSetting = ChatterinoSetting; - SettingManager(); - friend class Application; - public: + SettingManager(); + ~SettingManager() = delete; messages::MessageElement::Flags getWordFlags(); bool isIgnoredEmote(const QString &emote); void initialize(); + void load(); /// Appearance BoolSetting showTimestamps = {"/appearance/messages/showTimestamps", true}; diff --git a/src/singletons/thememanager.hpp b/src/singletons/thememanager.hpp index 2968f6e4c..65bad368b 100644 --- a/src/singletons/thememanager.hpp +++ b/src/singletons/thememanager.hpp @@ -13,10 +13,9 @@ class WindowManager; class ThemeManager { - ThemeManager(); - friend class Application; - public: + ThemeManager(); + ~ThemeManager() = delete; inline bool isLightTheme() const diff --git a/src/singletons/windowmanager.cpp b/src/singletons/windowmanager.cpp index 7ec61e754..fa9499371 100644 --- a/src/singletons/windowmanager.cpp +++ b/src/singletons/windowmanager.cpp @@ -331,16 +331,17 @@ IndirectChannel WindowManager::decodeChannel(const QJsonObject &obj) { util::assertInGuiThread(); + auto app = getApp(); + QString type = obj.value("type").toString(); if (type == "twitch") { - return providers::twitch::TwitchServer::getInstance().getOrAddChannel( - obj.value("name").toString()); + return app->twitch.server->getOrAddChannel(obj.value("name").toString()); } else if (type == "mentions") { - return providers::twitch::TwitchServer::getInstance().mentionsChannel; + return app->twitch.server->mentionsChannel; } else if (type == "watching") { - return providers::twitch::TwitchServer::getInstance().watchingChannel; + return app->twitch.server->watchingChannel; } else if (type == "whispers") { - return providers::twitch::TwitchServer::getInstance().whispersChannel; + return app->twitch.server->whispersChannel; } return Channel::getEmpty(); diff --git a/src/singletons/windowmanager.hpp b/src/singletons/windowmanager.hpp index 81d62f81d..814f92318 100644 --- a/src/singletons/windowmanager.hpp +++ b/src/singletons/windowmanager.hpp @@ -7,10 +7,9 @@ namespace singletons { class WindowManager { - WindowManager(); - friend class Application; - public: + WindowManager(); + ~WindowManager() = delete; void showSettingsDialog(); diff --git a/src/widgets/helper/channelview.cpp b/src/widgets/helper/channelview.cpp index 4797f0d08..79167ac24 100644 --- a/src/widgets/helper/channelview.cpp +++ b/src/widgets/helper/channelview.cpp @@ -75,10 +75,9 @@ ChannelView::ChannelView(BaseWidget *parent) this->goToBottom->getLabel().setText("More messages below"); this->goToBottom->setVisible(false); - this->managedConnections.emplace_back( - singletons::FontManager::getInstance().fontChanged.connect([this] { - this->layoutMessages(); // - })); + this->managedConnections.emplace_back(app->fonts->fontChanged.connect([this] { + this->layoutMessages(); // + })); connect(goToBottom, &RippleEffectLabel::clicked, this, [=] { QTimer::singleShot(180, [=] { @@ -514,7 +513,7 @@ messages::MessageElement::Flags ChannelView::getFlags() const if (split->getModerationMode()) { flags = (MessageElement::Flags)(flags | MessageElement::ModeratorTools); } - if (this->channel == TwitchServer::getInstance().mentionsChannel) { + if (this->channel == app->twitch.server->mentionsChannel) { flags = (MessageElement::Flags)(flags | MessageElement::ChannelName); } } diff --git a/src/widgets/helper/label.cpp b/src/widgets/helper/label.cpp index 26bc71607..45dadf3d6 100644 --- a/src/widgets/helper/label.cpp +++ b/src/widgets/helper/label.cpp @@ -1,4 +1,6 @@ #include "label.hpp" + +#include "application.hpp" #include "singletons/fontmanager.hpp" #include @@ -9,8 +11,11 @@ namespace widgets { Label::Label(BaseWidget *parent) : BaseWidget(parent) { - singletons::FontManager::getInstance().fontChanged.connect( - [this]() { this->scaleChangedEvent(this->getScale()); }); + auto app = getApp(); + + app->fonts->fontChanged.connect([=]() { + this->scaleChangedEvent(this->getScale()); // + }); } const QString &Label::getText() const @@ -37,8 +42,9 @@ void Label::setFontStyle(FontStyle style) void Label::scaleChangedEvent(float scale) { - QFontMetrics metrics = - singletons::FontManager::getInstance().getFontMetrics(this->fontStyle, scale); + auto app = getApp(); + + QFontMetrics metrics = app->fonts->getFontMetrics(this->fontStyle, scale); this->preferedSize = QSize(metrics.width(this->text), metrics.height()); @@ -57,13 +63,13 @@ QSize Label::minimumSizeHint() const void Label::paintEvent(QPaintEvent *) { - QPainter painter(this); - painter.setFont(singletons::FontManager::getInstance().getFont( - this->fontStyle, this->getScale() / painter.device()->devicePixelRatioF())); + auto app = getApp(); - int width = singletons::FontManager::getInstance() - .getFontMetrics(this->fontStyle, this->getScale()) - .width(this->text); + QPainter painter(this); + painter.setFont(app->fonts->getFont(this->fontStyle, + this->getScale() / painter.device()->devicePixelRatioF())); + + int width = app->fonts->getFontMetrics(this->fontStyle, this->getScale()).width(this->text); int flags = Qt::TextSingleLine; diff --git a/src/widgets/helper/splitheader.cpp b/src/widgets/helper/splitheader.cpp index e01b65b52..42fef1c01 100644 --- a/src/widgets/helper/splitheader.cpp +++ b/src/widgets/helper/splitheader.cpp @@ -1,4 +1,6 @@ #include "widgets/helper/splitheader.hpp" + +#include "application.hpp" #include "providers/twitch/twitchchannel.hpp" #include "providers/twitch/twitchserver.hpp" #include "singletons/resourcemanager.hpp" @@ -28,17 +30,16 @@ SplitHeader::SplitHeader(Split *_split) : BaseWidget(_split) , split(_split) { + auto app = getApp(); this->setMouseTracking(true); - singletons::ResourceManager &resourceManager = singletons::ResourceManager::getInstance(); - util::LayoutCreator layoutCreator(this); auto layout = layoutCreator.emplace().withoutMargin(); { // dropdown label auto dropdown = layout.emplace(this).assign(&this->dropdownButton); dropdown->setMouseTracking(true); - dropdown->setPixmap(resourceManager.splitHeaderContext->getPixmap()); + dropdown->setPixmap(app->resources->splitHeaderContext->getPixmap()); this->addDropdownItems(dropdown.getElement()); QObject::connect(dropdown.getElement(), &RippleEffectButton::clicked, this, [this] { QTimer::singleShot(80, [&] { @@ -197,10 +198,11 @@ void SplitHeader::updateChannelText() void SplitHeader::updateModerationModeIcon() { - singletons::ResourceManager &resourceManager = singletons::ResourceManager::getInstance(); + auto app = getApp(); + this->moderationButton->setPixmap(this->split->getModerationMode() - ? resourceManager.moderationmode_enabled->getPixmap() - : resourceManager.moderationmode_disabled->getPixmap()); + ? app->resources->moderationmode_enabled->getPixmap() + : app->resources->moderationmode_disabled->getPixmap()); bool modButtonVisible = false; ChannelPtr channel = this->split->getChannel(); @@ -285,8 +287,10 @@ void SplitHeader::menuReloadChannelEmotes() void SplitHeader::menuManualReconnect() { + auto app = getApp(); + // fourtf: connection - providers::twitch::TwitchServer::getInstance().connect(); + app->twitch.server->connect(); } void SplitHeader::menuShowChangelog() diff --git a/src/widgets/helper/splitinput.cpp b/src/widgets/helper/splitinput.cpp index 85272306f..90416f15d 100644 --- a/src/widgets/helper/splitinput.cpp +++ b/src/widgets/helper/splitinput.cpp @@ -39,7 +39,6 @@ SplitInput::SplitInput(Split *_chatWidget) void SplitInput::initLayout() { auto app = getApp(); - auto &fontManager = singletons::FontManager::getInstance(); util::LayoutCreator layoutCreator(this); auto layout = layoutCreator.setLayoutType().withoutMargin().assign(&this->ui.hbox); @@ -66,11 +65,11 @@ void SplitInput::initLayout() // set edit font this->ui.textEdit->setFont( - fontManager.getFont(singletons::FontManager::Type::Medium, this->getScale())); + app->fonts->getFont(singletons::FontManager::Type::Medium, this->getScale())); - this->managedConnections.emplace_back(fontManager.fontChanged.connect([this, &fontManager]() { + this->managedConnections.emplace_back(app->fonts->fontChanged.connect([=]() { this->ui.textEdit->setFont( - fontManager.getFont(singletons::FontManager::Type::Medium, this->getScale())); + app->fonts->getFont(singletons::FontManager::Type::Medium, this->getScale())); })); // open emote popup diff --git a/src/widgets/selectchanneldialog.cpp b/src/widgets/selectchanneldialog.cpp index e0decf2e2..0a81b1dca 100644 --- a/src/widgets/selectchanneldialog.cpp +++ b/src/widgets/selectchanneldialog.cpp @@ -1,5 +1,6 @@ #include "selectchanneldialog.hpp" +#include "application.hpp" #include "providers/twitch/twitchserver.hpp" #include "util/layoutcreator.hpp" @@ -179,17 +180,18 @@ IndirectChannel SelectChannelDialog::getSelectedChannel() const return this->selectedChannel; } + auto app = getApp(); + switch (this->ui.notebook->getSelectedIndex()) { case TAB_TWITCH: { if (this->ui.twitch.channel->isChecked()) { - return providers::twitch::TwitchServer::getInstance().getOrAddChannel( - this->ui.twitch.channelName->text()); + return app->twitch.server->getOrAddChannel(this->ui.twitch.channelName->text()); } else if (this->ui.twitch.watching->isChecked()) { - return providers::twitch::TwitchServer::getInstance().watchingChannel; + return app->twitch.server->watchingChannel; } else if (this->ui.twitch.mentions->isChecked()) { - return providers::twitch::TwitchServer::getInstance().mentionsChannel; + return app->twitch.server->mentionsChannel; } else if (this->ui.twitch.whispers->isChecked()) { - return providers::twitch::TwitchServer::getInstance().whispersChannel; + return app->twitch.server->whispersChannel; } } } diff --git a/src/widgets/settingspages/appearancepage.cpp b/src/widgets/settingspages/appearancepage.cpp index 60b353012..783dc6e44 100644 --- a/src/widgets/settingspages/appearancepage.cpp +++ b/src/widgets/settingspages/appearancepage.cpp @@ -142,35 +142,33 @@ QLayout *AppearancePage::createThemeColorChanger() QLayout *AppearancePage::createFontChanger() { - QHBoxLayout *layout = new QHBoxLayout; + auto app = getApp(); - auto &fontManager = singletons::FontManager::getInstance(); + QHBoxLayout *layout = new QHBoxLayout; // LABEL QLabel *label = new QLabel(); layout->addWidget(label); - auto updateFontFamilyLabel = [label, &fontManager](auto) { - label->setText(QString::fromStdString(fontManager.currentFontFamily.getValue()) + ", " + - QString::number(fontManager.currentFontSize) + "pt"); + auto updateFontFamilyLabel = [=](auto) { + label->setText(QString::fromStdString(app->fonts->currentFontFamily.getValue()) + ", " + + QString::number(app->fonts->currentFontSize) + "pt"); }; - fontManager.currentFontFamily.connectSimple(updateFontFamilyLabel, this->managedConnections); - fontManager.currentFontSize.connectSimple(updateFontFamilyLabel, this->managedConnections); + app->fonts->currentFontFamily.connectSimple(updateFontFamilyLabel, this->managedConnections); + app->fonts->currentFontSize.connectSimple(updateFontFamilyLabel, this->managedConnections); // BUTTON QPushButton *button = new QPushButton("Select"); layout->addWidget(button); button->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Policy::Fixed); - QObject::connect(button, &QPushButton::clicked, []() { - auto &fontManager = singletons::FontManager::getInstance(); - QFontDialog dialog(fontManager.getFont(singletons::FontManager::Medium, 1.)); + QObject::connect(button, &QPushButton::clicked, [=]() { + QFontDialog dialog(app->fonts->getFont(singletons::FontManager::Medium, 1.)); - dialog.connect(&dialog, &QFontDialog::fontSelected, [](const QFont &font) { - auto &fontManager = singletons::FontManager::getInstance(); - fontManager.currentFontFamily = font.family().toStdString(); - fontManager.currentFontSize = font.pointSize(); + dialog.connect(&dialog, &QFontDialog::fontSelected, [=](const QFont &font) { + app->fonts->currentFontFamily = font.family().toStdString(); + app->fonts->currentFontSize = font.pointSize(); }); dialog.show(); diff --git a/src/widgets/tooltipwidget.cpp b/src/widgets/tooltipwidget.cpp index 22c3f0be0..9637e8284 100644 --- a/src/widgets/tooltipwidget.cpp +++ b/src/widgets/tooltipwidget.cpp @@ -1,4 +1,6 @@ #include "tooltipwidget.hpp" + +#include "application.hpp" #include "singletons/fontmanager.hpp" #include "singletons/thememanager.hpp" @@ -14,6 +16,8 @@ TooltipWidget::TooltipWidget(BaseWidget *parent) : BaseWindow(parent) , displayText(new QLabel()) { + auto app = getApp(); + this->setStyleSheet("color: #fff; background: #000"); this->setWindowOpacity(0.8); this->updateFont(); @@ -31,8 +35,7 @@ TooltipWidget::TooltipWidget(BaseWidget *parent) layout->addWidget(displayText); this->setLayout(layout); - this->fontChangedConnection = - singletons::FontManager::getInstance().fontChanged.connect([this] { this->updateFont(); }); + this->fontChangedConnection = app->fonts->fontChanged.connect([this] { this->updateFont(); }); } TooltipWidget::~TooltipWidget() @@ -47,8 +50,10 @@ void TooltipWidget::scaleChangedEvent(float) void TooltipWidget::updateFont() { - this->setFont(singletons::FontManager::getInstance().getFont( - singletons::FontManager::Type::MediumSmall, this->getScale())); + auto app = getApp(); + + this->setFont( + app->fonts->getFont(singletons::FontManager::Type::MediumSmall, this->getScale())); } void TooltipWidget::setText(QString text)