Chris@929
|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
Chris@929
|
2
|
Chris@929
|
3 /*
|
Chris@929
|
4 Sonic Visualiser
|
Chris@929
|
5 An audio file viewer and annotation editor.
|
Chris@929
|
6 Centre for Digital Music, Queen Mary, University of London.
|
Chris@929
|
7
|
Chris@929
|
8 This program is free software; you can redistribute it and/or
|
Chris@929
|
9 modify it under the terms of the GNU General Public License as
|
Chris@929
|
10 published by the Free Software Foundation; either version 2 of the
|
Chris@929
|
11 License, or (at your option) any later version. See the file
|
Chris@929
|
12 COPYING included with this distribution for more information.
|
Chris@929
|
13 */
|
Chris@929
|
14
|
Chris@929
|
15 #include "LevelPanToolButton.h"
|
Chris@929
|
16 #include "LevelPanWidget.h"
|
Chris@929
|
17
|
Chris@929
|
18 #include <QMenu>
|
Chris@929
|
19 #include <QWidgetAction>
|
Chris@929
|
20 #include <QImage>
|
Chris@1300
|
21 #include <QMouseEvent>
|
Chris@936
|
22 #include <QStylePainter>
|
Chris@936
|
23 #include <QStyleOptionToolButton>
|
Chris@1589
|
24 #include <QMenu>
|
Chris@929
|
25
|
Chris@1300
|
26 #include "base/Debug.h"
|
Chris@1589
|
27 #include "base/AudioLevel.h"
|
Chris@1589
|
28 #include "MenuTitle.h"
|
Chris@1300
|
29
|
Chris@929
|
30 #include <iostream>
|
Chris@929
|
31 using std::cerr;
|
Chris@929
|
32 using std::endl;
|
Chris@929
|
33
|
Chris@929
|
34 LevelPanToolButton::LevelPanToolButton(QWidget *parent) :
|
Chris@929
|
35 QToolButton(parent),
|
Chris@930
|
36 m_pixels(32),
|
Chris@942
|
37 m_pixelsBig(32 * 3),
|
Chris@930
|
38 m_muted(false),
|
Chris@1589
|
39 m_savedLevel(1.f),
|
Chris@1589
|
40 m_provideContextMenu(true),
|
Chris@1589
|
41 m_lastContextMenu(nullptr)
|
Chris@929
|
42 {
|
Chris@929
|
43 m_lpw = new LevelPanWidget();
|
Chris@929
|
44
|
Chris@929
|
45 connect(m_lpw, SIGNAL(levelChanged(float)), this, SIGNAL(levelChanged(float)));
|
Chris@930
|
46 connect(m_lpw, SIGNAL(levelChanged(float)), this, SLOT(selfLevelChanged(float)));
|
Chris@929
|
47
|
Chris@929
|
48 connect(m_lpw, SIGNAL(panChanged(float)), this, SIGNAL(panChanged(float)));
|
Chris@932
|
49 connect(m_lpw, SIGNAL(panChanged(float)), this, SLOT(update()));
|
Chris@930
|
50
|
Chris@930
|
51 connect(this, SIGNAL(clicked(bool)), this, SLOT(selfClicked()));
|
Chris@929
|
52
|
Chris@929
|
53 QMenu *menu = new QMenu();
|
Chris@929
|
54 QWidgetAction *wa = new QWidgetAction(menu);
|
Chris@929
|
55 wa->setDefaultWidget(m_lpw);
|
Chris@929
|
56 menu->addAction(wa);
|
Chris@929
|
57
|
Chris@936
|
58 setPopupMode(InstantPopup);
|
Chris@929
|
59 setMenu(menu);
|
Chris@1191
|
60 setToolTip(tr("Click to adjust level and pan"));
|
Chris@929
|
61
|
Chris@932
|
62 setImageSize(m_pixels);
|
Chris@942
|
63 setBigImageSize(m_pixelsBig);
|
Chris@1589
|
64
|
Chris@1589
|
65 setContextMenuPolicy(Qt::CustomContextMenu);
|
Chris@1589
|
66 connect(this, SIGNAL(customContextMenuRequested(const QPoint &)),
|
Chris@1589
|
67 this, SLOT(contextMenuRequested(const QPoint &)));
|
Chris@929
|
68 }
|
Chris@929
|
69
|
Chris@929
|
70 LevelPanToolButton::~LevelPanToolButton()
|
Chris@929
|
71 {
|
Chris@1589
|
72 delete m_lastContextMenu;
|
Chris@929
|
73 }
|
Chris@929
|
74
|
Chris@1200
|
75 void
|
Chris@1300
|
76 LevelPanToolButton::mousePressEvent(QMouseEvent *e)
|
Chris@1300
|
77 {
|
Chris@1300
|
78 if (e->button() == Qt::MidButton ||
|
Chris@1300
|
79 ((e->button() == Qt::LeftButton) &&
|
Chris@1300
|
80 (e->modifiers() & Qt::ControlModifier))) {
|
Chris@1300
|
81 m_lpw->setToDefault();
|
Chris@1300
|
82 e->accept();
|
Chris@1300
|
83 } else {
|
Chris@1300
|
84 QToolButton::mousePressEvent(e);
|
Chris@1300
|
85 }
|
Chris@1300
|
86 }
|
Chris@1300
|
87
|
Chris@1300
|
88 void
|
Chris@1200
|
89 LevelPanToolButton::wheelEvent(QWheelEvent *e)
|
Chris@1200
|
90 {
|
Chris@1200
|
91 m_lpw->wheelEvent(e);
|
Chris@1200
|
92 }
|
Chris@1200
|
93
|
Chris@929
|
94 float
|
Chris@929
|
95 LevelPanToolButton::getLevel() const
|
Chris@929
|
96 {
|
Chris@929
|
97 return m_lpw->getLevel();
|
Chris@929
|
98 }
|
Chris@929
|
99
|
Chris@929
|
100 float
|
Chris@929
|
101 LevelPanToolButton::getPan() const
|
Chris@929
|
102 {
|
Chris@929
|
103 return m_lpw->getPan();
|
Chris@929
|
104 }
|
Chris@929
|
105
|
Chris@940
|
106 bool
|
Chris@940
|
107 LevelPanToolButton::includesMute() const
|
Chris@940
|
108 {
|
Chris@940
|
109 return m_lpw->includesMute();
|
Chris@940
|
110 }
|
Chris@940
|
111
|
Chris@929
|
112 void
|
Chris@929
|
113 LevelPanToolButton::setImageSize(int pixels)
|
Chris@929
|
114 {
|
Chris@929
|
115 m_pixels = pixels;
|
Chris@932
|
116
|
Chris@932
|
117 QPixmap px(m_pixels, m_pixels);
|
Chris@932
|
118 px.fill(Qt::transparent);
|
Chris@932
|
119 setIcon(px);
|
Chris@942
|
120 }
|
Chris@932
|
121
|
Chris@942
|
122 void
|
Chris@1589
|
123 LevelPanToolButton::setProvideContextMenu(bool provide)
|
Chris@1589
|
124 {
|
Chris@1589
|
125 m_provideContextMenu = provide;
|
Chris@1589
|
126 }
|
Chris@1589
|
127
|
Chris@1589
|
128 void
|
Chris@942
|
129 LevelPanToolButton::setBigImageSize(int pixels)
|
Chris@942
|
130 {
|
Chris@942
|
131 m_pixelsBig = pixels;
|
Chris@942
|
132
|
Chris@942
|
133 m_lpw->setFixedWidth(m_pixelsBig);
|
Chris@942
|
134 m_lpw->setFixedHeight(m_pixelsBig);
|
Chris@929
|
135 }
|
Chris@929
|
136
|
Chris@929
|
137 void
|
Chris@929
|
138 LevelPanToolButton::setLevel(float level)
|
Chris@929
|
139 {
|
Chris@929
|
140 m_lpw->setLevel(level);
|
Chris@932
|
141 update();
|
Chris@929
|
142 }
|
Chris@929
|
143
|
Chris@929
|
144 void
|
Chris@929
|
145 LevelPanToolButton::setPan(float pan)
|
Chris@929
|
146 {
|
Chris@929
|
147 m_lpw->setPan(pan);
|
Chris@932
|
148 update();
|
Chris@930
|
149 }
|
Chris@930
|
150
|
Chris@930
|
151 void
|
Chris@1187
|
152 LevelPanToolButton::setMonitoringLevels(float left, float right)
|
Chris@1187
|
153 {
|
Chris@1187
|
154 m_lpw->setMonitoringLevels(left, right);
|
Chris@1187
|
155 update();
|
Chris@1187
|
156 }
|
Chris@1187
|
157
|
Chris@1187
|
158 void
|
Chris@940
|
159 LevelPanToolButton::setIncludeMute(bool include)
|
Chris@940
|
160 {
|
Chris@940
|
161 m_lpw->setIncludeMute(include);
|
Chris@940
|
162 update();
|
Chris@940
|
163 }
|
Chris@940
|
164
|
Chris@940
|
165 void
|
Chris@933
|
166 LevelPanToolButton::setEnabled(bool enabled)
|
Chris@933
|
167 {
|
Chris@933
|
168 m_lpw->setEnabled(enabled);
|
Chris@933
|
169 QToolButton::setEnabled(enabled);
|
Chris@933
|
170 }
|
Chris@933
|
171
|
Chris@933
|
172 void
|
Chris@930
|
173 LevelPanToolButton::selfLevelChanged(float level)
|
Chris@930
|
174 {
|
Chris@930
|
175 if (level > 0.f) {
|
Chris@1266
|
176 m_muted = false;
|
Chris@930
|
177 } else {
|
Chris@1266
|
178 m_muted = true;
|
Chris@1266
|
179 m_savedLevel = 1.f;
|
Chris@930
|
180 }
|
Chris@932
|
181 update();
|
Chris@930
|
182 }
|
Chris@930
|
183
|
Chris@930
|
184 void
|
Chris@930
|
185 LevelPanToolButton::selfClicked()
|
Chris@930
|
186 {
|
Chris@930
|
187 if (m_muted) {
|
Chris@1266
|
188 m_muted = false;
|
Chris@1266
|
189 m_lpw->setLevel(m_savedLevel);
|
Chris@1266
|
190 emit levelChanged(m_savedLevel);
|
Chris@930
|
191 } else {
|
Chris@1266
|
192 m_savedLevel = m_lpw->getLevel();
|
Chris@1266
|
193 m_muted = true;
|
Chris@1266
|
194 m_lpw->setLevel(0.f);
|
Chris@1266
|
195 emit levelChanged(0.f);
|
Chris@930
|
196 }
|
Chris@932
|
197 update();
|
Chris@929
|
198 }
|
Chris@929
|
199
|
Chris@929
|
200 void
|
Chris@1589
|
201 LevelPanToolButton::contextMenuRequested(const QPoint &pos)
|
Chris@1589
|
202 {
|
Chris@1589
|
203 if (!m_provideContextMenu) {
|
Chris@1589
|
204 return;
|
Chris@1589
|
205 }
|
Chris@1589
|
206
|
Chris@1589
|
207 delete m_lastContextMenu;
|
Chris@1589
|
208 m_lastContextMenu = new QMenu;
|
Chris@1589
|
209 auto m = m_lastContextMenu;
|
Chris@1589
|
210
|
Chris@1589
|
211 QString title;
|
Chris@1589
|
212
|
Chris@1589
|
213 if (m_muted) {
|
Chris@1589
|
214 title = tr("Muted");
|
Chris@1589
|
215 } else {
|
Chris@1589
|
216 // Pan is actually stereo balance in most applications...
|
Chris@1589
|
217 auto level = AudioLevel::multiplier_to_dB(m_lpw->getLevel());
|
Chris@1589
|
218 auto pan = m_lpw->getPan();
|
Chris@1589
|
219 if (pan == 0) {
|
Chris@1589
|
220 title = tr("Level: %1 dB - Balance: Middle").arg(level);
|
Chris@1589
|
221 } else if (pan > 0) {
|
Chris@1589
|
222 title = tr("Level: %1 dB - Balance: +%2").arg(level).arg(pan);
|
Chris@1589
|
223 } else {
|
Chris@1589
|
224 title = tr("Level: %1 dB - Balance: %2").arg(level).arg(pan);
|
Chris@1589
|
225 }
|
Chris@1589
|
226 }
|
Chris@1589
|
227
|
Chris@1589
|
228 MenuTitle::addTitle(m, title);
|
Chris@1589
|
229
|
Chris@1589
|
230 m->addAction(tr("&Reset to Default"),
|
Chris@1589
|
231 [=]() {
|
Chris@1589
|
232 m_lpw->setToDefault();
|
Chris@1589
|
233 });
|
Chris@1589
|
234
|
Chris@1589
|
235 m->popup(mapToGlobal(pos));
|
Chris@1589
|
236 }
|
Chris@1589
|
237
|
Chris@1589
|
238 void
|
Chris@936
|
239 LevelPanToolButton::paintEvent(QPaintEvent *)
|
Chris@929
|
240 {
|
Chris@936
|
241 QStylePainter p(this);
|
Chris@936
|
242 QStyleOptionToolButton opt;
|
Chris@936
|
243 initStyleOption(&opt);
|
Chris@936
|
244 opt.features &= (~QStyleOptionToolButton::HasMenu);
|
Chris@936
|
245 p.drawComplexControl(QStyle::CC_ToolButton, opt);
|
Chris@936
|
246
|
Chris@934
|
247 if (m_pixels >= height()) {
|
Chris@934
|
248 setImageSize(height()-1);
|
Chris@934
|
249 }
|
Chris@936
|
250
|
Chris@932
|
251 double margin = (double(height()) - m_pixels) / 2.0;
|
Chris@932
|
252 m_lpw->renderTo(this, QRectF(margin, margin, m_pixels, m_pixels), false);
|
Chris@929
|
253 }
|
Chris@929
|
254
|
Chris@1180
|
255 void
|
Chris@1180
|
256 LevelPanToolButton::enterEvent(QEvent *e)
|
Chris@1180
|
257 {
|
Chris@1180
|
258 QToolButton::enterEvent(e);
|
Chris@1180
|
259 emit mouseEntered();
|
Chris@1180
|
260 }
|
Chris@932
|
261
|
Chris@1180
|
262 void
|
Chris@1180
|
263 LevelPanToolButton::leaveEvent(QEvent *e)
|
Chris@1180
|
264 {
|
Chris@1180
|
265 QToolButton::enterEvent(e);
|
Chris@1180
|
266 emit mouseLeft();
|
Chris@1180
|
267 }
|
Chris@1180
|
268
|
Chris@1180
|
269
|