mirror of
https://github.com/Chatterino/chatterino2.git
synced 2024-11-13 19:49:51 +01:00
refactored the settings dialog
This commit is contained in:
parent
4cbc3b8b61
commit
e0bb061c81
|
@ -116,7 +116,17 @@ SOURCES += \
|
|||
src/messages/image.cpp \
|
||||
src/messages/layouts/messagelayout.cpp \
|
||||
src/messages/layouts/messagelayoutelement.cpp \
|
||||
src/messages/layouts/messagelayoutcontainer.cpp
|
||||
src/messages/layouts/messagelayoutcontainer.cpp \
|
||||
src/widgets/settingspages/appearancepage.cpp \
|
||||
src/widgets/settingspages/settingspage.cpp \
|
||||
src/widgets/settingspages/behaviourpage.cpp \
|
||||
src/widgets/settingspages/commandpage.cpp \
|
||||
src/widgets/settingspages/emotespage.cpp \
|
||||
src/widgets/settingspages/highlightingpage.cpp \
|
||||
src/widgets/settingspages/accountspage.cpp \
|
||||
src/widgets/settingspages/aboutpage.cpp \
|
||||
src/widgets/settingspages/moderationpage.cpp \
|
||||
src/widgets/settingspages/logspage.cpp
|
||||
|
||||
HEADERS += \
|
||||
src/precompiled_headers.hpp \
|
||||
|
@ -203,7 +213,18 @@ HEADERS += \
|
|||
src/messages/layouts/messagelayout.hpp \
|
||||
src/messages/layouts/messagelayoutelement.hpp \
|
||||
src/messages/layouts/messagelayoutcontainer.hpp \
|
||||
src/util/property.hpp
|
||||
src/util/property.hpp \
|
||||
src/widgets/settingspages/appearancepage.hpp \
|
||||
src/widgets/settingspages/settingspage.hpp \
|
||||
src/util/layoutcreator.hpp \
|
||||
src/widgets/settingspages/behaviourpage.hpp \
|
||||
src/widgets/settingspages/commandpage.hpp \
|
||||
src/widgets/settingspages/emotespage.hpp \
|
||||
src/widgets/settingspages/highlightingpage.hpp \
|
||||
src/widgets/settingspages/accountspage.hpp \
|
||||
src/widgets/settingspages/aboutpage.hpp \
|
||||
src/widgets/settingspages/moderationpage.hpp \
|
||||
src/widgets/settingspages/logspage.hpp
|
||||
|
||||
|
||||
PRECOMPILED_HEADER =
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
../.clang-format
|
|
@ -1 +0,0 @@
|
|||
../.clang-format
|
|
@ -1 +0,0 @@
|
|||
../.clang-format
|
|
@ -213,23 +213,25 @@ TimestampElement::~TimestampElement()
|
|||
void TimestampElement::addToContainer(MessageLayoutContainer &container,
|
||||
MessageElement::Flags _flags)
|
||||
{
|
||||
if (singletons::SettingManager::getInstance().timestampFormat != this->format) {
|
||||
this->format = singletons::SettingManager::getInstance().timestampFormat;
|
||||
delete this->element;
|
||||
this->element = TimestampElement::formatTime(this->time);
|
||||
}
|
||||
|
||||
this->element->addToContainer(container, _flags);
|
||||
}
|
||||
|
||||
void TimestampElement::update(UpdateFlags _flags)
|
||||
{
|
||||
if (_flags == UpdateFlags::Update_All) {
|
||||
this->element = TimestampElement::formatTime(this->time);
|
||||
} else {
|
||||
this->element->update(_flags);
|
||||
}
|
||||
}
|
||||
|
||||
TextElement *TimestampElement::formatTime(const QTime &time)
|
||||
{
|
||||
QString text = time.toString(singletons::SettingManager::getInstance().timestampFormat);
|
||||
QString format = time.toString(singletons::SettingManager::getInstance().timestampFormat);
|
||||
|
||||
return new TextElement(text, Flags::Timestamp, MessageColor::System, FontStyle::Medium);
|
||||
return new TextElement(format, Flags::Timestamp, MessageColor::System, FontStyle::Medium);
|
||||
}
|
||||
|
||||
// TWITCH MODERATION
|
||||
|
|
|
@ -189,6 +189,7 @@ class TimestampElement : public MessageElement
|
|||
{
|
||||
QTime time;
|
||||
TextElement *element;
|
||||
QString format;
|
||||
|
||||
public:
|
||||
TimestampElement();
|
||||
|
|
|
@ -49,8 +49,8 @@ public:
|
|||
BoolSetting allowDuplicateMessages = {"/behaviour/allowDuplicateMessages", true};
|
||||
BoolSetting mentionUsersWithAt = {"/behaviour/mentionUsersWithAt", false};
|
||||
FloatSetting mouseScrollMultiplier = {"/behaviour/mouseScrollMultiplier", 1.0};
|
||||
StringSetting streamlinkPath = {"/behaviour/streamlink/path", ""};
|
||||
StringSetting preferredQuality = {"/behaviour/streamlink/quality", "Choose"};
|
||||
QStringSetting streamlinkPath = {"/behaviour/streamlink/path", ""};
|
||||
QStringSetting preferredQuality = {"/behaviour/streamlink/quality", "Choose"};
|
||||
BoolSetting pauseChatHover = {"/behaviour/pauseChatHover", false};
|
||||
|
||||
/// Commands
|
||||
|
|
|
@ -11,7 +11,7 @@ namespace singletons {
|
|||
|
||||
namespace detail {
|
||||
|
||||
double getMultiplierByTheme(const std::string &themeName)
|
||||
double getMultiplierByTheme(const QString &themeName)
|
||||
{
|
||||
if (themeName == "Light") {
|
||||
return 0.8;
|
||||
|
@ -46,7 +46,7 @@ ThemeManager::ThemeManager()
|
|||
|
||||
void ThemeManager::update()
|
||||
{
|
||||
this->actuallyUpdate(this->themeHue, detail::getMultiplierByTheme(this->themeName));
|
||||
this->actuallyUpdate(this->themeHue, detail::getMultiplierByTheme(this->themeName.getValue()));
|
||||
}
|
||||
|
||||
// hue: theme color (0 - 1)
|
||||
|
@ -157,9 +157,9 @@ void ThemeManager::normalizeColor(QColor &color)
|
|||
}
|
||||
|
||||
if (color.lightnessF() > 0.4f && color.hueF() > 0.1 && color.hueF() < 0.33333) {
|
||||
color.setHslF(color.hueF(), color.saturationF(),
|
||||
color.lightnessF() -
|
||||
sin((color.hueF() - 0.1) / (0.3333 - 0.1) * 3.14159) *
|
||||
color.setHslF(
|
||||
color.hueF(), color.saturationF(),
|
||||
color.lightnessF() - sin((color.hueF() - 0.1) / (0.3333 - 0.1) * 3.14159) *
|
||||
color.saturationF() * 0.2);
|
||||
}
|
||||
} else {
|
||||
|
@ -168,13 +168,13 @@ void ThemeManager::normalizeColor(QColor &color)
|
|||
}
|
||||
|
||||
if (color.lightnessF() < 0.6f && color.hueF() > 0.54444 && color.hueF() < 0.83333) {
|
||||
color.setHslF(color.hueF(), color.saturationF(),
|
||||
color.lightnessF() +
|
||||
sin((color.hueF() - 0.54444) / (0.8333 - 0.54444) * 3.14159) *
|
||||
color.setHslF(
|
||||
color.hueF(), color.saturationF(),
|
||||
color.lightnessF() + sin((color.hueF() - 0.54444) / (0.8333 - 0.54444) * 3.14159) *
|
||||
color.saturationF() * 0.4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace singletons
|
||||
} // namespace chatterino
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <QColor>
|
||||
#include <boost/signals2.hpp>
|
||||
#include <pajlada/settings/setting.hpp>
|
||||
#include <util/serialize-custom.hpp>
|
||||
|
||||
namespace chatterino {
|
||||
namespace singletons {
|
||||
|
@ -102,10 +103,10 @@ public:
|
|||
|
||||
boost::signals2::signal<void()> updated;
|
||||
|
||||
private:
|
||||
pajlada::Settings::Setting<std::string> themeName;
|
||||
pajlada::Settings::Setting<QString> themeName;
|
||||
pajlada::Settings::Setting<double> themeHue;
|
||||
|
||||
private:
|
||||
void actuallyUpdate(double hue, double multiplier);
|
||||
QColor blendColors(const QColor &color1, const QColor &color2, qreal ratio);
|
||||
|
||||
|
@ -122,5 +123,5 @@ private:
|
|||
friend class WindowManager;
|
||||
};
|
||||
|
||||
} // namespace singletons
|
||||
} // namespace chatterino
|
||||
}
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
../.clang-format
|
|
@ -1 +0,0 @@
|
|||
../.clang-format
|
103
src/util/layoutcreator.hpp
Normal file
103
src/util/layoutcreator.hpp
Normal file
|
@ -0,0 +1,103 @@
|
|||
#pragma once
|
||||
|
||||
#include <QHBoxLayout>
|
||||
#include <QWidget>
|
||||
|
||||
#include <cassert>
|
||||
#include <type_traits>
|
||||
|
||||
namespace chatterino {
|
||||
namespace util {
|
||||
|
||||
template <class T>
|
||||
class LayoutCreator
|
||||
{
|
||||
public:
|
||||
LayoutCreator(T *_item)
|
||||
: item(_item)
|
||||
{
|
||||
}
|
||||
|
||||
T *operator->()
|
||||
{
|
||||
return this->item;
|
||||
}
|
||||
|
||||
T *getElement()
|
||||
{
|
||||
return this->item;
|
||||
}
|
||||
|
||||
template <typename T2>
|
||||
LayoutCreator<T2> append(T2 *_item)
|
||||
{
|
||||
this->_addItem(this->getOrCreateLayout(), _item);
|
||||
|
||||
return LayoutCreator<T2>(_item);
|
||||
}
|
||||
|
||||
template <typename T2, typename... Args>
|
||||
LayoutCreator<T2> emplace(Args &&... args)
|
||||
{
|
||||
T2 *t = new T2(std::forward<Args>(args)...);
|
||||
|
||||
this->_addItem(this->getOrCreateLayout(), t);
|
||||
|
||||
return LayoutCreator<T2>(t);
|
||||
}
|
||||
|
||||
LayoutCreator<T> assign(T **ptr)
|
||||
{
|
||||
*ptr = this->item;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename Q = T,
|
||||
typename std::enable_if<std::is_base_of<QLayout, Q>::value, int>::type = 0>
|
||||
LayoutCreator<T> withoutMargin()
|
||||
{
|
||||
this->item->setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
T *item;
|
||||
|
||||
template <typename T2,
|
||||
typename std::enable_if<std::is_base_of<QWidget, T2>::value, int>::type = 0>
|
||||
void _addItem(QLayout *layout, T2 *item)
|
||||
{
|
||||
layout->addWidget(item);
|
||||
}
|
||||
|
||||
template <typename T2,
|
||||
typename std::enable_if<std::is_base_of<QLayout, T2>::value, int>::type = 0>
|
||||
void _addItem(QLayout *layout, T2 *item)
|
||||
{
|
||||
QWidget *widget = new QWidget();
|
||||
widget->setLayout(item);
|
||||
layout->addWidget(widget);
|
||||
}
|
||||
|
||||
template <typename Q = T,
|
||||
typename std::enable_if<std::is_base_of<QLayout, Q>::value, int>::type = 0>
|
||||
QLayout *getOrCreateLayout()
|
||||
{
|
||||
return this->item;
|
||||
}
|
||||
|
||||
template <typename Q = T,
|
||||
typename std::enable_if<std::is_base_of<QWidget, Q>::value, int>::type = 0>
|
||||
QLayout *getOrCreateLayout()
|
||||
{
|
||||
if (!this->item->layout()) {
|
||||
this->item->setLayout(new QHBoxLayout());
|
||||
}
|
||||
|
||||
return this->item->layout();
|
||||
}
|
||||
};
|
||||
} // namespace util
|
||||
} // namespace chatterino
|
|
@ -1 +0,0 @@
|
|||
../.clang-format
|
|
@ -1 +0,0 @@
|
|||
../.clang-format
|
|
@ -7,11 +7,12 @@
|
|||
namespace chatterino {
|
||||
namespace widgets {
|
||||
|
||||
SettingsDialogTab::SettingsDialogTab(SettingsDialog *_dialog, QString _labelText,
|
||||
SettingsDialogTab::SettingsDialogTab(SettingsDialog *_dialog, settingspages::SettingsPage *_page,
|
||||
QString imageFileName)
|
||||
: dialog(_dialog)
|
||||
, page(_page)
|
||||
{
|
||||
this->ui.labelText = _labelText;
|
||||
this->ui.labelText = page->getName();
|
||||
this->ui.icon.addFile(imageFileName);
|
||||
|
||||
this->setCursor(QCursor(Qt::PointingHandCursor));
|
||||
|
@ -31,14 +32,9 @@ void SettingsDialogTab::setSelected(bool _selected)
|
|||
emit selectedChanged(selected);
|
||||
}
|
||||
|
||||
QWidget *SettingsDialogTab::getWidget()
|
||||
settingspages::SettingsPage *SettingsDialogTab::getSettingsPage()
|
||||
{
|
||||
return this->ui.widget;
|
||||
}
|
||||
|
||||
void SettingsDialogTab::setWidget(QWidget *widget)
|
||||
{
|
||||
this->ui.widget = widget;
|
||||
return this->page;
|
||||
}
|
||||
|
||||
void SettingsDialogTab::paintEvent(QPaintEvent *)
|
||||
|
@ -53,7 +49,6 @@ void SettingsDialogTab::paintEvent(QPaintEvent *)
|
|||
int a = (this->height() - 20) / 2;
|
||||
QPixmap pixmap = this->ui.icon.pixmap(QSize(20, 20));
|
||||
|
||||
|
||||
painter.drawPixmap(0, a, pixmap);
|
||||
|
||||
a = a + a + 20;
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
#pragma once
|
||||
|
||||
#include <QIcon>
|
||||
#include <QPaintEvent>
|
||||
#include <QWidget>
|
||||
#include <QIcon>
|
||||
|
||||
namespace chatterino {
|
||||
namespace widgets {
|
||||
namespace settingspages {
|
||||
class SettingsPage;
|
||||
}
|
||||
|
||||
class SettingsDialog;
|
||||
|
||||
|
@ -14,11 +17,11 @@ class SettingsDialogTab : public QWidget
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
SettingsDialogTab(SettingsDialog *dialog, QString _label, QString imageFileName);
|
||||
SettingsDialogTab(SettingsDialog *dialog, settingspages::SettingsPage *page,
|
||||
QString imageFileName);
|
||||
|
||||
void setSelected(bool selected);
|
||||
QWidget *getWidget();
|
||||
void setWidget(QWidget *widget);
|
||||
settingspages::SettingsPage *getSettingsPage();
|
||||
|
||||
signals:
|
||||
void selectedChanged(bool);
|
||||
|
@ -28,13 +31,13 @@ private:
|
|||
void mousePressEvent(QMouseEvent *event);
|
||||
|
||||
struct {
|
||||
QWidget *widget;
|
||||
QString labelText;
|
||||
QIcon icon;
|
||||
} ui;
|
||||
|
||||
// Parent settings dialog
|
||||
SettingsDialog *dialog;
|
||||
settingspages::SettingsPage *page;
|
||||
|
||||
bool selected = false;
|
||||
};
|
||||
|
|
|
@ -6,8 +6,18 @@
|
|||
#include "singletons/windowmanager.hpp"
|
||||
#include "twitch/twitchmessagebuilder.hpp"
|
||||
#include "twitch/twitchuser.hpp"
|
||||
#include "util/layoutcreator.hpp"
|
||||
#include "widgets/helper/settingsdialogtab.hpp"
|
||||
#include "widgets/logindialog.hpp"
|
||||
#include "widgets/settingspages/aboutpage.hpp"
|
||||
#include "widgets/settingspages/accountspage.hpp"
|
||||
#include "widgets/settingspages/appearancepage.hpp"
|
||||
#include "widgets/settingspages/behaviourpage.hpp"
|
||||
#include "widgets/settingspages/commandpage.hpp"
|
||||
#include "widgets/settingspages/emotespage.hpp"
|
||||
#include "widgets/settingspages/highlightingpage.hpp"
|
||||
#include "widgets/settingspages/logspage.hpp"
|
||||
#include "widgets/settingspages/moderationpage.hpp"
|
||||
|
||||
#include <QComboBox>
|
||||
#include <QDebug>
|
||||
|
@ -33,50 +43,53 @@ SettingsDialog *SettingsDialog::handle = nullptr;
|
|||
|
||||
SettingsDialog::SettingsDialog()
|
||||
: BaseWidget()
|
||||
, usernameDisplayMode(
|
||||
"/appearance/messages/usernameDisplayMode",
|
||||
twitch::TwitchMessageBuilder::UsernameDisplayMode::UsernameAndLocalizedName)
|
||||
{
|
||||
this->initAsWindow();
|
||||
|
||||
QPalette palette;
|
||||
palette.setColor(QPalette::Background, QColor("#444"));
|
||||
this->setPalette(palette);
|
||||
|
||||
this->ui.pageStack.setObjectName("pages");
|
||||
|
||||
this->setLayout(&this->ui.vbox);
|
||||
|
||||
this->ui.vbox.addLayout(&this->ui.hbox);
|
||||
|
||||
this->ui.vbox.addWidget(&this->ui.buttonBox);
|
||||
|
||||
auto tabWidget = &ui.tabWidget;
|
||||
tabWidget->setObjectName("tabWidget");
|
||||
|
||||
tabWidget->setLayout(&this->ui.tabs);
|
||||
|
||||
this->ui.hbox.addWidget(tabWidget);
|
||||
this->ui.hbox.addLayout(&this->ui.pageStack);
|
||||
|
||||
this->ui.buttonBox.addButton(&this->ui.okButton, QDialogButtonBox::ButtonRole::AcceptRole);
|
||||
this->ui.buttonBox.addButton(&this->ui.cancelButton, QDialogButtonBox::ButtonRole::RejectRole);
|
||||
|
||||
QObject::connect(&this->ui.okButton, &QPushButton::clicked, this,
|
||||
&SettingsDialog::okButtonClicked);
|
||||
QObject::connect(&this->ui.cancelButton, &QPushButton::clicked, this,
|
||||
&SettingsDialog::cancelButtonClicked);
|
||||
|
||||
this->ui.okButton.setText("OK");
|
||||
this->ui.cancelButton.setText("Cancel");
|
||||
|
||||
this->resize(600, 500);
|
||||
this->initUi();
|
||||
|
||||
this->addTabs();
|
||||
|
||||
this->dpiMultiplierChanged(this->getDpiMultiplier(), this->getDpiMultiplier());
|
||||
}
|
||||
|
||||
void SettingsDialog::initUi()
|
||||
{
|
||||
util::LayoutCreator<SettingsDialog> layoutCreator(this);
|
||||
|
||||
// tab pages
|
||||
layoutCreator.emplace<QWidget>()
|
||||
.assign(&this->ui.tabContainerContainer)
|
||||
.emplace<QVBoxLayout>()
|
||||
.withoutMargin()
|
||||
.assign(&this->ui.tabContainer);
|
||||
|
||||
// right side layout
|
||||
auto right = layoutCreator.emplace<QVBoxLayout>();
|
||||
{
|
||||
right.emplace<QStackedLayout>().assign(&this->ui.pageStack).emplace<QPushButton>("NaM");
|
||||
|
||||
auto buttons = right.emplace<QDialogButtonBox>(Qt::Horizontal);
|
||||
{
|
||||
this->ui.okButton = buttons->addButton("Ok", QDialogButtonBox::YesRole);
|
||||
this->ui.cancelButton = buttons->addButton("Cancel", QDialogButtonBox::NoRole);
|
||||
}
|
||||
}
|
||||
|
||||
// ---- misc
|
||||
QPalette palette;
|
||||
palette.setColor(QPalette::Background, QColor("#444"));
|
||||
this->setPalette(palette);
|
||||
|
||||
this->ui.tabContainerContainer->setObjectName("tabWidget");
|
||||
this->ui.pageStack->setObjectName("pages");
|
||||
|
||||
QObject::connect(this->ui.okButton, &QPushButton::clicked, this,
|
||||
&SettingsDialog::okButtonClicked);
|
||||
QObject::connect(this->ui.cancelButton, &QPushButton::clicked, this,
|
||||
&SettingsDialog::cancelButtonClicked);
|
||||
}
|
||||
|
||||
SettingsDialog *SettingsDialog::getHandle()
|
||||
{
|
||||
return SettingsDialog::handle;
|
||||
|
@ -84,682 +97,34 @@ SettingsDialog *SettingsDialog::getHandle()
|
|||
|
||||
void SettingsDialog::addTabs()
|
||||
{
|
||||
this->addTab(this->createAccountsTab(), "Accounts", ":/images/accounts.svg");
|
||||
|
||||
this->addTab(this->createAppearanceTab(), "Appearance", ":/images/theme.svg");
|
||||
|
||||
this->addTab(this->createBehaviourTab(), "Behaviour", ":/images/behave.svg");
|
||||
|
||||
this->addTab(this->createCommandsTab(), "Commands", ":/images/commands.svg");
|
||||
|
||||
this->addTab(this->createEmotesTab(), "Emotes", ":/images/emote.svg");
|
||||
|
||||
// this->addTab(this->createIgnoredUsersTab(), "Ignored Users",
|
||||
// ":/images/StatusAnnotations_Blocked_16xLG_color.png");
|
||||
|
||||
// this->addTab(this->createIgnoredMessagesTab(), "Ignored Messages",
|
||||
// ":/images/Filter_16x.png");
|
||||
|
||||
// this->addTab(this->createLinksTab(), "Links", ":/images/VSO_Link_blue_16x.png");
|
||||
|
||||
// this->addTab(this->createLogsTab(), "Logs", ":/images/VSO_Link_blue_16x.png");
|
||||
|
||||
this->addTab(this->createHighlightingTab(), "Highlighting", ":/images/notifications.svg");
|
||||
|
||||
// this->addTab(this->createWhispersTab(), "Whispers", ":/images/Message_16xLG.png");
|
||||
|
||||
this->addTab(this->createAboutTab(), "About", ":/images/about.svg");
|
||||
|
||||
// Add stretch
|
||||
this->ui.tabs.addStretch(1);
|
||||
this->addTab(new settingspages::AccountsPage);
|
||||
this->addTab(new settingspages::AppearancePage);
|
||||
this->addTab(new settingspages::BehaviourPage);
|
||||
this->addTab(new settingspages::CommandPage);
|
||||
this->addTab(new settingspages::EmotesPage);
|
||||
// this->addTab(new settingspages::HighlightingPage);
|
||||
// this->addTab(new settingspages::LogsPage);
|
||||
// this->addTab(new settingspages::ModerationPage);
|
||||
this->ui.tabContainer->addStretch(1);
|
||||
this->addTab(new settingspages::AboutPage, Qt::AlignBottom);
|
||||
}
|
||||
|
||||
QVBoxLayout *SettingsDialog::createAccountsTab()
|
||||
void SettingsDialog::addTab(settingspages::SettingsPage *page, Qt::Alignment alignment)
|
||||
{
|
||||
auto layout = new QVBoxLayout();
|
||||
auto tab = new SettingsDialogTab(this, page, "xD");
|
||||
|
||||
// add remove buttons
|
||||
auto buttonBox = new QDialogButtonBox(this);
|
||||
this->ui.pageStack->addWidget(page);
|
||||
this->ui.tabContainer->addWidget(tab, 0, alignment);
|
||||
this->tabs.push_back(tab);
|
||||
|
||||
auto addButton = new QPushButton("Add", this);
|
||||
addButton->setToolTip("Log in with a new account");
|
||||
|
||||
auto removeButton = new QPushButton("Remove", this);
|
||||
removeButton->setToolTip("Remove selected account");
|
||||
|
||||
connect(addButton, &QPushButton::clicked, []() {
|
||||
static auto loginWidget = new LoginWidget();
|
||||
loginWidget->show();
|
||||
});
|
||||
|
||||
buttonBox->addButton(addButton, QDialogButtonBox::YesRole);
|
||||
buttonBox->addButton(removeButton, QDialogButtonBox::NoRole);
|
||||
|
||||
layout->addWidget(buttonBox);
|
||||
|
||||
this->ui.accountSwitchWidget = new AccountSwitchWidget(this);
|
||||
|
||||
connect(removeButton, &QPushButton::clicked, [this]() {
|
||||
auto selectedUser = this->ui.accountSwitchWidget->currentItem()->text();
|
||||
if (selectedUser == ANONYMOUS_USERNAME_LABEL) {
|
||||
// Do nothing
|
||||
return;
|
||||
}
|
||||
|
||||
singletons::AccountManager::getInstance().Twitch.removeUser(selectedUser);
|
||||
});
|
||||
|
||||
layout->addWidget(this->ui.accountSwitchWidget);
|
||||
|
||||
return layout;
|
||||
}
|
||||
|
||||
QVBoxLayout *SettingsDialog::createAppearanceTab()
|
||||
{
|
||||
auto &settings = singletons::SettingManager::getInstance();
|
||||
auto layout = this->createTabLayout();
|
||||
|
||||
{
|
||||
auto group = new QGroupBox("Application");
|
||||
|
||||
auto form = new QFormLayout();
|
||||
auto combo = new QComboBox();
|
||||
|
||||
auto fontLayout = new QHBoxLayout();
|
||||
auto fontFamilyLabel = new QLabel("font family, size");
|
||||
auto fontButton = new QPushButton("Select");
|
||||
|
||||
fontLayout->addWidget(fontButton);
|
||||
fontLayout->addWidget(fontFamilyLabel);
|
||||
|
||||
{
|
||||
auto &fontManager = singletons::FontManager::getInstance();
|
||||
|
||||
auto UpdateFontFamilyLabel = [fontFamilyLabel, &fontManager](auto) {
|
||||
fontFamilyLabel->setText(
|
||||
QString::fromStdString(fontManager.currentFontFamily.getValue()) + ", " +
|
||||
QString::number(fontManager.currentFontSize) + "pt");
|
||||
};
|
||||
|
||||
fontManager.currentFontFamily.connectSimple(UpdateFontFamilyLabel,
|
||||
this->managedConnections);
|
||||
fontManager.currentFontSize.connectSimple(UpdateFontFamilyLabel,
|
||||
this->managedConnections);
|
||||
}
|
||||
|
||||
fontButton->connect(fontButton, &QPushButton::clicked, []() {
|
||||
auto &fontManager = singletons::FontManager::getInstance();
|
||||
QFontDialog dialog(fontManager.getFont(singletons::FontManager::Medium, 1.));
|
||||
|
||||
dialog.connect(&dialog, &QFontDialog::fontSelected, [](const QFont &font) {
|
||||
auto &fontManager = singletons::FontManager::getInstance();
|
||||
fontManager.currentFontFamily = font.family().toStdString();
|
||||
fontManager.currentFontSize = font.pointSize();
|
||||
});
|
||||
|
||||
dialog.show();
|
||||
dialog.exec();
|
||||
});
|
||||
|
||||
auto compactTabs = createCheckbox("Hide tab X", settings.hideTabX);
|
||||
auto hidePreferencesButton = createCheckbox("Hide preferences button (ctrl+p to show)",
|
||||
settings.hidePreferencesButton);
|
||||
auto hideUserButton = createCheckbox("Hide user button", settings.hideUserButton);
|
||||
|
||||
form->addRow("Theme:", combo);
|
||||
|
||||
{
|
||||
auto hbox = new QHBoxLayout();
|
||||
|
||||
auto slider = new QSlider(Qt::Horizontal);
|
||||
// Theme hue
|
||||
slider->setMinimum(0);
|
||||
slider->setMaximum(1000);
|
||||
|
||||
pajlada::Settings::Setting<double> themeHue("/appearance/theme/hue");
|
||||
|
||||
slider->setValue(std::min(std::max(themeHue.getValue(), 0.0), 1.0) * 1000);
|
||||
|
||||
hbox->addWidget(slider);
|
||||
|
||||
auto button = new QPushButton();
|
||||
button->setFlat(true);
|
||||
|
||||
hbox->addWidget(button);
|
||||
|
||||
form->addRow("Theme color:", hbox);
|
||||
|
||||
QObject::connect(slider, &QSlider::valueChanged, this, [button](int value) mutable {
|
||||
double newValue = value / 1000.0;
|
||||
pajlada::Settings::Setting<double> themeHue("/appearance/theme/hue");
|
||||
|
||||
themeHue.setValue(newValue);
|
||||
|
||||
QPalette pal = button->palette();
|
||||
QColor color;
|
||||
color.setHsvF(newValue, 1.0, 1.0, 1.0);
|
||||
pal.setColor(QPalette::Button, color);
|
||||
button->setAutoFillBackground(true);
|
||||
button->setPalette(pal);
|
||||
button->update();
|
||||
|
||||
// TODO(pajlada): re-implement
|
||||
// this->windowManager.updateAll();
|
||||
});
|
||||
}
|
||||
|
||||
form->addRow("Font:", fontLayout);
|
||||
form->addRow("Tab bar:", compactTabs);
|
||||
form->addRow("", hidePreferencesButton);
|
||||
form->addRow("", hideUserButton);
|
||||
|
||||
{
|
||||
// Theme name
|
||||
combo->addItems({
|
||||
"White", //
|
||||
"Light", //
|
||||
"Dark", //
|
||||
"Black", //
|
||||
});
|
||||
// combo->addItem("White");
|
||||
// combo->addItem("Light");
|
||||
// combo->addItem("Dark");
|
||||
// combo->addItem("Black");
|
||||
|
||||
QString currentComboText = QString::fromStdString(
|
||||
pajlada::Settings::Setting<std::string>::get("/appearance/theme/name"));
|
||||
|
||||
combo->setCurrentText(currentComboText);
|
||||
|
||||
QObject::connect(combo, &QComboBox::currentTextChanged, this, [](const QString &value) {
|
||||
// dirty hack
|
||||
singletons::EmoteManager::getInstance().incGeneration();
|
||||
pajlada::Settings::Setting<std::string>::set("/appearance/theme/name",
|
||||
value.toStdString());
|
||||
});
|
||||
}
|
||||
|
||||
auto enableSmoothScrolling =
|
||||
createCheckbox("Enable smooth scrolling", settings.enableSmoothScrolling);
|
||||
form->addRow("Scrolling:", enableSmoothScrolling);
|
||||
|
||||
auto enableSmoothScrollingNewMessages = createCheckbox(
|
||||
"Enable smooth scrolling for new messages", settings.enableSmoothScrollingNewMessages);
|
||||
form->addRow("", enableSmoothScrollingNewMessages);
|
||||
|
||||
group->setLayout(form);
|
||||
|
||||
layout->addWidget(group);
|
||||
}
|
||||
|
||||
{
|
||||
auto group = new QGroupBox("Messages");
|
||||
|
||||
auto v = new QVBoxLayout();
|
||||
v->addWidget(createCheckbox("Show timestamp", settings.showTimestamps));
|
||||
// fourtf: add timestamp format
|
||||
v->addWidget(createCheckbox("Show badges", settings.showBadges));
|
||||
v->addWidget(createCheckbox("Allow sending duplicate messages (add a space at the end)",
|
||||
settings.allowDuplicateMessages));
|
||||
v->addWidget(createCheckbox("Seperate messages", settings.seperateMessages));
|
||||
v->addWidget(createCheckbox("Show message length", settings.showMessageLength));
|
||||
v->addLayout(this->createCombobox(
|
||||
"Username display mode", this->usernameDisplayMode,
|
||||
{"Username (Localized name)", "Username", "Localized name"},
|
||||
[](const QString &newValue, pajlada::Settings::Setting<int> &setting) {
|
||||
if (newValue == "Username (Localized name)") {
|
||||
setting =
|
||||
twitch::TwitchMessageBuilder::UsernameDisplayMode::UsernameAndLocalizedName;
|
||||
} else if (newValue == "Username") {
|
||||
setting = twitch::TwitchMessageBuilder::UsernameDisplayMode::Username;
|
||||
} else if (newValue == "Localized name") {
|
||||
setting = twitch::TwitchMessageBuilder::UsernameDisplayMode::LocalizedName;
|
||||
}
|
||||
}));
|
||||
|
||||
group->setLayout(v);
|
||||
|
||||
layout->addWidget(group);
|
||||
}
|
||||
return layout;
|
||||
}
|
||||
|
||||
QVBoxLayout *SettingsDialog::createBehaviourTab()
|
||||
{
|
||||
singletons::SettingManager &settings = singletons::SettingManager::getInstance();
|
||||
auto layout = this->createTabLayout();
|
||||
|
||||
auto form = new QFormLayout();
|
||||
|
||||
// WINDOW
|
||||
{
|
||||
form->addRow("Window:", createCheckbox("Window always on top (requires restart)",
|
||||
settings.windowTopMost));
|
||||
// form->addRow("Messages:", createCheckbox("Mention users with a @ (except in
|
||||
// commands)",
|
||||
// settings.mentionUsersWithAt));
|
||||
}
|
||||
// MESSAGES
|
||||
{
|
||||
form->addRow("Messages:",
|
||||
createCheckbox("Hide input box if empty", settings.hideEmptyInput));
|
||||
form->addRow("", createCheckbox("Show last read message indicator",
|
||||
settings.showLastMessageIndicator));
|
||||
}
|
||||
// PAUSE
|
||||
{
|
||||
form->addRow("Pause chat:", createCheckbox("When hovering", settings.pauseChatHover));
|
||||
}
|
||||
// MOUSE SCROLL SPEED
|
||||
{
|
||||
auto scroll = new QSlider(Qt::Horizontal);
|
||||
form->addRow("Mouse scroll speed:", scroll);
|
||||
|
||||
float currentValue = singletons::SettingManager::getInstance().mouseScrollMultiplier;
|
||||
int scrollValue = ((currentValue - 0.1f) / 2.f) * 99.f;
|
||||
scroll->setValue(scrollValue);
|
||||
|
||||
connect(scroll, &QSlider::valueChanged, [](int newValue) {
|
||||
float mul = static_cast<float>(newValue) / 99.f;
|
||||
float newScrollValue = (mul * 2.1f) + 0.1f;
|
||||
singletons::SettingManager::getInstance().mouseScrollMultiplier = newScrollValue;
|
||||
});
|
||||
}
|
||||
// STREAMLINK
|
||||
{
|
||||
form->addRow("Streamlink path:", createLineEdit(settings.streamlinkPath));
|
||||
form->addRow(this->createCombobox(
|
||||
"Preferred quality:", settings.preferredQuality,
|
||||
{"Choose", "Source", "High", "Medium", "Low", "Audio only"},
|
||||
[](const QString &newValue, pajlada::Settings::Setting<std::string> &setting) {
|
||||
setting = newValue.toStdString();
|
||||
}));
|
||||
}
|
||||
|
||||
layout->addLayout(form);
|
||||
|
||||
return layout;
|
||||
}
|
||||
|
||||
QVBoxLayout *SettingsDialog::createCommandsTab()
|
||||
{
|
||||
singletons::CommandManager &commandManager = singletons::CommandManager::getInstance();
|
||||
|
||||
this->commandsTextChangedDelay.setSingleShot(true);
|
||||
|
||||
auto layout = this->createTabLayout();
|
||||
|
||||
layout->addWidget(new QLabel("One command per line."));
|
||||
layout->addWidget(new QLabel("\"/cmd example command\" will print "
|
||||
"\"example command\" when you type /cmd in chat."));
|
||||
layout->addWidget(new QLabel("{1} will be replaced with the first word you type after the "
|
||||
"command, {2} with the second and so on."));
|
||||
layout->addWidget(new QLabel("{1+} will be replaced with first word and everything after, {2+} "
|
||||
"with everything after the second word and so on"));
|
||||
layout->addWidget(new QLabel("Duplicate commands will be ignored."));
|
||||
|
||||
QTextEdit *textEdit = new QTextEdit();
|
||||
textEdit->setPlainText(QString(commandManager.getCommands().join('\n')));
|
||||
|
||||
layout->addWidget(textEdit);
|
||||
|
||||
QObject::connect(textEdit, &QTextEdit::textChanged,
|
||||
[this] { this->commandsTextChangedDelay.start(200); });
|
||||
|
||||
QObject::connect(&this->commandsTextChangedDelay, &QTimer::timeout,
|
||||
[textEdit, &commandManager] {
|
||||
QString text = textEdit->toPlainText();
|
||||
QStringList lines = text.split(QRegularExpression("(\r?\n|\r\n?)"));
|
||||
|
||||
commandManager.setCommands(lines);
|
||||
});
|
||||
|
||||
return layout;
|
||||
}
|
||||
|
||||
QVBoxLayout *SettingsDialog::createEmotesTab()
|
||||
{
|
||||
singletons::SettingManager &settings = singletons::SettingManager::getInstance();
|
||||
auto layout = this->createTabLayout();
|
||||
|
||||
layout->addWidget(createCheckbox("Enable Twitch Emotes", settings.enableTwitchEmotes));
|
||||
layout->addWidget(createCheckbox("Enable BetterTTV Emotes", settings.enableBttvEmotes));
|
||||
layout->addWidget(createCheckbox("Enable FrankerFaceZ Emotes", settings.enableFfzEmotes));
|
||||
layout->addWidget(createCheckbox("Enable Gif Emotes", settings.enableGifAnimations));
|
||||
layout->addWidget(createCheckbox("Enable Emojis", settings.enableEmojis));
|
||||
|
||||
layout->addWidget(createCheckbox("Enable Twitch Emotes", settings.enableTwitchEmotes));
|
||||
|
||||
// Preferred emote quality
|
||||
{
|
||||
auto box = new QHBoxLayout();
|
||||
auto label = new QLabel("Preferred emote quality");
|
||||
label->setToolTip("Select which emote quality you prefer to download");
|
||||
auto widget = new QComboBox();
|
||||
widget->addItems({"1x", "2x", "4x"});
|
||||
box->addWidget(label);
|
||||
box->addWidget(widget);
|
||||
|
||||
settings.preferredEmoteQuality.connect([widget](int newIndex, auto) {
|
||||
widget->setCurrentIndex(newIndex); //
|
||||
});
|
||||
|
||||
QObject::connect(
|
||||
widget, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [](int index) {
|
||||
singletons::SettingManager &settings = singletons::SettingManager::getInstance();
|
||||
settings.preferredEmoteQuality = index; //
|
||||
});
|
||||
|
||||
layout->addLayout(box);
|
||||
}
|
||||
|
||||
return layout;
|
||||
}
|
||||
|
||||
QVBoxLayout *SettingsDialog::createAboutTab()
|
||||
{
|
||||
auto layout = this->createTabLayout();
|
||||
QPixmap image;
|
||||
image.load(":/images/aboutlogo.png");
|
||||
|
||||
auto aboutimage = new QLabel();
|
||||
aboutimage->setPixmap(image.scaled(QSize(631, 132)));
|
||||
layout->addWidget(aboutimage);
|
||||
|
||||
auto created = new QLabel();
|
||||
created->setText("Twitch Chat Client created by <a href=\"github.com/fourtf\">fourtf</a>");
|
||||
created->setTextFormat(Qt::RichText);
|
||||
created->setTextInteractionFlags(Qt::TextBrowserInteraction);
|
||||
created->setOpenExternalLinks(true);
|
||||
layout->addWidget(created);
|
||||
|
||||
auto github = new QLabel();
|
||||
github->setText("<a href=\"github.com/fourt/chatterino2\">Chatterino on Github</a>");
|
||||
github->setTextFormat(Qt::RichText);
|
||||
github->setTextInteractionFlags(Qt::TextBrowserInteraction);
|
||||
github->setOpenExternalLinks(true);
|
||||
layout->addWidget(github);
|
||||
|
||||
return layout;
|
||||
}
|
||||
|
||||
QVBoxLayout *SettingsDialog::createIgnoredUsersTab()
|
||||
{
|
||||
auto layout = this->createTabLayout();
|
||||
|
||||
return layout;
|
||||
}
|
||||
|
||||
QVBoxLayout *SettingsDialog::createIgnoredMessagesTab()
|
||||
{
|
||||
auto layout = this->createTabLayout();
|
||||
|
||||
return layout;
|
||||
}
|
||||
|
||||
QVBoxLayout *SettingsDialog::createLinksTab()
|
||||
{
|
||||
auto layout = this->createTabLayout();
|
||||
|
||||
return layout;
|
||||
}
|
||||
|
||||
QVBoxLayout *SettingsDialog::createLogsTab()
|
||||
{
|
||||
auto layout = this->createTabLayout();
|
||||
|
||||
return layout;
|
||||
}
|
||||
|
||||
QVBoxLayout *SettingsDialog::createHighlightingTab()
|
||||
{
|
||||
singletons::SettingManager &settings = singletons::SettingManager::getInstance();
|
||||
auto layout = this->createTabLayout();
|
||||
|
||||
auto highlights = new QListWidget();
|
||||
auto highlightUserBlacklist = new QTextEdit();
|
||||
globalHighlights = highlights;
|
||||
const auto highlightProperties = settings.highlightProperties.getValue();
|
||||
for (const auto &highlightProperty : highlightProperties) {
|
||||
highlights->addItem(highlightProperty.key);
|
||||
}
|
||||
highlightUserBlacklist->setText(settings.highlightUserBlacklist);
|
||||
auto highlightTab = new QTabWidget();
|
||||
auto customSound = new QHBoxLayout();
|
||||
auto soundForm = new QFormLayout();
|
||||
{
|
||||
layout->addWidget(createCheckbox("Enable Highlighting", settings.enableHighlights));
|
||||
layout->addWidget(createCheckbox("Highlight messages containing your name",
|
||||
settings.enableHighlightsSelf));
|
||||
layout->addWidget(createCheckbox("Play sound when your name is mentioned",
|
||||
settings.enableHighlightSound));
|
||||
layout->addWidget(createCheckbox("Flash taskbar when your name is mentioned",
|
||||
settings.enableHighlightTaskbar));
|
||||
customSound->addWidget(createCheckbox("Custom sound", settings.customHighlightSound));
|
||||
auto selectBtn = new QPushButton("Select");
|
||||
QObject::connect(selectBtn, &QPushButton::clicked, this, [&settings, this] {
|
||||
auto fileName = QFileDialog::getOpenFileName(this, tr("Open Sound"), "",
|
||||
tr("Audio Files (*.mp3 *.wav)"));
|
||||
settings.pathHighlightSound = fileName;
|
||||
});
|
||||
customSound->addWidget(selectBtn);
|
||||
}
|
||||
|
||||
soundForm->addRow(customSound);
|
||||
|
||||
{
|
||||
auto hbox = new QHBoxLayout();
|
||||
auto addBtn = new QPushButton("Add");
|
||||
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);
|
||||
|
||||
auto edit = new QLineEdit();
|
||||
auto add = new QPushButton("Add");
|
||||
|
||||
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()) {
|
||||
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();
|
||||
}
|
||||
});
|
||||
box->addWidget(edit);
|
||||
box->addWidget(add);
|
||||
box->addWidget(sound);
|
||||
box->addWidget(task);
|
||||
show->setLayout(box);
|
||||
show->show();
|
||||
});
|
||||
|
||||
// Open "Edit selected highlight" dialog
|
||||
QObject::connect(editBtn, &QPushButton::clicked, this, [highlights, this, &settings] {
|
||||
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(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);
|
||||
|
||||
// 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(apply);
|
||||
box->addWidget(sound);
|
||||
box->addWidget(task);
|
||||
show->setLayout(box);
|
||||
show->show();
|
||||
});
|
||||
|
||||
// Delete selected highlight
|
||||
QObject::connect(delBtn, &QPushButton::clicked, this, [highlights, &settings] {
|
||||
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)",
|
||||
settings.highlightAlwaysPlaySound));
|
||||
auto layoutVbox = new QVBoxLayout();
|
||||
auto btnHbox = new QHBoxLayout();
|
||||
|
||||
auto highlightWidget = new QWidget();
|
||||
auto btnWidget = new QWidget();
|
||||
|
||||
btnHbox->addWidget(addBtn);
|
||||
btnHbox->addWidget(editBtn);
|
||||
btnHbox->addWidget(delBtn);
|
||||
btnWidget->setLayout(btnHbox);
|
||||
|
||||
layoutVbox->addWidget(highlights);
|
||||
layoutVbox->addWidget(btnWidget);
|
||||
highlightWidget->setLayout(layoutVbox);
|
||||
|
||||
highlightTab->addTab(highlightWidget, "Highlights");
|
||||
highlightTab->addTab(highlightUserBlacklist, "Disabled Users");
|
||||
layout->addWidget(highlightTab);
|
||||
|
||||
layout->addLayout(hbox);
|
||||
}
|
||||
|
||||
QObject::connect(&this->ui.okButton, &QPushButton::clicked, this, [=, &settings]() {
|
||||
QStringList list =
|
||||
highlightUserBlacklist->toPlainText().split("\n", QString::SkipEmptyParts);
|
||||
list.removeDuplicates();
|
||||
settings.highlightUserBlacklist = list.join("\n") + "\n";
|
||||
});
|
||||
|
||||
settings.highlightUserBlacklist.connect([=](const QString &str, auto) {
|
||||
highlightUserBlacklist->setPlainText(str); //
|
||||
});
|
||||
|
||||
return layout;
|
||||
}
|
||||
|
||||
QVBoxLayout *SettingsDialog::createWhispersTab()
|
||||
{
|
||||
auto layout = this->createTabLayout();
|
||||
|
||||
return layout;
|
||||
}
|
||||
|
||||
void SettingsDialog::addTab(QBoxLayout *layout, QString title, QString imageRes)
|
||||
{
|
||||
layout->addStretch(1);
|
||||
|
||||
auto widget = new QWidget();
|
||||
|
||||
widget->setLayout(layout);
|
||||
|
||||
auto tab = new SettingsDialogTab(this, title, imageRes);
|
||||
|
||||
tab->setWidget(widget);
|
||||
|
||||
this->ui.tabs.addWidget(tab, 0, Qt::AlignTop);
|
||||
tabs.push_back(tab);
|
||||
|
||||
this->ui.pageStack.addWidget(widget);
|
||||
|
||||
if (this->ui.tabs.count() == 1) {
|
||||
if (this->tabs.size() == 1) {
|
||||
this->select(tab);
|
||||
}
|
||||
}
|
||||
|
||||
void SettingsDialog::select(SettingsDialogTab *tab)
|
||||
{
|
||||
this->ui.pageStack.setCurrentWidget(tab->getWidget());
|
||||
this->ui.pageStack->setCurrentWidget(tab->getSettingsPage());
|
||||
|
||||
if (this->selectedTab != nullptr) {
|
||||
this->selectedTab->setSelected(false);
|
||||
|
@ -790,7 +155,7 @@ void SettingsDialog::showDialog(PreferredTab preferredTab)
|
|||
|
||||
void SettingsDialog::refresh()
|
||||
{
|
||||
this->ui.accountSwitchWidget->refresh();
|
||||
// this->ui.accountSwitchWidget->refresh();
|
||||
|
||||
singletons::SettingManager::getInstance().saveSnapshot();
|
||||
}
|
||||
|
@ -809,107 +174,32 @@ void SettingsDialog::dpiMultiplierChanged(float oldDpi, float newDpi)
|
|||
|
||||
this->setStyleSheet(styleSheet);
|
||||
|
||||
this->ui.tabWidget.setFixedWidth((int)(200 * newDpi));
|
||||
this->ui.tabContainerContainer->setFixedWidth((int)(200 * newDpi));
|
||||
}
|
||||
|
||||
void SettingsDialog::setChildrensFont(QLayout *object, QFont &font, int indent)
|
||||
{
|
||||
// for (QWidget *widget : this->widgets) {
|
||||
// widget->setFont(font);
|
||||
// }
|
||||
// for (int i = 0; i < object->count(); i++) {
|
||||
// if (object->itemAt(i)->layout()) {
|
||||
// setChildrensFont(object->layout()->itemAt(i)->layout(), font, indent + 2);
|
||||
// void SettingsDialog::setChildrensFont(QLayout *object, QFont &font, int indent)
|
||||
//{
|
||||
// // for (QWidget *widget : this->widgets) {
|
||||
// // widget->setFont(font);
|
||||
// // }
|
||||
// // for (int i = 0; i < object->count(); i++) {
|
||||
// // if (object->itemAt(i)->layout()) {
|
||||
// // setChildrensFont(object->layout()->itemAt(i)->layout(), font, indent + 2);
|
||||
// // }
|
||||
|
||||
// // if (object->itemAt(i)->widget()) {
|
||||
// // object->itemAt(i)->widget()->setFont(font);
|
||||
|
||||
// // if (object->itemAt(i)->widget()->layout() &&
|
||||
// // !object->itemAt(i)->widget()->layout()->isEmpty()) {
|
||||
// // setChildrensFont(object->itemAt(i)->widget()->layout(), font, indent +
|
||||
// 2);
|
||||
// // }
|
||||
// // }
|
||||
// // }
|
||||
//}
|
||||
|
||||
// if (object->itemAt(i)->widget()) {
|
||||
// object->itemAt(i)->widget()->setFont(font);
|
||||
|
||||
// if (object->itemAt(i)->widget()->layout() &&
|
||||
// !object->itemAt(i)->widget()->layout()->isEmpty()) {
|
||||
// setChildrensFont(object->itemAt(i)->widget()->layout(), font, indent + 2);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
/// Widget creation helpers
|
||||
QVBoxLayout *SettingsDialog::createTabLayout()
|
||||
{
|
||||
auto layout = new QVBoxLayout();
|
||||
|
||||
return layout;
|
||||
}
|
||||
|
||||
QCheckBox *SettingsDialog::createCheckbox(const QString &title,
|
||||
pajlada::Settings::Setting<bool> &setting)
|
||||
{
|
||||
auto checkbox = new QCheckBox(title);
|
||||
|
||||
// Set checkbox initial state
|
||||
setting.connect([checkbox](const bool &value, auto) {
|
||||
checkbox->setChecked(value); //
|
||||
});
|
||||
|
||||
QObject::connect(checkbox, &QCheckBox::toggled, this, [&setting](bool state) {
|
||||
qDebug() << "update checkbox value";
|
||||
setting = state; //
|
||||
});
|
||||
|
||||
return checkbox;
|
||||
}
|
||||
|
||||
QHBoxLayout *SettingsDialog::createCombobox(
|
||||
const QString &title, pajlada::Settings::Setting<int> &setting, QStringList items,
|
||||
std::function<void(QString, pajlada::Settings::Setting<int> &)> cb)
|
||||
{
|
||||
auto box = new QHBoxLayout();
|
||||
auto label = new QLabel(title);
|
||||
auto widget = new QComboBox();
|
||||
widget->addItems(items);
|
||||
|
||||
QObject::connect(widget, &QComboBox::currentTextChanged, this,
|
||||
[&setting, cb](const QString &newValue) {
|
||||
cb(newValue, setting); //
|
||||
});
|
||||
|
||||
box->addWidget(label);
|
||||
box->addWidget(widget);
|
||||
|
||||
return box;
|
||||
}
|
||||
|
||||
QHBoxLayout *SettingsDialog::createCombobox(
|
||||
const QString &title, pajlada::Settings::Setting<std::string> &setting, QStringList items,
|
||||
std::function<void(QString, pajlada::Settings::Setting<std::string> &)> cb)
|
||||
{
|
||||
auto box = new QHBoxLayout();
|
||||
auto label = new QLabel(title);
|
||||
auto widget = new QComboBox();
|
||||
widget->addItems(items);
|
||||
widget->setCurrentText(QString::fromStdString(setting.getValue()));
|
||||
|
||||
QObject::connect(widget, &QComboBox::currentTextChanged, this,
|
||||
[&setting, cb](const QString &newValue) {
|
||||
cb(newValue, setting); //
|
||||
});
|
||||
|
||||
box->addWidget(label);
|
||||
box->addWidget(widget);
|
||||
|
||||
return box;
|
||||
}
|
||||
|
||||
QLineEdit *SettingsDialog::createLineEdit(pajlada::Settings::Setting<std::string> &setting)
|
||||
{
|
||||
auto widget = new QLineEdit(QString::fromStdString(setting.getValue()));
|
||||
|
||||
QObject::connect(widget, &QLineEdit::textChanged, this,
|
||||
[&setting](const QString &newValue) { setting = newValue.toStdString(); });
|
||||
|
||||
return widget;
|
||||
}
|
||||
|
||||
///// Widget creation helpers
|
||||
void SettingsDialog::okButtonClicked()
|
||||
{
|
||||
this->close();
|
||||
|
@ -919,6 +209,10 @@ void SettingsDialog::cancelButtonClicked()
|
|||
{
|
||||
auto &settings = singletons::SettingManager::getInstance();
|
||||
|
||||
for (auto &tab : this->tabs) {
|
||||
tab->getSettingsPage()->cancel();
|
||||
}
|
||||
|
||||
settings.recallSnapshot();
|
||||
|
||||
this->close();
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include "singletons/settingsmanager.hpp"
|
||||
#include "widgets/accountswitchwidget.hpp"
|
||||
#include "widgets/helper/settingsdialogtab.hpp"
|
||||
#include "widgets/settingspages/appearancepage.hpp"
|
||||
|
||||
#include <QButtonGroup>
|
||||
#include <QCheckBox>
|
||||
|
@ -27,6 +28,7 @@ namespace widgets {
|
|||
|
||||
class SettingsDialog : public BaseWidget
|
||||
{
|
||||
public:
|
||||
SettingsDialog();
|
||||
|
||||
void select(SettingsDialogTab *tab);
|
||||
|
@ -50,62 +52,26 @@ private:
|
|||
void refresh();
|
||||
static SettingsDialog *handle;
|
||||
|
||||
std::vector<SettingsDialogTab *> tabs;
|
||||
|
||||
pajlada::Settings::Setting<int> usernameDisplayMode;
|
||||
QTimer commandsTextChangedDelay;
|
||||
|
||||
struct {
|
||||
QVBoxLayout tabs;
|
||||
QVBoxLayout vbox;
|
||||
QHBoxLayout hbox;
|
||||
QWidget tabWidget;
|
||||
QStackedLayout pageStack;
|
||||
QDialogButtonBox buttonBox;
|
||||
QPushButton okButton;
|
||||
QPushButton cancelButton;
|
||||
|
||||
AccountSwitchWidget *accountSwitchWidget = nullptr;
|
||||
QWidget *tabContainerContainer;
|
||||
QVBoxLayout *tabContainer;
|
||||
QStackedLayout *pageStack;
|
||||
QPushButton *okButton;
|
||||
QPushButton *cancelButton;
|
||||
} ui;
|
||||
|
||||
void addTab(QBoxLayout *layout, QString title, QString imageRes);
|
||||
void addTabs();
|
||||
std::vector<SettingsDialogTab *> tabs;
|
||||
|
||||
QVBoxLayout *createAccountsTab();
|
||||
QVBoxLayout *createAppearanceTab();
|
||||
QVBoxLayout *createMessagesTab();
|
||||
QVBoxLayout *createBehaviourTab();
|
||||
QVBoxLayout *createCommandsTab();
|
||||
QVBoxLayout *createEmotesTab();
|
||||
QVBoxLayout *createIgnoredUsersTab();
|
||||
QVBoxLayout *createIgnoredMessagesTab();
|
||||
QVBoxLayout *createLinksTab();
|
||||
QVBoxLayout *createLogsTab();
|
||||
QVBoxLayout *createHighlightingTab();
|
||||
QVBoxLayout *createWhispersTab();
|
||||
QVBoxLayout *createAboutTab();
|
||||
void initUi();
|
||||
void addTabs();
|
||||
void addTab(settingspages::SettingsPage *page, Qt::Alignment alignment = Qt::AlignTop);
|
||||
|
||||
SettingsDialogTab *selectedTab = nullptr;
|
||||
|
||||
QListWidget *globalHighlights;
|
||||
|
||||
/// Widget creation helpers
|
||||
QVBoxLayout *createTabLayout();
|
||||
QCheckBox *createCheckbox(const QString &title, pajlada::Settings::Setting<bool> &setting);
|
||||
QHBoxLayout *createCombobox(const QString &title, pajlada::Settings::Setting<int> &setting,
|
||||
QStringList items,
|
||||
std::function<void(QString, pajlada::Settings::Setting<int> &)> cb);
|
||||
QHBoxLayout *createCombobox(
|
||||
const QString &title, pajlada::Settings::Setting<std::string> &setting, QStringList items,
|
||||
std::function<void(QString, pajlada::Settings::Setting<std::string> &)> cb);
|
||||
QLineEdit *createLineEdit(pajlada::Settings::Setting<std::string> &setting);
|
||||
|
||||
void okButtonClicked();
|
||||
void cancelButtonClicked();
|
||||
|
||||
std::vector<pajlada::Signals::ScopedConnection> managedConnections;
|
||||
|
||||
static void setChildrensFont(QLayout *object, QFont &font, int indent = 0);
|
||||
// static void setChildrensFont(QLayout *object, QFont &font, int indent = 0);
|
||||
};
|
||||
|
||||
} // namespace widgets
|
||||
|
|
13
src/widgets/settingspages/aboutpage.cpp
Normal file
13
src/widgets/settingspages/aboutpage.cpp
Normal file
|
@ -0,0 +1,13 @@
|
|||
#include "aboutpage.hpp"
|
||||
|
||||
namespace chatterino {
|
||||
namespace widgets {
|
||||
namespace settingspages {
|
||||
|
||||
AboutPage::AboutPage()
|
||||
: SettingsPage("About", ":/images/about.svg")
|
||||
{
|
||||
}
|
||||
} // namespace settingspages
|
||||
} // namespace widgets
|
||||
} // namespace chatterino
|
16
src/widgets/settingspages/aboutpage.hpp
Normal file
16
src/widgets/settingspages/aboutpage.hpp
Normal file
|
@ -0,0 +1,16 @@
|
|||
#pragma once
|
||||
|
||||
#include "widgets/settingspages/settingspage.hpp"
|
||||
|
||||
namespace chatterino {
|
||||
namespace widgets {
|
||||
namespace settingspages {
|
||||
|
||||
class AboutPage : public SettingsPage
|
||||
{
|
||||
public:
|
||||
AboutPage();
|
||||
};
|
||||
} // namespace settingspages
|
||||
} // namespace widgets
|
||||
} // namespace chatterino
|
46
src/widgets/settingspages/accountspage.cpp
Normal file
46
src/widgets/settingspages/accountspage.cpp
Normal file
|
@ -0,0 +1,46 @@
|
|||
#include "accountspage.hpp"
|
||||
|
||||
#include <QDialogButtonBox>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#include "const.hpp"
|
||||
#include "singletons/accountmanager.hpp"
|
||||
#include "util/layoutcreator.hpp"
|
||||
#include "widgets/logindialog.hpp"
|
||||
|
||||
namespace chatterino {
|
||||
namespace widgets {
|
||||
namespace settingspages {
|
||||
AccountsPage::AccountsPage()
|
||||
: SettingsPage("Accounts", ":/images/accounts.svg")
|
||||
{
|
||||
util::LayoutCreator<AccountsPage> layoutCreator(this);
|
||||
|
||||
auto layout = layoutCreator.emplace<QVBoxLayout>().withoutMargin();
|
||||
auto buttons = layout.emplace<QDialogButtonBox>();
|
||||
{
|
||||
this->addButton = buttons->addButton("Add", QDialogButtonBox::YesRole);
|
||||
this->removeButton = buttons->addButton("Remove", QDialogButtonBox::NoRole);
|
||||
}
|
||||
|
||||
auto accountSwitch = layout.emplace<AccountSwitchWidget>(this).assign(&this->accSwitchWidget);
|
||||
|
||||
// ----
|
||||
QObject::connect(this->addButton, &QPushButton::clicked, []() {
|
||||
static auto loginWidget = new LoginWidget();
|
||||
loginWidget->show();
|
||||
});
|
||||
|
||||
QObject::connect(this->removeButton, &QPushButton::clicked, [this] {
|
||||
auto selectedUser = this->accSwitchWidget->currentItem()->text();
|
||||
if (selectedUser == ANONYMOUS_USERNAME_LABEL) {
|
||||
// Do nothing
|
||||
return;
|
||||
}
|
||||
|
||||
singletons::AccountManager::getInstance().Twitch.removeUser(selectedUser);
|
||||
});
|
||||
}
|
||||
} // namespace settingspages
|
||||
} // namespace widgets
|
||||
} // namespace chatterino
|
24
src/widgets/settingspages/accountspage.hpp
Normal file
24
src/widgets/settingspages/accountspage.hpp
Normal file
|
@ -0,0 +1,24 @@
|
|||
#pragma once
|
||||
|
||||
#include <QPushButton>
|
||||
|
||||
#include "widgets/accountswitchwidget.hpp"
|
||||
#include "widgets/settingspages/settingspage.hpp"
|
||||
|
||||
namespace chatterino {
|
||||
namespace widgets {
|
||||
namespace settingspages {
|
||||
|
||||
class AccountsPage : public SettingsPage
|
||||
{
|
||||
public:
|
||||
AccountsPage();
|
||||
|
||||
private:
|
||||
QPushButton *addButton;
|
||||
QPushButton *removeButton;
|
||||
AccountSwitchWidget *accSwitchWidget;
|
||||
};
|
||||
} // namespace settingspages
|
||||
} // namespace widgets
|
||||
} // namespace chatterino
|
148
src/widgets/settingspages/appearancepage.cpp
Normal file
148
src/widgets/settingspages/appearancepage.cpp
Normal file
|
@ -0,0 +1,148 @@
|
|||
#include "appearancepage.hpp"
|
||||
|
||||
#include <QFontDialog>
|
||||
#include <QFormLayout>
|
||||
#include <QGroupBox>
|
||||
#include <QLabel>
|
||||
#include <QPushButton>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#include <util/layoutcreator.hpp>
|
||||
|
||||
#define THEME_ITEMS "White", "Light", "Dark", "Black"
|
||||
|
||||
#define TAB_X "Hide tab x"
|
||||
#define TAB_PREF "Hide preferences button (ctrl+p to show)"
|
||||
#define TAB_USER "Hide user button"
|
||||
|
||||
#define SCROLL_SMOOTH "Enable smooth scrolling"
|
||||
#define SCROLL_NEWMSG "Enable smooth scrolling for new messages"
|
||||
|
||||
#define TIMESTAMP_FORMATS "hh:mm a", "h:mm a", "HH:mm", "H:mm"
|
||||
|
||||
namespace chatterino {
|
||||
namespace widgets {
|
||||
namespace settingspages {
|
||||
|
||||
AppearancePage::AppearancePage()
|
||||
: SettingsPage("Appearance", ":/images/theme.svg")
|
||||
{
|
||||
singletons::SettingManager &settings = singletons::SettingManager::getInstance();
|
||||
util::LayoutCreator<AppearancePage> layoutCreator(this);
|
||||
auto layout = layoutCreator.emplace<QVBoxLayout>().withoutMargin();
|
||||
|
||||
auto application =
|
||||
layout.emplace<QGroupBox>("Application").emplace<QVBoxLayout>().withoutMargin();
|
||||
{
|
||||
auto form = application.emplace<QFormLayout>();
|
||||
|
||||
// clang-format off
|
||||
form->addRow("Theme:", this->createComboBox({THEME_ITEMS}, singletons::ThemeManager::getInstance().themeName));
|
||||
form->addRow("Theme color:", this->createThemeColorChanger());
|
||||
form->addRow("Font:", this->createFontChanger());
|
||||
|
||||
form->addRow("Tab bar:", this->createCheckBox(TAB_X, settings.hideTabX));
|
||||
form->addRow("", this->createCheckBox(TAB_PREF, settings.hidePreferencesButton));
|
||||
form->addRow("", this->createCheckBox(TAB_USER, settings.hideUserButton));
|
||||
|
||||
form->addRow("Scrolling:", this->createCheckBox(SCROLL_SMOOTH, settings.enableSmoothScrolling));
|
||||
form->addRow("", this->createCheckBox(SCROLL_NEWMSG, settings.enableSmoothScrollingNewMessages));
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
auto messages = layout.emplace<QGroupBox>("Messages").emplace<QVBoxLayout>().withoutMargin();
|
||||
{
|
||||
messages.append(this->createCheckBox("Show timestamp", settings.showTimestamps));
|
||||
auto tbox = messages.emplace<QHBoxLayout>();
|
||||
{
|
||||
tbox.emplace<QLabel>("timestamp format:");
|
||||
tbox.append(this->createComboBox({TIMESTAMP_FORMATS}, settings.timestampFormat));
|
||||
}
|
||||
messages.append(this->createCheckBox("Show badges", settings.showBadges));
|
||||
messages.append(this->createCheckBox("Seperate messages", settings.seperateMessages));
|
||||
messages.append(this->createCheckBox("Show message length", settings.showMessageLength));
|
||||
}
|
||||
|
||||
layout->addStretch(1);
|
||||
}
|
||||
|
||||
QLayout *AppearancePage::createThemeColorChanger()
|
||||
{
|
||||
QHBoxLayout *layout = new QHBoxLayout;
|
||||
|
||||
auto &themeHue = singletons::ThemeManager::getInstance().themeHue;
|
||||
|
||||
// SLIDER
|
||||
QSlider *slider = new QSlider(Qt::Horizontal);
|
||||
layout->addWidget(slider);
|
||||
slider->setValue(std::min(std::max(themeHue.getValue(), 0.0), 1.0) * 1000);
|
||||
|
||||
// BUTTON
|
||||
QPushButton *button = new QPushButton;
|
||||
layout->addWidget(button);
|
||||
button->setFlat(true);
|
||||
button->setFixedWidth(64);
|
||||
|
||||
// SIGNALS
|
||||
QObject::connect(slider, &QSlider::valueChanged, this, [button, &themeHue](int value) mutable {
|
||||
double newValue = value / 1000.0;
|
||||
|
||||
themeHue.setValue(newValue);
|
||||
|
||||
QPalette pal = button->palette();
|
||||
QColor color;
|
||||
color.setHsvF(newValue, 1.0, 1.0, 1.0);
|
||||
pal.setColor(QPalette::Button, color);
|
||||
button->setAutoFillBackground(true);
|
||||
button->setPalette(pal);
|
||||
button->update();
|
||||
|
||||
// TODO(pajlada): re-implement
|
||||
// this->windowManager.updateAll();
|
||||
});
|
||||
|
||||
return layout;
|
||||
}
|
||||
|
||||
QLayout *AppearancePage::createFontChanger()
|
||||
{
|
||||
QHBoxLayout *layout = new QHBoxLayout;
|
||||
|
||||
auto &fontManager = singletons::FontManager::getInstance();
|
||||
|
||||
// LABEL
|
||||
QLabel *label = new QLabel();
|
||||
layout->addWidget(label);
|
||||
|
||||
auto updateFontFamilyLabel = [label, &fontManager](auto) {
|
||||
label->setText(QString::fromStdString(fontManager.currentFontFamily.getValue()) + ", " +
|
||||
QString::number(fontManager.currentFontSize) + "pt");
|
||||
};
|
||||
|
||||
fontManager.currentFontFamily.connectSimple(updateFontFamilyLabel, this->managedConnections);
|
||||
fontManager.currentFontSize.connectSimple(updateFontFamilyLabel, this->managedConnections);
|
||||
|
||||
// BUTTON
|
||||
QPushButton *button = new QPushButton("Select");
|
||||
layout->addWidget(button);
|
||||
button->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Policy::Fixed);
|
||||
|
||||
QObject::connect(button, &QPushButton::clicked, []() {
|
||||
auto &fontManager = singletons::FontManager::getInstance();
|
||||
QFontDialog dialog(fontManager.getFont(singletons::FontManager::Medium, 1.));
|
||||
|
||||
dialog.connect(&dialog, &QFontDialog::fontSelected, [](const QFont &font) {
|
||||
auto &fontManager = singletons::FontManager::getInstance();
|
||||
fontManager.currentFontFamily = font.family().toStdString();
|
||||
fontManager.currentFontSize = font.pointSize();
|
||||
});
|
||||
|
||||
dialog.show();
|
||||
dialog.exec();
|
||||
});
|
||||
|
||||
return layout;
|
||||
}
|
||||
} // namespace settingspages
|
||||
} // namespace widgets
|
||||
} // namespace chatterino
|
22
src/widgets/settingspages/appearancepage.hpp
Normal file
22
src/widgets/settingspages/appearancepage.hpp
Normal file
|
@ -0,0 +1,22 @@
|
|||
#pragma once
|
||||
|
||||
#include "widgets/settingspages/settingspage.hpp"
|
||||
|
||||
#include <QSlider>
|
||||
|
||||
namespace chatterino {
|
||||
namespace widgets {
|
||||
namespace settingspages {
|
||||
|
||||
class AppearancePage : public SettingsPage
|
||||
{
|
||||
public:
|
||||
AppearancePage();
|
||||
|
||||
QLayout *createThemeColorChanger();
|
||||
QLayout *createFontChanger();
|
||||
};
|
||||
|
||||
} // namespace settingspages
|
||||
} // namespace widgets
|
||||
} // namespace chatterino
|
57
src/widgets/settingspages/behaviourpage.cpp
Normal file
57
src/widgets/settingspages/behaviourpage.cpp
Normal file
|
@ -0,0 +1,57 @@
|
|||
#include "behaviourpage.hpp"
|
||||
|
||||
#include <QFormLayout>
|
||||
#include <QLabel>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#include <util/layoutcreator.hpp>
|
||||
|
||||
#define WINDOW_TOPMOST "Window always on top (requires restart)"
|
||||
#define INPUT_EMPTY "Hide input box when empty"
|
||||
#define LAST_MSG "Show last read message indicator"
|
||||
#define PAUSE_HOVERING "When hovering"
|
||||
|
||||
#define STREAMLINK_QUALITY "Source", "High", "Medium", "Low", "Audio only"
|
||||
|
||||
namespace chatterino {
|
||||
namespace widgets {
|
||||
namespace settingspages {
|
||||
BehaviourPage::BehaviourPage()
|
||||
: SettingsPage("Behaviour", nullptr)
|
||||
{
|
||||
singletons::SettingManager &settings = singletons::SettingManager::getInstance();
|
||||
util::LayoutCreator<BehaviourPage> layoutCreator(this);
|
||||
|
||||
auto form = layoutCreator.emplace<QFormLayout>().withoutMargin();
|
||||
{
|
||||
form->addRow("Window:", this->createCheckBox(WINDOW_TOPMOST, settings.windowTopMost));
|
||||
form->addRow("Messages:", this->createCheckBox(INPUT_EMPTY, settings.windowTopMost));
|
||||
form->addRow("", this->createCheckBox(LAST_MSG, settings.windowTopMost));
|
||||
form->addRow("Pause chat:", this->createCheckBox(PAUSE_HOVERING, settings.windowTopMost));
|
||||
|
||||
form->addRow("Mouse scroll speed:", this->createMouseScrollSlider());
|
||||
form->addRow("Streamlink path:", this->createLineEdit(settings.streamlinkPath));
|
||||
form->addRow("Prefered quality:",
|
||||
this->createComboBox({STREAMLINK_QUALITY}, settings.preferredQuality));
|
||||
}
|
||||
}
|
||||
|
||||
QSlider *BehaviourPage::createMouseScrollSlider()
|
||||
{
|
||||
QSlider *slider = new QSlider(Qt::Horizontal);
|
||||
|
||||
float currentValue = singletons::SettingManager::getInstance().mouseScrollMultiplier;
|
||||
int sliderValue = ((currentValue - 0.1f) / 2.f) * 99.f;
|
||||
slider->setValue(sliderValue);
|
||||
|
||||
QObject::connect(slider, &QSlider::valueChanged, [](int newValue) {
|
||||
float mul = static_cast<float>(newValue) / 99.f;
|
||||
float newSliderValue = (mul * 2.1f) + 0.1f;
|
||||
singletons::SettingManager::getInstance().mouseScrollMultiplier = newSliderValue;
|
||||
});
|
||||
|
||||
return slider;
|
||||
}
|
||||
} // namespace settingspages
|
||||
} // namespace widgets
|
||||
} // namespace chatterino
|
22
src/widgets/settingspages/behaviourpage.hpp
Normal file
22
src/widgets/settingspages/behaviourpage.hpp
Normal file
|
@ -0,0 +1,22 @@
|
|||
#pragma once
|
||||
|
||||
#include <QSlider>
|
||||
|
||||
#include "widgets/settingspages/settingspage.hpp"
|
||||
|
||||
namespace chatterino {
|
||||
namespace widgets {
|
||||
namespace settingspages {
|
||||
|
||||
class BehaviourPage : public SettingsPage
|
||||
{
|
||||
public:
|
||||
BehaviourPage();
|
||||
|
||||
private:
|
||||
QSlider *createMouseScrollSlider();
|
||||
};
|
||||
|
||||
} // namespace settingspages
|
||||
} // namespace widgets
|
||||
} // namespace chatterino
|
65
src/widgets/settingspages/commandpage.cpp
Normal file
65
src/widgets/settingspages/commandpage.cpp
Normal file
|
@ -0,0 +1,65 @@
|
|||
#include "commandpage.hpp"
|
||||
|
||||
#include <QLabel>
|
||||
#include <QTextEdit>
|
||||
|
||||
#include <util/layoutcreator.hpp>
|
||||
#include "singletons/commandmanager.hpp"
|
||||
|
||||
// clang-format off
|
||||
#define TEXT "One command per line.\n"\
|
||||
"\"/cmd example command\" will print \"example command\" when you type /cmd in chat.\n"\
|
||||
"{1} will be replaced with the first word you type after then command, {2} with the second and so on.\n"\
|
||||
"{1+} will be replaced with first word and everything after, {2+} with everything after the second word and so on\n"\
|
||||
"Duplicate commands will be ignored."
|
||||
// clang-format on
|
||||
|
||||
namespace chatterino {
|
||||
namespace widgets {
|
||||
namespace settingspages {
|
||||
|
||||
CommandPage::CommandPage()
|
||||
: SettingsPage("Commands", ":/images/commands.svg")
|
||||
{
|
||||
util::LayoutCreator<CommandPage> layoutCreator(this);
|
||||
auto layout = layoutCreator.emplace<QVBoxLayout>();
|
||||
|
||||
layout.emplace<QLabel>(TEXT)->setWordWrap(true);
|
||||
|
||||
layout.append(this->getCommandsTextEdit());
|
||||
|
||||
// ---- end of layout
|
||||
this->commandsEditTimer.setSingleShot(true);
|
||||
}
|
||||
|
||||
QTextEdit *CommandPage::getCommandsTextEdit()
|
||||
{
|
||||
singletons::CommandManager &commandManager = singletons::CommandManager::getInstance();
|
||||
|
||||
// cancel
|
||||
QStringList currentCommands = commandManager.getCommands();
|
||||
|
||||
this->onCancel.connect(
|
||||
[currentCommands, &commandManager] { commandManager.setCommands(currentCommands); });
|
||||
|
||||
// create text edit
|
||||
QTextEdit *textEdit = new QTextEdit;
|
||||
|
||||
textEdit->setPlainText(QString(commandManager.getCommands().join('\n')));
|
||||
|
||||
QObject::connect(textEdit, &QTextEdit::textChanged,
|
||||
[this] { this->commandsEditTimer.start(200); });
|
||||
|
||||
QObject::connect(&this->commandsEditTimer, &QTimer::timeout, [textEdit, &commandManager] {
|
||||
QString text = textEdit->toPlainText();
|
||||
QStringList lines = text.split(QRegularExpression("(\r?\n|\r\n?)"));
|
||||
|
||||
commandManager.setCommands(lines);
|
||||
});
|
||||
|
||||
return textEdit;
|
||||
}
|
||||
|
||||
} // namespace settingspages
|
||||
} // namespace widgets
|
||||
} // namespace chatterino
|
25
src/widgets/settingspages/commandpage.hpp
Normal file
25
src/widgets/settingspages/commandpage.hpp
Normal file
|
@ -0,0 +1,25 @@
|
|||
#pragma once
|
||||
|
||||
#include <QTextEdit>
|
||||
#include <QTimer>
|
||||
|
||||
#include "widgets/settingspages/settingspage.hpp"
|
||||
|
||||
namespace chatterino {
|
||||
namespace widgets {
|
||||
namespace settingspages {
|
||||
|
||||
class CommandPage : public SettingsPage
|
||||
{
|
||||
public:
|
||||
CommandPage();
|
||||
|
||||
private:
|
||||
QTextEdit *getCommandsTextEdit();
|
||||
|
||||
QTimer commandsEditTimer;
|
||||
};
|
||||
|
||||
} // namespace settingspages
|
||||
} // namespace widgets
|
||||
} // namespace chatterino
|
27
src/widgets/settingspages/emotespage.cpp
Normal file
27
src/widgets/settingspages/emotespage.cpp
Normal file
|
@ -0,0 +1,27 @@
|
|||
#include "emotespage.hpp"
|
||||
|
||||
#include <util/layoutcreator.hpp>
|
||||
|
||||
namespace chatterino {
|
||||
namespace widgets {
|
||||
namespace settingspages {
|
||||
EmotesPage::EmotesPage()
|
||||
: SettingsPage("Emotes", ":/images/emote.svg")
|
||||
{
|
||||
singletons::SettingManager &settings = singletons::SettingManager::getInstance();
|
||||
util::LayoutCreator<EmotesPage> layoutCreator(this);
|
||||
auto layout = layoutCreator.emplace<QVBoxLayout>().withoutMargin();
|
||||
|
||||
// clang-format off
|
||||
layout.append(this->createCheckBox("Enable Twitch emotes", settings.enableTwitchEmotes));
|
||||
layout.append(this->createCheckBox("Enable BetterTTV emotes", settings.enableBttvEmotes));
|
||||
layout.append(this->createCheckBox("Enable FrankerFaceZ emotes", settings.enableFfzEmotes));
|
||||
layout.append(this->createCheckBox("Enable emojis", settings.enableEmojis));
|
||||
layout.append(this->createCheckBox("Enable gif animations", settings.enableGifAnimations));
|
||||
// clang-format on
|
||||
|
||||
layout->addStretch(1);
|
||||
}
|
||||
} // namespace settingspages
|
||||
} // namespace widgets
|
||||
} // namespace chatterino
|
16
src/widgets/settingspages/emotespage.hpp
Normal file
16
src/widgets/settingspages/emotespage.hpp
Normal file
|
@ -0,0 +1,16 @@
|
|||
#pragma once
|
||||
|
||||
#include "widgets/settingspages/settingspage.hpp"
|
||||
|
||||
namespace chatterino {
|
||||
namespace widgets {
|
||||
namespace settingspages {
|
||||
|
||||
class EmotesPage : public SettingsPage
|
||||
{
|
||||
public:
|
||||
EmotesPage();
|
||||
};
|
||||
} // namespace settingspages
|
||||
} // namespace widgets
|
||||
} // namespace chatterino
|
12
src/widgets/settingspages/highlightingpage.cpp
Normal file
12
src/widgets/settingspages/highlightingpage.cpp
Normal file
|
@ -0,0 +1,12 @@
|
|||
#include "highlightingpage.hpp"
|
||||
|
||||
namespace chatterino {
|
||||
namespace widgets {
|
||||
namespace settingspages {
|
||||
HighlightingPage::HighlightingPage()
|
||||
: SettingsPage("Highlights", ":/images/VSO_Link_blue_16x.png")
|
||||
{
|
||||
}
|
||||
} // namespace settingspages
|
||||
} // namespace widgets
|
||||
} // namespace chatterino
|
17
src/widgets/settingspages/highlightingpage.hpp
Normal file
17
src/widgets/settingspages/highlightingpage.hpp
Normal file
|
@ -0,0 +1,17 @@
|
|||
#pragma once
|
||||
|
||||
#include "widgets/settingspages/settingspage.hpp"
|
||||
|
||||
namespace chatterino {
|
||||
namespace widgets {
|
||||
namespace settingspages {
|
||||
|
||||
class HighlightingPage : public SettingsPage
|
||||
{
|
||||
public:
|
||||
HighlightingPage();
|
||||
};
|
||||
|
||||
} // namespace settingspages
|
||||
} // namespace widgets
|
||||
} // namespace chatterino
|
12
src/widgets/settingspages/logspage.cpp
Normal file
12
src/widgets/settingspages/logspage.cpp
Normal file
|
@ -0,0 +1,12 @@
|
|||
#include "logspage.hpp"
|
||||
|
||||
namespace chatterino {
|
||||
namespace widgets {
|
||||
namespace settingspages {
|
||||
LogsPage::LogsPage()
|
||||
: SettingsPage("Logs", ":/images/VSO_Link_blue_16x.png")
|
||||
{
|
||||
}
|
||||
} // namespace settingspages
|
||||
} // namespace widgets
|
||||
} // namespace chatterino
|
16
src/widgets/settingspages/logspage.hpp
Normal file
16
src/widgets/settingspages/logspage.hpp
Normal file
|
@ -0,0 +1,16 @@
|
|||
#pragma once
|
||||
|
||||
#include "widgets/settingspages/settingspage.hpp"
|
||||
|
||||
namespace chatterino {
|
||||
namespace widgets {
|
||||
namespace settingspages {
|
||||
|
||||
class LogsPage : public SettingsPage
|
||||
{
|
||||
public:
|
||||
LogsPage();
|
||||
};
|
||||
} // namespace settingspages
|
||||
} // namespace widgets
|
||||
} // namespace chatterino
|
12
src/widgets/settingspages/moderationpage.cpp
Normal file
12
src/widgets/settingspages/moderationpage.cpp
Normal file
|
@ -0,0 +1,12 @@
|
|||
#include "moderationpage.hpp"
|
||||
|
||||
namespace chatterino {
|
||||
namespace widgets {
|
||||
namespace settingspages {
|
||||
ModerationPage::ModerationPage()
|
||||
: SettingsPage("Moderation", ":/images/VSO_Link_blue_16x.png")
|
||||
{
|
||||
}
|
||||
} // namespace settingspages
|
||||
} // namespace widgets
|
||||
} // namespace chatterino
|
16
src/widgets/settingspages/moderationpage.hpp
Normal file
16
src/widgets/settingspages/moderationpage.hpp
Normal file
|
@ -0,0 +1,16 @@
|
|||
#pragma once
|
||||
|
||||
#include "widgets/settingspages/settingspage.hpp"
|
||||
|
||||
namespace chatterino {
|
||||
namespace widgets {
|
||||
namespace settingspages {
|
||||
|
||||
class ModerationPage : public SettingsPage
|
||||
{
|
||||
public:
|
||||
ModerationPage();
|
||||
};
|
||||
} // namespace settingspages
|
||||
} // namespace widgets
|
||||
} // namespace chatterino
|
78
src/widgets/settingspages/settingspage.cpp
Normal file
78
src/widgets/settingspages/settingspage.cpp
Normal file
|
@ -0,0 +1,78 @@
|
|||
#include "settingspage.hpp"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
namespace chatterino {
|
||||
namespace widgets {
|
||||
namespace settingspages {
|
||||
|
||||
SettingsPage::SettingsPage(const QString &_name, const QString &_resourceName)
|
||||
: name(_name)
|
||||
, resourceName(_resourceName)
|
||||
{
|
||||
}
|
||||
|
||||
const QString &SettingsPage::getName()
|
||||
{
|
||||
return this->name;
|
||||
}
|
||||
|
||||
void SettingsPage::cancel()
|
||||
{
|
||||
this->onCancel.invoke();
|
||||
}
|
||||
|
||||
QCheckBox *SettingsPage::createCheckBox(const QString &text,
|
||||
pajlada::Settings::Setting<bool> &setting)
|
||||
{
|
||||
QCheckBox *checkbox = new QCheckBox(text);
|
||||
|
||||
// update when setting changes
|
||||
setting.connect(
|
||||
[checkbox](const bool &value, auto) {
|
||||
checkbox->setChecked(value); //
|
||||
},
|
||||
this->managedConnections);
|
||||
|
||||
// update setting on toggle
|
||||
QObject::connect(checkbox, &QCheckBox::toggled, this, [&setting](bool state) {
|
||||
qDebug() << "update checkbox value";
|
||||
setting = state; //
|
||||
});
|
||||
|
||||
return checkbox;
|
||||
}
|
||||
|
||||
QComboBox *SettingsPage::createComboBox(const QStringList &items,
|
||||
pajlada::Settings::Setting<QString> &setting)
|
||||
{
|
||||
QComboBox *combo = new QComboBox();
|
||||
|
||||
// update setting on toogle
|
||||
combo->addItems(items);
|
||||
|
||||
// update when setting changes
|
||||
setting.connect([combo](const QString &value, auto) { combo->setCurrentText(value); },
|
||||
this->managedConnections);
|
||||
|
||||
QObject::connect(combo, &QComboBox::currentTextChanged,
|
||||
[&setting](const QString &newValue) { setting = newValue; });
|
||||
|
||||
return combo;
|
||||
}
|
||||
|
||||
QLineEdit *SettingsPage::createLineEdit(pajlada::Settings::Setting<QString> &setting)
|
||||
{
|
||||
QLineEdit *edit = new QLineEdit();
|
||||
|
||||
edit->setText(setting);
|
||||
|
||||
// update when setting changes
|
||||
QObject::connect(edit, &QLineEdit::textChanged,
|
||||
[&setting](const QString &newValue) { setting = newValue; });
|
||||
|
||||
return edit;
|
||||
}
|
||||
} // namespace settingspages
|
||||
} // namespace widgets
|
||||
} // namespace chatterino
|
37
src/widgets/settingspages/settingspage.hpp
Normal file
37
src/widgets/settingspages/settingspage.hpp
Normal file
|
@ -0,0 +1,37 @@
|
|||
#pragma once
|
||||
|
||||
#include <QCheckBox>
|
||||
#include <QComboBox>
|
||||
#include <QLineEdit>
|
||||
#include <pajlada/signals/signal.hpp>
|
||||
|
||||
#include "singletons/settingsmanager.hpp"
|
||||
|
||||
namespace chatterino {
|
||||
namespace widgets {
|
||||
namespace settingspages {
|
||||
|
||||
class SettingsPage : public QWidget
|
||||
{
|
||||
public:
|
||||
SettingsPage(const QString &name, const QString &resourceName);
|
||||
|
||||
const QString &getName();
|
||||
|
||||
void cancel();
|
||||
|
||||
QCheckBox *createCheckBox(const QString &text, pajlada::Settings::Setting<bool> &setting);
|
||||
QComboBox *createComboBox(const QStringList &items,
|
||||
pajlada::Settings::Setting<QString> &setting);
|
||||
QLineEdit *createLineEdit(pajlada::Settings::Setting<QString> &setting);
|
||||
|
||||
protected:
|
||||
QString name;
|
||||
QString resourceName;
|
||||
|
||||
pajlada::Signals::NoArgSignal onCancel;
|
||||
std::vector<pajlada::Signals::ScopedConnection> managedConnections;
|
||||
};
|
||||
} // namespace settingspages
|
||||
} // namespace widgets
|
||||
} // namespace chatterino
|
|
@ -289,10 +289,9 @@ void Split::doOpenPopupPlayer()
|
|||
void Split::doOpenStreamlink()
|
||||
{
|
||||
singletons::SettingManager &settings = singletons::SettingManager::getInstance();
|
||||
QString preferredQuality =
|
||||
QString::fromStdString(settings.preferredQuality.getValue()).toLower();
|
||||
QString preferredQuality = settings.preferredQuality;
|
||||
// TODO(Confuseh): Default streamlink paths
|
||||
QString path = QString::fromStdString(settings.streamlinkPath.getValue());
|
||||
QString path = settings.streamlinkPath;
|
||||
QString channel = QString::fromStdString(this->channelName.getValue());
|
||||
QFileInfo fileinfo = QFileInfo(path);
|
||||
|
||||
|
|
Loading…
Reference in a new issue