Added a Live status indicator to tabs

This commit is contained in:
Rasmus Karlsson 2018-10-13 14:20:06 +02:00
parent 71a51d34c7
commit 49449379da
14 changed files with 104 additions and 51 deletions

View file

@ -221,6 +221,11 @@ bool Channel::hasModRights() const
return this->isMod() || this->isBroadcaster();
}
bool Channel::isLive() const
{
return false;
}
std::shared_ptr<Channel> Channel::getEmpty()
{
static std::shared_ptr<Channel> channel(new Channel("", Type::None));

View file

@ -69,6 +69,7 @@ public:
virtual bool isMod() const;
virtual bool isBroadcaster() const;
virtual bool hasModRights() const;
virtual bool isLive() const;
static std::shared_ptr<Channel> getEmpty();

View file

@ -17,7 +17,6 @@ enum class HighlightState {
None,
Highlighted,
NewMessage,
Notification,
};
inline QString qS(const std::string &string)

View file

@ -413,8 +413,6 @@ void TwitchChannel::setLive(bool newLiveStatus)
}
auto live = makeSystemMessage(this->getName() + " is live");
this->addMessage(live);
this->tabHighlightRequested.invoke(
HighlightState::Notification);
} else {
auto offline =
makeSystemMessage(this->getName() + " is offline");

View file

@ -66,7 +66,7 @@ public:
const QString &subscriptionUrl();
const QString &channelUrl();
const QString &popoutPlayerUrl();
bool isLive() const;
virtual bool isLive() const override;
QString roomId() const;
AccessGuard<const RoomModes> accessRoomModes() const;
AccessGuard<const StreamStatus> accessStreamStatus() const;

View file

@ -105,10 +105,6 @@ void Theme::actuallyUpdate(double hue, double multiplier)
QColor("#000"),
{QColor("#b4d7ff"), QColor("#b4d7ff"), QColor("#b4d7ff")},
{QColor("#00aeef"), QColor("#00aeef"), QColor("#00aeef")}};
this->tabs.notified = {
fg,
{QColor("#fff"), QColor("#fff"), QColor("#fff")},
{QColor("#F824A8"), QColor("#F824A8"), QColor("#F824A8")}};
} else {
this->tabs.regular = {
QColor("#aaa"),
@ -127,10 +123,6 @@ void Theme::actuallyUpdate(double hue, double multiplier)
QColor("#fff"),
{QColor("#555555"), QColor("#555555"), QColor("#555555")},
{QColor("#00aeef"), QColor("#00aeef"), QColor("#00aeef")}};
this->tabs.notified = {
fg,
{QColor("#252525"), QColor("#252525"), QColor("#252525")},
{QColor("#F824A8"), QColor("#F824A8"), QColor("#F824A8")}};
}
this->splits.input.focusedLine = highlighted;

View file

@ -50,7 +50,6 @@ public:
TabColors newMessage;
TabColors highlighted;
TabColors selected;
TabColors notified;
QColor border;
QColor bottomLine;
} tabs;

View file

@ -555,7 +555,10 @@ void ChannelView::setChannel(ChannelPtr newChannel)
TwitchChannel *tc = dynamic_cast<TwitchChannel *>(newChannel.get());
if (tc != nullptr) {
tc->tabHighlightRequested.connect([this](HighlightState state) {
this->tabHighlightRequested.invoke(HighlightState::Notification);
this->tabHighlightRequested.invoke(state);
});
tc->liveStatusChanged.connect([this]() {
this->liveStatusChanged.invoke(); //
});
}
}

View file

@ -61,6 +61,7 @@ public:
pajlada::Signals::Signal<QMouseEvent *> mouseDown;
pajlada::Signals::NoArgSignal selectionChanged;
pajlada::Signals::Signal<HighlightState> tabHighlightRequested;
pajlada::Signals::NoArgSignal liveStatusChanged;
pajlada::Signals::Signal<const Link &> linkClicked;
pajlada::Signals::Signal<QString> joinToChannel;

View file

