mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-06-11 16:44:48 -07:00
the long type has different sizes across operating systems and should not be used in the timeline an overflow could occur if the width in pixels multiplied by the total amount of milliseconds in the replay is larger than 2^31 which is easy enough considering with only 500 pixels width you'll reach this number with only 1.2 hours of replay (about 4 million millis), note that this would be windows exclusive as *nix uses 64 bits ~~qt-json's own repo suggests using qt5's implementation instead, testing revealed this is quite a bit faster, contrary to #3480~~ testing proved this to not be compatible with older qt versions servatrice uses the qthread usleep function which used to be protected but is now public cockatrice is not compatible with qt4 and hasn't been for a while
117 lines
3.3 KiB
C++
117 lines
3.3 KiB
C++
#include "replay_timeline_widget.h"
|
|
|
|
#include <QPainter>
|
|
#include <QPainterPath>
|
|
#include <QPalette>
|
|
#include <QTimer>
|
|
|
|
ReplayTimelineWidget::ReplayTimelineWidget(QWidget *parent)
|
|
: QWidget(parent), maxBinValue(1), maxTime(1), timeScaleFactor(1.0), currentTime(0), currentEvent(0)
|
|
{
|
|
replayTimer = new QTimer(this);
|
|
connect(replayTimer, SIGNAL(timeout()), this, SLOT(replayTimerTimeout()));
|
|
}
|
|
|
|
const int ReplayTimelineWidget::binLength = 5000;
|
|
|
|
void ReplayTimelineWidget::setTimeline(const QList<int> &_replayTimeline)
|
|
{
|
|
replayTimeline = _replayTimeline;
|
|
histogram.clear();
|
|
int binEndTime = binLength - 1;
|
|
int binValue = 0;
|
|
for (int i : replayTimeline) {
|
|
if (i > binEndTime) {
|
|
histogram.append(binValue);
|
|
if (binValue > maxBinValue)
|
|
maxBinValue = binValue;
|
|
while (i > binEndTime + binLength) {
|
|
histogram.append(0);
|
|
binEndTime += binLength;
|
|
}
|
|
binValue = 1;
|
|
binEndTime += binLength;
|
|
} else
|
|
++binValue;
|
|
}
|
|
histogram.append(binValue);
|
|
if (!replayTimeline.isEmpty())
|
|
maxTime = replayTimeline.last();
|
|
|
|
update();
|
|
}
|
|
|
|
void ReplayTimelineWidget::paintEvent(QPaintEvent * /* event */)
|
|
{
|
|
QPainter painter(this);
|
|
painter.drawRect(0, 0, width() - 1, height() - 1);
|
|
|
|
qreal binWidth = (qreal)width() / histogram.size();
|
|
QPainterPath path;
|
|
path.moveTo(0, height() - 1);
|
|
for (int i = 0; i < histogram.size(); ++i)
|
|
path.lineTo(qRound(i * binWidth), (height() - 1) * (1.0 - (qreal)histogram[i] / maxBinValue));
|
|
path.lineTo(width() - 1, height() - 1);
|
|
path.lineTo(0, height() - 1);
|
|
painter.fillPath(path, Qt::black);
|
|
|
|
const QColor barColor = QColor::fromHsv(120, 255, 255, 100);
|
|
quint64 w = (quint64)(width() - 1) * (quint64)currentTime / maxTime;
|
|
painter.fillRect(0, 0, static_cast<int>(w), height() - 1, barColor);
|
|
}
|
|
|
|
void ReplayTimelineWidget::mousePressEvent(QMouseEvent *event)
|
|
{
|
|
int newTime = static_cast<int>((qint64)maxTime * (qint64)event->x() / width());
|
|
newTime -= newTime % 200; // Time should always be a multiple of 200
|
|
if (newTime < currentTime) {
|
|
currentTime = 0;
|
|
currentEvent = 0;
|
|
emit rewound();
|
|
}
|
|
currentTime = newTime - 200; // 200 is added back in replayTimerTimeout
|
|
replayTimerTimeout();
|
|
update();
|
|
}
|
|
|
|
QSize ReplayTimelineWidget::sizeHint() const
|
|
{
|
|
return {-1, 50};
|
|
}
|
|
|
|
QSize ReplayTimelineWidget::minimumSizeHint() const
|
|
{
|
|
return {400, 50};
|
|
}
|
|
|
|
void ReplayTimelineWidget::replayTimerTimeout()
|
|
{
|
|
currentTime += 200;
|
|
while ((currentEvent < replayTimeline.size()) && (replayTimeline[currentEvent] < currentTime)) {
|
|
emit processNextEvent();
|
|
++currentEvent;
|
|
}
|
|
if (currentEvent == replayTimeline.size()) {
|
|
emit replayFinished();
|
|
replayTimer->stop();
|
|
}
|
|
|
|
if (!(currentTime % 1000))
|
|
update();
|
|
}
|
|
|
|
void ReplayTimelineWidget::setTimeScaleFactor(qreal _timeScaleFactor)
|
|
{
|
|
timeScaleFactor = _timeScaleFactor;
|
|
replayTimer->setInterval(static_cast<int>(200 / timeScaleFactor));
|
|
}
|
|
|
|
void ReplayTimelineWidget::startReplay()
|
|
{
|
|
replayTimer->start(static_cast<int>(200 / timeScaleFactor));
|
|
}
|
|
|
|
void ReplayTimelineWidget::stopReplay()
|
|
{
|
|
replayTimer->stop();
|
|
}
|