-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathtimelinewidget.cpp
153 lines (125 loc) · 4.74 KB
/
timelinewidget.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
#include "timelinewidget.h"
#include <QPainter>
#include <QWheelEvent>
#include <QMouseEvent>
#include <QApplication>
#include <QDebug>
TimelineWidget::TimelineWidget(QWidget *parent) : QWidget(parent)
{
mCursor = 0;
mLength = 60;
mViewOffset = 0;
mViewLength = 60;
}
void TimelineWidget::wheelEvent(QWheelEvent* ev)
{
if (QApplication::keyboardModifiers() & Qt::ControlModifier) {
// zoom
mViewLength += (int)(ev->delta() * -0.04);
mViewLength = std::max<double>(mViewLength, 5);
} else {
// scroll
// this should really snap to intervalLength()
double scrollAmt = (int)(ev->delta() * -0.00035 * size().width() / pxPerSecond());
if (scrollAmt < 1 && scrollAmt > -1)
scrollAmt = signbit((float)ev->delta()) ? 1 : -1;
mViewOffset += scrollAmt;
}
emit viewportChanged(mViewOffset, mViewLength);
update();
ev->accept();
}
void TimelineWidget::mousePressEvent(QMouseEvent* ev)
{
double time = ev->x() / pxPerSecond() + mViewOffset;
emit timeClicked(time);
ev->accept();
}
void TimelineWidget::setCursor(double time)
{
mCursor = time;
emit cursorMoved(mCursor);
update();
}
void TimelineWidget::setLength(double length)
{
mLength = length;
update();
}
double TimelineWidget::intervalLength() const
{
if (mViewLength >= 60)
return 15.0;
else if (mViewLength >= 15)
return 5.0;
else
return 1.0;
}
double TimelineWidget::pxPerSecond() const
{
return size().width() / mViewLength;
}
void TimelineWidget::paintEvent(QPaintEvent*)
{
QPainter painter(this);
const int numSubTicks = (intervalLength() >= 15
? (int)(intervalLength() / 5.0)
: (int)(intervalLength()));
const double pxPerInterval = pxPerSecond() * intervalLength();
int curInterval; // in seconds
if (mViewOffset >= 0)
curInterval = (int)(floor(mViewOffset / intervalLength()) * intervalLength());
else
curInterval = (int)(ceil(mViewOffset / intervalLength()) * intervalLength());
double remainder = (-fmod(mViewOffset, intervalLength())) * pxPerSecond(); // in px
static const QPen outOfRangePen(QColor(255, 0, 0));
static const QPen inRangePen(QColor(0, 0, 0));
static const QBrush inRangeBrush(QColor(0, 0, 0));
static const QBrush outOfRangeBrush(QColor(255, 0, 0));
// start one interval early so we get subticks on the left
curInterval -= intervalLength();
remainder -= pxPerInterval;
// draw tick marks + text
for (double i = remainder; i <= size().width(); i += pxPerInterval) {
const int mins = abs(curInterval / 60);
const int secs = abs(curInterval % 60);
const QString text = QString("%1%2:%3")
.arg((curInterval < 0) ? "-" : "")
.arg(mins)
.arg(QString("%1").arg(secs), 2, QLatin1Char('0'));
painter.setPen((curInterval < 0 || curInterval >= mLength)
? outOfRangePen
: inRangePen);
static const float bigTickHeightPerc = 0.3f;
const float textLeft = i - (pxPerInterval / 2.0f);
const float textHeight = size().height() * (1 - bigTickHeightPerc);
// draw the text
painter.drawText(QRectF(textLeft, 0, pxPerInterval, textHeight),
text, QTextOption(Qt::AlignCenter));
// draw the tick
static const float bigTickWidth = 2;
painter.fillRect(QRectF(i - bigTickWidth / 2, // x
size().height() * (1 - bigTickHeightPerc), // y
bigTickWidth, // width
(size().height() * bigTickHeightPerc) - 1), // height
inRange(curInterval) ? inRangeBrush : outOfRangeBrush);
curInterval += intervalLength();
// draw sub-ticks
for (int j = 1; j < numSubTicks; j++) {
const double subTickTime = curInterval -
((double)j / numSubTicks) * intervalLength();
const float left = i + j * ((float)1 / numSubTicks * pxPerInterval);
static const float subTickHeightPerc = 0.2f;
painter.fillRect(QRectF(left, size().height() * (1 - subTickHeightPerc),
1, (size().height() * subTickHeightPerc) - 1),
inRange(subTickTime) ? inRangeBrush : outOfRangeBrush);
}
}
// draw cursor
painter.fillRect(QRectF(((mCursor - mViewOffset) * pxPerSecond()) - 1, 0,
2, size().height()), QBrush(QColor(0, 0, 20)));
}
bool TimelineWidget::inRange(double time)
{
return (time >= 0 && time < mLength);
}