mirror of
https://github.com/Chatterino/chatterino2.git
synced 2024-11-13 19:49:51 +01:00
Merge e288742360
into 6d139af553
This commit is contained in:
commit
96f9b845d3
|
@ -204,7 +204,7 @@ void Notebook::duplicatePage(QWidget *page)
|
||||||
{
|
{
|
||||||
newTabPosition = tabPosition + 1;
|
newTabPosition = tabPosition + 1;
|
||||||
}
|
}
|
||||||
auto newTabHighlightState = item->tab->highlightState();
|
|
||||||
QString newTabTitle = "";
|
QString newTabTitle = "";
|
||||||
if (item->tab->hasCustomTitle())
|
if (item->tab->hasCustomTitle())
|
||||||
{
|
{
|
||||||
|
@ -213,7 +213,7 @@ void Notebook::duplicatePage(QWidget *page)
|
||||||
|
|
||||||
auto *tab =
|
auto *tab =
|
||||||
this->addPageAt(newContainer, newTabPosition, newTabTitle, false);
|
this->addPageAt(newContainer, newTabPosition, newTabTitle, false);
|
||||||
tab->setHighlightState(newTabHighlightState);
|
tab->copyHighlightStateAndSourcesFrom(item->tab);
|
||||||
|
|
||||||
newContainer->setTab(tab);
|
newContainer->setTab(tab);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include "widgets/BaseWidget.hpp"
|
#include "widgets/BaseWidget.hpp"
|
||||||
|
|
||||||
|
#include <ForwardDecl.hpp>
|
||||||
#include <pajlada/signals/signal.hpp>
|
#include <pajlada/signals/signal.hpp>
|
||||||
#include <pajlada/signals/signalholder.hpp>
|
#include <pajlada/signals/signalholder.hpp>
|
||||||
#include <QList>
|
#include <QList>
|
||||||
|
|
|
@ -1190,11 +1190,13 @@ void ChannelView::messageAppended(MessagePtr &message,
|
||||||
(this->channel_->getType() == Channel::Type::TwitchAutomod &&
|
(this->channel_->getType() == Channel::Type::TwitchAutomod &&
|
||||||
getSettings()->enableAutomodHighlight))
|
getSettings()->enableAutomodHighlight))
|
||||||
{
|
{
|
||||||
this->tabHighlightRequested.invoke(HighlightState::Highlighted);
|
this->tabHighlightRequested.invoke(HighlightState::Highlighted,
|
||||||
|
message);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
this->tabHighlightRequested.invoke(HighlightState::NewMessage);
|
this->tabHighlightRequested.invoke(HighlightState::NewMessage,
|
||||||
|
message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -179,6 +179,9 @@ public:
|
||||||
|
|
||||||
LimitedQueueSnapshot<MessageLayoutPtr> &getMessagesSnapshot();
|
LimitedQueueSnapshot<MessageLayoutPtr> &getMessagesSnapshot();
|
||||||
|
|
||||||
|
// Returns true if message should be included
|
||||||
|
bool shouldIncludeMessage(const MessagePtr &m) const;
|
||||||
|
|
||||||
void queueLayout();
|
void queueLayout();
|
||||||
void invalidateBuffers();
|
void invalidateBuffers();
|
||||||
|
|
||||||
|
@ -214,7 +217,8 @@ public:
|
||||||
|
|
||||||
pajlada::Signals::Signal<QMouseEvent *> mouseDown;
|
pajlada::Signals::Signal<QMouseEvent *> mouseDown;
|
||||||
pajlada::Signals::NoArgSignal selectionChanged;
|
pajlada::Signals::NoArgSignal selectionChanged;
|
||||||
pajlada::Signals::Signal<HighlightState> tabHighlightRequested;
|
pajlada::Signals::Signal<HighlightState, const MessagePtr &>
|
||||||
|
tabHighlightRequested;
|
||||||
pajlada::Signals::NoArgSignal liveStatusChanged;
|
pajlada::Signals::NoArgSignal liveStatusChanged;
|
||||||
pajlada::Signals::Signal<const Link &> linkClicked;
|
pajlada::Signals::Signal<const Link &> linkClicked;
|
||||||
pajlada::Signals::Signal<QString, FromTwitchLinkOpenChannelIn>
|
pajlada::Signals::Signal<QString, FromTwitchLinkOpenChannelIn>
|
||||||
|
@ -374,9 +378,6 @@ private:
|
||||||
|
|
||||||
FilterSetPtr channelFilters_;
|
FilterSetPtr channelFilters_;
|
||||||
|
|
||||||
// Returns true if message should be included
|
|
||||||
bool shouldIncludeMessage(const MessagePtr &m) const;
|
|
||||||
|
|
||||||
// Returns whether the scrollbar should have highlights
|
// Returns whether the scrollbar should have highlights
|
||||||
bool showScrollbarHighlights() const;
|
bool showScrollbarHighlights() const;
|
||||||
|
|
||||||
|
|
|
@ -10,8 +10,10 @@
|
||||||
#include "singletons/WindowManager.hpp"
|
#include "singletons/WindowManager.hpp"
|
||||||
#include "util/Helpers.hpp"
|
#include "util/Helpers.hpp"
|
||||||
#include "widgets/dialogs/SettingsDialog.hpp"
|
#include "widgets/dialogs/SettingsDialog.hpp"
|
||||||
|
#include "widgets/helper/ChannelView.hpp"
|
||||||
#include "widgets/Notebook.hpp"
|
#include "widgets/Notebook.hpp"
|
||||||
#include "widgets/splits/DraggedSplit.hpp"
|
#include "widgets/splits/DraggedSplit.hpp"
|
||||||
|
#include "widgets/splits/Split.hpp"
|
||||||
#include "widgets/splits/SplitContainer.hpp"
|
#include "widgets/splits/SplitContainer.hpp"
|
||||||
|
|
||||||
#include <boost/bind/bind.hpp>
|
#include <boost/bind/bind.hpp>
|
||||||
|
@ -302,10 +304,98 @@ bool NotebookTab::isSelected() const
|
||||||
return this->selected_;
|
return this->selected_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NotebookTab::removeHighlightSources(const HighlightSources &toRemove)
|
||||||
|
{
|
||||||
|
for (const auto &source : toRemove.newMessageSource)
|
||||||
|
{
|
||||||
|
this->highlightSources_.newMessageSource.erase(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto &source : toRemove.highlightedSource)
|
||||||
|
{
|
||||||
|
this->highlightSources_.highlightedSource.erase(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this->highlightSources_.highlightedSource.empty())
|
||||||
|
{
|
||||||
|
assert(this->highlightState_ == 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(this->highlightState_ != HighlightState::Highlighted);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
void NotebookTab::setSelected(bool value)
|
||||||
{
|
{
|
||||||
this->selected_ = value;
|
this->selected_ = value;
|
||||||
|
|
||||||
|
if (value)
|
||||||
|
{
|
||||||
|
auto *splitNotebook = dynamic_cast<SplitNotebook *>(this->notebook_);
|
||||||
|
if (splitNotebook)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < splitNotebook->getPageCount(); ++i)
|
||||||
|
{
|
||||||
|
auto *splitContainer =
|
||||||
|
dynamic_cast<SplitContainer *>(splitNotebook->getPageAt(i));
|
||||||
|
if (splitContainer)
|
||||||
|
{
|
||||||
|
auto *tab = splitContainer->getTab();
|
||||||
|
if (tab && tab != this)
|
||||||
|
{
|
||||||
|
tab->removeHighlightSources(this->highlightSources_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this->highlightSources_.clear();
|
||||||
this->highlightState_ = HighlightState::None;
|
this->highlightState_ = HighlightState::None;
|
||||||
|
|
||||||
this->update();
|
this->update();
|
||||||
|
@ -358,13 +448,82 @@ bool NotebookTab::isLive() const
|
||||||
return this->isLive_;
|
return this->isLive_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HighlightState NotebookTab::highlightState() const
|
||||||
|
{
|
||||||
|
return this->highlightState_;
|
||||||
|
}
|
||||||
|
|
||||||
void NotebookTab::setHighlightState(HighlightState newHighlightStyle)
|
void NotebookTab::setHighlightState(HighlightState newHighlightStyle)
|
||||||
{
|
{
|
||||||
if (this->isSelected())
|
if (this->isSelected())
|
||||||
{
|
{
|
||||||
|
assert(this->highlightSources_.highlightedSource.empty());
|
||||||
|
assert(this->highlightSources_.newMessageSource.empty());
|
||||||
|
assert(this->highlightState_ == HighlightState::None);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this->highlightSources_.clear();
|
||||||
|
|
||||||
|
if (!this->highlightEnabled_ &&
|
||||||
|
newHighlightStyle == HighlightState::NewMessage)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->highlightState_ == newHighlightStyle ||
|
||||||
|
this->highlightState_ == HighlightState::Highlighted)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this->shouldMessageHighlight(channelViewSource, message))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto underlyingChannel = channelViewSource.underlyingChannel();
|
||||||
|
|
||||||
|
switch (newHighlightStyle)
|
||||||
|
{
|
||||||
|
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_ &&
|
if (!this->highlightEnabled_ &&
|
||||||
newHighlightStyle == HighlightState::NewMessage)
|
newHighlightStyle == HighlightState::NewMessage)
|
||||||
{
|
{
|
||||||
|
@ -381,9 +540,37 @@ void NotebookTab::setHighlightState(HighlightState newHighlightStyle)
|
||||||
this->update();
|
this->update();
|
||||||
}
|
}
|
||||||
|
|
||||||
HighlightState NotebookTab::highlightState() const
|
bool NotebookTab::shouldMessageHighlight(const ChannelView &channelViewSource,
|
||||||
|
const MessagePtr &message) const
|
||||||
{
|
{
|
||||||
return this->highlightState_;
|
auto *visibleSplitContainer =
|
||||||
|
dynamic_cast<SplitContainer *>(this->notebook_->getSelectedPage());
|
||||||
|
if (visibleSplitContainer != nullptr)
|
||||||
|
{
|
||||||
|
const auto &visibleSplits = visibleSplitContainer->getSplits();
|
||||||
|
for (const auto &visibleSplit : visibleSplits)
|
||||||
|
{
|
||||||
|
auto filterIdsSource = channelViewSource.getFilterIds();
|
||||||
|
auto filterIdsSplit = visibleSplit->getChannelView().getFilterIds();
|
||||||
|
|
||||||
|
auto isSubset = []<typename T>(const QList<T> &sub,
|
||||||
|
const QList<T> &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))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NotebookTab::setHighlightsEnabled(const bool &newVal)
|
void NotebookTab::setHighlightsEnabled(const bool &newVal)
|
||||||
|
|
|
@ -14,6 +14,7 @@ namespace chatterino {
|
||||||
inline constexpr int NOTEBOOK_TAB_HEIGHT = 28;
|
inline constexpr int NOTEBOOK_TAB_HEIGHT = 28;
|
||||||
|
|
||||||
class SplitContainer;
|
class SplitContainer;
|
||||||
|
class ChannelView;
|
||||||
|
|
||||||
class NotebookTab : public Button
|
class NotebookTab : public Button
|
||||||
{
|
{
|
||||||
|
@ -59,11 +60,24 @@ public:
|
||||||
**/
|
**/
|
||||||
bool isLive() const;
|
bool isLive() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets the highlight state of this tab clearing highlight sources
|
||||||
|
*
|
||||||
|
* Obeys the HighlightsEnabled setting and highlight states hierarchy
|
||||||
|
*/
|
||||||
void setHighlightState(HighlightState style);
|
void setHighlightState(HighlightState style);
|
||||||
HighlightState highlightState() const;
|
/**
|
||||||
|
* @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);
|
void setHighlightsEnabled(const bool &newVal);
|
||||||
bool hasHighlightsEnabled() const;
|
bool hasHighlightsEnabled() const;
|
||||||
|
HighlightState highlightState() const;
|
||||||
|
|
||||||
void moveAnimated(QPoint targetPos, bool animated = true);
|
void moveAnimated(QPoint targetPos, bool animated = true);
|
||||||
|
|
||||||
|
@ -107,6 +121,23 @@ private:
|
||||||
|
|
||||||
int normalTabWidthForHeight(int height) const;
|
int normalTabWidthForHeight(int height) const;
|
||||||
|
|
||||||
|
bool shouldMessageHighlight(const ChannelView &channelViewSource,
|
||||||
|
const MessagePtr &message) const;
|
||||||
|
|
||||||
|
struct HighlightSources {
|
||||||
|
std::unordered_set<ChannelPtr> newMessageSource;
|
||||||
|
std::unordered_set<ChannelPtr> highlightedSource;
|
||||||
|
|
||||||
|
void clear()
|
||||||
|
{
|
||||||
|
this->newMessageSource.clear();
|
||||||
|
this->highlightedSource.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
} highlightSources_;
|
||||||
|
|
||||||
|
void removeHighlightSources(const HighlightSources &toRemove);
|
||||||
|
|
||||||
QPropertyAnimation positionChangedAnimation_;
|
QPropertyAnimation positionChangedAnimation_;
|
||||||
QPoint positionAnimationDesiredPoint_;
|
QPoint positionAnimationDesiredPoint_;
|
||||||
|
|
||||||
|
|
|
@ -214,10 +214,12 @@ void SplitContainer::addSplit(Split *split)
|
||||||
auto &&conns = this->connectionsPerSplit_[split];
|
auto &&conns = this->connectionsPerSplit_[split];
|
||||||
|
|
||||||
conns.managedConnect(split->getChannelView().tabHighlightRequested,
|
conns.managedConnect(split->getChannelView().tabHighlightRequested,
|
||||||
[this](HighlightState state) {
|
[this, &channelView = split->getChannelView()](
|
||||||
|
HighlightState state, const MessagePtr &message) {
|
||||||
if (this->tab_ != nullptr)
|
if (this->tab_ != nullptr)
|
||||||
{
|
{
|
||||||
this->tab_->setHighlightState(state);
|
this->tab_->updateHighlightState(
|
||||||
|
state, channelView, message);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue