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