mirror-chatterino2/src/widgets/settingspages/LookPage.cpp

508 lines
17 KiB
C++
Raw Normal View History

#include "LookPage.hpp"
2018-01-12 23:09:05 +01:00
2018-06-26 14:09:39 +02:00
#include "Application.hpp"
#include "messages/Image.hpp"
2018-08-07 01:35:24 +02:00
#include "messages/MessageBuilder.hpp"
#include "singletons/Resources.hpp"
#include "singletons/Theme.hpp"
2018-06-26 14:09:39 +02:00
#include "singletons/WindowManager.hpp"
#include "util/LayoutCreator.hpp"
#include "util/RemoveScrollAreaBackground.hpp"
#include "widgets/helper/ChannelView.hpp"
#include "widgets/helper/Line.hpp"
2018-01-12 23:09:05 +01:00
#include <QFontDialog>
#include <QFormLayout>
#include <QGroupBox>
#include <QLabel>
#include <QPushButton>
2018-04-25 20:35:32 +02:00
#include <QScrollArea>
#include <QSlider>
2018-01-12 23:09:05 +01:00
#include <QVBoxLayout>
#define THEME_ITEMS "White", "Light", "Dark", "Black"
2018-07-05 18:17:12 +02:00
#define TAB_X "Show tab close button"
2018-07-05 17:38:24 +02:00
#define TAB_PREF "Preferences button (ctrl+p to show)"
#define TAB_USER "User button"
2018-01-12 23:09:05 +01:00
2018-01-17 18:36:12 +01:00
// clang-format off
#define TIMESTAMP_FORMATS "hh:mm a", "h:mm a", "hh:mm:ss a", "h:mm:ss a", "HH:mm", "H:mm", "HH:mm:ss", "H:mm:ss"
// clang-format on
2018-01-12 23:09:05 +01:00
2018-07-05 18:17:12 +02:00
#ifdef USEWINSDK
#define WINDOW_TOPMOST "Window always on top"
#else
#define WINDOW_TOPMOST "Window always on top (requires restart)"
#endif
#define INPUT_EMPTY "Show input box when empty"
#define LAST_MSG "Mark the last message you read"
2018-01-12 23:09:05 +01:00
namespace chatterino {
LookPage::LookPage()
2018-08-09 06:22:55 +02:00
: SettingsPage("Look", ":/settings/theme.svg")
2018-07-05 18:17:12 +02:00
{
this->initializeUi();
}
void LookPage::initializeUi()
2018-01-12 23:09:05 +01:00
{
LayoutCreator<LookPage> layoutCreator(this);
2018-04-25 20:35:32 +02:00
2018-07-05 17:38:24 +02:00
auto layout = layoutCreator.emplace<QVBoxLayout>().withoutMargin();
// settings
2018-07-05 17:38:24 +02:00
auto tabs = layout.emplace<QTabWidget>();
2018-04-25 20:35:32 +02:00
2018-07-05 17:38:24 +02:00
this->addInterfaceTab(tabs.appendTab(new QVBoxLayout, "Interface"));
this->addMessageTab(tabs.appendTab(new QVBoxLayout, "Messages"));
this->addEmoteTab(tabs.appendTab(new QVBoxLayout, "Emotes"));
this->addSplitHeaderTab(tabs.appendTab(new QVBoxLayout, "Split header"));
2018-01-12 23:09:05 +01:00
2018-07-05 17:38:24 +02:00
layout->addStretch(1);
// preview
2018-07-05 17:38:24 +02:00
layout.emplace<Line>(false);
2018-07-05 17:38:24 +02:00
auto channelView = layout.emplace<ChannelView>();
auto channel = this->createPreviewChannel();
channelView->setChannel(channel);
channelView->setScaleIndependantHeight(74);
}
2018-07-05 17:38:24 +02:00
void LookPage::addInterfaceTab(LayoutCreator<QVBoxLayout> layout)
{
// theme
2018-07-05 17:38:24 +02:00
{
2018-08-06 21:17:03 +02:00
auto *theme =
this->createComboBox({THEME_ITEMS}, getApp()->themes->themeName);
2018-07-05 17:38:24 +02:00
QObject::connect(theme, &QComboBox::currentTextChanged,
2018-08-06 21:17:03 +02:00
[](const QString &) {
getApp()->windows->forceLayoutChannelViews();
});
2018-07-05 17:38:24 +02:00
auto box = layout.emplace<QHBoxLayout>().withoutMargin();
box.emplace<QLabel>("Theme: ");
box.append(theme);
box->addStretch(1);
}
// ui scale
2018-07-05 17:38:24 +02:00
{
auto box = layout.emplace<QHBoxLayout>().withoutMargin();
2018-07-05 18:17:12 +02:00
box.emplace<QLabel>("Window scale: ");
2018-07-05 17:38:24 +02:00
box.append(this->createUiScaleSlider());
}
2018-08-06 21:17:03 +02:00
layout.append(
this->createCheckBox(WINDOW_TOPMOST, getSettings()->windowTopMost));
2018-07-05 18:17:12 +02:00
// --
layout.emplace<Line>(false);
// tab x
2018-08-06 21:17:03 +02:00
layout.append(
this->createCheckBox(TAB_X, getSettings()->showTabCloseButton));
// show buttons
#ifndef USEWINSDK
2018-08-06 21:17:03 +02:00
layout.append(
this->createCheckBox(TAB_PREF, getSettings()->hidePreferencesButton));
layout.append(
this->createCheckBox(TAB_USER, getSettings()->hideUserButton));
#endif
2018-07-05 18:17:12 +02:00
// empty input
2018-07-05 17:38:24 +02:00
layout.append(
2018-08-06 21:17:03 +02:00
this->createCheckBox(INPUT_EMPTY, getSettings()->showEmptyInput));
layout.append(this->createCheckBox("Show message length while typing",
getSettings()->showMessageLength));
2018-07-05 17:38:24 +02:00
layout->addStretch(1);
}
2018-07-05 17:38:24 +02:00
void LookPage::addMessageTab(LayoutCreator<QVBoxLayout> layout)
{
2018-07-05 17:38:24 +02:00
// font
layout.append(this->createFontChanger());
// bold-slider
{
auto box = layout.emplace<QHBoxLayout>().withoutMargin();
box.emplace<QLabel>("Boldness: ");
box.append(this->createBoldScaleSlider());
}
2018-07-05 17:38:24 +02:00
// --
layout.emplace<Line>(false);
// timestamps
2018-07-05 18:17:12 +02:00
{
auto box = layout.emplace<QHBoxLayout>().withoutMargin();
2018-08-06 21:17:03 +02:00
box.append(this->createCheckBox("Show timestamps",
getSettings()->showTimestamps));
box.append(this->createComboBox({TIMESTAMP_FORMATS},
getSettings()->timestampFormat));
2018-07-05 18:17:12 +02:00
box->addStretch(1);
}
2018-01-12 23:09:05 +01:00
// badges
2018-08-06 21:17:03 +02:00
layout.append(
this->createCheckBox("Show badges", getSettings()->showBadges));
2018-07-05 17:38:24 +02:00
// --
layout.emplace<Line>(false);
// seperate
2018-08-06 21:17:03 +02:00
layout.append(this->createCheckBox("Seperate lines",
getSettings()->separateMessages));
2018-07-05 17:38:24 +02:00
// alternate
2018-08-06 21:17:03 +02:00
layout.append(this->createCheckBox(
"Alternate background", getSettings()->alternateMessageBackground));
2018-07-05 17:38:24 +02:00
// --
layout.emplace<Line>(false);
// lowercase links
2018-08-06 21:17:03 +02:00
layout.append(this->createCheckBox("Lowercase domains",
getSettings()->enableLowercaseLink));
2018-07-05 17:38:24 +02:00
// bold usernames
2018-08-06 21:17:03 +02:00
layout.append(this->createCheckBox("Bold @usernames",
getSettings()->enableUsernameBold));
// collapsing
2018-01-12 23:09:05 +01:00
{
auto *combo = new QComboBox(this);
2018-08-06 21:17:03 +02:00
combo->addItems({"Never", "2", "3", "4", "5", "6", "7", "8", "9", "10",
"11", "12", "13", "14", "15"});
const auto currentIndex = []() -> int {
auto val = getSettings()->collpseMessagesMinLines.getValue();
if (val > 0) {
--val;
}
return val;
}();
combo->setCurrentIndex(currentIndex);
2018-08-06 21:17:03 +02:00
QObject::connect(
combo, &QComboBox::currentTextChanged, [](const QString &str) {
getSettings()->collpseMessagesMinLines = str.toInt();
});
2018-07-05 17:38:24 +02:00
auto hbox = layout.emplace<QHBoxLayout>().withoutMargin();
hbox.emplace<QLabel>("Collapse messages longer than");
hbox.append(combo);
hbox.emplace<QLabel>("lines");
2018-01-12 23:09:05 +01:00
}
2018-07-05 18:17:12 +02:00
// last read message
this->addLastReadMessageIndicatorPatternSelector(layout);
2018-07-05 17:38:24 +02:00
// --
layout->addStretch(1);
}
2018-07-05 17:38:24 +02:00
void LookPage::addEmoteTab(LayoutCreator<QVBoxLayout> layout)
{
/*
emotes.append(
2018-08-06 21:17:03 +02:00
this->createCheckBox("Enable Twitch emotes",
getSettings()->enableTwitchEmotes));
emotes.append(this->createCheckBox("Enable BetterTTV emotes for Twitch",
getSettings()->enableBttvEmotes));
emotes.append(this->createCheckBox("Enable FrankerFaceZ emotes for Twitch",
getSettings()->enableFfzEmotes));
2018-08-06 21:17:03 +02:00
emotes.append(this->createCheckBox("Enable emojis",
getSettings()->enableEmojis));
*/
2018-08-06 21:17:03 +02:00
layout.append(
this->createCheckBox("Animations", getSettings()->enableGifAnimations));
2018-07-05 17:38:24 +02:00
auto scaleBox = layout.emplace<QHBoxLayout>().withoutMargin();
2018-01-12 23:09:05 +01:00
{
scaleBox.emplace<QLabel>("Size:");
auto emoteScale = scaleBox.emplace<QSlider>(Qt::Horizontal);
emoteScale->setMinimum(5);
emoteScale->setMaximum(50);
auto scaleLabel = scaleBox.emplace<QLabel>("1.0");
scaleLabel->setFixedWidth(100);
QObject::connect(emoteScale.getElement(), &QSlider::valueChanged,
[scaleLabel](int value) mutable {
float f = float(value) / 10.f;
scaleLabel->setText(QString::number(f));
getSettings()->emoteScale.setValue(f);
});
2018-08-06 21:17:03 +02:00
emoteScale->setValue(std::max<int>(
5, std::min<int>(
50, int(getSettings()->emoteScale.getValue() * 10.f))));
2018-08-06 21:17:03 +02:00
scaleLabel->setText(
QString::number(getSettings()->emoteScale.getValue()));
2018-04-25 20:35:32 +02:00
}
{
auto *combo = new QComboBox(this);
2018-08-06 21:17:03 +02:00
combo->addItems({"EmojiOne 2", "EmojiOne 3", "Twitter", "Facebook",
"Apple", "Google", "Messenger"});
combo->setCurrentText(getSettings()->emojiSet);
2018-08-06 21:17:03 +02:00
QObject::connect(combo, &QComboBox::currentTextChanged,
[](const QString &str) {
getSettings()->emojiSet = str; //
});
2018-07-05 17:38:24 +02:00
auto hbox = layout.emplace<QHBoxLayout>().withoutMargin();
hbox.emplace<QLabel>("Emoji set:");
hbox.append(combo);
}
2018-07-05 17:38:24 +02:00
layout->addStretch(1);
}
void LookPage::addSplitHeaderTab(LayoutCreator<QVBoxLayout> layout)
{
2018-08-06 21:17:03 +02:00
layout.append(this->createCheckBox("Show viewer count",
getSettings()->showViewerCount));
layout.append(this->createCheckBox("Show title", getSettings()->showTitle));
layout.append(this->createCheckBox("Show game", getSettings()->showGame));
2018-08-06 21:17:03 +02:00
layout.append(
this->createCheckBox("Show uptime", getSettings()->showUptime));
layout->addStretch(1);
}
2018-08-06 21:17:03 +02:00
void LookPage::addLastReadMessageIndicatorPatternSelector(
LayoutCreator<QVBoxLayout> layout)
2018-07-05 18:17:12 +02:00
{
// combo
auto *combo = new QComboBox(this);
combo->addItems({"Dotted line", "Solid line"});
const auto currentIndex = []() -> int {
switch (getSettings()->lastMessagePattern.getValue()) {
2018-07-05 18:17:12 +02:00
case Qt::SolidLine:
return 1;
case Qt::VerPattern:
default:
return 0;
}
}();
combo->setCurrentIndex(currentIndex);
2018-08-06 21:17:03 +02:00
QObject::connect(
combo,
static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
[](int index) {
getSettings()->lastMessagePattern = [&] {
switch (index) {
case 1:
return Qt::SolidPattern;
case 0:
default:
return Qt::VerPattern;
}
}();
});
2018-07-05 18:17:12 +02:00
// layout
auto hbox = layout.emplace<QHBoxLayout>().withoutMargin();
2018-08-06 21:17:03 +02:00
hbox.append(this->createCheckBox(LAST_MSG,
getSettings()->showLastMessageIndicator));
2018-07-05 18:17:12 +02:00
hbox.append(combo);
hbox->addStretch(1);
}
ChannelPtr LookPage::createPreviewChannel()
{
2018-07-06 17:30:12 +02:00
auto channel = ChannelPtr(new Channel("preview", Channel::Type::Misc));
2018-08-07 01:35:24 +02:00
// clang-format off
{
2018-08-07 01:35:24 +02:00
MessageBuilder builder;
builder.emplace<TimestampElement>(QTime(8, 13, 42));
2018-08-10 18:56:17 +02:00
builder.emplace<ImageElement>(Image::fromPixmap(getApp()->resources->twitch.moderator), MessageElementFlag::BadgeChannelAuthority);
builder.emplace<ImageElement>(Image::fromPixmap(getApp()->resources->twitch.subscriber, 0.25), MessageElementFlag::BadgeSubscription);
2018-08-07 07:55:31 +02:00
builder.emplace<TextElement>("username1:", MessageElementFlag::Username, QColor("#0094FF"), FontStyle::ChatMediumBold);
builder.emplace<TextElement>("This is a preview message", MessageElementFlag::Text);
2018-08-10 18:56:17 +02:00
builder.emplace<ImageElement>(Image::fromPixmap(getApp()->resources->pajaDank, 0.25), MessageElementFlag::AlwaysShow);
2018-08-07 07:55:31 +02:00
builder.emplace<TextElement>("@fourtf", MessageElementFlag::BoldUsername, MessageColor::Text, FontStyle::ChatMediumBold);
builder.emplace<TextElement>("@fourtf", MessageElementFlag::NonBoldUsername);
2018-08-07 01:35:24 +02:00
channel->addMessage(builder.release());
}
2018-04-25 20:35:32 +02:00
{
2018-08-07 01:35:24 +02:00
MessageBuilder message;
message.emplace<TimestampElement>(QTime(8, 15, 21));
2018-08-10 18:56:17 +02:00
message.emplace<ImageElement>(Image::fromPixmap(getApp()->resources->twitch.broadcaster), MessageElementFlag::BadgeChannelAuthority);
2018-08-07 07:55:31 +02:00
message.emplace<TextElement>("username2:", MessageElementFlag::Username, QColor("#FF6A00"), FontStyle::ChatMediumBold);
message.emplace<TextElement>("This is another one", MessageElementFlag::Text);
// message.emplace<ImageElement>(Image::fromNonOwningPixmap(&getApp()->resources->ppHop), MessageElementFlag::BttvEmote);
message.emplace<TextElement>("www.fourtf.com", MessageElementFlag::LowercaseLink, MessageColor::Link)->setLink(Link(Link::Url, "https://www.fourtf.com"));
message.emplace<TextElement>("wWw.FoUrTf.CoM", MessageElementFlag::OriginalLink, MessageColor::Link)->setLink(Link(Link::Url, "https://www.fourtf.com"));
2018-08-07 01:35:24 +02:00
channel->addMessage(message.release());
2018-01-12 23:09:05 +01:00
}
2018-08-07 01:35:24 +02:00
// clang-format on
2018-01-12 23:09:05 +01:00
return channel;
}
2018-01-12 23:09:05 +01:00
QLayout *LookPage::createThemeColorChanger()
2018-01-12 23:09:05 +01:00
{
auto app = getApp();
2018-01-12 23:09:05 +01:00
QHBoxLayout *layout = new QHBoxLayout;
auto &themeHue = app->themes->themeHue;
2018-01-12 23:09:05 +01:00
// SLIDER
QSlider *slider = new QSlider(Qt::Horizontal);
layout->addWidget(slider);
2018-08-06 21:17:03 +02:00
slider->setValue(
int(std::min(std::max(themeHue.getValue(), 0.0), 1.0) * 100));
2018-01-12 23:09:05 +01:00
// BUTTON
QPushButton *button = new QPushButton;
layout->addWidget(button);
button->setFlat(true);
button->setFixedWidth(64);
auto setButtonColor = [button, app](int value) mutable {
double newValue = value / 100.0;
app->themes->themeHue.setValue(newValue);
2018-01-12 23:09:05 +01:00
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();
2018-02-06 00:10:30 +01:00
};
// SIGNALS
QObject::connect(slider, &QSlider::valueChanged, this, setButtonColor);
2018-01-12 23:09:05 +01:00
2018-02-06 00:10:30 +01:00
setButtonColor(themeHue * 100);
2018-01-12 23:09:05 +01:00
return layout;
}
QLayout *LookPage::createFontChanger()
2018-01-12 23:09:05 +01:00
{
auto app = getApp();
2018-01-12 23:09:05 +01:00
QHBoxLayout *layout = new QHBoxLayout;
2018-07-05 17:38:24 +02:00
layout->setMargin(0);
2018-01-12 23:09:05 +01:00
// LABEL
QLabel *label = new QLabel();
layout->addWidget(label);
auto updateFontFamilyLabel = [=](auto) {
2018-08-06 21:17:03 +02:00
label->setText(
"Font (" +
QString::fromStdString(app->fonts->chatFontFamily.getValue()) +
", " + QString::number(app->fonts->chatFontSize) + "pt)");
2018-01-12 23:09:05 +01:00
};
2018-08-06 21:17:03 +02:00
app->fonts->chatFontFamily.connectSimple(updateFontFamilyLabel,
this->managedConnections_);
app->fonts->chatFontSize.connectSimple(updateFontFamilyLabel,
this->managedConnections_);
2018-01-12 23:09:05 +01:00
// BUTTON
QPushButton *button = new QPushButton("Select");
layout->addWidget(button);
button->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Policy::Fixed);
QObject::connect(button, &QPushButton::clicked, [=]() {
QFontDialog dialog(app->fonts->getFont(FontStyle::ChatMedium, 1.));
2018-01-12 23:09:05 +01:00
dialog.setWindowFlag(Qt::WindowStaysOnTopHint);
2018-08-06 21:17:03 +02:00
dialog.connect(
&dialog, &QFontDialog::fontSelected, [=](const QFont &font) {
app->fonts->chatFontFamily = font.family().toStdString();
app->fonts->chatFontSize = font.pointSize();
});
2018-01-12 23:09:05 +01:00
dialog.show();
dialog.exec();
});
2018-07-05 17:38:24 +02:00
layout->addStretch(1);
2018-01-12 23:09:05 +01:00
return layout;
}
QLayout *LookPage::createUiScaleSlider()
2018-06-11 15:04:54 +02:00
{
auto layout = new QHBoxLayout();
auto slider = new QSlider(Qt::Horizontal);
auto label = new QLabel();
layout->addWidget(slider);
layout->addWidget(label);
slider->setMinimum(WindowManager::uiScaleMin);
slider->setMaximum(WindowManager::uiScaleMax);
2018-08-06 21:17:03 +02:00
slider->setValue(
WindowManager::clampUiScale(getSettings()->uiScale.getValue()));
2018-06-11 15:04:54 +02:00
label->setMinimumWidth(100);
2018-08-06 21:17:03 +02:00
QObject::connect(slider, &QSlider::valueChanged, [](auto value) {
getSettings()->uiScale.setValue(value);
});
2018-06-11 15:04:54 +02:00
getSettings()->uiScale.connect(
2018-08-06 21:17:03 +02:00
[label](auto, auto) {
label->setText(QString::number(WindowManager::getUiScaleValue()));
},
2018-06-11 15:04:54 +02:00
this->connections_);
return layout;
}
QLayout *LookPage::createBoldScaleSlider()
{
auto layout = new QHBoxLayout();
auto slider = new QSlider(Qt::Horizontal);
auto label = new QLabel();
layout->addWidget(slider);
layout->addWidget(label);
slider->setMinimum(50);
slider->setMaximum(100);
slider->setValue(getSettings()->boldScale.getValue());
label->setMinimumWidth(100);
2018-08-06 21:17:03 +02:00
QObject::connect(slider, &QSlider::valueChanged, [](auto value) {
getSettings()->boldScale.setValue(value);
});
// show value
// getSettings()->boldScale.connect(
// [label](auto, auto) {
// label->setText(QString::number(getSettings()->boldScale.getValue()));
// },
// this->connections_);
QPushButton *button = new QPushButton("Reset");
layout->addWidget(button);
button->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Policy::Fixed);
QObject::connect(button, &QPushButton::clicked, [=]() {
getSettings()->boldScale.setValue(57);
slider->setValue(57);
});
return layout;
}
2018-01-12 23:09:05 +01:00
} // namespace chatterino