feat: show live indicator in usercard (#6383)

This commit is contained in:
nerix
2025-08-17 12:05:52 +02:00
committed by GitHub
parent 0f11a9050a
commit bc85df04b1
11 changed files with 259 additions and 40 deletions
+76
View File
@@ -0,0 +1,76 @@
#include "widgets/helper/LiveIndicator.hpp"
#include "singletons/Theme.hpp"
#include "util/Helpers.hpp"
#include <QPainter>
#include <QString>
namespace chatterino {
using namespace Qt::Literals;
LiveIndicator::LiveIndicator(QWidget *parent)
: BaseWidget(parent)
{
this->setMinimumHeight(5); // fixed min height for the circle to fit
this->setMouseTracking(true); // for hover and tooltip
this->updateScale();
}
void LiveIndicator::setViewers(int viewers)
{
this->setToolTip(u"Live with %1 viewers"_s.arg(localizeNumbers(viewers)));
this->updateScale();
}
void LiveIndicator::scaleChangedEvent(float /*newScale*/)
{
this->updateScale();
}
void LiveIndicator::paintEvent(QPaintEvent * /*event*/)
{
QPainter painter(this);
QColor color = getTheme()->tabs.liveIndicator;
// Indicate that there's a tooltip here
if (this->hovered)
{
if (getTheme()->isLightTheme())
{
color = color.darker(150);
}
else
{
color = color.lighter(150);
}
}
painter.setBrush(color);
painter.setPen(Qt::NoPen);
painter.setRenderHint(QPainter::Antialiasing);
painter.drawEllipse(QRect{
QPoint{0, 0},
QSize{5, 5} * this->scale(),
});
}
void LiveIndicator::enterEvent(QEnterEvent * /*event*/)
{
this->hovered = true;
this->update();
}
void LiveIndicator::leaveEvent(QEvent * /*event*/)
{
this->hovered = false;
this->update();
}
void LiveIndicator::updateScale()
{
this->setFixedWidth(qRound(6 * this->scale()));
this->update();
}
} // namespace chatterino
+26
View File
@@ -0,0 +1,26 @@
#pragma once
#include "widgets/BaseWidget.hpp"
namespace chatterino {
class LiveIndicator : public BaseWidget
{
public:
LiveIndicator(QWidget *parent = nullptr);
void setViewers(int viewers);
protected:
void scaleChangedEvent(float newScale) override;
void paintEvent(QPaintEvent *event) override;
void enterEvent(QEnterEvent *event) override;
void leaveEvent(QEvent *event) override;
private:
void updateScale();
bool hovered = false;
};
} // namespace chatterino
+52
View File
@@ -0,0 +1,52 @@
#include "widgets/helper/ScalingSpacerItem.hpp"
#include "singletons/Settings.hpp"
namespace chatterino {
ScalingSpacerItem *ScalingSpacerItem::horizontal(int baseWidth)
{
return new ScalingSpacerItem({baseWidth, 0}, QSizePolicy::Fixed,
QSizePolicy::Minimum);
}
ScalingSpacerItem *ScalingSpacerItem::vertical(int baseHeight)
{
return new ScalingSpacerItem({0, baseHeight}, QSizePolicy::Minimum,
QSizePolicy::Fixed);
}
ScalingSpacerItem::ScalingSpacerItem(QSize baseSize, QSizePolicy::Policy horiz,
QSizePolicy::Policy vert)
: QSpacerItem(
qRound(static_cast<float>(baseSize.width()) * getSettings()->uiScale),
qRound(static_cast<float>(baseSize.height()) *
getSettings()->uiScale),
horiz, vert)
, baseSize(baseSize)
, scaledSize(baseSize * getSettings()->uiScale)
, horizontalPolicy(horiz)
, verticalPolicy(vert)
{
getSettings()->uiScale.connect(
[this] {
this->refresh();
},
this->connections, false);
}
void ScalingSpacerItem::refresh()
{
auto nextSize = this->baseSize * getSettings()->uiScale;
if (nextSize == this->scaledSize)
{
return;
}
this->scaledSize = nextSize;
this->changeSize(this->scaledSize.width(), this->scaledSize.height(),
this->horizontalPolicy, this->verticalPolicy);
this->invalidate();
}
} // namespace chatterino
+34
View File
@@ -0,0 +1,34 @@
#pragma once
#include <pajlada/signals/scoped-connection.hpp>
#include <QSpacerItem>
#include <memory>
#include <vector>
namespace chatterino {
/// A QSpacerItem that scales with Chatterino's scale
class ScalingSpacerItem : public QSpacerItem
{
public:
static ScalingSpacerItem *horizontal(int baseWidth);
static ScalingSpacerItem *vertical(int baseHeight);
private:
ScalingSpacerItem(QSize baseSize, QSizePolicy::Policy horiz,
QSizePolicy::Policy vert);
void refresh();
QSize baseSize;
QSize scaledSize;
QSizePolicy::Policy horizontalPolicy;
QSizePolicy::Policy verticalPolicy;
std::vector<std::unique_ptr<pajlada::Signals::ScopedConnection>>
connections;
};
} // namespace chatterino