From 3c3be99177237b62e1c2b2bbee4e91c9e90d8df4 Mon Sep 17 00:00:00 2001 From: fourtf Date: Wed, 31 Oct 2018 19:45:51 +0100 Subject: [PATCH] new settings page --- chatterino.pro | 8 +- resources/qss/settings.qss | 20 ++ src/messages/layouts/MessageLayout.cpp | 2 +- src/providers/LinkResolver.cpp | 2 +- src/providers/ffz/FfzModBadge.cpp | 1 + src/providers/twitch/TwitchChannel.cpp | 3 - src/singletons/Settings.hpp | 29 +- src/singletons/Theme.cpp | 5 +- src/singletons/WindowManager.cpp | 12 +- src/singletons/helper/GifTimer.cpp | 4 +- src/util/FuzzyConvert.cpp | 33 +++ src/util/FuzzyConvert.hpp | 10 + src/util/Helpers.hpp | 35 +-- src/util/LayoutCreator.hpp | 7 + src/widgets/dialogs/SettingsDialog.cpp | 31 +- src/widgets/helper/ChannelView.cpp | 4 +- src/widgets/helper/NotebookTab.cpp | 6 +- src/widgets/settingspages/FeelPage.cpp | 9 +- src/widgets/settingspages/GeneralPage.cpp | 327 +++++++++++++++++++++ src/widgets/settingspages/GeneralPage.hpp | 152 ++++++++++ src/widgets/settingspages/LookPage.cpp | 32 +- src/widgets/settingspages/SettingsPage.hpp | 4 +- src/widgets/splits/SplitHeader.cpp | 16 +- 23 files changed, 651 insertions(+), 101 deletions(-) create mode 100644 src/util/FuzzyConvert.cpp create mode 100644 src/util/FuzzyConvert.hpp create mode 100644 src/widgets/settingspages/GeneralPage.cpp create mode 100644 src/widgets/settingspages/GeneralPage.hpp diff --git a/chatterino.pro b/chatterino.pro index c804e99e..57f3b043 100644 --- a/chatterino.pro +++ b/chatterino.pro @@ -264,7 +264,9 @@ SOURCES += \ src/widgets/settingspages/AdvancedPage.cpp \ src/util/IncognitoBrowser.cpp \ src/widgets/splits/ClosedSplits.cpp \ - src/providers/ffz/FfzModBadge.cpp + src/providers/ffz/FfzModBadge.cpp \ + src/widgets/settingspages/GeneralPage.cpp \ + src/util/FuzzyConvert.cpp HEADERS += \ src/Application.hpp \ @@ -468,7 +470,9 @@ HEADERS += \ src/widgets/settingspages/AdvancedPage.hpp \ src/util/IncognitoBrowser.hpp \ src/widgets/splits/ClosedSplits.hpp \ - src/providers/ffz/FfzModBadge.hpp + src/providers/ffz/FfzModBadge.hpp \ + src/widgets/settingspages/GeneralPage.hpp \ + src/util/FuzzyConvert.hpp RESOURCES += \ resources/resources.qrc \ diff --git a/resources/qss/settings.qss b/resources/qss/settings.qss index e7ee0a1e..e883bfe2 100644 --- a/resources/qss/settings.qss +++ b/resources/qss/settings.qss @@ -6,3 +6,23 @@ QCheckBox::indicator { width: px; height: px; } + +QComboBox { + width: 100px; +} + +chatterino--TitleLabel { + font-family: "Segoe UI light"; + font-size: 24px; + color: #4FC3F7; +} + +chatterino--TitleLabel2 { + font-family: "Segoe UI light"; + font-size: 24px; + color: #bbb; +} + +chatterino--DescriptionLabel { + color: #999; +} diff --git a/src/messages/layouts/MessageLayout.cpp b/src/messages/layouts/MessageLayout.cpp index ed79a93c..2bf11734 100644 --- a/src/messages/layouts/MessageLayout.cpp +++ b/src/messages/layouts/MessageLayout.cpp @@ -237,7 +237,7 @@ void MessageLayout::updateBuffer(QPixmap *buffer, int /*messageIndex*/, { backgroundColor = app->themes->messages.backgrounds.subscription; } - else if (getSettings()->alternateMessageBackground.getValue() && + else if (getSettings()->alternateMessages.getValue() && this->flags.has(MessageLayoutFlag::AlternateBackground)) { backgroundColor = app->themes->messages.backgrounds.alternate; diff --git a/src/providers/LinkResolver.cpp b/src/providers/LinkResolver.cpp index 679d9a5f..d7cc3a1f 100644 --- a/src/providers/LinkResolver.cpp +++ b/src/providers/LinkResolver.cpp @@ -28,7 +28,7 @@ void LinkResolver::getLinkInfo( if (statusCode == 200) { response = root.value("tooltip").toString(); - if (getSettings()->enableUnshortLinks) + if (getSettings()->unshortLinks) { linkString = root.value("link").toString(); } diff --git a/src/providers/ffz/FfzModBadge.cpp b/src/providers/ffz/FfzModBadge.cpp index 2ebe21f1..e4a6569e 100644 --- a/src/providers/ffz/FfzModBadge.cpp +++ b/src/providers/ffz/FfzModBadge.cpp @@ -48,6 +48,7 @@ void FfzModBadge::loadCustomModBadge() Url{url}}; this->badge_ = std::make_shared(emote); + // getBadge.execute(); return Success; }); diff --git a/src/providers/twitch/TwitchChannel.cpp b/src/providers/twitch/TwitchChannel.cpp index 38c5cf7d..c03ad2b6 100644 --- a/src/providers/twitch/TwitchChannel.cpp +++ b/src/providers/twitch/TwitchChannel.cpp @@ -474,12 +474,9 @@ void TwitchChannel::refreshLiveStatus() QString url("https://api.twitch.tv/kraken/streams/" + roomID); - //<<<<<<< HEAD // auto request = makeGetStreamRequest(roomID, QThread::currentThread()); - //======= auto request = NetworkRequest::twitchRequest(url); request.setCaller(QThread::currentThread()); - //>>>>>>> 9bfbdefd2f0972a738230d5b95a009f73b1dd933 request.onSuccess( [this, weak = weakOf(this)](auto result) -> Outcome { diff --git a/src/singletons/Settings.hpp b/src/singletons/Settings.hpp index 6593ba88..aa49cfca 100644 --- a/src/singletons/Settings.hpp +++ b/src/singletons/Settings.hpp @@ -25,7 +25,7 @@ public: /// Appearance BoolSetting showTimestamps = {"/appearance/messages/showTimestamps", true}; - BoolSetting enableAnimationsWhenFocused = { + BoolSetting animationsWhenFocused = { "/appearance/enableAnimationsWhenFocused", false}; QStringSetting timestampFormat = {"/appearance/messages/timestampFormat", "h:mm"}; @@ -48,26 +48,27 @@ public: // {"/appearance/messages/collapseLongMessages", false}; IntSetting collpseMessagesMinLines = { "/appearance/messages/collapseMessagesMinLines", 0}; - BoolSetting alternateMessageBackground = { + BoolSetting alternateMessages = { "/appearance/messages/alternateMessageBackground", false}; IntSetting uiScale = {"/appearance/uiScale", 0}; IntSetting boldScale = {"/appearance/boldScale", 57}; BoolSetting windowTopMost = {"/appearance/windowAlwaysOnTop", false}; BoolSetting showTabCloseButton = {"/appearance/showTabCloseButton", true}; + BoolSetting showTabLive = {"/appearance/showTabLiveButton", false}; BoolSetting hidePreferencesButton = {"/appearance/hidePreferencesButton", false}; BoolSetting hideUserButton = {"/appearance/hideUserButton", false}; BoolSetting enableSmoothScrolling = {"/appearance/smoothScrolling", true}; BoolSetting enableSmoothScrollingNewMessages = { "/appearance/smoothScrollingNewMessages", false}; - BoolSetting enableUsernameBold = {"/appearance/messages/boldUsernames", - false}; + BoolSetting boldUsernames = {"/appearance/messages/boldUsernames", false}; // BoolSetting customizable splitheader - BoolSetting showViewerCount = {"/appearance/splitheader/showViewerCount", - false}; - BoolSetting showTitle = {"/appearance/splitheader/showTitle", false}; - BoolSetting showGame = {"/appearance/splitheader/showGame", false}; - BoolSetting showUptime = {"/appearance/splitheader/showUptime", false}; + BoolSetting headerViewerCount = {"/appearance/splitheader/showViewerCount", + false}; + BoolSetting headerStreamTitle = {"/appearance/splitheader/showTitle", + false}; + BoolSetting headerGame = {"/appearance/splitheader/showGame", false}; + BoolSetting headerUptime = {"/appearance/splitheader/showUptime", false}; FloatSetting customThemeMultiplier = {"/appearance/customThemeMultiplier", -0.5f}; // BoolSetting useCustomWindowFrame = {"/appearance/useCustomWindowFrame", @@ -100,7 +101,7 @@ public: IntSetting smallStreamerLimit = { "/behaviour/autocompletion/smallStreamerLimit", 1000}; - BoolSetting pauseChatHover = {"/behaviour/pauseChatHover", false}; + BoolSetting pauseChatOnHover = {"/behaviour/pauseChatHover", false}; /// Commands BoolSetting allowCommandsAtEnd = {"/commands/allowCommandsAtEnd", false}; @@ -112,16 +113,16 @@ public: BoolSetting enableBttvEmotes = {"/emotes/enableBTTVEmotes", true}; BoolSetting enableFfzEmotes = {"/emotes/enableFFZEmotes", true}; BoolSetting enableEmojis = {"/emotes/enableEmojis", true}; - BoolSetting enableGifAnimations = {"/emotes/enableGifAnimations", true}; + BoolSetting animateEmotes = {"/emotes/enableGifAnimations", true}; FloatSetting emoteScale = {"/emotes/scale", 1.f}; QStringSetting emojiSet = {"/emotes/emojiSet", "EmojiOne 2"}; /// Links BoolSetting linksDoubleClickOnly = {"/links/doubleClickToOpen", false}; - BoolSetting enableLinkInfoTooltip = {"/links/linkInfoTooltip", false}; - BoolSetting enableUnshortLinks = {"/links/unshortLinks", false}; - BoolSetting enableLowercaseLink = {"/links/linkLowercase", true}; + BoolSetting linkInfoTooltip = {"/links/linkInfoTooltip", false}; + BoolSetting unshortLinks = {"/links/unshortLinks", false}; + BoolSetting lowercaseDomains = {"/links/linkLowercase", true}; /// Ignored phrases QStringSetting ignoredPhraseReplace = {"/ignore/ignoredPhraseReplace", diff --git a/src/singletons/Theme.cpp b/src/singletons/Theme.cpp index 67ceacb9..9098a1b1 100644 --- a/src/singletons/Theme.cpp +++ b/src/singletons/Theme.cpp @@ -28,7 +28,8 @@ namespace detail { { return -0.8; } - else if (themeName == "Custom") { + else if (themeName == "Custom") + { return getSettings()->customThemeMultiplier.getValue(); } @@ -214,7 +215,7 @@ void Theme::actuallyUpdate(double hue, double multiplier) this->messages.textColors.system = QColor(140, 127, 127); this->messages.backgrounds.regular = splits.background; - this->messages.backgrounds.alternate = getColor(0, sat, 0.93); + this->messages.backgrounds.alternate = getColor(0, sat, 0.95); if (isLight_) { diff --git a/src/singletons/WindowManager.cpp b/src/singletons/WindowManager.cpp index 2f771690..a77ed22a 100644 --- a/src/singletons/WindowManager.cpp +++ b/src/singletons/WindowManager.cpp @@ -82,8 +82,8 @@ WindowManager::WindowManager() this->wordFlagsListener_.addSetting(settings->enableEmojis); this->wordFlagsListener_.addSetting(settings->enableFfzEmotes); this->wordFlagsListener_.addSetting(settings->enableTwitchEmotes); - this->wordFlagsListener_.addSetting(settings->enableUsernameBold); - this->wordFlagsListener_.addSetting(settings->enableLowercaseLink); + this->wordFlagsListener_.addSetting(settings->boldUsernames); + this->wordFlagsListener_.addSetting(settings->lowercaseDomains); this->wordFlagsListener_.cb = [this](auto) { this->updateWordTypeMask(); // }; @@ -127,7 +127,7 @@ void WindowManager::updateWordTypeMask() // bits flags.set(MEF::BitsAmount); - flags.set(settings->enableGifAnimations ? MEF::BitsAnimated + flags.set(settings->animateEmotes ? MEF::BitsAnimated : MEF::BitsStatic); // badges @@ -147,9 +147,9 @@ void WindowManager::updateWordTypeMask() // misc flags.set(MEF::AlwaysShow); flags.set(MEF::Collapsed); - flags.set(settings->enableUsernameBold ? MEF::BoldUsername + flags.set(settings->boldUsernames ? MEF::BoldUsername : MEF::NonBoldUsername); - flags.set(settings->enableLowercaseLink ? MEF::LowercaseLink + flags.set(settings->lowercaseDomains ? MEF::LowercaseLink : MEF::OriginalLink); // update flags @@ -384,7 +384,7 @@ void WindowManager::initialize(Settings &settings, Paths &paths) settings.timestampFormat.connect( [this](auto, auto) { this->forceLayoutChannelViews(); }); - settings.alternateMessageBackground.connect( + settings.alternateMessages.connect( [this](auto, auto) { this->forceLayoutChannelViews(); }); settings.separateMessages.connect( [this](auto, auto) { this->forceLayoutChannelViews(); }); diff --git a/src/singletons/helper/GifTimer.cpp b/src/singletons/helper/GifTimer.cpp index 8f362452..28e1b77e 100644 --- a/src/singletons/helper/GifTimer.cpp +++ b/src/singletons/helper/GifTimer.cpp @@ -10,7 +10,7 @@ void GIFTimer::initialize() { this->timer.setInterval(30); - getSettings()->enableGifAnimations.connect([this](bool enabled, auto) { + getSettings()->animateEmotes.connect([this](bool enabled, auto) { if (enabled) this->timer.start(); else @@ -18,7 +18,7 @@ void GIFTimer::initialize() }); QObject::connect(&this->timer, &QTimer::timeout, [this] { - if (getSettings()->enableAnimationsWhenFocused && + if (getSettings()->animationsWhenFocused && qApp->activeWindow() == nullptr) return; diff --git a/src/util/FuzzyConvert.cpp b/src/util/FuzzyConvert.cpp new file mode 100644 index 00000000..cfdc3f01 --- /dev/null +++ b/src/util/FuzzyConvert.cpp @@ -0,0 +1,33 @@ +#include "FuzzyConvert.hpp" + +#include + +namespace chatterino { + +int fuzzyToInt(const QString &str, int default_) +{ + static auto intFinder = QRegularExpression("[0-9]+"); + + auto match = intFinder.match(str); + if (match.hasMatch()) + { + return match.captured().toInt(); + } + + return default_; +} + +float fuzzyToFloat(const QString &str, float default_) +{ + static auto floatFinder = QRegularExpression("[0-9]+(\\.[0-9]+)?"); + + auto match = floatFinder.match(str); + if (match.hasMatch()) + { + return match.captured().toFloat(); + } + + return default_; +} + +} // namespace chatterino diff --git a/src/util/FuzzyConvert.hpp b/src/util/FuzzyConvert.hpp new file mode 100644 index 00000000..a3875da9 --- /dev/null +++ b/src/util/FuzzyConvert.hpp @@ -0,0 +1,10 @@ +#pragma once + +#include + +namespace chatterino { + +int fuzzyToInt(const QString &str, int default_); +float fuzzyToFloat(const QString &str, float default_); + +} // namespace chatterino diff --git a/src/util/Helpers.hpp b/src/util/Helpers.hpp index dfb91b78..640a9840 100644 --- a/src/util/Helpers.hpp +++ b/src/util/Helpers.hpp @@ -19,43 +19,28 @@ static QString CreateUUID() static QString createLink(const QString &url, bool file = false) { - if (file) - { - return QString("" + url + - ""); - } - - return QString("" + - url + ""); + return QString("" + + url + ""; } static QString createNamedLink(const QString &url, const QString &name, bool file = false) { - if (file) - { - return QString("" + name + - ""); - } - - return QString("" + - name + ""); + return QString("" + + name + ""; } static QString shortenString(const QString &str, unsigned maxWidth = 50) { - if (str.size() <= maxWidth) + auto shortened = QString(str); + + if (str.size() > int(maxWidth)) { - return str; + shortened.resize(int(maxWidth)); + shortened += "..."; } - QString shortenedStr = str; - shortenedStr.resize(47); - shortenedStr += "..."; - - return shortenedStr; + return shortened; } } // namespace chatterino diff --git a/src/util/LayoutCreator.hpp b/src/util/LayoutCreator.hpp index bd137a43..b31fcef8 100644 --- a/src/util/LayoutCreator.hpp +++ b/src/util/LayoutCreator.hpp @@ -93,6 +93,13 @@ public: return *this; } + LayoutCreator withoutSpacing() + { + this->item_->setSpacing(0); + + return *this; + } + template ::value, int>::type = 0> diff --git a/src/widgets/dialogs/SettingsDialog.cpp b/src/widgets/dialogs/SettingsDialog.cpp index b7d1d1e9..bc25b017 100644 --- a/src/widgets/dialogs/SettingsDialog.cpp +++ b/src/widgets/dialogs/SettingsDialog.cpp @@ -11,6 +11,7 @@ #include "widgets/settingspages/EmotesPage.hpp" #include "widgets/settingspages/ExternalToolsPage.hpp" #include "widgets/settingspages/FeelPage.hpp" +#include "widgets/settingspages/GeneralPage.hpp" #include "widgets/settingspages/HighlightingPage.hpp" #include "widgets/settingspages/IgnoresPage.hpp" #include "widgets/settingspages/KeyboardSettingsPage.hpp" @@ -36,6 +37,8 @@ SettingsDialog::SettingsDialog() this->overrideBackgroundColor_ = QColor("#282828"); this->themeChangedEvent(); + + this->resize(766, 600); } void SettingsDialog::initUi() @@ -43,12 +46,18 @@ void SettingsDialog::initUi() LayoutCreator layoutCreator(this); // tab pages - layoutCreator.emplace() + layoutCreator.setLayoutType() + .withoutSpacing() + .emplace() .assign(&this->ui_.tabContainerContainer) .emplace() .withoutMargin() .assign(&this->ui_.tabContainer); + this->ui_.tabContainerContainer->layout()->setContentsMargins(8, 8, 0, 8); + + this->layout()->setSpacing(0); + // right side layout auto right = layoutCreator.emplace().withoutMargin(); { @@ -65,6 +74,8 @@ void SettingsDialog::initUi() } } + this->ui_.pageStack->setMargin(0); + // ---- misc this->ui_.tabContainerContainer->setObjectName("tabWidget"); this->ui_.pageStack->setObjectName("pages"); @@ -82,14 +93,19 @@ SettingsDialog *SettingsDialog::getHandle() void SettingsDialog::addTabs() { + this->ui_.tabContainer->setMargin(0); this->ui_.tabContainer->setSpacing(0); - this->addTab(new AccountsPage); + this->addTab(new GeneralPage); this->ui_.tabContainer->addSpacing(16); - this->addTab(new LookPage); - this->addTab(new FeelPage); + this->addTab(new AccountsPage); + + // this->ui_.tabContainer->addSpacing(16); + + // this->addTab(new LookPage); + // this->addTab(new FeelPage); this->ui_.tabContainer->addSpacing(16); @@ -105,7 +121,7 @@ void SettingsDialog::addTabs() this->addTab(this->ui_.moderationPage = new ModerationPage); this->addTab(new NotificationPage); // this->addTab(new SpecialChannelsPage); - this->addTab(new BrowserExtensionPage); + // this->addTab(new BrowserExtensionPage); this->addTab(new ExternalToolsPage); this->addTab(new AdvancedPage); @@ -139,7 +155,8 @@ void SettingsDialog::selectTab(SettingsDialogTab *tab) } tab->setSelected(true); - tab->setStyleSheet("background: #555; color: #FFF"); + tab->setStyleSheet( + "background: #161616; color: #4FC3F7; border: 1px solid #111"); this->selectedTab_ = tab; } @@ -201,7 +218,7 @@ void SettingsDialog::scaleChangedEvent(float newDpi) this->setStyleSheet(styleSheet); - this->ui_.tabContainerContainer->setFixedWidth(int(200 * newDpi)); + this->ui_.tabContainerContainer->setFixedWidth(int(150 * newDpi)); } void SettingsDialog::themeChangedEvent() diff --git a/src/widgets/helper/ChannelView.cpp b/src/widgets/helper/ChannelView.cpp index a7ea3548..8138bc44 100644 --- a/src/widgets/helper/ChannelView.cpp +++ b/src/widgets/helper/ChannelView.cpp @@ -927,7 +927,7 @@ void ChannelView::mouseMoveEvent(QMouseEvent *event) return; } - if (getSettings()->pauseChatHover.getValue()) + if (getSettings()->pauseChatOnHover.getValue()) { this->pause(CHAT_HOVER_PAUSE_DURATION); } @@ -1117,7 +1117,7 @@ void ChannelView::mouseMoveEvent(QMouseEvent *event) { tooltipWidget->hide(); } - else if (isLinkValid && !getSettings()->enableLinkInfoTooltip) + else if (isLinkValid && !getSettings()->linkInfoTooltip) { tooltipWidget->hide(); } diff --git a/src/widgets/helper/NotebookTab.cpp b/src/widgets/helper/NotebookTab.cpp index cbb801a4..c57d44b1 100644 --- a/src/widgets/helper/NotebookTab.cpp +++ b/src/widgets/helper/NotebookTab.cpp @@ -39,6 +39,8 @@ NotebookTab::NotebookTab(Notebook *notebook) getSettings()->showTabCloseButton.connect( boost::bind(&NotebookTab::hideTabXChanged, this, _1), this->managedConnections_); + getSettings()->showTabLive.connect([this](auto, auto) { this->update(); }, + this->managedConnections_); this->setMouseTracking(true); @@ -311,7 +313,7 @@ void NotebookTab::paintEvent(QPaintEvent *) : (windowFocused ? colors.line.regular : colors.line.unfocused)); // draw live indicator - if (this->isLive_) + if (this->isLive_ && getSettings()->showTabLive) { painter.setPen(QColor(Qt::GlobalColor::red)); painter.setRenderHint(QPainter::Antialiasing); @@ -355,6 +357,8 @@ void NotebookTab::paintEvent(QPaintEvent *) // draw close x if (this->shouldDrawXButton()) { + painter.setRenderHint(QPainter::Antialiasing, false); + QRect xRect = this->getXRect(); if (!xRect.isNull()) { diff --git a/src/widgets/settingspages/FeelPage.cpp b/src/widgets/settingspages/FeelPage.cpp index c74bbb67..70d1adb9 100644 --- a/src/widgets/settingspages/FeelPage.cpp +++ b/src/widgets/settingspages/FeelPage.cpp @@ -44,18 +44,17 @@ FeelPage::FeelPage() form->addRow("Pause chat:", this->createCheckBox(PAUSE_HOVERING, - getSettings()->pauseChatHover)); + getSettings()->pauseChatOnHover)); form->addRow("Mouse scroll speed:", this->createMouseScrollSlider()); form->addRow("Links:", this->createCheckBox("Open links only on double click", getSettings()->linksDoubleClickOnly)); - form->addRow( - "", this->createCheckBox("Show link info in tooltips", - getSettings()->enableLinkInfoTooltip)); + form->addRow("", this->createCheckBox("Show link info in tooltips", + getSettings()->linkInfoTooltip)); form->addRow( "", this->createCheckBox("Auto unshort links (requires restart)", - getSettings()->enableUnshortLinks)); + getSettings()->unshortLinks)); } layout->addSpacing(16); diff --git a/src/widgets/settingspages/GeneralPage.cpp b/src/widgets/settingspages/GeneralPage.cpp new file mode 100644 index 00000000..df0f62e8 --- /dev/null +++ b/src/widgets/settingspages/GeneralPage.cpp @@ -0,0 +1,327 @@ +#include "GeneralPage.hpp" + +#include +#include +#include + +#include "Application.hpp" +#include "singletons/Fonts.hpp" +#include "singletons/Theme.hpp" +#include "singletons/WindowManager.hpp" +#include "util/FuzzyConvert.hpp" +#include "util/Helpers.hpp" +#include "widgets/helper/Line.hpp" + +#define CHROME_EXTENSION_LINK \ + "https://chrome.google.com/webstore/detail/chatterino-native-host/" \ + "glknmaideaikkmemifbfkhnomoknepka" +#define FIREFOX_EXTENSION_LINK \ + "https://addons.mozilla.org/en-US/firefox/addon/chatterino-native-host/" + +namespace chatterino { + +TitleLabel *SettingsLayout::addTitle(const QString &title) +{ + auto label = new TitleLabel(title + ":"); + + if (this->count() != 0) + this->addSpacing(16); + + this->addWidget(label); + return label; +} + +TitleLabel2 *SettingsLayout::addTitle2(const QString &title) +{ + auto label = new TitleLabel2(title); + + this->addSpacing(16); + + this->addWidget(label); + return label; +} + +QCheckBox *SettingsLayout::addCheckbox(const QString &text, + BoolSetting &setting) +{ + auto check = new QCheckBox(text); + + // update when setting changes + setting.connect( + [check](const bool &value, auto) { check->setChecked(value); }, + this->managedConnections_); + + // update setting on toggle + QObject::connect(check, &QCheckBox::toggled, this, + [&setting](bool state) { setting = state; }); + + this->addWidget(check); + return check; +} + +QComboBox *SettingsLayout::addDropdown(const QString &text, + const QStringList &list) +{ + auto layout = new QHBoxLayout; + auto combo = new QComboBox; + combo->addItems(list); + + layout->addWidget(new QLabel(text + ":")); + layout->addStretch(1); + layout->addWidget(combo); + + this->addLayout(layout); + return combo; +} + +QComboBox *SettingsLayout::addDropdown( + const QString &text, const QStringList &items, + pajlada::Settings::Setting &setting) +{ + auto combo = this->addDropdown(text, 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; + getApp()->windows->forceLayoutChannelViews(); + }); + + return combo; +} + +DescriptionLabel *SettingsLayout::addDescription(const QString &text) +{ + auto label = new DescriptionLabel(text); + + label->setTextInteractionFlags(Qt::TextBrowserInteraction | + Qt::LinksAccessibleByKeyboard); + label->setOpenExternalLinks(true); + label->setWordWrap(true); + + this->addWidget(label); + + return label; +} + +void SettingsLayout::addSeperator() +{ + this->addWidget(new Line(false)); +} + +GeneralPage::GeneralPage() + : SettingsPage("General", ":/settings/about.svg") +{ + auto y = new QVBoxLayout; + auto scroll = new QScrollArea; + scroll->setWidgetResizable(true); + y->addWidget(scroll); + auto x = new QHBoxLayout; + auto layout = new SettingsLayout; + x->addStretch(1); + x->addLayout(layout, 0); + x->addStretch(1); + auto z = new QFrame; + z->setLayout(x); + scroll->setWidget(z); + this->setLayout(y); + + this->initLayout(*layout); + + layout->addStretch(1); + + this->initExtra(); +} + +void GeneralPage::initLayout(SettingsLayout &layout) +{ + auto &s = *getSettings(); + + layout.addTitle("Appearance"); + layout.addDropdown("Theme", {"White", "Light", "Dark", "Black"}, + getApp()->themes->themeName); + layout.addDropdown( + "Font", {"Segoe UI", "Arial", "Choose..."}, + getApp()->fonts->chatFontFamily, + [](auto val) { return QString::fromStdString(val); }, + [this](auto args) { return this->getFont(args); }); + layout.addDropdown( + "Font size", {"9pt", "10pt", "12pt", "14pt", "16pt", "20pt"}, + getApp()->fonts->chatFontSize, + [](auto val) { return QString::number(val) + "pt"; }, + [](auto args) { return fuzzyToInt(args.value, 10); }); + layout.addDropdown( + "UI Scale", + {"0.5x", "0.6x", "0.7x", "0.8x", "0.9x", "Default", "1.2x", "1.4x", + "1.6x", "1.8x", "2x", "2.33x", "2.66x", "3x", "3.5x", "4x"}, + s.uiScale, [](auto val) { return val + 5; }, + [](auto args) { return args.index - 5; }, false); + layout.addCheckbox("Always on top", s.windowTopMost); + + layout.addTitle("Interface"); + layout.addDropdown( + "Mouse scroll speed", {"0.5x", "0.75x", "Default", "1.5x", "2x"}, + s.mouseScrollMultiplier, + [](auto val) { + if (val == 1) + return QString("Default"); + else + return QString::number(val) + "x"; + }, + [](auto args) { return fuzzyToFloat(args.value, 1.f); }); + layout.addCheckbox("Smooth scrolling", s.enableSmoothScrolling); + layout.addCheckbox("Smooth scrolling on new messages.", + s.enableSmoothScrollingNewMessages); + layout.addCheckbox("Pause chat while hovering", s.pauseChatOnHover); + layout.addCheckbox("Show tab close button", s.showTabCloseButton); + layout.addCheckbox("Show input when empty", s.showEmptyInput); + layout.addCheckbox("Show input message length", s.showMessageLength); + + layout.addTitle("Messages"); + layout.addCheckbox("Timestamps", s.showTimestamps); + layout.addDropdown("Timestamp format", + {"hh:mm", "h:mm", "hh:mm a", "h:mm a"}, + s.timestampFormat); + layout.addDropdown( + "Collapse messages", + {"Never", "Longer than 2 lines", "Longer than 3 lines", + "Longer than 4 lines", "Longer than 5 lines"}, + s.collpseMessagesMinLines, + [](auto val) { + return val ? QString("After ") + QString::number(val) + " lines" + : QString("Never"); + }, + [](auto args) { return fuzzyToInt(args.value, 0); }); + layout.addCheckbox("Seperate with lines", s.separateMessages); + layout.addCheckbox("Alternate background color", s.alternateMessages); + // layout.addCheckbox("Mark last message you read"); + // layout.addDropdown("Last read message style", {"Default"}); + + layout.addTitle("Emotes"); + layout.addDropdown( + "Emote size", {"0.5x", "0.75x", "Default", "1.25", "1.5x", "2x"}, + s.emoteScale, + [](auto val) { + if (val == 1) + return QString("Default"); + else + return QString::number(val) + "x"; + }, + [](auto args) { return fuzzyToFloat(args.value, 1.f); }); + layout.addCheckbox("Gif animations", s.animateEmotes); + layout.addCheckbox("Animate only when focused", s.animationsWhenFocused); + layout.addDropdown("Emoji set", + {"EmojiOne 2", "EmojiOne 3", "Twitter", "Facebook", + "Apple", "Google", "Messenger"}); + + layout.addTitle("Badges"); + layout.addCheckbox("Show authority badges (staff, admin, turbo, etc)", + getSettings()->showBadgesGlobalAuthority); + layout.addCheckbox("Show channel badges (broadcaster, moderator)", + getSettings()->showBadgesChannelAuthority); + layout.addCheckbox("Show subscriber badges ", + getSettings()->showBadgesSubscription); + layout.addCheckbox("Show vanity badges (prime, bits, subgifter)", + getSettings()->showBadgesVanity); + layout.addCheckbox("Show chatterino badges", + getSettings()->showBadgesChatterino); + + layout.addTitle("Header"); + layout.addCheckbox("Show stream uptime", s.headerUptime); + layout.addCheckbox("Show stream viewer count", s.headerViewerCount); + layout.addCheckbox("Show stream category", s.headerGame); + layout.addCheckbox("Show stream title", s.headerStreamTitle); + + layout.addTitle("Miscellaneous"); + layout.addCheckbox("Show joined users (< 1000 chatters)", s.showJoins); + layout.addCheckbox("Show parted users (< 1000 chatters)", s.showParts); + layout.addDropdown("Boldness", {"Not implemented"}); + layout.addCheckbox("Lowercase domains", s.lowercaseDomains); + layout.addCheckbox("Bold @usernames", s.boldUsernames); + layout.addCheckbox("Show link info when hovering", s.linkInfoTooltip); + layout.addCheckbox("Double click links to open", s.linksDoubleClickOnly); + layout.addCheckbox("Unshorten links", s.unshortLinks); + layout.addCheckbox("Show live indicator in tabs", s.showTabLive); + + layout.addSpacing(16); + layout.addSeperator(); + + /* + layout.addTitle2("Cache"); + layout.addDescription("Chatterino saves files on disk to speed up loading " + "times and reduce network usage."); + this->cachePath = layout.addDescription("%cachePath%"); + layout.addDropdown("Cache directory", {"Automatic"}); + */ + + layout.addTitle2("Browser Integration"); + layout.addDescription("The browser extension replaces the default " + "Twitch.tv chat with chatterino."); + + layout.addDescription( + createNamedLink(CHROME_EXTENSION_LINK, "Download for Google Chrome")); + layout.addDescription( + createNamedLink(FIREFOX_EXTENSION_LINK, "Download for Firefox")); + + /* + layout.addTitle2("Streamlink"); + layout.addDescription("Streamlinks allows you to watch streams with " + "desktop media players like VLC."); + layout.addDescription( + createNamedLink("https://streamlink.github.io/", "Website") + " " + + createNamedLink("https://github.com/streamlink/streamlink/" + "releases/latest", + "Download")); + + layout.addDropdown("Executable path", {"Automatic"}); + layout.addDropdown("Preferred quality", {"Choose", "Source", "High", + "Medium", "Low", "Audio only"}); + layout.addDropdown("Command line arguments", {"..."}); + */ +} + +void GeneralPage::initExtra() +{ + /// update cache path + if (this->cachePath) + { + getSettings()->cachePath.connect( + [cachePath = this->cachePath](const auto &, auto) mutable { + QString newPath = getPaths()->cacheDirectory(); + + QString pathShortened = "Current location: " + + shortenString(newPath, 50) + ""; + + cachePath->setText(pathShortened); + cachePath->setToolTip(newPath); + }); + } +} + +std::string GeneralPage::getFont(const DropdownArgs &args) const +{ + if (args.combobox->currentIndex() == args.combobox->count() - 1) + { + args.combobox->setCurrentIndex(0); + args.combobox->setEditText("Choosing..."); + QFontDialog dialog(getApp()->fonts->getFont(FontStyle::ChatMedium, 1.)); + + dialog.setWindowFlag(Qt::WindowStaysOnTopHint); + + auto ok = bool(); + auto font = dialog.getFont(&ok); + + if (ok) + return font.family().toStdString(); + else + return args.combobox->itemText(0).toStdString(); + } + return args.value.toStdString(); +} + +} // namespace chatterino diff --git a/src/widgets/settingspages/GeneralPage.hpp b/src/widgets/settingspages/GeneralPage.hpp new file mode 100644 index 00000000..26a381b3 --- /dev/null +++ b/src/widgets/settingspages/GeneralPage.hpp @@ -0,0 +1,152 @@ +#pragma once + +#include +#include +#include + +#include "boost/variant.hpp" +#include "pajlada/signals/signal.hpp" +#include "singletons/Settings.hpp" +#include "widgets/settingspages/SettingsPage.hpp" + +class QLabel; +class QCheckBox; +class QComboBox; + +namespace chatterino { + +class TitleLabel : public QLabel +{ + Q_OBJECT + +public: + TitleLabel(const QString &text) + : QLabel(text) + { + } +}; + +class TitleLabel2 : public QLabel +{ + Q_OBJECT + +public: + TitleLabel2(const QString &text) + : QLabel(text) + { + } +}; + +class DescriptionLabel : public QLabel +{ + Q_OBJECT + +public: + DescriptionLabel(const QString &text) + : QLabel(text) + { + } +}; + +struct DropdownArgs { + QString value; + int index; + QComboBox *combobox; +}; + +class SettingsLayout : public QVBoxLayout +{ + Q_OBJECT + +public: + TitleLabel *addTitle(const QString &text); + TitleLabel2 *addTitle2(const QString &text); + QCheckBox *addCheckbox(const QString &text, BoolSetting &setting); + QComboBox *addDropdown(const QString &text, const QStringList &items); + QComboBox *addDropdown(const QString &text, const QStringList &items, + pajlada::Settings::Setting &setting); + + template + QComboBox *addDropdown( + const QString &text, const QStringList &items, + pajlada::Settings::Setting &setting, + std::function(T)> getValue, + std::function setValue, bool editable = true) + { + auto items2 = items; + auto selected = getValue(setting.getValue()); + + if (selected.which() == 1) + { + // QString + if (!editable && !items2.contains(boost::get(selected))) + items2.insert(0, boost::get(selected)); + } + + auto combo = this->addDropdown(text, items2); + if (editable) + combo->setEditable(true); + + if (selected.which() == 0) + { + // int + auto value = boost::get(selected); + if (value >= 0 && value < items2.size()) + combo->setCurrentIndex(value); + } + else if (selected.which() == 1) + { + // QString + combo->setEditText(boost::get(selected)); + } + + setting.connect( + [getValue = std::move(getValue), combo](const T &value, auto) { + auto var = getValue(value); + if (var.which() == 0) + combo->setCurrentIndex(boost::get(var)); + else + { + combo->setCurrentText(boost::get(var)); + combo->setEditText(boost::get(var)); + } + }, + this->managedConnections_); + + QObject::connect( + combo, + QOverload::of(&QComboBox::currentIndexChanged), + // &QComboBox::editTextChanged, + [combo, &setting, + setValue = std::move(setValue)](const QString &newValue) { + setting = setValue( + DropdownArgs{newValue, combo->currentIndex(), combo}); + getApp()->windows->forceLayoutChannelViews(); + }); + + return combo; + } + DescriptionLabel *addDescription(const QString &text); + void addSeperator(); + +private: + std::vector managedConnections_; +}; + +class GeneralPage : public SettingsPage +{ + Q_OBJECT + +public: + GeneralPage(); + +private: + void initLayout(SettingsLayout &layout); + void initExtra(); + + std::string getFont(const DropdownArgs &args) const; + + DescriptionLabel *cachePath{}; +}; + +} // namespace chatterino diff --git a/src/widgets/settingspages/LookPage.cpp b/src/widgets/settingspages/LookPage.cpp index 728563ba..04080d47 100644 --- a/src/widgets/settingspages/LookPage.cpp +++ b/src/widgets/settingspages/LookPage.cpp @@ -184,8 +184,8 @@ void LookPage::addMessageTab(LayoutCreator layout) getSettings()->separateMessages)); // alternate - layout.append(this->createCheckBox( - "Alternate background", getSettings()->alternateMessageBackground)); + layout.append(this->createCheckBox("Alternate background", + getSettings()->alternateMessages)); layout.append( this->createCheckBox("Compact emotes", getSettings()->compactEmotes)); @@ -204,14 +204,14 @@ void LookPage::addMessageTab(LayoutCreator layout) // bold usernames layout.append(this->createCheckBox("Bold mentions (@username)", - getSettings()->enableUsernameBold)); + getSettings()->boldUsernames)); // -- layout.emplace(false); // lowercase links layout.append(this->createCheckBox("Lowercase domains", - getSettings()->enableLowercaseLink)); + getSettings()->lowercaseDomains)); // collapsing { @@ -249,22 +249,11 @@ void LookPage::addMessageTab(LayoutCreator layout) void LookPage::addEmoteTab(LayoutCreator layout) { - /* - emotes.append( - 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)); - emotes.append(this->createCheckBox("Enable emojis", - getSettings()->enableEmojis)); - */ layout.append( - this->createCheckBox("Animations", getSettings()->enableGifAnimations)); + this->createCheckBox("Animations", getSettings()->animateEmotes)); layout.append( this->createCheckBox("Animations only when chatterino has focus", - getSettings()->enableAnimationsWhenFocused)); + getSettings()->animationsWhenFocused)); auto scaleBox = layout.emplace().withoutMargin(); { @@ -315,11 +304,12 @@ void LookPage::addEmoteTab(LayoutCreator layout) void LookPage::addSplitHeaderTab(LayoutCreator layout) { layout.append( - this->createCheckBox("Show uptime", getSettings()->showUptime)); + this->createCheckBox("Show uptime", getSettings()->headerUptime)); layout.append(this->createCheckBox("Show viewer count", - getSettings()->showViewerCount)); - layout.append(this->createCheckBox("Show game", getSettings()->showGame)); - layout.append(this->createCheckBox("Show title", getSettings()->showTitle)); + getSettings()->headerViewerCount)); + layout.append(this->createCheckBox("Show game", getSettings()->headerGame)); + layout.append( + this->createCheckBox("Show title", getSettings()->headerStreamTitle)); layout->addStretch(1); } diff --git a/src/widgets/settingspages/SettingsPage.hpp b/src/widgets/settingspages/SettingsPage.hpp index f394a3ac..79d3a724 100644 --- a/src/widgets/settingspages/SettingsPage.hpp +++ b/src/widgets/settingspages/SettingsPage.hpp @@ -12,8 +12,10 @@ namespace chatterino { class SettingsDialogTab; -class SettingsPage : public QWidget +class SettingsPage : public QFrame { + Q_OBJECT + public: SettingsPage(const QString &name, const QString &iconResource); diff --git a/src/widgets/splits/SplitHeader.cpp b/src/widgets/splits/SplitHeader.cpp index 199fd82e..351197fe 100644 --- a/src/widgets/splits/SplitHeader.cpp +++ b/src/widgets/splits/SplitHeader.cpp @@ -102,13 +102,13 @@ namespace { title += " (live)"; // description - if (settings.showUptime) + if (settings.headerUptime) title += " - " + s.uptime; - if (settings.showViewerCount) + if (settings.headerViewerCount) title += " - " + QString::number(s.viewerCount); - if (settings.showGame) + if (settings.headerGame) title += " - " + s.game; - if (settings.showTitle) + if (settings.headerStreamTitle) title += " - " + s.title; return title; @@ -142,10 +142,10 @@ SplitHeader::SplitHeader(Split *_split) [this] { this->updateModerationModeIcon(); }); auto _ = [this](const auto &, const auto &) { this->updateChannelText(); }; - getSettings()->showViewerCount.connect(_, this->managedConnections_); - getSettings()->showTitle.connect(_, this->managedConnections_); - getSettings()->showGame.connect(_, this->managedConnections_); - getSettings()->showUptime.connect(_, this->managedConnections_); + getSettings()->headerViewerCount.connect(_, this->managedConnections_); + getSettings()->headerStreamTitle.connect(_, this->managedConnections_); + getSettings()->headerGame.connect(_, this->managedConnections_); + getSettings()->headerUptime.connect(_, this->managedConnections_); } void SplitHeader::initializeLayout()