Mercurial > hg > svgui
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 |