refactor: Un-singletonize Paths & Updates (#5092)

This commit is contained in:
pajlada 2024-01-16 21:56:43 +01:00 committed by GitHub
parent 7f935665f9
commit 718696db53
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
60 changed files with 237 additions and 165 deletions

View file

@ -117,6 +117,7 @@
- Dev: Channels without any animated elements on screen will skip updates from the GIF timer. (#5042, #5043, #5045) - Dev: Channels without any animated elements on screen will skip updates from the GIF timer. (#5042, #5043, #5045)
- Dev: Autogenerate docs/plugin-meta.lua. (#5055) - Dev: Autogenerate docs/plugin-meta.lua. (#5055)
- Dev: Refactor `NetworkPrivate`. (#5063) - Dev: Refactor `NetworkPrivate`. (#5063)
- Dev: Refactor `Paths` & `Updates`, focusing on reducing their singletoniability. (#5092)
- Dev: Removed duplicate scale in settings dialog. (#5069) - Dev: Removed duplicate scale in settings dialog. (#5069)
- Dev: Fix `NotebookTab` emitting updates for every message. (#5068) - Dev: Fix `NotebookTab` emitting updates for every message. (#5068)
- Dev: Added benchmark for parsing and building recent messages. (#5071) - Dev: Added benchmark for parsing and building recent messages. (#5071)

View file

@ -2,14 +2,26 @@
#include "Application.hpp" #include "Application.hpp"
#include "common/Args.hpp" #include "common/Args.hpp"
#include "singletons/Paths.hpp"
#include "singletons/Updates.hpp"
namespace chatterino::mock { namespace chatterino::mock {
class EmptyApplication : public IApplication class EmptyApplication : public IApplication
{ {
public: public:
EmptyApplication()
: updates_(this->paths_)
{
}
virtual ~EmptyApplication() = default; virtual ~EmptyApplication() = default;
const Paths &getPaths() override
{
return this->paths_;
}
const Args &getArgs() override const Args &getArgs() override
{ {
return this->args_; return this->args_;
@ -168,8 +180,15 @@ public:
return nullptr; return nullptr;
} }
Updates &getUpdates() override
{
return this->updates_;
}
private: private:
Paths paths_;
Args args_; Args args_;
Updates updates_;
}; };
} // namespace chatterino::mock } // namespace chatterino::mock

View file

@ -107,18 +107,20 @@ IApplication::IApplication()
// It will create the instances of the major classes, and connect their signals // It will create the instances of the major classes, and connect their signals
// to each other // to each other
Application::Application(Settings &_settings, Paths &_paths, const Args &_args) Application::Application(Settings &_settings, const Paths &paths,
: args_(_args) const Args &_args, Updates &_updates)
: paths_(paths)
, args_(_args)
, themes(&this->emplace<Theme>()) , themes(&this->emplace<Theme>())
, fonts(&this->emplace<Fonts>()) , fonts(&this->emplace<Fonts>())
, emotes(&this->emplace<Emotes>()) , emotes(&this->emplace<Emotes>())
, accounts(&this->emplace<AccountController>()) , accounts(&this->emplace<AccountController>())
, hotkeys(&this->emplace<HotkeyController>()) , hotkeys(&this->emplace<HotkeyController>())
, windows(&this->emplace<WindowManager>()) , windows(&this->emplace(new WindowManager(paths)))
, toasts(&this->emplace<Toasts>()) , toasts(&this->emplace<Toasts>())
, imageUploader(&this->emplace<ImageUploader>()) , imageUploader(&this->emplace<ImageUploader>())
, seventvAPI(&this->emplace<SeventvAPI>()) , seventvAPI(&this->emplace<SeventvAPI>())
, crashHandler(&this->emplace<CrashHandler>()) , crashHandler(&this->emplace(new CrashHandler(paths)))
, commands(&this->emplace<CommandController>()) , commands(&this->emplace<CommandController>())
, notifications(&this->emplace<NotificationController>()) , notifications(&this->emplace<NotificationController>())
@ -127,14 +129,15 @@ Application::Application(Settings &_settings, Paths &_paths, const Args &_args)
, chatterinoBadges(&this->emplace<ChatterinoBadges>()) , chatterinoBadges(&this->emplace<ChatterinoBadges>())
, ffzBadges(&this->emplace<FfzBadges>()) , ffzBadges(&this->emplace<FfzBadges>())
, seventvBadges(&this->emplace<SeventvBadges>()) , seventvBadges(&this->emplace<SeventvBadges>())
, userData(&this->emplace<UserDataController>()) , userData(&this->emplace(new UserDataController(paths)))
, sound(&this->emplace<ISoundController>(makeSoundController(_settings))) , sound(&this->emplace<ISoundController>(makeSoundController(_settings)))
, twitchLiveController(&this->emplace<TwitchLiveController>()) , twitchLiveController(&this->emplace<TwitchLiveController>())
, twitchPubSub(new PubSub(TWITCH_PUBSUB_URL)) , twitchPubSub(new PubSub(TWITCH_PUBSUB_URL))
, logging(new Logging(_settings)) , logging(new Logging(_settings))
#ifdef CHATTERINO_HAVE_PLUGINS #ifdef CHATTERINO_HAVE_PLUGINS
, plugins(&this->emplace<PluginController>()) , plugins(&this->emplace(new PluginController(paths)))
#endif #endif
, updates(_updates)
{ {
Application::instance = this; Application::instance = this;
@ -152,7 +155,7 @@ void Application::fakeDtor()
this->twitchPubSub.reset(); this->twitchPubSub.reset();
} }
void Application::initialize(Settings &settings, Paths &paths) void Application::initialize(Settings &settings, const Paths &paths)
{ {
assert(isAppInitialized == false); assert(isAppInitialized == false);
isAppInitialized = true; isAppInitialized = true;
@ -237,8 +240,8 @@ int Application::run(QApplication &qtApp)
} }
getSettings()->betaUpdates.connect( getSettings()->betaUpdates.connect(
[] { [this] {
Updates::instance().checkForUpdates(); this->updates.checkForUpdates();
}, },
false); false);
@ -340,7 +343,7 @@ void Application::save()
} }
} }
void Application::initNm(Paths &paths) void Application::initNm(const Paths &paths)
{ {
(void)paths; (void)paths;

View file

@ -15,6 +15,7 @@ class Args;
class TwitchIrcServer; class TwitchIrcServer;
class ITwitchIrcServer; class ITwitchIrcServer;
class PubSub; class PubSub;
class Updates;
class CommandController; class CommandController;
class AccountController; class AccountController;
@ -55,6 +56,7 @@ public:
static IApplication *instance; static IApplication *instance;
virtual const Paths &getPaths() = 0;
virtual const Args &getArgs() = 0; virtual const Args &getArgs() = 0;
virtual Theme *getThemes() = 0; virtual Theme *getThemes() = 0;
virtual Fonts *getFonts() = 0; virtual Fonts *getFonts() = 0;
@ -78,10 +80,12 @@ public:
virtual ITwitchLiveController *getTwitchLiveController() = 0; virtual ITwitchLiveController *getTwitchLiveController() = 0;
virtual ImageUploader *getImageUploader() = 0; virtual ImageUploader *getImageUploader() = 0;
virtual SeventvAPI *getSeventvAPI() = 0; virtual SeventvAPI *getSeventvAPI() = 0;
virtual Updates &getUpdates() = 0;
}; };
class Application : public IApplication class Application : public IApplication
{ {
const Paths &paths_;
const Args &args_; const Args &args_;
std::vector<std::unique_ptr<Singleton>> singletons_; std::vector<std::unique_ptr<Singleton>> singletons_;
int argc_{}; int argc_{};
@ -90,7 +94,8 @@ class Application : public IApplication
public: public:
static Application *instance; static Application *instance;
Application(Settings &_settings, Paths &_paths, const Args &_args); Application(Settings &_settings, const Paths &paths, const Args &_args,
Updates &_updates);
~Application() override; ~Application() override;
Application(const Application &) = delete; Application(const Application &) = delete;
@ -104,7 +109,7 @@ public:
*/ */
void fakeDtor(); void fakeDtor();
void initialize(Settings &settings, Paths &paths); void initialize(Settings &settings, const Paths &paths);
void load(); void load();
void save(); void save();
@ -143,6 +148,10 @@ public:
PluginController *const plugins{}; PluginController *const plugins{};
#endif #endif
const Paths &getPaths() override
{
return this->paths_;
}
const Args &getArgs() override const Args &getArgs() override
{ {
return this->args_; return this->args_;
@ -214,6 +223,10 @@ public:
{ {
return this->seventvAPI; return this->seventvAPI;
} }
Updates &getUpdates() override
{
return this->updates;
}
pajlada::Signals::NoArgSignal streamerModeChanged; pajlada::Signals::NoArgSignal streamerModeChanged;
@ -222,7 +235,7 @@ private:
void initPubSub(); void initPubSub();
void initBttvLiveUpdates(); void initBttvLiveUpdates();
void initSeventvEventAPI(); void initSeventvEventAPI();
void initNm(Paths &paths); void initNm(const Paths &paths);
template <typename T, template <typename T,
typename = std::enable_if_t<std::is_base_of<Singleton, T>::value>> typename = std::enable_if_t<std::is_base_of<Singleton, T>::value>>
@ -242,6 +255,7 @@ private:
} }
NativeMessagingServer nmServer{}; NativeMessagingServer nmServer{};
Updates &updates;
}; };
Application *getApp(); Application *getApp();

View file

@ -98,9 +98,9 @@ namespace {
installCustomPalette(); installCustomPalette();
} }
void showLastCrashDialog(const Args &args) void showLastCrashDialog(const Args &args, const Paths &paths)
{ {
auto *dialog = new LastRunCrashDialog(args); auto *dialog = new LastRunCrashDialog(args, paths);
// Use exec() over open() to block the app from being loaded // Use exec() over open() to block the app from being loaded
// and to be able to set the safe mode. // and to be able to set the safe mode.
dialog->exec(); dialog->exec();
@ -223,7 +223,8 @@ namespace {
} }
} // namespace } // namespace
void runGui(QApplication &a, Paths &paths, Settings &settings, const Args &args) void runGui(QApplication &a, const Paths &paths, Settings &settings,
const Args &args, Updates &updates)
{ {
initQt(); initQt();
initResources(); initResources();
@ -232,7 +233,7 @@ void runGui(QApplication &a, Paths &paths, Settings &settings, const Args &args)
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
if (args.crashRecovery) if (args.crashRecovery)
{ {
showLastCrashDialog(args); showLastCrashDialog(args, paths);
} }
#endif #endif
@ -269,9 +270,9 @@ void runGui(QApplication &a, Paths &paths, Settings &settings, const Args &args)
}); });
chatterino::NetworkManager::init(); chatterino::NetworkManager::init();
chatterino::Updates::instance().checkForUpdates(); updates.checkForUpdates();
Application app(settings, paths, args); Application app(settings, paths, args, updates);
app.initialize(settings, paths); app.initialize(settings, paths);
app.run(a); app.run(a);
app.save(); app.save();

View file

@ -7,8 +7,9 @@ namespace chatterino {
class Args; class Args;
class Paths; class Paths;
class Settings; class Settings;
class Updates;
void runGui(QApplication &a, Paths &paths, Settings &settings, void runGui(QApplication &a, const Paths &paths, Settings &settings,
const Args &args); const Args &args, Updates &updates);
} // namespace chatterino } // namespace chatterino

View file

@ -66,7 +66,7 @@ QStringList extractCommandLine(
namespace chatterino { namespace chatterino {
Args::Args(const QApplication &app) Args::Args(const QApplication &app, const Paths &paths)
{ {
QCommandLineParser parser; QCommandLineParser parser;
parser.setApplicationDescription("Chatterino 2 Client for Twitch Chat"); parser.setApplicationDescription("Chatterino 2 Client for Twitch Chat");
@ -132,7 +132,7 @@ Args::Args(const QApplication &app)
if (parser.isSet(channelLayout)) if (parser.isSet(channelLayout))
{ {
this->applyCustomChannelLayout(parser.value(channelLayout)); this->applyCustomChannelLayout(parser.value(channelLayout), paths);
} }
this->verbose = parser.isSet(verboseOption); this->verbose = parser.isSet(verboseOption);
@ -175,7 +175,7 @@ QStringList Args::currentArguments() const
return this->currentArguments_; return this->currentArguments_;
} }
void Args::applyCustomChannelLayout(const QString &argValue) void Args::applyCustomChannelLayout(const QString &argValue, const Paths &paths)
{ {
WindowLayout layout; WindowLayout layout;
WindowDescriptor window; WindowDescriptor window;
@ -187,10 +187,9 @@ void Args::applyCustomChannelLayout(const QString &argValue)
window.type_ = WindowType::Main; window.type_ = WindowType::Main;
// Load main window layout from config file so we can use the same geometry // Load main window layout from config file so we can use the same geometry
const QRect configMainLayout = [] { const QRect configMainLayout = [paths] {
const QString windowLayoutFile = const QString windowLayoutFile = combinePath(
combinePath(getPaths()->settingsDirectory, paths.settingsDirectory, WindowManager::WINDOW_LAYOUT_FILENAME);
WindowManager::WINDOW_LAYOUT_FILENAME);
const WindowLayout configLayout = const WindowLayout configLayout =
WindowLayout::loadFromFile(windowLayoutFile); WindowLayout::loadFromFile(windowLayoutFile);

View file

@ -8,6 +8,8 @@
namespace chatterino { namespace chatterino {
class Paths;
/// Command line arguments passed to Chatterino. /// Command line arguments passed to Chatterino.
/// ///
/// All accepted arguments: /// All accepted arguments:
@ -31,7 +33,7 @@ class Args
{ {
public: public:
Args() = default; Args() = default;
Args(const QApplication &app); Args(const QApplication &app, const Paths &paths);
bool printVersion{}; bool printVersion{};
@ -56,7 +58,7 @@ public:
QStringList currentArguments() const; QStringList currentArguments() const;
private: private:
void applyCustomChannelLayout(const QString &argValue); void applyCustomChannelLayout(const QString &argValue, const Paths &paths);
QStringList currentArguments_; QStringList currentArguments_;
}; };

View file

@ -1,5 +1,6 @@
#include "common/Credentials.hpp" #include "common/Credentials.hpp"
#include "Application.hpp"
#include "debug/AssertInGuiThread.hpp" #include "debug/AssertInGuiThread.hpp"
#include "singletons/Paths.hpp" #include "singletons/Paths.hpp"
#include "singletons/Settings.hpp" #include "singletons/Settings.hpp"
@ -40,7 +41,7 @@ bool useKeyring()
#ifdef NO_QTKEYCHAIN #ifdef NO_QTKEYCHAIN
return false; return false;
#endif #endif
if (getPaths()->isPortable()) if (getIApp()->getPaths().isPortable())
{ {
return false; return false;
} }
@ -55,7 +56,8 @@ bool useKeyring()
// Insecure storage: // Insecure storage:
QString insecurePath() QString insecurePath()
{ {
return combinePath(getPaths()->settingsDirectory, "credentials.json"); return combinePath(getIApp()->getPaths().settingsDirectory,
"credentials.json");
} }
QJsonDocument loadInsecure() QJsonDocument loadInsecure()

View file

@ -17,7 +17,7 @@ public:
Singleton(Singleton &&) = delete; Singleton(Singleton &&) = delete;
Singleton &operator=(Singleton &&) = delete; Singleton &operator=(Singleton &&) = delete;
virtual void initialize(Settings &settings, Paths &paths) virtual void initialize(Settings &settings, const Paths &paths)
{ {
(void)(settings); (void)(settings);
(void)(paths); (void)(paths);

View file

@ -1,5 +1,6 @@
#include "common/network/NetworkPrivate.hpp" #include "common/network/NetworkPrivate.hpp"
#include "Application.hpp"
#include "common/network/NetworkManager.hpp" #include "common/network/NetworkManager.hpp"
#include "common/network/NetworkResult.hpp" #include "common/network/NetworkResult.hpp"
#include "common/network/NetworkTask.hpp" #include "common/network/NetworkTask.hpp"
@ -57,7 +58,8 @@ void loadUncached(std::shared_ptr<NetworkData> &&data)
void loadCached(std::shared_ptr<NetworkData> &&data) void loadCached(std::shared_ptr<NetworkData> &&data)
{ {
QFile cachedFile(getPaths()->cacheDirectory() + "/" + data->getHash()); QFile cachedFile(getIApp()->getPaths().cacheDirectory() + "/" +
data->getHash());
if (!cachedFile.exists() || !cachedFile.open(QIODevice::ReadOnly)) if (!cachedFile.exists() || !cachedFile.open(QIODevice::ReadOnly))
{ {

View file

@ -1,5 +1,6 @@
#include "common/network/NetworkTask.hpp" #include "common/network/NetworkTask.hpp"
#include "Application.hpp"
#include "common/network/NetworkManager.hpp" #include "common/network/NetworkManager.hpp"
#include "common/network/NetworkPrivate.hpp" #include "common/network/NetworkPrivate.hpp"
#include "common/network/NetworkResult.hpp" #include "common/network/NetworkResult.hpp"
@ -117,7 +118,8 @@ void NetworkTask::logReply()
void NetworkTask::writeToCache(const QByteArray &bytes) const void NetworkTask::writeToCache(const QByteArray &bytes) const
{ {
std::ignore = QtConcurrent::run([data = this->data_, bytes] { std::ignore = QtConcurrent::run([data = this->data_, bytes] {
QFile cachedFile(getPaths()->cacheDirectory() + "/" + data->getHash()); QFile cachedFile(getIApp()->getPaths().cacheDirectory() + "/" +
data->getHash());
if (cachedFile.open(QIODevice::WriteOnly)) if (cachedFile.open(QIODevice::WriteOnly))
{ {

View file

@ -47,7 +47,7 @@ AccountController::AccountController()
}); });
} }
void AccountController::initialize(Settings &settings, Paths &paths) void AccountController::initialize(Settings &settings, const Paths &paths)
{ {
this->twitch.load(); this->twitch.load();
} }

View file

@ -21,7 +21,7 @@ public:
AccountModel *createModel(QObject *parent); AccountModel *createModel(QObject *parent);
void initialize(Settings &settings, Paths &paths) override; void initialize(Settings &settings, const Paths &paths) override;
TwitchAccountManager twitch; TwitchAccountManager twitch;

View file

@ -261,7 +261,7 @@ const std::unordered_map<QString, VariableReplacer> COMMAND_VARS{
namespace chatterino { namespace chatterino {
void CommandController::initialize(Settings &, Paths &paths) void CommandController::initialize(Settings &, const Paths &paths)
{ {
// Update commands map when the vector of commands has been updated // Update commands map when the vector of commands has been updated
auto addFirstMatchToMap = [this](auto args) { auto addFirstMatchToMap = [this](auto args) {

View file

@ -33,7 +33,7 @@ public:
bool dryRun); bool dryRun);
QStringList getDefaultChatterinoCommandList(); QStringList getDefaultChatterinoCommandList();
void initialize(Settings &, Paths &paths) override; void initialize(Settings &, const Paths &paths) override;
void save() override; void save() override;
CommandModel *createModel(QObject *parent); CommandModel *createModel(QObject *parent);

View file

@ -440,7 +440,8 @@ std::ostream &operator<<(std::ostream &os, const HighlightResult &result)
return os; return os;
} }
void HighlightController::initialize(Settings &settings, Paths & /*paths*/) void HighlightController::initialize(Settings &settings,
const Paths & /*paths*/)
{ {
this->rebuildListener_.addSetting(settings.enableSelfHighlight); this->rebuildListener_.addSetting(settings.enableSelfHighlight);
this->rebuildListener_.addSetting(settings.enableSelfHighlightSound); this->rebuildListener_.addSetting(settings.enableSelfHighlightSound);

View file

@ -86,7 +86,7 @@ struct HighlightCheck {
class HighlightController final : public Singleton class HighlightController final : public Singleton
{ {
public: public:
void initialize(Settings &settings, Paths &paths) override; void initialize(Settings &settings, const Paths &paths) override;
/** /**
* @brief Checks the given message parameters if it matches our internal checks, and returns a result * @brief Checks the given message parameters if it matches our internal checks, and returns a result

View file

@ -26,7 +26,7 @@
namespace chatterino { namespace chatterino {
void NotificationController::initialize(Settings &settings, Paths &paths) void NotificationController::initialize(Settings &settings, const Paths &paths)
{ {
this->initialized_ = true; this->initialized_ = true;
for (const QString &channelName : this->twitchSetting_.getValue()) for (const QString &channelName : this->twitchSetting_.getValue())

View file

@ -20,7 +20,7 @@ enum class Platform : uint8_t {
class NotificationController final : public Singleton, private QObject class NotificationController final : public Singleton, private QObject
{ {
public: public:
void initialize(Settings &settings, Paths &paths) override; void initialize(Settings &settings, const Paths &paths) override;
bool isChannelNotified(const QString &channelName, Platform p); bool isChannelNotified(const QString &channelName, Platform p);
void updateChannelNotification(const QString &channelName, Platform p); void updateChannelNotification(const QString &channelName, Platform p);

View file

@ -23,7 +23,12 @@
namespace chatterino { namespace chatterino {
void PluginController::initialize(Settings &settings, Paths &paths) PluginController::PluginController(const Paths &paths_)
: paths(paths_)
{
}
void PluginController::initialize(Settings &settings, const Paths &paths)
{ {
(void)paths; (void)paths;
@ -44,7 +49,7 @@ void PluginController::initialize(Settings &settings, Paths &paths)
void PluginController::loadPlugins() void PluginController::loadPlugins()
{ {
this->plugins_.clear(); this->plugins_.clear();
auto dir = QDir(getPaths()->pluginsDirectory); auto dir = QDir(this->paths.pluginsDirectory);
qCDebug(chatterinoLua) << "Loading plugins in" << dir.path(); qCDebug(chatterinoLua) << "Loading plugins in" << dir.path();
for (const auto &info : for (const auto &info :
dir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot)) dir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot))

View file

@ -26,8 +26,12 @@ class Paths;
class PluginController : public Singleton class PluginController : public Singleton
{ {
const Paths &paths;
public: public:
void initialize(Settings &settings, Paths &paths) override; explicit PluginController(const Paths &paths_);
void initialize(Settings &settings, const Paths &paths) override;
QString tryExecPluginCommand(const QString &commandName, QString tryExecPluginCommand(const QString &commandName,
const CommandContext &ctx); const CommandContext &ctx);

View file

@ -68,7 +68,7 @@ namespace chatterino {
// NUM_SOUNDS specifies how many simultaneous default ping sounds & decoders to create // NUM_SOUNDS specifies how many simultaneous default ping sounds & decoders to create
constexpr const auto NUM_SOUNDS = 4; constexpr const auto NUM_SOUNDS = 4;
void MiniaudioBackend::initialize(Settings &settings, Paths &paths) void MiniaudioBackend::initialize(Settings &settings, const Paths &paths)
{ {
(void)(settings); (void)(settings);
(void)(paths); (void)(paths);

View file

@ -25,7 +25,7 @@ namespace chatterino {
**/ **/
class MiniaudioBackend : public ISoundController class MiniaudioBackend : public ISoundController
{ {
void initialize(Settings &settings, Paths &paths) override; void initialize(Settings &settings, const Paths &paths) override;
public: public:
MiniaudioBackend(); MiniaudioBackend();

View file

@ -8,13 +8,12 @@ namespace {
using namespace chatterino; using namespace chatterino;
std::shared_ptr<pajlada::Settings::SettingManager> initSettingsInstance() std::shared_ptr<pajlada::Settings::SettingManager> initSettingsInstance(
const Paths &paths)
{ {
auto sm = std::make_shared<pajlada::Settings::SettingManager>(); auto sm = std::make_shared<pajlada::Settings::SettingManager>();
auto *paths = getPaths(); auto path = combinePath(paths.settingsDirectory, "user-data.json");
auto path = combinePath(paths->settingsDirectory, "user-data.json");
sm->setPath(path.toUtf8().toStdString()); sm->setPath(path.toUtf8().toStdString());
@ -30,8 +29,8 @@ std::shared_ptr<pajlada::Settings::SettingManager> initSettingsInstance()
namespace chatterino { namespace chatterino {
UserDataController::UserDataController() UserDataController::UserDataController(const Paths &paths)
: sm(initSettingsInstance()) : sm(initSettingsInstance(paths))
, setting("/users", this->sm) , setting("/users", this->sm)
{ {
this->sm->load(); this->sm->load();

View file

@ -17,6 +17,8 @@
namespace chatterino { namespace chatterino {
class Paths;
class IUserDataController class IUserDataController
{ {
public: public:
@ -31,7 +33,7 @@ public:
class UserDataController : public IUserDataController, public Singleton class UserDataController : public IUserDataController, public Singleton
{ {
public: public:
UserDataController(); explicit UserDataController(const Paths &paths);
// Get extra data about a user // Get extra data about a user
// If the user does not have any extra data, return none // If the user does not have any extra data, return none

View file

@ -11,6 +11,7 @@
#include "singletons/CrashHandler.hpp" #include "singletons/CrashHandler.hpp"
#include "singletons/Paths.hpp" #include "singletons/Paths.hpp"
#include "singletons/Settings.hpp" #include "singletons/Settings.hpp"
#include "singletons/Updates.hpp"
#include "util/AttachToConsole.hpp" #include "util/AttachToConsole.hpp"
#include <QApplication> #include <QApplication>
@ -35,11 +36,11 @@ int main(int argc, char **argv)
QCoreApplication::setApplicationVersion(CHATTERINO_VERSION); QCoreApplication::setApplicationVersion(CHATTERINO_VERSION);
QCoreApplication::setOrganizationDomain("chatterino.com"); QCoreApplication::setOrganizationDomain("chatterino.com");
Paths *paths{}; std::unique_ptr<Paths> paths;
try try
{ {
paths = new Paths; paths = std::make_unique<Paths>();
} }
catch (std::runtime_error &error) catch (std::runtime_error &error)
{ {
@ -62,10 +63,10 @@ int main(int argc, char **argv)
return 1; return 1;
} }
const Args args(a); const Args args(a, *paths);
#ifdef CHATTERINO_WITH_CRASHPAD #ifdef CHATTERINO_WITH_CRASHPAD
const auto crashpadHandler = installCrashHandler(args); const auto crashpadHandler = installCrashHandler(args, *paths);
#endif #endif
// run in gui mode or browser extension host mode // run in gui mode or browser extension host mode
@ -92,6 +93,8 @@ int main(int argc, char **argv)
attachToConsole(); attachToConsole();
} }
Updates updates(*paths);
NetworkConfigurationProvider::applyFromEnv(Env::get()); NetworkConfigurationProvider::applyFromEnv(Env::get());
IvrApi::initialize(); IvrApi::initialize();
@ -99,7 +102,7 @@ int main(int argc, char **argv)
Settings settings(paths->settingsDirectory); Settings settings(paths->settingsDirectory);
runGui(a, *paths, settings, args); runGui(a, *paths, settings, args, updates);
} }
return 0; return 0;
} }

View file

@ -11,7 +11,7 @@
#include <QUrl> #include <QUrl>
namespace chatterino { namespace chatterino {
void ChatterinoBadges::initialize(Settings &settings, Paths &paths) void ChatterinoBadges::initialize(Settings &settings, const Paths &paths)
{ {
this->loadChatterinoBadges(); this->loadChatterinoBadges();
} }

View file

@ -18,7 +18,7 @@ using EmotePtr = std::shared_ptr<const Emote>;
class ChatterinoBadges : public Singleton class ChatterinoBadges : public Singleton
{ {
public: public:
void initialize(Settings &settings, Paths &paths) override; void initialize(Settings &settings, const Paths &paths) override;
ChatterinoBadges(); ChatterinoBadges();
std::optional<EmotePtr> getBadge(const UserId &id); std::optional<EmotePtr> getBadge(const UserId &id);

View file

@ -16,7 +16,7 @@
namespace chatterino { namespace chatterino {
void FfzBadges::initialize(Settings &settings, Paths &paths) void FfzBadges::initialize(Settings &settings, const Paths &paths)
{ {
this->load(); this->load();
} }

View file

@ -21,7 +21,7 @@ using EmotePtr = std::shared_ptr<const Emote>;
class FfzBadges : public Singleton class FfzBadges : public Singleton
{ {
public: public:
void initialize(Settings &settings, Paths &paths) override; void initialize(Settings &settings, const Paths &paths) override;
FfzBadges() = default; FfzBadges() = default;
struct Badge { struct Badge {

View file

@ -1,5 +1,6 @@
#include "Irc2.hpp" #include "Irc2.hpp"
#include "Application.hpp"
#include "common/Credentials.hpp" #include "common/Credentials.hpp"
#include "common/SignalVectorModel.hpp" #include "common/SignalVectorModel.hpp"
#include "providers/irc/IrcChannel2.hpp" #include "providers/irc/IrcChannel2.hpp"
@ -21,7 +22,7 @@ namespace {
QString configPath() QString configPath()
{ {
return combinePath(getPaths()->settingsDirectory, "irc.json"); return combinePath(getIApp()->getPaths().settingsDirectory, "irc.json");
} }
class Model : public SignalVectorModel<IrcServerData> class Model : public SignalVectorModel<IrcServerData>

View file

@ -64,7 +64,7 @@ TwitchIrcServer::TwitchIrcServer()
// false); // false);
} }
void TwitchIrcServer::initialize(Settings &settings, Paths &paths) void TwitchIrcServer::initialize(Settings &settings, const Paths &paths)
{ {
getApp()->accounts->twitch.currentUserChanged.connect([this]() { getApp()->accounts->twitch.currentUserChanged.connect([this]() {
postToThread([this] { postToThread([this] {

View file

@ -43,7 +43,7 @@ public:
TwitchIrcServer(); TwitchIrcServer();
~TwitchIrcServer() override = default; ~TwitchIrcServer() override = default;
void initialize(Settings &settings, Paths &paths) override; void initialize(Settings &settings, const Paths &paths) override;
void forEachChannelAndSpecialChannels(std::function<void(ChannelPtr)> func); void forEachChannelAndSpecialChannels(std::function<void(ChannelPtr)> func);

View file

@ -128,7 +128,12 @@ namespace chatterino {
using namespace std::string_literals; using namespace std::string_literals;
void CrashHandler::initialize(Settings & /*settings*/, Paths &paths) CrashHandler::CrashHandler(const Paths &paths_)
: paths(paths_)
{
}
void CrashHandler::initialize(Settings & /*settings*/, const Paths &paths_)
{ {
auto optSettings = readRecoverySettings(paths); auto optSettings = readRecoverySettings(paths);
if (optSettings) if (optSettings)
@ -146,7 +151,7 @@ void CrashHandler::saveShouldRecover(bool value)
{ {
this->shouldRecover_ = value; this->shouldRecover_ = value;
QFile file(QDir(getPaths()->crashdumpDirectory).filePath(RECOVERY_FILE)); QFile file(QDir(this->paths.crashdumpDirectory).filePath(RECOVERY_FILE));
if (!file.open(QFile::WriteOnly | QFile::Truncate)) if (!file.open(QFile::WriteOnly | QFile::Truncate))
{ {
qCWarning(chatterinoCrashhandler) qCWarning(chatterinoCrashhandler)
@ -160,7 +165,8 @@ void CrashHandler::saveShouldRecover(bool value)
} }
#ifdef CHATTERINO_WITH_CRASHPAD #ifdef CHATTERINO_WITH_CRASHPAD
std::unique_ptr<crashpad::CrashpadClient> installCrashHandler(const Args &args) std::unique_ptr<crashpad::CrashpadClient> installCrashHandler(
const Args &args, const Paths &paths)
{ {
// Currently, the following directory layout is assumed: // Currently, the following directory layout is assumed:
// [applicationDirPath] // [applicationDirPath]
@ -188,15 +194,14 @@ std::unique_ptr<crashpad::CrashpadClient> installCrashHandler(const Args &args)
// Argument passed in --database // Argument passed in --database
// > Crash reports are written to this database, and if uploads are enabled, // > Crash reports are written to this database, and if uploads are enabled,
// uploaded from this database to a crash report collection server. // uploaded from this database to a crash report collection server.
auto databaseDir = auto databaseDir = base::FilePath(nativeString(paths.crashdumpDirectory));
base::FilePath(nativeString(getPaths()->crashdumpDirectory));
auto client = std::make_unique<crashpad::CrashpadClient>(); auto client = std::make_unique<crashpad::CrashpadClient>();
std::map<std::string, std::string> annotations{ std::map<std::string, std::string> annotations{
{ {
"canRestart"s, "canRestart"s,
canRestart(*getPaths(), args) ? "true"s : "false"s, canRestart(paths, args) ? "true"s : "false"s,
}, },
{ {
"exePath"s, "exePath"s,

View file

@ -13,10 +13,15 @@
namespace chatterino { namespace chatterino {
class Args; class Args;
class Paths;
class CrashHandler : public Singleton class CrashHandler : public Singleton
{ {
const Paths &paths;
public: public:
explicit CrashHandler(const Paths &paths_);
bool shouldRecover() const bool shouldRecover() const
{ {
return this->shouldRecover_; return this->shouldRecover_;
@ -25,14 +30,15 @@ public:
/// Sets and saves whether Chatterino should restart on a crash /// Sets and saves whether Chatterino should restart on a crash
void saveShouldRecover(bool value); void saveShouldRecover(bool value);
void initialize(Settings &settings, Paths &paths) override; void initialize(Settings &settings, const Paths &paths) override;
private: private:
bool shouldRecover_ = false; bool shouldRecover_ = false;
}; };
#ifdef CHATTERINO_WITH_CRASHPAD #ifdef CHATTERINO_WITH_CRASHPAD
std::unique_ptr<crashpad::CrashpadClient> installCrashHandler(const Args &args); std::unique_ptr<crashpad::CrashpadClient> installCrashHandler(
const Args &args, const Paths &paths);
#endif #endif
} // namespace chatterino } // namespace chatterino

View file

@ -6,7 +6,7 @@ Emotes::Emotes()
{ {
} }
void Emotes::initialize(Settings &settings, Paths &paths) void Emotes::initialize(Settings &settings, const Paths &paths)
{ {
this->emojis.load(); this->emojis.load();

View file

@ -25,7 +25,7 @@ class Emotes final : public IEmotes, public Singleton
public: public:
Emotes(); Emotes();
void initialize(Settings &settings, Paths &paths) override; void initialize(Settings &settings, const Paths &paths) override;
bool isIgnoredEmote(const QString &emote); bool isIgnoredEmote(const QString &emote);

View file

@ -79,7 +79,7 @@ Fonts::Fonts()
this->fontsByType_.resize(size_t(FontStyle::EndType)); this->fontsByType_.resize(size_t(FontStyle::EndType));
} }
void Fonts::initialize(Settings &, Paths &) void Fonts::initialize(Settings &, const Paths &)
{ {
this->chatFontFamily.connect( this->chatFontFamily.connect(
[this]() { [this]() {

View file

@ -43,7 +43,7 @@ class Fonts final : public Singleton
public: public:
Fonts(); Fonts();
void initialize(Settings &settings, Paths &paths) override; void initialize(Settings &settings, const Paths &paths) override;
// font data gets set in createFontData(...) // font data gets set in createFontData(...)

View file

@ -1,5 +1,6 @@
#include "singletons/ImageUploader.hpp" #include "singletons/ImageUploader.hpp"
#include "Application.hpp"
#include "common/Env.hpp" #include "common/Env.hpp"
#include "common/network/NetworkRequest.hpp" #include "common/network/NetworkRequest.hpp"
#include "common/network/NetworkResult.hpp" #include "common/network/NetworkResult.hpp"
@ -50,7 +51,7 @@ void ImageUploader::logToFile(const QString &originalFilePath,
{ {
const QString logFileName = const QString logFileName =
combinePath((getSettings()->logPath.getValue().isEmpty() combinePath((getSettings()->logPath.getValue().isEmpty()
? getPaths()->messageLogDirectory ? getIApp()->getPaths().messageLogDirectory
: getSettings()->logPath), : getSettings()->logPath),
"ImageUploader.json"); "ImageUploader.json");

View file

@ -34,11 +34,11 @@ namespace chatterino {
using namespace literals; using namespace literals;
void registerNmManifest(Paths &paths, const QString &manifestFilename, void registerNmManifest(const Paths &paths, const QString &manifestFilename,
const QString &registryKeyName, const QString &registryKeyName,
const QJsonDocument &document); const QJsonDocument &document);
void registerNmHost(Paths &paths) void registerNmHost(const Paths &paths)
{ {
if (paths.isPortable()) if (paths.isPortable())
{ {
@ -80,7 +80,7 @@ void registerNmHost(Paths &paths)
} }
} }
void registerNmManifest(Paths &paths, const QString &manifestFilename, void registerNmManifest(const Paths &paths, const QString &manifestFilename,
const QString &registryKeyName, const QString &registryKeyName,
const QJsonDocument &document) const QJsonDocument &document)
{ {
@ -99,7 +99,7 @@ void registerNmManifest(Paths &paths, const QString &manifestFilename,
#endif #endif
} }
std::string &getNmQueueName(Paths &paths) std::string &getNmQueueName(const Paths &paths)
{ {
static std::string name = static std::string name =
"chatterino_gui" + paths.applicationFilePathHash.toStdString(); "chatterino_gui" + paths.applicationFilePathHash.toStdString();

View file

@ -16,8 +16,8 @@ class Channel;
using ChannelPtr = std::shared_ptr<Channel>; using ChannelPtr = std::shared_ptr<Channel>;
void registerNmHost(Paths &paths); void registerNmHost(const Paths &paths);
std::string &getNmQueueName(Paths &paths); std::string &getNmQueueName(const Paths &paths);
Atomic<std::optional<QString>> &nmIpcError(); Atomic<std::optional<QString>> &nmIpcError();

View file

@ -15,12 +15,8 @@ using namespace std::literals;
namespace chatterino { namespace chatterino {
Paths *Paths::instance = nullptr;
Paths::Paths() Paths::Paths()
{ {
this->instance = this;
this->initAppFilePathHash(); this->initAppFilePathHash();
this->initCheckPortable(); this->initCheckPortable();
@ -33,12 +29,12 @@ bool Paths::createFolder(const QString &folderPath)
return QDir().mkpath(folderPath); return QDir().mkpath(folderPath);
} }
bool Paths::isPortable() bool Paths::isPortable() const
{ {
return Modes::instance().isPortable; return Modes::instance().isPortable;
} }
QString Paths::cacheDirectory() QString Paths::cacheDirectory() const
{ {
static const auto pathSetting = [] { static const auto pathSetting = [] {
QStringSetting cachePathSetting("/cache/path"); QStringSetting cachePathSetting("/cache/path");
@ -146,9 +142,4 @@ void Paths::initSubDirectories()
this->crashdumpDirectory = makePath("Crashes"); this->crashdumpDirectory = makePath("Crashes");
} }
Paths *getPaths()
{
return Paths::instance;
}
} // namespace chatterino } // namespace chatterino

View file

@ -9,8 +9,6 @@ namespace chatterino {
class Paths class Paths
{ {
public: public:
static Paths *instance;
Paths(); Paths();
// Root directory for the configuration files. %APPDATA%/chatterino or // Root directory for the configuration files. %APPDATA%/chatterino or
@ -42,9 +40,10 @@ public:
QString themesDirectory; QString themesDirectory;
bool createFolder(const QString &folderPath); bool createFolder(const QString &folderPath);
bool isPortable(); [[deprecated("use Modes::instance().portable instead")]] bool isPortable()
const;
QString cacheDirectory(); QString cacheDirectory() const;
private: private:
void initAppFilePathHash(); void initAppFilePathHash();
@ -58,6 +57,4 @@ private:
QString cacheDirectory_; QString cacheDirectory_;
}; };
Paths *getPaths();
} // namespace chatterino } // namespace chatterino

View file

@ -219,7 +219,7 @@ bool Theme::isLightTheme() const
return this->isLight_; return this->isLight_;
} }
void Theme::initialize(Settings &settings, Paths &paths) void Theme::initialize(Settings &settings, const Paths &paths)
{ {
this->themeName.connect( this->themeName.connect(
[this](auto themeName) { [this](auto themeName) {
@ -228,7 +228,7 @@ void Theme::initialize(Settings &settings, Paths &paths)
}, },
false); false);
this->loadAvailableThemes(); this->loadAvailableThemes(paths);
this->update(); this->update();
} }
@ -328,11 +328,11 @@ std::vector<std::pair<QString, QVariant>> Theme::availableThemes() const
return packagedThemes; return packagedThemes;
} }
void Theme::loadAvailableThemes() void Theme::loadAvailableThemes(const Paths &paths)
{ {
this->availableThemes_ = Theme::builtInThemes; this->availableThemes_ = Theme::builtInThemes;
auto dir = QDir(getPaths()->themesDirectory); auto dir = QDir(paths.themesDirectory);
for (const auto &info : for (const auto &info :
dir.entryInfoList(QDir::Files | QDir::NoDotAndDotDot, QDir::Name)) dir.entryInfoList(QDir::Files | QDir::NoDotAndDotDot, QDir::Name))
{ {

View file

@ -43,7 +43,7 @@ public:
static const int AUTO_RELOAD_INTERVAL_MS = 500; static const int AUTO_RELOAD_INTERVAL_MS = 500;
void initialize(Settings &settings, Paths &paths) final; void initialize(Settings &settings, const Paths &paths) final;
bool isLightTheme() const; bool isLightTheme() const;
@ -169,7 +169,7 @@ private:
* *
* NOTE: This is currently not built to be reloadable * NOTE: This is currently not built to be reloadable
**/ **/
void loadAvailableThemes(); void loadAvailableThemes(const Paths &paths);
std::optional<ThemeDescriptor> findThemeByKey(const QString &key); std::optional<ThemeDescriptor> findThemeByKey(const QString &key);

View file

@ -33,7 +33,8 @@ using namespace literals;
QString avatarFilePath(const QString &channelName) QString avatarFilePath(const QString &channelName)
{ {
// TODO: cleanup channel (to be used as a file) and use combinePath // TODO: cleanup channel (to be used as a file) and use combinePath
return getPaths()->twitchProfileAvatars % '/' % channelName % u".png"; return getIApp()->getPaths().twitchProfileAvatars % '/' % channelName %
u".png";
} }
bool hasAvatarForChannel(const QString &channelName) bool hasAvatarForChannel(const QString &channelName)

View file

@ -26,21 +26,14 @@ namespace {
} // namespace } // namespace
Updates::Updates() Updates::Updates(const Paths &paths_)
: currentVersion_(CHATTERINO_VERSION) : paths(paths_)
, currentVersion_(CHATTERINO_VERSION)
, updateGuideLink_("https://chatterino.com") , updateGuideLink_("https://chatterino.com")
{ {
qCDebug(chatterinoUpdate) << "init UpdateManager"; qCDebug(chatterinoUpdate) << "init UpdateManager";
} }
Updates &Updates::instance()
{
// fourtf: don't add this class to the application class
static Updates instance;
return instance;
}
/// Checks if the online version is newer or older than the current version. /// Checks if the online version is newer or older than the current version.
bool Updates::isDowngradeOf(const QString &online, const QString &current) bool Updates::isDowngradeOf(const QString &online, const QString &current)
{ {
@ -97,7 +90,7 @@ void Updates::installUpdates()
box->exec(); box->exec();
QDesktopServices::openUrl(this->updateGuideLink_); QDesktopServices::openUrl(this->updateGuideLink_);
#elif defined Q_OS_WIN #elif defined Q_OS_WIN
if (getPaths()->isPortable()) if (this->paths.isPortable())
{ {
QMessageBox *box = QMessageBox *box =
new QMessageBox(QMessageBox::Information, "Chatterino Update", new QMessageBox(QMessageBox::Information, "Chatterino Update",
@ -136,7 +129,7 @@ void Updates::installUpdates()
QByteArray object = result.getData(); QByteArray object = result.getData();
auto filename = auto filename =
combinePath(getPaths()->miscDirectory, "update.zip"); combinePath(this->paths.miscDirectory, "update.zip");
QFile file(filename); QFile file(filename);
file.open(QIODevice::Truncate | QIODevice::WriteOnly); file.open(QIODevice::Truncate | QIODevice::WriteOnly);
@ -196,7 +189,7 @@ void Updates::installUpdates()
QByteArray object = result.getData(); QByteArray object = result.getData();
auto filePath = auto filePath =
combinePath(getPaths()->miscDirectory, "Update.exe"); combinePath(this->paths.miscDirectory, "Update.exe");
QFile file(filePath); QFile file(filePath);
file.open(QIODevice::Truncate | QIODevice::WriteOnly); file.open(QIODevice::Truncate | QIODevice::WriteOnly);

View file

@ -5,11 +5,19 @@
namespace chatterino { namespace chatterino {
class Paths;
/**
* To check for updates, use the `checkForUpdates` method.
* The class by itself does not start any automatic updates.
*/
class Updates class Updates
{ {
Updates(); const Paths &paths;
public: public:
explicit Updates(const Paths &paths_);
enum Status { enum Status {
None, None,
Searching, Searching,
@ -21,9 +29,6 @@ public:
WriteFileFailed, WriteFileFailed,
}; };
// fourtf: don't add this class to the application class
static Updates &instance();
static bool isDowngradeOf(const QString &online, const QString &current); static bool isDowngradeOf(const QString &online, const QString &current);
void checkForUpdates(); void checkForUpdates();

View file

@ -91,8 +91,8 @@ void WindowManager::showAccountSelectPopup(QPoint point)
w->setFocus(); w->setFocus();
} }
WindowManager::WindowManager() WindowManager::WindowManager(const Paths &paths)
: windowLayoutFilePath(combinePath(getPaths()->settingsDirectory, : windowLayoutFilePath(combinePath(paths.settingsDirectory,
WindowManager::WINDOW_LAYOUT_FILENAME)) WindowManager::WINDOW_LAYOUT_FILENAME))
{ {
qCDebug(chatterinoWindowmanager) << "init WindowManager"; qCDebug(chatterinoWindowmanager) << "init WindowManager";
@ -338,7 +338,7 @@ void WindowManager::setEmotePopupPos(QPoint pos)
this->emotePopupPos_ = pos; this->emotePopupPos_ = pos;
} }
void WindowManager::initialize(Settings &settings, Paths &paths) void WindowManager::initialize(Settings &settings, const Paths &paths)
{ {
(void)paths; (void)paths;
assertInGuiThread(); assertInGuiThread();

View file

@ -37,9 +37,14 @@ class WindowManager final : public Singleton
public: public:
static const QString WINDOW_LAYOUT_FILENAME; static const QString WINDOW_LAYOUT_FILENAME;
WindowManager(); explicit WindowManager(const Paths &paths);
~WindowManager() override; ~WindowManager() override;
WindowManager(const WindowManager &) = delete;
WindowManager(WindowManager &&) = delete;
WindowManager &operator=(const WindowManager &) = delete;
WindowManager &operator=(WindowManager &&) = delete;
static void encodeTab(SplitContainer *tab, bool isSelected, static void encodeTab(SplitContainer *tab, bool isSelected,
QJsonObject &obj); QJsonObject &obj);
static void encodeChannel(IndirectChannel channel, QJsonObject &obj); static void encodeChannel(IndirectChannel channel, QJsonObject &obj);
@ -93,7 +98,7 @@ public:
QPoint emotePopupPos(); QPoint emotePopupPos();
void setEmotePopupPos(QPoint pos); void setEmotePopupPos(QPoint pos);
void initialize(Settings &settings, Paths &paths) override; void initialize(Settings &settings, const Paths &paths) override;
void save() override; void save() override;
void closeAll(); void closeAll();

View file

@ -1,5 +1,6 @@
#include "LoggingChannel.hpp" #include "LoggingChannel.hpp"
#include "Application.hpp"
#include "common/QLogging.hpp" #include "common/QLogging.hpp"
#include "messages/Message.hpp" #include "messages/Message.hpp"
#include "messages/MessageThread.hpp" #include "messages/MessageThread.hpp"
@ -44,8 +45,9 @@ LoggingChannel::LoggingChannel(const QString &_channelName,
QDir::separator() + this->subDirectory; QDir::separator() + this->subDirectory;
getSettings()->logPath.connect([this](const QString &logPath, auto) { getSettings()->logPath.connect([this](const QString &logPath, auto) {
this->baseDirectory = this->baseDirectory = logPath.isEmpty()
logPath.isEmpty() ? getPaths()->messageLogDirectory : logPath; ? getIApp()->getPaths().messageLogDirectory
: logPath;
this->openLogFile(); this->openLogFile();
}); });
} }

View file

@ -1,5 +1,6 @@
#include "util/InitUpdateButton.hpp" #include "util/InitUpdateButton.hpp"
#include "Application.hpp"
#include "widgets/dialogs/UpdateDialog.hpp" #include "widgets/dialogs/UpdateDialog.hpp"
#include "widgets/helper/Button.hpp" #include "widgets/helper/Button.hpp"
@ -40,7 +41,7 @@ void initUpdateButton(Button &button,
} }
break; break;
case UpdateDialog::Install: { case UpdateDialog::Install: {
Updates::instance().installUpdates(); getIApp()->getUpdates().installUpdates();
} }
break; break;
} }
@ -52,17 +53,17 @@ void initUpdateButton(Button &button,
// update image when state changes // update image when state changes
auto updateChange = [&button](auto) { auto updateChange = [&button](auto) {
button.setVisible(Updates::instance().shouldShowUpdateButton()); button.setVisible(getIApp()->getUpdates().shouldShowUpdateButton());
const auto *imageUrl = Updates::instance().isError() const auto *imageUrl = getIApp()->getUpdates().isError()
? ":/buttons/updateError.png" ? ":/buttons/updateError.png"
: ":/buttons/update.png"; : ":/buttons/update.png";
button.setPixmap(QPixmap(imageUrl)); button.setPixmap(QPixmap(imageUrl));
}; };
updateChange(Updates::instance().getStatus()); updateChange(getIApp()->getUpdates().getStatus());
signalHolder.managedConnect(Updates::instance().statusUpdated, signalHolder.managedConnect(getIApp()->getUpdates().statusUpdated,
[updateChange](auto status) { [updateChange](auto status) {
updateChange(status); updateChange(status);
}); });

View file

@ -43,7 +43,7 @@ namespace chatterino {
using namespace literals; using namespace literals;
LastRunCrashDialog::LastRunCrashDialog(const Args &args) LastRunCrashDialog::LastRunCrashDialog(const Args &args, const Paths &paths)
{ {
this->setWindowFlag(Qt::WindowContextHelpButtonHint, false); this->setWindowFlag(Qt::WindowContextHelpButtonHint, false);
this->setWindowTitle(u"Chatterino - " % randomMessage()); this->setWindowTitle(u"Chatterino - " % randomMessage());
@ -56,8 +56,7 @@ LastRunCrashDialog::LastRunCrashDialog(const Args &args)
"<i>You can disable automatic restarts in the settings.</i><br><br>"; "<i>You can disable automatic restarts in the settings.</i><br><br>";
#ifdef CHATTERINO_WITH_CRASHPAD #ifdef CHATTERINO_WITH_CRASHPAD
auto reportsDir = auto reportsDir = QDir(paths.crashdumpDirectory).filePath(u"reports"_s);
QDir(getPaths()->crashdumpDirectory).filePath(u"reports"_s);
text += u"A <b>crash report</b> has been saved to " text += u"A <b>crash report</b> has been saved to "
"<a href=\"file:///" % "<a href=\"file:///" %
reportsDir % u"\">" % reportsDir % u"</a>.<br>"; reportsDir % u"\">" % reportsDir % u"</a>.<br>";

View file

@ -5,11 +5,12 @@
namespace chatterino { namespace chatterino {
class Args; class Args;
class Paths;
class LastRunCrashDialog : public QDialog class LastRunCrashDialog : public QDialog
{ {
public: public:
explicit LastRunCrashDialog(const Args &args); explicit LastRunCrashDialog(const Args &args, const Paths &paths);
}; };
} // namespace chatterino } // namespace chatterino

View file

@ -1,5 +1,6 @@
#include "UpdateDialog.hpp" #include "widgets/dialogs/UpdateDialog.hpp"
#include "Application.hpp"
#include "singletons/Updates.hpp" #include "singletons/Updates.hpp"
#include "util/LayoutCreator.hpp" #include "util/LayoutCreator.hpp"
#include "widgets/Label.hpp" #include "widgets/Label.hpp"
@ -26,7 +27,7 @@ UpdateDialog::UpdateDialog()
auto *dismiss = buttons->addButton("Dismiss", QDialogButtonBox::RejectRole); auto *dismiss = buttons->addButton("Dismiss", QDialogButtonBox::RejectRole);
QObject::connect(install, &QPushButton::clicked, this, [this] { QObject::connect(install, &QPushButton::clicked, this, [this] {
Updates::instance().installUpdates(); getIApp()->getUpdates().installUpdates();
this->close(); this->close();
}); });
QObject::connect(dismiss, &QPushButton::clicked, this, [this] { QObject::connect(dismiss, &QPushButton::clicked, this, [this] {
@ -34,8 +35,8 @@ UpdateDialog::UpdateDialog()
this->close(); this->close();
}); });
this->updateStatusChanged(Updates::instance().getStatus()); this->updateStatusChanged(getIApp()->getUpdates().getStatus());
this->connections_.managedConnect(Updates::instance().statusUpdated, this->connections_.managedConnect(getIApp()->getUpdates().statusUpdated,
[this](auto status) { [this](auto status) {
this->updateStatusChanged(status); this->updateStatusChanged(status);
}); });
@ -52,17 +53,17 @@ void UpdateDialog::updateStatusChanged(Updates::Status status)
{ {
case Updates::UpdateAvailable: { case Updates::UpdateAvailable: {
this->ui_.label->setText(( this->ui_.label->setText((
Updates::instance().isDowngrade() getIApp()->getUpdates().isDowngrade()
? QString( ? QString(
"The version online (%1) seems to be\nlower than the " "The version online (%1) seems to be\nlower than the "
"current (%2).\nEither a version was reverted or " "current (%2).\nEither a version was reverted or "
"you are\nrunning a newer build.\n\nDo you want to " "you are\nrunning a newer build.\n\nDo you want to "
"download and install it?") "download and install it?")
.arg(Updates::instance().getOnlineVersion(), .arg(getIApp()->getUpdates().getOnlineVersion(),
Updates::instance().getCurrentVersion()) getIApp()->getUpdates().getCurrentVersion())
: QString("An update (%1) is available.\n\nDo you want to " : QString("An update (%1) is available.\n\nDo you want to "
"download and install it?") "download and install it?")
.arg(Updates::instance().getOnlineVersion()))); .arg(getIApp()->getUpdates().getOnlineVersion())));
this->updateGeometry(); this->updateGeometry();
} }
break; break;

View file

@ -791,9 +791,10 @@ void GeneralPage::initLayout(GeneralPageView &layout)
"store in this directory."); "store in this directory.");
layout.addButton("Open AppData directory", [] { layout.addButton("Open AppData directory", [] {
#ifdef Q_OS_DARWIN #ifdef Q_OS_DARWIN
QDesktopServices::openUrl("file://" + getPaths()->rootAppDataDirectory); QDesktopServices::openUrl("file://" +
getIApp()->getPaths().rootAppDataDirectory);
#else #else
QDesktopServices::openUrl(getPaths()->rootAppDataDirectory); QDesktopServices::openUrl(getIApp()->getPaths().rootAppDataDirectory);
#endif #endif
}); });
@ -805,7 +806,7 @@ void GeneralPage::initLayout(GeneralPageView &layout)
auto *cachePathLabel = layout.addDescription("placeholder :D"); auto *cachePathLabel = layout.addDescription("placeholder :D");
getSettings()->cachePath.connect([cachePathLabel](const auto &, getSettings()->cachePath.connect([cachePathLabel](const auto &,
auto) mutable { auto) mutable {
QString newPath = getPaths()->cacheDirectory(); QString newPath = getIApp()->getPaths().cacheDirectory();
QString pathShortened = "Cache saved at <a href=\"file:///" + newPath + QString pathShortened = "Cache saved at <a href=\"file:///" + newPath +
"\"><span style=\"color: white;\">" + "\"><span style=\"color: white;\">" +
@ -833,9 +834,9 @@ void GeneralPage::initLayout(GeneralPageView &layout)
if (reply == QMessageBox::Yes) if (reply == QMessageBox::Yes)
{ {
auto cacheDir = QDir(getPaths()->cacheDirectory()); auto cacheDir = QDir(getIApp()->getPaths().cacheDirectory());
cacheDir.removeRecursively(); cacheDir.removeRecursively();
cacheDir.mkdir(getPaths()->cacheDirectory()); cacheDir.mkdir(getIApp()->getPaths().cacheDirectory());
} }
})); }));
box->addStretch(1); box->addStretch(1);
@ -947,7 +948,7 @@ void GeneralPage::initLayout(GeneralPageView &layout)
"When possible, restart Chatterino if the program crashes"); "When possible, restart Chatterino if the program crashes");
#if defined(Q_OS_LINUX) && !defined(NO_QTKEYCHAIN) #if defined(Q_OS_LINUX) && !defined(NO_QTKEYCHAIN)
if (!getPaths()->isPortable()) if (!getIApp()->getPaths().isPortable())
{ {
layout.addCheckbox( layout.addCheckbox(
"Use libsecret/KWallet/Gnome keychain to secure passwords", "Use libsecret/KWallet/Gnome keychain to secure passwords",
@ -1232,7 +1233,7 @@ void GeneralPage::initExtra()
{ {
getSettings()->cachePath.connect( getSettings()->cachePath.connect(
[cachePath = this->cachePath_](const auto &, auto) mutable { [cachePath = this->cachePath_](const auto &, auto) mutable {
QString newPath = getPaths()->cacheDirectory(); QString newPath = getIApp()->getPaths().cacheDirectory();
QString pathShortened = "Current location: <a href=\"file:///" + QString pathShortened = "Current location: <a href=\"file:///" +
newPath + "\">" + newPath + "\">" +

View file

@ -54,7 +54,7 @@ QString formatSize(qint64 size)
QString fetchLogDirectorySize() QString fetchLogDirectorySize()
{ {
QString logsDirectoryPath = getSettings()->logPath.getValue().isEmpty() QString logsDirectoryPath = getSettings()->logPath.getValue().isEmpty()
? getPaths()->messageLogDirectory ? getIApp()->getPaths().messageLogDirectory
: getSettings()->logPath; : getSettings()->logPath;
auto logsSize = dirSize(logsDirectoryPath); auto logsSize = dirSize(logsDirectoryPath);
@ -82,7 +82,8 @@ ModerationPage::ModerationPage()
getSettings()->logPath.connect([logsPathLabel](const QString &logPath, getSettings()->logPath.connect([logsPathLabel](const QString &logPath,
auto) mutable { auto) mutable {
QString pathOriginal = QString pathOriginal =
logPath.isEmpty() ? getPaths()->messageLogDirectory : logPath; logPath.isEmpty() ? getIApp()->getPaths().messageLogDirectory
: logPath;
QString pathShortened = QString pathShortened =
"Logs are saved at <a href=\"file:///" + pathOriginal + "Logs are saved at <a href=\"file:///" + pathOriginal +

View file

@ -37,9 +37,10 @@ PluginsPage::PluginsPage()
auto group = layout.emplace<QGroupBox>("General plugin settings"); auto group = layout.emplace<QGroupBox>("General plugin settings");
this->generalGroup = group.getElement(); this->generalGroup = group.getElement();
auto groupLayout = group.setLayoutType<QFormLayout>(); auto groupLayout = group.setLayoutType<QFormLayout>();
auto *description = new QLabel( auto *description =
"You can load plugins by putting them into " + new QLabel("You can load plugins by putting them into " +
formatRichNamedLink("file:///" + getPaths()->pluginsDirectory, formatRichNamedLink(
"file:///" + getIApp()->getPaths().pluginsDirectory,
"the Plugins directory") + "the Plugins directory") +
". Each one is a new directory."); ". Each one is a new directory.");
description->setOpenExternalLinks(true); description->setOpenExternalLinks(true);