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