annotate widgets/LevelPanToolButton.cpp @ 1600:1acd7be4df9a

Complete round-trip name-type conversion for melodic range & peak freq spectrograms (also has the effect of making them creatable from OSC)
author Chris Cannam
date Wed, 29 Apr 2020 13:26:23 +0100
parents 27ea5d61b402
children a798a7b5e215
rev   line source
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