Move highlight phrases to new settings system

Add a setting serialize/deserializer for QString
Add constructor to ChatterinoSetting that doesn't take a default value
This commit is contained in:
Rasmus Karlsson 2018-01-04 01:52:37 +01:00
parent dc9f1b96eb
commit df733282be
9 changed files with 252 additions and 130 deletions

View file

@ -195,7 +195,9 @@ HEADERS += \
src/singletons/helper/chatterinosetting.hpp \
src/singletons/resourcemanager.hpp \
src/util/emotemap.hpp \
src/singletons/helper/ircmessagehandler.hpp
src/singletons/helper/ircmessagehandler.hpp \
src/util/serialize-custom.hpp \
src/messages/highlightphrase.hpp
PRECOMPILED_HEADER =

View file

@ -34,8 +34,6 @@ Application::Application()
Application::~Application()
{
this->save();
chatterino::singletons::SettingManager::getInstance().save();
}
int Application::run(QApplication &qtApp)

View file

@ -0,0 +1,78 @@
#pragma once
#include "util/serialize-custom.hpp"
#include <QString>
#include <pajlada/settings/serialize.hpp>
namespace chatterino {
namespace messages {
struct HighlightPhrase {
QString key;
bool sound;
bool alert;
bool operator==(const HighlightPhrase &rhs) const
{
return std::tie(this->key, this->sound, this->alert) ==
std::tie(rhs.key, rhs.sound, rhs.alert);
}
};
} // namespace messages
} // namespace chatterino
namespace pajlada {
namespace Settings {
template <>
struct Serialize<chatterino::messages::HighlightPhrase> {
static rapidjson::Value get(const chatterino::messages::HighlightPhrase &value,
rapidjson::Document::AllocatorType &a)
{
rapidjson::Value ret(rapidjson::kObjectType);
AddMember(ret, "key", value.key, a);
AddMember(ret, "alert", value.alert, a);
AddMember(ret, "sound", value.sound, a);
return ret;
}
};
template <>
struct Deserialize<chatterino::messages::HighlightPhrase> {
static chatterino::messages::HighlightPhrase get(const rapidjson::Value &value)
{
chatterino::messages::HighlightPhrase ret;
if (!value.IsObject()) {
return ret;
}
if (value.HasMember("key")) {
const rapidjson::Value &key = value["key"];
if (key.IsString()) {
ret.key = key.GetString();
}
}
if (value.HasMember("alert")) {
const rapidjson::Value &alert = value["alert"];
if (alert.IsBool()) {
ret.alert = alert.GetBool();
}
}
if (value.HasMember("sound")) {
const rapidjson::Value &sound = value["sound"];
if (sound.IsBool()) {
ret.sound = sound.GetBool();
}
}
return ret;
}
};
} // namespace Settings
} // namespace pajlada

View file