@ -168,13 +168,20 @@ void NotebookTab::setSelected(bool value)
this->update();
}
void NotebookTab::setLive(bool isLive)
{
if (this->isLive_ != isLive) {
this->isLive_ = isLive;
this->update();
}
}
void NotebookTab::setHighlightState(HighlightState newHighlightStyle)
{
if (this->isSelected() || !this->highlightEnabled_) {
return;
}
if (this->highlightState_ != HighlightState::Highlighted &&
this->highlightState_ != HighlightState::Notification) {
if (this->highlightState_ != HighlightState::Highlighted) {
this->highlightState_ = newHighlightStyle;
this->update();
@ -252,8 +259,6 @@ void NotebookTab::paintEvent(QPaintEvent *)
colors = this->theme->tabs.selected;
} else if (this->highlightState_ == HighlightState::Highlighted) {
colors = this->theme->tabs.highlighted;
} else if (this->highlightState_ == HighlightState::Notification) {
colors = this->theme->tabs.notified;
} else if (this->highlightState_ == HighlightState::NewMessage) {
colors = this->theme->tabs.newMessage;
} else {
@ -297,6 +302,20 @@ void NotebookTab::paintEvent(QPaintEvent *)
? colors.line.hover
: (windowFocused ? colors.line.regular : colors.line.unfocused));
// draw live indicator
if (this->isLive_) {
painter.setPen(QColor(Qt::GlobalColor::red));
QBrush b;
b.setColor(QColor(Qt::GlobalColor::red));
b.setStyle(Qt::SolidPattern);
painter.setBrush(b);
auto x = this->width() - (6.f * scale);
auto y = 4.f * scale;
auto diameter = 4.f * scale;
painter.drawEllipse(QRectF(x, y, diameter, diameter));
}
// set the pen color
painter.setPen(colors.text);

View file

@ -39,6 +39,7 @@ public:
bool isSelected() const;
void setSelected(bool value);
void setLive(bool isLive);
void setHighlightState(HighlightState style);
void setHighlightsEnabled(const bool &newVal);
bool hasHighlightsEnabled() const;
@ -88,6 +89,8 @@ private:
bool highlightEnabled_ = true;
QAction *highlightNewMessagesAction_;
bool isLive_{};
QMenu menu_;
std::vector<pajlada::Signals::ScopedConnection> managedConnections_;

View file

@ -290,7 +290,7 @@ void Split::showChangeChannelPopup(const char *dialogTitle, bool empty,
if (dialog->hasSeletedChannel()) {
this->setChannel(dialog->getSelectedChannel());
if (this->isInContainer()) {
this->container_->refreshTabTitle();
this->container_->refreshTab();
}
}

View file

@ -84,7 +84,7 @@ void SplitContainer::setTab(NotebookTab *_tab)
this->tab_->page = this;
this->refreshTabTitle();
this->refreshTab();
}
void SplitContainer::hideResizeHandles()
@ -177,7 +177,7 @@ void SplitContainer::addSplit(Split *split)
this->unsetCursor();
this->splits_.push_back(split);
this->refreshTabTitle();
this->refreshTab();
split->getChannelView().tabHighlightRequested.connect(
[this](HighlightState state) {
@ -186,6 +186,10 @@ void SplitContainer::addSplit(Split *split)
}
});
split->getChannelView().liveStatusChanged.connect([this]() {
this->refreshTabLiveStatus(); //
});
split->focused.connect([this, split] { this->setSelected(split); });
this->layout();
@ -228,7 +232,7 @@ SplitContainer::Position SplitContainer::releaseSplit(Split *split)
this->splits_.front()->giveFocus(Qt::MouseFocusReason);
}
this->refreshTabTitle();
this->refreshTab();
// fourtf: really bad
split->getChannelView().tabHighlightRequested.disconnectAll();
@ -568,34 +572,10 @@ void SplitContainer::focusInEvent(QFocusEvent *)
}
}
void SplitContainer::refreshTabTitle()
void SplitContainer::refreshTab()
{
if (this->tab_ == nullptr) {
return;
}
QString newTitle = "";
bool first = true;
for (const auto &chatWidget : this->splits_) {
auto channelName = chatWidget->getChannel()->getName();
if (channelName.isEmpty()) {
continue;
}
if (!first) {
newTitle += ", ";
}
newTitle += channelName;
first = false;
}
if (newTitle.isEmpty()) {
newTitle = "empty";
}
this->tab_->setDefaultTitle(newTitle);
this->refreshTabTitle();
this->refreshTabLiveStatus();
}
int SplitContainer::getSplitCount()
@ -677,6 +657,54 @@ void SplitContainer::decodeNodeRecusively(QJsonObject &obj, Node *node)
}
}
void SplitContainer::refreshTabTitle()
{
if (this->tab_ == nullptr) {
return;
}
QString newTitle = "";
bool first = true;
for (const auto &chatWidget : this->splits_) {
auto channelName = chatWidget->getChannel()->getName();
if (channelName.isEmpty()) {
continue;
}
if (!first) {
newTitle += ", ";
}
newTitle += channelName;
first = false;
}
if (newTitle.isEmpty()) {
newTitle = "empty";
}
this->tab_->setDefaultTitle(newTitle);
}
void SplitContainer::refreshTabLiveStatus()
{
if (this->tab_ == nullptr) {
return;
}
bool liveStatus = false;
for (const auto &s : this->splits_) {
auto c = s->getChannel();
if (c->isLive()) {
liveStatus = true;
break;
}
}
this->tab_->setLive(liveStatus);
}
//
// Node
//

View file

@ -171,7 +171,7 @@ private:
public:
SplitContainer(Notebook *parent);
Split* appendNewSplit(bool openChannelNameDialog);
Split *appendNewSplit(bool openChannelNameDialog);
void appendSplit(Split *split);
void insertSplit(Split *split, const Position &position);
void insertSplit(Split *split, Direction direction, Split *relativeTo);
@ -186,7 +186,9 @@ public:
int getSplitCount();
const std::vector<Split *> getSplits() const;
void refreshTabTitle();
void refreshTab();
NotebookTab *getTab() const;
Node *getBaseNode();
@ -221,6 +223,9 @@ private:
void decodeNodeRecusively(QJsonObject &obj, Node *node);
Split *getTopRightSplit(Node &node);
void refreshTabTitle();
void refreshTabLiveStatus();
struct DropRegion {
QRect rect;
std::pair<int, int> position;