From c43c1dc207b3ace4b75cfaded48874e96b915bbd Mon Sep 17 00:00:00 2001 From: hemirt <1310440+hemirt@users.noreply.github.com> Date: Fri, 10 May 2019 22:36:37 +0200 Subject: [PATCH] Adds option to mute ping sound for specific channels (#990) Co-Authored-By: hemirt --- chatterino.pro | 4 ++ src/Application.cpp | 2 + src/Application.hpp | 2 + src/controllers/pings/PingController.cpp | 70 +++++++++++++++++++ src/controllers/pings/PingController.hpp | 36 ++++++++++ src/controllers/pings/PingModel.cpp | 28 ++++++++ src/controllers/pings/PingModel.hpp | 28 ++++++++ src/providers/twitch/TwitchMessageBuilder.cpp | 10 ++- src/widgets/splits/SplitHeader.cpp | 18 +++++ 9 files changed, 195 insertions(+), 3 deletions(-) create mode 100644 src/controllers/pings/PingController.cpp create mode 100644 src/controllers/pings/PingController.hpp create mode 100644 src/controllers/pings/PingModel.cpp create mode 100644 src/controllers/pings/PingModel.hpp diff --git a/chatterino.pro b/chatterino.pro index 68eff9568..2cb069551 100644 --- a/chatterino.pro +++ b/chatterino.pro @@ -198,6 +198,8 @@ SOURCES += \ src/widgets/splits/SplitOverlay.cpp \ src/widgets/StreamView.cpp \ src/widgets/Window.cpp \ + src/controllers/pings/PingController.cpp \ + src/controllers/pings/PingModel.cpp \ HEADERS += \ src/Application.hpp \ @@ -382,6 +384,8 @@ HEADERS += \ src/widgets/splits/SplitOverlay.hpp \ src/widgets/StreamView.hpp \ src/widgets/Window.hpp \ + src/controllers/pings/PingController.hpp \ + src/controllers/pings/PingModel.hpp \ RESOURCES += \ resources/resources.qrc \ diff --git a/src/Application.cpp b/src/Application.cpp index d92e6e896..42067d9bd 100644 --- a/src/Application.cpp +++ b/src/Application.cpp @@ -6,6 +6,7 @@ #include "controllers/ignores/IgnoreController.hpp" #include "controllers/moderationactions/ModerationActions.hpp" #include "controllers/notifications/NotificationController.hpp" +#include "controllers/pings/PingController.hpp" #include "controllers/taggedusers/TaggedUsersController.hpp" #include "debug/Log.hpp" #include "messages/MessageBuilder.hpp" @@ -53,6 +54,7 @@ Application::Application(Settings &_settings, Paths &_paths) , commands(&this->emplace()) , highlights(&this->emplace()) , notifications(&this->emplace()) + , pings(&this->emplace()) , ignores(&this->emplace()) , taggedUsers(&this->emplace()) , moderationActions(&this->emplace()) diff --git a/src/Application.hpp b/src/Application.hpp index c872a4c62..49c8fe96c 100644 --- a/src/Application.hpp +++ b/src/Application.hpp @@ -18,6 +18,7 @@ class TaggedUsersController; class AccountController; class ModerationActions; class NotificationController; +class PingController; class Theme; class WindowManager; @@ -62,6 +63,7 @@ public: CommandController *const commands{}; HighlightController *const highlights{}; NotificationController *const notifications{}; + PingController *const pings{}; IgnoreController *const ignores{}; TaggedUsersController *const taggedUsers{}; ModerationActions *const moderationActions{}; diff --git a/src/controllers/pings/PingController.cpp b/src/controllers/pings/PingController.cpp new file mode 100644 index 000000000..0f0ed37d8 --- /dev/null +++ b/src/controllers/pings/PingController.cpp @@ -0,0 +1,70 @@ +#include "controllers/pings/PingController.hpp" +#include "controllers/pings/PingModel.hpp" + +namespace chatterino { + +void PingController::initialize(Settings &settings, Paths &paths) +{ + this->initialized_ = true; + for (const QString &channelName : this->pingSetting_.getValue()) + { + this->channelVector.appendItem(channelName); + } + + this->channelVector.delayedItemsChanged.connect([this] { // + this->pingSetting_.setValue(this->channelVector.getVector()); + }); +} + +PingModel *PingController::createModel(QObject *parent) +{ + PingModel *model = new PingModel(parent); + model->init(&this->channelVector); + return model; +} + +bool PingController::isMuted(const QString &channelName) +{ + for (const auto &channel : this->channelVector.getVector()) + { + if (channelName.toLower() == channel.toLower()) + { + return true; + } + } + return false; +} + +void PingController::muteChannel(const QString &channelName) +{ + channelVector.appendItem(channelName); +} + +void PingController::unmuteChannel(const QString &channelName) +{ + for (std::vector::size_type i = 0; + i != channelVector.getVector().size(); i++) + { + if (channelVector.getVector()[i].toLower() == channelName.toLower()) + { + channelVector.removeItem(i); + i--; + } + } +} + +bool PingController::toggleMuteChannel(const QString &channelName) +{ + if (this->isMuted(channelName)) + { + unmuteChannel(channelName); + return false; + } + else + { + muteChannel(channelName); + return true; + } +} + +} // namespace chatterino diff --git a/src/controllers/pings/PingController.hpp b/src/controllers/pings/PingController.hpp new file mode 100644 index 000000000..80805e856 --- /dev/null +++ b/src/controllers/pings/PingController.hpp @@ -0,0 +1,36 @@ +#pragma once + +#include + +#include "common/SignalVector.hpp" +#include "common/Singleton.hpp" +#include "singletons/Settings.hpp" + +namespace chatterino { + +class Settings; +class Paths; + +class PingModel; + +class PingController final : public Singleton, private QObject +{ +public: + virtual void initialize(Settings &settings, Paths &paths) override; + + bool isMuted(const QString &channelName); + void muteChannel(const QString &channelName); + void unmuteChannel(const QString &channelName); + bool toggleMuteChannel(const QString &channelName); + + PingModel *createModel(QObject *parent); + +private: + bool initialized_ = false; + + UnsortedSignalVector channelVector; + + ChatterinoSetting> pingSetting_ = {"/pings/muted"}; +}; + +} // namespace chatterino diff --git a/src/controllers/pings/PingModel.cpp b/src/controllers/pings/PingModel.cpp new file mode 100644 index 000000000..28098a209 --- /dev/null +++ b/src/controllers/pings/PingModel.cpp @@ -0,0 +1,28 @@ +#include "PingModel.hpp" + +#include "Application.hpp" +#include "singletons/Settings.hpp" +#include "util/StandardItemHelper.hpp" + +namespace chatterino { + +PingModel::PingModel(QObject *parent) + : SignalVectorModel(1, parent) +{ +} + +// turn a vector item into a model row +QString PingModel::getItemFromRow(std::vector &row, + const QString &original) +{ + return QString(row[0]->data(Qt::DisplayRole).toString()); +} + +// turn a model +void PingModel::getRowFromItem(const QString &item, + std::vector &row) +{ + setStringItem(row[0], item); +} + +} // namespace chatterino diff --git a/src/controllers/pings/PingModel.hpp b/src/controllers/pings/PingModel.hpp new file mode 100644 index 000000000..137be5e0c --- /dev/null +++ b/src/controllers/pings/PingModel.hpp @@ -0,0 +1,28 @@ +#pragma once + +#include + +#include "common/SignalVectorModel.hpp" +#include "controllers/notifications/NotificationController.hpp" + +namespace chatterino { + +class PingController; + +class PingModel : public SignalVectorModel +{ + explicit PingModel(QObject *parent); + +protected: + // turn a vector item into a model row + virtual QString getItemFromRow(std::vector &row, + const QString &original) override; + + // turns a row in the model into a vector item + virtual void getRowFromItem(const QString &item, + std::vector &row) override; + + friend class PingController; +}; + +} // namespace chatterino diff --git a/src/providers/twitch/TwitchMessageBuilder.cpp b/src/providers/twitch/TwitchMessageBuilder.cpp index c39889aba..c386d2c8d 100644 --- a/src/providers/twitch/TwitchMessageBuilder.cpp +++ b/src/providers/twitch/TwitchMessageBuilder.cpp @@ -4,6 +4,7 @@ #include "controllers/accounts/AccountController.hpp" #include "controllers/highlights/HighlightController.hpp" #include "controllers/ignores/IgnoreController.hpp" +#include "controllers/pings/PingController.hpp" #include "debug/Log.hpp" #include "messages/Message.hpp" #include "providers/chatterino/ChatterinoBadges.hpp" @@ -885,13 +886,16 @@ void TwitchMessageBuilder::parseHighlights(bool isPastMsg) if (!isPastMsg) { - if (playSound && - (!hasFocus || getSettings()->highlightAlwaysPlaySound)) + bool notMuted = !getApp()->pings->isMuted(this->channel->getName()); + bool resolveFocus = + !hasFocus || getSettings()->highlightAlwaysPlaySound; + + if (playSound && notMuted && resolveFocus) { player->play(); } - if (doAlert) + if (doAlert && notMuted) { getApp()->windows->sendAlert(); } diff --git a/src/widgets/splits/SplitHeader.cpp b/src/widgets/splits/SplitHeader.cpp index 8f4baa179..bd8949073 100644 --- a/src/widgets/splits/SplitHeader.cpp +++ b/src/widgets/splits/SplitHeader.cpp @@ -4,6 +4,7 @@ #include "controllers/accounts/AccountController.hpp" #include "controllers/moderationactions/ModerationActions.hpp" #include "controllers/notifications/NotificationController.hpp" +#include "controllers/pings/PingController.hpp" #include "providers/twitch/TwitchChannel.hpp" #include "providers/twitch/TwitchServer.hpp" #include "singletons/Resources.hpp" @@ -297,6 +298,23 @@ std::unique_ptr SplitHeader::createMainMenu() moreMenu->addAction(action); + { + auto action = new QAction(this); + action->setText("Mute highlight sound"); + action->setCheckable(true); + + QObject::connect(moreMenu, &QMenu::aboutToShow, this, [action, this]() { + action->setChecked(getApp()->pings->isMuted( + this->split_->getChannel()->getName())); + }); + action->connect(action, &QAction::triggered, this, [this]() { + getApp()->pings->toggleMuteChannel( + this->split_->getChannel()->getName()); + }); + + moreMenu->addAction(action); + } + moreMenu->addSeparator(); moreMenu->addAction("Reconnect", this, SLOT(reconnect())); moreMenu->addAction("Reload channel emotes", this,