#include "widgets/splits/SplitHeader.hpp" #include "Application.hpp" #include "controllers/accounts/AccountController.hpp" #include "controllers/commands/CommandController.hpp" #include "controllers/notifications/NotificationController.hpp" #include "providers/twitch/TwitchChannel.hpp" #include "providers/twitch/TwitchIrcServer.hpp" #include "singletons/Resources.hpp" #include "singletons/Settings.hpp" #include "singletons/Theme.hpp" #include "singletons/TooltipPreviewImage.hpp" #include "singletons/WindowManager.hpp" #include "util/Helpers.hpp" #include "util/LayoutCreator.hpp" #include "util/LayoutHelper.hpp" #include "util/StreamerMode.hpp" #include "widgets/Label.hpp" #include "widgets/TooltipWidget.hpp" #include "widgets/dialogs/SettingsDialog.hpp" #include "widgets/helper/CommonTexts.hpp" #include "widgets/helper/EffectLabel.hpp" #include "widgets/splits/Split.hpp" #include "widgets/splits/SplitContainer.hpp" #include #include #include #include #include #include #include #include #ifdef USEWEBENGINE # include "widgets/StreamView.hpp" #endif namespace chatterino { namespace { auto formatRoomMode(TwitchChannel &channel) -> QString { QString text; { auto modes = channel.accessRoomModes(); if (modes->r9k) text += "r9k, "; if (modes->slowMode) text += QString("slow(%1), ").arg(localizeNumbers(modes->slowMode)); if (modes->emoteOnly) text += "emote, "; if (modes->submode) text += "sub, "; if (modes->followerOnly != -1) { if (modes->followerOnly != 0) { text += QString("follow(%1m), ") .arg(localizeNumbers(modes->followerOnly)); } else { text += QString("follow, "); } } } if (text.length() > 2) { text = text.mid(0, text.size() - 2); } if (!text.isEmpty()) { static QRegularExpression commaReplacement("^(.+?, .+?,) (.+)$"); auto match = commaReplacement.match(text); if (match.hasMatch()) text = match.captured(1) + '\n' + match.captured(2); } if (text.isEmpty() && channel.hasModRights()) return "none"; return text; } auto formatTooltip(const TwitchChannel::StreamStatus &s, QString thumbnail) { auto title = [&s]() -> QString { if (s.title.isEmpty()) { return QStringLiteral(""); } return s.title.toHtmlEscaped() + "

"; }(); auto tooltip = [&thumbnail]() -> QString { if (getSettings()->thumbnailSizeStream.getValue() == 0) { return QStringLiteral(""); } if (thumbnail.isEmpty()) { return QStringLiteral("Couldn't fetch thumbnail
"); } return "
"; }(); auto game = [&s]() -> QString { if (s.game.isEmpty()) { return QStringLiteral(""); } return s.game.toHtmlEscaped() + "
"; }(); auto extraStreamData = [&s]() -> QString { if (isInStreamerMode() && getSettings()->streamerModeHideViewerCountAndDuration) { return QStringLiteral( "<Streamer " "Mode>"); } return QString("%1 for %2 with %3 viewers") .arg(s.rerun ? "Vod-casting" : "Live") .arg(s.uptime) .arg(localizeNumbers(s.viewerCount)); }(); return QString("

" + // title + // tooltip + // game + // extraStreamData + // "

" // ); } auto formatOfflineTooltip(const TwitchChannel::StreamStatus &s) { return QString("

Offline
%1

") .arg(s.title.toHtmlEscaped()); } auto formatTitle(const TwitchChannel::StreamStatus &s, Settings &settings) { auto title = QString(); // live if (s.rerun) title += " (rerun)"; else if (s.streamType.isEmpty()) title += " (" + s.streamType + ")"; else title += " (live)"; // description if (settings.headerUptime) title += " - " + s.uptime; if (settings.headerViewerCount) title += " - " + localizeNumbers(s.viewerCount); if (settings.headerGame && !s.game.isEmpty()) title += " - " + s.game; if (settings.headerStreamTitle && !s.title.isEmpty()) { title += " - " + s.title.simplified(); } return title; } auto distance(QPoint a, QPoint b) { auto x = std::abs(a.x() - b.x()); auto y = std::abs(a.y() - b.y()); return std::sqrt(x * x + y * y); } } // namespace SplitHeader::SplitHeader(Split *_split) : BaseWidget(_split) , split_(_split) { this->initializeLayout(); this->setMouseTracking(true); this->updateChannelText(); this->handleChannelChanged(); this->updateModerationModeIcon(); this->split_->focused.connect([this]() { this->themeChangedEvent(); }); this->split_->focusLost.connect([this]() { this->themeChangedEvent(); }); this->split_->channelChanged.connect([this]() { this->handleChannelChanged(); }); this->bSignals_.emplace_back( getApp()->accounts->twitch.currentUserChanged.connect([this] { this->updateModerationModeIcon(); })); auto _ = [this](const auto &, const auto &) { this->updateChannelText(); }; getSettings()->headerViewerCount.connect(_, this->managedConnections_); getSettings()->headerStreamTitle.connect(_, this->managedConnections_); getSettings()->headerGame.connect(_, this->managedConnections_); getSettings()->headerUptime.connect(_, this->managedConnections_); } void SplitHeader::initializeLayout() { auto layout = makeLayout({ // space makeWidget([](auto w) { w->setScaleIndependantSize(8, 4); }), // title this->titleLabel_ = makeWidget