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