@ -8,6 +8,12 @@ template <typename Type>
class ChatterinoSetting : public pajlada::Settings::Setting<Type>
{
public:
ChatterinoSetting(const std::string &_path)
: pajlada::Settings::Setting<Type>(_path)
{
_registerSetting(this->data);
}
ChatterinoSetting(const std::string &_path, const Type &_defaultValue)
: pajlada::Settings::Setting<Type>(_path, _defaultValue)
{

View file

@ -22,8 +22,6 @@ SettingManager::SettingManager()
, preferredQuality("/behaviour/streamlink/quality", "Choose")
, emoteScale(this->settingsItems, "emoteScale", 1.0)
, pathHighlightSound(this->settingsItems, "pathHighlightSound", "qrc:/sounds/ping2.wav")
, highlightProperties(this->settingsItems, "highlightProperties",
QMap<QString, QPair<bool, bool>>())
, highlightUserBlacklist(this->settingsItems, "highlightUserBlacklist", "")
, snapshot(nullptr)
, settings(Path::getAppdataPath() + "settings.ini", QSettings::IniFormat)
@ -40,49 +38,6 @@ SettingManager::SettingManager()
};
}
void SettingManager::save()
{
for (auto &item : this->settingsItems) {
if (item.get().getName() != "highlightProperties") {
this->settings.setValue(item.get().getName(), item.get().getVariant());
} else {
this->settings.beginGroup("Highlights");
QStringList list = highlightProperties.get().keys();
list.removeAll("");
this->settings.remove("");
for (auto string : list) {
this->settings.beginGroup(string);
this->settings.setValue("highlightSound",
highlightProperties.get().value(string).first);
this->settings.setValue("highlightTask",
highlightProperties.get().value(string).second);
this->settings.endGroup();
}
this->settings.endGroup();
}
}
}
void SettingManager::load()
{
for (auto &item : this->settingsItems) {
if (item.get().getName() != "highlightProperties") {
item.get().setVariant(this->settings.value(item.get().getName()));
} else {
this->settings.beginGroup("Highlights");
QStringList list = this->settings.childGroups();
for (auto string : list) {
this->settings.beginGroup(string);
highlightProperties.insertMap(string,
this->settings.value("highlightSound").toBool(),
this->settings.value("highlightTask").toBool());
this->settings.endGroup();
}
this->settings.endGroup();
}
}
}
Word::Flags SettingManager::getWordTypeMask()
{
return this->wordTypeMask;
@ -98,6 +53,12 @@ QSettings &SettingManager::getQSettings()
return this->settings;
}
void SettingManager::load()
{
// Just to make sure the singleton is initialized
debug::Log(".");
}
void SettingManager::updateWordTypeMask()
{
uint32_t newMaskUint = Word::Text;
@ -184,5 +145,5 @@ void SettingManager::recallSnapshot()
}
}
} // namespace singletons
} // namespace chatterino
}

View file

@ -1,5 +1,6 @@
#pragma once
#include "messages/highlightphrase.hpp"
#include "messages/word.hpp"
#include "setting.hpp"
#include "singletons/helper/chatterinosetting.hpp"
@ -21,13 +22,12 @@ class SettingManager : public QObject
using FloatSetting = ChatterinoSetting<float>;
public:
void load();
void save();
messages::Word::Flags getWordTypeMask();
bool isIgnoredEmote(const QString &emote);
QSettings &getQSettings();
void load();
/// Appearance
BoolSetting showTimestamps = {"/appearance/messages/showTimestamps", true};
BoolSetting showTimestampSeconds = {"/appearance/messages/showTimestampSeconds", true};
@ -73,9 +73,10 @@ public:
pajlada::Settings::Setting<std::string> preferredQuality;
Setting<float> emoteScale;
ChatterinoSetting<std::vector<messages::HighlightPhrase>> highlightProperties = {
"/highlighting/highlights"};
Setting<QString> pathHighlightSound;
Setting<QMap<QString, QPair<bool, bool>>> highlightProperties;
Setting<QString> highlightUserBlacklist;
BoolSetting highlightAlwaysPlaySound = {"/highlighting/alwaysPlaySound", false};
@ -107,5 +108,5 @@ private:
pajlada::Settings::SettingListener wordMaskListener;
};
} // namespace singletons
} // namespace chatterino
}

View file

