LevelPanToolButton.cpp
Go to the documentation of this file.
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 "LevelPanToolButton.h"
16 #include "LevelPanWidget.h"
17 
18 #include <QMenu>
19 #include <QWidgetAction>
20 #include <QImage>
21 #include <QMouseEvent>
22 #include <QStylePainter>
23 #include <QStyleOptionToolButton>
24 #include <QMenu>
25 
26 #include "base/Debug.h"
27 #include "base/AudioLevel.h"
28 #include "MenuTitle.h"
29 
30 #include <iostream>
31 using std::cerr;
32 using std::endl;
33 
35  QToolButton(parent),
36  m_pixels(32),
37  m_pixelsBig(32 * 3),
38  m_muted(false),
39  m_savedLevel(1.f),
40  m_provideContextMenu(true),
41  m_lastContextMenu(nullptr)
42 {
43  m_lpw = new LevelPanWidget();
44 
45  connect(m_lpw, SIGNAL(levelChanged(float)), this, SIGNAL(levelChanged(float)));
46  connect(m_lpw, SIGNAL(levelChanged(float)), this, SLOT(selfLevelChanged(float)));
47 
48  connect(m_lpw, SIGNAL(panChanged(float)), this, SIGNAL(panChanged(float)));
49  connect(m_lpw, SIGNAL(panChanged(float)), this, SLOT(update()));
50 
51  connect(this, SIGNAL(clicked(bool)), this, SLOT(selfClicked()));
52 
53  QMenu *menu = new QMenu();
54  QWidgetAction *wa = new QWidgetAction(menu);
55  wa->setDefaultWidget(m_lpw);
56  menu->addAction(wa);
57 
58  setPopupMode(InstantPopup);
59  setMenu(menu);
60  setToolTip(tr("Click to adjust level and pan"));
61 
64 
65  setContextMenuPolicy(Qt::CustomContextMenu);
66  connect(this, SIGNAL(customContextMenuRequested(const QPoint &)),
67  this, SLOT(contextMenuRequested(const QPoint &)));
68 }
69 
71 {
72  delete m_lastContextMenu;
73 }
74 
75 void
77 {
78  if (e->button() == Qt::MidButton ||
79  ((e->button() == Qt::LeftButton) &&
80  (e->modifiers() & Qt::ControlModifier))) {
82  e->accept();
83  } else {
84  QToolButton::mousePressEvent(e);
85  }
86 }
87 
88 void
90 {
91  m_lpw->wheelEvent(e);
92 }
93 
94 float
96 {
97  return m_lpw->getLevel();
98 }
99 
100 float
102 {
103  return m_lpw->getPan();
104 }
105 
106 bool
108 {
109  return m_lpw->includesMute();
110 }
111 
112 void
114 {
115  m_pixels = pixels;
116 
117  QPixmap px(m_pixels, m_pixels);
118  px.fill(Qt::transparent);
119  setIcon(px);
120 }
121 
122 void
124 {
125  m_provideContextMenu = provide;
126 }
127 
128 void
130 {
131  m_pixelsBig = pixels;
132 
133  m_lpw->setFixedWidth(m_pixelsBig);
134  m_lpw->setFixedHeight(m_pixelsBig);
135 }
136 
137 void
139 {
140  m_lpw->setLevel(level);
141  update();
142 }
143 
144 void
146 {
147  m_lpw->setPan(pan);
148  update();
149 }
150 
151 void
153 {
154  m_lpw->setMonitoringLevels(left, right);
155  update();
156 }
157 
158 void
160 {
161  m_lpw->setIncludeMute(include);
162  update();
163 }
164 
165 void
167 {
168  m_lpw->setEnabled(enabled);
169  QToolButton::setEnabled(enabled);
170 }
171 
172 void
174 {
175  if (level > 0.f) {
176  m_muted = false;
177  } else {
178  m_muted = true;
179  m_savedLevel = 1.f;
180  }
181  update();
182 }
183 
184 void
186 {
187  if (m_muted) {
188  m_muted = false;
191  } else {
193  m_muted = true;
194  m_lpw->setLevel(0.f);
195  emit levelChanged(0.f);
196  }
197  update();
198 }
199 
200 void
202 {
203  if (!m_provideContextMenu) {
204  return;
205  }
206 
207  delete m_lastContextMenu;
208  m_lastContextMenu = new QMenu;
209  auto m = m_lastContextMenu;
210 
211  QString title;
212 
213  if (m_muted) {
214  title = tr("Muted");
215  } else {
216  // Pan is actually stereo balance in most applications...
217  auto level = AudioLevel::multiplier_to_dB(m_lpw->getLevel());
218  auto pan = m_lpw->getPan();
219  if (pan == 0) {
220  title = tr("Level: %1 dB - Balance: Middle").arg(level);
221  } else if (pan > 0) {
222  title = tr("Level: %1 dB - Balance: +%2").arg(level).arg(pan);
223  } else {
224  title = tr("Level: %1 dB - Balance: %2").arg(level).arg(pan);
225  }
226  }
227 
228  MenuTitle::addTitle(m, title);
229 
230  m->addAction(tr("&Reset to Default"), m_lpw, SLOT(setToDefault()));
231 
232  m->popup(mapToGlobal(pos));
233 }
234 
235 void
237 {
238  QStylePainter p(this);
239  QStyleOptionToolButton opt;
240  initStyleOption(&opt);
241  opt.features &= (~QStyleOptionToolButton::HasMenu);
242  p.drawComplexControl(QStyle::CC_ToolButton, opt);
243 
244  if (m_pixels >= height()) {
245  setImageSize(height()-1);
246  }
247 
248  double margin = (double(height()) - m_pixels) / 2.0;
249  m_lpw->renderTo(this, QRectF(margin, margin, m_pixels, m_pixels), false);
250 }
251 
252 void
254 {
255  QToolButton::enterEvent(e);
256  emit mouseEntered();
257 }
258 
259 void
261 {
262  QToolButton::enterEvent(e);
263  emit mouseLeft();
264 }
265 
266 
void setLevel(float)
Set level in the range [0,1] – will be rounded.
void setLevel(float)
Set level.
static void addTitle(QMenu *m, QString text)
Definition: MenuTitle.h:29
float getLevel() const
Return level as a gain value in the range [0,1].
void setPan(float)
Set pan in the range [-1,1]. The value will be rounded.
void setEnabled(bool enabled)
void wheelEvent(QWheelEvent *e) override
LevelPanToolButton(QWidget *parent=0)
void setIncludeMute(bool)
Specify whether the level range should include muting or not.
bool includesMute() const
Discover whether the level range includes muting or not.
float getPan() const
Return pan as a value in the range [-1,1].
void setPan(float)
Set pan in the range [-1,1] – will be rounded.
void renderTo(QPaintDevice *, QRectF, bool asIfEditable) const
Draw a suitably sized copy of the widget&#39;s contents to the given device.
void setMonitoringLevels(float, float)
Set left and right peak monitoring levels in the range [0,1].
void paintEvent(QPaintEvent *) override
void panChanged(float)
void wheelEvent(QWheelEvent *ev) override
void setIncludeMute(bool)
Specify whether the level range should include muting or not.
void setMonitoringLevels(float, float)
Set left and right peak monitoring levels in the range [0,1].
LevelPanWidget * m_lpw
float getPan() const
Return pan as a value in the range [-1,1].
void contextMenuRequested(const QPoint &)
void enterEvent(QEvent *) override
void setBigImageSize(int pixels)
void setImageSize(int pixels)
A simple widget for coarse level and pan control.
void leaveEvent(QEvent *) override
void levelChanged(float)
bool includesMute() const
Discover whether the level range includes muting or not.
void mousePressEvent(QMouseEvent *) override
void setProvideContextMenu(bool)
Specify whether a right-click context menu is provided.
void setToDefault()
Reset to default values.
float getLevel() const
Return level as a gain value.