Mercurial > hg > svgui
comparison widgets/LevelPanWidget.cpp @ 923:2a9f1eb6e0ed tonioni
Try adding a combined simple level/pan widget
| author | Chris Cannam |
|---|---|
| date | Tue, 24 Mar 2015 14:40:31 +0000 |
| parents | |
| children | cfcdec324712 |
comparison
equal
deleted
inserted
replaced
| 922:26da827e8fb5 | 923:2a9f1eb6e0ed |
|---|---|
| 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ | |
| 2 | |
| 3 /* | |
| 4 Sonic Visualiser | |
| 5 An audio file viewer and annotation editor. | |
| 6 Centre for Digital Music, Queen Mary, University of London. | |
| 7 | |
| 8 This program is free software; you can redistribute it and/or | |
| 9 modify it under the terms of the GNU General Public License as | |
| 10 published by the Free Software Foundation; either version 2 of the | |
| 11 License, or (at your option) any later version. See the file | |
| 12 COPYING included with this distribution for more information. | |
| 13 */ | |
| 14 | |
| 15 #include "LevelPanWidget.h" | |
| 16 | |
| 17 #include <QPainter> | |
| 18 #include <QMouseEvent> | |
| 19 #include <QWheelEvent> | |
| 20 | |
| 21 #include "layer/ColourMapper.h" | |
| 22 | |
| 23 #include <iostream> | |
| 24 | |
| 25 using std::cerr; | |
| 26 using std::endl; | |
| 27 | |
| 28 static const int maxLevel = 5; | |
| 29 static const int maxPan = 2; // range is -maxPan to maxPan | |
| 30 | |
| 31 LevelPanWidget::LevelPanWidget(QWidget *parent) : | |
| 32 QWidget(parent), | |
| 33 m_level(maxLevel), | |
| 34 m_pan(0), | |
| 35 m_editable(true) | |
| 36 { | |
| 37 } | |
| 38 | |
| 39 LevelPanWidget::~LevelPanWidget() | |
| 40 { | |
| 41 } | |
| 42 | |
| 43 void | |
| 44 LevelPanWidget::setLevel(float level) | |
| 45 { | |
| 46 m_level = int(round(level * maxLevel)); | |
| 47 if (m_level < 0) m_level = 0; | |
| 48 if (m_level > maxLevel) m_level = maxLevel; | |
| 49 update(); | |
| 50 } | |
| 51 | |
| 52 void | |
| 53 LevelPanWidget::setPan(float pan) | |
| 54 { | |
| 55 m_pan = int(round(pan * maxPan)); | |
| 56 if (m_pan < -maxPan) m_pan = -maxPan; | |
| 57 if (m_pan > maxPan) m_pan = maxPan; | |
| 58 update(); | |
| 59 } | |
| 60 | |
| 61 void | |
| 62 LevelPanWidget::setEditable(bool editable) | |
| 63 { | |
| 64 m_editable = editable; | |
| 65 update(); | |
| 66 } | |
| 67 | |
| 68 float | |
| 69 LevelPanWidget::getLevel() const | |
| 70 { | |
| 71 return float(m_level) / float(maxLevel); | |
| 72 } | |
| 73 | |
| 74 float | |
| 75 LevelPanWidget::getPan() const | |
| 76 { | |
| 77 return float(m_pan) / float(maxPan); | |
| 78 } | |
| 79 | |
| 80 void | |
| 81 LevelPanWidget::emitLevelChanged() | |
| 82 { | |
| 83 cerr << "emitting levelChanged(" << getLevel() << ")" << endl; | |
| 84 emit levelChanged(getLevel()); | |
| 85 } | |
| 86 | |
| 87 void | |
| 88 LevelPanWidget::emitPanChanged() | |
| 89 { | |
| 90 cerr << "emitting panChanged(" << getPan() << ")" << endl; | |
| 91 emit panChanged(getPan()); | |
| 92 } | |
| 93 | |
| 94 void | |
| 95 LevelPanWidget::mousePressEvent(QMouseEvent *e) | |
| 96 { | |
| 97 mouseMoveEvent(e); | |
| 98 } | |
| 99 | |
| 100 void | |
| 101 LevelPanWidget::mouseMoveEvent(QMouseEvent *e) | |
| 102 { | |
| 103 if (!m_editable) return; | |
| 104 | |
| 105 int level, pan; | |
| 106 toCell(e->pos(), level, pan); | |
| 107 if (level == m_level && pan == m_pan) { | |
| 108 return; | |
| 109 } | |
| 110 if (level != m_level) { | |
| 111 m_level = level; | |
| 112 emitLevelChanged(); | |
| 113 } | |
| 114 if (pan != m_pan) { | |
| 115 m_pan = pan; | |
| 116 emitPanChanged(); | |
| 117 } | |
| 118 update(); | |
| 119 } | |
| 120 | |
| 121 void | |
| 122 LevelPanWidget::mouseReleaseEvent(QMouseEvent *e) | |
| 123 { | |
| 124 mouseMoveEvent(e); | |
| 125 } | |
| 126 | |
| 127 void | |
| 128 LevelPanWidget::wheelEvent(QWheelEvent *e) | |
| 129 { | |
| 130 if (e->modifiers() & Qt::ControlModifier) { | |
| 131 if (e->delta() > 0) { | |
| 132 if (m_pan < maxPan) { | |
| 133 ++m_pan; | |
| 134 emitPanChanged(); | |
| 135 update(); | |
| 136 } | |
| 137 } else { | |
| 138 if (m_pan > -maxPan) { | |
| 139 --m_pan; | |
| 140 emitPanChanged(); | |
| 141 update(); | |
| 142 } | |
| 143 } | |
| 144 } else { | |
| 145 if (e->delta() > 0) { | |
| 146 if (m_level < maxLevel) { | |
| 147 ++m_level; | |
| 148 emitLevelChanged(); | |
| 149 update(); | |
| 150 } | |
| 151 } else { | |
| 152 if (m_level > 0) { | |
| 153 --m_level; | |
| 154 emitLevelChanged(); | |
| 155 update(); | |
| 156 } | |
| 157 } | |
| 158 } | |
| 159 } | |
| 160 | |
| 161 void | |
| 162 LevelPanWidget::toCell(QPointF loc, int &level, int &pan) const | |
| 163 { | |
| 164 double w = width(), h = height(); | |
| 165 int npan = maxPan * 2 + 1; | |
| 166 double wcell = w / npan, hcell = h / maxLevel; | |
| 167 level = int((h - loc.y()) / hcell) + 1; | |
| 168 if (level < 1) level = 1; | |
| 169 if (level > maxLevel) level = maxLevel; | |
| 170 pan = int(loc.x() / wcell) - maxPan; | |
| 171 if (pan < -maxPan) pan = -maxPan; | |
| 172 if (pan > maxPan) pan = maxPan; | |
| 173 } | |
| 174 | |
| 175 QSizeF | |
| 176 LevelPanWidget::cellSize() const | |
| 177 { | |
| 178 double w = width(), h = height(); | |
| 179 int npan = maxPan * 2 + 1; | |
| 180 double wcell = w / npan, hcell = h / maxLevel; | |
| 181 return QSizeF(wcell, hcell); | |
| 182 } | |
| 183 | |
| 184 QPointF | |
| 185 LevelPanWidget::cellCentre(int level, int pan) const | |
| 186 { | |
| 187 QSizeF cs = cellSize(); | |
| 188 return QPointF(cs.width() * (pan + maxPan) + cs.width() / 2., | |
| 189 height() - cs.height() * level + cs.height() / 2.); | |
| 190 } | |
| 191 | |
| 192 QSizeF | |
| 193 LevelPanWidget::cellLightSize() const | |
| 194 { | |
| 195 double extent = 3. / 4.; | |
| 196 QSizeF cs = cellSize(); | |
| 197 double m = std::min(cs.width(), cs.height()); | |
| 198 return QSizeF(m * extent, m * extent); | |
| 199 } | |
| 200 | |
| 201 QRectF | |
| 202 LevelPanWidget::cellLightRect(int level, int pan) const | |
| 203 { | |
| 204 QSizeF cls = cellLightSize(); | |
| 205 QPointF cc = cellCentre(level, pan); | |
| 206 return QRectF(cc.x() - cls.width() / 2., | |
| 207 cc.y() - cls.height() / 2., | |
| 208 cls.width(), | |
| 209 cls.height()); | |
| 210 } | |
| 211 | |
| 212 double | |
| 213 LevelPanWidget::thinLineWidth() const | |
| 214 { | |
| 215 double tw = ceil(width() / (maxPan * 2. * 10.)); | |
| 216 double th = ceil(height() / (maxLevel * 10.)); | |
| 217 return std::min(th, tw); | |
| 218 } | |
| 219 | |
| 220 void | |
| 221 LevelPanWidget::paintEvent(QPaintEvent *) | |
| 222 { | |
| 223 QPainter paint(this); | |
| 224 ColourMapper mapper(ColourMapper::Sunset, 0, maxLevel); | |
| 225 | |
| 226 paint.setRenderHint(QPainter::Antialiasing, true); | |
| 227 | |
| 228 QPen pen; | |
| 229 | |
| 230 double thin = thinLineWidth(); | |
| 231 | |
| 232 pen.setColor(QColor(127, 127, 127, 127)); | |
| 233 pen.setWidthF(cellLightSize().width() + thin); | |
| 234 pen.setCapStyle(Qt::RoundCap); | |
| 235 paint.setPen(pen); | |
| 236 | |
| 237 for (int pan = -maxPan; pan <= maxPan; ++pan) { | |
| 238 paint.drawLine(cellCentre(1, pan), cellCentre(maxLevel, pan)); | |
| 239 } | |
| 240 | |
| 241 pen.setColor(Qt::black); | |
| 242 pen.setWidthF(thin); | |
| 243 pen.setCapStyle(Qt::FlatCap); | |
| 244 paint.setPen(pen); | |
| 245 | |
| 246 for (int level = 1; level <= m_level; ++level) { | |
| 247 // level starts at 1 because we handle mute separately | |
| 248 paint.setBrush(mapper.map(level)); | |
| 249 paint.drawEllipse(cellLightRect(level, m_pan)); | |
| 250 } | |
| 251 } | |
| 252 | |
| 253 |
