Mercurial > hg > svgui
changeset 1592:1da52d5e6700
Merge from branch audio-source-refactor. Mostly handling changes to plugin ownership
author | Chris Cannam |
---|---|
date | Fri, 03 Apr 2020 12:12:47 +0100 |
parents | 26e80a450e74 (diff) 11660e0c896f (current diff) |
children | 32171776fcc9 5aef3f53a425 |
files | |
diffstat | 19 files changed, 471 insertions(+), 50 deletions(-) [+] |
line wrap: on
line diff
--- a/files.pri Fri Mar 20 16:31:23 2020 +0000 +++ b/files.pri Fri Apr 03 12:12:47 2020 +0100 @@ -68,6 +68,7 @@ widgets/LevelPanToolButton.h \ widgets/LevelPanWidget.h \ widgets/ListInputDialog.h \ + widgets/MenuTitle.h \ widgets/MIDIFileImportDialog.h \ widgets/ModelDataTableDialog.h \ widgets/NotifyingCheckBox.h \
--- a/layer/Layer.cpp Fri Mar 20 16:31:23 2020 +0000 +++ b/layer/Layer.cpp Fri Apr 03 12:12:47 2020 +0100 @@ -89,6 +89,12 @@ m_presentationName = name; } +bool +Layer::isPresentationNameSet() const +{ + return (m_presentationName != ""); +} + QString Layer::getLayerPresentationName() const {
--- a/layer/Layer.h Fri Mar 20 16:31:23 2020 +0000 +++ b/layer/Layer.h Fri Apr 03 12:12:47 2020 +0100 @@ -159,6 +159,8 @@ virtual void setPresentationName(QString name); + virtual bool isPresentationNameSet() const; + virtual QString getLayerPresentationName() const; virtual QPixmap getLayerPresentationPixmap(QSize) const { return QPixmap(); }
--- a/view/Pane.cpp Fri Mar 20 16:31:23 2020 +0000 +++ b/view/Pane.cpp Fri Apr 03 12:12:47 2020 +0100 @@ -32,6 +32,7 @@ #include "layer/LayerFactory.h" #include "layer/FlexiNoteLayer.h" +#include "widgets/MenuTitle.h" //!!! ugh #include "data/model/WaveFileModel.h" @@ -46,6 +47,7 @@ #include <QTextStream> #include <QMimeData> #include <QApplication> +#include <QMenu> #include <iostream> #include <cmath> @@ -54,6 +56,7 @@ #include <QFrame> #include <QGridLayout> #include <QPushButton> + #include "widgets/Thumbwheel.h" #include "widgets/Panner.h" #include "widgets/RangeInputDialog.h" @@ -86,6 +89,7 @@ m_hthumb(nullptr), m_vthumb(nullptr), m_reset(nullptr), + m_lastVerticalPannerContextMenu(nullptr), m_mouseInWidget(false), m_playbackFrameMoveScheduled(false), m_playbackFrameMoveTo(0) @@ -102,6 +106,11 @@ cerr << "Pane::Pane(" << this << ") returning" << endl; } +Pane::~Pane() +{ + delete m_lastVerticalPannerContextMenu; +} + void Pane::updateHeadsUpDisplay() { @@ -149,6 +158,11 @@ connect(m_vpan, SIGNAL(mouseEntered()), this, SLOT(mouseEnteredWidget())); connect(m_vpan, SIGNAL(mouseLeft()), this, SLOT(mouseLeftWidget())); + // Panner doesn't provide its own context menu + m_vpan->setContextMenuPolicy(Qt::CustomContextMenu); + connect(m_vpan, SIGNAL(customContextMenuRequested(const QPoint &)), + this, SLOT(verticalPannerContextMenuRequested(const QPoint &))); + m_vthumb = new Thumbwheel(Qt::Vertical); m_vthumb->setObjectName(tr("Vertical Zoom")); m_vthumb->setCursor(Qt::ArrowCursor); @@ -2540,6 +2554,44 @@ } void +Pane::verticalPannerContextMenuRequested(const QPoint &pos) +{ + Panner *panner = qobject_cast<Panner *>(sender()); + if (!panner) { + return; + } + + double vmin, vmax, dmin, dmax; + QString unit; + if (!getTopLayerDisplayExtents(vmin, vmax, dmin, dmax, &unit)) { + return; + } + + delete m_lastVerticalPannerContextMenu; + QMenu *m = new QMenu; + m_lastVerticalPannerContextMenu = m; + + MenuTitle::addTitle(m, tr("Vertical Range: %1 - %2 %3") + .arg(dmin).arg(dmax).arg(unit)); + + m->addAction(tr("&Edit..."), + [=]() { + editVerticalPannerExtents(); + }); + m->addAction(tr("&Reset to Default"), + [=]() { + if (m_vthumb) { + // This determines the "size" of the panner box + m_vthumb->resetToDefault(); + } + panner->resetToDefault(); + }); + + m->popup(panner->mapToGlobal(pos)); + m_lastVerticalPannerContextMenu = m; +} + +void Pane::editVerticalPannerExtents() { if (!m_vpan || !m_manager || !m_manager->getZoomWheelsEnabled()) return; @@ -2552,7 +2604,7 @@ } RangeInputDialog dialog(tr("Enter new range"), - tr("New vertical display range, from %1 to %2 %4:") + tr("New vertical display range, from %1 to %2 %3:") .arg(vmin).arg(vmax).arg(unit), unit, float(vmin), float(vmax), this); dialog.setRange(float(dmin), float(dmax));
--- a/view/Pane.h Fri Mar 20 16:31:23 2020 +0000 +++ b/view/Pane.h Fri Apr 03 12:12:47 2020 +0100 @@ -30,6 +30,7 @@ class Panner; class NotifyingPushButton; class KeyReference; +class QMenu; class Pane : public View { @@ -37,6 +38,8 @@ public: Pane(QWidget *parent = 0); + virtual ~Pane(); + virtual QString getPropertyContainerIconName() const override { return "pane"; } virtual bool shouldIlluminateLocalFeatures(const Layer *layer, @@ -91,11 +94,12 @@ virtual void modelAlignmentCompletionChanged(ModelId) override; // local slots, not overrides - virtual void horizontalThumbwheelMoved(int value); - virtual void verticalThumbwheelMoved(int value); - virtual void verticalZoomChanged(); - virtual void verticalPannerMoved(float x, float y, float w, float h); - virtual void editVerticalPannerExtents(); + void horizontalThumbwheelMoved(int value); + void verticalThumbwheelMoved(int value); + void verticalZoomChanged(); + void verticalPannerMoved(float x, float y, float w, float h); + void verticalPannerContextMenuRequested(const QPoint &); + void editVerticalPannerExtents(); virtual void layerParametersChanged() override; @@ -207,6 +211,7 @@ Thumbwheel *m_hthumb; Thumbwheel *m_vthumb; NotifyingPushButton *m_reset; + QMenu *m_lastVerticalPannerContextMenu; bool m_mouseInWidget;
--- a/view/PaneStack.cpp Fri Mar 20 16:31:23 2020 +0000 +++ b/view/PaneStack.cpp Fri Apr 03 12:12:47 2020 +0100 @@ -146,6 +146,8 @@ properties = new PropertyStack(frame, pane); connect(properties, SIGNAL(propertyContainerSelected(View *, PropertyContainer *)), this, SLOT(propertyContainerSelected(View *, PropertyContainer *))); + connect(properties, SIGNAL(propertyContainerContextMenuRequested(View *, PropertyContainer *, QPoint)), + this, SLOT(propertyContainerContextMenuRequested(View *, PropertyContainer *, QPoint))); connect(properties, SIGNAL(viewSelected(View *)), this, SLOT(viewSelected(View *))); connect(properties, SIGNAL(contextHelpChanged(const QString &)), @@ -588,6 +590,23 @@ } void +PaneStack::propertyContainerContextMenuRequested(View *client, + PropertyContainer *pc, + QPoint pos) +{ + Pane *pane = dynamic_cast<Pane *>(client); + Layer *layer = dynamic_cast<Layer *>(pc); + + if (pane) { + if (layer) { + emit layerPropertiesRightButtonMenuRequested(pane, layer, pos); + } else { + emit panePropertiesRightButtonMenuRequested(pane, pos); + } + } +} + +void PaneStack::viewSelected(View *v) { Pane *p = dynamic_cast<Pane *>(v); @@ -607,7 +626,7 @@ { Pane *pane = dynamic_cast<Pane *>(sender()); if (!pane) return; - emit rightButtonMenuRequested(pane, position); + emit paneRightButtonMenuRequested(pane, position); } void
--- a/view/PaneStack.h Fri Mar 20 16:31:23 2020 +0000 +++ b/view/PaneStack.h Fri Apr 03 12:12:47 2020 +0100 @@ -92,7 +92,9 @@ signals: void currentPaneChanged(Pane *pane); void currentLayerChanged(Pane *pane, Layer *layer); - void rightButtonMenuRequested(Pane *pane, QPoint position); + void paneRightButtonMenuRequested(Pane *pane, QPoint position); + void panePropertiesRightButtonMenuRequested(Pane *, QPoint); + void layerPropertiesRightButtonMenuRequested(Pane *, Layer *, QPoint); void propertyStacksResized(int width); void propertyStacksResized(); void contextHelpChanged(const QString &); @@ -115,6 +117,8 @@ void propertyContainerAdded(PropertyContainer *); void propertyContainerRemoved(PropertyContainer *); void propertyContainerSelected(View *client, PropertyContainer *); + void propertyContainerContextMenuRequested(View *, PropertyContainer *, + QPoint); void viewSelected(View *v); void paneInteractedWith(); void rightButtonMenuRequested(QPoint);
--- a/widgets/AudioDial.cpp Fri Mar 20 16:31:23 2020 +0000 +++ b/widgets/AudioDial.cpp Fri Apr 03 12:12:47 2020 +0100 @@ -49,9 +49,12 @@ #include <QMouseEvent> #include <QPaintEvent> #include <QInputDialog> +#include <QMenu> #include "base/Profiler.h" +#include "MenuTitle.h" + @@ -68,8 +71,6 @@ #define AUDIO_DIAL_RANGE (AUDIO_DIAL_MAX - AUDIO_DIAL_MIN) -//static int dialsExtant = 0; - // Constructor. AudioDial::AudioDial(QWidget *parent) : @@ -81,11 +82,15 @@ m_mappedValue(0), m_noMappedUpdate(false), m_showTooltip(true), + m_provideContextMenu(true), + m_lastContextMenu(nullptr), m_rangeMapper(nullptr) { m_mouseDial = false; m_mousePressed = false; -// ++dialsExtant; + setContextMenuPolicy(Qt::CustomContextMenu); + connect(this, SIGNAL(customContextMenuRequested(const QPoint &)), + this, SLOT(contextMenuRequested(const QPoint &))); } @@ -93,14 +98,39 @@ AudioDial::~AudioDial (void) { delete m_rangeMapper; -// --dialsExtant; + delete m_lastContextMenu; } +void AudioDial::contextMenuRequested(const QPoint &pos) +{ + if (!m_provideContextMenu) { + return; + } + + delete m_lastContextMenu; + m_lastContextMenu = new QMenu; + auto m = m_lastContextMenu; + + if (m_title == "") { + MenuTitle::addTitle(m, tr("Dial")); + } else { + MenuTitle::addTitle(m, m_title); + } + + m->addAction(tr("&Edit..."), + [=]() { + edit(); + }); + m->addAction(tr("&Reset to Default"), + [=]() { + setToDefault(); + }); + + m->popup(mapToGlobal(pos)); +} void AudioDial::setRangeMapper(RangeMapper *mapper) { -// cerr << "AudioDial[" << this << "][\"" << objectName() << "\"::setRangeMapper(" << mapper << ") [current is " << m_rangeMapper << "] (have " << dialsExtant << " dials extant)" << endl; - if (m_rangeMapper == mapper) return; if (!m_rangeMapper && mapper) { @@ -422,6 +452,12 @@ } +void AudioDial::setProvideContextMenu(bool provide) +{ + m_provideContextMenu = provide; +} + + double AudioDial::mappedValue() const { if (m_rangeMapper) { @@ -442,31 +478,36 @@ } } + QString name = objectName(); + QString label; + if (m_rangeMapper) { + label = m_rangeMapper->getLabel(value); + } + QString text; + if (label != "") { + if (name != "") { + text = tr("%1: %2").arg(name).arg(label); + } else { + text = label; + } + } else { + QString unit = ""; + if (m_rangeMapper) { + unit = m_rangeMapper->getUnit(); + } + if (name != "") { + text = tr("%1: %2%3").arg(name).arg(m_mappedValue).arg(unit); + } else { + text = tr("%2%3").arg(m_mappedValue).arg(unit); + } + } + + m_title = text; + if (m_showTooltip) { - QString name = objectName(); - QString label; - if (m_rangeMapper) { - label = m_rangeMapper->getLabel(value); - } - QString text; - if (label != "") { - if (name != "") { - text = tr("%1: %2").arg(name).arg(label); - } else { - text = label; - } - } else { - QString unit = ""; - if (m_rangeMapper) { - unit = m_rangeMapper->getUnit(); - } - if (name != "") { - text = tr("%1: %2%3").arg(name).arg(m_mappedValue).arg(unit); - } else { - text = tr("%2%3").arg(m_mappedValue).arg(unit); - } - } setToolTip(text); + } else { + setToolTip(""); } } @@ -509,6 +550,11 @@ return; } + edit(); +} + +void AudioDial::edit() +{ bool ok = false; if (m_rangeMapper) {
--- a/widgets/AudioDial.h Fri Mar 20 16:31:23 2020 +0000 +++ b/widgets/AudioDial.h Fri Apr 03 12:12:47 2020 +0100 @@ -42,6 +42,7 @@ #include <map> class RangeMapper; +class QMenu; /** * AudioDial is a nicer-looking QDial that by default reacts to mouse @@ -78,6 +79,7 @@ int defaultValue() const { return m_defaultValue; } void setShowToolTip(bool show); + void setProvideContextMenu(bool provide); signals: void mouseEntered(); @@ -113,6 +115,8 @@ void setToDefault(); + void edit(); + protected: void drawTick(QPainter &paint, double angle, int size, bool internal); void paintEvent(QPaintEvent *) override; @@ -127,6 +131,7 @@ protected slots: void updateMappedValue(int value); + void contextMenuRequested(const QPoint &); private: QColor m_knobColor; @@ -143,6 +148,11 @@ QPoint m_posMouse; bool m_showTooltip; + bool m_provideContextMenu; + + QString m_title; + + QMenu *m_lastContextMenu; RangeMapper *m_rangeMapper; };
--- a/widgets/LevelPanToolButton.cpp Fri Mar 20 16:31:23 2020 +0000 +++ b/widgets/LevelPanToolButton.cpp Fri Apr 03 12:12:47 2020 +0100 @@ -21,8 +21,11 @@ #include <QMouseEvent> #include <QStylePainter> #include <QStyleOptionToolButton> +#include <QMenu> #include "base/Debug.h" +#include "base/AudioLevel.h" +#include "MenuTitle.h" #include <iostream> using std::cerr; @@ -33,7 +36,9 @@ m_pixels(32), m_pixelsBig(32 * 3), m_muted(false), - m_savedLevel(1.f) + m_savedLevel(1.f), + m_provideContextMenu(true), + m_lastContextMenu(nullptr) { m_lpw = new LevelPanWidget(); @@ -56,10 +61,15 @@ setImageSize(m_pixels); setBigImageSize(m_pixelsBig); + + setContextMenuPolicy(Qt::CustomContextMenu); + connect(this, SIGNAL(customContextMenuRequested(const QPoint &)), + this, SLOT(contextMenuRequested(const QPoint &))); } LevelPanToolButton::~LevelPanToolButton() { + delete m_lastContextMenu; } void @@ -110,6 +120,12 @@ } void +LevelPanToolButton::setProvideContextMenu(bool provide) +{ + m_provideContextMenu = provide; +} + +void LevelPanToolButton::setBigImageSize(int pixels) { m_pixelsBig = pixels; @@ -182,6 +198,44 @@ } void +LevelPanToolButton::contextMenuRequested(const QPoint &pos) +{ + if (!m_provideContextMenu) { + return; + } + + delete m_lastContextMenu; + m_lastContextMenu = new QMenu; + auto m = m_lastContextMenu; + + QString title; + + if (m_muted) { + title = tr("Muted"); + } else { + // Pan is actually stereo balance in most applications... + auto level = AudioLevel::multiplier_to_dB(m_lpw->getLevel()); + auto pan = m_lpw->getPan(); + if (pan == 0) { + title = tr("Level: %1 dB - Balance: Middle").arg(level); + } else if (pan > 0) { + title = tr("Level: %1 dB - Balance: +%2").arg(level).arg(pan); + } else { + title = tr("Level: %1 dB - Balance: %2").arg(level).arg(pan); + } + } + + MenuTitle::addTitle(m, title); + + m->addAction(tr("&Reset to Default"), + [=]() { + m_lpw->setToDefault(); + }); + + m->popup(mapToGlobal(pos)); +} + +void LevelPanToolButton::paintEvent(QPaintEvent *) { QStylePainter p(this);
--- a/widgets/LevelPanToolButton.h Fri Mar 20 16:31:23 2020 +0000 +++ b/widgets/LevelPanToolButton.h Fri Apr 03 12:12:47 2020 +0100 @@ -18,6 +18,7 @@ #include <QToolButton> class LevelPanWidget; +class QMenu; class LevelPanToolButton : public QToolButton { @@ -37,6 +38,9 @@ bool includesMute() const; void setImageSize(int pixels); + + /// Specify whether a right-click context menu is provided + void setProvideContextMenu(bool); void setBigImageSize(int pixels); @@ -55,6 +59,9 @@ void setEnabled(bool enabled); +protected slots: + void contextMenuRequested(const QPoint &); + signals: void levelChanged(float); void panChanged(float); @@ -78,6 +85,8 @@ int m_pixelsBig; bool m_muted; float m_savedLevel; + bool m_provideContextMenu; + QMenu *m_lastContextMenu; }; #endif
--- a/widgets/LevelPanWidget.h Fri Mar 20 16:31:23 2020 +0000 +++ b/widgets/LevelPanWidget.h Fri Apr 03 12:12:47 2020 +0100 @@ -71,7 +71,7 @@ // public so it can be called from LevelPanToolButton (ew) void wheelEvent(QWheelEvent *ev) override; - + signals: void levelChanged(float); // range [0,1] void panChanged(float); // range [-1,1]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/widgets/MenuTitle.h Fri Apr 03 12:12:47 2020 +0100 @@ -0,0 +1,56 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Sonic Visualiser + An audio file viewer and annotation editor. + Centre for Digital Music, Queen Mary, University of London. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + +#ifndef SV_MENU_TITLE_H +#define SV_MENU_TITLE_H + +#include "view/ViewManager.h" + +#include <QStyle> +#include <QWidgetAction> +#include <QLabel> +#include <QApplication> +#include <QMenu> + +class MenuTitle +{ +public: + static void addTitle(QMenu *m, QString text) { + +#ifdef Q_OS_LINUX + static int leftIndent = + (ViewManager::scalePixelSize(8) + + qApp->style()->pixelMetric(QStyle::PM_SmallIconSize)); +#else +#ifdef Q_OS_WIN + static int leftIndent = + (9 + qApp->style()->pixelMetric(QStyle::PM_SmallIconSize)); +#else + static int leftIndent = 16; +#endif +#endif + + QWidgetAction *wa = new QWidgetAction(m); + QLabel *title = new QLabel; + title->setText(QObject::tr("<b>%1</b>") + .arg(XmlExportable::encodeEntities(text))); + title->setMargin(ViewManager::scalePixelSize(3)); + title->setIndent(leftIndent); + wa->setDefaultWidget(title); + m->addAction(wa); + m->addSeparator(); + } +}; + +#endif
--- a/widgets/PropertyBox.cpp Fri Mar 20 16:31:23 2020 +0000 +++ b/widgets/PropertyBox.cpp Fri Apr 03 12:12:47 2020 +0100 @@ -29,6 +29,7 @@ #include "LevelPanWidget.h" #include "LevelPanToolButton.h" #include "WidgetScale.h" +#include "MenuTitle.h" #include "NotifyingCheckBox.h" #include "NotifyingComboBox.h" @@ -48,6 +49,7 @@ #include <QColorDialog> #include <QInputDialog> #include <QDir> +#include <QMenu> #include <cassert> #include <iostream> @@ -58,7 +60,8 @@ PropertyBox::PropertyBox(PropertyContainer *container) : m_container(container), m_showButton(nullptr), - m_playButton(nullptr) + m_playButton(nullptr), + m_lastContextMenu(nullptr) { #ifdef DEBUG_PROPERTY_BOX SVDEBUG << "PropertyBox[" << this << "(\"" << @@ -118,6 +121,7 @@ #ifdef DEBUG_PROPERTY_BOX SVDEBUG << "PropertyBox[" << this << "]::~PropertyBox" << endl; #endif + delete m_lastContextMenu; } void @@ -328,6 +332,10 @@ this, SLOT(mouseLeftWidget())); button->setToolTip(propertyLabel); + button->setContextMenuPolicy(Qt::CustomContextMenu); + connect(button, SIGNAL(customContextMenuRequested(const QPoint &)), + this, SLOT(contextMenuRequested(const QPoint &))); + if (existing) { groupLayout->replaceWidget(existing, button); delete existing; @@ -422,6 +430,10 @@ cb->setToolTip(propertyLabel); + cb->setContextMenuPolicy(Qt::CustomContextMenu); + connect(cb, SIGNAL(customContextMenuRequested(const QPoint &)), + this, SLOT(contextMenuRequested(const QPoint &))); + if (existing) { groupLayout->replaceWidget(existing, cb); delete existing; @@ -535,6 +547,11 @@ this, SLOT(mouseLeftWidget())); cb->setToolTip(propertyLabel); + + cb->setContextMenuPolicy(Qt::CustomContextMenu); + connect(cb, SIGNAL(customContextMenuRequested(const QPoint &)), + this, SLOT(contextMenuRequested(const QPoint &))); + groupLayout->addWidget(cb, 0, groupLayout->columnCount()); m_propertyControllers[name] = cb; } else if (existing != cb) { @@ -667,6 +684,46 @@ } void +PropertyBox::contextMenuRequested(const QPoint &pos) +{ + QObject *obj = sender(); + QString name = obj->objectName(); + + QString label = m_container->getPropertyLabel(name); + int min = 0, max = 0, value = 0, deflt = 0; + value = m_container->getPropertyRangeAndValue(name, &min, &max, &deflt); + + delete m_lastContextMenu; + QMenu *m = new QMenu; + m_lastContextMenu = m; + + if (auto button = qobject_cast<QAbstractButton *>(obj)) { + if (value > 0) { + MenuTitle::addTitle(m, tr("%1: On").arg(label)); + } else { + MenuTitle::addTitle(m, tr("%1: Off").arg(label)); + } + + m->addAction(tr("&Reset to Default"), + [=]() { + button->setChecked(deflt > 0); + }); + + } else if (auto cb = qobject_cast<QComboBox *>(obj)) { + MenuTitle::addTitle(m, tr("%1: %2").arg(label).arg(cb->itemText(value))); + m->addAction(tr("&Reset to Default"), + [=]() { + cb->setCurrentIndex(deflt); + }); + } else { + // AudioDial has its own context menu, we don't handle it here + return; + } + + m->popup(qobject_cast<QWidget *>(sender())->mapToGlobal(pos)); +} + +void PropertyBox::playAudibleChanged(bool audible) { m_playButton->setChecked(audible);
--- a/widgets/PropertyBox.h Fri Mar 20 16:31:23 2020 +0000 +++ b/widgets/PropertyBox.h Fri Apr 03 12:12:47 2020 +0100 @@ -29,6 +29,7 @@ class LEDButton; class QToolButton; class NotifyingPushButton; +class QMenu; class PropertyBox : public QFrame { @@ -68,6 +69,8 @@ void mouseEnteredWidget(); void mouseLeftWidget(); + void contextMenuRequested(const QPoint &); + protected: void updatePropertyEditor(PropertyContainer::PropertyName, bool rangeChanged = false); @@ -81,6 +84,7 @@ QVBoxLayout *m_mainBox; LEDButton *m_showButton; QToolButton *m_playButton; + QMenu *m_lastContextMenu; std::map<QString, QGridLayout *> m_groupLayouts; std::map<QString, QWidget *> m_propertyControllers; };
--- a/widgets/PropertyStack.cpp Fri Mar 20 16:31:23 2020 +0000 +++ b/widgets/PropertyStack.cpp Fri Apr 03 12:12:47 2020 +0100 @@ -45,6 +45,10 @@ connect(bar, SIGNAL(mouseLeft()), this, SLOT(mouseLeftTabBar())); connect(bar, SIGNAL(activeTabClicked()), this, SLOT(activeTabClicked())); + bar->setContextMenuPolicy(Qt::CustomContextMenu); + connect(bar, SIGNAL(customContextMenuRequested(const QPoint &)), + this, SLOT(tabBarContextMenuRequested(const QPoint &))); + setTabBar(bar); setElideMode(Qt::ElideNone); @@ -164,6 +168,19 @@ blockSignals(false); } +void +PropertyStack::tabBarContextMenuRequested(const QPoint &pos) +{ + int tab = tabBar()->tabAt(pos); + if (!in_range_for(m_boxes, tab)) { + return; + } + + emit propertyContainerContextMenuRequested(m_client, + m_boxes[tab]->getContainer(), + mapToGlobal(pos)); +} + bool PropertyStack::containsContainer(PropertyContainer *pc) const {
--- a/widgets/PropertyStack.h Fri Mar 20 16:31:23 2020 +0000 +++ b/widgets/PropertyStack.h Fri Apr 03 12:12:47 2020 +0100 @@ -40,6 +40,9 @@ signals: void viewSelected(View *client); void propertyContainerSelected(View *client, PropertyContainer *container); + void propertyContainerContextMenuRequested(View *client, + PropertyContainer *container, + QPoint pos); void contextHelpChanged(const QString &); public slots: @@ -54,6 +57,7 @@ void mouseEnteredTabBar(); void mouseLeftTabBar(); void activeTabClicked(); + void tabBarContextMenuRequested(const QPoint &); protected slots: void selectedContainerChanged(int);
--- a/widgets/Thumbwheel.cpp Fri Mar 20 16:31:23 2020 +0000 +++ b/widgets/Thumbwheel.cpp Fri Apr 03 12:12:47 2020 +0100 @@ -24,6 +24,9 @@ #include <QInputDialog> #include <QPainter> #include <QPainterPath> +#include <QMenu> + +#include "MenuTitle.h" #include <cmath> #include <iostream> @@ -46,13 +49,48 @@ m_atDefault(true), m_clickRotation(m_rotation), m_showTooltip(true), + m_provideContextMenu(true), + m_lastContextMenu(nullptr), m_rangeMapper(nullptr) { + setContextMenuPolicy(Qt::CustomContextMenu); + connect(this, SIGNAL(customContextMenuRequested(const QPoint &)), + this, SLOT(contextMenuRequested(const QPoint &))); } Thumbwheel::~Thumbwheel() { delete m_rangeMapper; + delete m_lastContextMenu; +} + +void +Thumbwheel::contextMenuRequested(const QPoint &pos) +{ + if (!m_provideContextMenu) { + return; + } + + delete m_lastContextMenu; + m_lastContextMenu = new QMenu; + auto m = m_lastContextMenu; + + if (m_title == "") { + MenuTitle::addTitle(m, tr("Thumbwheel")); + } else { + MenuTitle::addTitle(m, m_title); + } + + m->addAction(tr("&Edit..."), + [=]() { + edit(); + }); + m->addAction(tr("&Reset to Default"), + [=]() { + resetToDefault(); + }); + + m->popup(mapToGlobal(pos)); } void @@ -81,6 +119,12 @@ } void +Thumbwheel::setProvideContextMenu(bool provide) +{ + m_provideContextMenu = provide; +} + +void Thumbwheel::setMinimumValue(int min) { if (m_min == min) return; @@ -183,7 +227,11 @@ m_rotation = float(m_value - m_min) / float(m_max - m_min); m_cache = QImage(); - if (isVisible()) update(); + + if (isVisible()) { + update(); + updateTitle(); + } } void @@ -223,17 +271,30 @@ } } + updateTitle(); +} + +void +Thumbwheel::updateTitle() +{ + QString name = objectName(); + QString unit = ""; + QString text; + double mappedValue = getMappedValue(); + + if (m_rangeMapper) unit = m_rangeMapper->getUnit(); + if (name != "") { + text = tr("%1: %2%3").arg(name).arg(mappedValue).arg(unit); + } else { + text = tr("%2%3").arg(mappedValue).arg(unit); + } + + m_title = text; + if (m_showTooltip) { - QString name = objectName(); - QString unit = ""; - QString text; - if (m_rangeMapper) unit = m_rangeMapper->getUnit(); - if (name != "") { - text = tr("%1: %2%3").arg(name).arg(m_mappedValue).arg(unit); - } else { - text = tr("%2%3").arg(m_mappedValue).arg(unit); - } setToolTip(text); + } else { + setToolTip(""); } } @@ -323,6 +384,12 @@ return; } + edit(); +} + +void +Thumbwheel::edit() +{ bool ok = false; if (m_rangeMapper) {
--- a/widgets/Thumbwheel.h Fri Mar 20 16:31:23 2020 +0000 +++ b/widgets/Thumbwheel.h Fri Apr 03 12:12:47 2020 +0100 @@ -24,6 +24,7 @@ #include "WheelCounter.h" class RangeMapper; +class QMenu; class Thumbwheel : public QWidget { @@ -46,6 +47,7 @@ double getMappedValue() const; void setShowToolTip(bool show); + void setProvideContextMenu(bool provide); QSize sizeHint() const override; @@ -66,9 +68,12 @@ void setMappedValue(double mappedValue); void scroll(bool up); void resetToDefault(); + void edit(); protected slots: void updateMappedValue(int value); + void updateTitle(); + void contextMenuRequested(const QPoint &); protected: void mousePressEvent(QMouseEvent *e) override; @@ -96,6 +101,9 @@ QPoint m_clickPos; float m_clickRotation; bool m_showTooltip; + bool m_provideContextMenu; + QString m_title; + QMenu *m_lastContextMenu; RangeMapper *m_rangeMapper; QImage m_cache; WheelCounter m_wheelCounter;