@ -407,35 +407,18 @@ void TwitchMessageBuilder::parseHighlights()
currentPlayerUrl = highlightSoundUrl;
}
struct Highlight {
Highlight(const QString &_target, bool _sound, bool _alert)
: target(_target)
, sound(_sound)
, alert(_alert)
{
}
QString target;
bool sound;
bool alert;
};
QStringList blackList =
settings.highlightUserBlacklist.get().split("\n", QString::SkipEmptyParts);
// TODO: This vector should only be rebuilt upon highlights being changed
std::vector<Highlight> activeHighlights;
auto activeHighlights = settings.highlightProperties.getValue();
if (settings.enableHighlightsSelf && currentUsername.size() > 0) {
activeHighlights.emplace_back(currentUsername, settings.enableHighlightSound,
settings.enableHighlightTaskbar);
}
const auto &highlightProperties = settings.highlightProperties.get();
for (auto it = highlightProperties.begin(); it != highlightProperties.end(); ++it) {
auto properties = it.value();
activeHighlights.emplace_back(it.key(), properties.first, properties.second);
messages::HighlightPhrase selfHighlight;
selfHighlight.key = currentUsername;
selfHighlight.sound = settings.enableHighlightSound;
selfHighlight.alert = settings.enableHighlightTaskbar;
activeHighlights.emplace_back(std::move(selfHighlight));
}
bool doHighlight = false;
@ -445,10 +428,10 @@ void TwitchMessageBuilder::parseHighlights()
bool hasFocus = (QApplication::focusWidget() != nullptr);
if (!blackList.contains(this->ircMessage->nick(), Qt::CaseInsensitive)) {
for (const Highlight &highlight : activeHighlights) {
if (this->originalMessage.contains(highlight.target, Qt::CaseInsensitive)) {
for (const messages::HighlightPhrase &highlight : activeHighlights) {
if (this->originalMessage.contains(highlight.key, Qt::CaseInsensitive)) {
debug::Log("Highlight because {} contains {}", this->originalMessage,
highlight.target);
highlight.key);
doHighlight = true;
if (highlight.sound) {

View file

@ -0,0 +1,32 @@
#pragma once
#include <QString>
#include <pajlada/settings/serialize.hpp>
namespace pajlada {
namespace Settings {
template <>
struct Serialize<QString> {
static rapidjson::Value get(const QString &value, rapidjson::Document::AllocatorType &a)
{
rapidjson::Value ret(qPrintable(value), a);
return ret;
}
};
template <>
struct Deserialize<QString> {
static QString get(const rapidjson::Value &value)
{
if (!value.IsString()) {
throw std::runtime_error("Deserialized rapidjson::Value is not a string");
}
return value.GetString();
}
};
} // namespace Settings
} // namespace pajlada

View file

@ -418,8 +418,10 @@ QVBoxLayout *SettingsDialog::createHighlightingTab()
auto highlights = new QListWidget();
auto highlightUserBlacklist = new QTextEdit();
globalHighlights = highlights;
QStringList items = settings.highlightProperties.get().keys();
highlights->addItems(items);
const auto highlightProperties = settings.highlightProperties.getValue();
for (const auto &highlightProperty : highlightProperties) {
highlights->addItem(highlightProperty.key);
}
highlightUserBlacklist->setText(settings.highlightUserBlacklist.getnonConst());
auto highlightTab = new QTabWidget();
auto customSound = new QHBoxLayout();
@ -450,6 +452,7 @@ QVBoxLayout *SettingsDialog::createHighlightingTab()
auto editBtn = new QPushButton("Edit");
auto delBtn = new QPushButton("Remove");
// Open "Add new highlight" dialog
QObject::connect(addBtn, &QPushButton::clicked, this, [highlights, this, &settings] {
auto show = new QWidget();
auto box = new QBoxLayout(QBoxLayout::TopToBottom);
@ -460,11 +463,23 @@ QVBoxLayout *SettingsDialog::createHighlightingTab()
auto sound = new QCheckBox("Play sound");
auto task = new QCheckBox("Flash taskbar");
// Save highlight
QObject::connect(add, &QPushButton::clicked, this, [=, &settings] {
if (edit->text().length()) {
highlights->addItem(edit->text());
settings.highlightProperties.insertMap(edit->text(), sound->isChecked(),
task->isChecked());
QString highlightKey = edit->text();
highlights->addItem(highlightKey);
auto properties = settings.highlightProperties.getValue();
messages::HighlightPhrase newHighlightProperty;
newHighlightProperty.key = highlightKey;
newHighlightProperty.sound = sound->isChecked();
newHighlightProperty.alert = task->isChecked();
properties.push_back(newHighlightProperty);
settings.highlightProperties = properties;
show->close();
}
});
@ -475,50 +490,103 @@ QVBoxLayout *SettingsDialog::createHighlightingTab()
show->setLayout(box);
show->show();
});
// Open "Edit selected highlight" dialog
QObject::connect(editBtn, &QPushButton::clicked, this, [highlights, this, &settings] {
if (!highlights->selectedItems().isEmpty()) {
if (highlights->selectedItems().isEmpty()) {
// No item selected
return;
}
QListWidgetItem *selectedHighlight = highlights->selectedItems().first();
QString highlightKey = selectedHighlight->text();
auto properties = settings.highlightProperties.getValue();
auto highlightIt = std::find_if(properties.begin(), properties.end(),
[highlightKey](const auto &highlight) {
return highlight.key == highlightKey; //
});
if (highlightIt == properties.end()) {
debug::Log("Unable to find highlight key {} in highlight properties. "
"This is weird",
highlightKey);
return;
}
messages::HighlightPhrase &selectedSetting = *highlightIt;
auto show = new QWidget();
auto box = new QBoxLayout(QBoxLayout::TopToBottom);
auto edit = new QLineEdit();
edit->setText(highlights->selectedItems().first()->text());
auto add = new QPushButton("Apply");
auto edit = new QLineEdit(highlightKey);
auto apply = new QPushButton("Apply");
auto sound = new QCheckBox("Play sound");
sound->setChecked(selectedSetting.sound);
auto task = new QCheckBox("Flash taskbar");
task->setChecked(selectedSetting.alert);
QObject::connect(add, &QPushButton::clicked, this, [=, &settings] {
if (edit->text().length()) {
settings.highlightProperties.getnonConst().remove(
highlights->selectedItems().first()->text());
delete highlights->selectedItems().first();
highlights->addItem(edit->text());
settings.highlightProperties.insertMap(edit->text(), sound->isChecked(),
task->isChecked());
show->close();
// Apply edited changes
QObject::connect(apply, &QPushButton::clicked, this, [=, &settings] {
QString newHighlightKey = edit->text();
if (newHighlightKey.length() == 0) {
return;
}
auto properties = settings.highlightProperties.getValue();
auto highlightIt =
std::find_if(properties.begin(), properties.end(), [=](const auto &highlight) {
return highlight.key == highlightKey; //
});
if (highlightIt == properties.end()) {
debug::Log("Unable to find highlight key {} in highlight properties. "
"This is weird",
highlightKey);
return;
}
auto &highlightProperty = *highlightIt;
highlightProperty.key = newHighlightKey;
highlightProperty.sound = sound->isCheckable();
highlightProperty.alert = task->isCheckable();
settings.highlightProperties = properties;
selectedHighlight->setText(newHighlightKey);
show->close();
});
box->addWidget(edit);
box->addWidget(add);
box->addWidget(apply);
box->addWidget(sound);
sound->setChecked(settings.highlightProperties.get()
.value(highlights->selectedItems().first()->text())
.first);
box->addWidget(task);
task->setChecked(settings.highlightProperties.get()
.value(highlights->selectedItems().first()->text())
.second);
show->setLayout(box);
show->show();
}
});
// Delete selected highlight
QObject::connect(delBtn, &QPushButton::clicked, this, [highlights, &settings] {
if (!highlights->selectedItems().isEmpty()) {
settings.highlightProperties.getnonConst().remove(
highlights->selectedItems().first()->text());
delete highlights->selectedItems().first();
if (highlights->selectedItems().isEmpty()) {
// No highlight selected
return;
}
QListWidgetItem *selectedHighlight = highlights->selectedItems().first();
QString highlightKey = selectedHighlight->text();
auto properties = settings.highlightProperties.getValue();
properties.erase(std::remove_if(properties.begin(), properties.end(),
[highlightKey](const auto &highlight) {
return highlight.key == highlightKey; //
}),
properties.end());
settings.highlightProperties = properties;
delete selectedHighlight;
});
layout->addLayout(soundForm);
layout->addWidget(
createCheckbox("Always play highlight sound (Even if Chatterino is focused)",
@ -765,13 +833,6 @@ void SettingsDialog::cancelButtonClicked()
settings.recallSnapshot();
QStringList list = settings.highlightProperties.get().keys();
list.removeDuplicates();
while (globalHighlights->count() > 0) {
delete globalHighlights->takeItem(0);
}
globalHighlights->addItems(list);
this->close();
}