Remove BaseSettings & merge ConcurrentSettings (#4775)

This commit is contained in:
pajlada 2023-08-28 17:51:28 +02:00 committed by GitHub
parent 4c942a2a42
commit 7cb04bf58b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 235 additions and 281 deletions

View file

@ -6,6 +6,7 @@
- Dev: Fixed UTF16 encoding of `modes` file for the installer. (#4791) - Dev: Fixed UTF16 encoding of `modes` file for the installer. (#4791)
- Dev: Temporarily disable High DPI scaling on Qt6 builds on Windows. (#4767) - Dev: Temporarily disable High DPI scaling on Qt6 builds on Windows. (#4767)
- Dev: Tests now run on Ubuntu 22.04 instead of 20.04 to loosen C++ restrictions in tests. (#4774) - Dev: Tests now run on Ubuntu 22.04 instead of 20.04 to loosen C++ restrictions in tests. (#4774)
- Dev: Do a pretty major refactor of the Settings classes. List settings (e.g. highlights) are most heavily modified, and should have an extra eye kept on them. (#4775)
## 2.4.5 ## 2.4.5

View file

@ -1,128 +0,0 @@
#include "BaseSettings.hpp"
#include "util/Clamp.hpp"
#include <QDebug>
namespace chatterino {
std::vector<std::weak_ptr<pajlada::Settings::SettingData>> _settings;
AB_SETTINGS_CLASS *AB_SETTINGS_CLASS::instance = nullptr;
void _actuallyRegisterSetting(
std::weak_ptr<pajlada::Settings::SettingData> setting)
{
_settings.push_back(std::move(setting));
}
AB_SETTINGS_CLASS::AB_SETTINGS_CLASS(const QString &settingsDirectory)
{
AB_SETTINGS_CLASS::instance = this;
QString settingsPath = settingsDirectory + "/settings.json";
// 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;
}
void AB_SETTINGS_CLASS::saveSnapshot()
{
rapidjson::Document *d = new rapidjson::Document(rapidjson::kObjectType);
rapidjson::Document::AllocatorType &a = d->GetAllocator();
for (const auto &weakSetting : _settings)
{
auto setting = weakSetting.lock();
if (!setting)
{
continue;
}
rapidjson::Value key(setting->getPath().c_str(), a);
auto curVal = setting->unmarshalJSON();
if (curVal == nullptr)
{
continue;
}
rapidjson::Value val;
val.CopyFrom(*curVal, a);
d->AddMember(key.Move(), val.Move(), a);
}
// log("Snapshot state: {}", rj::stringify(*d));
this->snapshot_.reset(d);
}
void AB_SETTINGS_CLASS::restoreSnapshot()
{
if (!this->snapshot_)
{
return;
}
const auto &snapshot = *(this->snapshot_.get());
if (!snapshot.IsObject())
{
return;
}
for (const auto &weakSetting : _settings)
{
auto setting = weakSetting.lock();
if (!setting)
{
continue;
}
const char *path = setting->getPath().c_str();
if (!snapshot.HasMember(path))
{
continue;
}
setting->marshalJSON(snapshot[path]);
}
}
float AB_SETTINGS_CLASS::getClampedUiScale() const
{
return clamp<float>(this->uiScale.getValue(), 0.2f, 10);
}
void AB_SETTINGS_CLASS::setClampedUiScale(float value)
{
this->uiScale.setValue(clamp<float>(value, 0.2f, 10));
}
#ifndef AB_CUSTOM_SETTINGS
Settings *getSettings()
{
static_assert(std::is_same_v<AB_SETTINGS_CLASS, Settings>,
"`AB_SETTINGS_CLASS` must be the same as `Settings`");
assert(AB_SETTINGS_CLASS::instance != nullptr);
return AB_SETTINGS_CLASS::instance;
}
#endif
AB_SETTINGS_CLASS *getABSettings()
{
assert(AB_SETTINGS_CLASS::instance);
return AB_SETTINGS_CLASS::instance;
}
} // namespace chatterino

View file

@ -1,47 +0,0 @@
#pragma once
#include "common/ChatterinoSetting.hpp"
#include <pajlada/settings/settingdata.hpp>
#include <QString>
#include <rapidjson/document.h>
#include <memory>
#ifdef AB_CUSTOM_SETTINGS
# define AB_SETTINGS_CLASS ABSettings
#else
# define AB_SETTINGS_CLASS Settings
#endif
namespace chatterino {
class Settings;
void _actuallyRegisterSetting(
std::weak_ptr<pajlada::Settings::SettingData> setting);
class AB_SETTINGS_CLASS
{
public:
AB_SETTINGS_CLASS(const QString &settingsDirectory);
void saveSnapshot();
void restoreSnapshot();
static AB_SETTINGS_CLASS *instance;
FloatSetting uiScale = {"/appearance/uiScale2", 1};
BoolSetting windowTopMost = {"/appearance/windowAlwaysOnTop", false};
float getClampedUiScale() const;
void setClampedUiScale(float value);
private:
std::unique_ptr<rapidjson::Document> snapshot_;
};
Settings *getSettings();
AB_SETTINGS_CLASS *getABSettings();
} // namespace chatterino

View file

@ -9,8 +9,6 @@ option(CHATTERINO_DEBUG_NATIVE_MESSAGES "Debug native messages" OFF)
set(SOURCE_FILES set(SOURCE_FILES
Application.cpp Application.cpp
Application.hpp Application.hpp
BaseSettings.cpp
BaseSettings.hpp
BrowserExtension.cpp BrowserExtension.cpp
BrowserExtension.hpp BrowserExtension.hpp
RunGui.cpp RunGui.cpp

View file

@ -1,6 +1,6 @@
#include "common/ChatterinoSetting.hpp" #include "common/ChatterinoSetting.hpp"
#include "BaseSettings.hpp" #include "singletons/Settings.hpp"
namespace chatterino { namespace chatterino {

View file

@ -8,14 +8,14 @@ namespace chatterino {
FilterSet::FilterSet() FilterSet::FilterSet()
{ {
this->listener_ = this->listener_ =
getCSettings().filterRecords.delayedItemsChanged.connect([this] { getSettings()->filterRecords.delayedItemsChanged.connect([this] {
this->reloadFilters(); this->reloadFilters();
}); });
} }
FilterSet::FilterSet(const QList<QUuid> &filterIds) FilterSet::FilterSet(const QList<QUuid> &filterIds)
{ {
auto filters = getCSettings().filterRecords.readOnly(); auto filters = getSettings()->filterRecords.readOnly();
for (const auto &f : *filters) for (const auto &f : *filters)
{ {
if (filterIds.contains(f->getId())) if (filterIds.contains(f->getId()))
@ -23,7 +23,7 @@ FilterSet::FilterSet(const QList<QUuid> &filterIds)
} }
this->listener_ = this->listener_ =
getCSettings().filterRecords.delayedItemsChanged.connect([this] { getSettings()->filterRecords.delayedItemsChanged.connect([this] {
this->reloadFilters(); this->reloadFilters();
}); });
} }
@ -55,7 +55,7 @@ const QList<QUuid> FilterSet::filterIds() const
void FilterSet::reloadFilters() void FilterSet::reloadFilters()
{ {
auto filters = getCSettings().filterRecords.readOnly(); auto filters = getSettings()->filterRecords.readOnly();
for (const auto &key : this->filters_.keys()) for (const auto &key : this->filters_.keys())
{ {
bool found = false; bool found = false;

View file

@ -441,7 +441,7 @@ void HighlightController::initialize(Settings &settings, Paths & /*paths*/)
}); });
this->signalHolder_.managedConnect( this->signalHolder_.managedConnect(
getCSettings().highlightedBadges.delayedItemsChanged, getSettings()->highlightedBadges.delayedItemsChanged,
[this, &settings] { [this, &settings] {
qCDebug(chatterinoHighlights) qCDebug(chatterinoHighlights)
<< "Rebuild checks because highlight badges changed"; << "Rebuild checks because highlight badges changed";
@ -449,14 +449,14 @@ void HighlightController::initialize(Settings &settings, Paths & /*paths*/)
}); });
this->signalHolder_.managedConnect( this->signalHolder_.managedConnect(
getCSettings().highlightedUsers.delayedItemsChanged, [this, &settings] { getSettings()->highlightedUsers.delayedItemsChanged, [this, &settings] {
qCDebug(chatterinoHighlights) qCDebug(chatterinoHighlights)
<< "Rebuild checks because highlight users changed"; << "Rebuild checks because highlight users changed";
this->rebuildChecks(settings); this->rebuildChecks(settings);
}); });
this->signalHolder_.managedConnect( this->signalHolder_.managedConnect(
getCSettings().highlightedMessages.delayedItemsChanged, getSettings()->highlightedMessages.delayedItemsChanged,
[this, &settings] { [this, &settings] {
qCDebug(chatterinoHighlights) qCDebug(chatterinoHighlights)
<< "Rebuild checks because highlight messages changed"; << "Rebuild checks because highlight messages changed";

View file

@ -14,7 +14,7 @@ bool isIgnoredMessage(IgnoredMessageParameters &&params)
if (!params.message.isEmpty()) if (!params.message.isEmpty())
{ {
// TODO(pajlada): Do we need to check if the phrase is valid first? // TODO(pajlada): Do we need to check if the phrase is valid first?
auto phrases = getCSettings().ignoredMessages.readOnly(); auto phrases = getSettings()->ignoredMessages.readOnly();
for (const auto &phrase : *phrases) for (const auto &phrase : *phrases)
{ {
if (phrase.isBlock() && phrase.isMatch(params.message)) if (phrase.isBlock() && phrase.isMatch(params.message))

View file

@ -806,7 +806,7 @@ void TwitchModerationElement::addToContainer(MessageLayoutContainer &container,
{ {
QSize size(int(container.getScale() * 16), QSize size(int(container.getScale() * 16),
int(container.getScale() * 16)); int(container.getScale() * 16));
auto actions = getCSettings().moderationActions.readOnly(); auto actions = getSettings()->moderationActions.readOnly();
for (const auto &action : *actions) for (const auto &action : *actions)
{ {
if (auto image = action.getImage()) if (auto image = action.getImage())

View file

@ -147,7 +147,7 @@ void SharedMessageBuilder::parseUsername()
void SharedMessageBuilder::parseHighlights() void SharedMessageBuilder::parseHighlights()
{ {
if (getCSettings().isBlacklistedUser(this->ircMessage->nick())) if (getSettings()->isBlacklistedUser(this->ircMessage->nick()))
{ {
// Do nothing. We ignore highlights from this user. // Do nothing. We ignore highlights from this user.
return; return;
@ -206,7 +206,7 @@ void SharedMessageBuilder::triggerHighlights()
return; return;
} }
if (getCSettings().isMutedChannel(this->channel->getName())) if (getSettings()->isMutedChannel(this->channel->getName()))
{ {
// Do nothing. Pings are muted in this channel. // Do nothing. Pings are muted in this channel.
return; return;
@ -270,7 +270,7 @@ QString SharedMessageBuilder::stylizeUsername(const QString &username,
break; break;
} }
if (auto nicknameText = getCSettings().matchNickname(usernameText)) if (auto nicknameText = getSettings()->matchNickname(usernameText))
{ {
usernameText = *nicknameText; usernameText = *nicknameText;
} }

View file

@ -834,7 +834,7 @@ void TwitchMessageBuilder::appendUsername()
void TwitchMessageBuilder::runIgnoreReplaces( void TwitchMessageBuilder::runIgnoreReplaces(
std::vector<TwitchEmoteOccurrence> &twitchEmotes) std::vector<TwitchEmoteOccurrence> &twitchEmotes)
{ {
auto phrases = getCSettings().ignoredMessages.readOnly(); auto phrases = getSettings()->ignoredMessages.readOnly();
auto removeEmotesInRange = [](int pos, int len, auto removeEmotesInRange = [](int pos, int len,
auto &twitchEmotes) mutable { auto &twitchEmotes) mutable {
auto it = std::partition( auto it = std::partition(

View file

@ -8,40 +8,46 @@
#include "controllers/ignores/IgnorePhrase.hpp" #include "controllers/ignores/IgnorePhrase.hpp"
#include "controllers/moderationactions/ModerationAction.hpp" #include "controllers/moderationactions/ModerationAction.hpp"
#include "controllers/nicknames/Nickname.hpp" #include "controllers/nicknames/Nickname.hpp"
#include "util/Clamp.hpp"
#include "util/PersistSignalVector.hpp" #include "util/PersistSignalVector.hpp"
#include "util/WindowsHelper.hpp" #include "util/WindowsHelper.hpp"
namespace chatterino { #include <pajlada/signals/scoped-connection.hpp>
ConcurrentSettings *concurrentInstance_{}; namespace {
ConcurrentSettings::ConcurrentSettings() using namespace chatterino;
// NOTE: these do not get deleted
: highlightedMessages(*new SignalVector<HighlightPhrase>()) template <typename T>
, highlightedUsers(*new SignalVector<HighlightPhrase>()) void initializeSignalVector(pajlada::Signals::SignalHolder &signalHolder,
, highlightedBadges(*new SignalVector<HighlightBadge>()) ChatterinoSetting<std::vector<T>> &setting,
, blacklistedUsers(*new SignalVector<HighlightBlacklistUser>()) SignalVector<T> &vec)
, ignoredMessages(*new SignalVector<IgnorePhrase>())
, mutedChannels(*new SignalVector<QString>())
, filterRecords(*new SignalVector<FilterRecordPtr>())
, nicknames(*new SignalVector<Nickname>())
, moderationActions(*new SignalVector<ModerationAction>)
, loggedChannels(*new SignalVector<ChannelLog>)
{ {
persist(this->highlightedMessages, "/highlighting/highlights"); // Fill the SignalVector up with initial values
persist(this->blacklistedUsers, "/highlighting/blacklist"); for (auto &&item : setting.getValue())
persist(this->highlightedBadges, "/highlighting/badges"); {
persist(this->highlightedUsers, "/highlighting/users"); vec.append(item);
persist(this->ignoredMessages, "/ignore/phrases"); }
persist(this->mutedChannels, "/pings/muted");
persist(this->filterRecords, "/filtering/filters"); // Set up a signal to
persist(this->nicknames, "/nicknames"); signalHolder.managedConnect(vec.delayedItemsChanged, [&] {
// tagged users? setting.setValue(vec.raw());
persist(this->moderationActions, "/moderation/actions"); });
persist(this->loggedChannels, "/logging/channels");
} }
bool ConcurrentSettings::isHighlightedUser(const QString &username) } // namespace
namespace chatterino {
std::vector<std::weak_ptr<pajlada::Settings::SettingData>> _settings;
void _actuallyRegisterSetting(
std::weak_ptr<pajlada::Settings::SettingData> setting)
{
_settings.push_back(std::move(setting));
}
bool Settings::isHighlightedUser(const QString &username)
{ {
auto items = this->highlightedUsers.readOnly(); auto items = this->highlightedUsers.readOnly();
@ -54,7 +60,7 @@ bool ConcurrentSettings::isHighlightedUser(const QString &username)
return false; return false;
} }
bool ConcurrentSettings::isBlacklistedUser(const QString &username) bool Settings::isBlacklistedUser(const QString &username)
{ {
auto items = this->blacklistedUsers.readOnly(); auto items = this->blacklistedUsers.readOnly();
@ -67,7 +73,7 @@ bool ConcurrentSettings::isBlacklistedUser(const QString &username)
return false; return false;
} }
bool ConcurrentSettings::isMutedChannel(const QString &channelName) bool Settings::isMutedChannel(const QString &channelName)
{ {
auto items = this->mutedChannels.readOnly(); auto items = this->mutedChannels.readOnly();
@ -81,10 +87,9 @@ bool ConcurrentSettings::isMutedChannel(const QString &channelName)
return false; return false;
} }
boost::optional<QString> ConcurrentSettings::matchNickname( boost::optional<QString> Settings::matchNickname(const QString &usernameText)
const QString &usernameText)
{ {
auto nicknames = getCSettings().nicknames.readOnly(); auto nicknames = this->nicknames.readOnly();
for (const auto &nickname : *nicknames) for (const auto &nickname : *nicknames)
{ {
@ -97,12 +102,12 @@ boost::optional<QString> ConcurrentSettings::matchNickname(
return boost::none; return boost::none;
} }
void ConcurrentSettings::mute(const QString &channelName) void Settings::mute(const QString &channelName)
{ {
mutedChannels.append(channelName); mutedChannels.append(channelName);
} }
void ConcurrentSettings::unmute(const QString &channelName) void Settings::unmute(const QString &channelName)
{ {
for (std::vector<int>::size_type i = 0; i != mutedChannels.raw().size(); for (std::vector<int>::size_type i = 0; i != mutedChannels.raw().size();
i++) i++)
@ -115,7 +120,7 @@ void ConcurrentSettings::unmute(const QString &channelName)
} }
} }
bool ConcurrentSettings::toggleMutedChannel(const QString &channelName) bool Settings::toggleMutedChannel(const QString &channelName)
{ {
if (this->isMutedChannel(channelName)) if (this->isMutedChannel(channelName))
{ {
@ -129,21 +134,44 @@ bool ConcurrentSettings::toggleMutedChannel(const QString &channelName)
} }
} }
ConcurrentSettings &getCSettings()
{
// `concurrentInstance_` gets assigned in Settings ctor.
assert(concurrentInstance_);
return *concurrentInstance_;
}
Settings *Settings::instance_ = nullptr; Settings *Settings::instance_ = nullptr;
Settings::Settings(const QString &settingsDirectory) Settings::Settings(const QString &settingsDirectory)
: ABSettings(settingsDirectory)
{ {
QString settingsPath = settingsDirectory + "/settings.json";
// 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;
initializeSignalVector(this->signalHolder, this->highlightedMessagesSetting,
this->highlightedMessages);
initializeSignalVector(this->signalHolder, this->highlightedUsersSetting,
this->highlightedUsers);
initializeSignalVector(this->signalHolder, this->highlightedBadgesSetting,
this->highlightedBadges);
initializeSignalVector(this->signalHolder, this->blacklistedUsersSetting,
this->blacklistedUsers);
initializeSignalVector(this->signalHolder, this->ignoredMessagesSetting,
this->ignoredMessages);
initializeSignalVector(this->signalHolder, this->mutedChannelsSetting,
this->mutedChannels);
initializeSignalVector(this->signalHolder, this->filterRecordsSetting,
this->filterRecords);
initializeSignalVector(this->signalHolder, this->nicknamesSetting,
this->nicknames);
initializeSignalVector(this->signalHolder, this->moderationActionsSetting,
this->moderationActions);
initializeSignalVector(this->signalHolder, this->loggedChannelsSetting,
this->loggedChannels);
instance_ = this; instance_ = this;
concurrentInstance_ = this;
#ifdef USEWINSDK #ifdef USEWINSDK
this->autorun = isRegisteredForStartup(); this->autorun = isRegisteredForStartup();
@ -160,6 +188,81 @@ Settings::Settings(const QString &settingsDirectory)
false); false);
} }
Settings::~Settings() = default;
void Settings::saveSnapshot()
{
rapidjson::Document *d = new rapidjson::Document(rapidjson::kObjectType);
rapidjson::Document::AllocatorType &a = d->GetAllocator();
for (const auto &weakSetting : _settings)
{
auto setting = weakSetting.lock();
if (!setting)
{
continue;
}
rapidjson::Value key(setting->getPath().c_str(), a);
auto curVal = setting->unmarshalJSON();
if (curVal == nullptr)
{
continue;
}
rapidjson::Value val;
val.CopyFrom(*curVal, a);
d->AddMember(key.Move(), val.Move(), a);
}
// log("Snapshot state: {}", rj::stringify(*d));
this->snapshot_.reset(d);
}
void Settings::restoreSnapshot()
{
if (!this->snapshot_)
{
return;
}
const auto &snapshot = *(this->snapshot_.get());
if (!snapshot.IsObject())
{
return;
}
for (const auto &weakSetting : _settings)
{
auto setting = weakSetting.lock();
if (!setting)
{
continue;
}
const char *path = setting->getPath().c_str();
if (!snapshot.HasMember(path))
{
continue;
}
setting->marshalJSON(snapshot[path]);
}
}
float Settings::getClampedUiScale() const
{
return clamp<float>(this->uiScale.getValue(), 0.2f, 10);
}
void Settings::setClampedUiScale(float value)
{
this->uiScale.setValue(clamp<float>(value, 0.2f, 10));
}
Settings &Settings::instance() Settings &Settings::instance()
{ {
assert(instance_ != nullptr); assert(instance_ != nullptr);

View file

@ -1,10 +1,17 @@
#pragma once #pragma once
#include "BaseSettings.hpp"
#include "common/Channel.hpp" #include "common/Channel.hpp"
#include "common/ChatterinoSetting.hpp"
#include "common/enums/MessageOverflow.hpp" #include "common/enums/MessageOverflow.hpp"
#include "common/SignalVector.hpp" #include "common/SignalVector.hpp"
#include "controllers/filters/FilterRecord.hpp"
#include "controllers/highlights/HighlightBadge.hpp"
#include "controllers/highlights/HighlightBlacklistUser.hpp"
#include "controllers/highlights/HighlightPhrase.hpp"
#include "controllers/ignores/IgnorePhrase.hpp"
#include "controllers/logging/ChannelLog.hpp" #include "controllers/logging/ChannelLog.hpp"
#include "controllers/moderationactions/ModerationAction.hpp"
#include "controllers/nicknames/Nickname.hpp"
#include "singletons/Toasts.hpp" #include "singletons/Toasts.hpp"
#include "util/RapidJsonSerializeQString.hpp" #include "util/RapidJsonSerializeQString.hpp"
#include "util/StreamerMode.hpp" #include "util/StreamerMode.hpp"
@ -12,49 +19,14 @@
#include <pajlada/settings/setting.hpp> #include <pajlada/settings/setting.hpp>
#include <pajlada/settings/settinglistener.hpp> #include <pajlada/settings/settinglistener.hpp>
#include <pajlada/signals/signalholder.hpp>
using TimeoutButton = std::pair<QString, int>; using TimeoutButton = std::pair<QString, int>;
namespace chatterino { namespace chatterino {
class HighlightPhrase; void _actuallyRegisterSetting(
class HighlightBlacklistUser; std::weak_ptr<pajlada::Settings::SettingData> setting);
class IgnorePhrase;
class FilterRecord;
using FilterRecordPtr = std::shared_ptr<FilterRecord>;
class Nickname;
class HighlightBadge;
class ModerationAction;
/// Settings which are available for reading on all threads.
class ConcurrentSettings
{
public:
ConcurrentSettings();
SignalVector<HighlightPhrase> &highlightedMessages;
SignalVector<HighlightPhrase> &highlightedUsers;
SignalVector<HighlightBadge> &highlightedBadges;
SignalVector<HighlightBlacklistUser> &blacklistedUsers;
SignalVector<IgnorePhrase> &ignoredMessages;
SignalVector<QString> &mutedChannels;
SignalVector<FilterRecordPtr> &filterRecords;
SignalVector<Nickname> &nicknames;
SignalVector<ModerationAction> &moderationActions;
SignalVector<ChannelLog> &loggedChannels;
bool isHighlightedUser(const QString &username);
bool isBlacklistedUser(const QString &username);
bool isMutedChannel(const QString &channelName);
bool toggleMutedChannel(const QString &channelName);
boost::optional<QString> matchNickname(const QString &username);
private:
void mute(const QString &channelName);
void unmute(const QString &channelName);
};
ConcurrentSettings &getCSettings();
enum UsernameDisplayMode : int { enum UsernameDisplayMode : int {
Username = 1, // Username Username = 1, // Username
@ -91,15 +63,25 @@ enum UsernameRightClickBehavior : int {
/// Settings which are availlable for reading and writing on the gui thread. /// Settings which are availlable for reading and writing on the gui thread.
// These settings are still accessed concurrently in the code but it is bad practice. // These settings are still accessed concurrently in the code but it is bad practice.
class Settings : public ABSettings, public ConcurrentSettings class Settings
{ {
static Settings *instance_; static Settings *instance_;
public: public:
Settings(const QString &settingsDirectory); Settings(const QString &settingsDirectory);
~Settings();
static Settings &instance(); static Settings &instance();
void saveSnapshot();
void restoreSnapshot();
FloatSetting uiScale = {"/appearance/uiScale2", 1};
BoolSetting windowTopMost = {"/appearance/windowAlwaysOnTop", false};
float getClampedUiScale() const;
void setClampedUiScale(float value);
/// Appearance /// Appearance
BoolSetting showTimestamps = {"/appearance/messages/showTimestamps", true}; BoolSetting showTimestamps = {"/appearance/messages/showTimestamps", true};
BoolSetting animationsWhenFocused = { BoolSetting animationsWhenFocused = {
@ -575,7 +557,55 @@ public:
"/plugins/enabledPlugins", {}}; "/plugins/enabledPlugins", {}};
private: private:
ChatterinoSetting<std::vector<HighlightPhrase>> highlightedMessagesSetting =
{"/highlighting/highlights"};
ChatterinoSetting<std::vector<HighlightPhrase>> highlightedUsersSetting = {
"/highlighting/users"};
ChatterinoSetting<std::vector<HighlightBadge>> highlightedBadgesSetting = {
"/highlighting/badges"};
ChatterinoSetting<std::vector<HighlightBlacklistUser>>
blacklistedUsersSetting = {"/highlighting/blacklist"};
ChatterinoSetting<std::vector<IgnorePhrase>> ignoredMessagesSetting = {
"/ignore/phrases"};
ChatterinoSetting<std::vector<QString>> mutedChannelsSetting = {
"/pings/muted"};
ChatterinoSetting<std::vector<FilterRecordPtr>> filterRecordsSetting = {
"/filtering/filters"};
ChatterinoSetting<std::vector<Nickname>> nicknamesSetting = {"/nicknames"};
ChatterinoSetting<std::vector<ModerationAction>> moderationActionsSetting =
{"/moderation/actions"};
ChatterinoSetting<std::vector<ChannelLog>> loggedChannelsSetting = {
"/logging/channels"};
public:
SignalVector<HighlightPhrase> highlightedMessages;
SignalVector<HighlightPhrase> highlightedUsers;
SignalVector<HighlightBadge> highlightedBadges;
SignalVector<HighlightBlacklistUser> blacklistedUsers;
SignalVector<IgnorePhrase> ignoredMessages;
SignalVector<QString> mutedChannels;
SignalVector<FilterRecordPtr> filterRecords;
SignalVector<Nickname> nicknames;
SignalVector<ModerationAction> moderationActions;
SignalVector<ChannelLog> loggedChannels;
bool isHighlightedUser(const QString &username);
bool isBlacklistedUser(const QString &username);
bool isMutedChannel(const QString &channelName);
bool toggleMutedChannel(const QString &channelName);
boost::optional<QString> matchNickname(const QString &username);
private:
void mute(const QString &channelName);
void unmute(const QString &channelName);
void updateModerationActions(); void updateModerationActions();
std::unique_ptr<rapidjson::Document> snapshot_;
pajlada::Signals::SignalHolder signalHolder;
}; };
Settings *getSettings();
} // namespace chatterino } // namespace chatterino

View file

@ -1,6 +1,5 @@
#include "widgets/BaseWidget.hpp" #include "widgets/BaseWidget.hpp"
#include "BaseSettings.hpp"
#include "common/QLogging.hpp" #include "common/QLogging.hpp"
#include "controllers/hotkeys/HotkeyController.hpp" #include "controllers/hotkeys/HotkeyController.hpp"
#include "singletons/Theme.hpp" #include "singletons/Theme.hpp"

View file

@ -710,7 +710,7 @@ void BaseWindow::updateScale()
auto scale = auto scale =
this->nativeScale_ * (this->flags_.has(DisableCustomScaling) this->nativeScale_ * (this->flags_.has(DisableCustomScaling)
? 1 ? 1
: getABSettings()->getClampedUiScale()); : getSettings()->getClampedUiScale());
this->setScale(scale); this->setScale(scale);

View file

@ -49,7 +49,7 @@ SelectChannelFiltersDialog::SelectChannelFiltersDialog(
(this->windowFlags() & ~(Qt::WindowContextHelpButtonHint)) | (this->windowFlags() & ~(Qt::WindowContextHelpButtonHint)) |
Qt::Dialog | Qt::MSWindowsFixedSizeDialogHint); Qt::Dialog | Qt::MSWindowsFixedSizeDialogHint);
auto availableFilters = getCSettings().filterRecords.readOnly(); auto availableFilters = getSettings()->filterRecords.readOnly();
if (availableFilters->size() == 0) if (availableFilters->size() == 0)
{ {

View file

@ -1,6 +1,5 @@
#include "controllers/highlights/HighlightController.hpp" #include "controllers/highlights/HighlightController.hpp"
#include "BaseSettings.hpp"
#include "controllers/accounts/AccountController.hpp" #include "controllers/accounts/AccountController.hpp"
#include "controllers/highlights/HighlightPhrase.hpp" #include "controllers/highlights/HighlightPhrase.hpp"
#include "messages/MessageBuilder.hpp" // for MessageParseArgs #include "messages/MessageBuilder.hpp" // for MessageParseArgs

View file

@ -1,5 +1,4 @@
#include "Application.hpp" #include "Application.hpp"
#include "BaseSettings.hpp"
#include "common/Aliases.hpp" #include "common/Aliases.hpp"
#include "common/CompletionModel.hpp" #include "common/CompletionModel.hpp"
#include "controllers/accounts/AccountController.hpp" #include "controllers/accounts/AccountController.hpp"