Add BarModelEditor and improve layouts

Add the new class `BarModelEditor` which is intended to become a new way
to adjust values of float models.

Simplify the layout in `LadspaMatrixControlDialog` by removing some
nested layouts. Remove the "Parameters" column.

Adjust `LadspaMatrixControlView` to implement the following changes:
* Show the name of the control next to toggle buttons (`LedCheckBox`).
* Use the new `BarModelEditor` for integer and float types.
* SHow the name of the control next to time based parameters that use
`TempoSyncKnob`.

The names are shown so that the "Parameters" column can be removed.

Technical details
------------------
The class `LadspaMatrixControlDialog` now creates a widget that contains
the matrix layout with the controls. This widget is then added to a
scroll area. The layout is populated in the new method
`arrangeControls`.

Add some helper methods to `LadspaMatrixControlDialog` which retrieve
the `LadspaControls` instance and the number of channels.

Add the implementation of `BarModelEditor` to `src/gui/CMakeLists.txt`.

TODOs
------
Extract common code out of the `Knob` class so that it can be reused by
`BarModelEditor`.
This commit is contained in:
Michael Gregorius
2023-07-08 12:11:46 +02:00
parent 1295deb3a8
commit 610fb3442f
6 changed files with 327 additions and 66 deletions

View File

@@ -95,6 +95,7 @@ SET(LMMS_SRCS
gui/widgets/AutomatableButton.cpp
gui/widgets/AutomatableSlider.cpp
gui/widgets/BarModelEditor.cpp
gui/widgets/CPULoadWidget.cpp
gui/widgets/CaptionMenu.cpp
gui/widgets/ComboBox.cpp

View File

@@ -29,10 +29,12 @@
#include "LadspaControl.h"
#include "LadspaBase.h"
#include "BarModelEditor.h"
#include "LedCheckBox.h"
#include "TempoSyncKnob.h"
#include <QLayout>
#include <QLabel>
namespace lmms::gui
@@ -51,12 +53,13 @@ LadspaMatrixControlView::LadspaMatrixControlView(QWidget * parent,
Knob * knob = nullptr;
buffer_data_t dataType = m_ladspaControl->port()->data_type;
QString const name = m_ladspaControl->port()->name;
switch (dataType)
{
case TOGGLED:
{
LedCheckBox * toggle = new LedCheckBox(
"", this, QString(), LedCheckBox::Green);
name, this, QString(), LedCheckBox::Green);
toggle->setModel(m_ladspaControl->toggledModel());
layout->addWidget(toggle);
setFixedSize(toggle->width(), toggle->height());
@@ -65,16 +68,20 @@ LadspaMatrixControlView::LadspaMatrixControlView(QWidget * parent,
case INTEGER:
case FLOATING:
knob = new Knob(knobBright_26, this, m_ladspaControl->port()->name);
/*knob = new Knob(knobBright_26, this, name);
knob->setModel(m_ladspaControl->knobModel());
knob->setLabel(name);*/
layout->addWidget(new BarModelEditor(name, m_ladspaControl->knobModel(), this));
break;
case TIME:
knob = new TempoSyncKnob(knobBright_26, this, m_ladspaControl->port()->name);
knob = new TempoSyncKnob(knobBright_26, this, name);
knob->setModel(m_ladspaControl->tempoSyncKnobModel());
knob->setLabel(name);
break;
default:
layout->addWidget(new QLabel(tr("%1 (unsupported)").arg(name), this));
break;
}

View File

@@ -0,0 +1,115 @@
#include <BarModelEditor.h>
#include "CaptionMenu.h"
#include <QPainter>
#include <QInputDialog>
namespace lmms::gui
{
BarModelEditor::BarModelEditor(QString text, FloatModel * floatModel, QWidget * parent) :
QWidget(parent),
FloatModelView( floatModel, this ),
m_text(text)
{
connectToModelSignals();
}
QSizePolicy BarModelEditor::sizePolicy() const
{
return QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
}
QSize BarModelEditor::minimumSizeHint() const
{
auto const fm = fontMetrics();
return QSize(200, fm.height() * 1.3);
}
QSize BarModelEditor::sizeHint() const
{
return minimumSizeHint();
}
void BarModelEditor::paintEvent(QPaintEvent *event)
{
QWidget::paintEvent(event);
QColor const background(30, 40, 51);
QColor const foreground(3, 94, 97);
QColor const textColor(14, 192, 198);
auto const * mod = model();
auto const minValue = mod->minValue();
auto const maxValue = mod->maxValue();
auto const range = maxValue - minValue;
QRect const r = rect();
QPainter painter(this);
painter.setPen(background);
painter.setBrush(background);
painter.drawRect(r);
// Compute the percentage
// min + x * (max - min) = v <=> x = (v - min) / (max - min)
auto const percentage = range == 0 ? 1. : (mod->value() - minValue) / range;
int const margin = 2;
QMargins const margins(margin, margin, margin, margin);
QRect const valueRect = r.marginsRemoved(margins);
painter.setPen(foreground);
painter.setBrush(foreground);
painter.drawRect(QRect(valueRect.topLeft(), QPoint(valueRect.width() * percentage, valueRect.height())));
// Draw text
QRect const textRect = valueRect.marginsRemoved(margins);
painter.setPen(textColor);
painter.drawText(textRect, m_text);
}
void BarModelEditor::contextMenuEvent(QContextMenuEvent * me)
{
CaptionMenu contextMenu(model()->displayName(), this);
addDefaultActions(&contextMenu);
contextMenu.addSeparator();
contextMenu.exec(QCursor::pos());
}
void BarModelEditor::mouseDoubleClickEvent(QMouseEvent * me)
{
bool ok;
float new_val = QInputDialog::getDouble(
this, tr("Set value"),
tr("Please enter a new value between "
"%1 and %2:").
arg(model()->minValue()).
arg(model()->maxValue()),
model()->getRoundedValue(),
model()->minValue(),
model()->maxValue(), model()->getDigitCount(), &ok);
if (ok)
{
model()->setValue(new_val);
}
}
void BarModelEditor::connectToModelSignals()
{
auto * m = model();
if(m)
{
// TODO The first connection does a "friendly" update in Knob. Do we also have to do this?
QObject::connect(m, SIGNAL(dataChanged()), this, SLOT(update()));
QObject::connect(m ,SIGNAL(propertiesChanged()), this, SLOT(update()));
}
}
}