annotate widgets/LevelPanWidget.cpp @ 924:cfcdec324712 tonioni

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