annotate widgets/Thumbwheel.cpp @ 132:5d3a483856ff

* Add Thumbwheel widget for all our zooming needs * Use QSettings to save/restore window size and position -- precursor to switching our preferences to QSettings as well -- wish I'd noticed it sooner * Only suspend writes (not reads from the underlying cache objects) from the fft caches when repainting the spectrogram -- performance should now be significantly better
author Chris Cannam
date Thu, 03 Aug 2006 15:40:11 +0000
parents
children 9e6b3e239b9d
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@132 7 This file copyright 2006 Chris Cannam.
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@132 18 #include <QMouseEvent>
Chris@132 19 #include <QPaintEvent>
Chris@132 20 #include <QWheelEvent>
Chris@132 21 #include <QPainter>
Chris@132 22
Chris@132 23 #include <cmath>
Chris@132 24 #include <iostream>
Chris@132 25
Chris@132 26 Thumbwheel::Thumbwheel(int min, int max, int defaultValue,
Chris@132 27 Qt::Orientation orientation,
Chris@132 28 QWidget *parent) :
Chris@132 29 QWidget(parent),
Chris@132 30 m_min(min),
Chris@132 31 m_max(max),
Chris@132 32 m_default(defaultValue),
Chris@132 33 m_value((min + max) / 2),
Chris@132 34 m_orientation(orientation),
Chris@132 35 m_tracking(true),
Chris@132 36 m_showScale(true),
Chris@132 37 m_clicked(false),
Chris@132 38 m_clickValue(m_value)
Chris@132 39 {
Chris@132 40 if (max <= min) max = min + 1;
Chris@132 41 m_speed = float(max - min) / 300.f;
Chris@132 42 }
Chris@132 43
Chris@132 44 Thumbwheel::~Thumbwheel()
Chris@132 45 {
Chris@132 46 }
Chris@132 47
Chris@132 48 void
Chris@132 49 Thumbwheel::setValue(int value)
Chris@132 50 {
Chris@132 51 if (value < m_min) value = m_min;
Chris@132 52 if (value > m_max) value = m_max;
Chris@132 53 m_value = value;
Chris@132 54 update();
Chris@132 55 }
Chris@132 56
Chris@132 57 int
Chris@132 58 Thumbwheel::getValue() const
Chris@132 59 {
Chris@132 60 return m_value;
Chris@132 61 }
Chris@132 62
Chris@132 63 void
Chris@132 64 Thumbwheel::setSpeed(float speed)
Chris@132 65 {
Chris@132 66 m_speed = speed;
Chris@132 67 }
Chris@132 68
Chris@132 69 float
Chris@132 70 Thumbwheel::getSpeed() const
Chris@132 71 {
Chris@132 72 return m_speed;
Chris@132 73 }
Chris@132 74
Chris@132 75 void
Chris@132 76 Thumbwheel::setTracking(bool tracking)
Chris@132 77 {
Chris@132 78 m_tracking = tracking;
Chris@132 79 }
Chris@132 80
Chris@132 81 bool
Chris@132 82 Thumbwheel::getTracking() const
Chris@132 83 {
Chris@132 84 return m_tracking;
Chris@132 85 }
Chris@132 86
Chris@132 87 void
Chris@132 88 Thumbwheel::setShowScale(bool showScale)
Chris@132 89 {
Chris@132 90 m_showScale = showScale;
Chris@132 91 }
Chris@132 92
Chris@132 93 bool
Chris@132 94 Thumbwheel::getShowScale() const
Chris@132 95 {
Chris@132 96 return m_showScale;
Chris@132 97 }
Chris@132 98
Chris@132 99 void
Chris@132 100 Thumbwheel::mousePressEvent(QMouseEvent *e)
Chris@132 101 {
Chris@132 102 m_clicked = true;
Chris@132 103 m_clickPos = e->pos();
Chris@132 104 m_clickValue = m_value;
Chris@132 105 }
Chris@132 106
Chris@132 107 void
Chris@132 108 Thumbwheel::mouseDoubleClickEvent(QMouseEvent *)
Chris@132 109 {
Chris@132 110 setValue(m_default);
Chris@132 111 emit valueChanged(getValue());
Chris@132 112 }
Chris@132 113
Chris@132 114 void
Chris@132 115 Thumbwheel::mouseMoveEvent(QMouseEvent *e)
Chris@132 116 {
Chris@132 117 int dist = 0;
Chris@132 118 if (m_orientation == Qt::Horizontal) {
Chris@132 119 dist = e->x() - m_clickPos.x();
Chris@132 120 } else {
Chris@132 121 dist = e->y() - m_clickPos.y();
Chris@132 122 }
Chris@132 123 int value = m_clickValue + lrintf(m_speed * dist);
Chris@132 124 if (value < m_min) value = m_min;
Chris@132 125 if (value > m_max) value = m_max;
Chris@132 126 if (value != m_value) {
Chris@132 127 setValue(value);
Chris@132 128 if (m_tracking) emit valueChanged(getValue());
Chris@132 129 }
Chris@132 130 }
Chris@132 131
Chris@132 132 void
Chris@132 133 Thumbwheel::mouseReleaseEvent(QMouseEvent *e)
Chris@132 134 {
Chris@132 135 bool reallyTracking = m_tracking;
Chris@132 136 m_tracking = true;
Chris@132 137 mouseMoveEvent(e);
Chris@132 138 m_tracking = reallyTracking;
Chris@132 139 }
Chris@132 140
Chris@132 141 void
Chris@132 142 Thumbwheel::wheelEvent(QWheelEvent *e)
Chris@132 143 {
Chris@132 144 int step = lrintf(m_speed);
Chris@132 145 if (step == 0) step = 1;
Chris@132 146
Chris@132 147 if (e->delta() > 0) {
Chris@132 148 setValue(m_value + step);
Chris@132 149 } else {
Chris@132 150 setValue(m_value - step);
Chris@132 151 }
Chris@132 152
Chris@132 153 emit valueChanged(getValue());
Chris@132 154 }
Chris@132 155
Chris@132 156 void
Chris@132 157 Thumbwheel::paintEvent(QPaintEvent *)
Chris@132 158 {
Chris@132 159 float distance = float(m_value - m_min) / float(m_max - m_min);
Chris@132 160 float rotation = distance * 1.5f * M_PI;
Chris@132 161
Chris@132 162 // std::cerr << "value = " << m_value << ", min = " << m_min << ", max = " << m_max << ", rotation = " << rotation << std::endl;
Chris@132 163
Chris@132 164 int w = (m_orientation == Qt::Horizontal ? width() : height());
Chris@132 165
Chris@132 166 // total number of notches on the entire wheel
Chris@132 167 int notches = 25;
Chris@132 168
Chris@132 169 // radius of the wheel including invisible part
Chris@132 170 int radius = w / 2 + 2;
Chris@132 171
Chris@132 172 QPainter paint(this);
Chris@132 173 paint.fillRect(rect(), palette().background().color());
Chris@132 174 paint.setRenderHint(QPainter::Antialiasing, true);
Chris@132 175
Chris@132 176 for (int i = 0; i < notches; ++i) {
Chris@132 177
Chris@132 178 float a0 = (2.f * M_PI * i) / notches + rotation;
Chris@132 179 float a1 = a0 + M_PI / (notches * 2);
Chris@132 180 float a2 = (2.f * M_PI * (i + 1)) / notches + rotation;
Chris@132 181
Chris@132 182 float depth = cosf((a0 + a2) / 2);
Chris@132 183 if (depth < 0) continue;
Chris@132 184
Chris@132 185 float x0 = radius * sinf(a0) + w/2;
Chris@132 186 float x1 = radius * sinf(a1) + w/2;
Chris@132 187 float x2 = radius * sinf(a2) + w/2;
Chris@132 188 if (x2 < 0 || x0 > w) continue;
Chris@132 189
Chris@132 190 if (x0 < 0) x0 = 0;
Chris@132 191 if (x2 > w) x2 = w;
Chris@132 192
Chris@132 193 int grey = lrintf(255 * depth);
Chris@132 194 QColor fc = QColor(grey, grey, grey);
Chris@132 195 QColor oc = palette().dark().color();
Chris@132 196
Chris@132 197 paint.setPen(oc);
Chris@132 198 paint.setBrush(fc);
Chris@132 199
Chris@132 200 if (m_orientation == Qt::Horizontal) {
Chris@132 201 paint.drawRect(QRectF(x1, 0, x2 - x1, height()));
Chris@132 202 } else {
Chris@132 203 paint.drawRect(QRectF(0, x1, width(), x2 - x1));
Chris@132 204 }
Chris@132 205
Chris@132 206 if (m_showScale) {
Chris@132 207
Chris@132 208 paint.setBrush(oc);
Chris@132 209
Chris@132 210 float prop;
Chris@132 211 if (i >= notches / 4) {
Chris@132 212 prop = float(notches - (((i - float(notches) / 4.f) * 4.f) / 3.f))
Chris@132 213 / notches;
Chris@132 214 } else {
Chris@132 215 prop = 0.f;
Chris@132 216 }
Chris@132 217
Chris@132 218 if (m_orientation == Qt::Horizontal) {
Chris@132 219 paint.drawRect(QRectF(x1, height() - height() * prop,
Chris@132 220 x2 - x1, height() * prop));
Chris@132 221 } else {
Chris@132 222 paint.drawRect(QRectF(0, x1, width() * prop, x2 - x1));
Chris@132 223 }
Chris@132 224 }
Chris@132 225
Chris@132 226 paint.setPen(oc);
Chris@132 227 paint.setBrush(palette().background().color());
Chris@132 228
Chris@132 229 if (m_orientation == Qt::Horizontal) {
Chris@132 230 paint.drawRect(QRectF(x0, 0, x1 - x0, height()));
Chris@132 231 } else {
Chris@132 232 paint.drawRect(QRectF(0, x0, width(), x1 - x0));
Chris@132 233 }
Chris@132 234 }
Chris@132 235 }
Chris@132 236
Chris@132 237 QSize
Chris@132 238 Thumbwheel::sizeHint() const
Chris@132 239 {
Chris@132 240 if (m_orientation == Qt::Horizontal) {
Chris@132 241 return QSize(80, 12);
Chris@132 242 } else {
Chris@132 243 return QSize(12, 80);
Chris@132 244 }
Chris@132 245 }
Chris@132 246