From f7dd6de8725a132242e7d3ce2389b52f72061138 Mon Sep 17 00:00:00 2001 From: unknown <1310440+hemirt@users.noreply.github.com> Date: Mon, 14 Oct 2024 17:28:16 +0200 Subject: [PATCH 01/28] highlight tabs only on unviewed messages --- src/widgets/helper/ChannelView.cpp | 6 ++- src/widgets/helper/ChannelView.hpp | 8 ++-- src/widgets/helper/NotebookTab.cpp | 61 +++++++++++++++++++++++++++ src/widgets/helper/NotebookTab.hpp | 3 ++ src/widgets/splits/SplitContainer.cpp | 6 ++- 5 files changed, 76 insertions(+), 8 deletions(-) diff --git a/src/widgets/helper/ChannelView.cpp b/src/widgets/helper/ChannelView.cpp index 066085030d0..54d5dded5ec 100644 --- a/src/widgets/helper/ChannelView.cpp +++ b/src/widgets/helper/ChannelView.cpp @@ -1190,11 +1190,13 @@ void ChannelView::messageAppended(MessagePtr &message, (this->channel_->getType() == Channel::Type::TwitchAutomod && getSettings()->enableAutomodHighlight)) { - this->tabHighlightRequested.invoke(HighlightState::Highlighted); + this->tabHighlightRequested.invoke(HighlightState::Highlighted, + message); } else { - this->tabHighlightRequested.invoke(HighlightState::NewMessage); + this->tabHighlightRequested.invoke(HighlightState::NewMessage, + message); } } diff --git a/src/widgets/helper/ChannelView.hpp b/src/widgets/helper/ChannelView.hpp index 7042107125a..56dd15aa003 100644 --- a/src/widgets/helper/ChannelView.hpp +++ b/src/widgets/helper/ChannelView.hpp @@ -179,6 +179,9 @@ class ChannelView final : public BaseWidget LimitedQueueSnapshot &getMessagesSnapshot(); + // Returns true if message should be included + bool shouldIncludeMessage(const MessagePtr &m) const; + void queueLayout(); void invalidateBuffers(); @@ -214,7 +217,7 @@ class ChannelView final : public BaseWidget pajlada::Signals::Signal mouseDown; pajlada::Signals::NoArgSignal selectionChanged; - pajlada::Signals::Signal tabHighlightRequested; + pajlada::Signals::Signal tabHighlightRequested; pajlada::Signals::NoArgSignal liveStatusChanged; pajlada::Signals::Signal linkClicked; pajlada::Signals::Signal @@ -374,9 +377,6 @@ class ChannelView final : public BaseWidget FilterSetPtr channelFilters_; - // Returns true if message should be included - bool shouldIncludeMessage(const MessagePtr &m) const; - // Returns whether the scrollbar should have highlights bool showScrollbarHighlights() const; diff --git a/src/widgets/helper/NotebookTab.cpp b/src/widgets/helper/NotebookTab.cpp index be2b371a3b0..72e28f5de0b 100644 --- a/src/widgets/helper/NotebookTab.cpp +++ b/src/widgets/helper/NotebookTab.cpp @@ -10,8 +10,10 @@ #include "singletons/WindowManager.hpp" #include "util/Helpers.hpp" #include "widgets/dialogs/SettingsDialog.hpp" +#include "widgets/helper/ChannelView.hpp" #include "widgets/Notebook.hpp" #include "widgets/splits/DraggedSplit.hpp" +#include "widgets/splits/Split.hpp" #include "widgets/splits/SplitContainer.hpp" #include @@ -381,6 +383,65 @@ void NotebookTab::setHighlightState(HighlightState newHighlightStyle) this->update(); } +void NotebookTab::setHighlightState(HighlightState newHighlightStyle, + ChannelView &channelViewSource, + MessagePtr message) +{ + if (this->isSelected()) + { + return; + } + + if (!this->highlightEnabled_ && + newHighlightStyle == HighlightState::NewMessage) + { + return; + } + + if (this->highlightState_ == newHighlightStyle || + this->highlightState_ == HighlightState::Highlighted) + { + return; + } + + auto splitContainer = + dynamic_cast(this->notebook_->getSelectedPage()); + if (splitContainer != nullptr) + { + const auto &splits = splitContainer->getSplits(); + for (const auto &split : splits) + { + auto &&filterIdsSource = channelViewSource.getFilterIds(); + auto uniqueFilterIdsSource = + QSet(filterIdsSource.cbegin(), filterIdsSource.cend()); + auto &&filterIdsSplit = split->getChannelView().getFilterIds(); + auto uniqueFilterIdsSplit = + QSet(filterIdsSplit.cbegin(), filterIdsSplit.cend()); + + auto isSubset = [](QSet sub, QSet super) { + for (auto &&subItem : sub) + { + if (!super.contains(subItem)) + { + return false; + } + } + return true; + }; + + if (channelViewSource.underlyingChannel() == split->getChannel() && + split->getChannelView().shouldIncludeMessage(message) && + isSubset(uniqueFilterIdsSource, uniqueFilterIdsSplit)) + { + return; + } + } + } + + this->highlightState_ = newHighlightStyle; + this->update(); +} + HighlightState NotebookTab::highlightState() const { return this->highlightState_; diff --git a/src/widgets/helper/NotebookTab.hpp b/src/widgets/helper/NotebookTab.hpp index 6ae7802d0d0..601957803fc 100644 --- a/src/widgets/helper/NotebookTab.hpp +++ b/src/widgets/helper/NotebookTab.hpp @@ -14,6 +14,7 @@ namespace chatterino { inline constexpr int NOTEBOOK_TAB_HEIGHT = 28; class SplitContainer; +class ChannelView; class NotebookTab : public Button { @@ -60,6 +61,8 @@ class NotebookTab : public Button bool isLive() const; void setHighlightState(HighlightState style); + void setHighlightState(HighlightState style, ChannelView &channelViewSource, + MessagePtr message); HighlightState highlightState() const; void setHighlightsEnabled(const bool &newVal); diff --git a/src/widgets/splits/SplitContainer.cpp b/src/widgets/splits/SplitContainer.cpp index c2ddc1160b2..6f289326509 100644 --- a/src/widgets/splits/SplitContainer.cpp +++ b/src/widgets/splits/SplitContainer.cpp @@ -214,10 +214,12 @@ void SplitContainer::addSplit(Split *split) auto &&conns = this->connectionsPerSplit_[split]; conns.managedConnect(split->getChannelView().tabHighlightRequested, - [this](HighlightState state) { + [this, &channelView = split->getChannelView()]( + HighlightState state, MessagePtr message) { if (this->tab_ != nullptr) { - this->tab_->setHighlightState(state); + this->tab_->setHighlightState( + state, channelView, message); } }); From e827097c1c9c6619650dab2890e0f8617100cb27 Mon Sep 17 00:00:00 2001 From: unknown <1310440+hemirt@users.noreply.github.com> Date: Tue, 15 Oct 2024 01:08:02 +0200 Subject: [PATCH 02/28] fix suggestions --- src/widgets/helper/NotebookTab.cpp | 15 +++++---------- src/widgets/helper/NotebookTab.hpp | 2 +- src/widgets/splits/SplitContainer.cpp | 2 +- 3 files changed, 7 insertions(+), 12 deletions(-) diff --git a/src/widgets/helper/NotebookTab.cpp b/src/widgets/helper/NotebookTab.cpp index 72e28f5de0b..f343ccdb25b 100644 --- a/src/widgets/helper/NotebookTab.cpp +++ b/src/widgets/helper/NotebookTab.cpp @@ -385,7 +385,7 @@ void NotebookTab::setHighlightState(HighlightState newHighlightStyle) void NotebookTab::setHighlightState(HighlightState newHighlightStyle, ChannelView &channelViewSource, - MessagePtr message) + const MessagePtr &message) { if (this->isSelected()) { @@ -404,7 +404,7 @@ void NotebookTab::setHighlightState(HighlightState newHighlightStyle, return; } - auto splitContainer = + auto *splitContainer = dynamic_cast(this->notebook_->getSelectedPage()); if (splitContainer != nullptr) { @@ -419,14 +419,9 @@ void NotebookTab::setHighlightState(HighlightState newHighlightStyle, QSet(filterIdsSplit.cbegin(), filterIdsSplit.cend()); auto isSubset = [](QSet sub, QSet super) { - for (auto &&subItem : sub) - { - if (!super.contains(subItem)) - { - return false; - } - } - return true; + return std::ranges::none_of(sub, [&super](const auto &subItem) { + return !super.contains(subItem); + }); }; if (channelViewSource.underlyingChannel() == split->getChannel() && diff --git a/src/widgets/helper/NotebookTab.hpp b/src/widgets/helper/NotebookTab.hpp index 601957803fc..1dc0721c9c7 100644 --- a/src/widgets/helper/NotebookTab.hpp +++ b/src/widgets/helper/NotebookTab.hpp @@ -62,7 +62,7 @@ class NotebookTab : public Button void setHighlightState(HighlightState style); void setHighlightState(HighlightState style, ChannelView &channelViewSource, - MessagePtr message); + const MessagePtr &message); HighlightState highlightState() const; void setHighlightsEnabled(const bool &newVal); diff --git a/src/widgets/splits/SplitContainer.cpp b/src/widgets/splits/SplitContainer.cpp index 6f289326509..e8f654d0a98 100644 --- a/src/widgets/splits/SplitContainer.cpp +++ b/src/widgets/splits/SplitContainer.cpp @@ -219,7 +219,7 @@ void SplitContainer::addSplit(Split *split) if (this->tab_ != nullptr) { this->tab_->setHighlightState( - state, channelView, message); + state, channelView, std::move(message)); } }); From 3b64f142e69356a36f3fcc3ffca9dc617faf109f Mon Sep 17 00:00:00 2001 From: unknown <1310440+hemirt@users.noreply.github.com> Date: Tue, 15 Oct 2024 02:43:30 +0200 Subject: [PATCH 03/28] commit suggestions --- src/widgets/helper/ChannelView.hpp | 3 ++- src/widgets/splits/SplitContainer.cpp | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/widgets/helper/ChannelView.hpp b/src/widgets/helper/ChannelView.hpp index 56dd15aa003..52d08803a16 100644 --- a/src/widgets/helper/ChannelView.hpp +++ b/src/widgets/helper/ChannelView.hpp @@ -217,7 +217,8 @@ class ChannelView final : public BaseWidget pajlada::Signals::Signal mouseDown; pajlada::Signals::NoArgSignal selectionChanged; - pajlada::Signals::Signal tabHighlightRequested; + pajlada::Signals::Signal + tabHighlightRequested; pajlada::Signals::NoArgSignal liveStatusChanged; pajlada::Signals::Signal linkClicked; pajlada::Signals::Signal diff --git a/src/widgets/splits/SplitContainer.cpp b/src/widgets/splits/SplitContainer.cpp index e8f654d0a98..45ae0ced290 100644 --- a/src/widgets/splits/SplitContainer.cpp +++ b/src/widgets/splits/SplitContainer.cpp @@ -215,11 +215,11 @@ void SplitContainer::addSplit(Split *split) conns.managedConnect(split->getChannelView().tabHighlightRequested, [this, &channelView = split->getChannelView()]( - HighlightState state, MessagePtr message) { + HighlightState state, const MessagePtr &message) { if (this->tab_ != nullptr) { this->tab_->setHighlightState( - state, channelView, std::move(message)); + state, channelView, message); } }); From 70f497d3bd39307ad00a632c0c574632a4121a01 Mon Sep 17 00:00:00 2001 From: hemirt <1310440+hemirt@users.noreply.github.com> Date: Tue, 15 Oct 2024 18:03:14 +0200 Subject: [PATCH 04/28] Update src/widgets/helper/NotebookTab.cpp Co-authored-by: nerix --- src/widgets/helper/NotebookTab.cpp | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/src/widgets/helper/NotebookTab.cpp b/src/widgets/helper/NotebookTab.cpp index f343ccdb25b..2b33e82c4a5 100644 --- a/src/widgets/helper/NotebookTab.cpp +++ b/src/widgets/helper/NotebookTab.cpp @@ -411,16 +411,12 @@ void NotebookTab::setHighlightState(HighlightState newHighlightStyle, const auto &splits = splitContainer->getSplits(); for (const auto &split : splits) { - auto &&filterIdsSource = channelViewSource.getFilterIds(); - auto uniqueFilterIdsSource = - QSet(filterIdsSource.cbegin(), filterIdsSource.cend()); - auto &&filterIdsSplit = split->getChannelView().getFilterIds(); - auto uniqueFilterIdsSplit = - QSet(filterIdsSplit.cbegin(), filterIdsSplit.cend()); - - auto isSubset = [](QSet sub, QSet super) { - return std::ranges::none_of(sub, [&super](const auto &subItem) { - return !super.contains(subItem); + auto filterIdsSource = channelViewSource.getFilterIds(); + auto filterIdsSplit = split->getChannelView().getFilterIds(); + + auto isSubset = [](const QList &sub, const QList &super) { + return std::ranges::all_of(sub, [&super](const auto &subItem) { + return super.contains(subItem); }); }; From 7728f01916d8914970e482788a6d5ec73c75f22f Mon Sep 17 00:00:00 2001 From: unknown <1310440+hemirt@users.noreply.github.com> Date: Tue, 15 Oct 2024 18:14:11 +0200 Subject: [PATCH 05/28] name fixes --- src/widgets/helper/NotebookTab.cpp | 22 ++++++++++++---------- src/widgets/helper/NotebookTab.hpp | 3 ++- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/src/widgets/helper/NotebookTab.cpp b/src/widgets/helper/NotebookTab.cpp index 2b33e82c4a5..d70d9cd25f8 100644 --- a/src/widgets/helper/NotebookTab.cpp +++ b/src/widgets/helper/NotebookTab.cpp @@ -384,7 +384,7 @@ void NotebookTab::setHighlightState(HighlightState newHighlightStyle) } void NotebookTab::setHighlightState(HighlightState newHighlightStyle, - ChannelView &channelViewSource, + const ChannelView &channelViewSource, const MessagePtr &message) { if (this->isSelected()) @@ -404,25 +404,27 @@ void NotebookTab::setHighlightState(HighlightState newHighlightStyle, return; } - auto *splitContainer = + auto *visibleSplitContainer = dynamic_cast(this->notebook_->getSelectedPage()); - if (splitContainer != nullptr) + if (visibleSplitContainer != nullptr) { - const auto &splits = splitContainer->getSplits(); - for (const auto &split : splits) + const auto &visibleSplits = visibleSplitContainer->getSplits(); + for (const auto &visibleSplit : visibleSplits) { auto filterIdsSource = channelViewSource.getFilterIds(); - auto filterIdsSplit = split->getChannelView().getFilterIds(); + auto filterIdsSplit = visibleSplit->getChannelView().getFilterIds(); - auto isSubset = [](const QList &sub, const QList &super) { + auto isSubset = [](const QList &sub, + const QList &super) { return std::ranges::all_of(sub, [&super](const auto &subItem) { return super.contains(subItem); }); }; - if (channelViewSource.underlyingChannel() == split->getChannel() && - split->getChannelView().shouldIncludeMessage(message) && - isSubset(uniqueFilterIdsSource, uniqueFilterIdsSplit)) + if (channelViewSource.underlyingChannel() == + visibleSplit->getChannel() && + visibleSplit->getChannelView().shouldIncludeMessage(message) && + isSubset(filterIdsSource, filterIdsSplit)) { return; } diff --git a/src/widgets/helper/NotebookTab.hpp b/src/widgets/helper/NotebookTab.hpp index 1dc0721c9c7..7284a17864e 100644 --- a/src/widgets/helper/NotebookTab.hpp +++ b/src/widgets/helper/NotebookTab.hpp @@ -61,7 +61,8 @@ class NotebookTab : public Button bool isLive() const; void setHighlightState(HighlightState style); - void setHighlightState(HighlightState style, ChannelView &channelViewSource, + void setHighlightState(HighlightState style, + const ChannelView &channelViewSource, const MessagePtr &message); HighlightState highlightState() const; From edaafac0100999ccbc55062c8cfc6e7076463c66 Mon Sep 17 00:00:00 2001 From: unknown <1310440+hemirt@users.noreply.github.com> Date: Thu, 17 Oct 2024 13:16:37 +0200 Subject: [PATCH 06/28] initial state of selecting to unhiglight --- src/widgets/helper/NotebookTab.cpp | 60 ++++++++++++++++++++++++++++-- src/widgets/helper/NotebookTab.hpp | 11 ++++++ 2 files changed, 68 insertions(+), 3 deletions(-) diff --git a/src/widgets/helper/NotebookTab.cpp b/src/widgets/helper/NotebookTab.cpp index d70d9cd25f8..42d9d43405d 100644 --- a/src/widgets/helper/NotebookTab.cpp +++ b/src/widgets/helper/NotebookTab.cpp @@ -304,10 +304,49 @@ bool NotebookTab::isSelected() const return this->selected_; } +void NotebookTab::updateHighlightSources( + const QHash &removedHighlightSources) +{ + for (const auto &[otherChannel, otherEvent] : + removedHighlightSources.asKeyValueRange()) + { + this->highlightSources_.remove(otherChannel); + } + + if (this->highlightSources_.empty()) + { + this->highlightState_ = HighlightState::None; + this->update(); + } +} + void NotebookTab::setSelected(bool value) { this->selected_ = value; + if (value == true) + { + auto *splitNotebook = dynamic_cast(this->notebook_); + if (splitNotebook) + { + for (int i = 0; i < splitNotebook->getPageCount(); ++i) + { + auto *splitContainer = + dynamic_cast(splitNotebook->getPageAt(i)); + if (splitContainer) + { + auto *tab = splitContainer->getTab(); + if (tab && tab != this) + { + tab->updateHighlightSources(this->highlightSources_); + } + } + } + } + } + + this->highlightSources_.clear(); + this->highlightState_ = HighlightState::None; this->update(); @@ -362,6 +401,7 @@ bool NotebookTab::isLive() const void NotebookTab::setHighlightState(HighlightState newHighlightStyle) { + // change this to "copy" highlight state, its used by duplicating a tab if (this->isSelected()) { return; @@ -392,6 +432,14 @@ void NotebookTab::setHighlightState(HighlightState newHighlightStyle, return; } + if (!this->shouldMessageHighlight(channelViewSource, message)) + { + return; + } + + this->highlightSources_.insert(channelViewSource.underlyingChannel(), + HighlightEvent{}); + if (!this->highlightEnabled_ && newHighlightStyle == HighlightState::NewMessage) { @@ -404,6 +452,13 @@ void NotebookTab::setHighlightState(HighlightState newHighlightStyle, return; } + this->highlightState_ = newHighlightStyle; + this->update(); +} + +bool NotebookTab::shouldMessageHighlight(const ChannelView &channelViewSource, + const MessagePtr &message) const +{ auto *visibleSplitContainer = dynamic_cast(this->notebook_->getSelectedPage()); if (visibleSplitContainer != nullptr) @@ -426,13 +481,12 @@ void NotebookTab::setHighlightState(HighlightState newHighlightStyle, visibleSplit->getChannelView().shouldIncludeMessage(message) && isSubset(filterIdsSource, filterIdsSplit)) { - return; + return false; } } } - this->highlightState_ = newHighlightStyle; - this->update(); + return true; } HighlightState NotebookTab::highlightState() const diff --git a/src/widgets/helper/NotebookTab.hpp b/src/widgets/helper/NotebookTab.hpp index 7284a17864e..c709eb42eb9 100644 --- a/src/widgets/helper/NotebookTab.hpp +++ b/src/widgets/helper/NotebookTab.hpp @@ -111,6 +111,15 @@ class NotebookTab : public Button int normalTabWidthForHeight(int height) const; + bool shouldMessageHighlight(const ChannelView &channelViewSource, + const MessagePtr &message) const; + + struct HighlightEvent { + }; + + void updateHighlightSources( + const QHash &removedHighlightSources); + QPropertyAnimation positionChangedAnimation_; QPoint positionAnimationDesiredPoint_; @@ -139,6 +148,8 @@ class NotebookTab : public Button QMenu menu_; + QHash highlightSources_; + pajlada::Signals::SignalHolder managedConnections_; }; From 806fa7790d4c079edc0cad80822df3203359c879 Mon Sep 17 00:00:00 2001 From: unknown <1310440+hemirt@users.noreply.github.com> Date: Thu, 17 Oct 2024 15:37:36 +0200 Subject: [PATCH 07/28] missing include --- src/widgets/Notebook.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/widgets/Notebook.hpp b/src/widgets/Notebook.hpp index ac6c4dad79f..23888ae612c 100644 --- a/src/widgets/Notebook.hpp +++ b/src/widgets/Notebook.hpp @@ -2,6 +2,7 @@ #include "widgets/BaseWidget.hpp" +#include #include #include #include From 13d7692a89331ef4183ba3307bb9f5d3c916b4eb Mon Sep 17 00:00:00 2001 From: unknown <1310440+hemirt@users.noreply.github.com> Date: Thu, 17 Oct 2024 16:38:32 +0200 Subject: [PATCH 08/28] add older version code --- src/widgets/helper/NotebookTab.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/widgets/helper/NotebookTab.cpp b/src/widgets/helper/NotebookTab.cpp index 42d9d43405d..8b08c1bbdee 100644 --- a/src/widgets/helper/NotebookTab.cpp +++ b/src/widgets/helper/NotebookTab.cpp @@ -307,11 +307,20 @@ bool NotebookTab::isSelected() const void NotebookTab::updateHighlightSources( const QHash &removedHighlightSources) { +#if QT_VERSION >= QT_VERSION_CHECK(6, 4, 0) for (const auto &[otherChannel, otherEvent] : removedHighlightSources.asKeyValueRange()) { this->highlightSources_.remove(otherChannel); } +#else + for (auto it = removedHighlightSources.cbegin(), + end = removedHighlightSources.cend(); + it != end; ++it) + { + this->highlightSources_.remove(it.key()); + } +#endif if (this->highlightSources_.empty()) { @@ -324,7 +333,7 @@ void NotebookTab::setSelected(bool value) { this->selected_ = value; - if (value == true) + if (value) { auto *splitNotebook = dynamic_cast(this->notebook_); if (splitNotebook) From a2af8e791b91ce8337f2dd1cdf03f8c27cd92b51 Mon Sep 17 00:00:00 2001 From: unknown <1310440+hemirt@users.noreply.github.com> Date: Thu, 17 Oct 2024 17:25:54 +0200 Subject: [PATCH 09/28] switch from QHash to std::unordered_map --- src/widgets/helper/NotebookTab.cpp | 25 ++++++++++--------------- src/widgets/helper/NotebookTab.hpp | 5 +++-- 2 files changed, 13 insertions(+), 17 deletions(-) diff --git a/src/widgets/helper/NotebookTab.cpp b/src/widgets/helper/NotebookTab.cpp index 8b08c1bbdee..febfbd3054c 100644 --- a/src/widgets/helper/NotebookTab.cpp +++ b/src/widgets/helper/NotebookTab.cpp @@ -305,22 +305,13 @@ bool NotebookTab::isSelected() const } void NotebookTab::updateHighlightSources( - const QHash &removedHighlightSources) + const std::unordered_map + &removedHighlightSources) { -#if QT_VERSION >= QT_VERSION_CHECK(6, 4, 0) - for (const auto &[otherChannel, otherEvent] : - removedHighlightSources.asKeyValueRange()) + for (const auto &[otherChannel, otherEvent] : removedHighlightSources) { - this->highlightSources_.remove(otherChannel); + this->highlightSources_.erase(otherChannel); } -#else - for (auto it = removedHighlightSources.cbegin(), - end = removedHighlightSources.cend(); - it != end; ++it) - { - this->highlightSources_.remove(it.key()); - } -#endif if (this->highlightSources_.empty()) { @@ -446,8 +437,12 @@ void NotebookTab::setHighlightState(HighlightState newHighlightStyle, return; } - this->highlightSources_.insert(channelViewSource.underlyingChannel(), - HighlightEvent{}); + if (!this->highlightSources_.contains( + channelViewSource.underlyingChannel())) + { + this->highlightSources_.emplace(channelViewSource.underlyingChannel(), + HighlightEvent{}); + } if (!this->highlightEnabled_ && newHighlightStyle == HighlightState::NewMessage) diff --git a/src/widgets/helper/NotebookTab.hpp b/src/widgets/helper/NotebookTab.hpp index c709eb42eb9..a7b1e518e42 100644 --- a/src/widgets/helper/NotebookTab.hpp +++ b/src/widgets/helper/NotebookTab.hpp @@ -118,7 +118,8 @@ class NotebookTab : public Button }; void updateHighlightSources( - const QHash &removedHighlightSources); + const std::unordered_map + &removedHighlightSources); QPropertyAnimation positionChangedAnimation_; QPoint positionAnimationDesiredPoint_; @@ -148,7 +149,7 @@ class NotebookTab : public Button QMenu menu_; - QHash highlightSources_; + std::unordered_map highlightSources_; pajlada::Signals::SignalHolder managedConnections_; }; From 5f862c5e5ee6ec4b4c61c266dd74ad6591b0806d Mon Sep 17 00:00:00 2001 From: unknown <1310440+hemirt@users.noreply.github.com> Date: Thu, 17 Oct 2024 18:56:14 +0200 Subject: [PATCH 10/28] solve highlighted tabs --- src/widgets/helper/NotebookTab.cpp | 62 ++++++++++++++++++++++++------ src/widgets/helper/NotebookTab.hpp | 18 ++++++--- 2 files changed, 63 insertions(+), 17 deletions(-) diff --git a/src/widgets/helper/NotebookTab.cpp b/src/widgets/helper/NotebookTab.cpp index febfbd3054c..ebfdd2ff838 100644 --- a/src/widgets/helper/NotebookTab.cpp +++ b/src/widgets/helper/NotebookTab.cpp @@ -305,18 +305,39 @@ bool NotebookTab::isSelected() const } void NotebookTab::updateHighlightSources( - const std::unordered_map - &removedHighlightSources) + const HighlightSources &removedHighlightSources) { - for (const auto &[otherChannel, otherEvent] : removedHighlightSources) + for (const auto &source : removedHighlightSources.newMessageSource) { - this->highlightSources_.erase(otherChannel); + this->highlightSources_.newMessageSource.erase(source); } - if (this->highlightSources_.empty()) + for (const auto &source : removedHighlightSources.highlightedSource) { - this->highlightState_ = HighlightState::None; - this->update(); + this->highlightSources_.highlightedSource.erase(source); + } + + if (!this->highlightSources_.highlightedSource.empty()) + { + // keep HighlightState::Highlighted + return; + } + + if (!this->highlightSources_.newMessageSource.empty()) + { + if (this->highlightState_ != HighlightState::NewMessage) + { + this->highlightState_ = HighlightState::NewMessage; + this->update(); + } + } + else + { + if (this->highlightState_ != HighlightState::None) + { + this->highlightState_ = HighlightState::None; + this->update(); + } } } @@ -437,11 +458,30 @@ void NotebookTab::setHighlightState(HighlightState newHighlightStyle, return; } - if (!this->highlightSources_.contains( - channelViewSource.underlyingChannel())) + auto underlyingChannel = channelViewSource.underlyingChannel(); + + switch (newHighlightStyle) { - this->highlightSources_.emplace(channelViewSource.underlyingChannel(), - HighlightEvent{}); + case HighlightState::Highlighted: { + if (!this->highlightSources_.highlightedSource.contains( + underlyingChannel)) + { + this->highlightSources_.highlightedSource.insert( + underlyingChannel); + } + break; + } + case HighlightState::NewMessage: { + if (!this->highlightSources_.newMessageSource.contains( + underlyingChannel)) + { + this->highlightSources_.newMessageSource.insert( + underlyingChannel); + } + break; + } + case HighlightState::None: + break; } if (!this->highlightEnabled_ && diff --git a/src/widgets/helper/NotebookTab.hpp b/src/widgets/helper/NotebookTab.hpp index a7b1e518e42..e5fe6c9cd14 100644 --- a/src/widgets/helper/NotebookTab.hpp +++ b/src/widgets/helper/NotebookTab.hpp @@ -114,12 +114,20 @@ class NotebookTab : public Button bool shouldMessageHighlight(const ChannelView &channelViewSource, const MessagePtr &message) const; - struct HighlightEvent { - }; + struct HighlightSources { + std::unordered_set newMessageSource; + std::unordered_set highlightedSource; + + void clear() + { + this->newMessageSource.clear(); + this->highlightedSource.clear(); + } + + } highlightSources_; void updateHighlightSources( - const std::unordered_map - &removedHighlightSources); + const HighlightSources &removedHighlightSources); QPropertyAnimation positionChangedAnimation_; QPoint positionAnimationDesiredPoint_; @@ -149,8 +157,6 @@ class NotebookTab : public Button QMenu menu_; - std::unordered_map highlightSources_; - pajlada::Signals::SignalHolder managedConnections_; }; From 8745d0740f7b4330971628fdcae4c565573af3a1 Mon Sep 17 00:00:00 2001 From: unknown <1310440+hemirt@users.noreply.github.com> Date: Thu, 17 Oct 2024 19:24:53 +0200 Subject: [PATCH 11/28] fix duplicating tabs --- src/widgets/Notebook.cpp | 4 +- src/widgets/helper/NotebookTab.cpp | 63 ++++++++++++++---------------- src/widgets/helper/NotebookTab.hpp | 7 +--- 3 files changed, 33 insertions(+), 41 deletions(-) diff --git a/src/widgets/Notebook.cpp b/src/widgets/Notebook.cpp index 2a01020fc8f..53c6dfcfa45 100644 --- a/src/widgets/Notebook.cpp +++ b/src/widgets/Notebook.cpp @@ -204,7 +204,7 @@ void Notebook::duplicatePage(QWidget *page) { newTabPosition = tabPosition + 1; } - auto newTabHighlightState = item->tab->highlightState(); + QString newTabTitle = ""; if (item->tab->hasCustomTitle()) { @@ -213,7 +213,7 @@ void Notebook::duplicatePage(QWidget *page) auto *tab = this->addPageAt(newContainer, newTabPosition, newTabTitle, false); - tab->setHighlightState(newTabHighlightState); + tab->copyHighlightStateAndSourcesFrom(item->tab); newContainer->setTab(tab); } diff --git a/src/widgets/helper/NotebookTab.cpp b/src/widgets/helper/NotebookTab.cpp index ebfdd2ff838..66bc0cc4a8a 100644 --- a/src/widgets/helper/NotebookTab.cpp +++ b/src/widgets/helper/NotebookTab.cpp @@ -304,15 +304,14 @@ bool NotebookTab::isSelected() const return this->selected_; } -void NotebookTab::updateHighlightSources( - const HighlightSources &removedHighlightSources) +void NotebookTab::removeHighlightSources(const HighlightSources &toRemove) { - for (const auto &source : removedHighlightSources.newMessageSource) + for (const auto &source : toRemove.newMessageSource) { this->highlightSources_.newMessageSource.erase(source); } - for (const auto &source : removedHighlightSources.highlightedSource) + for (const auto &source : toRemove.highlightedSource) { this->highlightSources_.highlightedSource.erase(source); } @@ -341,6 +340,31 @@ void NotebookTab::updateHighlightSources( } } +void NotebookTab::copyHighlightStateAndSourcesFrom(const NotebookTab *sourceTab) +{ + if (this->isSelected()) + { + return; + } + + this->highlightSources_ = sourceTab->highlightSources_; + + if (!this->highlightEnabled_ && + sourceTab->highlightState_ == HighlightState::NewMessage) + { + return; + } + + if (this->highlightState_ == sourceTab->highlightState_ || + this->highlightState_ == HighlightState::Highlighted) + { + return; + } + + this->highlightState_ = sourceTab->highlightState_; + this->update(); +} + void NotebookTab::setSelected(bool value) { this->selected_ = value; @@ -359,7 +383,7 @@ void NotebookTab::setSelected(bool value) auto *tab = splitContainer->getTab(); if (tab && tab != this) { - tab->updateHighlightSources(this->highlightSources_); + tab->removeHighlightSources(this->highlightSources_); } } } @@ -420,30 +444,6 @@ bool NotebookTab::isLive() const return this->isLive_; } -void NotebookTab::setHighlightState(HighlightState newHighlightStyle) -{ - // change this to "copy" highlight state, its used by duplicating a tab - if (this->isSelected()) - { - return; - } - - if (!this->highlightEnabled_ && - newHighlightStyle == HighlightState::NewMessage) - { - return; - } - - if (this->highlightState_ == newHighlightStyle || - this->highlightState_ == HighlightState::Highlighted) - { - return; - } - - this->highlightState_ = newHighlightStyle; - this->update(); -} - void NotebookTab::setHighlightState(HighlightState newHighlightStyle, const ChannelView &channelViewSource, const MessagePtr &message) @@ -533,11 +533,6 @@ bool NotebookTab::shouldMessageHighlight(const ChannelView &channelViewSource, return true; } -HighlightState NotebookTab::highlightState() const -{ - return this->highlightState_; -} - void NotebookTab::setHighlightsEnabled(const bool &newVal) { this->highlightNewMessagesAction_->setChecked(newVal); diff --git a/src/widgets/helper/NotebookTab.hpp b/src/widgets/helper/NotebookTab.hpp index e5fe6c9cd14..ba073ad2d86 100644 --- a/src/widgets/helper/NotebookTab.hpp +++ b/src/widgets/helper/NotebookTab.hpp @@ -60,12 +60,10 @@ class NotebookTab : public Button **/ bool isLive() const; - void setHighlightState(HighlightState style); void setHighlightState(HighlightState style, const ChannelView &channelViewSource, const MessagePtr &message); - HighlightState highlightState() const; - + void copyHighlightStateAndSourcesFrom(const NotebookTab *sourceTab); void setHighlightsEnabled(const bool &newVal); bool hasHighlightsEnabled() const; @@ -126,8 +124,7 @@ class NotebookTab : public Button } highlightSources_; - void updateHighlightSources( - const HighlightSources &removedHighlightSources); + void removeHighlightSources(const HighlightSources &toRemove); QPropertyAnimation positionChangedAnimation_; QPoint positionAnimationDesiredPoint_; From 39e0e00f2d254330c8c890b912bcdc32f90dcf2a Mon Sep 17 00:00:00 2001 From: unknown <1310440+hemirt@users.noreply.github.com> Date: Thu, 17 Oct 2024 20:05:05 +0200 Subject: [PATCH 12/28] add more highlight state functions --- src/widgets/helper/NotebookTab.cpp | 40 +++++++++++++++++++++++++-- src/widgets/helper/NotebookTab.hpp | 24 ++++++++++++++-- src/widgets/splits/SplitContainer.cpp | 2 +- 3 files changed, 59 insertions(+), 7 deletions(-) diff --git a/src/widgets/helper/NotebookTab.cpp b/src/widgets/helper/NotebookTab.cpp index 66bc0cc4a8a..d1c0055cf05 100644 --- a/src/widgets/helper/NotebookTab.cpp +++ b/src/widgets/helper/NotebookTab.cpp @@ -444,9 +444,43 @@ bool NotebookTab::isLive() const return this->isLive_; } -void NotebookTab::setHighlightState(HighlightState newHighlightStyle, - const ChannelView &channelViewSource, - const MessagePtr &message) +HighlightState NotebookTab::highlightState() const +{ + return this->highlightState_; +} + +void NotebookTab::setHighlightState(HighlightState newHighlightStyle) +{ + if (this->isSelected()) + { + return; + } + + if (!this->highlightEnabled_ && + newHighlightStyle == HighlightState::NewMessage) + { + return; + } + + if (this->highlightState_ == newHighlightStyle || + this->highlightState_ == HighlightState::Highlighted) + { + return; + } + + this->highlightState_ = newHighlightStyle; + this->update(); +} + +void NotebookTab::forceHighlightState(HighlightState newHighlightStyle) +{ + this->highlightState_ = newHighlightStyle; + this->update(); +} + +void NotebookTab::updateHighlightState(HighlightState newHighlightStyle, + const ChannelView &channelViewSource, + const MessagePtr &message) { if (this->isSelected()) { diff --git a/src/widgets/helper/NotebookTab.hpp b/src/widgets/helper/NotebookTab.hpp index ba073ad2d86..cab7b094135 100644 --- a/src/widgets/helper/NotebookTab.hpp +++ b/src/widgets/helper/NotebookTab.hpp @@ -60,12 +60,30 @@ class NotebookTab : public Button **/ bool isLive() const; - void setHighlightState(HighlightState style, - const ChannelView &channelViewSource, - const MessagePtr &message); + /** + * @brief Sets the highlight state of this tab clearing out highlight sources + * + * Obeys the HighlightsEnabled setting and highlight states hierarchy + */ + void setHighlightState(HighlightState style); + /** + * @brief Forces the highlight state of this tab + * + * Does NOT obey the HighlightsEnabled setting and the highlight states hierarchy + */ + void forceHighlightState(HighlightState style); + /** + * @brief Updates the highlight state and highlight sources of this tab + * + * Obeys the HighlightsEnabled setting and the highlight state hierarchy and tracks the highlight state update sources + */ + void updateHighlightState(HighlightState style, + const ChannelView &channelViewSource, + const MessagePtr &message); void copyHighlightStateAndSourcesFrom(const NotebookTab *sourceTab); void setHighlightsEnabled(const bool &newVal); bool hasHighlightsEnabled() const; + HighlightState highlightState() const; void moveAnimated(QPoint targetPos, bool animated = true); diff --git a/src/widgets/splits/SplitContainer.cpp b/src/widgets/splits/SplitContainer.cpp index 45ae0ced290..7b4192ca6a8 100644 --- a/src/widgets/splits/SplitContainer.cpp +++ b/src/widgets/splits/SplitContainer.cpp @@ -218,7 +218,7 @@ void SplitContainer::addSplit(Split *split) HighlightState state, const MessagePtr &message) { if (this->tab_ != nullptr) { - this->tab_->setHighlightState( + this->tab_->updateHighlightState( state, channelView, message); } }); From 1ca5d38ad5efaa661140d4f2c65c4b73be0df537 Mon Sep 17 00:00:00 2001 From: unknown <1310440+hemirt@users.noreply.github.com> Date: Thu, 17 Oct 2024 20:35:52 +0200 Subject: [PATCH 13/28] add some asserts --- src/widgets/helper/NotebookTab.cpp | 18 +++++++++++------- src/widgets/helper/NotebookTab.hpp | 8 +------- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/src/widgets/helper/NotebookTab.cpp b/src/widgets/helper/NotebookTab.cpp index d1c0055cf05..886366d5e07 100644 --- a/src/widgets/helper/NotebookTab.cpp +++ b/src/widgets/helper/NotebookTab.cpp @@ -344,6 +344,9 @@ void NotebookTab::copyHighlightStateAndSourcesFrom(const NotebookTab *sourceTab) { if (this->isSelected()) { + assert(this->highlightSources_.highlightedSource.empty()); + assert(this->highlightSources_.newMessageSource.empty()); + assert(this->highlightState_ == HighlightState::None); return; } @@ -391,7 +394,6 @@ void NotebookTab::setSelected(bool value) } this->highlightSources_.clear(); - this->highlightState_ = HighlightState::None; this->update(); @@ -453,9 +455,14 @@ void NotebookTab::setHighlightState(HighlightState newHighlightStyle) { if (this->isSelected()) { + assert(this->highlightSources_.highlightedSource.empty()); + assert(this->highlightSources_.newMessageSource.empty()); + assert(this->highlightState_ == HighlightState::None); return; } + this->highlightSources_.clear(); + if (!this->highlightEnabled_ && newHighlightStyle == HighlightState::NewMessage) { @@ -472,18 +479,15 @@ void NotebookTab::setHighlightState(HighlightState newHighlightStyle) this->update(); } -void NotebookTab::forceHighlightState(HighlightState newHighlightStyle) -{ - this->highlightState_ = newHighlightStyle; - this->update(); -} - void NotebookTab::updateHighlightState(HighlightState newHighlightStyle, const ChannelView &channelViewSource, const MessagePtr &message) { if (this->isSelected()) { + assert(this->highlightSources_.highlightedSource.empty()); + assert(this->highlightSources_.newMessageSource.empty()); + assert(this->highlightState_ == HighlightState::None); return; } diff --git a/src/widgets/helper/NotebookTab.hpp b/src/widgets/helper/NotebookTab.hpp index cab7b094135..8be7f1e97f3 100644 --- a/src/widgets/helper/NotebookTab.hpp +++ b/src/widgets/helper/NotebookTab.hpp @@ -61,17 +61,11 @@ class NotebookTab : public Button bool isLive() const; /** - * @brief Sets the highlight state of this tab clearing out highlight sources + * @brief Sets the highlight state of this tab clearing highlight sources * * Obeys the HighlightsEnabled setting and highlight states hierarchy */ void setHighlightState(HighlightState style); - /** - * @brief Forces the highlight state of this tab - * - * Does NOT obey the HighlightsEnabled setting and the highlight states hierarchy - */ - void forceHighlightState(HighlightState style); /** * @brief Updates the highlight state and highlight sources of this tab * From e2887423600e9b3f12ffae5b875626b2e339e12c Mon Sep 17 00:00:00 2001 From: unknown <1310440+hemirt@users.noreply.github.com> Date: Thu, 17 Oct 2024 20:43:25 +0200 Subject: [PATCH 14/28] more asserts --- src/widgets/helper/NotebookTab.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/widgets/helper/NotebookTab.cpp b/src/widgets/helper/NotebookTab.cpp index 886366d5e07..5a66606396c 100644 --- a/src/widgets/helper/NotebookTab.cpp +++ b/src/widgets/helper/NotebookTab.cpp @@ -318,7 +318,7 @@ void NotebookTab::removeHighlightSources(const HighlightSources &toRemove) if (!this->highlightSources_.highlightedSource.empty()) { - // keep HighlightState::Highlighted + assert(this->highlightState_ == HighlightState::Highlighted); return; } @@ -338,6 +338,8 @@ void NotebookTab::removeHighlightSources(const HighlightSources &toRemove) this->update(); } } + + assert(this->highlightState_ != HighlightState::Highlighted); } void NotebookTab::copyHighlightStateAndSourcesFrom(const NotebookTab *sourceTab) From 2884c828b03c940d26e776f803824cd3d499e416 Mon Sep 17 00:00:00 2001 From: unknown <1310440+hemirt@users.noreply.github.com> Date: Fri, 18 Oct 2024 09:24:34 +0200 Subject: [PATCH 15/28] update highlights of other tabs when adding new channel or changing channel --- src/widgets/helper/NotebookTab.cpp | 51 ++++++++++++++++++++++++--- src/widgets/helper/NotebookTab.hpp | 6 +++- src/widgets/splits/SplitContainer.cpp | 28 ++++++++++----- 3 files changed, 71 insertions(+), 14 deletions(-) diff --git a/src/widgets/helper/NotebookTab.cpp b/src/widgets/helper/NotebookTab.cpp index 5a66606396c..a04725909b1 100644 --- a/src/widgets/helper/NotebookTab.cpp +++ b/src/widgets/helper/NotebookTab.cpp @@ -304,18 +304,59 @@ bool NotebookTab::isSelected() const return this->selected_; } -void NotebookTab::removeHighlightSources(const HighlightSources &toRemove) +void NotebookTab::removeNewMessageSource(const ChannelPtr &source) +{ + this->highlightSources_.newMessageSource.erase(source); +} + +void NotebookTab::removeHighlightedSource(const ChannelPtr &source) +{ + this->highlightSources_.highlightedSource.erase(source); +} + +void NotebookTab::removeHighlightStateChangeSources( + const HighlightSources &toRemove) { for (const auto &source : toRemove.newMessageSource) { - this->highlightSources_.newMessageSource.erase(source); + this->removeNewMessageSource(source); } for (const auto &source : toRemove.highlightedSource) { - this->highlightSources_.highlightedSource.erase(source); + this->removeHighlightedSource(source); + } +} + +void NotebookTab::newHighlightSourceAdded(const ChannelPtr &source) +{ + this->removeHighlightedSource(source); + this->removeNewMessageSource(source); + this->updateHighlightStateDueSourcesChange(); + + auto *splitNotebook = dynamic_cast(this->notebook_); + if (splitNotebook) + { + for (int i = 0; i < splitNotebook->getPageCount(); ++i) + { + auto *splitContainer = + dynamic_cast(splitNotebook->getPageAt(i)); + if (splitContainer) + { + auto *tab = splitContainer->getTab(); + if (tab && tab != this) + { + tab->removeHighlightedSource(source); + tab->removeNewMessageSource(source); + tab->updateHighlightStateDueSourcesChange(); + } + } + } } +} +void NotebookTab::updateHighlightStateDueSourcesChange() +{ if (!this->highlightSources_.highlightedSource.empty()) { assert(this->highlightState_ == HighlightState::Highlighted); @@ -388,7 +429,9 @@ void NotebookTab::setSelected(bool value) auto *tab = splitContainer->getTab(); if (tab && tab != this) { - tab->removeHighlightSources(this->highlightSources_); + tab->removeHighlightStateChangeSources( + this->highlightSources_); + tab->updateHighlightStateDueSourcesChange(); } } } diff --git a/src/widgets/helper/NotebookTab.hpp b/src/widgets/helper/NotebookTab.hpp index 8be7f1e97f3..cfd2e1d348c 100644 --- a/src/widgets/helper/NotebookTab.hpp +++ b/src/widgets/helper/NotebookTab.hpp @@ -76,6 +76,7 @@ class NotebookTab : public Button const MessagePtr &message); void copyHighlightStateAndSourcesFrom(const NotebookTab *sourceTab); void setHighlightsEnabled(const bool &newVal); + void newHighlightSourceAdded(const ChannelPtr &source); bool hasHighlightsEnabled() const; HighlightState highlightState() const; @@ -136,7 +137,10 @@ class NotebookTab : public Button } highlightSources_; - void removeHighlightSources(const HighlightSources &toRemove); + void removeHighlightStateChangeSources(const HighlightSources &toRemove); + void removeNewMessageSource(const ChannelPtr &source); + void removeHighlightedSource(const ChannelPtr &source); + void updateHighlightStateDueSourcesChange(); QPropertyAnimation positionChangedAnimation_; QPoint positionAnimationDesiredPoint_; diff --git a/src/widgets/splits/SplitContainer.cpp b/src/widgets/splits/SplitContainer.cpp index 7b4192ca6a8..4e430c6b008 100644 --- a/src/widgets/splits/SplitContainer.cpp +++ b/src/widgets/splits/SplitContainer.cpp @@ -213,15 +213,25 @@ void SplitContainer::addSplit(Split *split) auto &&conns = this->connectionsPerSplit_[split]; - conns.managedConnect(split->getChannelView().tabHighlightRequested, - [this, &channelView = split->getChannelView()]( - HighlightState state, const MessagePtr &message) { - if (this->tab_ != nullptr) - { - this->tab_->updateHighlightState( - state, channelView, message); - } - }); + conns.managedConnect( + split->getChannelView().tabHighlightRequested, + [this, split](HighlightState state, const MessagePtr &message) { + if (this->tab_ != nullptr) + { + this->tab_->updateHighlightState(state, split->getChannelView(), + message); + } + }); + + conns.managedConnect(split->channelChanged, [this, split] { + qDebug() << "Changing Channel" + << split->getChannelView().underlyingChannel()->getName(); + if (this->tab_ != nullptr) + { + this->tab_->newHighlightSourceAdded( + split->getChannelView().underlyingChannel()); + } + }); conns.managedConnect(split->getChannelView().liveStatusChanged, [this]() { this->refreshTabLiveStatus(); From fe51ba85e772e2d8e8c85033e0311636cd5fdf72 Mon Sep 17 00:00:00 2001 From: unknown <1310440+hemirt@users.noreply.github.com> Date: Sun, 20 Oct 2024 17:46:22 +0200 Subject: [PATCH 16/28] hash based matching based on ChannelView name and filters --- src/widgets/helper/NotebookTab.cpp | 63 ++++++++++++++++++++++----- src/widgets/helper/NotebookTab.hpp | 32 +++++++++++--- src/widgets/splits/SplitContainer.cpp | 5 +-- 3 files changed, 78 insertions(+), 22 deletions(-) diff --git a/src/widgets/helper/NotebookTab.cpp b/src/widgets/helper/NotebookTab.cpp index a04725909b1..db444b23771 100644 --- a/src/widgets/helper/NotebookTab.cpp +++ b/src/widgets/helper/NotebookTab.cpp @@ -1,6 +1,7 @@ #include "widgets/helper/NotebookTab.hpp" #include "Application.hpp" +#include "common/Channel.hpp" #include "common/Common.hpp" #include "controllers/hotkeys/HotkeyCategory.hpp" #include "controllers/hotkeys/HotkeyController.hpp" @@ -10,7 +11,6 @@ #include "singletons/WindowManager.hpp" #include "util/Helpers.hpp" #include "widgets/dialogs/SettingsDialog.hpp" -#include "widgets/helper/ChannelView.hpp" #include "widgets/Notebook.hpp" #include "widgets/splits/DraggedSplit.hpp" #include "widgets/splits/Split.hpp" @@ -55,6 +55,27 @@ namespace { } } // namespace +std::size_t NotebookTab::HighlightSources::ChannelViewProxyHash::operator()( + const ChannelViewProxy &cp) const noexcept +{ + std::size_t seed = 0; + auto first = qHash(cp.channelView->underlyingChannel()->getName()); + auto second = qHash(cp.channelView->getFilterIds()); + + boost::hash_combine(seed, first); + boost::hash_combine(seed, second); + + return seed; +} + +bool NotebookTab::HighlightSources::ChannelViewProxyEqual::operator()( + const ChannelViewProxy &lp, const ChannelViewProxy &rp) const +{ + return lp.channelView->underlyingChannel() == + rp.channelView->underlyingChannel() && + lp.channelView->getFilterIds() == rp.channelView->getFilterIds(); +} + NotebookTab::NotebookTab(Notebook *notebook) : Button(notebook) , positionChangedAnimation_(this, "pos") @@ -304,12 +325,14 @@ bool NotebookTab::isSelected() const return this->selected_; } -void NotebookTab::removeNewMessageSource(const ChannelPtr &source) +void NotebookTab::removeNewMessageSource( + const HighlightSources::ChannelViewProxy &source) { this->highlightSources_.newMessageSource.erase(source); } -void NotebookTab::removeHighlightedSource(const ChannelPtr &source) +void NotebookTab::removeHighlightedSource( + const HighlightSources::ChannelViewProxy &source) { this->highlightSources_.highlightedSource.erase(source); } @@ -328,10 +351,13 @@ void NotebookTab::removeHighlightStateChangeSources( } } -void NotebookTab::newHighlightSourceAdded(const ChannelPtr &source) +void NotebookTab::newHighlightSourceAdded(const ChannelView &channelViewSource) { - this->removeHighlightedSource(source); - this->removeNewMessageSource(source); + auto channelViewProxy = + HighlightSources::ChannelViewProxy{&channelViewSource}; + auto sourceChannel = channelViewSource.underlyingChannel(); + this->removeHighlightedSource(channelViewProxy); + this->removeNewMessageSource(channelViewProxy); this->updateHighlightStateDueSourcesChange(); auto *splitNotebook = dynamic_cast(this->notebook_); @@ -346,8 +372,8 @@ void NotebookTab::newHighlightSourceAdded(const ChannelPtr &source) auto *tab = splitContainer->getTab(); if (tab && tab != this) { - tab->removeHighlightedSource(source); - tab->removeNewMessageSource(source); + tab->removeHighlightedSource(channelViewProxy); + tab->removeNewMessageSource(channelViewProxy); tab->updateHighlightStateDueSourcesChange(); } } @@ -541,25 +567,34 @@ void NotebookTab::updateHighlightState(HighlightState newHighlightStyle, return; } + // message is highlighting unvisible tab + auto underlyingChannel = channelViewSource.underlyingChannel(); + auto newFilters = channelViewSource.getFilterIds(); + auto channelViewProxy = + HighlightSources::ChannelViewProxy{&channelViewSource}; + + // the unvisible tab should unhighlight other tabs iff + // the other tab's filters are more generic therefore + // the other tab's filter set is subset of the unvisible tab switch (newHighlightStyle) { case HighlightState::Highlighted: { if (!this->highlightSources_.highlightedSource.contains( - underlyingChannel)) + channelViewProxy)) { this->highlightSources_.highlightedSource.insert( - underlyingChannel); + channelViewProxy); } break; } case HighlightState::NewMessage: { if (!this->highlightSources_.newMessageSource.contains( - underlyingChannel)) + channelViewProxy)) { this->highlightSources_.newMessageSource.insert( - underlyingChannel); + channelViewProxy); } break; } @@ -608,6 +643,10 @@ bool NotebookTab::shouldMessageHighlight(const ChannelView &channelViewSource, visibleSplit->getChannelView().shouldIncludeMessage(message) && isSubset(filterIdsSource, filterIdsSplit)) { + // all filters in unvisible source are found in visible split + // therefore the unvisible split is more generic than the visible one + // and the visible one is showing current message + // so no highlight of unvisible tab needed return false; } } diff --git a/src/widgets/helper/NotebookTab.hpp b/src/widgets/helper/NotebookTab.hpp index cfd2e1d348c..ec0ad0ad986 100644 --- a/src/widgets/helper/NotebookTab.hpp +++ b/src/widgets/helper/NotebookTab.hpp @@ -2,6 +2,7 @@ #include "common/Common.hpp" #include "widgets/helper/Button.hpp" +#include "widgets/helper/ChannelView.hpp" #include "widgets/Notebook.hpp" #include @@ -14,7 +15,6 @@ namespace chatterino { inline constexpr int NOTEBOOK_TAB_HEIGHT = 28; class SplitContainer; -class ChannelView; class NotebookTab : public Button { @@ -76,7 +76,7 @@ class NotebookTab : public Button const MessagePtr &message); void copyHighlightStateAndSourcesFrom(const NotebookTab *sourceTab); void setHighlightsEnabled(const bool &newVal); - void newHighlightSourceAdded(const ChannelPtr &source); + void newHighlightSourceAdded(const ChannelView &channelViewSource); bool hasHighlightsEnabled() const; HighlightState highlightState() const; @@ -126,8 +126,26 @@ class NotebookTab : public Button const MessagePtr &message) const; struct HighlightSources { - std::unordered_set newMessageSource; - std::unordered_set highlightedSource; + struct ChannelViewProxy { + const ChannelView *channelView; + }; + + struct ChannelViewProxyHash { + using is_transparent = void; + std::size_t operator()(const ChannelViewProxy &cp) const noexcept; + }; + + struct ChannelViewProxyEqual { + bool operator()(const ChannelViewProxy &l, + const ChannelViewProxy &r) const; + }; + + std::unordered_set + newMessageSource; + std::unordered_set + highlightedSource; void clear() { @@ -138,8 +156,10 @@ class NotebookTab : public Button } highlightSources_; void removeHighlightStateChangeSources(const HighlightSources &toRemove); - void removeNewMessageSource(const ChannelPtr &source); - void removeHighlightedSource(const ChannelPtr &source); + void removeNewMessageSource( + const HighlightSources::ChannelViewProxy &source); + void removeHighlightedSource( + const HighlightSources::ChannelViewProxy &source); void updateHighlightStateDueSourcesChange(); QPropertyAnimation positionChangedAnimation_; diff --git a/src/widgets/splits/SplitContainer.cpp b/src/widgets/splits/SplitContainer.cpp index 4e430c6b008..c684d56ea59 100644 --- a/src/widgets/splits/SplitContainer.cpp +++ b/src/widgets/splits/SplitContainer.cpp @@ -224,12 +224,9 @@ void SplitContainer::addSplit(Split *split) }); conns.managedConnect(split->channelChanged, [this, split] { - qDebug() << "Changing Channel" - << split->getChannelView().underlyingChannel()->getName(); if (this->tab_ != nullptr) { - this->tab_->newHighlightSourceAdded( - split->getChannelView().underlyingChannel()); + this->tab_->newHighlightSourceAdded(split->getChannelView()); } }); From b0e3a4131293d3d5ddeeed1dde7e404286a32ad1 Mon Sep 17 00:00:00 2001 From: unknown <1310440+hemirt@users.noreply.github.com> Date: Sun, 20 Oct 2024 18:04:24 +0200 Subject: [PATCH 17/28] message shown based inclusion --- src/widgets/helper/NotebookTab.cpp | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/src/widgets/helper/NotebookTab.cpp b/src/widgets/helper/NotebookTab.cpp index db444b23771..277506890a8 100644 --- a/src/widgets/helper/NotebookTab.cpp +++ b/src/widgets/helper/NotebookTab.cpp @@ -628,20 +628,10 @@ bool NotebookTab::shouldMessageHighlight(const ChannelView &channelViewSource, const auto &visibleSplits = visibleSplitContainer->getSplits(); for (const auto &visibleSplit : visibleSplits) { - auto filterIdsSource = channelViewSource.getFilterIds(); - auto filterIdsSplit = visibleSplit->getChannelView().getFilterIds(); - - auto isSubset = [](const QList &sub, - const QList &super) { - return std::ranges::all_of(sub, [&super](const auto &subItem) { - return super.contains(subItem); - }); - }; - if (channelViewSource.underlyingChannel() == visibleSplit->getChannel() && visibleSplit->getChannelView().shouldIncludeMessage(message) && - isSubset(filterIdsSource, filterIdsSplit)) + channelViewSource.shouldIncludeMessage(message)) { // all filters in unvisible source are found in visible split // therefore the unvisible split is more generic than the visible one From ef2647fe050f2ff5f5a5e2d60b623b7f8d4ae688 Mon Sep 17 00:00:00 2001 From: unknown <1310440+hemirt@users.noreply.github.com> Date: Sun, 20 Oct 2024 18:23:21 +0200 Subject: [PATCH 18/28] treat filters as special channels that should highlight always --- src/widgets/helper/NotebookTab.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/widgets/helper/NotebookTab.cpp b/src/widgets/helper/NotebookTab.cpp index 277506890a8..f56cef83516 100644 --- a/src/widgets/helper/NotebookTab.cpp +++ b/src/widgets/helper/NotebookTab.cpp @@ -631,12 +631,9 @@ bool NotebookTab::shouldMessageHighlight(const ChannelView &channelViewSource, if (channelViewSource.underlyingChannel() == visibleSplit->getChannel() && visibleSplit->getChannelView().shouldIncludeMessage(message) && - channelViewSource.shouldIncludeMessage(message)) + channelViewSource.shouldIncludeMessage(message) && + channelViewSource.getFilterIds().empty()) { - // all filters in unvisible source are found in visible split - // therefore the unvisible split is more generic than the visible one - // and the visible one is showing current message - // so no highlight of unvisible tab needed return false; } } From af3d46fe25453a041ce45ca0ff225fc216c995bf Mon Sep 17 00:00:00 2001 From: unknown <1310440+hemirt@users.noreply.github.com> Date: Sun, 20 Oct 2024 18:45:34 +0200 Subject: [PATCH 19/28] add boost hash include --- src/widgets/helper/NotebookTab.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/widgets/helper/NotebookTab.cpp b/src/widgets/helper/NotebookTab.cpp index f56cef83516..ca14d384bd6 100644 --- a/src/widgets/helper/NotebookTab.cpp +++ b/src/widgets/helper/NotebookTab.cpp @@ -17,6 +17,7 @@ #include "widgets/splits/SplitContainer.hpp" #include +#include #include #include #include From 79ee3dc417da572ec02270421b5310feae38db4f Mon Sep 17 00:00:00 2001 From: unknown <1310440+hemirt@users.noreply.github.com> Date: Mon, 21 Oct 2024 07:27:00 +0200 Subject: [PATCH 20/28] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a08aac4806..71a68604728 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,6 +37,7 @@ - Minor: Indicate when subscriptions and resubscriptions are for multiple months. (#5642) - Minor: Proxy URL information is now included in the `/debug-env` command. (#5648) - Minor: Make raid entry message usernames clickable. (#5651) +- Minor: Tabs unhighlight when their content is read in other tabs. (#5649) - Bugfix: Fixed tab move animation occasionally failing to start after closing a tab. (#5426, #5612) - Bugfix: If a network request errors with 200 OK, Qt's error code is now reported instead of the HTTP status. (#5378) - Bugfix: Fixed restricted users usernames not being clickable. (#5405) From e5e5a79645b7e3163468b0ae73ad75fbeb88ab00 Mon Sep 17 00:00:00 2001 From: unknown <1310440+hemirt@users.noreply.github.com> Date: Tue, 22 Oct 2024 10:04:35 +0200 Subject: [PATCH 21/28] do not higlight tabs that are marked as not highlight for new messages --- src/widgets/helper/NotebookTab.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/widgets/helper/NotebookTab.cpp b/src/widgets/helper/NotebookTab.cpp index ca14d384bd6..251b64af25b 100644 --- a/src/widgets/helper/NotebookTab.cpp +++ b/src/widgets/helper/NotebookTab.cpp @@ -568,6 +568,12 @@ void NotebookTab::updateHighlightState(HighlightState newHighlightStyle, return; } + if (!this->highlightEnabled_ && + newHighlightStyle == HighlightState::NewMessage) + { + return; + } + // message is highlighting unvisible tab auto underlyingChannel = channelViewSource.underlyingChannel(); @@ -603,12 +609,6 @@ void NotebookTab::updateHighlightState(HighlightState newHighlightStyle, break; } - if (!this->highlightEnabled_ && - newHighlightStyle == HighlightState::NewMessage) - { - return; - } - if (this->highlightState_ == newHighlightStyle || this->highlightState_ == HighlightState::Highlighted) { From 374e0c5fa03d9b8e3dec45dd3873620d8301ca69 Mon Sep 17 00:00:00 2001 From: unknown <1310440+hemirt@users.noreply.github.com> Date: Wed, 23 Oct 2024 00:28:47 +0200 Subject: [PATCH 22/28] remove leftovers --- src/widgets/Notebook.hpp | 1 - src/widgets/helper/NotebookTab.cpp | 5 ----- 2 files changed, 6 deletions(-) diff --git a/src/widgets/Notebook.hpp b/src/widgets/Notebook.hpp index 23888ae612c..ac6c4dad79f 100644 --- a/src/widgets/Notebook.hpp +++ b/src/widgets/Notebook.hpp @@ -2,7 +2,6 @@ #include "widgets/BaseWidget.hpp" -#include #include #include #include diff --git a/src/widgets/helper/NotebookTab.cpp b/src/widgets/helper/NotebookTab.cpp index 251b64af25b..1040ebe3811 100644 --- a/src/widgets/helper/NotebookTab.cpp +++ b/src/widgets/helper/NotebookTab.cpp @@ -356,7 +356,6 @@ void NotebookTab::newHighlightSourceAdded(const ChannelView &channelViewSource) { auto channelViewProxy = HighlightSources::ChannelViewProxy{&channelViewSource}; - auto sourceChannel = channelViewSource.underlyingChannel(); this->removeHighlightedSource(channelViewProxy); this->removeNewMessageSource(channelViewProxy); this->updateHighlightStateDueSourcesChange(); @@ -581,10 +580,6 @@ void NotebookTab::updateHighlightState(HighlightState newHighlightStyle, auto channelViewProxy = HighlightSources::ChannelViewProxy{&channelViewSource}; - // the unvisible tab should unhighlight other tabs iff - // the other tab's filters are more generic therefore - // the other tab's filter set is subset of the unvisible tab - switch (newHighlightStyle) { case HighlightState::Highlighted: { From 0e4897969b8e132f2f675c84f418c9412ac1d313 Mon Sep 17 00:00:00 2001 From: unknown <1310440+hemirt@users.noreply.github.com> Date: Wed, 23 Oct 2024 00:57:57 +0200 Subject: [PATCH 23/28] replace ChannelViewProxy with ChannelViewId --- src/widgets/helper/NotebookTab.cpp | 57 ++++++++++-------------------- src/widgets/helper/NotebookTab.hpp | 44 ++++++++++------------- 2 files changed, 37 insertions(+), 64 deletions(-) diff --git a/src/widgets/helper/NotebookTab.cpp b/src/widgets/helper/NotebookTab.cpp index 1040ebe3811..eddb441236b 100644 --- a/src/widgets/helper/NotebookTab.cpp +++ b/src/widgets/helper/NotebookTab.cpp @@ -56,27 +56,6 @@ namespace { } } // namespace -std::size_t NotebookTab::HighlightSources::ChannelViewProxyHash::operator()( - const ChannelViewProxy &cp) const noexcept -{ - std::size_t seed = 0; - auto first = qHash(cp.channelView->underlyingChannel()->getName()); - auto second = qHash(cp.channelView->getFilterIds()); - - boost::hash_combine(seed, first); - boost::hash_combine(seed, second); - - return seed; -} - -bool NotebookTab::HighlightSources::ChannelViewProxyEqual::operator()( - const ChannelViewProxy &lp, const ChannelViewProxy &rp) const -{ - return lp.channelView->underlyingChannel() == - rp.channelView->underlyingChannel() && - lp.channelView->getFilterIds() == rp.channelView->getFilterIds(); -} - NotebookTab::NotebookTab(Notebook *notebook) : Button(notebook) , positionChangedAnimation_(this, "pos") @@ -327,13 +306,13 @@ bool NotebookTab::isSelected() const } void NotebookTab::removeNewMessageSource( - const HighlightSources::ChannelViewProxy &source) + const HighlightSources::ChannelViewId &source) { this->highlightSources_.newMessageSource.erase(source); } void NotebookTab::removeHighlightedSource( - const HighlightSources::ChannelViewProxy &source) + const HighlightSources::ChannelViewId &source) { this->highlightSources_.highlightedSource.erase(source); } @@ -354,10 +333,12 @@ void NotebookTab::removeHighlightStateChangeSources( void NotebookTab::newHighlightSourceAdded(const ChannelView &channelViewSource) { - auto channelViewProxy = - HighlightSources::ChannelViewProxy{&channelViewSource}; - this->removeHighlightedSource(channelViewProxy); - this->removeNewMessageSource(channelViewProxy); + const auto &channelName = channelViewSource.underlyingChannel()->getName(); + const auto &channelFilterIds = channelViewSource.getFilterIds(); + auto channelViewId = + HighlightSources::GetChannelViewId(channelName, channelFilterIds); + this->removeHighlightedSource(channelViewId); + this->removeNewMessageSource(channelViewId); this->updateHighlightStateDueSourcesChange(); auto *splitNotebook = dynamic_cast(this->notebook_); @@ -372,8 +353,8 @@ void NotebookTab::newHighlightSourceAdded(const ChannelView &channelViewSource) auto *tab = splitContainer->getTab(); if (tab && tab != this) { - tab->removeHighlightedSource(channelViewProxy); - tab->removeNewMessageSource(channelViewProxy); + tab->removeHighlightedSource(channelViewId); + tab->removeNewMessageSource(channelViewId); tab->updateHighlightStateDueSourcesChange(); } } @@ -575,28 +556,26 @@ void NotebookTab::updateHighlightState(HighlightState newHighlightStyle, // message is highlighting unvisible tab - auto underlyingChannel = channelViewSource.underlyingChannel(); - auto newFilters = channelViewSource.getFilterIds(); - auto channelViewProxy = - HighlightSources::ChannelViewProxy{&channelViewSource}; + const auto &channelName = channelViewSource.underlyingChannel()->getName(); + const auto &channelFilterIds = channelViewSource.getFilterIds(); + auto channelViewId = + HighlightSources::GetChannelViewId(channelName, channelFilterIds); switch (newHighlightStyle) { case HighlightState::Highlighted: { if (!this->highlightSources_.highlightedSource.contains( - channelViewProxy)) + channelViewId)) { - this->highlightSources_.highlightedSource.insert( - channelViewProxy); + this->highlightSources_.highlightedSource.insert(channelViewId); } break; } case HighlightState::NewMessage: { if (!this->highlightSources_.newMessageSource.contains( - channelViewProxy)) + channelViewId)) { - this->highlightSources_.newMessageSource.insert( - channelViewProxy); + this->highlightSources_.newMessageSource.insert(channelViewId); } break; } diff --git a/src/widgets/helper/NotebookTab.hpp b/src/widgets/helper/NotebookTab.hpp index ec0ad0ad986..5bef5fbeecd 100644 --- a/src/widgets/helper/NotebookTab.hpp +++ b/src/widgets/helper/NotebookTab.hpp @@ -126,40 +126,34 @@ class NotebookTab : public Button const MessagePtr &message) const; struct HighlightSources { - struct ChannelViewProxy { - const ChannelView *channelView; - }; - - struct ChannelViewProxyHash { - using is_transparent = void; - std::size_t operator()(const ChannelViewProxy &cp) const noexcept; - }; - - struct ChannelViewProxyEqual { - bool operator()(const ChannelViewProxy &l, - const ChannelViewProxy &r) const; - }; - - std::unordered_set - newMessageSource; - std::unordered_set - highlightedSource; + using ChannelViewId = std::size_t; + + static ChannelViewId GetChannelViewId( + const QString &channelName, const QList &channelFilterIds) + { + std::size_t seed = 0; + auto first = qHash(channelName); + auto second = qHash(channelFilterIds); + + boost::hash_combine(seed, first); + boost::hash_combine(seed, second); + + return seed; + } + + std::unordered_set newMessageSource; + std::unordered_set highlightedSource; void clear() { this->newMessageSource.clear(); this->highlightedSource.clear(); } - } highlightSources_; void removeHighlightStateChangeSources(const HighlightSources &toRemove); - void removeNewMessageSource( - const HighlightSources::ChannelViewProxy &source); - void removeHighlightedSource( - const HighlightSources::ChannelViewProxy &source); + void removeNewMessageSource(const HighlightSources::ChannelViewId &source); + void removeHighlightedSource(const HighlightSources::ChannelViewId &source); void updateHighlightStateDueSourcesChange(); QPropertyAnimation positionChangedAnimation_; From 1bdb11839129fe3ceff801746b653dc77f4d4622 Mon Sep 17 00:00:00 2001 From: unknown <1310440+hemirt@users.noreply.github.com> Date: Wed, 23 Oct 2024 01:29:37 +0200 Subject: [PATCH 24/28] cache channel view id --- src/widgets/helper/ChannelView.cpp | 27 +++++++++++++++++++++++++++ src/widgets/helper/ChannelView.hpp | 6 ++++++ src/widgets/helper/NotebookTab.cpp | 14 ++++---------- src/widgets/helper/NotebookTab.hpp | 23 ++++------------------- 4 files changed, 41 insertions(+), 29 deletions(-) diff --git a/src/widgets/helper/ChannelView.cpp b/src/widgets/helper/ChannelView.cpp index 54d5dded5ec..7e2f37409d3 100644 --- a/src/widgets/helper/ChannelView.cpp +++ b/src/widgets/helper/ChannelView.cpp @@ -1063,6 +1063,8 @@ void ChannelView::setChannel(const ChannelPtr &underlyingChannel) this->underlyingChannel_ = underlyingChannel; + this->updateID(); + this->performLayout(); this->queueUpdate(); @@ -1081,6 +1083,8 @@ void ChannelView::setChannel(const ChannelPtr &underlyingChannel) void ChannelView::setFilters(const QList &ids) { this->channelFilters_ = std::make_shared(ids); + + this->updateID(); } QList ChannelView::getFilterIds() const @@ -3237,4 +3241,27 @@ void ChannelView::pendingLinkInfoStateChanged() this->tooltipWidget_->applyLastBoundsCheck(); } +void ChannelView::updateID() +{ + if (!this->underlyingChannel_) + { + // cannot update + return; + } + + std::size_t seed = 0; + auto first = qHash(this->underlyingChannel_->getName()); + auto second = qHash(this->getFilterIds()); + + boost::hash_combine(seed, first); + boost::hash_combine(seed, second); + + this->id_ = seed; +} + +ChannelView::ChannelViewID ChannelView::getID() const +{ + return this->id_; +} + } // namespace chatterino diff --git a/src/widgets/helper/ChannelView.hpp b/src/widgets/helper/ChannelView.hpp index 52d08803a16..74fd0aa393c 100644 --- a/src/widgets/helper/ChannelView.hpp +++ b/src/widgets/helper/ChannelView.hpp @@ -215,6 +215,9 @@ class ChannelView final : public BaseWidget Scrollbar *scrollbar(); + using ChannelViewID = std::size_t; + ChannelViewID getID() const; + pajlada::Signals::Signal mouseDown; pajlada::Signals::NoArgSignal selectionChanged; pajlada::Signals::Signal @@ -318,6 +321,9 @@ class ChannelView final : public BaseWidget void showReplyThreadPopup(const MessagePtr &message); bool canReplyToMessages() const; + void updateID(); + ChannelViewID id_{}; + bool layoutQueued_ = false; bool bufferInvalidationQueued_ = false; diff --git a/src/widgets/helper/NotebookTab.cpp b/src/widgets/helper/NotebookTab.cpp index eddb441236b..23d7d90bc98 100644 --- a/src/widgets/helper/NotebookTab.cpp +++ b/src/widgets/helper/NotebookTab.cpp @@ -306,13 +306,13 @@ bool NotebookTab::isSelected() const } void NotebookTab::removeNewMessageSource( - const HighlightSources::ChannelViewId &source) + const ChannelView::ChannelViewID &source) { this->highlightSources_.newMessageSource.erase(source); } void NotebookTab::removeHighlightedSource( - const HighlightSources::ChannelViewId &source) + const ChannelView::ChannelViewID &source) { this->highlightSources_.highlightedSource.erase(source); } @@ -333,10 +333,7 @@ void NotebookTab::removeHighlightStateChangeSources( void NotebookTab::newHighlightSourceAdded(const ChannelView &channelViewSource) { - const auto &channelName = channelViewSource.underlyingChannel()->getName(); - const auto &channelFilterIds = channelViewSource.getFilterIds(); - auto channelViewId = - HighlightSources::GetChannelViewId(channelName, channelFilterIds); + auto channelViewId = channelViewSource.getID(); this->removeHighlightedSource(channelViewId); this->removeNewMessageSource(channelViewId); this->updateHighlightStateDueSourcesChange(); @@ -556,10 +553,7 @@ void NotebookTab::updateHighlightState(HighlightState newHighlightStyle, // message is highlighting unvisible tab - const auto &channelName = channelViewSource.underlyingChannel()->getName(); - const auto &channelFilterIds = channelViewSource.getFilterIds(); - auto channelViewId = - HighlightSources::GetChannelViewId(channelName, channelFilterIds); + auto channelViewId = channelViewSource.getID(); switch (newHighlightStyle) { diff --git a/src/widgets/helper/NotebookTab.hpp b/src/widgets/helper/NotebookTab.hpp index 5bef5fbeecd..2d3865daafd 100644 --- a/src/widgets/helper/NotebookTab.hpp +++ b/src/widgets/helper/NotebookTab.hpp @@ -126,23 +126,8 @@ class NotebookTab : public Button const MessagePtr &message) const; struct HighlightSources { - using ChannelViewId = std::size_t; - - static ChannelViewId GetChannelViewId( - const QString &channelName, const QList &channelFilterIds) - { - std::size_t seed = 0; - auto first = qHash(channelName); - auto second = qHash(channelFilterIds); - - boost::hash_combine(seed, first); - boost::hash_combine(seed, second); - - return seed; - } - - std::unordered_set newMessageSource; - std::unordered_set highlightedSource; + std::unordered_set newMessageSource; + std::unordered_set highlightedSource; void clear() { @@ -152,8 +137,8 @@ class NotebookTab : public Button } highlightSources_; void removeHighlightStateChangeSources(const HighlightSources &toRemove); - void removeNewMessageSource(const HighlightSources::ChannelViewId &source); - void removeHighlightedSource(const HighlightSources::ChannelViewId &source); + void removeNewMessageSource(const ChannelView::ChannelViewID &source); + void removeHighlightedSource(const ChannelView::ChannelViewID &source); void updateHighlightStateDueSourcesChange(); QPropertyAnimation positionChangedAnimation_; From 55c0e6980f468e52fe0e486b6bff67305c62ff61 Mon Sep 17 00:00:00 2001 From: unknown <1310440+hemirt@users.noreply.github.com> Date: Sat, 26 Oct 2024 13:38:38 +0200 Subject: [PATCH 25/28] treat each channelView with its filter as its own --- src/widgets/helper/ChannelView.hpp | 7 ++++++- src/widgets/helper/NotebookTab.cpp | 7 +++---- src/widgets/helper/NotebookTab.hpp | 5 +++++ 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/widgets/helper/ChannelView.hpp b/src/widgets/helper/ChannelView.hpp index 74fd0aa393c..7c91d723445 100644 --- a/src/widgets/helper/ChannelView.hpp +++ b/src/widgets/helper/ChannelView.hpp @@ -180,7 +180,7 @@ class ChannelView final : public BaseWidget LimitedQueueSnapshot &getMessagesSnapshot(); // Returns true if message should be included - bool shouldIncludeMessage(const MessagePtr &m) const; + bool shouldIncludeMessage(const MessagePtr &message) const; void queueLayout(); void invalidateBuffers(); @@ -216,6 +216,11 @@ class ChannelView final : public BaseWidget Scrollbar *scrollbar(); using ChannelViewID = std::size_t; + /// + /// \brief Get the ID of this ChannelView + /// + /// The ID is made of the underlying channel's name + /// combined with the filter set IDs ChannelViewID getID() const; pajlada::Signals::Signal mouseDown; diff --git a/src/widgets/helper/NotebookTab.cpp b/src/widgets/helper/NotebookTab.cpp index 23d7d90bc98..d3b2c2517b3 100644 --- a/src/widgets/helper/NotebookTab.cpp +++ b/src/widgets/helper/NotebookTab.cpp @@ -597,11 +597,10 @@ bool NotebookTab::shouldMessageHighlight(const ChannelView &channelViewSource, const auto &visibleSplits = visibleSplitContainer->getSplits(); for (const auto &visibleSplit : visibleSplits) { - if (channelViewSource.underlyingChannel() == - visibleSplit->getChannel() && + if (channelViewSource.getID() == + visibleSplit->getChannelView().getID() && visibleSplit->getChannelView().shouldIncludeMessage(message) && - channelViewSource.shouldIncludeMessage(message) && - channelViewSource.getFilterIds().empty()) + channelViewSource.shouldIncludeMessage(message)) { return false; } diff --git a/src/widgets/helper/NotebookTab.hpp b/src/widgets/helper/NotebookTab.hpp index 2d3865daafd..28682eef6e4 100644 --- a/src/widgets/helper/NotebookTab.hpp +++ b/src/widgets/helper/NotebookTab.hpp @@ -126,6 +126,11 @@ class NotebookTab : public Button const MessagePtr &message) const; struct HighlightSources { + // Source of the update to the highlight status is the split + // in which a message that causes the update appears. + // This message can be just a plain message causing the + // HighlightState::NewMessage state, or a message that pings the user + // causing the HighlightState::Highlighted state std::unordered_set newMessageSource; std::unordered_set highlightedSource; From 05ab3b27e783c33aceaed78f283a6b05aeed54e5 Mon Sep 17 00:00:00 2001 From: unknown <1310440+hemirt@users.noreply.github.com> Date: Sat, 26 Oct 2024 16:19:57 +0200 Subject: [PATCH 26/28] switch from using two sets to one map --- src/widgets/helper/NotebookTab.cpp | 67 ++++++++++++------------------ src/widgets/helper/NotebookTab.hpp | 21 ++-------- 2 files changed, 30 insertions(+), 58 deletions(-) diff --git a/src/widgets/helper/NotebookTab.cpp b/src/widgets/helper/NotebookTab.cpp index d3b2c2517b3..09630c7e087 100644 --- a/src/widgets/helper/NotebookTab.cpp +++ b/src/widgets/helper/NotebookTab.cpp @@ -305,37 +305,25 @@ bool NotebookTab::isSelected() const return this->selected_; } -void NotebookTab::removeNewMessageSource( - const ChannelView::ChannelViewID &source) -{ - this->highlightSources_.newMessageSource.erase(source); -} - -void NotebookTab::removeHighlightedSource( - const ChannelView::ChannelViewID &source) -{ - this->highlightSources_.highlightedSource.erase(source); -} - void NotebookTab::removeHighlightStateChangeSources( const HighlightSources &toRemove) { - for (const auto &source : toRemove.newMessageSource) + for (const auto &[source, _] : toRemove) { - this->removeNewMessageSource(source); + this->removeHighlightSource(source); } +} - for (const auto &source : toRemove.highlightedSource) - { - this->removeHighlightedSource(source); - } +void NotebookTab::removeHighlightSource( + const ChannelView::ChannelViewID &source) +{ + this->highlightSources_.erase(source); } void NotebookTab::newHighlightSourceAdded(const ChannelView &channelViewSource) { auto channelViewId = channelViewSource.getID(); - this->removeHighlightedSource(channelViewId); - this->removeNewMessageSource(channelViewId); + this->removeHighlightSource(channelViewId); this->updateHighlightStateDueSourcesChange(); auto *splitNotebook = dynamic_cast(this->notebook_); @@ -350,8 +338,7 @@ void NotebookTab::newHighlightSourceAdded(const ChannelView &channelViewSource) auto *tab = splitContainer->getTab(); if (tab && tab != this) { - tab->removeHighlightedSource(channelViewId); - tab->removeNewMessageSource(channelViewId); + tab->removeHighlightSource(channelViewId); tab->updateHighlightStateDueSourcesChange(); } } @@ -361,13 +348,17 @@ void NotebookTab::newHighlightSourceAdded(const ChannelView &channelViewSource) void NotebookTab::updateHighlightStateDueSourcesChange() { - if (!this->highlightSources_.highlightedSource.empty()) + if (std::ranges::any_of(this->highlightSources_, [](const auto &keyval) { + return keyval.second == HighlightState::Highlighted; + })) { assert(this->highlightState_ == HighlightState::Highlighted); return; } - if (!this->highlightSources_.newMessageSource.empty()) + if (std::ranges::any_of(this->highlightSources_, [](const auto &keyval) { + return keyval.second == HighlightState::NewMessage; + })) { if (this->highlightState_ != HighlightState::NewMessage) { @@ -391,8 +382,7 @@ void NotebookTab::copyHighlightStateAndSourcesFrom(const NotebookTab *sourceTab) { if (this->isSelected()) { - assert(this->highlightSources_.highlightedSource.empty()); - assert(this->highlightSources_.newMessageSource.empty()); + assert(this->highlightSources_.empty()); assert(this->highlightState_ == HighlightState::None); return; } @@ -504,8 +494,7 @@ void NotebookTab::setHighlightState(HighlightState newHighlightStyle) { if (this->isSelected()) { - assert(this->highlightSources_.highlightedSource.empty()); - assert(this->highlightSources_.newMessageSource.empty()); + assert(this->highlightSources_.empty()); assert(this->highlightState_ == HighlightState::None); return; } @@ -534,8 +523,7 @@ void NotebookTab::updateHighlightState(HighlightState newHighlightStyle, { if (this->isSelected()) { - assert(this->highlightSources_.highlightedSource.empty()); - assert(this->highlightSources_.newMessageSource.empty()); + assert(this->highlightSources_.empty()); assert(this->highlightState_ == HighlightState::None); return; } @@ -557,19 +545,16 @@ void NotebookTab::updateHighlightState(HighlightState newHighlightStyle, switch (newHighlightStyle) { - case HighlightState::Highlighted: { - if (!this->highlightSources_.highlightedSource.contains( - channelViewId)) - { - this->highlightSources_.highlightedSource.insert(channelViewId); - } - break; - } + case HighlightState::Highlighted: + // override lower states + this->highlightSources_.insert_or_assign(channelViewId, + newHighlightStyle); case HighlightState::NewMessage: { - if (!this->highlightSources_.newMessageSource.contains( - channelViewId)) + // only insert if no state already there to avoid overriding + if (!this->highlightSources_.contains(channelViewId)) { - this->highlightSources_.newMessageSource.insert(channelViewId); + this->highlightSources_.emplace(channelViewId, + newHighlightStyle); } break; } diff --git a/src/widgets/helper/NotebookTab.hpp b/src/widgets/helper/NotebookTab.hpp index 28682eef6e4..e210d4829a2 100644 --- a/src/widgets/helper/NotebookTab.hpp +++ b/src/widgets/helper/NotebookTab.hpp @@ -125,25 +125,12 @@ class NotebookTab : public Button bool shouldMessageHighlight(const ChannelView &channelViewSource, const MessagePtr &message) const; - struct HighlightSources { - // Source of the update to the highlight status is the split - // in which a message that causes the update appears. - // This message can be just a plain message causing the - // HighlightState::NewMessage state, or a message that pings the user - // causing the HighlightState::Highlighted state - std::unordered_set newMessageSource; - std::unordered_set highlightedSource; - - void clear() - { - this->newMessageSource.clear(); - this->highlightedSource.clear(); - } - } highlightSources_; + using HighlightSources = + std::unordered_map; + HighlightSources highlightSources_; void removeHighlightStateChangeSources(const HighlightSources &toRemove); - void removeNewMessageSource(const ChannelView::ChannelViewID &source); - void removeHighlightedSource(const ChannelView::ChannelViewID &source); + void removeHighlightSource(const ChannelView::ChannelViewID &source); void updateHighlightStateDueSourcesChange(); QPropertyAnimation positionChangedAnimation_; From 0e506fc1757dde8c553b296d3689fcb44119e4d4 Mon Sep 17 00:00:00 2001 From: unknown <1310440+hemirt@users.noreply.github.com> Date: Mon, 28 Oct 2024 13:41:16 +0100 Subject: [PATCH 27/28] remove remnants of different strategy --- src/widgets/helper/ChannelView.cpp | 6 ++---- src/widgets/helper/ChannelView.hpp | 3 +-- src/widgets/helper/NotebookTab.cpp | 13 +++++-------- src/widgets/helper/NotebookTab.hpp | 6 ++---- src/widgets/splits/SplitContainer.cpp | 17 ++++++++--------- 5 files changed, 18 insertions(+), 27 deletions(-) diff --git a/src/widgets/helper/ChannelView.cpp b/src/widgets/helper/ChannelView.cpp index eb33cef3b2c..c63ba474bed 100644 --- a/src/widgets/helper/ChannelView.cpp +++ b/src/widgets/helper/ChannelView.cpp @@ -1194,13 +1194,11 @@ void ChannelView::messageAppended(MessagePtr &message, (this->channel_->getType() == Channel::Type::TwitchAutomod && getSettings()->enableAutomodHighlight)) { - this->tabHighlightRequested.invoke(HighlightState::Highlighted, - message); + this->tabHighlightRequested.invoke(HighlightState::Highlighted); } else { - this->tabHighlightRequested.invoke(HighlightState::NewMessage, - message); + this->tabHighlightRequested.invoke(HighlightState::NewMessage); } } diff --git a/src/widgets/helper/ChannelView.hpp b/src/widgets/helper/ChannelView.hpp index 7c91d723445..a39efe4e85a 100644 --- a/src/widgets/helper/ChannelView.hpp +++ b/src/widgets/helper/ChannelView.hpp @@ -225,8 +225,7 @@ class ChannelView final : public BaseWidget pajlada::Signals::Signal mouseDown; pajlada::Signals::NoArgSignal selectionChanged; - pajlada::Signals::Signal - tabHighlightRequested; + pajlada::Signals::Signal tabHighlightRequested; pajlada::Signals::NoArgSignal liveStatusChanged; pajlada::Signals::Signal linkClicked; pajlada::Signals::Signal diff --git a/src/widgets/helper/NotebookTab.cpp b/src/widgets/helper/NotebookTab.cpp index 09630c7e087..563084d39fb 100644 --- a/src/widgets/helper/NotebookTab.cpp +++ b/src/widgets/helper/NotebookTab.cpp @@ -518,8 +518,7 @@ void NotebookTab::setHighlightState(HighlightState newHighlightStyle) } void NotebookTab::updateHighlightState(HighlightState newHighlightStyle, - const ChannelView &channelViewSource, - const MessagePtr &message) + const ChannelView &channelViewSource) { if (this->isSelected()) { @@ -528,7 +527,7 @@ void NotebookTab::updateHighlightState(HighlightState newHighlightStyle, return; } - if (!this->shouldMessageHighlight(channelViewSource, message)) + if (!this->shouldMessageHighlight(channelViewSource)) { return; } @@ -572,8 +571,8 @@ void NotebookTab::updateHighlightState(HighlightState newHighlightStyle, this->update(); } -bool NotebookTab::shouldMessageHighlight(const ChannelView &channelViewSource, - const MessagePtr &message) const +bool NotebookTab::shouldMessageHighlight( + const ChannelView &channelViewSource) const { auto *visibleSplitContainer = dynamic_cast(this->notebook_->getSelectedPage()); @@ -583,9 +582,7 @@ bool NotebookTab::shouldMessageHighlight(const ChannelView &channelViewSource, for (const auto &visibleSplit : visibleSplits) { if (channelViewSource.getID() == - visibleSplit->getChannelView().getID() && - visibleSplit->getChannelView().shouldIncludeMessage(message) && - channelViewSource.shouldIncludeMessage(message)) + visibleSplit->getChannelView().getID()) { return false; } diff --git a/src/widgets/helper/NotebookTab.hpp b/src/widgets/helper/NotebookTab.hpp index e210d4829a2..ae3bfbc2f76 100644 --- a/src/widgets/helper/NotebookTab.hpp +++ b/src/widgets/helper/NotebookTab.hpp @@ -72,8 +72,7 @@ class NotebookTab : public Button * Obeys the HighlightsEnabled setting and the highlight state hierarchy and tracks the highlight state update sources */ void updateHighlightState(HighlightState style, - const ChannelView &channelViewSource, - const MessagePtr &message); + const ChannelView &channelViewSource); void copyHighlightStateAndSourcesFrom(const NotebookTab *sourceTab); void setHighlightsEnabled(const bool &newVal); void newHighlightSourceAdded(const ChannelView &channelViewSource); @@ -122,8 +121,7 @@ class NotebookTab : public Button int normalTabWidthForHeight(int height) const; - bool shouldMessageHighlight(const ChannelView &channelViewSource, - const MessagePtr &message) const; + bool shouldMessageHighlight(const ChannelView &channelViewSource) const; using HighlightSources = std::unordered_map; diff --git a/src/widgets/splits/SplitContainer.cpp b/src/widgets/splits/SplitContainer.cpp index e0ef7d4eaec..430098f0ed8 100644 --- a/src/widgets/splits/SplitContainer.cpp +++ b/src/widgets/splits/SplitContainer.cpp @@ -213,15 +213,14 @@ void SplitContainer::addSplit(Split *split) auto &&conns = this->connectionsPerSplit_[split]; - conns.managedConnect( - split->getChannelView().tabHighlightRequested, - [this, split](HighlightState state, const MessagePtr &message) { - if (this->tab_ != nullptr) - { - this->tab_->updateHighlightState(state, split->getChannelView(), - message); - } - }); + conns.managedConnect(split->getChannelView().tabHighlightRequested, + [this, split](HighlightState state) { + if (this->tab_ != nullptr) + { + this->tab_->updateHighlightState( + state, split->getChannelView()); + } + }); conns.managedConnect(split->channelChanged, [this, split] { if (this->tab_ != nullptr) From de87f226844a5dfcb61aecbf46cbc4a29ffba45b Mon Sep 17 00:00:00 2001 From: unknown <1310440+hemirt@users.noreply.github.com> Date: Mon, 28 Oct 2024 20:11:31 +0100 Subject: [PATCH 28/28] revert publicizing shouldIncludeMessage from channelview --- src/widgets/helper/ChannelView.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/widgets/helper/ChannelView.hpp b/src/widgets/helper/ChannelView.hpp index a39efe4e85a..e0981dd493b 100644 --- a/src/widgets/helper/ChannelView.hpp +++ b/src/widgets/helper/ChannelView.hpp @@ -179,9 +179,6 @@ class ChannelView final : public BaseWidget LimitedQueueSnapshot &getMessagesSnapshot(); - // Returns true if message should be included - bool shouldIncludeMessage(const MessagePtr &message) const; - void queueLayout(); void invalidateBuffers(); @@ -388,6 +385,9 @@ class ChannelView final : public BaseWidget FilterSetPtr channelFilters_; + // Returns true if message should be included + bool shouldIncludeMessage(const MessagePtr &message) const; + // Returns whether the scrollbar should have highlights bool showScrollbarHighlights() const;