comparison widgets/Pane.cpp @ 0:2a4f26e85b4c

initial import
author Chris Cannam
date Tue, 10 Jan 2006 16:33:16 +0000
parents
children 37b110168acf
comparison
equal deleted inserted replaced
-1:000000000000 0:2a4f26e85b4c
1 /* -*- c-basic-offset: 4 -*- vi:set ts=8 sts=4 sw=4: */
2
3 /*
4 A waveform viewer and audio annotation editor.
5 Chris Cannam, Queen Mary University of London, 2005
6
7 This is experimental software. Not for distribution.
8 */
9
10 #include "widgets/Pane.h"
11 #include "base/Layer.h"
12 #include "base/Model.h"
13 #include "base/ZoomConstraint.h"
14 #include "base/RealTime.h"
15 #include "base/Profiler.h"
16
17 #include <QPaintEvent>
18 #include <QPainter>
19 #include <iostream>
20 #include <cmath>
21
22 using std::cerr;
23 using std::endl;
24
25 Pane::Pane(QWidget *w) :
26 View(w, true),
27 m_identifyFeatures(false),
28 m_clickedInRange(false),
29 m_shiftPressed(false),
30 m_centreLineVisible(true)
31 {
32 setObjectName("Pane");
33 setMouseTracking(true);
34 }
35
36 bool
37 Pane::shouldIlluminateLocalFeatures(const Layer *layer, QPoint &pos)
38 {
39 for (LayerList::iterator vi = m_layers.end(); vi != m_layers.begin(); ) {
40 --vi;
41 if (layer != *vi) return false;
42 pos = m_identifyPoint;
43 return m_identifyFeatures;
44 }
45
46 return false;
47 }
48
49 void
50 Pane::setCentreLineVisible(bool visible)
51 {
52 m_centreLineVisible = visible;
53 update();
54 }
55
56 void
57 Pane::paintEvent(QPaintEvent *e)
58 {
59 QPainter paint;
60
61 QRect r(rect());
62
63 if (e) {
64 r = e->rect();
65 }
66 /*
67 paint.begin(this);
68 paint.setClipRect(r);
69
70 if (hasLightBackground()) {
71 paint.setPen(Qt::white);
72 paint.setBrush(Qt::white);
73 } else {
74 paint.setPen(Qt::black);
75 paint.setBrush(Qt::black);
76 }
77 paint.drawRect(r);
78
79 paint.end();
80 */
81 View::paintEvent(e);
82
83 paint.begin(this);
84
85 if (e) {
86 paint.setClipRect(r);
87 }
88
89 for (LayerList::iterator vi = m_layers.end(); vi != m_layers.begin(); ) {
90 --vi;
91
92 int sw = (*vi)->getVerticalScaleWidth(paint);
93
94 if (sw > 0 && r.left() < sw) {
95
96 // Profiler profiler("Pane::paintEvent - painting vertical scale", true);
97
98 // std::cerr << "Pane::paintEvent: calling paint.save() in vertical scale block" << std::endl;
99 paint.save();
100
101 paint.setPen(Qt::black);
102 paint.setBrush(Qt::white);
103 paint.drawRect(0, 0, sw, height());
104
105 paint.setBrush(Qt::NoBrush);
106 (*vi)->paintVerticalScale(paint, QRect(0, 0, sw, height()));
107
108 paint.restore();
109 }
110
111 if (m_identifyFeatures) {
112 QRect descRect = (*vi)->getFeatureDescriptionRect(paint,
113 m_identifyPoint);
114 if (descRect.width() > 0 && descRect.height() > 0 &&
115 r.left() + r.width() >= width() - descRect.width() &&
116 r.top() < descRect.height()) {
117
118 // Profiler profiler("Pane::paintEvent - painting local feature description", true);
119
120 // std::cerr << "Pane::paintEvent: calling paint.save() in feature description block" << std::endl;
121 paint.save();
122
123 paint.setPen(Qt::black);
124 paint.setBrush(Qt::white);
125
126 QRect rect(width() - descRect.width() - 1, 0,
127 descRect.width(), descRect.height());
128
129 paint.drawRect(rect);
130
131 paint.setBrush(Qt::NoBrush);
132 (*vi)->paintLocalFeatureDescription(paint, rect, m_identifyPoint);
133
134 paint.restore();
135 }
136 }
137
138 break;
139 }
140
141 if (m_centreLineVisible) {
142
143 if (hasLightBackground()) {
144 paint.setPen(QColor(50, 50, 50));
145 } else {
146 paint.setPen(QColor(200, 200, 200));
147 }
148 paint.setBrush(Qt::NoBrush);
149 paint.drawLine(width() / 2, 0, width() / 2, height() - 1);
150
151 // QFont font(paint.font());
152 // font.setBold(true);
153 // paint.setFont(font);
154
155 int sampleRate = getModelsSampleRate();
156 int y = height() - paint.fontMetrics().height()
157 + paint.fontMetrics().ascent() - 6;
158
159 LayerList::iterator vi = m_layers.end();
160
161 if (vi != m_layers.begin()) {
162
163 switch ((*--vi)->getPreferredFrameCountPosition()) {
164
165 case Layer::PositionTop:
166 y = paint.fontMetrics().ascent() + 6;
167 break;
168
169 case Layer::PositionMiddle:
170 y = (height() - paint.fontMetrics().height()) / 2
171 + paint.fontMetrics().ascent();
172 break;
173
174 case Layer::PositionBottom:
175 // y already set correctly
176 break;
177 }
178 }
179
180 if (sampleRate) {
181
182 QString text(QString::fromStdString
183 (RealTime::frame2RealTime
184 (m_centreFrame, sampleRate).toText(true)));
185
186 int tw = paint.fontMetrics().width(text);
187 int x = width()/2 - 4 - tw;
188
189 if (hasLightBackground()) {
190 paint.setPen(palette().background().color());
191 for (int dx = -1; dx <= 1; ++dx) {
192 for (int dy = -1; dy <= 1; ++dy) {
193 if ((dx && dy) || !(dx || dy)) continue;
194 paint.drawText(x + dx, y + dy, text);
195 }
196 }
197 paint.setPen(QColor(50, 50, 50));
198 } else {
199 paint.setPen(QColor(200, 200, 200));
200 }
201
202 paint.drawText(x, y, text);
203 }
204
205 QString text = QString("%1").arg(m_centreFrame);
206
207 int tw = paint.fontMetrics().width(text);
208 int x = width()/2 + 4;
209
210 if (hasLightBackground()) {
211 paint.setPen(palette().background().color());
212 for (int dx = -1; dx <= 1; ++dx) {
213 for (int dy = -1; dy <= 1; ++dy) {
214 if ((dx && dy) || !(dx || dy)) continue;
215 paint.drawText(x + dx, y + dy, text);
216 }
217 }
218 paint.setPen(QColor(50, 50, 50));
219 } else {
220 paint.setPen(QColor(200, 200, 200));
221 }
222 paint.drawText(x, y, text);
223 }
224
225 if (m_clickedInRange && m_shiftPressed) {
226 paint.setPen(Qt::blue);
227 paint.drawRect(m_clickPos.x(), m_clickPos.y(),
228 m_mousePos.x() - m_clickPos.x(),
229 m_mousePos.y() - m_clickPos.y());
230 }
231
232 paint.end();
233 }
234
235 void
236 Pane::mousePressEvent(QMouseEvent *e)
237 {
238 m_clickPos = e->pos();
239 m_clickedInRange = true;
240 m_shiftPressed = (e->modifiers() & Qt::ShiftModifier);
241 m_dragCentreFrame = m_centreFrame;
242
243 emit paneInteractedWith();
244 }
245
246 void
247 Pane::mouseReleaseEvent(QMouseEvent *e)
248 {
249 if (m_clickedInRange) {
250 mouseMoveEvent(e);
251 }
252 if (m_shiftPressed) {
253
254 int x0 = std::min(m_clickPos.x(), m_mousePos.x());
255 int x1 = std::max(m_clickPos.x(), m_mousePos.x());
256 int w = x1 - x0;
257
258 long newStartFrame = getStartFrame() + m_zoomLevel * x0;
259
260 if (newStartFrame <= -long(width() * m_zoomLevel)) {
261 newStartFrame = -long(width() * m_zoomLevel) + 1;
262 }
263
264 if (newStartFrame >= long(getModelsEndFrame())) {
265 newStartFrame = getModelsEndFrame() - 1;
266 }
267
268 float ratio = float(w) / float(width());
269 // std::cerr << "ratio: " << ratio << std::endl;
270 size_t newZoomLevel = (size_t)nearbyint(m_zoomLevel * ratio);
271 if (newZoomLevel < 1) newZoomLevel = 1;
272
273 // std::cerr << "start: " << m_startFrame << ", level " << m_zoomLevel << std::endl;
274 setZoomLevel(getZoomConstraintBlockSize(newZoomLevel));
275 setStartFrame(newStartFrame);
276
277 //cerr << "mouseReleaseEvent: start frame now " << m_startFrame << endl;
278 // update();
279 }
280 m_clickedInRange = false;
281
282 emit paneInteractedWith();
283 }
284
285 void
286 Pane::mouseMoveEvent(QMouseEvent *e)
287 {
288 if (!m_clickedInRange) {
289
290 // std::cerr << "Pane: calling identifyLocalFeatures" << std::endl;
291
292 //!!! identifyLocalFeatures(true, e->x(), e->y());
293
294 bool previouslyIdentifying = m_identifyFeatures;
295 QPoint prevPoint = m_identifyPoint;
296
297 m_identifyFeatures = true;
298 m_identifyPoint = e->pos();
299
300 if (m_identifyFeatures != previouslyIdentifying ||
301 m_identifyPoint != prevPoint) {
302 update();
303 }
304
305 } else if (m_shiftPressed) {
306
307 m_mousePos = e->pos();
308 update();
309
310 } else {
311
312 long xoff = int(e->x()) - int(m_clickPos.x());
313 long frameOff = xoff * m_zoomLevel;
314
315 size_t newCentreFrame = m_dragCentreFrame;
316
317 if (frameOff < 0) {
318 newCentreFrame -= frameOff;
319 } else if (newCentreFrame >= size_t(frameOff)) {
320 newCentreFrame -= frameOff;
321 } else {
322 newCentreFrame = 0;
323 }
324
325 if (newCentreFrame >= getModelsEndFrame()) {
326 newCentreFrame = getModelsEndFrame();
327 if (newCentreFrame > 0) --newCentreFrame;
328 }
329
330 if (std::max(m_centreFrame, newCentreFrame) -
331 std::min(m_centreFrame, newCentreFrame) > size_t(m_zoomLevel)) {
332 setCentreFrame(newCentreFrame);
333 }
334 }
335 }
336
337 void
338 Pane::mouseDoubleClickEvent(QMouseEvent *e)
339 {
340 std::cerr << "mouseDoubleClickEvent" << std::endl;
341 }
342
343 void
344 Pane::leaveEvent(QEvent *)
345 {
346 bool previouslyIdentifying = m_identifyFeatures;
347 m_identifyFeatures = false;
348 if (previouslyIdentifying) update();
349 }
350
351 void
352 Pane::wheelEvent(QWheelEvent *e)
353 {
354 //std::cerr << "wheelEvent, delta " << e->delta() << std::endl;
355
356 int newZoomLevel = m_zoomLevel;
357
358 int count = e->delta();
359
360 if (count > 0) {
361 if (count >= 120) count /= 120;
362 else count = 1;
363 }
364
365 if (count < 0) {
366 if (count <= -120) count /= 120;
367 else count = -1;
368 }
369
370 while (count > 0) {
371 if (newZoomLevel <= 2) {
372 newZoomLevel = 1;
373 break;
374 }
375 newZoomLevel = getZoomConstraintBlockSize(newZoomLevel - 1,
376 ZoomConstraint::RoundDown);
377 --count;
378 }
379
380 while (count < 0) {
381 newZoomLevel = getZoomConstraintBlockSize(newZoomLevel + 1,
382 ZoomConstraint::RoundUp);
383 ++count;
384 }
385
386 if (newZoomLevel != m_zoomLevel) {
387 setZoomLevel(newZoomLevel);
388 }
389
390 emit paneInteractedWith();
391 }
392
393
394 #ifdef INCLUDE_MOCFILES
395 #include "Pane.moc.cpp"
396 #endif
397