diff --git a/chatterino.pro b/chatterino.pro index c9987cfc7..c0626b5cb 100644 --- a/chatterino.pro +++ b/chatterino.pro @@ -4,7 +4,7 @@ # #------------------------------------------------- -QT += core gui network +QT += core gui network multimedia CONFIG += communi COMMUNI += core model util CONFIG += c++14 diff --git a/lib/settings b/lib/settings index d3faa9b39..1282c351d 160000 --- a/lib/settings +++ b/lib/settings @@ -1 +1 @@ -Subproject commit d3faa9b3996e0871473b0e2b1821c93a50821f40 +Subproject commit 1282c351db528f9e2f166b2bb1c217c9d67a8bc8 diff --git a/resources/resources.qrc b/resources/resources.qrc index 0195cedce..e1e4f1a76 100644 --- a/resources/resources.qrc +++ b/resources/resources.qrc @@ -31,5 +31,6 @@ images/StatusAnnotations_Blocked_16xLG_color.png images/UserProfile_22x.png images/VSO_Link_blue_16x.png + sounds/ping2.wav diff --git a/resources/sounds/ping2.wav b/resources/sounds/ping2.wav new file mode 100644 index 000000000..0a83c0007 Binary files /dev/null and b/resources/sounds/ping2.wav differ diff --git a/src/messages/message.cpp b/src/messages/message.cpp index 36ec05263..6b3797c9a 100644 --- a/src/messages/message.cpp +++ b/src/messages/message.cpp @@ -29,9 +29,10 @@ Message::Message(const QString &text) } */ -Message::Message(const QString &text, const std::vector &words) +Message::Message(const QString &text, const std::vector &words, const bool &highlight) : text(text) , words(words) + , highlightTab(highlight) { } diff --git a/src/messages/message.hpp b/src/messages/message.hpp index f6a843f41..1aa708c47 100644 --- a/src/messages/message.hpp +++ b/src/messages/message.hpp @@ -24,7 +24,7 @@ class Message { public: // explicit Message(const QString &text); - explicit Message(const QString &text, const std::vector &words); + explicit Message(const QString &text, const std::vector &words, const bool &highlight); bool getCanHighlightTab() const; const QString &getTimeoutUser() const; diff --git a/src/messages/messagebuilder.cpp b/src/messages/messagebuilder.cpp index 6c2bf89f7..aa1fa95cc 100644 --- a/src/messages/messagebuilder.cpp +++ b/src/messages/messagebuilder.cpp @@ -16,7 +16,7 @@ MessageBuilder::MessageBuilder() SharedMessage MessageBuilder::build() { - return SharedMessage(new Message(this->originalMessage, _words)); + return SharedMessage(new Message(this->originalMessage, _words,highlight)); } void MessageBuilder::appendWord(const Word &word) @@ -31,6 +31,10 @@ void MessageBuilder::appendTimestamp() appendTimestamp(t); } +void MessageBuilder::setHighlight(const bool &value){ + highlight = value; +} + void MessageBuilder::appendTimestamp(time_t time) { char timeStampBuffer[69]; diff --git a/src/messages/messagebuilder.hpp b/src/messages/messagebuilder.hpp index fddd63169..27c01737b 100644 --- a/src/messages/messagebuilder.hpp +++ b/src/messages/messagebuilder.hpp @@ -18,6 +18,7 @@ public: void appendWord(const Word &word); void appendTimestamp(); void appendTimestamp(std::time_t time); + void setHighlight(const bool &value); QString matchLink(const QString &string); QRegularExpression regex; @@ -26,6 +27,7 @@ public: private: std::vector _words; + bool highlight = false; std::chrono::time_point _parseTime; }; diff --git a/src/setting.hpp b/src/setting.hpp index e69bfa1dd..73fc850db 100644 --- a/src/setting.hpp +++ b/src/setting.hpp @@ -43,6 +43,10 @@ public: return _value; } + T &getnonConst() { + return _value; + } + void set(const T &newValue) { if (_value != newValue) { @@ -65,6 +69,12 @@ public: } } + void insertMap(QString id, bool sound, bool task){ + QPair pair(sound,task); + _value.insert(id,pair); + } + + boost::signals2::signal valueChanged; private: diff --git a/src/settingsmanager.cpp b/src/settingsmanager.cpp index 33134ff6f..81cf0b250 100644 --- a/src/settingsmanager.cpp +++ b/src/settingsmanager.cpp @@ -27,9 +27,12 @@ SettingsManager::SettingsManager() , mentionUsersWithAt(_settingsItems, "mentionUsersWithAt", false) , allowCommandsAtEnd(_settingsItems, "allowCommandsAtEnd", false) , enableHighlights(_settingsItems, "enableHighlights", true) + , enableHighlightsSelf(_settingsItems,"enableHighlightsSelf", true) , enableHighlightSound(_settingsItems, "enableHighlightSound", true) , enableHighlightTaskbar(_settingsItems, "enableHighlightTaskbar", true) , customHighlightSound(_settingsItems, "customHighlightSound", false) + , pathHighlightSound(_settingsItems, "pathHighlightSound", "qrc:/sounds/ping2.wav") + , highlightProperties(_settingsItems,"highlightProperties",QMap>()) , enableTwitchEmotes(_settingsItems, "enableTwitchEmotes", true) , enableBttvEmotes(_settingsItems, "enableBttvEmotes", true) , enableFfzEmotes(_settingsItems, "enableFfzEmotes", true) @@ -61,17 +64,44 @@ SettingsManager::SettingsManager() void SettingsManager::save() { for (auto &item : _settingsItems) { - _settings.setValue(item.get().getName(), item.get().getVariant()); + if(item.get().getName() != "highlightProperties"){ + _settings.setValue(item.get().getName(), item.get().getVariant()); + } else { + _settings.beginGroup("Highlights"); + QStringList list = highlightProperties.get().keys(); + list.removeAll(""); + _settings.remove(""); + for (auto string : list){ + _settings.beginGroup(string); + _settings.setValue("highlightSound",highlightProperties.get().value(string).first); + _settings.setValue("highlightTask",highlightProperties.get().value(string).second); + _settings.endGroup(); + } + _settings.endGroup(); + } } } void SettingsManager::load() { for (auto &item : _settingsItems) { - item.get().setVariant(_settings.value(item.get().getName())); + if(item.get().getName() != "highlightProperties"){ + item.get().setVariant(_settings.value(item.get().getName())); + } else { + _settings.beginGroup("Highlights"); + QStringList list = _settings.childGroups(); + qDebug() << list.join(","); + for (auto string : list){ + _settings.beginGroup(string); + highlightProperties.insertMap(string,_settings.value("highlightSound").toBool(),_settings.value("highlightTask").toBool()); + _settings.endGroup(); + } + _settings.endGroup(); + } } } + Word::Type SettingsManager::getWordTypeMask() { return _wordTypeMask; @@ -129,7 +159,11 @@ SettingsSnapshot SettingsManager::createSnapshot() SettingsSnapshot snapshot; for (auto &item : this->_settingsItems) { + if(item.get().getName() != "highlightProperties"){ snapshot.addItem(item, item.get().getVariant()); + } else { + snapshot._mapItems = highlightProperties.get(); + } } return snapshot; diff --git a/src/settingsmanager.hpp b/src/settingsmanager.hpp index 57ad83371..c59564e01 100644 --- a/src/settingsmanager.hpp +++ b/src/settingsmanager.hpp @@ -57,9 +57,12 @@ public: Setting mentionUsersWithAt; Setting allowCommandsAtEnd; Setting enableHighlights; + Setting enableHighlightsSelf; Setting enableHighlightSound; Setting enableHighlightTaskbar; Setting customHighlightSound; + Setting pathHighlightSound; + Setting>> highlightProperties; Setting enableTwitchEmotes; Setting enableBttvEmotes; Setting enableFfzEmotes; diff --git a/src/settingssnapshot.hpp b/src/settingssnapshot.hpp index d17225c74..990352acf 100644 --- a/src/settingssnapshot.hpp +++ b/src/settingssnapshot.hpp @@ -8,6 +8,7 @@ struct SettingsSnapshot { public: SettingsSnapshot() : _items() + , _mapItems() { } @@ -17,6 +18,12 @@ public: std::pair, QVariant>(setting.get(), value)); } + void addMapItem(QString string,QPair pair){ + QMap> map; + _mapItems.insert(string,pair); + } + + void apply() { for (auto &item : _items) { @@ -24,6 +31,8 @@ public: } } + QMap> _mapItems; + private: std::vector, QVariant>> _items; }; diff --git a/src/twitch/twitchmessagebuilder.cpp b/src/twitch/twitchmessagebuilder.cpp index 11fc29990..4d1ed7fea 100644 --- a/src/twitch/twitchmessagebuilder.cpp +++ b/src/twitch/twitchmessagebuilder.cpp @@ -3,8 +3,13 @@ #include "emotemanager.hpp" #include "ircmanager.hpp" #include "resources.hpp" +#include "settingsmanager.hpp" #include "windowmanager.hpp" +#include +#include +#include + using namespace chatterino::messages; namespace chatterino { @@ -48,7 +53,41 @@ SharedMessage TwitchMessageBuilder::parse() this->parseUsername(); // highlights - // TODO: implement this xD + const QString &originalMessage = ircMessage->content(); + this->originalMessage = originalMessage; + SettingsManager &settings = SettingsManager::getInstance(); + static auto player = new QMediaPlayer; + if(settings.customHighlightSound.get()){ + player->setMedia(QUrl(settings.pathHighlightSound.get())); + } else { + player->setMedia(QUrl("qrc:/sounds/ping2.wav")); + } + if(settings.enableHighlights.get() && ircMessage->nick().compare(settings.selectedUser.get(), Qt::CaseInsensitive)){ + if(settings.enableHighlightsSelf.get() && originalMessage.contains(settings.selectedUser.get(), Qt::CaseInsensitive)){ + this->setHighlight(true); + if(settings.enableHighlightSound.get()){ + player->play(); + } + if(settings.enableHighlightTaskbar.get()){ + QApplication::alert(windowManager.getMainWindow().window(),2500); + } + } else { + QStringList lines = settings.highlightProperties.get().keys(); + for(QString string : lines){ + if(originalMessage.contains(string,Qt::CaseInsensitive)){ + this->setHighlight(true); + // Sound + if(settings.highlightProperties.get().value(string).first){ + player->play(); + } + // Taskbar + if(settings.highlightProperties.get().value(string).second){ + QApplication::alert(windowManager.getMainWindow().window(),2500); + } + } + } + } + } // bits QString bits = ""; @@ -85,8 +124,6 @@ SharedMessage TwitchMessageBuilder::parse() // words QColor textColor = ircMessage->isAction() ? this->usernameColor : this->colorScheme.Text; - const QString &originalMessage = ircMessage->content(); - this->originalMessage = originalMessage; QStringList splits = originalMessage.split(' '); long int i = 0; diff --git a/src/twitch/twitchmessagebuilder.hpp b/src/twitch/twitchmessagebuilder.hpp index 64dd5fb65..96efbc812 100644 --- a/src/twitch/twitchmessagebuilder.hpp +++ b/src/twitch/twitchmessagebuilder.hpp @@ -53,6 +53,7 @@ private: std::string roomID; QColor usernameColor; + bool highlight; void parseMessageID(); void parseRoomID(); diff --git a/src/widgets/chatwidgetview.cpp b/src/widgets/chatwidgetview.cpp index b360b4415..0ef5e2053 100644 --- a/src/widgets/chatwidgetview.cpp +++ b/src/widgets/chatwidgetview.cpp @@ -227,8 +227,7 @@ void ChatWidgetView::paintEvent(QPaintEvent * /*event*/) // update messages that have been changed if (updateBuffer) { QPainter painter(buffer); - painter.fillRect(buffer->rect(), this->colorScheme.ChatBackground); - + painter.fillRect(buffer->rect(), (messageRef->getMessage()->getCanHighlightTab()) ? this->colorScheme.ChatBackgroundHighlighted : this->colorScheme.ChatBackground); for (messages::WordPart const &wordPart : messageRef->getWordParts()) { // image if (wordPart.getWord().isImage()) { diff --git a/src/widgets/settingsdialog.cpp b/src/widgets/settingsdialog.cpp index 14de56c5c..2459746e7 100644 --- a/src/widgets/settingsdialog.cpp +++ b/src/widgets/settingsdialog.cpp @@ -11,10 +11,12 @@ #include #include #include +#include #include #include #include #include +#include #include namespace chatterino { @@ -106,6 +108,23 @@ void SettingsDialog::addTabs() listWidget->addItem(user.getUserName()); } + if(listWidget->count()){ + int itemIndex = 0; + for(; itemIndex < listWidget->count(); ++itemIndex){ + if(listWidget->item(itemIndex)->text().compare(settings.selectedUser.get(),Qt::CaseInsensitive)){ + ++itemIndex; + break; + } + } + listWidget->setCurrentRow(itemIndex); + } + + QObject::connect(listWidget,&QListWidget::clicked,this,[&,listWidget]{ + if(!listWidget->selectedItems().isEmpty()){ + settings.selectedUser.set(listWidget->currentItem()->text()); + } + }); + vbox->addWidget(listWidget); } @@ -347,6 +366,105 @@ void SettingsDialog::addTabs() // Highlighting vbox = new QVBoxLayout(); + auto highlights = new QListWidget(); + globalHighlights = highlights; + QStringList items = settings.highlightProperties.get().keys(); + highlights->addItems(items); + auto customSound = new QHBoxLayout(); + auto soundForm = new QFormLayout(); + { + vbox->addWidget(createCheckbox("Enable Highlighting", settings.enableHighlights)); + vbox->addWidget(createCheckbox("Highlight messages containing your name", settings.enableHighlightsSelf)); + vbox->addWidget(createCheckbox("Play sound when your name is mentioned", settings.enableHighlightSound)); + vbox->addWidget(createCheckbox("Flash taskbar when your name is mentioned", settings.enableHighlightTaskbar)); + customSound->addWidget(createCheckbox("Custom sound", settings.customHighlightSound)); + auto selectBtn = new QPushButton("Select"); + QObject::connect(selectBtn,&QPushButton::clicked,this,[&settings,this]{ + auto fileName = QFileDialog::getOpenFileName(this, + tr("Open Sound"), "", tr("Image Files (*.mp3 *.wav)")); + settings.pathHighlightSound.set(fileName); + }); + customSound->addWidget(selectBtn); + } + + soundForm->addRow(customSound); + + { + auto hbox = new QHBoxLayout(); + auto addBtn = new QPushButton("Add"); + auto editBtn = new QPushButton("Edit"); + auto delBtn = new QPushButton("Remove"); + + QObject::connect(addBtn,&QPushButton::clicked,this,[highlights,this,&settings]{ + auto show = new QWidget(); + auto box = new QBoxLayout(QBoxLayout::TopToBottom); + + auto edit = new QLineEdit(); + auto add = new QPushButton("Add"); + + auto sound = new QCheckBox("Play sound"); + auto task = new QCheckBox("Flash taskbar"); + + QObject::connect(add,&QPushButton::clicked,this,[=,&settings]{ + if(edit->text().length()){ + highlights->addItem(edit->text()); + settings.highlightProperties.insertMap(edit->text(),sound->isChecked(),task->isChecked()); + show->close(); + } + }); + box->addWidget(edit); + box->addWidget(add); + box->addWidget(sound); + box->addWidget(task); + show->setLayout(box); + show->show(); + }); + QObject::connect(editBtn,&QPushButton::clicked,this,[highlights,this,&settings]{ + if(!highlights->selectedItems().isEmpty()){ + auto show = new QWidget(); + auto box = new QBoxLayout(QBoxLayout::TopToBottom); + + auto edit = new QLineEdit(); + edit->setText(highlights->selectedItems().first()->text()); + auto add = new QPushButton("Apply"); + + auto sound = new QCheckBox("Play sound"); + auto task = new QCheckBox("Flash taskbar"); + + QObject::connect(add,&QPushButton::clicked,this,[=,&settings]{ + if(edit->text().length()){ + settings.highlightProperties.getnonConst().remove(highlights->selectedItems().first()->text()); + delete highlights->selectedItems().first(); + highlights->addItem(edit->text()); + settings.highlightProperties.insertMap(edit->text(),sound->isChecked(),task->isChecked()); + show->close(); + } + }); + box->addWidget(edit); + box->addWidget(add); + box->addWidget(sound); + sound->setChecked(settings.highlightProperties.get().value(highlights->selectedItems().first()->text()).first); + box->addWidget(task); + task->setChecked(settings.highlightProperties.get().value(highlights->selectedItems().first()->text()).second); + show->setLayout(box); + show->show(); + } + }); + QObject::connect(delBtn,&QPushButton::clicked,this,[highlights,&settings]{ + if(!highlights->selectedItems().isEmpty()){ + settings.highlightProperties.getnonConst().remove(highlights->selectedItems().first()->text()); + delete highlights->selectedItems().first(); + } + }); + vbox->addLayout(soundForm); + vbox->addWidget(highlights); + + hbox->addWidget(addBtn); + hbox->addWidget(editBtn); + hbox->addWidget(delBtn); + + vbox->addLayout(hbox); + } vbox->addStretch(1); addTab(vbox, "Highlighting", ":/images/format_Bold_16xLG.png"); @@ -461,7 +579,18 @@ void SettingsDialog::okButtonClicked() void SettingsDialog::cancelButtonClicked() { // TODO: Re-implement the snapshot feature properly + auto &instance = SettingsManager::getInstance(); + this->snapshot.apply(); + instance.highlightProperties.set(this->snapshot._mapItems); + + QStringList list = instance.highlightProperties.get().keys(); + list.removeDuplicates(); + while(globalHighlights->count()>0) + { + delete globalHighlights->takeItem(0); + } + globalHighlights->addItems(list); this->close(); } diff --git a/src/widgets/settingsdialog.hpp b/src/widgets/settingsdialog.hpp index 982d6247c..cb8988610 100644 --- a/src/widgets/settingsdialog.hpp +++ b/src/widgets/settingsdialog.hpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -51,6 +52,8 @@ private: SettingsDialogTab *selectedTab = nullptr; + QListWidget* globalHighlights; + /// Widget creation helpers QCheckBox *createCheckbox(const QString &title, Setting &setting); QCheckBox *createCheckbox(const QString &title, pajlada::Settings::Setting &setting);