diff --git a/.clang-format b/.clang-format index a60c54689..6e663cb67 100644 --- a/.clang-format +++ b/.clang-format @@ -27,4 +27,4 @@ BraceWrapping: { BeforeCatch: 'false' } ColumnLimit: 100 -FixNamespaceComments: true \ No newline at end of file +FixNamespaceComments: true diff --git a/chatterino.pro b/chatterino.pro index 96d8bd3a6..f5b32d67c 100644 --- a/chatterino.pro +++ b/chatterino.pro @@ -223,7 +223,8 @@ SOURCES += \ src/singletons/Resources.cpp \ src/singletons/Settings.cpp \ src/singletons/Updates.cpp \ - src/singletons/Theme.cpp + src/singletons/Theme.cpp \ + src/controllers/moderationactions/ModerationActionModel.cpp HEADERS += \ src/Application.hpp \ @@ -393,7 +394,8 @@ HEADERS += \ src/singletons/Theme.hpp \ src/common/SimpleSignalVector.hpp \ src/common/SignalVector.hpp \ - src/common/Singleton.hpp + src/common/Singleton.hpp \ + src/controllers/moderationactions/ModerationActionModel.hpp RESOURCES += \ resources/resources.qrc \ diff --git a/resources/qss/settings.qss b/resources/qss/settings.qss index c3d731241..e7ee0a1ea 100644 --- a/resources/qss/settings.qss +++ b/resources/qss/settings.qss @@ -1,23 +1,7 @@ -#tabWidget { - background-color: #333; -} - * { font-size: px; } -SettingsDialogTab:hover { - border: 1px solid grey; -} - -QLabel, QCheckBox, QGroupBox, SettingsDialogTab { - color: white; -} - -QGroupBox { - background-color: #444; -} - QCheckBox::indicator { width: px; height: px; diff --git a/src/common/Channel.hpp b/src/common/Channel.hpp index 66e82e235..efa5b57c2 100644 --- a/src/common/Channel.hpp +++ b/src/common/Channel.hpp @@ -28,6 +28,7 @@ public: TwitchWatching, TwitchMentions, TwitchEnd, + Misc }; explicit Channel(const QString &_name, Type type); diff --git a/src/common/SignalVector.hpp b/src/common/SignalVector.hpp index f479cd85b..98253e451 100644 --- a/src/common/SignalVector.hpp +++ b/src/common/SignalVector.hpp @@ -50,6 +50,8 @@ public: } } + virtual bool isSorted() const = 0; + protected: std::vector vector; QTimer itemsChangedTimer; @@ -60,9 +62,10 @@ class BaseSignalVector : public ReadOnlySignalVector { public: // returns the actual index of the inserted item - virtual int insertItem(const TVectorItem &item, int proposedIndex = -1, void *caller = 0) = 0; + virtual int insertItem(const TVectorItem &item, int proposedIndex = -1, + void *caller = nullptr) = 0; - void removeItem(int index, void *caller = 0) + void removeItem(int index, void *caller = nullptr) { assertInGuiThread(); assert(index >= 0 && index < this->vector.size()); @@ -75,7 +78,7 @@ public: this->invokeDelayedItemsChanged(); } - int appendItem(const TVectorItem &item, void *caller = 0) + int appendItem(const TVectorItem &item, void *caller = nullptr) { return this->insertItem(item, -1, caller); } @@ -85,7 +88,7 @@ template class UnsortedSignalVector : public BaseSignalVector { public: - virtual int insertItem(const TVectorItem &item, int index = -1, void *caller = 0) override + virtual int insertItem(const TVectorItem &item, int index = -1, void *caller = nullptr) override { assertInGuiThread(); if (index == -1) { @@ -101,6 +104,11 @@ public: this->invokeDelayedItemsChanged(); return index; } + + virtual bool isSorted() const override + { + return false; + } }; template @@ -120,6 +128,11 @@ public: this->invokeDelayedItemsChanged(); return index; } + + virtual bool isSorted() const override + { + return true; + } }; } // namespace chatterino diff --git a/src/controllers/commands/CommandController.cpp b/src/controllers/commands/CommandController.cpp index e6f12c52e..0421d763f 100644 --- a/src/controllers/commands/CommandController.cpp +++ b/src/controllers/commands/CommandController.cpp @@ -171,8 +171,8 @@ QString CommandController::execCommand(const QString &text, ChannelPtr channel, auto target = words.at(1); if (user->isAnon()) { - channel->addMessage(Message::createSystemMessage( - "You must be logged in to ignore someone")); + channel->addMessage( + Message::createSystemMessage("You must be logged in to ignore someone")); return ""; } @@ -188,8 +188,8 @@ QString CommandController::execCommand(const QString &text, ChannelPtr channel, auto target = words.at(1); if (user->isAnon()) { - channel->addMessage(Message::createSystemMessage( - "You must be logged in to ignore someone")); + channel->addMessage( + Message::createSystemMessage("You must be logged in to ignore someone")); return ""; } diff --git a/src/controllers/moderationactions/ModerationAction.hpp b/src/controllers/moderationactions/ModerationAction.hpp index fe51be353..cc5adc39b 100644 --- a/src/controllers/moderationactions/ModerationAction.hpp +++ b/src/controllers/moderationactions/ModerationAction.hpp @@ -24,7 +24,7 @@ public: private: bool isImage_; - Image *image_; + Image *image_ = nullptr; QString line1_; QString line2_; QString action_; diff --git a/src/controllers/moderationactions/ModerationActionModel.cpp b/src/controllers/moderationactions/ModerationActionModel.cpp new file mode 100644 index 000000000..aa0fe134c --- /dev/null +++ b/src/controllers/moderationactions/ModerationActionModel.cpp @@ -0,0 +1,27 @@ +#include "ModerationActionModel.hpp" + +#include "util/StandardItemHelper.hpp" + +namespace chatterino { + +// commandmodel +ModerationActionModel ::ModerationActionModel(QObject *parent) + : SignalVectorModel(1, parent) +{ +} + +// turn a vector item into a model row +ModerationAction ModerationActionModel::getItemFromRow(std::vector &row, + const ModerationAction &original) +{ + return ModerationAction(row[0]->data(Qt::DisplayRole).toString()); +} + +// turns a row in the model into a vector item +void ModerationActionModel::getRowFromItem(const ModerationAction &item, + std::vector &row) +{ + setStringItem(row[0], item.getAction()); +} + +} // namespace chatterino diff --git a/src/controllers/moderationactions/ModerationActionModel.hpp b/src/controllers/moderationactions/ModerationActionModel.hpp new file mode 100644 index 000000000..3c8a11675 --- /dev/null +++ b/src/controllers/moderationactions/ModerationActionModel.hpp @@ -0,0 +1,31 @@ +#pragma once + +#include + +#include "common/SignalVectorModel.hpp" +#include "controllers/moderationactions/ModerationAction.hpp" + +namespace chatterino { + +class ModerationActions; + +class ModerationActionModel : public SignalVectorModel +{ +public: + explicit ModerationActionModel(QObject *parent); + +protected: + // turn a vector item into a model row + virtual ModerationAction getItemFromRow(std::vector &row, + const ModerationAction &original) override; + + // turns a row in the model into a vector item + virtual void getRowFromItem(const ModerationAction &item, + std::vector &row) override; + + friend class HighlightController; + + friend class ModerationActions; +}; + +} // namespace chatterino diff --git a/src/controllers/moderationactions/ModerationActions.cpp b/src/controllers/moderationactions/ModerationActions.cpp index 9d5095647..2b7b38ee5 100644 --- a/src/controllers/moderationactions/ModerationActions.cpp +++ b/src/controllers/moderationactions/ModerationActions.cpp @@ -1,6 +1,7 @@ #include "ModerationActions.hpp" #include "Application.hpp" +#include "controllers/moderationactions/ModerationActionModel.hpp" #include "singletons/Settings.hpp" #include @@ -25,4 +26,12 @@ void ModerationActions::initialize() }); } +ModerationActionModel *ModerationActions::createModel(QObject *parent) +{ + ModerationActionModel *model = new ModerationActionModel(parent); + model->init(&this->items); + + return model; +} + } // namespace chatterino diff --git a/src/controllers/moderationactions/ModerationActions.hpp b/src/controllers/moderationactions/ModerationActions.hpp index 823f97bad..1dcf77dc9 100644 --- a/src/controllers/moderationactions/ModerationActions.hpp +++ b/src/controllers/moderationactions/ModerationActions.hpp @@ -1,11 +1,13 @@ #pragma once +#include "common/ChatterinoSetting.hpp" #include "common/SignalVector.hpp" #include "controllers/moderationactions/ModerationAction.hpp" -#include "common/ChatterinoSetting.hpp" namespace chatterino { +class ModerationActionModel; + class ModerationActions { public: @@ -15,6 +17,8 @@ public: UnsortedSignalVector items; + ModerationActionModel *createModel(QObject *parent); + private: ChatterinoSetting> setting = {"/moderation/actions"}; bool initialized = false; diff --git a/src/messages/MessageBuilder.cpp b/src/messages/MessageBuilder.cpp index 9d19dbdd9..636bd91c0 100644 --- a/src/messages/MessageBuilder.cpp +++ b/src/messages/MessageBuilder.cpp @@ -47,8 +47,8 @@ QString MessageBuilder::matchLink(const QString &string) { LinkParser linkParser(string); - static QRegularExpression httpRegex("\\bhttps?://"); - static QRegularExpression ftpRegex("\\bftps?://"); + static QRegularExpression httpRegex("\\bhttps?://", QRegularExpression::CaseInsensitiveOption); + static QRegularExpression ftpRegex("\\bftps?://", QRegularExpression::CaseInsensitiveOption); if (!linkParser.hasMatch()) { return QString(); diff --git a/src/messages/MessageElement.cpp b/src/messages/MessageElement.cpp index 81d55b0d6..90420df17 100644 --- a/src/messages/MessageElement.cpp +++ b/src/messages/MessageElement.cpp @@ -247,7 +247,7 @@ void TwitchModerationElement::addToContainer(MessageLayoutContainer &container, MessageElement::Flags _flags) { if (_flags & MessageElement::ModeratorTools) { - QSize size((int)(container.getScale() * 16), (int)(container.getScale() * 16)); + QSize size(int(container.getScale() * 16), int(container.getScale() * 16)); for (const ModerationAction &m : getApp()->moderationActions->items.getVector()) { if (m.isImage()) { diff --git a/src/providers/bttv/BttvEmotes.cpp b/src/providers/bttv/BttvEmotes.cpp index ba44459b7..5780da47a 100644 --- a/src/providers/bttv/BttvEmotes.cpp +++ b/src/providers/bttv/BttvEmotes.cpp @@ -37,11 +37,11 @@ void BTTVEmotes::loadGlobalEmotes() EmoteData emoteData; emoteData.image1x = new Image(getEmoteLink(urlTemplate, id, "1x"), 1, code, - code + "
Global BTTV Emote"); - emoteData.image2x = new Image(getEmoteLink(urlTemplate, id, "2x"), 0.5, - code, code + "
Global BTTV Emote"); - emoteData.image3x = new Image(getEmoteLink(urlTemplate, id, "3x"), 0.25, - code, code + "
Global BTTV Emote"); + code + "
Global BTTV Emote"); + emoteData.image2x = new Image(getEmoteLink(urlTemplate, id, "2x"), 0.5, code, + code + "
Global BTTV Emote"); + emoteData.image3x = new Image(getEmoteLink(urlTemplate, id, "3x"), 0.25, code, + code + "
Global BTTV Emote"); emoteData.pageLink = "https://manage.betterttv.net/emotes/" + id; this->globalEmotes.insert(code, emoteData); @@ -89,19 +89,16 @@ void BTTVEmotes::loadChannelEmotes(const QString &channelName, std::weak_ptrChannel BTTV Emote"); + emoteData.image1x = new Image(link.replace("{{id}}", id).replace("{{image}}", "1x"), + 1, code, code + "
Channel BTTV Emote"); link = linkTemplate; link.detach(); - emoteData.image2x = - new Image(link.replace("{{id}}", id).replace("{{image}}", "2x"), - 0.5, code, code + "
Channel BTTV Emote"); + emoteData.image2x = new Image(link.replace("{{id}}", id).replace("{{image}}", "2x"), + 0.5, code, code + "
Channel BTTV Emote"); link = linkTemplate; link.detach(); - emoteData.image3x = - new Image(link.replace("{{id}}", id).replace("{{image}}", "3x"), - 0.25, code, code + "
Channel BTTV Emote"); + emoteData.image3x = new Image(link.replace("{{id}}", id).replace("{{image}}", "3x"), + 0.25, code, code + "
Channel BTTV Emote"); emoteData.pageLink = "https://manage.betterttv.net/emotes/" + id; return emoteData; diff --git a/src/providers/emoji/Emojis.cpp b/src/providers/emoji/Emojis.cpp index 1e57cd60b..277ba614c 100644 --- a/src/providers/emoji/Emojis.cpp +++ b/src/providers/emoji/Emojis.cpp @@ -260,8 +260,8 @@ void Emojis::loadEmojiSet() urlPrefix = it->second; } QString url = urlPrefix + code + ".png"; - emoji->emoteData.image1x = new Image( - url, 0.35, emoji->value, ":" + emoji->shortCodes[0] + ":
Emoji"); + emoji->emoteData.image1x = + new Image(url, 0.35, emoji->value, ":" + emoji->shortCodes[0] + ":
Emoji"); }); }); } diff --git a/src/providers/twitch/IrcMessageHandler.cpp b/src/providers/twitch/IrcMessageHandler.cpp index 9d1ea0d5e..904c772c8 100644 --- a/src/providers/twitch/IrcMessageHandler.cpp +++ b/src/providers/twitch/IrcMessageHandler.cpp @@ -253,8 +253,7 @@ void IrcMessageHandler::handleUserNoticeMessage(Communi::IrcMessage *message, Tw auto it = tags.find("system-msg"); if (it != tags.end()) { - auto newMessage = - Message::createSystemMessage(parseTagString(it.value().toString())); + auto newMessage = Message::createSystemMessage(parseTagString(it.value().toString())); newMessage->flags |= Message::Subscription; @@ -322,12 +321,22 @@ void IrcMessageHandler::handleNoticeMessage(Communi::IrcNoticeMessage *message) void IrcMessageHandler::handleWriteConnectionNoticeMessage(Communi::IrcNoticeMessage *message) { static std::unordered_set readConnectionOnlyIDs{ - "host_on", "host_off", "host_target_went_offline", "emote_only_on", "emote_only_off", - "slow_on", "slow_off", "subs_on", "subs_off", "r9k_on", "r9k_off", + "host_on", + "host_off", + "host_target_went_offline", + "emote_only_on", + "emote_only_off", + "slow_on", + "slow_off", + "subs_on", + "subs_off", + "r9k_on", + "r9k_off", // Display for user who times someone out. This implies you're a moderator, at which point // you will be connected to PubSub and receive a better message from there - "timeout_success", "ban_success", + "timeout_success", + "ban_success", }; QVariant v = message->tag("msg-id"); diff --git a/src/providers/twitch/TwitchServer.cpp b/src/providers/twitch/TwitchServer.cpp index e16c7760c..986981648 100644 --- a/src/providers/twitch/TwitchServer.cpp +++ b/src/providers/twitch/TwitchServer.cpp @@ -194,8 +194,7 @@ void TwitchServer::onMessageSendRequested(TwitchChannel *channel, const QString // check if you are sending messages too fast if (!lastMessage.empty() && lastMessage.back() + minMessageOffset > now) { if (this->lastErrorTimeSpeed_ + 30s < now) { - auto errorMessage = - Message::createSystemMessage("sending messages too fast"); + auto errorMessage = Message::createSystemMessage("sending messages too fast"); channel->addMessage(errorMessage); @@ -212,8 +211,7 @@ void TwitchServer::onMessageSendRequested(TwitchChannel *channel, const QString // check if you are sending too many messages if (lastMessage.size() >= maxMessageCount) { if (this->lastErrorTimeAmount_ + 30s < now) { - auto errorMessage = - Message::createSystemMessage("sending too many messages"); + auto errorMessage = Message::createSystemMessage("sending too many messages"); channel->addMessage(errorMessage); diff --git a/src/singletons/Paths.cpp b/src/singletons/Paths.cpp index 8df1bd4f6..4fee851b6 100644 --- a/src/singletons/Paths.cpp +++ b/src/singletons/Paths.cpp @@ -98,7 +98,6 @@ void Paths::initSubDirectories() // create settings subdirectories and validate that they are created properly auto makePath = [&](const std::string &name) -> QString { - auto path = combinePath(this->rootAppDataDirectory, QString::fromStdString(name)); if (!QDir().mkpath(path)) { diff --git a/src/widgets/BaseWindow.cpp b/src/widgets/BaseWindow.cpp index a7302cb80..a4360aa2f 100644 --- a/src/widgets/BaseWindow.cpp +++ b/src/widgets/BaseWindow.cpp @@ -434,6 +434,8 @@ bool BaseWindow::nativeEvent(const QByteArray &eventType, void *message, long *r default: return QWidget::nativeEvent(eventType, message, result); } +#else + return QWidget::nativeEvent(eventType, message, result); #endif } @@ -453,7 +455,12 @@ void BaseWindow::paintEvent(QPaintEvent *) painter.drawRect(0, 0, this->width() - 1, this->height() - 1); } - this->drawCustomWindowFrame(painter); + // this->drawCustomWindowFrame(painter); + // QPainter painter(this); + + QColor bg = this->overrideBackgroundColor_.value_or(this->themeManager->window.background); + + painter.fillRect(QRect(0, 1, this->width() - 0, this->height() - 0), bg); } void BaseWindow::updateScale() @@ -492,14 +499,16 @@ void BaseWindow::calcButtonsSizes() void BaseWindow::drawCustomWindowFrame(QPainter &painter) { -#ifdef USEWINSDK - if (this->hasCustomWindowFrame()) { - QPainter painter(this); + //#ifdef USEWINSDK + // if (this->hasCustomWindowFrame()) { + // QPainter painter(this); - painter.fillRect(QRect(0, 1, this->width() - 0, this->height() - 0), - this->themeManager->window.background); - } -#endif + // QColor bg = + // this->overrideBackgroundColor_.value_or(this->themeManager->window.background); + + // painter.fillRect(QRect(0, 1, this->width() - 0, this->height() - 0), bg); + // } + //#endif } bool BaseWindow::handleDPICHANGED(MSG *msg) diff --git a/src/widgets/BaseWindow.hpp b/src/widgets/BaseWindow.hpp index 6ba7c1be5..883cf0a4d 100644 --- a/src/widgets/BaseWindow.hpp +++ b/src/widgets/BaseWindow.hpp @@ -70,6 +70,8 @@ protected: void updateScale(); + boost::optional overrideBackgroundColor_; + private: void init(); void moveIntoDesktopRect(QWidget *parent); diff --git a/src/widgets/TooltipWidget.cpp b/src/widgets/TooltipWidget.cpp index a371f25bd..310eccc11 100644 --- a/src/widgets/TooltipWidget.cpp +++ b/src/widgets/TooltipWidget.cpp @@ -76,8 +76,7 @@ void TooltipWidget::updateFont() { auto app = getApp(); - this->setFont( - app->fonts->getFont(Fonts::Type::ChatMediumSmall, this->getScale())); + this->setFont(app->fonts->getFont(Fonts::Type::ChatMediumSmall, this->getScale())); } void TooltipWidget::setText(QString text) diff --git a/src/widgets/dialogs/SettingsDialog.cpp b/src/widgets/dialogs/SettingsDialog.cpp index 8dd7fb9c0..6b9bb9928 100644 --- a/src/widgets/dialogs/SettingsDialog.cpp +++ b/src/widgets/dialogs/SettingsDialog.cpp @@ -32,6 +32,8 @@ SettingsDialog::SettingsDialog() this->addTabs(); this->scaleChangedEvent(this->getScale()); + + this->overrideBackgroundColor_ = QColor("#282828"); } void SettingsDialog::initUi() @@ -149,8 +151,6 @@ void SettingsDialog::showDialog(PreferredTab preferredTab) void SettingsDialog::refresh() { - // this->ui.accountSwitchWidget->refresh(); - getApp()->settings->saveSnapshot(); for (auto *tab : this->tabs) { @@ -163,16 +163,16 @@ void SettingsDialog::scaleChangedEvent(float newDpi) QFile file(":/qss/settings.qss"); file.open(QFile::ReadOnly); QString styleSheet = QLatin1String(file.readAll()); - styleSheet.replace("", QString::number((int)(14 * newDpi))); - styleSheet.replace("", QString::number((int)(14 * newDpi))); + styleSheet.replace("", QString::number(int(14 * newDpi))); + styleSheet.replace("", QString::number(int(14 * newDpi))); for (SettingsDialogTab *tab : this->tabs) { - tab->setFixedHeight((int)(30 * newDpi)); + tab->setFixedHeight(int(30 * newDpi)); } this->setStyleSheet(styleSheet); - this->ui_.tabContainerContainer->setFixedWidth((int)(200 * newDpi)); + this->ui_.tabContainerContainer->setFixedWidth(int(200 * newDpi)); } void SettingsDialog::themeRefreshEvent() @@ -180,32 +180,10 @@ void SettingsDialog::themeRefreshEvent() BaseWindow::themeRefreshEvent(); QPalette palette; - palette.setColor(QPalette::Background, QColor("#444")); + palette.setColor(QPalette::Background, QColor("#f44")); this->setPalette(palette); } -// 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); -// // } -// // } -// // } -//} - ///// Widget creation helpers void SettingsDialog::okButtonClicked() { diff --git a/src/widgets/dialogs/UserInfoPopup.cpp b/src/widgets/dialogs/UserInfoPopup.cpp index 1165f3f17..b626d0012 100644 --- a/src/widgets/dialogs/UserInfoPopup.cpp +++ b/src/widgets/dialogs/UserInfoPopup.cpp @@ -364,9 +364,11 @@ UserInfoPopup::TimeoutWidget::TimeoutWidget() } a->setBorderColor(color1); - QObject::connect(a.getElement(), &RippleEffectLabel2::clicked, [ - this, timeout = std::get<1>(item) - ] { this->buttonClicked.invoke(std::make_pair(Action::Timeout, timeout)); }); + QObject::connect( + a.getElement(), &RippleEffectLabel2::clicked, + [this, timeout = std::get<1>(item)] { + this->buttonClicked.invoke(std::make_pair(Action::Timeout, timeout)); + }); } } }; @@ -375,16 +377,21 @@ UserInfoPopup::TimeoutWidget::TimeoutWidget() addTimeouts("sec", {{"1", 1}}); addTimeouts("min", { - {"1", 1 * 60}, {"5", 5 * 60}, {"10", 10 * 60}, + {"1", 1 * 60}, + {"5", 5 * 60}, + {"10", 10 * 60}, }); addTimeouts("hour", { - {"1", 1 * 60 * 60}, {"4", 4 * 60 * 60}, + {"1", 1 * 60 * 60}, + {"4", 4 * 60 * 60}, }); addTimeouts("days", { - {"1", 1 * 60 * 60 * 24}, {"3", 3 * 60 * 60 * 24}, + {"1", 1 * 60 * 60 * 24}, + {"3", 3 * 60 * 60 * 24}, }); addTimeouts("weeks", { - {"1", 1 * 60 * 60 * 24 * 7}, {"2", 2 * 60 * 60 * 24 * 7}, + {"1", 1 * 60 * 60 * 24 * 7}, + {"2", 2 * 60 * 60 * 24 * 7}, }); addButton(Ban, "ban", getApp()->resources->buttons.ban); diff --git a/src/widgets/helper/NotebookTab.cpp b/src/widgets/helper/NotebookTab.cpp index d14da7ae4..9efb54e60 100644 --- a/src/widgets/helper/NotebookTab.cpp +++ b/src/widgets/helper/NotebookTab.cpp @@ -238,8 +238,8 @@ void NotebookTab::paintEvent(QPaintEvent *) // || SettingsDialog::getHandle() == QApplication::activeWindow(); QBrush tabBackground = /*this->mouseOver_ ? colors.backgrounds.hover - :*/ (windowFocused ? colors.backgrounds.regular - : colors.backgrounds.unfocused); + :*/ + (windowFocused ? colors.backgrounds.regular : colors.backgrounds.unfocused); // painter.fillRect(rect(), this->mouseOver_ ? regular.backgrounds.hover // : (windowFocused ? regular.backgrounds.regular diff --git a/src/widgets/helper/ResizingTextEdit.cpp b/src/widgets/helper/ResizingTextEdit.cpp index 07544c72b..2bfc7ff04 100644 --- a/src/widgets/helper/ResizingTextEdit.cpp +++ b/src/widgets/helper/ResizingTextEdit.cpp @@ -93,8 +93,7 @@ void ResizingTextEdit::keyPressEvent(QKeyEvent *event) return; } - auto *completionModel = - static_cast(this->completer->model()); + auto *completionModel = static_cast(this->completer->model()); if (!this->completionInProgress) { // First type pressing tab after modifying a message, we refresh our completion model diff --git a/src/widgets/settingspages/AppearancePage.cpp b/src/widgets/settingspages/AppearancePage.cpp index 97d7459f9..f82402ad2 100644 --- a/src/widgets/settingspages/AppearancePage.cpp +++ b/src/widgets/settingspages/AppearancePage.cpp @@ -4,6 +4,7 @@ #include "singletons/WindowManager.hpp" #include "util/LayoutCreator.hpp" #include "util/RemoveScrollAreaBackground.hpp" +#include "widgets/helper/Line.hpp" #include #include @@ -23,8 +24,6 @@ #define SCROLL_SMOOTH "Enable smooth scrolling" #define SCROLL_NEWMSG "Enable smooth scrolling for new messages" -#define LAST_MSG "Mark the last message you read (dotted line)" - // 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 @@ -34,178 +33,206 @@ namespace chatterino { AppearancePage::AppearancePage() : SettingsPage("Look", ":/images/theme.svg") { - auto app = getApp(); LayoutCreator layoutCreator(this); - auto scroll = layoutCreator.emplace(); + auto xd = layoutCreator.emplace().withoutMargin(); + + // settings + auto scroll = xd.emplace(); auto widget = scroll.emplaceScrollAreaWidget(); removeScrollAreaBackground(scroll.getElement(), widget.getElement()); - auto layout = widget.setLayoutType(); + auto &layout = *widget.setLayoutType().withoutMargin(); - auto application = - layout.emplace("Application").emplace().withoutMargin(); - { - auto form = application.emplace(); + this->addApplicationGroup(layout); + this->addMessagesGroup(layout); + this->addEmotesGroup(layout); - auto *theme = this->createComboBox({THEME_ITEMS}, app->themes->themeName); - QObject::connect(theme, &QComboBox::currentTextChanged, - [](const QString &) { getApp()->windows->forceLayoutChannelViews(); }); + // preview + xd.emplace(false); - form->addRow("Theme:", theme); - // form->addRow("Theme color:", this->createThemeColorChanger()); - form->addRow("UI Scaling:", this->createUiScaleSlider()); - form->addRow("Font:", this->createFontChanger()); + auto channelView = xd.emplace(); + auto channel = this->createPreviewChannel(); + channelView->setChannel(channel); + channelView->setScaleIndependantHeight(64); - form->addRow("Tabs:", this->createCheckBox(TAB_X, app->settings->showTabCloseButton)); + layout.addStretch(1); +} + +void AppearancePage::addApplicationGroup(QVBoxLayout &layout) +{ + auto box = LayoutCreator(&layout) + .emplace("Application") + .emplace() + .withoutMargin(); + + auto form = box.emplace(); + + // theme + auto *theme = this->createComboBox({THEME_ITEMS}, getApp()->themes->themeName); + QObject::connect(theme, &QComboBox::currentTextChanged, + [](const QString &) { getApp()->windows->forceLayoutChannelViews(); }); + + form->addRow("Theme:", theme); + + // ui scale + form->addRow("UI Scaling:", this->createUiScaleSlider()); + + // font + form->addRow("Font:", this->createFontChanger()); + + // tab x + form->addRow("Tabs:", this->createCheckBox(TAB_X, getSettings()->showTabCloseButton)); + +// show buttons #ifndef USEWINSDK - form->addRow("", this->createCheckBox(TAB_PREF, app->settings->hidePreferencesButton)); - form->addRow("", this->createCheckBox(TAB_USER, app->settings->hideUserButton)); + form->addRow("", this->createCheckBox(TAB_PREF, app->settings->hidePreferencesButton)); + form->addRow("", this->createCheckBox(TAB_USER, app->settings->hideUserButton)); #endif - form->addRow("Scrolling:", - this->createCheckBox(SCROLL_SMOOTH, app->settings->enableSmoothScrolling)); - form->addRow("", this->createCheckBox(SCROLL_NEWMSG, - app->settings->enableSmoothScrollingNewMessages)); - } + // scrolling + form->addRow("Scrolling:", + this->createCheckBox(SCROLL_SMOOTH, getSettings()->enableSmoothScrolling)); + form->addRow( + "", this->createCheckBox(SCROLL_NEWMSG, getSettings()->enableSmoothScrollingNewMessages)); +} - auto messages = layout.emplace("Messages").emplace(); +void AppearancePage::addMessagesGroup(QVBoxLayout &layout) +{ + auto box = + LayoutCreator(&layout).emplace("Messages").emplace(); + + // timestamps + box.append(this->createCheckBox("Show timestamps", getSettings()->showTimestamps)); + auto tbox = box.emplace().withoutMargin(); { - messages.append(this->createCheckBox("Show timestamp", app->settings->showTimestamps)); - auto tbox = messages.emplace().withoutMargin(); - { - tbox.emplace("timestamp format (a = am/pm):"); - tbox.append(this->createComboBox({TIMESTAMP_FORMATS}, app->settings->timestampFormat)); - tbox->addStretch(1); - } - - messages.append(this->createCheckBox("Show badges", app->settings->showBadges)); - - { - auto *combo = new QComboBox(this); - combo->addItems({"Never", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", - "13", "14", "15"}); - const auto currentIndex = []() -> int { - auto val = getApp()->settings->collpseMessagesMinLines.getValue(); - if (val > 0) { - --val; - } - return val; - }(); - combo->setCurrentIndex(currentIndex); - - QObject::connect(combo, &QComboBox::currentTextChanged, [](const QString &str) { - getApp()->settings->collpseMessagesMinLines = str.toInt(); - }); - - auto hbox = messages.emplace().withoutMargin(); - hbox.emplace("Collapse messages longer than"); - hbox.append(combo); - hbox.emplace("lines"); - } - - messages.append(this->createCheckBox("Separate messages", app->settings->separateMessages)); - messages.append(this->createCheckBox("Alternate message background color", - app->settings->alternateMessageBackground)); - messages.append(this->createCheckBox("Show message length while typing", - app->settings->showMessageLength)); - - messages.append(this->createCheckBox(LAST_MSG, app->settings->showLastMessageIndicator)); - { - auto *combo = new QComboBox(this); - combo->addItems({"Dotted", "Solid"}); - - const auto currentIndex = []() -> int { - switch (getApp()->settings->lastMessagePattern.getValue()) { - case Qt::SolidLine: { - return 1; - } - default: - case Qt::VerPattern: { - return 0; - } - } - }(); - combo->setCurrentIndex(currentIndex); - - QObject::connect(combo, - static_cast(&QComboBox::currentIndexChanged), - [](int index) { - Qt::BrushStyle brush; - switch (index) { - case 1: - brush = Qt::SolidPattern; - break; - default: - case 0: - brush = Qt::VerPattern; - break; - } - getApp()->settings->lastMessagePattern = brush; - }); - - auto hbox = messages.emplace().withoutMargin(); - hbox.emplace("Last message indicator pattern"); - hbox.append(combo); - } + tbox.emplace("Timestamp format (a = am/pm):"); + tbox.append(this->createComboBox({TIMESTAMP_FORMATS}, getSettings()->timestampFormat)); + tbox->addStretch(1); } - auto emotes = layout.emplace("Emotes").setLayoutType(); + // badges + box.append(this->createCheckBox("Show badges", getSettings()->showBadges)); + + // collapsing { - /* - emotes.append( - this->createCheckBox("Enable Twitch emotes", app->settings->enableTwitchEmotes)); - emotes.append(this->createCheckBox("Enable BetterTTV emotes for Twitch", - app->settings->enableBttvEmotes)); - emotes.append(this->createCheckBox("Enable FrankerFaceZ emotes for Twitch", - app->settings->enableFfzEmotes)); - emotes.append(this->createCheckBox("Enable emojis", app->settings->enableEmojis)); - */ - emotes.append( - this->createCheckBox("Enable animations", app->settings->enableGifAnimations)); + auto *combo = new QComboBox(this); + combo->addItems( + {"Never", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15"}); - auto scaleBox = emotes.emplace(); - { - scaleBox.emplace("Emote scale:"); + const auto currentIndex = []() -> int { + auto val = getSettings()->collpseMessagesMinLines.getValue(); + if (val > 0) { + --val; + } + return val; + }(); + combo->setCurrentIndex(currentIndex); - auto emoteScale = scaleBox.emplace(Qt::Horizontal); - emoteScale->setMinimum(5); - emoteScale->setMaximum(50); + QObject::connect(combo, &QComboBox::currentTextChanged, [](const QString &str) { + getSettings()->collpseMessagesMinLines = str.toInt(); + }); - auto scaleLabel = scaleBox.emplace("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)); - - getApp()->settings->emoteScale.setValue(f); - }); - - emoteScale->setValue(std::max( - 5, std::min(50, (int)(app->settings->emoteScale.getValue() * 10.f)))); - - scaleLabel->setText(QString::number(app->settings->emoteScale.getValue())); - } - - { - auto *combo = new QComboBox(this); - combo->addItems({"EmojiOne 2", "EmojiOne 3", "Twitter", "Facebook", "Apple", "Google", - "Messenger"}); - - combo->setCurrentText(getApp()->settings->emojiSet); - - QObject::connect(combo, &QComboBox::currentTextChanged, [](const QString &str) { - getApp()->settings->emojiSet = str; // - }); - - auto hbox = emotes.emplace().withoutMargin(); - hbox.emplace("Emoji set"); - hbox.append(combo); - } + auto hbox = box.emplace().withoutMargin(); + hbox.emplace("Collapse messages longer than"); + hbox.append(combo); + hbox.emplace("lines"); } - layout->addStretch(1); + // seperate + box.append(this->createCheckBox("Separation lines", getSettings()->separateMessages)); + + // alternate + box.append(this->createCheckBox("Alternate background colors", + getSettings()->alternateMessageBackground)); +} + +void AppearancePage::addEmotesGroup(QVBoxLayout &layout) +{ + auto box = LayoutCreator(&layout) + .emplace("Emotes") + .setLayoutType(); + + /* + emotes.append( + this->createCheckBox("Enable Twitch emotes", app->settings->enableTwitchEmotes)); + emotes.append(this->createCheckBox("Enable BetterTTV emotes for Twitch", + app->settings->enableBttvEmotes)); + emotes.append(this->createCheckBox("Enable FrankerFaceZ emotes for Twitch", + app->settings->enableFfzEmotes)); + emotes.append(this->createCheckBox("Enable emojis", app->settings->enableEmojis)); + */ + box.append(this->createCheckBox("Animated emotes", getSettings()->enableGifAnimations)); + + auto scaleBox = box.emplace(); + { + scaleBox.emplace("Size:"); + + auto emoteScale = scaleBox.emplace(Qt::Horizontal); + emoteScale->setMinimum(5); + emoteScale->setMaximum(50); + + auto scaleLabel = scaleBox.emplace("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); + }); + + emoteScale->setValue( + std::max(5, std::min(50, int(getSettings()->emoteScale.getValue() * 10.f)))); + + scaleLabel->setText(QString::number(getSettings()->emoteScale.getValue())); + } + + { + auto *combo = new QComboBox(this); + combo->addItems( + {"EmojiOne 2", "EmojiOne 3", "Twitter", "Facebook", "Apple", "Google", "Messenger"}); + + combo->setCurrentText(getSettings()->emojiSet); + + QObject::connect(combo, &QComboBox::currentTextChanged, [](const QString &str) { + getSettings()->emojiSet = str; // + }); + + auto hbox = box.emplace().withoutMargin(); + hbox.emplace("Emoji set:"); + hbox.append(combo); + } +} + +ChannelPtr AppearancePage::createPreviewChannel() +{ + auto channel = ChannelPtr(new Channel("preview", Channel::Misc)); + + { + auto message = MessagePtr(new Message()); + message->addElement(new ImageElement(getApp()->resources->badgeModerator, + MessageElement::BadgeChannelAuthority)); + message->addElement(new ImageElement(getApp()->resources->badgeSubscriber, + MessageElement::BadgeSubscription)); + message->addElement(new TimestampElement()); + message->addElement(new TextElement("username1:", MessageElement::Username, + QColor("#0094FF"), FontStyle::ChatMediumBold)); + message->addElement(new TextElement("This is a preview message :)", MessageElement::Text)); + channel->addMessage(message); + } + { + auto message = MessagePtr(new Message()); + message->addElement(new ImageElement(getApp()->resources->badgePremium, + MessageElement::BadgeChannelAuthority)); + message->addElement(new TimestampElement()); + message->addElement(new TextElement("username2:", MessageElement::Username, + QColor("#FF6A00"), FontStyle::ChatMediumBold)); + message->addElement(new TextElement("This is another one :)", MessageElement::Text)); + channel->addMessage(message); + } + + return channel; } QLayout *AppearancePage::createThemeColorChanger() @@ -297,18 +324,15 @@ QLayout *AppearancePage::createUiScaleSlider() slider->setMinimum(WindowManager::uiScaleMin); slider->setMaximum(WindowManager::uiScaleMax); - slider->setValue( - WindowManager::clampUiScale(getApp()->settings->uiScale.getValue())); + slider->setValue(WindowManager::clampUiScale(getSettings()->uiScale.getValue())); label->setMinimumWidth(100); QObject::connect(slider, &QSlider::valueChanged, - [](auto value) { getApp()->settings->uiScale.setValue(value); }); + [](auto value) { getSettings()->uiScale.setValue(value); }); - getApp()->settings->uiScale.connect( - [label](auto, auto) { - label->setText(QString::number(WindowManager::getUiScaleValue())); - }, + getSettings()->uiScale.connect( + [label](auto, auto) { label->setText(QString::number(WindowManager::getUiScaleValue())); }, this->connections_); return layout; diff --git a/src/widgets/settingspages/AppearancePage.hpp b/src/widgets/settingspages/AppearancePage.hpp index fbd6803c2..ca7ea1102 100644 --- a/src/widgets/settingspages/AppearancePage.hpp +++ b/src/widgets/settingspages/AppearancePage.hpp @@ -1,10 +1,13 @@ #pragma once +#include "common/Channel.hpp" #include "widgets/settingspages/SettingsPage.hpp" #include #include +class QVBoxLayout; + namespace chatterino { class AppearancePage : public SettingsPage @@ -12,10 +15,16 @@ class AppearancePage : public SettingsPage public: AppearancePage(); + void addApplicationGroup(QVBoxLayout &layout); + void addMessagesGroup(QVBoxLayout &layout); + void addEmotesGroup(QVBoxLayout &layout); + QLayout *createThemeColorChanger(); QLayout *createFontChanger(); QLayout *createUiScaleSlider(); + ChannelPtr createPreviewChannel(); + std::vector connections_; }; diff --git a/src/widgets/settingspages/BehaviourPage.cpp b/src/widgets/settingspages/BehaviourPage.cpp index 905e9d771..621722ba0 100644 --- a/src/widgets/settingspages/BehaviourPage.cpp +++ b/src/widgets/settingspages/BehaviourPage.cpp @@ -15,6 +15,7 @@ #endif #define INPUT_EMPTY "Hide input box when empty" #define PAUSE_HOVERING "When hovering" +#define LAST_MSG "Mark the last message you read (dotted line)" #define LIMIT_CHATTERS_FOR_SMALLER_STREAMERS "Only fetch chatters list for viewers under X viewers" @@ -38,6 +39,48 @@ BehaviourPage::BehaviourPage() form->addRow( "", this->createCheckBox("Show which users parted the channel (up to 1000 chatters)", app->settings->showParts)); + + form->addRow("", this->createCheckBox("Show message length while typing", + getSettings()->showMessageLength)); + form->addRow("", this->createCheckBox(LAST_MSG, getSettings()->showLastMessageIndicator)); + { + auto *combo = new QComboBox(this); + combo->addItems({"Dotted", "Solid"}); + + const auto currentIndex = []() -> int { + switch (getApp()->settings->lastMessagePattern.getValue()) { + case Qt::SolidLine: { + return 1; + } + default: + case Qt::VerPattern: { + return 0; + } + } + }(); + combo->setCurrentIndex(currentIndex); + + QObject::connect(combo, + static_cast(&QComboBox::currentIndexChanged), + [](int index) { + Qt::BrushStyle brush; + switch (index) { + case 1: + brush = Qt::SolidPattern; + break; + default: + case 0: + brush = Qt::VerPattern; + break; + } + getSettings()->lastMessagePattern = brush; + }); + + auto hbox = form.emplace().withoutMargin(); + hbox.emplace("Last message indicator pattern"); + hbox.append(combo); + } + form->addRow("Pause chat:", this->createCheckBox(PAUSE_HOVERING, app->settings->pauseChatHover)); @@ -76,7 +119,7 @@ QSlider *BehaviourPage::createMouseScrollSlider() auto slider = new QSlider(Qt::Horizontal); float currentValue = app->settings->mouseScrollMultiplier; - int sliderValue = ((currentValue - 0.1f) / 2.f) * 99.f; + int sliderValue = int(((currentValue - 0.1f) / 2.f) * 99.f); slider->setValue(sliderValue); QObject::connect(slider, &QSlider::valueChanged, [=](int newValue) { diff --git a/src/widgets/settingspages/ModerationPage.cpp b/src/widgets/settingspages/ModerationPage.cpp index 20afe8ebe..4555e1834 100644 --- a/src/widgets/settingspages/ModerationPage.cpp +++ b/src/widgets/settingspages/ModerationPage.cpp @@ -1,6 +1,8 @@ #include "ModerationPage.hpp" #include "Application.hpp" +#include "controllers/moderationactions/ModerationActionModel.hpp" +#include "controllers/moderationactions/ModerationActions.hpp" #include "controllers/taggedusers/TaggedUsersController.hpp" #include "controllers/taggedusers/TaggedUsersModel.hpp" #include "singletons/Logging.hpp" @@ -8,6 +10,7 @@ #include "util/LayoutCreator.hpp" #include "widgets/helper/EditableModelView.hpp" +#include #include #include #include @@ -82,7 +85,7 @@ ModerationPage::ModerationPage() // Logs end } - auto modMode = tabs.appendTab(new QVBoxLayout, "Moderation mode"); + auto modMode = tabs.appendTab(new QVBoxLayout, "Moderation buttons"); { // clang-format off auto label = modMode.emplace("Click the moderation mod button () in a channel that you moderate to enable moderator mode.
"); @@ -97,26 +100,17 @@ ModerationPage::ModerationPage() // app->settings->timeoutAction)); // } - // auto modButtons = - // modMode.emplace("Custom moderator buttons").setLayoutType(); - // { - // auto label2 = - // modButtons.emplace("One action per line. {user} will be replaced with the - // " - // "username.
Example `/timeout {user} 120`
"); - // label2->setWordWrap(true); + EditableModelView *view = + modMode.emplace(app->moderationActions->createModel(nullptr)) + .getElement(); - // auto text = modButtons.emplace().getElement(); + view->setTitles({"Actions"}); + view->getTableView()->horizontalHeader()->setSectionResizeMode(QHeaderView::Fixed); + view->getTableView()->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch); - // text->setPlainText(app->moderationActions->items); - - // QObject::connect(text, &QTextEdit::textChanged, this, - // [this] { this->itemsChangedTimer.start(200); }); - - // QObject::connect(&this->itemsChangedTimer, &QTimer::timeout, this, [text, app]() { - // app->windows->moderationActions = text->toPlainText(); - // }); - // } + view->addButtonPressed.connect([] { + getApp()->moderationActions->items.appendItem(ModerationAction("/timeout {user} 300")); + }); /*auto taggedUsers = tabs.appendTab(new QVBoxLayout, "Tagged users"); { diff --git a/src/widgets/splits/SplitContainer.cpp b/src/widgets/splits/SplitContainer.cpp index ceef09ee0..6a250204d 100644 --- a/src/widgets/splits/SplitContainer.cpp +++ b/src/widgets/splits/SplitContainer.cpp @@ -581,8 +581,7 @@ void SplitContainer::decodeNodeRecusively(QJsonObject &obj, Node *node) auto _type = _obj.value("type"); if (_type == "split") { auto *split = new Split(this); - split->setChannel( - WindowManager::decodeChannel(_obj.value("data").toObject())); + split->setChannel(WindowManager::decodeChannel(_obj.value("data").toObject())); Node *_node = new Node(); _node->parent = node; @@ -605,8 +604,7 @@ void SplitContainer::decodeNodeRecusively(QJsonObject &obj, Node *node) for (int i = 0; i < 2; i++) { if (node->getChildren().size() < 2) { auto *split = new Split(this); - split->setChannel( - WindowManager::decodeChannel(obj.value("data").toObject())); + split->setChannel(WindowManager::decodeChannel(obj.value("data").toObject())); this->insertSplit(split, direction, node); } diff --git a/tools/clang-format-all.sh b/tools/clang-format-all.sh new file mode 100755 index 000000000..275d856d3 --- /dev/null +++ b/tools/clang-format-all.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +read -p "Are you sure you want to run clang-format on all files in src/? (y/n) " -n 1 -r +echo +if [[ $REPLY =~ ^[Yy]$ ]]; then + find src/ -iname "*.hpp" -o -iname "*.cpp" -exec clang-format -i {} \; +fi