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@0
|
46 m_widgets[widget] = WidgetRec(0, -1);
|
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 m_widgets[p].first = f;
|
Chris@0
|
66 update();
|
Chris@0
|
67 }
|
Chris@0
|
68 }
|
Chris@0
|
69
|
Chris@0
|
70 void
|
Chris@0
|
71 Panner::viewManagerZoomLevelChanged(void *p, unsigned long z, bool)
|
Chris@0
|
72 {
|
Chris@0
|
73 if (p == this) return;
|
Chris@0
|
74 if (m_widgets.find(p) != m_widgets.end()) {
|
Chris@0
|
75 m_widgets[p].second = z;
|
Chris@0
|
76 update();
|
Chris@0
|
77 }
|
Chris@0
|
78 }
|
Chris@0
|
79
|
Chris@0
|
80 void
|
Chris@0
|
81 Panner::viewManagerPlaybackFrameChanged(unsigned long f)
|
Chris@0
|
82 {
|
Chris@0
|
83 bool changed = false;
|
Chris@0
|
84
|
Chris@0
|
85 if (m_playPointerFrame / m_zoomLevel != f / m_zoomLevel) changed = true;
|
Chris@0
|
86 m_playPointerFrame = f;
|
Chris@0
|
87
|
Chris@0
|
88 for (WidgetMap::iterator i = m_widgets.begin(); i != m_widgets.end(); ++i) {
|
Chris@0
|
89 unsigned long of = i->second.first;
|
Chris@0
|
90 i->second.first = f;
|
Chris@0
|
91 if (of / m_zoomLevel != f / m_zoomLevel) changed = true;
|
Chris@0
|
92 }
|
Chris@0
|
93
|
Chris@0
|
94 if (changed) update();
|
Chris@0
|
95 }
|
Chris@0
|
96
|
Chris@0
|
97 void
|
Chris@0
|
98 Panner::paintEvent(QPaintEvent *e)
|
Chris@0
|
99 {
|
Chris@0
|
100 /*!!!
|
Chris@0
|
101 // Force View to recalculate zoom in case the size of the
|
Chris@0
|
102 // widget has changed. (We need a better name/mechanism for this)
|
Chris@0
|
103 m_newModel = true;
|
Chris@0
|
104 */
|
Chris@0
|
105
|
Chris@0
|
106 // Recalculate zoom in case the size of the widget has changed.
|
Chris@0
|
107
|
Chris@0
|
108 size_t startFrame = getModelsStartFrame();
|
Chris@0
|
109 size_t frameCount = getModelsEndFrame() - getModelsStartFrame();
|
Chris@0
|
110 int zoomLevel = frameCount / width();
|
Chris@0
|
111 if (zoomLevel < 1) zoomLevel = 1;
|
Chris@0
|
112 zoomLevel = getZoomConstraintBlockSize(zoomLevel,
|
Chris@0
|
113 ZoomConstraint::RoundUp);
|
Chris@0
|
114 if (zoomLevel != m_zoomLevel) {
|
Chris@0
|
115 m_zoomLevel = zoomLevel;
|
Chris@0
|
116 emit zoomLevelChanged(this, m_zoomLevel, m_followZoom);
|
Chris@0
|
117 }
|
Chris@0
|
118 size_t centreFrame = startFrame + m_zoomLevel * (width() / 2);
|
Chris@0
|
119 if (centreFrame > (startFrame + getModelsEndFrame())/2) {
|
Chris@0
|
120 centreFrame = (startFrame + getModelsEndFrame())/2;
|
Chris@0
|
121 }
|
Chris@0
|
122 if (centreFrame != m_centreFrame) {
|
Chris@0
|
123 m_centreFrame = centreFrame;
|
Chris@0
|
124 emit centreFrameChanged(this, m_centreFrame, false);
|
Chris@0
|
125 }
|
Chris@0
|
126
|
Chris@0
|
127 View::paintEvent(e);
|
Chris@0
|
128
|
Chris@0
|
129 QPainter paint;
|
Chris@0
|
130 paint.begin(this);
|
Chris@0
|
131
|
Chris@0
|
132 QRect r(rect());
|
Chris@0
|
133
|
Chris@0
|
134 if (e) {
|
Chris@0
|
135 r = e->rect();
|
Chris@0
|
136 paint.setClipRect(r);
|
Chris@0
|
137 }
|
Chris@0
|
138
|
Chris@0
|
139 paint.setPen(Qt::black);
|
Chris@0
|
140
|
Chris@0
|
141 int y = 0;
|
Chris@0
|
142 long prevCentre = 0;
|
Chris@0
|
143 long prevZoom = -1;
|
Chris@0
|
144
|
Chris@0
|
145 for (WidgetMap::iterator i = m_widgets.begin(); i != m_widgets.end(); ++i) {
|
Chris@0
|
146 if (!i->first) continue;
|
Chris@0
|
147
|
Chris@0
|
148 View *w = (View *)i->first;
|
Chris@0
|
149 if (i->second.second < 0) i->second.second = w->getZoomLevel();
|
Chris@0
|
150 if (i->second.second < 0) continue;
|
Chris@0
|
151
|
Chris@0
|
152 long c = (long)i->second.first;
|
Chris@0
|
153 long z = (long)i->second.second;
|
Chris@0
|
154
|
Chris@0
|
155 long f0 = c - (w->width() / 2) * z;
|
Chris@0
|
156 long f1 = c + (w->width() / 2) * z;
|
Chris@0
|
157
|
Chris@0
|
158 int x0 = (f0 - long(getCentreFrame())) / getZoomLevel() + width()/2;
|
Chris@0
|
159 int x1 = (f1 - long(getCentreFrame())) / getZoomLevel() + width()/2 - 1;
|
Chris@0
|
160
|
Chris@0
|
161 if (c != prevCentre || z != prevZoom) {
|
Chris@0
|
162 y += height() / 10 + 1;
|
Chris@0
|
163 prevCentre = c;
|
Chris@0
|
164 prevZoom = z;
|
Chris@0
|
165 }
|
Chris@0
|
166
|
Chris@0
|
167 paint.drawRect(x0, y, x1 - x0, height() - 2 * y);
|
Chris@0
|
168 }
|
Chris@0
|
169
|
Chris@0
|
170 paint.end();
|
Chris@0
|
171 }
|
Chris@0
|
172
|
Chris@0
|
173 void
|
Chris@0
|
174 Panner::mousePressEvent(QMouseEvent *e)
|
Chris@0
|
175 {
|
Chris@0
|
176 m_clickPos = e->pos();
|
Chris@0
|
177 for (WidgetMap::iterator i = m_widgets.begin(); i != m_widgets.end(); ++i) {
|
Chris@0
|
178 if (i->first && i->second.second >= 0) {
|
Chris@0
|
179 m_clickedInRange = true;
|
Chris@0
|
180 m_dragCentreFrame = i->second.first;
|
Chris@0
|
181 }
|
Chris@0
|
182 }
|
Chris@0
|
183 }
|
Chris@0
|
184
|
Chris@0
|
185 void
|
Chris@0
|
186 Panner::mouseReleaseEvent(QMouseEvent *e)
|
Chris@0
|
187 {
|
Chris@0
|
188 if (m_clickedInRange) {
|
Chris@0
|
189 mouseMoveEvent(e);
|
Chris@0
|
190 }
|
Chris@0
|
191 m_clickedInRange = false;
|
Chris@0
|
192 }
|
Chris@0
|
193
|
Chris@0
|
194 void
|
Chris@0
|
195 Panner::mouseMoveEvent(QMouseEvent *e)
|
Chris@0
|
196 {
|
Chris@0
|
197 if (!m_clickedInRange) return;
|
Chris@0
|
198
|
Chris@0
|
199 /*!!!
|
Chris@0
|
200 long newFrame = getStartFrame() + e->x() * m_zoomLevel;
|
Chris@0
|
201
|
Chris@0
|
202 if (newFrame < 0) newFrame = 0;
|
Chris@0
|
203 if (newFrame >= getModelsEndFrame()) {
|
Chris@0
|
204 newFrame = getModelsEndFrame();
|
Chris@0
|
205 if (newFrame > 0) --newFrame;
|
Chris@0
|
206 }
|
Chris@0
|
207 emit centreFrameChanged(this, newFrame, true);
|
Chris@0
|
208 */
|
Chris@0
|
209
|
Chris@0
|
210 long xoff = int(e->x()) - int(m_clickPos.x());
|
Chris@0
|
211 long frameOff = xoff * m_zoomLevel;
|
Chris@0
|
212
|
Chris@0
|
213 size_t newCentreFrame = m_dragCentreFrame;
|
Chris@0
|
214 if (frameOff > 0) {
|
Chris@0
|
215 newCentreFrame += frameOff;
|
Chris@0
|
216 } else if (newCentreFrame >= size_t(-frameOff)) {
|
Chris@0
|
217 newCentreFrame += frameOff;
|
Chris@0
|
218 } else {
|
Chris@0
|
219 newCentreFrame = 0;
|
Chris@0
|
220 }
|
Chris@0
|
221
|
Chris@0
|
222 if (newCentreFrame >= getModelsEndFrame()) {
|
Chris@0
|
223 newCentreFrame = getModelsEndFrame();
|
Chris@0
|
224 if (newCentreFrame > 0) --newCentreFrame;
|
Chris@0
|
225 }
|
Chris@0
|
226
|
Chris@0
|
227 if (std::max(m_centreFrame, newCentreFrame) -
|
Chris@0
|
228 std::min(m_centreFrame, newCentreFrame) > size_t(m_zoomLevel)) {
|
Chris@0
|
229 emit centreFrameChanged(this, newCentreFrame, true);
|
Chris@0
|
230 }
|
Chris@0
|
231 }
|
Chris@0
|
232
|
Chris@0
|
233 #ifdef INCLUDE_MOCFILES
|
Chris@0
|
234 #include "Panner.moc.cpp"
|
Chris@0
|
235 #endif
|
Chris@0
|
236
|