annotate widgets/Thumbwheel.cpp @ 1595:8b78b3c330fb

Use our base column type
author Chris Cannam
date Thu, 09 Apr 2020 11:23:40 +0100
parents 27ea5d61b402
children a798a7b5e215
rev   line source
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