Chris@929: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ Chris@929: Chris@929: /* Chris@929: Sonic Visualiser Chris@929: An audio file viewer and annotation editor. Chris@929: Centre for Digital Music, Queen Mary, University of London. Chris@929: Chris@929: This program is free software; you can redistribute it and/or Chris@929: modify it under the terms of the GNU General Public License as Chris@929: published by the Free Software Foundation; either version 2 of the Chris@929: License, or (at your option) any later version. See the file Chris@929: COPYING included with this distribution for more information. Chris@929: */ Chris@929: Chris@929: #include "LevelPanToolButton.h" Chris@929: #include "LevelPanWidget.h" Chris@929: Chris@929: #include Chris@929: #include Chris@929: #include Chris@1300: #include Chris@936: #include Chris@936: #include Chris@1589: #include Chris@929: Chris@1300: #include "base/Debug.h" Chris@1589: #include "base/AudioLevel.h" Chris@1589: #include "MenuTitle.h" Chris@1300: Chris@929: #include Chris@929: using std::cerr; Chris@929: using std::endl; Chris@929: Chris@929: LevelPanToolButton::LevelPanToolButton(QWidget *parent) : Chris@929: QToolButton(parent), Chris@930: m_pixels(32), Chris@942: m_pixelsBig(32 * 3), Chris@930: m_muted(false), Chris@1589: m_savedLevel(1.f), Chris@1589: m_provideContextMenu(true), Chris@1589: m_lastContextMenu(nullptr) Chris@929: { Chris@929: m_lpw = new LevelPanWidget(); Chris@929: Chris@929: connect(m_lpw, SIGNAL(levelChanged(float)), this, SIGNAL(levelChanged(float))); Chris@930: connect(m_lpw, SIGNAL(levelChanged(float)), this, SLOT(selfLevelChanged(float))); Chris@929: Chris@929: connect(m_lpw, SIGNAL(panChanged(float)), this, SIGNAL(panChanged(float))); Chris@932: connect(m_lpw, SIGNAL(panChanged(float)), this, SLOT(update())); Chris@930: Chris@930: connect(this, SIGNAL(clicked(bool)), this, SLOT(selfClicked())); Chris@929: Chris@929: QMenu *menu = new QMenu(); Chris@929: QWidgetAction *wa = new QWidgetAction(menu); Chris@929: wa->setDefaultWidget(m_lpw); Chris@929: menu->addAction(wa); Chris@929: Chris@936: setPopupMode(InstantPopup); Chris@929: setMenu(menu); Chris@1191: setToolTip(tr("Click to adjust level and pan")); Chris@929: Chris@932: setImageSize(m_pixels); Chris@942: setBigImageSize(m_pixelsBig); Chris@1589: Chris@1589: setContextMenuPolicy(Qt::CustomContextMenu); Chris@1589: connect(this, SIGNAL(customContextMenuRequested(const QPoint &)), Chris@1589: this, SLOT(contextMenuRequested(const QPoint &))); Chris@929: } Chris@929: Chris@929: LevelPanToolButton::~LevelPanToolButton() Chris@929: { Chris@1589: delete m_lastContextMenu; Chris@929: } Chris@929: Chris@1200: void Chris@1300: LevelPanToolButton::mousePressEvent(QMouseEvent *e) Chris@1300: { Chris@1300: if (e->button() == Qt::MidButton || Chris@1300: ((e->button() == Qt::LeftButton) && Chris@1300: (e->modifiers() & Qt::ControlModifier))) { Chris@1300: m_lpw->setToDefault(); Chris@1300: e->accept(); Chris@1300: } else { Chris@1300: QToolButton::mousePressEvent(e); Chris@1300: } Chris@1300: } Chris@1300: Chris@1300: void Chris@1200: LevelPanToolButton::wheelEvent(QWheelEvent *e) Chris@1200: { Chris@1200: m_lpw->wheelEvent(e); Chris@1200: } Chris@1200: Chris@929: float Chris@929: LevelPanToolButton::getLevel() const Chris@929: { Chris@929: return m_lpw->getLevel(); Chris@929: } Chris@929: Chris@929: float Chris@929: LevelPanToolButton::getPan() const Chris@929: { Chris@929: return m_lpw->getPan(); Chris@929: } Chris@929: Chris@940: bool Chris@940: LevelPanToolButton::includesMute() const Chris@940: { Chris@940: return m_lpw->includesMute(); Chris@940: } Chris@940: Chris@929: void Chris@929: LevelPanToolButton::setImageSize(int pixels) Chris@929: { Chris@929: m_pixels = pixels; Chris@932: Chris@932: QPixmap px(m_pixels, m_pixels); Chris@932: px.fill(Qt::transparent); Chris@932: setIcon(px); Chris@942: } Chris@932: Chris@942: void Chris@1589: LevelPanToolButton::setProvideContextMenu(bool provide) Chris@1589: { Chris@1589: m_provideContextMenu = provide; Chris@1589: } Chris@1589: Chris@1589: void Chris@942: LevelPanToolButton::setBigImageSize(int pixels) Chris@942: { Chris@942: m_pixelsBig = pixels; Chris@942: Chris@942: m_lpw->setFixedWidth(m_pixelsBig); Chris@942: m_lpw->setFixedHeight(m_pixelsBig); Chris@929: } Chris@929: Chris@929: void Chris@929: LevelPanToolButton::setLevel(float level) Chris@929: { Chris@929: m_lpw->setLevel(level); Chris@932: update(); Chris@929: } Chris@929: Chris@929: void Chris@929: LevelPanToolButton::setPan(float pan) Chris@929: { Chris@929: m_lpw->setPan(pan); Chris@932: update(); Chris@930: } Chris@930: Chris@930: void Chris@1187: LevelPanToolButton::setMonitoringLevels(float left, float right) Chris@1187: { Chris@1187: m_lpw->setMonitoringLevels(left, right); Chris@1187: update(); Chris@1187: } Chris@1187: Chris@1187: void Chris@940: LevelPanToolButton::setIncludeMute(bool include) Chris@940: { Chris@940: m_lpw->setIncludeMute(include); Chris@940: update(); Chris@940: } Chris@940: Chris@940: void Chris@933: LevelPanToolButton::setEnabled(bool enabled) Chris@933: { Chris@933: m_lpw->setEnabled(enabled); Chris@933: QToolButton::setEnabled(enabled); Chris@933: } Chris@933: Chris@933: void Chris@930: LevelPanToolButton::selfLevelChanged(float level) Chris@930: { Chris@930: if (level > 0.f) { Chris@1266: m_muted = false; Chris@930: } else { Chris@1266: m_muted = true; Chris@1266: m_savedLevel = 1.f; Chris@930: } Chris@932: update(); Chris@930: } Chris@930: Chris@930: void Chris@930: LevelPanToolButton::selfClicked() Chris@930: { Chris@930: if (m_muted) { Chris@1266: m_muted = false; Chris@1266: m_lpw->setLevel(m_savedLevel); Chris@1266: emit levelChanged(m_savedLevel); Chris@930: } else { Chris@1266: m_savedLevel = m_lpw->getLevel(); Chris@1266: m_muted = true; Chris@1266: m_lpw->setLevel(0.f); Chris@1266: emit levelChanged(0.f); Chris@930: } Chris@932: update(); Chris@929: } Chris@929: Chris@929: void Chris@1589: LevelPanToolButton::contextMenuRequested(const QPoint &pos) Chris@1589: { Chris@1589: if (!m_provideContextMenu) { Chris@1589: return; Chris@1589: } Chris@1589: Chris@1589: delete m_lastContextMenu; Chris@1589: m_lastContextMenu = new QMenu; Chris@1589: auto m = m_lastContextMenu; Chris@1589: Chris@1589: QString title; Chris@1589: Chris@1589: if (m_muted) { Chris@1589: title = tr("Muted"); Chris@1589: } else { Chris@1589: // Pan is actually stereo balance in most applications... Chris@1589: auto level = AudioLevel::multiplier_to_dB(m_lpw->getLevel()); Chris@1589: auto pan = m_lpw->getPan(); Chris@1589: if (pan == 0) { Chris@1589: title = tr("Level: %1 dB - Balance: Middle").arg(level); Chris@1589: } else if (pan > 0) { Chris@1589: title = tr("Level: %1 dB - Balance: +%2").arg(level).arg(pan); Chris@1589: } else { Chris@1589: title = tr("Level: %1 dB - Balance: %2").arg(level).arg(pan); Chris@1589: } Chris@1589: } Chris@1589: Chris@1589: MenuTitle::addTitle(m, title); Chris@1589: Chris@1602: m->addAction(tr("&Reset to Default"), m_lpw, SLOT(setToDefault())); Chris@1589: Chris@1589: m->popup(mapToGlobal(pos)); Chris@1589: } Chris@1589: Chris@1589: void Chris@936: LevelPanToolButton::paintEvent(QPaintEvent *) Chris@929: { Chris@936: QStylePainter p(this); Chris@936: QStyleOptionToolButton opt; Chris@936: initStyleOption(&opt); Chris@936: opt.features &= (~QStyleOptionToolButton::HasMenu); Chris@936: p.drawComplexControl(QStyle::CC_ToolButton, opt); Chris@936: Chris@934: if (m_pixels >= height()) { Chris@934: setImageSize(height()-1); Chris@934: } Chris@936: Chris@932: double margin = (double(height()) - m_pixels) / 2.0; Chris@932: m_lpw->renderTo(this, QRectF(margin, margin, m_pixels, m_pixels), false); Chris@929: } Chris@929: Chris@1180: void Chris@1180: LevelPanToolButton::enterEvent(QEvent *e) Chris@1180: { Chris@1180: QToolButton::enterEvent(e); Chris@1180: emit mouseEntered(); Chris@1180: } Chris@932: Chris@1180: void Chris@1180: LevelPanToolButton::leaveEvent(QEvent *e) Chris@1180: { Chris@1180: QToolButton::enterEvent(e); Chris@1180: emit mouseLeft(); Chris@1180: } Chris@1180: Chris@1180: