Chris@132
|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
Chris@132
|
2
|
Chris@132
|
3 /*
|
Chris@132
|
4 Sonic Visualiser
|
Chris@132
|
5 An audio file viewer and annotation editor.
|
Chris@132
|
6 Centre for Digital Music, Queen Mary, University of London.
|
Chris@182
|
7 This file copyright 2006 QMUL.
|
Chris@132
|
8
|
Chris@132
|
9 This program is free software; you can redistribute it and/or
|
Chris@132
|
10 modify it under the terms of the GNU General Public License as
|
Chris@132
|
11 published by the Free Software Foundation; either version 2 of the
|
Chris@132
|
12 License, or (at your option) any later version. See the file
|
Chris@132
|
13 COPYING included with this distribution for more information.
|
Chris@132
|
14 */
|
Chris@132
|
15
|
Chris@132
|
16 #include "Thumbwheel.h"
|
Chris@132
|
17
|
Chris@187
|
18 #include "base/RangeMapper.h"
|
Chris@190
|
19 #include "base/Profiler.h"
|
Chris@187
|
20
|
Chris@132
|
21 #include <QMouseEvent>
|
Chris@132
|
22 #include <QPaintEvent>
|
Chris@132
|
23 #include <QWheelEvent>
|
Chris@187
|
24 #include <QInputDialog>
|
Chris@132
|
25 #include <QPainter>
|
Chris@190
|
26 #include <QPainterPath>
|
Chris@1586
|
27 #include <QMenu>
|
Chris@1586
|
28
|
Chris@1586
|
29 #include "MenuTitle.h"
|
Chris@132
|
30
|
Chris@132
|
31 #include <cmath>
|
Chris@132
|
32 #include <iostream>
|
Chris@132
|
33
|
Chris@133
|
34 Thumbwheel::Thumbwheel(Qt::Orientation orientation,
|
Chris@1266
|
35 QWidget *parent) :
|
Chris@132
|
36 QWidget(parent),
|
Chris@133
|
37 m_min(0),
|
Chris@133
|
38 m_max(100),
|
Chris@133
|
39 m_default(50),
|
Chris@133
|
40 m_value(50),
|
Chris@187
|
41 m_mappedValue(50),
|
Chris@187
|
42 m_noMappedUpdate(false),
|
Chris@165
|
43 m_rotation(0.5),
|
Chris@132
|
44 m_orientation(orientation),
|
Chris@165
|
45 m_speed(1.0),
|
Chris@132
|
46 m_tracking(true),
|
Chris@132
|
47 m_showScale(true),
|
Chris@132
|
48 m_clicked(false),
|
Chris@133
|
49 m_atDefault(true),
|
Chris@187
|
50 m_clickRotation(m_rotation),
|
Chris@187
|
51 m_showTooltip(true),
|
Chris@1586
|
52 m_provideContextMenu(true),
|
Chris@1586
|
53 m_lastContextMenu(nullptr),
|
Chris@1408
|
54 m_rangeMapper(nullptr)
|
Chris@132
|
55 {
|
Chris@1586
|
56 setContextMenuPolicy(Qt::CustomContextMenu);
|
Chris@1586
|
57 connect(this, SIGNAL(customContextMenuRequested(const QPoint &)),
|
Chris@1586
|
58 this, SLOT(contextMenuRequested(const QPoint &)));
|
Chris@132
|
59 }
|
Chris@132
|
60
|
Chris@132
|
61 Thumbwheel::~Thumbwheel()
|
Chris@132
|
62 {
|
Chris@187
|
63 delete m_rangeMapper;
|
Chris@1586
|
64 delete m_lastContextMenu;
|
Chris@1586
|
65 }
|
Chris@1586
|
66
|
Chris@1586
|
67 void
|
Chris@1586
|
68 Thumbwheel::contextMenuRequested(const QPoint &pos)
|
Chris@1586
|
69 {
|
Chris@1586
|
70 if (!m_provideContextMenu) {
|
Chris@1586
|
71 return;
|
Chris@1586
|
72 }
|
Chris@1586
|
73
|
Chris@1589
|
74 delete m_lastContextMenu;
|
Chris@1589
|
75 m_lastContextMenu = new QMenu;
|
Chris@1589
|
76 auto m = m_lastContextMenu;
|
Chris@1586
|
77
|
Chris@1586
|
78 if (m_title == "") {
|
Chris@1586
|
79 MenuTitle::addTitle(m, tr("Thumbwheel"));
|
Chris@1586
|
80 } else {
|
Chris@1586
|
81 MenuTitle::addTitle(m, m_title);
|
Chris@1586
|
82 }
|
Chris@1586
|
83
|
Chris@1602
|
84 m->addAction(tr("&Edit..."), this, SLOT(edit()));
|
Chris@1602
|
85 m->addAction(tr("&Reset to Default"), this, SLOT(resetToDefault()));
|
Chris@1586
|
86
|
Chris@1586
|
87 m->popup(mapToGlobal(pos));
|
Chris@187
|
88 }
|
Chris@187
|
89
|
Chris@187
|
90 void
|
Chris@187
|
91 Thumbwheel::setRangeMapper(RangeMapper *mapper)
|
Chris@187
|
92 {
|
Chris@187
|
93 if (m_rangeMapper == mapper) return;
|
Chris@187
|
94
|
Chris@187
|
95 if (!m_rangeMapper && mapper) {
|
Chris@187
|
96 connect(this, SIGNAL(valueChanged(int)),
|
Chris@187
|
97 this, SLOT(updateMappedValue(int)));
|
Chris@187
|
98 }
|
Chris@187
|
99
|
Chris@187
|
100 delete m_rangeMapper;
|
Chris@187
|
101 m_rangeMapper = mapper;
|
Chris@187
|
102
|
Chris@187
|
103 updateMappedValue(getValue());
|
Chris@187
|
104 }
|
Chris@187
|
105
|
Chris@187
|
106 void
|
Chris@187
|
107 Thumbwheel::setShowToolTip(bool show)
|
Chris@187
|
108 {
|
Chris@187
|
109 m_showTooltip = show;
|
Chris@187
|
110 m_noMappedUpdate = true;
|
Chris@187
|
111 updateMappedValue(getValue());
|
Chris@187
|
112 m_noMappedUpdate = false;
|
Chris@132
|
113 }
|
Chris@132
|
114
|
Chris@132
|
115 void
|
Chris@1589
|
116 Thumbwheel::setProvideContextMenu(bool provide)
|
Chris@1589
|
117 {
|
Chris@1589
|
118 m_provideContextMenu = provide;
|
Chris@1589
|
119 }
|
Chris@1589
|
120
|
Chris@1589
|
121 void
|
Chris@133
|
122 Thumbwheel::setMinimumValue(int min)
|
Chris@133
|
123 {
|
Chris@133
|
124 if (m_min == min) return;
|
Chris@133
|
125
|
Chris@133
|
126 m_min = min;
|
Chris@133
|
127 if (m_max <= m_min) m_max = m_min + 1;
|
Chris@133
|
128 if (m_value < m_min) m_value = m_min;
|
Chris@133
|
129 if (m_value > m_max) m_value = m_max;
|
Chris@165
|
130
|
Chris@165
|
131 m_rotation = float(m_value - m_min) / float(m_max - m_min);
|
Chris@165
|
132 update();
|
Chris@133
|
133 }
|
Chris@133
|
134
|
Chris@133
|
135 int
|
Chris@133
|
136 Thumbwheel::getMinimumValue() const
|
Chris@133
|
137 {
|
Chris@133
|
138 return m_min;
|
Chris@133
|
139 }
|
Chris@133
|
140
|
Chris@133
|
141 void
|
Chris@133
|
142 Thumbwheel::setMaximumValue(int max)
|
Chris@133
|
143 {
|
Chris@133
|
144 if (m_max == max) return;
|
Chris@133
|
145
|
Chris@133
|
146 m_max = max;
|
Chris@133
|
147 if (m_min >= m_max) m_min = m_max - 1;
|
Chris@133
|
148 if (m_value < m_min) m_value = m_min;
|
Chris@133
|
149 if (m_value > m_max) m_value = m_max;
|
Chris@165
|
150
|
Chris@165
|
151 m_rotation = float(m_value - m_min) / float(m_max - m_min);
|
Chris@165
|
152 update();
|
Chris@133
|
153 }
|
Chris@133
|
154
|
Chris@133
|
155 int
|
Chris@133
|
156 Thumbwheel::getMaximumValue() const
|
Chris@133
|
157 {
|
Chris@133
|
158 return m_max;
|
Chris@133
|
159 }
|
Chris@133
|
160
|
Chris@133
|
161 void
|
Chris@133
|
162 Thumbwheel::setDefaultValue(int deft)
|
Chris@133
|
163 {
|
Chris@133
|
164 if (m_default == deft) return;
|
Chris@133
|
165
|
Chris@133
|
166 m_default = deft;
|
Chris@133
|
167 if (m_atDefault) {
|
Chris@133
|
168 setValue(m_default);
|
Chris@165
|
169 m_atDefault = true; // setValue unsets this
|
Chris@382
|
170 m_cache = QImage();
|
Chris@133
|
171 emit valueChanged(getValue());
|
Chris@133
|
172 }
|
Chris@133
|
173 }
|
Chris@133
|
174
|
Chris@187
|
175 void
|
Chris@908
|
176 Thumbwheel::setMappedValue(double mappedValue)
|
Chris@187
|
177 {
|
Chris@187
|
178 if (m_rangeMapper) {
|
Chris@187
|
179 int newValue = m_rangeMapper->getPositionForValue(mappedValue);
|
Chris@190
|
180 bool changed = (m_mappedValue != mappedValue);
|
Chris@187
|
181 m_mappedValue = mappedValue;
|
Chris@187
|
182 m_noMappedUpdate = true;
|
Chris@587
|
183 // SVDEBUG << "Thumbwheel::setMappedValue(" << mappedValue << "): new value is " << newValue << " (visible " << isVisible() << ")" << endl;
|
Chris@187
|
184 if (newValue != getValue()) {
|
Chris@187
|
185 setValue(newValue);
|
Chris@190
|
186 changed = true;
|
Chris@382
|
187 m_cache = QImage();
|
Chris@187
|
188 }
|
Chris@190
|
189 if (changed) emit valueChanged(newValue);
|
Chris@187
|
190 m_noMappedUpdate = false;
|
Chris@187
|
191 } else {
|
Chris@190
|
192 int v = int(mappedValue);
|
Chris@190
|
193 if (v != getValue()) {
|
Chris@190
|
194 setValue(v);
|
Chris@382
|
195 m_cache = QImage();
|
Chris@190
|
196 emit valueChanged(v);
|
Chris@190
|
197 }
|
Chris@187
|
198 }
|
Chris@187
|
199 }
|
Chris@187
|
200
|
Chris@133
|
201 int
|
Chris@133
|
202 Thumbwheel::getDefaultValue() const
|
Chris@133
|
203 {
|
Chris@133
|
204 return m_default;
|
Chris@133
|
205 }
|
Chris@133
|
206
|
Chris@133
|
207 void
|
Chris@132
|
208 Thumbwheel::setValue(int value)
|
Chris@132
|
209 {
|
Chris@587
|
210 // SVDEBUG << "Thumbwheel::setValue(" << value << ") (from " << m_value
|
Chris@585
|
211 // << ", rotation " << m_rotation << ")" << " (visible " << isVisible() << ")" << endl;
|
Chris@133
|
212
|
Chris@165
|
213 if (m_value != value) {
|
Chris@165
|
214
|
Chris@165
|
215 m_atDefault = false;
|
Chris@165
|
216
|
Chris@165
|
217 if (value < m_min) value = m_min;
|
Chris@165
|
218 if (value > m_max) value = m_max;
|
Chris@165
|
219 m_value = value;
|
Chris@165
|
220 }
|
Chris@165
|
221
|
Chris@165
|
222 m_rotation = float(m_value - m_min) / float(m_max - m_min);
|
Chris@382
|
223 m_cache = QImage();
|
Chris@1586
|
224
|
Chris@1586
|
225 if (isVisible()) {
|
Chris@1586
|
226 update();
|
Chris@1586
|
227 updateTitle();
|
Chris@1586
|
228 }
|
Chris@132
|
229 }
|
Chris@132
|
230
|
Chris@133
|
231 void
|
Chris@133
|
232 Thumbwheel::resetToDefault()
|
Chris@133
|
233 {
|
Chris@133
|
234 if (m_default == m_value) return;
|
Chris@133
|
235 setValue(m_default);
|
Chris@133
|
236 m_atDefault = true;
|
Chris@382
|
237 m_cache = QImage();
|
Chris@133
|
238 emit valueChanged(getValue());
|
Chris@133
|
239 }
|
Chris@133
|
240
|
Chris@132
|
241 int
|
Chris@132
|
242 Thumbwheel::getValue() const
|
Chris@132
|
243 {
|
Chris@132
|
244 return m_value;
|
Chris@132
|
245 }
|
Chris@132
|
246
|
Chris@908
|
247 double
|
Chris@187
|
248 Thumbwheel::getMappedValue() const
|
Chris@187
|
249 {
|
Chris@187
|
250 if (m_rangeMapper) {
|
Chris@587
|
251 // SVDEBUG << "Thumbwheel::getMappedValue(): value = " << getValue() << ", mappedValue = " << m_mappedValue << endl;
|
Chris@187
|
252 return m_mappedValue;
|
Chris@187
|
253 }
|
Chris@187
|
254 return getValue();
|
Chris@187
|
255 }
|
Chris@187
|
256
|
Chris@187
|
257 void
|
Chris@187
|
258 Thumbwheel::updateMappedValue(int value)
|
Chris@187
|
259 {
|
Chris@187
|
260 if (!m_noMappedUpdate) {
|
Chris@187
|
261 if (m_rangeMapper) {
|
Chris@187
|
262 m_mappedValue = m_rangeMapper->getValueForPosition(value);
|
Chris@187
|
263 } else {
|
Chris@187
|
264 m_mappedValue = value;
|
Chris@187
|
265 }
|
Chris@187
|
266 }
|
Chris@187
|
267
|
Chris@1586
|
268 updateTitle();
|
Chris@1586
|
269 }
|
Chris@1586
|
270
|
Chris@1586
|
271 void
|
Chris@1586
|
272 Thumbwheel::updateTitle()
|
Chris@1586
|
273 {
|
Chris@1586
|
274 QString name = objectName();
|
Chris@1586
|
275 QString unit = "";
|
Chris@1586
|
276 QString text;
|
Chris@1586
|
277 double mappedValue = getMappedValue();
|
Chris@1586
|
278
|
Chris@1586
|
279 if (m_rangeMapper) unit = m_rangeMapper->getUnit();
|
Chris@1586
|
280 if (name != "") {
|
Chris@1586
|
281 text = tr("%1: %2%3").arg(name).arg(mappedValue).arg(unit);
|
Chris@1586
|
282 } else {
|
Chris@1586
|
283 text = tr("%2%3").arg(mappedValue).arg(unit);
|
Chris@1586
|
284 }
|
Chris@1586
|
285
|
Chris@1586
|
286 m_title = text;
|
Chris@1586
|
287
|
Chris@187
|
288 if (m_showTooltip) {
|
Chris@187
|
289 setToolTip(text);
|
Chris@1586
|
290 } else {
|
Chris@1586
|
291 setToolTip("");
|
Chris@187
|
292 }
|
Chris@187
|
293 }
|
Chris@187
|
294
|
Chris@132
|
295 void
|
Chris@256
|
296 Thumbwheel::scroll(bool up)
|
Chris@256
|
297 {
|
Chris@908
|
298 int step = int(lrintf(m_speed));
|
Chris@256
|
299 if (step == 0) step = 1;
|
Chris@256
|
300
|
Chris@256
|
301 if (up) {
|
Chris@1266
|
302 setValue(m_value + step);
|
Chris@256
|
303 } else {
|
Chris@1266
|
304 setValue(m_value - step);
|
Chris@256
|
305 }
|
Chris@256
|
306
|
Chris@256
|
307 emit valueChanged(getValue());
|
Chris@256
|
308 }
|
Chris@256
|
309
|
Chris@256
|
310 void
|
Chris@132
|
311 Thumbwheel::setSpeed(float speed)
|
Chris@132
|
312 {
|
Chris@132
|
313 m_speed = speed;
|
Chris@132
|
314 }
|
Chris@132
|
315
|
Chris@132
|
316 float
|
Chris@132
|
317 Thumbwheel::getSpeed() const
|
Chris@132
|
318 {
|
Chris@132
|
319 return m_speed;
|
Chris@132
|
320 }
|
Chris@132
|
321
|
Chris@132
|
322 void
|
Chris@132
|
323 Thumbwheel::setTracking(bool tracking)
|
Chris@132
|
324 {
|
Chris@132
|
325 m_tracking = tracking;
|
Chris@132
|
326 }
|
Chris@132
|
327
|
Chris@132
|
328 bool
|
Chris@132
|
329 Thumbwheel::getTracking() const
|
Chris@132
|
330 {
|
Chris@132
|
331 return m_tracking;
|
Chris@132
|
332 }
|
Chris@132
|
333
|
Chris@132
|
334 void
|
Chris@132
|
335 Thumbwheel::setShowScale(bool showScale)
|
Chris@132
|
336 {
|
Chris@132
|
337 m_showScale = showScale;
|
Chris@132
|
338 }
|
Chris@132
|
339
|
Chris@132
|
340 bool
|
Chris@132
|
341 Thumbwheel::getShowScale() const
|
Chris@132
|
342 {
|
Chris@132
|
343 return m_showScale;
|
Chris@132
|
344 }
|
Chris@132
|
345
|
Chris@132
|
346 void
|
Chris@189
|
347 Thumbwheel::enterEvent(QEvent *)
|
Chris@189
|
348 {
|
Chris@189
|
349 emit mouseEntered();
|
Chris@189
|
350 }
|
Chris@189
|
351
|
Chris@189
|
352 void
|
Chris@189
|
353 Thumbwheel::leaveEvent(QEvent *)
|
Chris@189
|
354 {
|
Chris@189
|
355 emit mouseLeft();
|
Chris@189
|
356 }
|
Chris@189
|
357
|
Chris@189
|
358 void
|
Chris@132
|
359 Thumbwheel::mousePressEvent(QMouseEvent *e)
|
Chris@132
|
360 {
|
Chris@187
|
361 if (e->button() == Qt::MidButton ||
|
Chris@187
|
362 ((e->button() == Qt::LeftButton) &&
|
Chris@187
|
363 (e->modifiers() & Qt::ControlModifier))) {
|
Chris@187
|
364 resetToDefault();
|
Chris@187
|
365 } else if (e->button() == Qt::LeftButton) {
|
Chris@133
|
366 m_clicked = true;
|
Chris@133
|
367 m_clickPos = e->pos();
|
Chris@165
|
368 m_clickRotation = m_rotation;
|
Chris@133
|
369 }
|
Chris@132
|
370 }
|
Chris@132
|
371
|
Chris@132
|
372 void
|
Chris@187
|
373 Thumbwheel::mouseDoubleClickEvent(QMouseEvent *mouseEvent)
|
Chris@132
|
374 {
|
Chris@188
|
375 //!!! needs a common base class with AudioDial (and Panner?)
|
Chris@187
|
376
|
Chris@187
|
377 if (mouseEvent->button() != Qt::LeftButton) {
|
Chris@187
|
378 return;
|
Chris@187
|
379 }
|
Chris@187
|
380
|
Chris@1586
|
381 edit();
|
Chris@1586
|
382 }
|
Chris@1586
|
383
|
Chris@1586
|
384 void
|
Chris@1586
|
385 Thumbwheel::edit()
|
Chris@1586
|
386 {
|
Chris@187
|
387 bool ok = false;
|
Chris@187
|
388
|
Chris@187
|
389 if (m_rangeMapper) {
|
Chris@187
|
390
|
Chris@908
|
391 double min = m_rangeMapper->getValueForPosition(m_min);
|
Chris@908
|
392 double max = m_rangeMapper->getValueForPosition(m_max);
|
Chris@187
|
393
|
Chris@187
|
394 if (min > max) {
|
Chris@908
|
395 double tmp = min;
|
Chris@187
|
396 min = max;
|
Chris@187
|
397 max = tmp;
|
Chris@187
|
398 }
|
Chris@187
|
399
|
Chris@187
|
400 QString unit = m_rangeMapper->getUnit();
|
Chris@187
|
401
|
Chris@187
|
402 QString text;
|
Chris@187
|
403 if (objectName() != "") {
|
Chris@187
|
404 if (unit != "") {
|
Chris@187
|
405 text = tr("New value for %1, from %2 to %3 %4:")
|
Chris@187
|
406 .arg(objectName()).arg(min).arg(max).arg(unit);
|
Chris@187
|
407 } else {
|
Chris@187
|
408 text = tr("New value for %1, from %2 to %3:")
|
Chris@187
|
409 .arg(objectName()).arg(min).arg(max);
|
Chris@187
|
410 }
|
Chris@187
|
411 } else {
|
Chris@187
|
412 if (unit != "") {
|
Chris@187
|
413 text = tr("Enter a new value from %1 to %2 %3:")
|
Chris@187
|
414 .arg(min).arg(max).arg(unit);
|
Chris@187
|
415 } else {
|
Chris@187
|
416 text = tr("Enter a new value from %1 to %2:")
|
Chris@187
|
417 .arg(min).arg(max);
|
Chris@187
|
418 }
|
Chris@187
|
419 }
|
Chris@187
|
420
|
Chris@908
|
421 double newValue = QInputDialog::getDouble
|
Chris@187
|
422 (this,
|
Chris@187
|
423 tr("Enter new value"),
|
Chris@187
|
424 text,
|
Chris@187
|
425 m_mappedValue,
|
Chris@187
|
426 min,
|
Chris@187
|
427 max,
|
Chris@187
|
428 4,
|
Chris@187
|
429 &ok);
|
Chris@187
|
430
|
Chris@187
|
431 if (ok) {
|
Chris@187
|
432 setMappedValue(newValue);
|
Chris@187
|
433 }
|
Chris@187
|
434
|
Chris@187
|
435 } else {
|
Chris@187
|
436
|
Chris@616
|
437 int newValue = QInputDialog::getInt
|
Chris@187
|
438 (this,
|
Chris@187
|
439 tr("Enter new value"),
|
Chris@187
|
440 tr("Enter a new value from %1 to %2:")
|
Chris@187
|
441 .arg(m_min).arg(m_max),
|
Chris@187
|
442 getValue(), m_min, m_max, 1, &ok);
|
Chris@187
|
443
|
Chris@187
|
444 if (ok) {
|
Chris@187
|
445 setValue(newValue);
|
Chris@187
|
446 }
|
Chris@187
|
447 }
|
Chris@132
|
448 }
|
Chris@132
|
449
|
Chris@187
|
450
|
Chris@132
|
451 void
|
Chris@132
|
452 Thumbwheel::mouseMoveEvent(QMouseEvent *e)
|
Chris@132
|
453 {
|
Chris@133
|
454 if (!m_clicked) return;
|
Chris@132
|
455 int dist = 0;
|
Chris@132
|
456 if (m_orientation == Qt::Horizontal) {
|
Chris@132
|
457 dist = e->x() - m_clickPos.x();
|
Chris@132
|
458 } else {
|
Chris@132
|
459 dist = e->y() - m_clickPos.y();
|
Chris@132
|
460 }
|
Chris@165
|
461
|
Chris@908
|
462 float rotation = m_clickRotation + (m_speed * float(dist)) / 100;
|
Chris@165
|
463 if (rotation < 0.f) rotation = 0.f;
|
Chris@165
|
464 if (rotation > 1.f) rotation = 1.f;
|
Chris@908
|
465 int value = int(lrintf(float(m_min) + float(m_max - m_min) * m_rotation));
|
Chris@132
|
466 if (value != m_value) {
|
Chris@132
|
467 setValue(value);
|
Chris@132
|
468 if (m_tracking) emit valueChanged(getValue());
|
Chris@165
|
469 m_rotation = rotation;
|
Chris@165
|
470 } else if (fabsf(rotation - m_rotation) > 0.001) {
|
Chris@165
|
471 m_rotation = rotation;
|
Chris@165
|
472 repaint();
|
Chris@165
|
473 }
|
Chris@132
|
474 }
|
Chris@132
|
475
|
Chris@132
|
476 void
|
Chris@132
|
477 Thumbwheel::mouseReleaseEvent(QMouseEvent *e)
|
Chris@132
|
478 {
|
Chris@133
|
479 if (!m_clicked) return;
|
Chris@132
|
480 bool reallyTracking = m_tracking;
|
Chris@132
|
481 m_tracking = true;
|
Chris@132
|
482 mouseMoveEvent(e);
|
Chris@132
|
483 m_tracking = reallyTracking;
|
Chris@133
|
484 m_clicked = false;
|
Chris@132
|
485 }
|
Chris@132
|
486
|
Chris@132
|
487 void
|
Chris@132
|
488 Thumbwheel::wheelEvent(QWheelEvent *e)
|
Chris@132
|
489 {
|
Chris@1303
|
490 int delta = m_wheelCounter.count(e);
|
Chris@132
|
491
|
Chris@1303
|
492 if (delta == 0) {
|
Chris@1303
|
493 return;
|
Chris@132
|
494 }
|
Chris@1303
|
495
|
Chris@1303
|
496 setValue(m_value + delta);
|
Chris@132
|
497 emit valueChanged(getValue());
|
Chris@132
|
498 }
|
Chris@132
|
499
|
Chris@132
|
500 void
|
Chris@132
|
501 Thumbwheel::paintEvent(QPaintEvent *)
|
Chris@132
|
502 {
|
Chris@382
|
503 Profiler profiler("Thumbwheel::paintEvent");
|
Chris@382
|
504
|
Chris@382
|
505 if (!m_cache.isNull()) {
|
Chris@382
|
506 QPainter paint(this);
|
Chris@1192
|
507 paint.drawImage(rect(), m_cache, m_cache.rect());
|
Chris@382
|
508 return;
|
Chris@382
|
509 }
|
Chris@382
|
510
|
Chris@382
|
511 Profiler profiler2("Thumbwheel::paintEvent (no cache)");
|
Chris@382
|
512
|
Chris@1192
|
513 QSize imageSize = size() * devicePixelRatio();
|
Chris@1192
|
514 m_cache = QImage(imageSize, QImage::Format_ARGB32);
|
Chris@382
|
515 m_cache.fill(Qt::transparent);
|
Chris@190
|
516
|
Chris@1193
|
517 int w = m_cache.width();
|
Chris@1193
|
518 int h = m_cache.height();
|
Chris@1192
|
519 int bw = 3; // border width
|
Chris@191
|
520
|
Chris@191
|
521 QRect subclip;
|
Chris@191
|
522 if (m_orientation == Qt::Horizontal) {
|
Chris@1192
|
523 subclip = QRect(bw, bw+1, w - bw*2, h - bw*2 - 2);
|
Chris@191
|
524 } else {
|
Chris@1192
|
525 subclip = QRect(bw+1, bw, w - bw*2 - 2, h - bw*2);
|
Chris@191
|
526 }
|
Chris@191
|
527
|
Chris@382
|
528 QPainter paint(&m_cache);
|
Chris@1192
|
529 paint.setClipRect(m_cache.rect());
|
Chris@1478
|
530 paint.fillRect(subclip, palette().window().color());
|
Chris@190
|
531
|
Chris@190
|
532 paint.setRenderHint(QPainter::Antialiasing, true);
|
Chris@133
|
533
|
Chris@908
|
534 double w0 = 0.5;
|
Chris@908
|
535 double w1 = w - 0.5;
|
Chris@190
|
536
|
Chris@908
|
537 double h0 = 0.5;
|
Chris@908
|
538 double h1 = h - 0.5;
|
Chris@190
|
539
|
Chris@190
|
540 for (int i = bw-1; i >= 0; --i) {
|
Chris@190
|
541
|
Chris@133
|
542 int grey = (i + 1) * (256 / (bw + 1));
|
Chris@133
|
543 QColor fc = QColor(grey, grey, grey);
|
Chris@133
|
544 paint.setPen(fc);
|
Chris@190
|
545
|
Chris@190
|
546 QPainterPath path;
|
Chris@190
|
547
|
Chris@190
|
548 if (m_orientation == Qt::Horizontal) {
|
Chris@190
|
549 path.moveTo(w0 + i, h0 + i + 2);
|
Chris@190
|
550 path.quadTo(w/2, i * 1.25, w1 - i, h0 + i + 2);
|
Chris@190
|
551 path.lineTo(w1 - i, h1 - i - 2);
|
Chris@190
|
552 path.quadTo(w/2, h - i * 1.25, w0 + i, h1 - i - 2);
|
Chris@190
|
553 path.closeSubpath();
|
Chris@190
|
554 } else {
|
Chris@190
|
555 path.moveTo(w0 + i + 2, h0 + i);
|
Chris@190
|
556 path.quadTo(i * 1.25, h/2, w0 + i + 2, h1 - i);
|
Chris@190
|
557 path.lineTo(w1 - i - 2, h1 - i);
|
Chris@190
|
558 path.quadTo(w - i * 1.25, h/2, w1 - i - 2, h0 + i);
|
Chris@190
|
559 path.closeSubpath();
|
Chris@190
|
560 }
|
Chris@190
|
561
|
Chris@190
|
562 paint.drawPath(path);
|
Chris@133
|
563 }
|
Chris@133
|
564
|
Chris@191
|
565 paint.setClipRect(subclip);
|
Chris@133
|
566
|
Chris@908
|
567 double radians = m_rotation * 1.5f * M_PI;
|
Chris@132
|
568
|
Chris@682
|
569 // cerr << "value = " << m_value << ", min = " << m_min << ", max = " << m_max << ", rotation = " << rotation << endl;
|
Chris@132
|
570
|
Chris@1192
|
571 int ww = (m_orientation == Qt::Horizontal ? w : h) - bw*2; // wheel width
|
Chris@132
|
572
|
Chris@132
|
573 // total number of notches on the entire wheel
|
Chris@132
|
574 int notches = 25;
|
Chris@132
|
575
|
Chris@132
|
576 // radius of the wheel including invisible part
|
Chris@1192
|
577 int radius = int(ww / 2 + 2);
|
Chris@132
|
578
|
Chris@132
|
579 for (int i = 0; i < notches; ++i) {
|
Chris@132
|
580
|
Chris@908
|
581 double a0 = (2.0 * M_PI * i) / notches + radians;
|
Chris@908
|
582 double a1 = a0 + M_PI / (notches * 2);
|
Chris@908
|
583 double a2 = (2.0 * M_PI * (i + 1)) / notches + radians;
|
Chris@132
|
584
|
Chris@908
|
585 double depth = cos((a0 + a2) / 2);
|
Chris@132
|
586 if (depth < 0) continue;
|
Chris@132
|
587
|
Chris@1192
|
588 double x0 = radius * sin(a0) + ww/2;
|
Chris@1192
|
589 double x1 = radius * sin(a1) + ww/2;
|
Chris@1192
|
590 double x2 = radius * sin(a2) + ww/2;
|
Chris@1192
|
591 if (x2 < 0 || x0 > ww) continue;
|
Chris@132
|
592
|
Chris@132
|
593 if (x0 < 0) x0 = 0;
|
Chris@1192
|
594 if (x2 > ww) x2 = ww;
|
Chris@132
|
595
|
Chris@133
|
596 x0 += bw;
|
Chris@133
|
597 x1 += bw;
|
Chris@133
|
598 x2 += bw;
|
Chris@133
|
599
|
Chris@908
|
600 int grey = int(lrint(120 * depth));
|
Chris@541
|
601
|
Chris@132
|
602 QColor fc = QColor(grey, grey, grey);
|
Chris@541
|
603 QColor oc = palette().highlight().color();
|
Chris@132
|
604
|
Chris@541
|
605 paint.setPen(fc);
|
Chris@132
|
606
|
Chris@132
|
607 if (m_showScale) {
|
Chris@132
|
608
|
Chris@132
|
609 paint.setBrush(oc);
|
Chris@132
|
610
|
Chris@908
|
611 double prop;
|
Chris@132
|
612 if (i >= notches / 4) {
|
Chris@908
|
613 prop = double(notches - (((i - double(notches) / 4.f) * 4.f) / 3.f))
|
Chris@132
|
614 / notches;
|
Chris@132
|
615 } else {
|
Chris@132
|
616 prop = 0.f;
|
Chris@132
|
617 }
|
Chris@132
|
618
|
Chris@132
|
619 if (m_orientation == Qt::Horizontal) {
|
Chris@1192
|
620 paint.drawRect(QRectF(x1, h - (h - bw*2) * prop - bw,
|
Chris@1192
|
621 x2 - x1, h * prop));
|
Chris@132
|
622 } else {
|
Chris@1192
|
623 paint.drawRect(QRectF(bw, x1, (w - bw*2) * prop, x2 - x1));
|
Chris@132
|
624 }
|
Chris@132
|
625 }
|
Chris@132
|
626
|
Chris@541
|
627 paint.setPen(fc);
|
Chris@1478
|
628 paint.setBrush(palette().window().color());
|
Chris@132
|
629
|
Chris@132
|
630 if (m_orientation == Qt::Horizontal) {
|
Chris@1192
|
631 paint.drawRect(QRectF(x0, bw, x1 - x0, h - bw*2));
|
Chris@132
|
632 } else {
|
Chris@1192
|
633 paint.drawRect(QRectF(bw, x0, w - bw*2, x1 - x0));
|
Chris@132
|
634 }
|
Chris@132
|
635 }
|
Chris@382
|
636
|
Chris@382
|
637 QPainter paint2(this);
|
Chris@1192
|
638 paint2.drawImage(rect(), m_cache, m_cache.rect());
|
Chris@132
|
639 }
|
Chris@132
|
640
|
Chris@132
|
641 QSize
|
Chris@132
|
642 Thumbwheel::sizeHint() const
|
Chris@132
|
643 {
|
Chris@132
|
644 if (m_orientation == Qt::Horizontal) {
|
Chris@132
|
645 return QSize(80, 12);
|
Chris@132
|
646 } else {
|
Chris@132
|
647 return QSize(12, 80);
|
Chris@132
|
648 }
|
Chris@132
|
649 }
|
Chris@132
|
650
|