Chris@0
|
1 /* -*- c-basic-offset: 4 -*- vi:set ts=8 sts=4 sw=4: */
|
Chris@0
|
2
|
Chris@0
|
3 /*
|
Chris@0
|
4 A waveform viewer and audio annotation editor.
|
Chris@5
|
5 Chris Cannam, Queen Mary University of London, 2005-2006
|
Chris@0
|
6
|
Chris@0
|
7 This is experimental software. Not for distribution.
|
Chris@0
|
8 */
|
Chris@0
|
9
|
Chris@0
|
10 #include "Panner.h"
|
Chris@0
|
11 #include "base/Layer.h"
|
Chris@0
|
12 #include "base/Model.h"
|
Chris@0
|
13 #include "base/ZoomConstraint.h"
|
Chris@0
|
14
|
Chris@0
|
15 #include <QPaintEvent>
|
Chris@0
|
16 #include <QPainter>
|
Chris@0
|
17 #include <iostream>
|
Chris@0
|
18
|
Chris@0
|
19 using std::cerr;
|
Chris@0
|
20 using std::endl;
|
Chris@0
|
21
|
Chris@0
|
22 Panner::Panner(QWidget *w) :
|
Chris@0
|
23 View(w, false),
|
Chris@0
|
24 m_clickedInRange(false)
|
Chris@0
|
25 {
|
Chris@0
|
26 setObjectName(tr("Panner"));
|
Chris@0
|
27 m_followPan = false;
|
Chris@0
|
28 m_followZoom = false;
|
Chris@0
|
29 }
|
Chris@0
|
30
|
Chris@0
|
31 void
|
Chris@0
|
32 Panner::modelChanged(size_t startFrame, size_t endFrame)
|
Chris@0
|
33 {
|
Chris@0
|
34 View::modelChanged(startFrame, endFrame);
|
Chris@0
|
35 }
|
Chris@0
|
36
|
Chris@0
|
37 void
|
Chris@0
|
38 Panner::modelReplaced()
|
Chris@0
|
39 {
|
Chris@0
|
40 View::modelReplaced();
|
Chris@0
|
41 }
|
Chris@0
|
42
|
Chris@0
|
43 void
|
Chris@0
|
44 Panner::registerView(View *widget)
|
Chris@0
|
45 {
|
Chris@27
|
46 m_widgets.insert(widget);
|
Chris@0
|
47 update();
|
Chris@0
|
48 }
|
Chris@0
|
49
|
Chris@0
|
50 void
|
Chris@0
|
51 Panner::unregisterView(View *widget)
|
Chris@0
|
52 {
|
Chris@0
|
53 m_widgets.erase(widget);
|
Chris@0
|
54 update();
|
Chris@0
|
55 }
|
Chris@0
|
56
|
Chris@0
|
57 void
|
Chris@0
|
58 Panner::viewManagerCentreFrameChanged(void *p, unsigned long f, bool)
|
Chris@0
|
59 {
|
Chris@0
|
60 // std::cerr << "Panner[" << this << "]::viewManagerCentreFrameChanged("
|
Chris@0
|
61 // << p << ", " << f << ")" << std::endl;
|
Chris@0
|
62
|
Chris@0
|
63 if (p == this) return;
|
Chris@0
|
64 if (m_widgets.find(p) != m_widgets.end()) {
|
Chris@0
|
65 update();
|
Chris@0
|
66 }
|
Chris@0
|
67 }
|
Chris@0
|
68
|
Chris@0
|
69 void
|
Chris@0
|
70 Panner::viewManagerZoomLevelChanged(void *p, unsigned long z, bool)
|
Chris@0
|
71 {
|
Chris@0
|
72 if (p == this) return;
|
Chris@0
|
73 if (m_widgets.find(p) != m_widgets.end()) {
|
Chris@0
|
74 update();
|
Chris@0
|
75 }
|
Chris@0
|
76 }
|
Chris@0
|
77
|
Chris@0
|
78 void
|
Chris@0
|
79 Panner::viewManagerPlaybackFrameChanged(unsigned long f)
|
Chris@0
|
80 {
|
Chris@0
|
81 bool changed = false;
|
Chris@0
|
82
|
Chris@27
|
83 if (getXForFrame(m_playPointerFrame) != getXForFrame(f)) changed = true;
|
Chris@0
|
84 m_playPointerFrame = f;
|
Chris@0
|
85
|
Chris@0
|
86 if (changed) update();
|
Chris@0
|
87 }
|
Chris@0
|
88
|
Chris@0
|
89 void
|
Chris@0
|
90 Panner::paintEvent(QPaintEvent *e)
|
Chris@0
|
91 {
|
Chris@0
|
92 // Recalculate zoom in case the size of the widget has changed.
|
Chris@0
|
93
|
Chris@0
|
94 size_t startFrame = getModelsStartFrame();
|
Chris@0
|
95 size_t frameCount = getModelsEndFrame() - getModelsStartFrame();
|
Chris@0
|
96 int zoomLevel = frameCount / width();
|
Chris@0
|
97 if (zoomLevel < 1) zoomLevel = 1;
|
Chris@0
|
98 zoomLevel = getZoomConstraintBlockSize(zoomLevel,
|
Chris@0
|
99 ZoomConstraint::RoundUp);
|
Chris@0
|
100 if (zoomLevel != m_zoomLevel) {
|
Chris@0
|
101 m_zoomLevel = zoomLevel;
|
Chris@0
|
102 emit zoomLevelChanged(this, m_zoomLevel, m_followZoom);
|
Chris@0
|
103 }
|
Chris@0
|
104 size_t centreFrame = startFrame + m_zoomLevel * (width() / 2);
|
Chris@0
|
105 if (centreFrame > (startFrame + getModelsEndFrame())/2) {
|
Chris@0
|
106 centreFrame = (startFrame + getModelsEndFrame())/2;
|
Chris@0
|
107 }
|
Chris@0
|
108 if (centreFrame != m_centreFrame) {
|
Chris@0
|
109 m_centreFrame = centreFrame;
|
Chris@0
|
110 emit centreFrameChanged(this, m_centreFrame, false);
|
Chris@0
|
111 }
|
Chris@0
|
112
|
Chris@0
|
113 View::paintEvent(e);
|
Chris@0
|
114
|
Chris@0
|
115 QPainter paint;
|
Chris@0
|
116 paint.begin(this);
|
Chris@0
|
117
|
Chris@0
|
118 QRect r(rect());
|
Chris@0
|
119
|
Chris@0
|
120 if (e) {
|
Chris@0
|
121 r = e->rect();
|
Chris@0
|
122 paint.setClipRect(r);
|
Chris@0
|
123 }
|
Chris@0
|
124
|
Chris@0
|
125 paint.setPen(Qt::black);
|
Chris@0
|
126
|
Chris@0
|
127 int y = 0;
|
Chris@0
|
128
|
Chris@27
|
129 int prevx0 = -10;
|
Chris@27
|
130 int prevx1 = -10;
|
Chris@0
|
131
|
Chris@27
|
132 for (WidgetSet::iterator i = m_widgets.begin(); i != m_widgets.end(); ++i) {
|
Chris@27
|
133 if (!*i) continue;
|
Chris@0
|
134
|
Chris@27
|
135 View *w = (View *)*i;
|
Chris@0
|
136
|
Chris@27
|
137 long f0 = w->getFrameForX(0);
|
Chris@27
|
138 long f1 = w->getFrameForX(w->width());
|
Chris@0
|
139
|
Chris@27
|
140 int x0 = getXForFrame(f0);
|
Chris@27
|
141 int x1 = getXForFrame(f1);
|
Chris@0
|
142
|
Chris@27
|
143 if (x0 != prevx0 || x1 != prevx1) {
|
Chris@0
|
144 y += height() / 10 + 1;
|
Chris@27
|
145 prevx0 = x0;
|
Chris@27
|
146 prevx1 = x1;
|
Chris@0
|
147 }
|
Chris@27
|
148
|
Chris@27
|
149 if (x1 <= x0) x1 = x0 + 1;
|
Chris@0
|
150
|
Chris@0
|
151 paint.drawRect(x0, y, x1 - x0, height() - 2 * y);
|
Chris@0
|
152 }
|
Chris@0
|
153
|
Chris@0
|
154 paint.end();
|
Chris@0
|
155 }
|
Chris@0
|
156
|
Chris@0
|
157 void
|
Chris@0
|
158 Panner::mousePressEvent(QMouseEvent *e)
|
Chris@0
|
159 {
|
Chris@0
|
160 m_clickPos = e->pos();
|
Chris@27
|
161 for (WidgetSet::iterator i = m_widgets.begin(); i != m_widgets.end(); ++i) {
|
Chris@27
|
162 if (*i) {
|
Chris@0
|
163 m_clickedInRange = true;
|
Chris@27
|
164 m_dragCentreFrame = ((View *)*i)->getCentreFrame();
|
Chris@27
|
165 break;
|
Chris@0
|
166 }
|
Chris@0
|
167 }
|
Chris@0
|
168 }
|
Chris@0
|
169
|
Chris@0
|
170 void
|
Chris@0
|
171 Panner::mouseReleaseEvent(QMouseEvent *e)
|
Chris@0
|
172 {
|
Chris@0
|
173 if (m_clickedInRange) {
|
Chris@0
|
174 mouseMoveEvent(e);
|
Chris@0
|
175 }
|
Chris@0
|
176 m_clickedInRange = false;
|
Chris@0
|
177 }
|
Chris@0
|
178
|
Chris@0
|
179 void
|
Chris@0
|
180 Panner::mouseMoveEvent(QMouseEvent *e)
|
Chris@0
|
181 {
|
Chris@0
|
182 if (!m_clickedInRange) return;
|
Chris@0
|
183
|
Chris@0
|
184 long xoff = int(e->x()) - int(m_clickPos.x());
|
Chris@0
|
185 long frameOff = xoff * m_zoomLevel;
|
Chris@0
|
186
|
Chris@0
|
187 size_t newCentreFrame = m_dragCentreFrame;
|
Chris@0
|
188 if (frameOff > 0) {
|
Chris@0
|
189 newCentreFrame += frameOff;
|
Chris@0
|
190 } else if (newCentreFrame >= size_t(-frameOff)) {
|
Chris@0
|
191 newCentreFrame += frameOff;
|
Chris@0
|
192 } else {
|
Chris@0
|
193 newCentreFrame = 0;
|
Chris@0
|
194 }
|
Chris@0
|
195
|
Chris@0
|
196 if (newCentreFrame >= getModelsEndFrame()) {
|
Chris@0
|
197 newCentreFrame = getModelsEndFrame();
|
Chris@0
|
198 if (newCentreFrame > 0) --newCentreFrame;
|
Chris@0
|
199 }
|
Chris@0
|
200
|
Chris@0
|
201 if (std::max(m_centreFrame, newCentreFrame) -
|
Chris@0
|
202 std::min(m_centreFrame, newCentreFrame) > size_t(m_zoomLevel)) {
|
Chris@0
|
203 emit centreFrameChanged(this, newCentreFrame, true);
|
Chris@0
|
204 }
|
Chris@0
|
205 }
|
Chris@0
|
206
|
Chris@0
|
207 #ifdef INCLUDE_MOCFILES
|
Chris@0
|
208 #include "Panner.moc.cpp"
|
Chris@0
|
209 #endif
|
Chris@0
|
210
|