mirror of
https://github.com/Chatterino/chatterino2.git
synced 2024-11-21 22:24:07 +01:00
created base for all the list based settings
This commit is contained in:
parent
4c3f0921e2
commit
ba4173822e
21 changed files with 646 additions and 317 deletions
|
@ -188,7 +188,10 @@ SOURCES += \
|
||||||
src/util/signalvectormodel.cpp \
|
src/util/signalvectormodel.cpp \
|
||||||
src/controllers/commands/command.cpp \
|
src/controllers/commands/command.cpp \
|
||||||
src/controllers/commands/commandmodel.cpp \
|
src/controllers/commands/commandmodel.cpp \
|
||||||
src/controllers/commands/commandcontroller.cpp
|
src/controllers/commands/commandcontroller.cpp \
|
||||||
|
src/controllers/highlights/highlightcontroller.cpp \
|
||||||
|
src/controllers/highlights/highlightmodel.cpp \
|
||||||
|
src/widgets/helper/editablemodelview.cpp
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
src/precompiled_header.hpp \
|
src/precompiled_header.hpp \
|
||||||
|
@ -196,7 +199,6 @@ HEADERS += \
|
||||||
src/const.hpp \
|
src/const.hpp \
|
||||||
src/debug/log.hpp \
|
src/debug/log.hpp \
|
||||||
src/emojis.hpp \
|
src/emojis.hpp \
|
||||||
src/messages/highlightphrase.hpp \
|
|
||||||
src/messages/image.hpp \
|
src/messages/image.hpp \
|
||||||
src/messages/layouts/messagelayout.hpp \
|
src/messages/layouts/messagelayout.hpp \
|
||||||
src/messages/layouts/messagelayoutcontainer.hpp \
|
src/messages/layouts/messagelayoutcontainer.hpp \
|
||||||
|
@ -324,7 +326,11 @@ HEADERS += \
|
||||||
src/util/signalvectormodel.hpp \
|
src/util/signalvectormodel.hpp \
|
||||||
src/controllers/commands/command.hpp \
|
src/controllers/commands/command.hpp \
|
||||||
src/controllers/commands/commandmodel.hpp \
|
src/controllers/commands/commandmodel.hpp \
|
||||||
src/controllers/commands/commandcontroller.hpp
|
src/controllers/commands/commandcontroller.hpp \
|
||||||
|
src/controllers/highlights/highlightcontroller.hpp \
|
||||||
|
src/controllers/highlights/highlightphrase.hpp \
|
||||||
|
src/controllers/highlights/highlightmodel.hpp \
|
||||||
|
src/widgets/helper/editablemodelview.hpp
|
||||||
|
|
||||||
RESOURCES += \
|
RESOURCES += \
|
||||||
resources/resources.qrc
|
resources/resources.qrc
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include "application.hpp"
|
#include "application.hpp"
|
||||||
|
|
||||||
#include "controllers/commands/commandcontroller.hpp"
|
#include "controllers/commands/commandcontroller.hpp"
|
||||||
|
#include "controllers/highlights/highlightcontroller.hpp"
|
||||||
#include "providers/twitch/pubsub.hpp"
|
#include "providers/twitch/pubsub.hpp"
|
||||||
#include "providers/twitch/twitchserver.hpp"
|
#include "providers/twitch/twitchserver.hpp"
|
||||||
#include "singletons/accountmanager.hpp"
|
#include "singletons/accountmanager.hpp"
|
||||||
|
@ -64,6 +65,7 @@ void Application::construct()
|
||||||
this->windows = new singletons::WindowManager;
|
this->windows = new singletons::WindowManager;
|
||||||
this->logging = new singletons::LoggingManager;
|
this->logging = new singletons::LoggingManager;
|
||||||
this->commands = new controllers::commands::CommandController;
|
this->commands = new controllers::commands::CommandController;
|
||||||
|
this->highlights = new controllers::highlights::HighlightController;
|
||||||
this->accounts = new singletons::AccountManager;
|
this->accounts = new singletons::AccountManager;
|
||||||
this->emotes = new singletons::EmoteManager;
|
this->emotes = new singletons::EmoteManager;
|
||||||
this->settings = new singletons::SettingManager;
|
this->settings = new singletons::SettingManager;
|
||||||
|
@ -95,6 +97,8 @@ void Application::initialize()
|
||||||
this->settings->load();
|
this->settings->load();
|
||||||
this->commands->load();
|
this->commands->load();
|
||||||
|
|
||||||
|
this->highlights->initialize();
|
||||||
|
|
||||||
this->emotes->loadGlobalEmotes();
|
this->emotes->loadGlobalEmotes();
|
||||||
|
|
||||||
this->accounts->load();
|
this->accounts->load();
|
||||||
|
|
|
@ -20,6 +20,9 @@ namespace controllers {
|
||||||
namespace commands {
|
namespace commands {
|
||||||
class CommandController;
|
class CommandController;
|
||||||
}
|
}
|
||||||
|
namespace highlights {
|
||||||
|
class HighlightController;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace singletons {
|
namespace singletons {
|
||||||
|
@ -59,6 +62,7 @@ public:
|
||||||
singletons::WindowManager *windows = nullptr;
|
singletons::WindowManager *windows = nullptr;
|
||||||
singletons::LoggingManager *logging = nullptr;
|
singletons::LoggingManager *logging = nullptr;
|
||||||
controllers::commands::CommandController *commands = nullptr;
|
controllers::commands::CommandController *commands = nullptr;
|
||||||
|
controllers::highlights::HighlightController *highlights = nullptr;
|
||||||
singletons::AccountManager *accounts = nullptr;
|
singletons::AccountManager *accounts = nullptr;
|
||||||
singletons::EmoteManager *emotes = nullptr;
|
singletons::EmoteManager *emotes = nullptr;
|
||||||
singletons::NativeMessagingManager *nativeMessaging = nullptr;
|
singletons::NativeMessagingManager *nativeMessaging = nullptr;
|
||||||
|
|
|
@ -14,13 +14,13 @@ Command::Command(const QString &_text)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->name = _text.mid(0, index);
|
this->name = _text.mid(0, index).trimmed();
|
||||||
this->func = _text.mid(index + 1);
|
this->func = _text.mid(index + 1).trimmed();
|
||||||
}
|
}
|
||||||
|
|
||||||
Command::Command(const QString &_name, const QString &_func)
|
Command::Command(const QString &_name, const QString &_func)
|
||||||
: name(_name)
|
: name(_name.trimmed())
|
||||||
, func(_func)
|
, func(_func.trimmed())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,18 +25,6 @@ void CommandModel::getRowFromItem(const Command &item, std::vector<QStandardItem
|
||||||
row[1]->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable);
|
row[1]->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable);
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns the related index of the SignalVector
|
|
||||||
int CommandModel::getVectorIndexFromModelIndex(int index)
|
|
||||||
{
|
|
||||||
return index;
|
|
||||||
}
|
|
||||||
|
|
||||||
// returns the related index of the model
|
|
||||||
int CommandModel::getModelIndexFromVectorIndex(int index)
|
|
||||||
{
|
|
||||||
return index;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace commands
|
} // namespace commands
|
||||||
} // namespace controllers
|
} // namespace controllers
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|
|
@ -22,12 +22,6 @@ protected:
|
||||||
// turns a row in the model into a vector item
|
// turns a row in the model into a vector item
|
||||||
virtual void getRowFromItem(const Command &item, std::vector<QStandardItem *> &row) override;
|
virtual void getRowFromItem(const Command &item, std::vector<QStandardItem *> &row) override;
|
||||||
|
|
||||||
// returns the related index of the SignalVector
|
|
||||||
virtual int getVectorIndexFromModelIndex(int index) override;
|
|
||||||
|
|
||||||
// returns the related index of the model
|
|
||||||
virtual int getModelIndexFromVectorIndex(int index) override;
|
|
||||||
|
|
||||||
friend class CommandController;
|
friend class CommandController;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
39
src/controllers/highlights/highlightcontroller.cpp
Normal file
39
src/controllers/highlights/highlightcontroller.cpp
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
#include "highlightcontroller.hpp"
|
||||||
|
|
||||||
|
#include "application.hpp"
|
||||||
|
#include "controllers/highlights/highlightmodel.hpp"
|
||||||
|
|
||||||
|
namespace chatterino {
|
||||||
|
namespace controllers {
|
||||||
|
namespace highlights {
|
||||||
|
|
||||||
|
HighlightController::HighlightController()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void HighlightController::initialize()
|
||||||
|
{
|
||||||
|
assert(!this->initialized);
|
||||||
|
this->initialized = true;
|
||||||
|
|
||||||
|
for (const HighlightPhrase &phrase : this->highlightsSetting.getValue()) {
|
||||||
|
this->phrases.appendItem(phrase);
|
||||||
|
}
|
||||||
|
|
||||||
|
this->phrases.delayedItemsChanged.connect([this] { //
|
||||||
|
int xd = this->phrases.getVector().size();
|
||||||
|
this->highlightsSetting.setValue(this->phrases.getVector());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
HighlightModel *HighlightController::createModel(QObject *parent)
|
||||||
|
{
|
||||||
|
HighlightModel *model = new HighlightModel(parent);
|
||||||
|
model->init(&this->phrases);
|
||||||
|
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace highlights
|
||||||
|
} // namespace controllers
|
||||||
|
} // namespace chatterino
|
33
src/controllers/highlights/highlightcontroller.hpp
Normal file
33
src/controllers/highlights/highlightcontroller.hpp
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "controllers/highlights/highlightphrase.hpp"
|
||||||
|
#include "singletons/settingsmanager.hpp"
|
||||||
|
#include "util/signalvector2.hpp"
|
||||||
|
|
||||||
|
namespace chatterino {
|
||||||
|
namespace controllers {
|
||||||
|
namespace highlights {
|
||||||
|
|
||||||
|
class HighlightModel;
|
||||||
|
|
||||||
|
class HighlightController
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
HighlightController();
|
||||||
|
|
||||||
|
void initialize();
|
||||||
|
|
||||||
|
util::UnsortedSignalVector<HighlightPhrase> phrases;
|
||||||
|
|
||||||
|
HighlightModel *createModel(QObject *parent);
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool initialized = false;
|
||||||
|
|
||||||
|
singletons::ChatterinoSetting<std::vector<highlights::HighlightPhrase>> highlightsSetting = {
|
||||||
|
"/highlighting/highlights"};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace highlights
|
||||||
|
} // namespace controllers
|
||||||
|
} // namespace chatterino
|
91
src/controllers/highlights/highlightmodel.cpp
Normal file
91
src/controllers/highlights/highlightmodel.cpp
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
#include "highlightmodel.hpp"
|
||||||
|
|
||||||
|
#include "application.hpp"
|
||||||
|
#include "singletons/settingsmanager.hpp"
|
||||||
|
#include "util/standarditemhelper.hpp"
|
||||||
|
|
||||||
|
namespace chatterino {
|
||||||
|
namespace controllers {
|
||||||
|
namespace highlights {
|
||||||
|
|
||||||
|
// commandmodel
|
||||||
|
HighlightModel::HighlightModel(QObject *parent)
|
||||||
|
: util::SignalVectorModel<HighlightPhrase>(4, parent)
|
||||||
|
{
|
||||||
|
// auto app = getApp();
|
||||||
|
|
||||||
|
// std::vector<QStandardItem *> row = this->createRow();
|
||||||
|
|
||||||
|
// util::setBoolItem(row[0], app->settings->enableHighlightsSelf.getValue(), true, false);
|
||||||
|
// util::setBoolItem(row[1], app->settings->enableHighlightsSelf.getValue(), true, false);
|
||||||
|
// util::setBoolItem(row[2], app->settings->enableHighlightsSelf.getValue(), true, false);
|
||||||
|
// row[0]->setData("Your name (automatic)", Qt::DisplayRole);
|
||||||
|
|
||||||
|
// this->insertCustomRow(row, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// app->settings->highlightProperties.setValue(phrases);
|
||||||
|
// app->settings->enableHighlightsSelf.setValue(
|
||||||
|
// model->item(0, 0)->data(Qt::CheckStateRole).toBool());
|
||||||
|
// app->settings->enableHighlightTaskbar.setValue(
|
||||||
|
// model->item(0, 1)->data(Qt::CheckStateRole).toBool());
|
||||||
|
// app->settings->enableHighlightSound.setValue(
|
||||||
|
// model->item(0, 2)->data(Qt::CheckStateRole).toBool());
|
||||||
|
|
||||||
|
// turn a vector item into a model row
|
||||||
|
HighlightPhrase HighlightModel::getItemFromRow(std::vector<QStandardItem *> &row)
|
||||||
|
{
|
||||||
|
// key, alert, sound, regex
|
||||||
|
|
||||||
|
return HighlightPhrase{
|
||||||
|
row[0]->data(Qt::DisplayRole).toString(), row[1]->data(Qt::CheckStateRole).toBool(),
|
||||||
|
row[2]->data(Qt::CheckStateRole).toBool(), row[3]->data(Qt::CheckStateRole).toBool()};
|
||||||
|
}
|
||||||
|
|
||||||
|
// turns a row in the model into a vector item
|
||||||
|
void HighlightModel::getRowFromItem(const HighlightPhrase &item, std::vector<QStandardItem *> &row)
|
||||||
|
{
|
||||||
|
util::setStringItem(row[0], item.key);
|
||||||
|
util::setBoolItem(row[1], item.alert);
|
||||||
|
util::setBoolItem(row[2], item.sound);
|
||||||
|
util::setBoolItem(row[3], item.regex);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HighlightModel::afterInit()
|
||||||
|
{
|
||||||
|
std::vector<QStandardItem *> row = this->createRow();
|
||||||
|
util::setBoolItem(row[0], getApp()->settings->enableHighlightsSelf.getValue(), true, false);
|
||||||
|
row[0]->setData("Your username (automatic)", Qt::DisplayRole);
|
||||||
|
util::setBoolItem(row[1], getApp()->settings->enableHighlightTaskbar.getValue(), true, false);
|
||||||
|
util::setBoolItem(row[2], getApp()->settings->enableHighlightSound.getValue(), true, false);
|
||||||
|
this->insertCustomRow(row, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HighlightModel::customRowSetData(const std::vector<QStandardItem *> &row, int column,
|
||||||
|
const QVariant &value, int role)
|
||||||
|
{
|
||||||
|
switch (column) {
|
||||||
|
case 0: {
|
||||||
|
if (role == Qt::CheckStateRole) {
|
||||||
|
getApp()->settings->enableHighlightsSelf.setValue(value.toBool());
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
case 1: {
|
||||||
|
if (role == Qt::CheckStateRole) {
|
||||||
|
getApp()->settings->enableHighlightTaskbar.setValue(value.toBool());
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
case 2: {
|
||||||
|
if (role == Qt::CheckStateRole) {
|
||||||
|
getApp()->settings->enableHighlightSound.setValue(value.toBool());
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
case 3: {
|
||||||
|
// empty element
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace highlights
|
||||||
|
} // namespace controllers
|
||||||
|
} // namespace chatterino
|
36
src/controllers/highlights/highlightmodel.hpp
Normal file
36
src/controllers/highlights/highlightmodel.hpp
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
#include "controllers/highlights/highlightphrase.hpp"
|
||||||
|
#include "util/signalvectormodel.hpp"
|
||||||
|
|
||||||
|
namespace chatterino {
|
||||||
|
namespace controllers {
|
||||||
|
namespace highlights {
|
||||||
|
|
||||||
|
class HighlightController;
|
||||||
|
|
||||||
|
class HighlightModel : public util::SignalVectorModel<HighlightPhrase>
|
||||||
|
{
|
||||||
|
explicit HighlightModel(QObject *parent);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// turn a vector item into a model row
|
||||||
|
virtual HighlightPhrase getItemFromRow(std::vector<QStandardItem *> &row) override;
|
||||||
|
|
||||||
|
// turns a row in the model into a vector item
|
||||||
|
virtual void getRowFromItem(const HighlightPhrase &item,
|
||||||
|
std::vector<QStandardItem *> &row) override;
|
||||||
|
|
||||||
|
virtual void afterInit() override;
|
||||||
|
|
||||||
|
virtual void customRowSetData(const std::vector<QStandardItem *> &row, int column,
|
||||||
|
const QVariant &value, int role) override;
|
||||||
|
|
||||||
|
friend class HighlightController;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace highlights
|
||||||
|
} // namespace controllers
|
||||||
|
} // namespace chatterino
|
89
src/controllers/highlights/highlightphrase.hpp
Normal file
89
src/controllers/highlights/highlightphrase.hpp
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "util/serialize-custom.hpp"
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
#include <pajlada/settings/serialize.hpp>
|
||||||
|
|
||||||
|
namespace chatterino {
|
||||||
|
namespace controllers {
|
||||||
|
namespace highlights {
|
||||||
|
|
||||||
|
struct HighlightPhrase {
|
||||||
|
QString key;
|
||||||
|
bool alert;
|
||||||
|
bool sound;
|
||||||
|
bool regex;
|
||||||
|
|
||||||
|
bool operator==(const HighlightPhrase &other) const
|
||||||
|
{
|
||||||
|
return std::tie(this->key, this->sound, this->alert, this->regex) ==
|
||||||
|
std::tie(other.key, other.sound, other.alert, other.regex);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} // namespace highlights
|
||||||
|
} // namespace controllers
|
||||||
|
} // namespace chatterino
|
||||||
|
|
||||||
|
namespace pajlada {
|
||||||
|
namespace Settings {
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct Serialize<chatterino::controllers::highlights::HighlightPhrase> {
|
||||||
|
static rapidjson::Value get(const chatterino::controllers::highlights::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);
|
||||||
|
AddMember(ret, "regex", value.regex, a);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct Deserialize<chatterino::controllers::highlights::HighlightPhrase> {
|
||||||
|
static chatterino::controllers::highlights::HighlightPhrase get(const rapidjson::Value &value)
|
||||||
|
{
|
||||||
|
chatterino::controllers::highlights::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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value.HasMember("regex")) {
|
||||||
|
const rapidjson::Value ®ex = value["regex"];
|
||||||
|
if (regex.IsBool()) {
|
||||||
|
ret.regex = regex.GetBool();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Settings
|
||||||
|
} // namespace pajlada
|
|
@ -1,87 +1,87 @@
|
||||||
#pragma once
|
//#pragma once
|
||||||
|
|
||||||
#include "util/serialize-custom.hpp"
|
//#include "util/serialize-custom.hpp"
|
||||||
|
|
||||||
#include <QString>
|
//#include <QString>
|
||||||
#include <pajlada/settings/serialize.hpp>
|
//#include <pajlada/settings/serialize.hpp>
|
||||||
|
|
||||||
namespace chatterino {
|
//namespace chatterino {
|
||||||
namespace messages {
|
//namespace messages {
|
||||||
|
|
||||||
struct HighlightPhrase {
|
//struct HighlightPhrase {
|
||||||
QString key;
|
// QString key;
|
||||||
bool alert;
|
// bool alert;
|
||||||
bool sound;
|
// bool sound;
|
||||||
bool regex;
|
// bool regex;
|
||||||
|
|
||||||
bool operator==(const HighlightPhrase &other) const
|
// bool operator==(const HighlightPhrase &other) const
|
||||||
{
|
// {
|
||||||
return std::tie(this->key, this->sound, this->alert, this->regex) ==
|
// return std::tie(this->key, this->sound, this->alert, this->regex) ==
|
||||||
std::tie(other.key, other.sound, other.alert, other.regex);
|
// std::tie(other.key, other.sound, other.alert, other.regex);
|
||||||
}
|
// }
|
||||||
};
|
//};
|
||||||
} // namespace messages
|
//} // namespace messages
|
||||||
} // namespace chatterino
|
//} // namespace chatterino
|
||||||
|
|
||||||
namespace pajlada {
|
//namespace pajlada {
|
||||||
namespace Settings {
|
//namespace Settings {
|
||||||
|
|
||||||
template <>
|
//template <>
|
||||||
struct Serialize<chatterino::messages::HighlightPhrase> {
|
//struct Serialize<chatterino::messages::HighlightPhrase> {
|
||||||
static rapidjson::Value get(const chatterino::messages::HighlightPhrase &value,
|
// static rapidjson::Value get(const chatterino::messages::HighlightPhrase &value,
|
||||||
rapidjson::Document::AllocatorType &a)
|
// rapidjson::Document::AllocatorType &a)
|
||||||
{
|
// {
|
||||||
rapidjson::Value ret(rapidjson::kObjectType);
|
// rapidjson::Value ret(rapidjson::kObjectType);
|
||||||
|
|
||||||
AddMember(ret, "key", value.key, a);
|
// AddMember(ret, "key", value.key, a);
|
||||||
AddMember(ret, "alert", value.alert, a);
|
// AddMember(ret, "alert", value.alert, a);
|
||||||
AddMember(ret, "sound", value.sound, a);
|
// AddMember(ret, "sound", value.sound, a);
|
||||||
AddMember(ret, "regex", value.regex, a);
|
// AddMember(ret, "regex", value.regex, a);
|
||||||
|
|
||||||
return ret;
|
// return ret;
|
||||||
}
|
// }
|
||||||
};
|
//};
|
||||||
|
|
||||||
template <>
|
//template <>
|
||||||
struct Deserialize<chatterino::messages::HighlightPhrase> {
|
//struct Deserialize<chatterino::messages::HighlightPhrase> {
|
||||||
static chatterino::messages::HighlightPhrase get(const rapidjson::Value &value)
|
// static chatterino::messages::HighlightPhrase get(const rapidjson::Value &value)
|
||||||
{
|
// {
|
||||||
chatterino::messages::HighlightPhrase ret;
|
// chatterino::messages::HighlightPhrase ret;
|
||||||
if (!value.IsObject()) {
|
// if (!value.IsObject()) {
|
||||||
return ret;
|
// return ret;
|
||||||
}
|
// }
|
||||||
|
|
||||||
if (value.HasMember("key")) {
|
// if (value.HasMember("key")) {
|
||||||
const rapidjson::Value &key = value["key"];
|
// const rapidjson::Value &key = value["key"];
|
||||||
if (key.IsString()) {
|
// if (key.IsString()) {
|
||||||
ret.key = key.GetString();
|
// ret.key = key.GetString();
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
if (value.HasMember("alert")) {
|
// if (value.HasMember("alert")) {
|
||||||
const rapidjson::Value &alert = value["alert"];
|
// const rapidjson::Value &alert = value["alert"];
|
||||||
if (alert.IsBool()) {
|
// if (alert.IsBool()) {
|
||||||
ret.alert = alert.GetBool();
|
// ret.alert = alert.GetBool();
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
if (value.HasMember("sound")) {
|
// if (value.HasMember("sound")) {
|
||||||
const rapidjson::Value &sound = value["sound"];
|
// const rapidjson::Value &sound = value["sound"];
|
||||||
if (sound.IsBool()) {
|
// if (sound.IsBool()) {
|
||||||
ret.sound = sound.GetBool();
|
// ret.sound = sound.GetBool();
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
if (value.HasMember("regex")) {
|
// if (value.HasMember("regex")) {
|
||||||
const rapidjson::Value ®ex = value["regex"];
|
// const rapidjson::Value ®ex = value["regex"];
|
||||||
if (regex.IsBool()) {
|
// if (regex.IsBool()) {
|
||||||
ret.regex = regex.GetBool();
|
// ret.regex = regex.GetBool();
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
return ret;
|
// return ret;
|
||||||
}
|
// }
|
||||||
};
|
//};
|
||||||
|
|
||||||
} // namespace Settings
|
//} // namespace Settings
|
||||||
} // namespace pajlada
|
//} // namespace pajlada
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include "providers/twitch/twitchmessagebuilder.hpp"
|
#include "providers/twitch/twitchmessagebuilder.hpp"
|
||||||
|
|
||||||
#include "application.hpp"
|
#include "application.hpp"
|
||||||
|
#include "controllers/highlights/highlightcontroller.hpp"
|
||||||
#include "debug/log.hpp"
|
#include "debug/log.hpp"
|
||||||
#include "providers/twitch/twitchchannel.hpp"
|
#include "providers/twitch/twitchchannel.hpp"
|
||||||
#include "singletons/accountmanager.hpp"
|
#include "singletons/accountmanager.hpp"
|
||||||
|
@ -398,10 +399,12 @@ void TwitchMessageBuilder::parseHighlights()
|
||||||
app->settings->highlightUserBlacklist.getValue().split("\n", QString::SkipEmptyParts);
|
app->settings->highlightUserBlacklist.getValue().split("\n", QString::SkipEmptyParts);
|
||||||
|
|
||||||
// TODO: This vector should only be rebuilt upon highlights being changed
|
// TODO: This vector should only be rebuilt upon highlights being changed
|
||||||
auto activeHighlights = app->settings->highlightProperties.getValue();
|
// fourtf: should be implemented in the HighlightsController
|
||||||
|
std::vector<controllers::highlights::HighlightPhrase> activeHighlights =
|
||||||
|
app->highlights->phrases.getVector();
|
||||||
|
|
||||||
if (app->settings->enableHighlightsSelf && currentUsername.size() > 0) {
|
if (app->settings->enableHighlightsSelf && currentUsername.size() > 0) {
|
||||||
messages::HighlightPhrase selfHighlight;
|
controllers::highlights::HighlightPhrase selfHighlight;
|
||||||
selfHighlight.key = currentUsername;
|
selfHighlight.key = currentUsername;
|
||||||
selfHighlight.sound = app->settings->enableHighlightSound;
|
selfHighlight.sound = app->settings->enableHighlightSound;
|
||||||
selfHighlight.alert = app->settings->enableHighlightTaskbar;
|
selfHighlight.alert = app->settings->enableHighlightTaskbar;
|
||||||
|
@ -415,7 +418,7 @@ void TwitchMessageBuilder::parseHighlights()
|
||||||
bool hasFocus = (QApplication::focusWidget() != nullptr);
|
bool hasFocus = (QApplication::focusWidget() != nullptr);
|
||||||
|
|
||||||
if (!blackList.contains(this->ircMessage->nick(), Qt::CaseInsensitive)) {
|
if (!blackList.contains(this->ircMessage->nick(), Qt::CaseInsensitive)) {
|
||||||
for (const messages::HighlightPhrase &highlight : activeHighlights) {
|
for (const controllers::highlights::HighlightPhrase &highlight : activeHighlights) {
|
||||||
int index = -1;
|
int index = -1;
|
||||||
|
|
||||||
while ((index = this->originalMessage.indexOf(highlight.key, index + 1,
|
while ((index = this->originalMessage.indexOf(highlight.key, index + 1,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "messages/highlightphrase.hpp"
|
#include "controllers/highlights/highlightphrase.hpp"
|
||||||
#include "messages/messageelement.hpp"
|
#include "messages/messageelement.hpp"
|
||||||
#include "singletons/helper/chatterinosetting.hpp"
|
#include "singletons/helper/chatterinosetting.hpp"
|
||||||
#include "singletons/helper/moderationaction.hpp"
|
#include "singletons/helper/moderationaction.hpp"
|
||||||
|
@ -104,9 +104,6 @@ public:
|
||||||
/// Logging
|
/// Logging
|
||||||
BoolSetting enableLogging = {"/logging/enabled", false};
|
BoolSetting enableLogging = {"/logging/enabled", false};
|
||||||
|
|
||||||
ChatterinoSetting<std::vector<messages::HighlightPhrase>> highlightProperties = {
|
|
||||||
"/highlighting/highlights"};
|
|
||||||
|
|
||||||
QStringSetting pathHighlightSound = {"/highlighting/highlightSoundPath",
|
QStringSetting pathHighlightSound = {"/highlighting/highlightSoundPath",
|
||||||
"qrc:/sounds/ping2.wav"};
|
"qrc:/sounds/ping2.wav"};
|
||||||
QStringSetting highlightUserBlacklist = {"/highlighting/blacklistedUsers", ""};
|
QStringSetting highlightUserBlacklist = {"/highlighting/blacklistedUsers", ""};
|
||||||
|
|
|
@ -19,6 +19,8 @@ public:
|
||||||
{
|
{
|
||||||
QObject::connect(&this->itemsChangedTimer, &QTimer::timeout,
|
QObject::connect(&this->itemsChangedTimer, &QTimer::timeout,
|
||||||
[this] { this->delayedItemsChanged.invoke(); });
|
[this] { this->delayedItemsChanged.invoke(); });
|
||||||
|
this->itemsChangedTimer.setInterval(100);
|
||||||
|
this->itemsChangedTimer.setSingleShot(true);
|
||||||
}
|
}
|
||||||
virtual ~ReadOnlySignalVector() = default;
|
virtual ~ReadOnlySignalVector() = default;
|
||||||
|
|
||||||
|
@ -69,6 +71,8 @@ public:
|
||||||
this->vector.erase(this->vector.begin() + index);
|
this->vector.erase(this->vector.begin() + index);
|
||||||
typename ReadOnlySignalVector<TVectorItem>::ItemArgs args{item, index, caller};
|
typename ReadOnlySignalVector<TVectorItem>::ItemArgs args{item, index, caller};
|
||||||
this->itemRemoved.invoke(args);
|
this->itemRemoved.invoke(args);
|
||||||
|
|
||||||
|
this->invokeDelayedItemsChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
int appendItem(const TVectorItem &item, void *caller = 0)
|
int appendItem(const TVectorItem &item, void *caller = 0)
|
||||||
|
@ -94,6 +98,7 @@ public:
|
||||||
|
|
||||||
typename ReadOnlySignalVector<TVectorItem>::ItemArgs args{item, index, caller};
|
typename ReadOnlySignalVector<TVectorItem>::ItemArgs args{item, index, caller};
|
||||||
this->itemInserted.invoke(args);
|
this->itemInserted.invoke(args);
|
||||||
|
this->invokeDelayedItemsChanged();
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -111,6 +116,7 @@ public:
|
||||||
this->vector.begin();
|
this->vector.begin();
|
||||||
typename ReadOnlySignalVector<TVectorItem>::ItemArgs args{item, index, caller};
|
typename ReadOnlySignalVector<TVectorItem>::ItemArgs args{item, index, caller};
|
||||||
this->itemInserted.invoke(args);
|
this->itemInserted.invoke(args);
|
||||||
|
this->invokeDelayedItemsChanged();
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -32,20 +32,18 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
// get row index
|
// get row index
|
||||||
int row = this->getModelIndexFromVectorIndex(args.index);
|
int index = this->getModelIndexFromVectorIndex(args.index);
|
||||||
assert(row >= 0 && row <= this->rows.size());
|
assert(index >= 0 && index <= this->rows.size());
|
||||||
|
|
||||||
// get row items
|
// get row items
|
||||||
std::vector<QStandardItem *> items;
|
std::vector<QStandardItem *> row = this->createRow();
|
||||||
for (int i = 0; i < this->_columnCount; i++) {
|
this->getRowFromItem(args.item, row);
|
||||||
items.push_back(new QStandardItem());
|
|
||||||
}
|
|
||||||
|
|
||||||
this->getRowFromItem(args.item, items);
|
|
||||||
|
|
||||||
// insert row
|
// insert row
|
||||||
this->beginInsertRows(QModelIndex(), row, row);
|
index = this->beforeInsert(args.item, row, index);
|
||||||
this->rows.insert(this->rows.begin() + row, Row(items));
|
|
||||||
|
this->beginInsertRows(QModelIndex(), index, index);
|
||||||
|
this->rows.insert(this->rows.begin() + index, Row(row));
|
||||||
this->endInsertRows();
|
this->endInsertRows();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -74,6 +72,8 @@ public:
|
||||||
this->rows.erase(this->rows.begin() + row);
|
this->rows.erase(this->rows.begin() + row);
|
||||||
this->endRemoveRows();
|
this->endRemoveRows();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this->afterInit();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~SignalVectorModel()
|
virtual ~SignalVectorModel()
|
||||||
|
@ -108,12 +108,18 @@ public:
|
||||||
int row = index.row(), column = index.column();
|
int row = index.row(), column = index.column();
|
||||||
assert(row >= 0 && row < this->rows.size() && column >= 0 && column < this->_columnCount);
|
assert(row >= 0 && row < this->rows.size() && column >= 0 && column < this->_columnCount);
|
||||||
|
|
||||||
this->rows[row].items[column]->setData(value, role);
|
Row &rowItem = this->rows[row];
|
||||||
|
|
||||||
int vecRow = this->getVectorIndexFromModelIndex(row);
|
rowItem.items[column]->setData(value, role);
|
||||||
this->vector->removeItem(vecRow, this);
|
|
||||||
TVectorItem item = this->getItemFromRow(this->rows[row].items);
|
if (rowItem.isCustomRow) {
|
||||||
this->vector->insertItem(item, vecRow, this);
|
this->customRowSetData(rowItem.items, column, value, role);
|
||||||
|
} else {
|
||||||
|
int vecRow = this->getVectorIndexFromModelIndex(row);
|
||||||
|
this->vector->removeItem(vecRow, this);
|
||||||
|
TVectorItem item = this->getItemFromRow(this->rows[row].items);
|
||||||
|
this->vector->insertItem(item, vecRow, this);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -140,6 +146,8 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
this->_headerData[section][role] = value;
|
this->_headerData[section][role] = value;
|
||||||
|
|
||||||
|
emit this->headerDataChanged(Qt::Horizontal, section, section);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -151,51 +159,133 @@ public:
|
||||||
return this->rows[index.row()].items[index.column()]->flags();
|
return this->rows[index.row()].items[index.column()]->flags();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual QStandardItem *getItem(int row, int column)
|
QStandardItem *getItem(int row, int column)
|
||||||
{
|
{
|
||||||
assert(row >= 0 && row < this->rows.size() && column >= 0 && column < this->_columnCount);
|
assert(row >= 0 && row < this->rows.size() && column >= 0 && column < this->_columnCount);
|
||||||
|
|
||||||
return rows[row].items[column];
|
return rows[row].items[column];
|
||||||
}
|
}
|
||||||
|
|
||||||
void removeRow(int row)
|
void deleteRow(int row)
|
||||||
{
|
{
|
||||||
assert(row >= 0 && row <= this->rows.size());
|
|
||||||
|
|
||||||
int signalVectorRow = this->getVectorIndexFromModelIndex(row);
|
int signalVectorRow = this->getVectorIndexFromModelIndex(row);
|
||||||
this->vector->removeItem(signalVectorRow);
|
this->vector->removeItem(signalVectorRow);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual bool removeRows(int row, int count, const QModelIndex &parent) override
|
||||||
|
{
|
||||||
|
if (count != 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(row >= 0 && row < this->rows.size());
|
||||||
|
|
||||||
|
int signalVectorRow = this->getVectorIndexFromModelIndex(row);
|
||||||
|
this->vector->removeItem(signalVectorRow);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
virtual void afterInit()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
// turn a vector item into a model row
|
// turn a vector item into a model row
|
||||||
virtual TVectorItem getItemFromRow(std::vector<QStandardItem *> &row) = 0;
|
virtual TVectorItem getItemFromRow(std::vector<QStandardItem *> &row) = 0;
|
||||||
|
|
||||||
// turns a row in the model into a vector item
|
// turns a row in the model into a vector item
|
||||||
virtual void getRowFromItem(const TVectorItem &item, std::vector<QStandardItem *> &row) = 0;
|
virtual void getRowFromItem(const TVectorItem &item, std::vector<QStandardItem *> &row) = 0;
|
||||||
|
|
||||||
// returns the related index of the SignalVector
|
virtual int beforeInsert(const TVectorItem &item, std::vector<QStandardItem *> &row,
|
||||||
virtual int getVectorIndexFromModelIndex(int index) = 0;
|
int proposedIndex)
|
||||||
|
{
|
||||||
|
return proposedIndex;
|
||||||
|
}
|
||||||
|
|
||||||
// returns the related index of the model
|
virtual void afterRemoved(const TVectorItem &item, std::vector<QStandardItem *> &row, int index)
|
||||||
virtual int getModelIndexFromVectorIndex(int index) = 0;
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void customRowSetData(const std::vector<QStandardItem *> &row, int column,
|
||||||
|
const QVariant &value, int role)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void insertCustomRow(std::vector<QStandardItem *> row, int index)
|
||||||
|
{
|
||||||
|
assert(index >= 0 && index <= this->rows.size());
|
||||||
|
|
||||||
|
this->beginInsertRows(QModelIndex(), index, index);
|
||||||
|
this->rows.insert(this->rows.begin() + index, Row(std::move(row), true));
|
||||||
|
this->endInsertRows();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<QStandardItem *> createRow()
|
||||||
|
{
|
||||||
|
std::vector<QStandardItem *> row;
|
||||||
|
for (int i = 0; i < this->_columnCount; i++) {
|
||||||
|
row.push_back(new QStandardItem());
|
||||||
|
}
|
||||||
|
return row;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
|
||||||
struct Row {
|
struct Row {
|
||||||
std::vector<QStandardItem *> items;
|
std::vector<QStandardItem *> items;
|
||||||
bool isCustomRow;
|
bool isCustomRow;
|
||||||
|
|
||||||
Row(const std::vector<QStandardItem *> _items, bool _isCustomRow = false)
|
Row(std::vector<QStandardItem *> _items, bool _isCustomRow = false)
|
||||||
: items(_items)
|
: items(std::move(_items))
|
||||||
, isCustomRow(_isCustomRow)
|
, isCustomRow(_isCustomRow)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<Row> rows;
|
std::vector<Row> rows;
|
||||||
|
|
||||||
|
private:
|
||||||
std::vector<QMap<int, QVariant>> _headerData;
|
std::vector<QMap<int, QVariant>> _headerData;
|
||||||
BaseSignalVector<TVectorItem> *vector;
|
BaseSignalVector<TVectorItem> *vector;
|
||||||
|
|
||||||
int _columnCount;
|
int _columnCount;
|
||||||
|
|
||||||
|
// returns the related index of the SignalVector
|
||||||
|
int getVectorIndexFromModelIndex(int index)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
for (auto &row : this->rows) {
|
||||||
|
if (row.isCustomRow) {
|
||||||
|
index--;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == index) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns the related index of the model
|
||||||
|
int getModelIndexFromVectorIndex(int index)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
for (auto &row : this->rows) {
|
||||||
|
if (row.isCustomRow) {
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == index) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace util
|
} // namespace util
|
||||||
|
|
|
@ -5,21 +5,20 @@
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
namespace util {
|
namespace util {
|
||||||
|
|
||||||
static QStandardItem *boolItem(bool value, bool userCheckable = true, bool selectable = true)
|
static void setBoolItem(QStandardItem *item, bool value, bool userCheckable = true,
|
||||||
|
bool selectable = true)
|
||||||
{
|
{
|
||||||
auto *item = new QStandardItem();
|
|
||||||
item->setFlags((Qt::ItemFlags)(Qt::ItemIsEnabled | (selectable ? Qt::ItemIsSelectable : 0) |
|
item->setFlags((Qt::ItemFlags)(Qt::ItemIsEnabled | (selectable ? Qt::ItemIsSelectable : 0) |
|
||||||
(userCheckable ? Qt::ItemIsUserCheckable : 0)));
|
(userCheckable ? Qt::ItemIsUserCheckable : 0)));
|
||||||
item->setCheckState(value ? Qt::Checked : Qt::Unchecked);
|
item->setCheckState(value ? Qt::Checked : Qt::Unchecked);
|
||||||
return item;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static QStandardItem *stringItem(const QString &value, bool editable = true, bool selectable = true)
|
static void setStringItem(QStandardItem *item, const QString &value, bool editable = true,
|
||||||
|
bool selectable = true)
|
||||||
{
|
{
|
||||||
auto *item = new QStandardItem(value);
|
item->setData(value, Qt::EditRole);
|
||||||
item->setFlags((Qt::ItemFlags)(Qt::ItemIsEnabled | (selectable ? Qt::ItemIsSelectable : 0) |
|
item->setFlags((Qt::ItemFlags)(Qt::ItemIsEnabled | (selectable ? Qt::ItemIsSelectable : 0) |
|
||||||
(editable ? (Qt::ItemIsEditable) : 0)));
|
(editable ? (Qt::ItemIsEditable) : 0)));
|
||||||
return item;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static QStandardItem *emptyItem()
|
static QStandardItem *emptyItem()
|
||||||
|
|
75
src/widgets/helper/editablemodelview.cpp
Normal file
75
src/widgets/helper/editablemodelview.cpp
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
#include "editablemodelview.hpp"
|
||||||
|
|
||||||
|
#include <QAbstractTableModel>
|
||||||
|
#include <QHBoxLayout>
|
||||||
|
#include <QHeaderView>
|
||||||
|
#include <QPushButton>
|
||||||
|
#include <QTableView>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
|
||||||
|
namespace chatterino {
|
||||||
|
namespace widgets {
|
||||||
|
namespace helper {
|
||||||
|
|
||||||
|
EditableModelView::EditableModelView(QAbstractTableModel *_model)
|
||||||
|
: tableView(new QTableView(this))
|
||||||
|
, model(_model)
|
||||||
|
{
|
||||||
|
this->model->setParent(this);
|
||||||
|
this->tableView->setModel(_model);
|
||||||
|
this->tableView->setSelectionMode(QAbstractItemView::ExtendedSelection);
|
||||||
|
this->tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||||
|
this->tableView->verticalHeader()->hide();
|
||||||
|
|
||||||
|
// create layout
|
||||||
|
QVBoxLayout *vbox = new QVBoxLayout(this);
|
||||||
|
vbox->addWidget(this->tableView);
|
||||||
|
|
||||||
|
// create button layout
|
||||||
|
QHBoxLayout *buttons = new QHBoxLayout(this);
|
||||||
|
vbox->addLayout(buttons);
|
||||||
|
|
||||||
|
// add
|
||||||
|
QPushButton *add = new QPushButton("Add");
|
||||||
|
buttons->addWidget(add);
|
||||||
|
QObject::connect(add, &QPushButton::clicked, [this] { this->addButtonPressed.invoke(); });
|
||||||
|
|
||||||
|
// remove
|
||||||
|
QPushButton *remove = new QPushButton("Remove");
|
||||||
|
buttons->addWidget(remove);
|
||||||
|
QObject::connect(remove, &QPushButton::clicked, [this] {
|
||||||
|
QModelIndexList list;
|
||||||
|
while ((list = this->getTableView()->selectionModel()->selectedRows(0)).length() > 0) {
|
||||||
|
model->removeRow(list[0].row());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// finish button layout
|
||||||
|
buttons->addStretch(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditableModelView::setTitles(std::initializer_list<QString> titles)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
for (const QString &title : titles) {
|
||||||
|
if (this->model->columnCount() == i) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->model->setHeaderData(i++, Qt::Horizontal, title, Qt::DisplayRole);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QTableView *EditableModelView::getTableView()
|
||||||
|
{
|
||||||
|
return this->tableView;
|
||||||
|
}
|
||||||
|
|
||||||
|
QAbstractTableModel *EditableModelView::getModel()
|
||||||
|
{
|
||||||
|
return this->model;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace helper
|
||||||
|
} // namespace widgets
|
||||||
|
} // namespace chatterino
|
33
src/widgets/helper/editablemodelview.hpp
Normal file
33
src/widgets/helper/editablemodelview.hpp
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QWidget>
|
||||||
|
|
||||||
|
#include <pajlada/signals/signal.hpp>
|
||||||
|
|
||||||
|
class QAbstractTableModel;
|
||||||
|
class QTableView;
|
||||||
|
|
||||||
|
namespace chatterino {
|
||||||
|
namespace widgets {
|
||||||
|
namespace helper {
|
||||||
|
|
||||||
|
class EditableModelView : public QWidget
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
EditableModelView(QAbstractTableModel *model);
|
||||||
|
|
||||||
|
void setTitles(std::initializer_list<QString> titles);
|
||||||
|
|
||||||
|
QTableView *getTableView();
|
||||||
|
QAbstractTableModel *getModel();
|
||||||
|
|
||||||
|
pajlada::Signals::NoArgSignal addButtonPressed;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QTableView *tableView;
|
||||||
|
QAbstractTableModel *model;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace helper
|
||||||
|
} // namespace widgets
|
||||||
|
} // namespace chatterino
|
|
@ -1,5 +1,6 @@
|
||||||
#include "commandpage.hpp"
|
#include "commandpage.hpp"
|
||||||
|
|
||||||
|
#include <QHeaderView>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
#include <QStandardItemModel>
|
#include <QStandardItemModel>
|
||||||
|
@ -11,6 +12,7 @@
|
||||||
#include "controllers/commands/commandmodel.hpp"
|
#include "controllers/commands/commandmodel.hpp"
|
||||||
#include "util/layoutcreator.hpp"
|
#include "util/layoutcreator.hpp"
|
||||||
#include "util/standarditemhelper.hpp"
|
#include "util/standarditemhelper.hpp"
|
||||||
|
#include "widgets/helper/editablemodelview.hpp"
|
||||||
//#include "widgets/helper/comboboxitemdelegate.hpp"
|
//#include "widgets/helper/comboboxitemdelegate.hpp"
|
||||||
|
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
|
@ -34,107 +36,15 @@ CommandPage::CommandPage()
|
||||||
util::LayoutCreator<CommandPage> layoutCreator(this);
|
util::LayoutCreator<CommandPage> layoutCreator(this);
|
||||||
auto layout = layoutCreator.emplace<QVBoxLayout>().withoutMargin();
|
auto layout = layoutCreator.emplace<QVBoxLayout>().withoutMargin();
|
||||||
|
|
||||||
QTableView *view = *layout.emplace<QTableView>();
|
helper::EditableModelView *view =
|
||||||
|
*layout.emplace<helper::EditableModelView>(app->commands->createModel(nullptr));
|
||||||
|
|
||||||
auto *model = app->commands->createModel(view);
|
view->setTitles({"Trigger", "Command"});
|
||||||
view->setModel(model);
|
view->getTableView()->horizontalHeader()->setStretchLastSection(true);
|
||||||
model->setHeaderData(0, Qt::Horizontal, "Trigger");
|
view->addButtonPressed.connect([] {
|
||||||
model->setHeaderData(1, Qt::Horizontal, "Command");
|
getApp()->commands->items.appendItem(
|
||||||
view->setSelectionMode(QAbstractItemView::ExtendedSelection);
|
controllers::commands::Command{"/command", "I made a new command HeyGuys"});
|
||||||
view->setSelectionBehavior(QAbstractItemView::SelectRows);
|
});
|
||||||
view->horizontalHeader()->setSectionResizeMode(1, QHeaderView::Stretch);
|
|
||||||
view->verticalHeader()->hide();
|
|
||||||
|
|
||||||
auto buttons = layout.emplace<QHBoxLayout>().withoutMargin();
|
|
||||||
{
|
|
||||||
auto add = buttons.emplace<QPushButton>("Add");
|
|
||||||
QObject::connect(*add, &QPushButton::clicked, [model, view] {
|
|
||||||
getApp()->commands->items.appendItem(
|
|
||||||
controllers::commands::Command{"/command", "I made a new command HeyGuys"});
|
|
||||||
view->scrollToBottom();
|
|
||||||
});
|
|
||||||
|
|
||||||
auto remove = buttons.emplace<QPushButton>("Remove");
|
|
||||||
QObject::connect(*remove, &QPushButton::clicked, [view, model] {
|
|
||||||
std::vector<int> indices;
|
|
||||||
|
|
||||||
for (const QModelIndex &index : view->selectionModel()->selectedRows(0)) {
|
|
||||||
indices.push_back(index.row());
|
|
||||||
}
|
|
||||||
|
|
||||||
std::sort(indices.begin(), indices.end());
|
|
||||||
|
|
||||||
for (int i = indices.size() - 1; i >= 0; i--) {
|
|
||||||
model->removeRow(indices[i]);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
buttons->addStretch(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// QTableView *view = *layout.emplace<QTableView>();
|
|
||||||
// QStandardItemModel *model = new QStandardItemModel(0, 2, view);
|
|
||||||
|
|
||||||
// view->setModel(model);
|
|
||||||
// model->setHeaderData(0, Qt::Horizontal, "Trigger");
|
|
||||||
// model->setHeaderData(1, Qt::Horizontal, "Command");
|
|
||||||
// view->setSelectionMode(QAbstractItemView::ExtendedSelection);
|
|
||||||
// view->setSelectionBehavior(QAbstractItemView::SelectRows);
|
|
||||||
// view->horizontalHeader()->setSectionResizeMode(1, QHeaderView::Stretch);
|
|
||||||
|
|
||||||
// for (const QString &string : app->commands->getCommands()) {
|
|
||||||
// int index = string.indexOf(' ');
|
|
||||||
// if (index == -1) {
|
|
||||||
// model->appendRow({util::stringItem(string), util::stringItem("")});
|
|
||||||
// } else {
|
|
||||||
// model->appendRow(
|
|
||||||
// {util::stringItem(string.mid(0, index)), util::stringItem(string.mid(index +
|
|
||||||
// 1))});
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// QObject::connect(
|
|
||||||
// model, &QStandardItemModel::dataChanged,
|
|
||||||
// [model](const QModelIndex &topLeft, const QModelIndex &bottomRight,
|
|
||||||
// const QVector<int> &roles) {
|
|
||||||
// QStringList list;
|
|
||||||
|
|
||||||
// for (int i = 0; i < model->rowCount(); i++) {
|
|
||||||
// QString command = model->item(i, 0)->data(Qt::EditRole).toString();
|
|
||||||
// // int index = command.indexOf(' ');
|
|
||||||
// // if (index != -1) {
|
|
||||||
// // command = command.mid(index);
|
|
||||||
// // }
|
|
||||||
|
|
||||||
// list.append(command + " " + model->item(i, 1)->data(Qt::EditRole).toString());
|
|
||||||
// }
|
|
||||||
|
|
||||||
// getApp()->commands->setCommands(list);
|
|
||||||
// });
|
|
||||||
|
|
||||||
// auto buttons = layout.emplace<QHBoxLayout>().withoutMargin();
|
|
||||||
// {
|
|
||||||
// auto add = buttons.emplace<QPushButton>("Add");
|
|
||||||
// QObject::connect(*add, &QPushButton::clicked, [model, view] {
|
|
||||||
// model->appendRow({util::stringItem("/command"), util::stringItem("")});
|
|
||||||
// view->scrollToBottom();
|
|
||||||
// });
|
|
||||||
|
|
||||||
// auto remove = buttons.emplace<QPushButton>("Remove");
|
|
||||||
// QObject::connect(*remove, &QPushButton::clicked, [view, model] {
|
|
||||||
// std::vector<int> indices;
|
|
||||||
|
|
||||||
// for (const QModelIndex &index : view->selectionModel()->selectedRows(0)) {
|
|
||||||
// indices.push_back(index.row());
|
|
||||||
// }
|
|
||||||
|
|
||||||
// std::sort(indices.begin(), indices.end());
|
|
||||||
|
|
||||||
// for (int i = indices.size() - 1; i >= 0; i--) {
|
|
||||||
// model->removeRow(indices[i]);
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
// buttons->addStretch(1);
|
|
||||||
// }
|
|
||||||
|
|
||||||
layout.append(this->createCheckBox("Also match the trigger at the end of the message",
|
layout.append(this->createCheckBox("Also match the trigger at the end of the message",
|
||||||
app->settings->allowCommandsAtEnd));
|
app->settings->allowCommandsAtEnd));
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
#include "highlightingpage.hpp"
|
#include "highlightingpage.hpp"
|
||||||
|
|
||||||
#include "application.hpp"
|
#include "application.hpp"
|
||||||
|
#include "controllers/highlights/highlightcontroller.hpp"
|
||||||
|
#include "controllers/highlights/highlightmodel.hpp"
|
||||||
#include "debug/log.hpp"
|
#include "debug/log.hpp"
|
||||||
#include "singletons/settingsmanager.hpp"
|
#include "singletons/settingsmanager.hpp"
|
||||||
#include "util/layoutcreator.hpp"
|
#include "util/layoutcreator.hpp"
|
||||||
#include "util/standarditemhelper.hpp"
|
#include "util/standarditemhelper.hpp"
|
||||||
|
#include "widgets/helper/editablemodelview.hpp"
|
||||||
|
|
||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
#include <QListWidget>
|
#include <QListWidget>
|
||||||
|
@ -41,95 +44,24 @@ HighlightingPage::HighlightingPage()
|
||||||
// HIGHLIGHTS
|
// HIGHLIGHTS
|
||||||
auto highlights = tabs.appendTab(new QVBoxLayout, "Highlights");
|
auto highlights = tabs.appendTab(new QVBoxLayout, "Highlights");
|
||||||
{
|
{
|
||||||
QTableView *view = *highlights.emplace<QTableView>();
|
helper::EditableModelView *view = *highlights.emplace<helper::EditableModelView>(
|
||||||
auto *model = new QStandardItemModel(0, 4, view);
|
app->highlights->createModel(nullptr));
|
||||||
model->setHeaderData(0, Qt::Horizontal, "Pattern");
|
|
||||||
model->setHeaderData(1, Qt::Horizontal, "Flash taskbar");
|
|
||||||
model->setHeaderData(2, Qt::Horizontal, "Play sound");
|
|
||||||
model->setHeaderData(3, Qt::Horizontal, "Regex");
|
|
||||||
view->setModel(model);
|
|
||||||
view->setSelectionMode(QAbstractItemView::ExtendedSelection);
|
|
||||||
view->setSelectionBehavior(QAbstractItemView::SelectRows);
|
|
||||||
view->horizontalHeader()->setSectionResizeMode(QHeaderView::Fixed);
|
|
||||||
|
|
||||||
// own name
|
view->getTableView()->hideColumn(3);
|
||||||
auto *yourName = util::stringItem("Your name (automatic)", false, false);
|
|
||||||
yourName->setData(QBrush("#666"), Qt::ForegroundRole);
|
|
||||||
yourName->setFlags(yourName->flags() | Qt::ItemIsUserCheckable |
|
|
||||||
Qt::ItemIsUserCheckable);
|
|
||||||
yourName->setData(app->settings->enableHighlightsSelf ? 2 : 0, Qt::CheckStateRole);
|
|
||||||
model->appendRow(
|
|
||||||
{yourName,
|
|
||||||
util::boolItem(app->settings->enableHighlightTaskbar.getValue(), true, false),
|
|
||||||
util::boolItem(app->settings->enableHighlightSound.getValue(), true, false),
|
|
||||||
util::emptyItem()});
|
|
||||||
|
|
||||||
// highlight phrases
|
view->setTitles({"Pattern", "Flash taskbar", "Play sound", "Regex"});
|
||||||
// fourtf: could crash
|
view->getTableView()->horizontalHeader()->setSectionResizeMode(QHeaderView::Fixed);
|
||||||
for (const messages::HighlightPhrase &phrase :
|
|
||||||
app->settings->highlightProperties.getValue()) {
|
|
||||||
model->appendRow({util::stringItem(phrase.key), util::boolItem(phrase.alert),
|
|
||||||
util::boolItem(phrase.sound), util::boolItem(phrase.regex)});
|
|
||||||
}
|
|
||||||
|
|
||||||
// fourtf: make class extrend BaseWidget and add this to dpiChanged
|
// fourtf: make class extrend BaseWidget and add this to dpiChanged
|
||||||
QTimer::singleShot(1, [view] {
|
QTimer::singleShot(1, [view] {
|
||||||
view->resizeColumnsToContents();
|
view->getTableView()->resizeColumnsToContents();
|
||||||
view->setColumnWidth(0, 250);
|
view->getTableView()->setColumnWidth(0, 250);
|
||||||
});
|
});
|
||||||
|
|
||||||
auto buttons = highlights.emplace<QHBoxLayout>().withoutMargin();
|
view->addButtonPressed.connect([] {
|
||||||
|
getApp()->highlights->phrases.appendItem(
|
||||||
QObject::connect(
|
controllers::highlights::HighlightPhrase{"my phrase", true, false, false});
|
||||||
model, &QStandardItemModel::dataChanged,
|
|
||||||
[model, app](const QModelIndex &topLeft, const QModelIndex &bottomRight,
|
|
||||||
const QVector<int> &roles) {
|
|
||||||
std::vector<messages::HighlightPhrase> phrases;
|
|
||||||
for (int i = 1; i < model->rowCount(); i++) {
|
|
||||||
phrases.push_back(messages::HighlightPhrase{
|
|
||||||
model->item(i, 0)->data(Qt::DisplayRole).toString(),
|
|
||||||
model->item(i, 1)->data(Qt::CheckStateRole).toBool(),
|
|
||||||
model->item(i, 2)->data(Qt::CheckStateRole).toBool(),
|
|
||||||
model->item(i, 3)->data(Qt::CheckStateRole).toBool()});
|
|
||||||
}
|
|
||||||
app->settings->highlightProperties.setValue(phrases);
|
|
||||||
app->settings->enableHighlightsSelf.setValue(
|
|
||||||
model->item(0, 0)->data(Qt::CheckStateRole).toBool());
|
|
||||||
app->settings->enableHighlightTaskbar.setValue(
|
|
||||||
model->item(0, 1)->data(Qt::CheckStateRole).toBool());
|
|
||||||
app->settings->enableHighlightSound.setValue(
|
|
||||||
model->item(0, 2)->data(Qt::CheckStateRole).toBool());
|
|
||||||
});
|
|
||||||
|
|
||||||
auto add = buttons.emplace<QPushButton>("Add");
|
|
||||||
QObject::connect(*add, &QPushButton::clicked, [model, view] {
|
|
||||||
model->appendRow({util::stringItem(""),
|
|
||||||
util::boolItem(model->item(model->rowCount() - 1, 1)
|
|
||||||
->data(Qt::CheckStateRole)
|
|
||||||
.toBool()),
|
|
||||||
util::boolItem(model->item(model->rowCount() - 1, 2)
|
|
||||||
->data(Qt::CheckStateRole)
|
|
||||||
.toBool()),
|
|
||||||
util::boolItem(false)});
|
|
||||||
view->scrollToBottom();
|
|
||||||
});
|
});
|
||||||
auto remove = buttons.emplace<QPushButton>("Remove");
|
|
||||||
QObject::connect(*remove, &QPushButton::clicked, [view, model] {
|
|
||||||
std::vector<int> indices;
|
|
||||||
|
|
||||||
for (const QModelIndex &index : view->selectionModel()->selectedRows(0)) {
|
|
||||||
indices.push_back(index.row());
|
|
||||||
}
|
|
||||||
|
|
||||||
std::sort(indices.begin(), indices.end());
|
|
||||||
|
|
||||||
for (int i = indices.size() - 1; i >= 0; i--) {
|
|
||||||
model->removeRow(indices[i]);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
buttons->addStretch(1);
|
|
||||||
|
|
||||||
view->hideColumn(3);
|
|
||||||
}
|
}
|
||||||
auto disabledUsers = tabs.appendTab(new QVBoxLayout, "Disabled Users");
|
auto disabledUsers = tabs.appendTab(new QVBoxLayout, "Disabled Users");
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue