diff --git a/.gitmodules b/.gitmodules index 0141831b2..75ec51a0f 100644 --- a/.gitmodules +++ b/.gitmodules @@ -24,3 +24,6 @@ path = lib/WinToast url = https://github.com/mohabouje/WinToast.git +[submodule "lib/serialize"] + path = lib/serialize + url = https://github.com/pajlada/serialize.git diff --git a/chatterino.pro b/chatterino.pro index 57f3b0435..dcd0e3a20 100644 --- a/chatterino.pro +++ b/chatterino.pro @@ -9,7 +9,7 @@ message(----) QT += widgets core gui network multimedia svg concurrent CONFIG += communi COMMUNI += core model util -CONFIG += c++14 +CONFIG += c++17 INCLUDEPATH += src/ TARGET = chatterino TEMPLATE = app @@ -17,6 +17,8 @@ DEFINES += QT_DEPRECATED_WARNINGS PRECOMPILED_HEADER = src/PrecompiledHeader.hpp CONFIG += precompile_header +QMAKE_CXXFLAGS += -std=c++17 + debug { DEFINES += QT_DEBUG } @@ -43,6 +45,7 @@ macx { # Submodules include(dependencies/rapidjson.pri) +include(dependencies/serialize.pri) include(dependencies/settings.pri) include(dependencies/signals.pri) include(dependencies/humanize.pri) diff --git a/dependencies/boost.pri b/dependencies/boost.pri index 85459ed0b..044de1de7 100644 --- a/dependencies/boost.pri +++ b/dependencies/boost.pri @@ -17,5 +17,5 @@ win32 { LIBS += -L$$BOOST_DIRECTORY\\$$BOOST_LIB_SUFFIX } else { - LIBS += -lboost_system + LIBS += -lboost_system -lboost_filesystem } diff --git a/dependencies/serialize.pri b/dependencies/serialize.pri new file mode 100644 index 000000000..fd23c7642 --- /dev/null +++ b/dependencies/serialize.pri @@ -0,0 +1,2 @@ +# serialize +INCLUDEPATH += $$PWD/../lib/serialize/include/ diff --git a/dependencies/settings.pri b/dependencies/settings.pri index 9b30da6a8..329f9e14f 100644 --- a/dependencies/settings.pri +++ b/dependencies/settings.pri @@ -1,5 +1,5 @@ # settings -DEFINES += PAJLADA_SETTINGS_NO_BOOST +DEFINES += PAJLADA_SETTINGS_BOOST_FILESYSTEM SOURCES += \ $$PWD/../lib/settings/src/settings/settingdata.cpp \ diff --git a/lib/serialize b/lib/serialize new file mode 160000 index 000000000..8df89adc1 --- /dev/null +++ b/lib/serialize @@ -0,0 +1 @@ +Subproject commit 8df89adc101e3208098e323f66caf3d04582281f diff --git a/lib/settings b/lib/settings index bcbd29b79..f564560af 160000 --- a/lib/settings +++ b/lib/settings @@ -1 +1 @@ -Subproject commit bcbd29b793a2895ddf1772dca0105f51a0380798 +Subproject commit f564560afc62de01c0b616d7d219cca5b7c06d97 diff --git a/lib/signals b/lib/signals index a1b61606c..0fde0171d 160000 --- a/lib/signals +++ b/lib/signals @@ -1 +1 @@ -Subproject commit a1b61606c144c34a0f0f9173768cb85dd58e7f29 +Subproject commit 0fde0171d61077e6e30e13fd67f91f72dae34122 diff --git a/src/PrecompiledHeader.hpp b/src/PrecompiledHeader.hpp index 10dfcd418..07b9c4605 100644 --- a/src/PrecompiledHeader.hpp +++ b/src/PrecompiledHeader.hpp @@ -138,7 +138,7 @@ # include # include # include -# include +# include # include # include # include diff --git a/src/common/ChatterinoSetting.cpp b/src/common/ChatterinoSetting.cpp index 8c9a882fa..f3d9272bd 100644 --- a/src/common/ChatterinoSetting.cpp +++ b/src/common/ChatterinoSetting.cpp @@ -4,7 +4,7 @@ namespace chatterino { -void _registerSetting(std::weak_ptr setting) +void _registerSetting(std::weak_ptr setting) { _actuallyRegisterSetting(setting); } diff --git a/src/common/ChatterinoSetting.hpp b/src/common/ChatterinoSetting.hpp index 370f58414..886ef12ce 100644 --- a/src/common/ChatterinoSetting.hpp +++ b/src/common/ChatterinoSetting.hpp @@ -5,7 +5,7 @@ namespace chatterino { -void _registerSetting(std::weak_ptr setting); +void _registerSetting(std::weak_ptr setting); template class ChatterinoSetting : public pajlada::Settings::Setting @@ -14,13 +14,13 @@ public: ChatterinoSetting(const std::string &path) : pajlada::Settings::Setting(path) { - _registerSetting(this->data); + _registerSetting(this->getData()); } ChatterinoSetting(const std::string &path, const Type &defaultValue) : pajlada::Settings::Setting(path, defaultValue) { - _registerSetting(this->data); + _registerSetting(this->getData()); } template @@ -46,6 +46,7 @@ public: using BoolSetting = ChatterinoSetting; using FloatSetting = ChatterinoSetting; +using DoubleSetting = ChatterinoSetting; using IntSetting = ChatterinoSetting; using StringSetting = ChatterinoSetting; using QStringSetting = ChatterinoSetting; diff --git a/src/controllers/highlights/HighlightBlacklistUser.hpp b/src/controllers/highlights/HighlightBlacklistUser.hpp index 0e97b719f..04d2203a3 100644 --- a/src/controllers/highlights/HighlightBlacklistUser.hpp +++ b/src/controllers/highlights/HighlightBlacklistUser.hpp @@ -5,7 +5,7 @@ #include #include -#include +#include #include @@ -68,42 +68,38 @@ private: } // namespace chatterino namespace pajlada { -namespace Settings { - template <> - struct Serialize { - static rapidjson::Value get( - const chatterino::HighlightBlacklistUser &value, - rapidjson::Document::AllocatorType &a) +template <> +struct Serialize { + static rapidjson::Value get(const chatterino::HighlightBlacklistUser &value, + rapidjson::Document::AllocatorType &a) + { + rapidjson::Value ret(rapidjson::kObjectType); + + chatterino::rj::set(ret, "pattern", value.getPattern(), a); + chatterino::rj::set(ret, "regex", value.isRegex(), a); + + return ret; + } +}; + +template <> +struct Deserialize { + static chatterino::HighlightBlacklistUser get(const rapidjson::Value &value) + { + QString pattern; + bool isRegex = false; + + if (!value.IsObject()) { - rapidjson::Value ret(rapidjson::kObjectType); - - AddMember(ret, "pattern", value.getPattern(), a); - AddMember(ret, "regex", value.isRegex(), a); - - return ret; - } - }; - - template <> - struct Deserialize { - static chatterino::HighlightBlacklistUser get( - const rapidjson::Value &value) - { - QString pattern; - bool isRegex = false; - - if (!value.IsObject()) - { - return chatterino::HighlightBlacklistUser(pattern, isRegex); - } - - chatterino::rj::getSafe(value, "pattern", pattern); - chatterino::rj::getSafe(value, "regex", isRegex); - return chatterino::HighlightBlacklistUser(pattern, isRegex); } - }; -} // namespace Settings + chatterino::rj::getSafe(value, "pattern", pattern); + chatterino::rj::getSafe(value, "regex", isRegex); + + return chatterino::HighlightBlacklistUser(pattern, isRegex); + } +}; + } // namespace pajlada diff --git a/src/controllers/highlights/HighlightPhrase.hpp b/src/controllers/highlights/HighlightPhrase.hpp index d5fc5b884..5db0c6999 100644 --- a/src/controllers/highlights/HighlightPhrase.hpp +++ b/src/controllers/highlights/HighlightPhrase.hpp @@ -5,7 +5,7 @@ #include #include -#include +#include namespace chatterino { @@ -70,48 +70,44 @@ private: } // namespace chatterino namespace pajlada { -namespace Settings { - template <> - struct Serialize { - static rapidjson::Value get(const chatterino::HighlightPhrase &value, - rapidjson::Document::AllocatorType &a) +template <> +struct Serialize { + static rapidjson::Value get(const chatterino::HighlightPhrase &value, + rapidjson::Document::AllocatorType &a) + { + rapidjson::Value ret(rapidjson::kObjectType); + + chatterino::rj::set(ret, "pattern", value.getPattern(), a); + chatterino::rj::set(ret, "alert", value.getAlert(), a); + chatterino::rj::set(ret, "sound", value.getSound(), a); + chatterino::rj::set(ret, "regex", value.isRegex(), a); + + return ret; + } +}; + +template <> +struct Deserialize { + static chatterino::HighlightPhrase get(const rapidjson::Value &value) + { + if (!value.IsObject()) { - rapidjson::Value ret(rapidjson::kObjectType); - - AddMember(ret, "pattern", value.getPattern(), a); - AddMember(ret, "alert", value.getAlert(), a); - AddMember(ret, "sound", value.getSound(), a); - AddMember(ret, "regex", value.isRegex(), a); - - return ret; + return chatterino::HighlightPhrase(QString(), true, false, false); } - }; - template <> - struct Deserialize { - static chatterino::HighlightPhrase get(const rapidjson::Value &value) - { - if (!value.IsObject()) - { - return chatterino::HighlightPhrase(QString(), true, false, - false); - } + QString _pattern; + bool _alert = true; + bool _sound = false; + bool _isRegex = false; - QString _pattern; - bool _alert = true; - bool _sound = false; - bool _isRegex = false; + chatterino::rj::getSafe(value, "pattern", _pattern); + chatterino::rj::getSafe(value, "alert", _alert); + chatterino::rj::getSafe(value, "sound", _sound); + chatterino::rj::getSafe(value, "regex", _isRegex); - chatterino::rj::getSafe(value, "pattern", _pattern); - chatterino::rj::getSafe(value, "alert", _alert); - chatterino::rj::getSafe(value, "sound", _sound); - chatterino::rj::getSafe(value, "regex", _isRegex); + return chatterino::HighlightPhrase(_pattern, _alert, _sound, _isRegex); + } +}; - return chatterino::HighlightPhrase(_pattern, _alert, _sound, - _isRegex); - } - }; - -} // namespace Settings } // namespace pajlada diff --git a/src/controllers/ignores/IgnorePhrase.hpp b/src/controllers/ignores/IgnorePhrase.hpp index 10a943b89..892f8ec39 100644 --- a/src/controllers/ignores/IgnorePhrase.hpp +++ b/src/controllers/ignores/IgnorePhrase.hpp @@ -9,7 +9,7 @@ #include #include -#include +#include #include @@ -138,53 +138,51 @@ private: } // namespace chatterino namespace pajlada { -namespace Settings { - template <> - struct Serialize { - static rapidjson::Value get(const chatterino::IgnorePhrase &value, - rapidjson::Document::AllocatorType &a) +template <> +struct Serialize { + static rapidjson::Value get(const chatterino::IgnorePhrase &value, + rapidjson::Document::AllocatorType &a) + { + rapidjson::Value ret(rapidjson::kObjectType); + + chatterino::rj::set(ret, "pattern", value.getPattern(), a); + chatterino::rj::set(ret, "regex", value.isRegex(), a); + chatterino::rj::set(ret, "isBlock", value.isBlock(), a); + chatterino::rj::set(ret, "replaceWith", value.getReplace(), a); + chatterino::rj::set(ret, "caseSensitive", value.isCaseSensitive(), a); + + return ret; + } +}; + +template <> +struct Deserialize { + static chatterino::IgnorePhrase get(const rapidjson::Value &value) + { + if (!value.IsObject()) { - rapidjson::Value ret(rapidjson::kObjectType); - - AddMember(ret, "pattern", value.getPattern(), a); - AddMember(ret, "regex", value.isRegex(), a); - AddMember(ret, "isBlock", value.isBlock(), a); - AddMember(ret, "replaceWith", value.getReplace(), a); - AddMember(ret, "caseSensitive", value.isCaseSensitive(), a); - - return ret; + return chatterino::IgnorePhrase( + QString(), false, false, + ::chatterino::getSettings()->ignoredPhraseReplace.getValue(), + true); } - }; - template <> - struct Deserialize { - static chatterino::IgnorePhrase get(const rapidjson::Value &value) - { - if (!value.IsObject()) - { - return chatterino::IgnorePhrase( - QString(), false, false, - ::chatterino::getSettings() - ->ignoredPhraseReplace.getValue(), - true); - } + QString _pattern; + bool _isRegex = false; + bool _isBlock = false; + QString _replace; + bool _caseSens = true; - QString _pattern; - bool _isRegex = false; - bool _isBlock = false; - QString _replace; - bool _caseSens = true; + chatterino::rj::getSafe(value, "pattern", _pattern); + chatterino::rj::getSafe(value, "regex", _isRegex); + chatterino::rj::getSafe(value, "isBlock", _isBlock); + chatterino::rj::getSafe(value, "replaceWith", _replace); + chatterino::rj::getSafe(value, "caseSensitive", _caseSens); - chatterino::rj::getSafe(value, "pattern", _pattern); - chatterino::rj::getSafe(value, "regex", _isRegex); - chatterino::rj::getSafe(value, "isBlock", _isBlock); - chatterino::rj::getSafe(value, "replaceWith", _replace); - chatterino::rj::getSafe(value, "caseSensitive", _caseSens); + return chatterino::IgnorePhrase(_pattern, _isRegex, _isBlock, _replace, + _caseSens); + } +}; - return chatterino::IgnorePhrase(_pattern, _isRegex, _isBlock, - _replace, _caseSens); - } - }; -} // namespace Settings } // namespace pajlada diff --git a/src/controllers/moderationactions/ModerationAction.hpp b/src/controllers/moderationactions/ModerationAction.hpp index 6b1399c1b..e7d0eca31 100644 --- a/src/controllers/moderationactions/ModerationAction.hpp +++ b/src/controllers/moderationactions/ModerationAction.hpp @@ -2,7 +2,7 @@ #include #include -#include +#include #include "util/RapidjsonHelpers.hpp" @@ -34,37 +34,35 @@ private: } // namespace chatterino namespace pajlada { -namespace Settings { - template <> - struct Serialize { - static rapidjson::Value get(const chatterino::ModerationAction &value, - rapidjson::Document::AllocatorType &a) +template <> +struct Serialize { + static rapidjson::Value get(const chatterino::ModerationAction &value, + rapidjson::Document::AllocatorType &a) + { + rapidjson::Value ret(rapidjson::kObjectType); + + chatterino::rj::set(ret, "pattern", value.getAction(), a); + + return ret; + } +}; + +template <> +struct Deserialize { + static chatterino::ModerationAction get(const rapidjson::Value &value) + { + if (!value.IsObject()) { - rapidjson::Value ret(rapidjson::kObjectType); - - AddMember(ret, "pattern", value.getAction(), a); - - return ret; + return chatterino::ModerationAction(QString()); } - }; - template <> - struct Deserialize { - static chatterino::ModerationAction get(const rapidjson::Value &value) - { - if (!value.IsObject()) - { - return chatterino::ModerationAction(QString()); - } + QString pattern; - QString pattern; + chatterino::rj::getSafe(value, "pattern", pattern); - chatterino::rj::getSafe(value, "pattern", pattern); + return chatterino::ModerationAction(pattern); + } +}; - return chatterino::ModerationAction(pattern); - } - }; - -} // namespace Settings } // namespace pajlada diff --git a/src/providers/emoji/Emojis.cpp b/src/providers/emoji/Emojis.cpp index a219cceba..d42f619ef 100644 --- a/src/providers/emoji/Emojis.cpp +++ b/src/providers/emoji/Emojis.cpp @@ -242,7 +242,7 @@ void Emojis::loadEmojiSet() { auto app = getApp(); - getSettings()->emojiSet.connect([=](const auto &emojiSet, auto) { + getSettings()->emojiSet.connect([=](const auto &emojiSet) { this->emojis.each([=](const auto &name, std::shared_ptr &emoji) { QString emojiSetToUse = emojiSet; diff --git a/src/providers/twitch/TwitchAccountManager.cpp b/src/providers/twitch/TwitchAccountManager.cpp index a386d15d1..a42c344da 100644 --- a/src/providers/twitch/TwitchAccountManager.cpp +++ b/src/providers/twitch/TwitchAccountManager.cpp @@ -79,25 +79,25 @@ void TwitchAccountManager::reloadUsers() continue; } - std::string username = pajlada::Settings::Setting::get( + auto username = pajlada::Settings::Setting::get( "/accounts/" + uid + "/username"); - std::string userID = pajlada::Settings::Setting::get( - "/accounts/" + uid + "/userID"); - std::string clientID = pajlada::Settings::Setting::get( + auto userID = pajlada::Settings::Setting::get("/accounts/" + + uid + "/userID"); + auto clientID = pajlada::Settings::Setting::get( "/accounts/" + uid + "/clientID"); - std::string oauthToken = pajlada::Settings::Setting::get( + auto oauthToken = pajlada::Settings::Setting::get( "/accounts/" + uid + "/oauthToken"); - if (username.empty() || userID.empty() || clientID.empty() || - oauthToken.empty()) + if (username.isEmpty() || userID.isEmpty() || clientID.isEmpty() || + oauthToken.isEmpty()) { continue; } - userData.username = qS(username).trimmed(); - userData.userID = qS(userID).trimmed(); - userData.clientID = qS(clientID).trimmed(); - userData.oauthToken = qS(oauthToken).trimmed(); + userData.username = username.trimmed(); + userData.userID = userID.trimmed(); + userData.clientID = clientID.trimmed(); + userData.oauthToken = oauthToken.trimmed(); switch (this->addUser(userData)) { @@ -138,8 +138,7 @@ void TwitchAccountManager::load() { this->reloadUsers(); - this->currentUsername.connect([this](const auto &newValue, auto) { - QString newUsername(QString::fromStdString(newValue)); + this->currentUsername.connect([this](const QString &newUsername) { auto user = this->findUserByUsername(newUsername); if (user) { @@ -175,14 +174,14 @@ bool TwitchAccountManager::removeUser(TwitchAccount *account) { const auto &accs = this->accounts.getVector(); - std::string userID(account->getUserId().toStdString()); - if (!userID.empty()) + auto userID(account->getUserId()); + if (!userID.isEmpty()) { - pajlada::Settings::SettingManager::removeSetting("/accounts/uid" + - userID); + pajlada::Settings::SettingManager::removeSetting( + fS("/accounts/uid{}", userID)); } - if (account->getUserName() == qS(this->currentUsername.getValue())) + if (account->getUserName() == this->currentUsername) { // The user that was removed is the current user, log into the anonymous // user diff --git a/src/providers/twitch/TwitchAccountManager.hpp b/src/providers/twitch/TwitchAccountManager.hpp index 7c79ea249..d11bb79af 100644 --- a/src/providers/twitch/TwitchAccountManager.hpp +++ b/src/providers/twitch/TwitchAccountManager.hpp @@ -1,11 +1,10 @@ #pragma once +#include "common/ChatterinoSetting.hpp" #include "common/SignalVector.hpp" #include "providers/twitch/TwitchAccount.hpp" #include "util/SharedPtrElementLess.hpp" -#include - #include #include @@ -47,8 +46,7 @@ public: bool isLoggedIn() const; - pajlada::Settings::Setting currentUsername = { - "/accounts/current", ""}; + QStringSetting currentUsername{"/accounts/current", ""}; pajlada::Signals::NoArgSignal currentUserChanged; pajlada::Signals::NoArgSignal userListUpdated; diff --git a/src/providers/twitch/TwitchChannel.cpp b/src/providers/twitch/TwitchChannel.cpp index c03ad2b66..10685c9ee 100644 --- a/src/providers/twitch/TwitchChannel.cpp +++ b/src/providers/twitch/TwitchChannel.cpp @@ -470,8 +470,6 @@ void TwitchChannel::refreshLiveStatus() return; } - log("[TwitchChannel:{}] Refreshing live status", this->getName()); - QString url("https://api.twitch.tv/kraken/streams/" + roomID); // auto request = makeGetStreamRequest(roomID, QThread::currentThread()); diff --git a/src/providers/twitch/TwitchUser.hpp b/src/providers/twitch/TwitchUser.hpp index 6b68bec50..962ce8d38 100644 --- a/src/providers/twitch/TwitchUser.hpp +++ b/src/providers/twitch/TwitchUser.hpp @@ -4,7 +4,7 @@ #include #include -#include +#include #include @@ -32,49 +32,42 @@ struct TwitchUser { } // namespace chatterino namespace pajlada { -namespace Settings { - template <> - struct Deserialize { - static chatterino::TwitchUser get(const rapidjson::Value &value, - bool *error = nullptr) +template <> +struct Deserialize { + static chatterino::TwitchUser get(const rapidjson::Value &value, + bool *error = nullptr) + { + using namespace chatterino; + + TwitchUser user; + + if (!value.IsObject()) { - using namespace chatterino; - - TwitchUser user; - - if (!value.IsObject()) - { - PAJLADA_REPORT_ERROR(error) - PAJLADA_THROW_EXCEPTION( - "Deserialized rapidjson::Value is wrong type"); - return user; - } - - if (!rj::getSafe(value, "_id", user.id)) - { - PAJLADA_REPORT_ERROR(error) - PAJLADA_THROW_EXCEPTION("Missing ID key"); - return user; - } - - if (!rj::getSafe(value, "name", user.name)) - { - PAJLADA_REPORT_ERROR(error) - PAJLADA_THROW_EXCEPTION("Missing name key"); - return user; - } - - if (!rj::getSafe(value, "display_name", user.displayName)) - { - PAJLADA_REPORT_ERROR(error) - PAJLADA_THROW_EXCEPTION("Missing display name key"); - return user; - } - + PAJLADA_REPORT_ERROR(error) return user; } - }; -} // namespace Settings + if (!rj::getSafe(value, "_id", user.id)) + { + PAJLADA_REPORT_ERROR(error) + return user; + } + + if (!rj::getSafe(value, "name", user.name)) + { + PAJLADA_REPORT_ERROR(error) + return user; + } + + if (!rj::getSafe(value, "display_name", user.displayName)) + { + PAJLADA_REPORT_ERROR(error) + return user; + } + + return user; + } +}; + } // namespace pajlada diff --git a/src/singletons/Fonts.cpp b/src/singletons/Fonts.cpp index 1700f43b1..ea41c3406 100644 --- a/src/singletons/Fonts.cpp +++ b/src/singletons/Fonts.cpp @@ -32,37 +32,43 @@ Fonts::Fonts() void Fonts::initialize(Settings &, Paths &) { - this->chatFontFamily.connect([this](const std::string &, auto) { - assertInGuiThread(); + this->chatFontFamily.connect( + [this]() { + assertInGuiThread(); - for (auto &map : this->fontsByType_) - { - map.clear(); - } - this->fontChanged.invoke(); - }); + for (auto &map : this->fontsByType_) + { + map.clear(); + } + this->fontChanged.invoke(); + }, + false); - this->chatFontSize.connect([this](const int &, auto) { - assertInGuiThread(); + this->chatFontSize.connect( + [this]() { + assertInGuiThread(); - for (auto &map : this->fontsByType_) - { - map.clear(); - } - this->fontChanged.invoke(); - }); + for (auto &map : this->fontsByType_) + { + map.clear(); + } + this->fontChanged.invoke(); + }, + false); - getSettings()->boldScale.connect([this](const int &, auto) { - assertInGuiThread(); + getSettings()->boldScale.connect( + [this]() { + assertInGuiThread(); - getApp()->windows->incGeneration(); + getApp()->windows->incGeneration(); - for (auto &map : this->fontsByType_) - { - map.clear(); - } - this->fontChanged.invoke(); - }); + for (auto &map : this->fontsByType_) + { + map.clear(); + } + this->fontChanged.invoke(); + }, + false); } QFont Fonts::getFont(FontStyle type, float scale) @@ -118,7 +124,7 @@ Fonts::FontData Fonts::createFontData(FontStyle type, float scale) 1, false, QFont::Weight(getSettings()->boldScale.getValue())}; auto data = sizeScale[type]; return FontData( - QFont(QString::fromStdString(this->chatFontFamily.getValue()), + QFont(this->chatFontFamily.getValue(), int(this->chatFontSize.getValue() * data.scale * scale), data.weight, data.italic)); } diff --git a/src/singletons/Fonts.hpp b/src/singletons/Fonts.hpp index 61ba393d6..0a1eb5790 100644 --- a/src/singletons/Fonts.hpp +++ b/src/singletons/Fonts.hpp @@ -1,14 +1,15 @@ #pragma once +#include "common/ChatterinoSetting.hpp" #include "common/Singleton.hpp" #include #include #include -#include #include -#include #include + +#include #include namespace chatterino { @@ -49,8 +50,8 @@ public: QFont getFont(FontStyle type, float scale); QFontMetrics getFontMetrics(FontStyle type, float scale); - pajlada::Settings::Setting chatFontFamily; - pajlada::Settings::Setting chatFontSize; + QStringSetting chatFontFamily; + IntSetting chatFontSize; pajlada::Signals::NoArgSignal fontChanged; diff --git a/src/singletons/Settings.cpp b/src/singletons/Settings.cpp index 0cb2bef67..03b58936d 100644 --- a/src/singletons/Settings.cpp +++ b/src/singletons/Settings.cpp @@ -8,12 +8,12 @@ namespace chatterino { -std::vector> _settings; +std::vector> _settings; Settings *Settings::instance = nullptr; void _actuallyRegisterSetting( - std::weak_ptr setting) + std::weak_ptr setting) { _settings.push_back(setting); } @@ -24,7 +24,15 @@ Settings::Settings(Paths &paths) QString settingsPath = paths.settingsDirectory + "/settings.json"; - pajlada::Settings::SettingManager::gLoad(qPrintable(settingsPath)); + // get global instance of the settings library + auto settingsInstance = pajlada::Settings::SettingManager::getInstance(); + + settingsInstance->load(qPrintable(settingsPath)); + + settingsInstance->setBackupEnabled(true); + settingsInstance->setBackupSlots(9); + settingsInstance->saveMethod = + pajlada::Settings::SettingManager::SaveMethod::SaveOnExit; } Settings &Settings::getInstance() @@ -46,13 +54,20 @@ void Settings::saveSnapshot() } rapidjson::Value key(setting->getPath().c_str(), a); - rapidjson::Value val = setting->marshalInto(*d); + auto curVal = setting->unmarshalJSON(); + if (curVal == nullptr) + { + continue; + } + + rapidjson::Value val; + val.CopyFrom(*curVal, a); d->AddMember(key.Move(), val.Move(), a); } - this->snapshot_.reset(d); + // log("Snapshot state: {}", rj::stringify(*d)); - log("hehe: {}", pajlada::Settings::SettingManager::stringify(*d)); + this->snapshot_.reset(d); } void Settings::restoreSnapshot() @@ -62,26 +77,29 @@ void Settings::restoreSnapshot() return; } - const auto &snapshotObject = this->snapshot_->GetObject(); + const auto &snapshot = *(this->snapshot_.get()); + + if (!snapshot.IsObject()) + { + return; + } for (const auto &weakSetting : _settings) { auto setting = weakSetting.lock(); if (!setting) { - log("Error stage 1 of loading"); continue; } const char *path = setting->getPath().c_str(); - if (!snapshotObject.HasMember(path)) + if (!snapshot.HasMember(path)) { - log("Error stage 2 of loading"); continue; } - setting->unmarshalValue(snapshotObject[path]); + setting->marshalJSON(snapshot[path]); } } diff --git a/src/singletons/Settings.hpp b/src/singletons/Settings.hpp index aa49cfca8..e23bf6a72 100644 --- a/src/singletons/Settings.hpp +++ b/src/singletons/Settings.hpp @@ -12,7 +12,7 @@ namespace chatterino { void _actuallyRegisterSetting( - std::weak_ptr setting); + std::weak_ptr setting); class Settings { diff --git a/src/singletons/Theme.cpp b/src/singletons/Theme.cpp index 9aba1f500..f209c2d0f 100644 --- a/src/singletons/Theme.cpp +++ b/src/singletons/Theme.cpp @@ -39,8 +39,6 @@ namespace detail { } // namespace detail Theme::Theme() - : themeName("/appearance/theme/name", "Dark") - , themeHue("/appearance/theme/hue", 0.0) { this->update(); diff --git a/src/singletons/Theme.hpp b/src/singletons/Theme.hpp index 2267b68f3..f0521688c 100644 --- a/src/singletons/Theme.hpp +++ b/src/singletons/Theme.hpp @@ -130,8 +130,8 @@ public: pajlada::Signals::NoArgSignal updated; - pajlada::Settings::Setting themeName; - pajlada::Settings::Setting themeHue; + QStringSetting themeName{"/appearance/theme/name", "Dark"}; + DoubleSetting themeHue{"/appearance/theme/hue", 0.0}; private: void actuallyUpdate(double hue, double multiplier); diff --git a/src/util/RapidJsonSerializeQString.hpp b/src/util/RapidJsonSerializeQString.hpp index de6812c70..1c685d16f 100644 --- a/src/util/RapidJsonSerializeQString.hpp +++ b/src/util/RapidJsonSerializeQString.hpp @@ -1,49 +1,45 @@ #pragma once #include -#include +#include namespace pajlada { -namespace Settings { - template <> - struct Serialize { - static rapidjson::Value get(const QString &value, - rapidjson::Document::AllocatorType &a) +template <> +struct Serialize { + static rapidjson::Value get(const QString &value, + rapidjson::Document::AllocatorType &a) + { + return rapidjson::Value(value.toUtf8(), a); + } +}; + +template <> +struct Deserialize { + static QString get(const rapidjson::Value &value, bool *error = nullptr) + { + if (!value.IsString()) { - return rapidjson::Value(value.toUtf8(), a); - } - }; - - template <> - struct Deserialize { - static QString get(const rapidjson::Value &value, bool *error = nullptr) - { - if (!value.IsString()) - { - PAJLADA_REPORT_ERROR(error) - PAJLADA_THROW_EXCEPTION( - "Deserialized rapidjson::Value is not a string"); - return QString{}; - } - - try - { - return QString::fromUtf8(value.GetString(), - value.GetStringLength()); - } - catch (const std::exception &) - { - // int x = 5; - } - catch (...) - { - // int y = 5; - } - + PAJLADA_REPORT_ERROR(error) return QString{}; } - }; -} // namespace Settings + try + { + return QString::fromUtf8(value.GetString(), + value.GetStringLength()); + } + catch (const std::exception &) + { + // int x = 5; + } + catch (...) + { + // int y = 5; + } + + return QString{}; + } +}; + } // namespace pajlada diff --git a/src/util/RapidjsonHelpers.hpp b/src/util/RapidjsonHelpers.hpp index 85b0ba971..84a4b8f7e 100644 --- a/src/util/RapidjsonHelpers.hpp +++ b/src/util/RapidjsonHelpers.hpp @@ -3,7 +3,7 @@ #include "util/RapidJsonSerializeQString.hpp" #include -#include +#include #include #include @@ -24,8 +24,7 @@ namespace rj { { assert(obj.IsObject()); - addMember(obj, key, pajlada::Settings::Serialize::get(value, a), - a); + addMember(obj, key, pajlada::Serialize::get(value, a), a); } template <> @@ -45,8 +44,7 @@ namespace rj { auto &a = obj.GetAllocator(); - addMember(obj, key, pajlada::Settings::Serialize::get(value, a), - a); + addMember(obj, key, pajlada::Serialize::get(value, a), a); } template <> @@ -66,7 +64,7 @@ namespace rj { { assert(arr.IsArray()); - arr.PushBack(pajlada::Settings::Serialize::get(value, a), a); + arr.PushBack(pajlada::Serialize::get(value, a), a); } template @@ -88,7 +86,7 @@ namespace rj { } bool error = false; - out = pajlada::Settings::Deserialize::get(obj[key], &error); + out = pajlada::Deserialize::get(obj[key], &error); return !error; } @@ -97,7 +95,7 @@ namespace rj { bool getSafe(const rapidjson::Value &value, Type &out) { bool error = false; - out = pajlada::Settings::Deserialize::get(value, &error); + out = pajlada::Deserialize::get(value, &error); return !error; } diff --git a/src/widgets/AccountSwitchWidget.cpp b/src/widgets/AccountSwitchWidget.cpp index 9b4a920fd..b7a5eefc9 100644 --- a/src/widgets/AccountSwitchWidget.cpp +++ b/src/widgets/AccountSwitchWidget.cpp @@ -50,8 +50,7 @@ AccountSwitchWidget::AccountSwitchWidget(QWidget *parent) } else { - app->accounts->twitch.currentUsername = - newUsername.toStdString(); + app->accounts->twitch.currentUsername = newUsername; } } }); diff --git a/src/widgets/BaseWindow.cpp b/src/widgets/BaseWindow.cpp index 440935ea3..ae578cfd2 100644 --- a/src/widgets/BaseWindow.cpp +++ b/src/widgets/BaseWindow.cpp @@ -56,9 +56,9 @@ BaseWindow::BaseWindow(QWidget *parent, Flags _flags) this->init(); - this->connections_.managedConnect( - getSettings()->uiScale.getValueChangedSignal(), - [this](auto, auto) { postToThread([this] { this->updateScale(); }); }); + getSettings()->uiScale.connect( + [this]() { postToThread([this] { this->updateScale(); }); }, + this->connections_); this->updateScale(); @@ -133,8 +133,8 @@ void BaseWindow::init() ? Qt::WindowActive : Qt::WindowMaximized); }); - QObject::connect(_exitButton, &TitleBarButton::leftClicked, this, - [this] { this->close(); }); + QObject::connect(_exitButton, &TitleBarButton::leftClicked, + this, [this] { this->close(); }); this->ui_.minButton = _minButton; this->ui_.maxButton = _maxButton; diff --git a/src/widgets/dialogs/LoginDialog.cpp b/src/widgets/dialogs/LoginDialog.cpp index d94a6a23c..a1bd065cc 100644 --- a/src/widgets/dialogs/LoginDialog.cpp +++ b/src/widgets/dialogs/LoginDialog.cpp @@ -5,6 +5,7 @@ #include "common/NetworkRequest.hpp" #include "controllers/accounts/AccountController.hpp" #include "providers/twitch/PartialTwitchUser.hpp" +#include "util/Helpers.hpp" #ifdef USEWINSDK # include @@ -21,26 +22,25 @@ namespace chatterino { namespace { - void LogInWithCredentials(const std::string &userID, - const std::string &username, - const std::string &clientID, - const std::string &oauthToken) + void LogInWithCredentials(const QString &userID, const QString &username, + const QString &clientID, + const QString &oauthToken) { QStringList errors; - if (userID.empty()) + if (userID.isEmpty()) { errors.append("Missing user ID"); } - if (username.empty()) + if (username.isEmpty()) { errors.append("Missing username"); } - if (clientID.empty()) + if (clientID.isEmpty()) { errors.append("Missing Client ID"); } - if (oauthToken.empty()) + if (oauthToken.isEmpty()) { errors.append("Missing OAuth Token"); } @@ -65,14 +65,14 @@ namespace { // messageBox.setIcon(QMessageBox::Information); // messageBox.setText("Successfully logged in with user " + // qS(username) + "!"); - pajlada::Settings::Setting::set( - "/accounts/uid" + userID + "/username", username); - pajlada::Settings::Setting::set( - "/accounts/uid" + userID + "/userID", userID); - pajlada::Settings::Setting::set( - "/accounts/uid" + userID + "/clientID", clientID); - pajlada::Settings::Setting::set( - "/accounts/uid" + userID + "/oauthToken", oauthToken); + auto basePath = fS("/accounts/uid{}", userID); + pajlada::Settings::Setting::set(basePath + "/username", + username); + pajlada::Settings::Setting::set(basePath + "/userID", userID); + pajlada::Settings::Setting::set(basePath + "/clientID", + clientID); + pajlada::Settings::Setting::set(basePath + "/oauthToken", + oauthToken); getApp()->accounts->twitch.reloadUsers(); @@ -105,7 +105,7 @@ BasicLoginWidget::BasicLoginWidget() QString clipboardString = clipboard->text(); QStringList parameters = clipboardString.split(';'); - std::string oauthToken, clientID, username, userID; + QString oauthToken, clientID, username, userID; for (const auto ¶m : parameters) { @@ -119,19 +119,19 @@ BasicLoginWidget::BasicLoginWidget() if (key == "oauth_token") { - oauthToken = value.toStdString(); + oauthToken = value; } else if (key == "client_id") { - clientID = value.toStdString(); + clientID = value; } else if (key == "username") { - username = value.toStdString(); + username = value; } else if (key == "user_id") { - userID = value.toStdString(); + userID = value; } else { @@ -198,16 +198,15 @@ AdvancedLoginWidget::AdvancedLoginWidget() this->ui_.oauthTokenInput.clear(); }); - connect( - &this->ui_.buttonUpperRow.addUserButton, &QPushButton::clicked, [=]() { - std::string userID = this->ui_.userIDInput.text().toStdString(); - std::string username = this->ui_.usernameInput.text().toStdString(); - std::string clientID = this->ui_.clientIDInput.text().toStdString(); - std::string oauthToken = - this->ui_.oauthTokenInput.text().toStdString(); + connect(&this->ui_.buttonUpperRow.addUserButton, &QPushButton::clicked, + [=]() { + QString userID = this->ui_.userIDInput.text(); + QString username = this->ui_.usernameInput.text(); + QString clientID = this->ui_.clientIDInput.text(); + QString oauthToken = this->ui_.oauthTokenInput.text(); - LogInWithCredentials(userID, username, clientID, oauthToken); - }); + LogInWithCredentials(userID, username, clientID, oauthToken); + }); /// Lower button row this->ui_.buttonLowerRow.fillInUserIDButton.setText( diff --git a/src/widgets/helper/NotebookTab.cpp b/src/widgets/helper/NotebookTab.cpp index 5b3d09551..f09f550c5 100644 --- a/src/widgets/helper/NotebookTab.cpp +++ b/src/widgets/helper/NotebookTab.cpp @@ -36,8 +36,8 @@ NotebookTab::NotebookTab(Notebook *notebook) this->positionChangedAnimation_.setEasingCurve( QEasingCurve(QEasingCurve::InCubic)); - getSettings()->showTabCloseButton.connect( - boost::bind(&NotebookTab::hideTabXChanged, this, _1), + getSettings()->showTabCloseButton.connectSimple( + boost::bind(&NotebookTab::hideTabXChanged, this), this->managedConnections_); getSettings()->showTabLive.connect([this](auto, auto) { this->update(); }, this->managedConnections_); @@ -230,7 +230,7 @@ QRect NotebookTab::getDesiredRect() const return QRect(this->positionAnimationDesiredPoint_, size()); } -void NotebookTab::hideTabXChanged(bool) +void NotebookTab::hideTabXChanged() { this->updateSize(); this->update(); diff --git a/src/widgets/helper/NotebookTab.hpp b/src/widgets/helper/NotebookTab.hpp index 3d8a5cacb..d0dab2b9f 100644 --- a/src/widgets/helper/NotebookTab.hpp +++ b/src/widgets/helper/NotebookTab.hpp @@ -49,7 +49,7 @@ public: void moveAnimated(QPoint pos, bool animated = true); QRect getDesiredRect() const; - void hideTabXChanged(bool); + void hideTabXChanged(); protected: virtual void themeChangedEvent() override; diff --git a/src/widgets/settingspages/GeneralPage.cpp b/src/widgets/settingspages/GeneralPage.cpp index f3205a05f..78ad6d804 100644 --- a/src/widgets/settingspages/GeneralPage.cpp +++ b/src/widgets/settingspages/GeneralPage.cpp @@ -148,10 +148,9 @@ void GeneralPage::initLayout(SettingsLayout &layout) layout.addTitle("Appearance"); layout.addDropdown("Theme", {"White", "Light", "Dark", "Black"}, getApp()->themes->themeName); - layout.addDropdown( + layout.addDropdown( "Font", {"Segoe UI", "Arial", "Choose..."}, - getApp()->fonts->chatFontFamily, - [](auto val) { return QString::fromStdString(val); }, + getApp()->fonts->chatFontFamily, [](auto val) { return val; }, [this](auto args) { return this->getFont(args); }); layout.addDropdown( "Font size", {"9pt", "10pt", "12pt", "14pt", "16pt", "20pt"}, @@ -220,7 +219,8 @@ void GeneralPage::initLayout(SettingsLayout &layout) layout.addCheckbox("Animate only when focused", s.animationsWhenFocused); layout.addDropdown("Emoji set", {"EmojiOne 2", "EmojiOne 3", "Twitter", "Facebook", - "Apple", "Google", "Messenger"}); + "Apple", "Google", "Messenger"}, + s.emojiSet); layout.addTitle("Badges"); layout.addCheckbox("Show authority badges (staff, admin, turbo, etc)", @@ -311,7 +311,7 @@ void GeneralPage::initExtra() } } -std::string GeneralPage::getFont(const DropdownArgs &args) const +QString GeneralPage::getFont(const DropdownArgs &args) const { if (args.combobox->currentIndex() == args.combobox->count() - 1) { @@ -325,11 +325,11 @@ std::string GeneralPage::getFont(const DropdownArgs &args) const auto font = dialog.getFont(&ok); if (ok) - return font.family().toStdString(); + return font.family(); else - return args.combobox->itemText(0).toStdString(); + return args.combobox->itemText(0); } - return args.value.toStdString(); + return args.value; } } // namespace chatterino diff --git a/src/widgets/settingspages/GeneralPage.hpp b/src/widgets/settingspages/GeneralPage.hpp index 4fd496997..51db64e40 100644 --- a/src/widgets/settingspages/GeneralPage.hpp +++ b/src/widgets/settingspages/GeneralPage.hpp @@ -156,7 +156,7 @@ private: void initLayout(SettingsLayout &layout); void initExtra(); - std::string getFont(const DropdownArgs &args) const; + QString getFont(const DropdownArgs &args) const; DescriptionLabel *cachePath{}; }; diff --git a/src/widgets/settingspages/LookPage.cpp b/src/widgets/settingspages/LookPage.cpp index 04080d476..f45fc69c5 100644 --- a/src/widgets/settingspages/LookPage.cpp +++ b/src/widgets/settingspages/LookPage.cpp @@ -532,17 +532,15 @@ QLayout *LookPage::createFontChanger() QLabel *label = new QLabel(); layout->addWidget(label); - auto updateFontFamilyLabel = [=](auto) { - label->setText( - "Font (" + - QString::fromStdString(app->fonts->chatFontFamily.getValue()) + - ", " + QString::number(app->fonts->chatFontSize) + "pt)"); + auto updateFontFamilyLabel = [=]() { + label->setText("Font (" + app->fonts->chatFontFamily.getValue() + ", " + + QString::number(app->fonts->chatFontSize) + "pt)"); }; - app->fonts->chatFontFamily.connectSimple(updateFontFamilyLabel, - this->managedConnections_); - app->fonts->chatFontSize.connectSimple(updateFontFamilyLabel, - this->managedConnections_); + app->fonts->chatFontFamily.connect(updateFontFamilyLabel, + this->managedConnections_); + app->fonts->chatFontSize.connect(updateFontFamilyLabel, + this->managedConnections_); // BUTTON QPushButton *button = new QPushButton("Select"); @@ -554,11 +552,11 @@ QLayout *LookPage::createFontChanger() dialog.setWindowFlag(Qt::WindowStaysOnTopHint); - dialog.connect( - &dialog, &QFontDialog::fontSelected, [=](const QFont &font) { - app->fonts->chatFontFamily = font.family().toStdString(); - app->fonts->chatFontSize = font.pointSize(); - }); + dialog.connect(&dialog, &QFontDialog::fontSelected, + [=](const QFont &font) { + app->fonts->chatFontFamily = font.family(); + app->fonts->chatFontSize = font.pointSize(); + }); dialog.show(); dialog.exec();