annotate widgets/LevelPanToolButton.cpp @ 1605:ae2d5f8ff005

When asked to render the whole view width, we need to wait for the layers to be ready before we can determine what the width is
author Chris Cannam
date Thu, 30 Apr 2020 14:47:13 +0100
parents a798a7b5e215
children
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@1602 230 m->addAction(tr("&Reset to Default"), m_lpw, SLOT(setToDefault()));
Chris@1589 231
Chris@1589 232 m->popup(mapToGlobal(pos));
Chris@1589 233 }
Chris@1589 234
Chris@1589 235 void
Chris@936 236 LevelPanToolButton::paintEvent(QPaintEvent *)
Chris@929 237 {
Chris@936 238 QStylePainter p(this);
Chris@936 239 QStyleOptionToolButton opt;
Chris@936 240 initStyleOption(&opt);
Chris@936 241 opt.features &= (~QStyleOptionToolButton::HasMenu);
Chris@936 242 p.drawComplexControl(QStyle::CC_ToolButton, opt);
Chris@936 243
Chris@934 244 if (m_pixels >= height()) {
Chris@934 245 setImageSize(height()-1);
Chris@934 246 }
Chris@936 247
Chris@932 248 double margin = (double(height()) - m_pixels) / 2.0;
Chris@932 249 m_lpw->renderTo(this, QRectF(margin, margin, m_pixels, m_pixels), false);
Chris@929 250 }
Chris@929 251
Chris@1180 252 void
Chris@1180 253 LevelPanToolButton::enterEvent(QEvent *e)
Chris@1180 254 {
Chris@1180 255 QToolButton::enterEvent(e);
Chris@1180 256 emit mouseEntered();
Chris@1180 257 }
Chris@932 258
Chris@1180 259 void
Chris@1180 260 LevelPanToolButton::leaveEvent(QEvent *e)
Chris@1180 261 {
Chris@1180 262 QToolButton::enterEvent(e);
Chris@1180 263 emit mouseLeft();
Chris@1180 264 }
Chris@1180 265
Chris@1180 266