Add bar controller with tempo sync option
Add `TempoSyncBarModelEditor` which adds a tempo sync option to a `BarModelEditor`. Please note that the code was mostly copied and adjusted from the `TempoSyncKnob` class. It was not attempted yet to unify some of the code because with the current design it seems to be a road to "inheritance hell". A better solution might be to refactor the code so that it is more composable. Another option might be to move the tempo sync functionality into a class like `FloatModelEditorBase`. Although this would not be a 100% right place either because `TempoSyncKnobModel` inherits from `FloatModel`. In that case we'd have specialized code in a generic base class. Adjust `LadspaWidgetFactory` so that it now returns an instance of a `TempoSyncBarModelEditor` instead of a `TempoSyncKnob`. Remove the extra layout code from `LadspaMatrixControlDialog.cpp` as most things are bar editors now. Adjust `TempoSyncKnobModel` so we do not have to make `TempoSyncBarModelEditor` a friend of it.
This commit is contained in:
88
include/TempoSyncBarModelEditor.h
Normal file
88
include/TempoSyncBarModelEditor.h
Normal file
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* TempoSyncBarModelEditor.h - adds bpm to ms conversion for the bar editor class
|
||||
*
|
||||
* Copyright (c) 2005-2008 Danny McRae <khjklujn/at/yahoo.com>
|
||||
* Copyright (c) 2009-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
* Copyright (c) 2023 Michael Gregorius
|
||||
*
|
||||
* This file is part of LMMS - https://lmms.io
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this program (see COPYING); if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LMMS_GUI_TEMPO_SYNC_BAR_MODEL_EDITOR_H
|
||||
#define LMMS_GUI_TEMPO_SYNC_BAR_MODEL_EDITOR_H
|
||||
|
||||
#include <QPixmap>
|
||||
#include <QPointer>
|
||||
|
||||
#include "BarModelEditor.h"
|
||||
#include "TempoSyncKnobModel.h"
|
||||
|
||||
namespace lmms::gui
|
||||
{
|
||||
|
||||
class MeterDialog;
|
||||
|
||||
class LMMS_EXPORT TempoSyncBarModelEditor : public BarModelEditor
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
TempoSyncBarModelEditor(QString text, FloatModel * floatModel, QWidget * parent = nullptr);
|
||||
~TempoSyncBarModelEditor() override;
|
||||
|
||||
const QString & syncDescription();
|
||||
void setSyncDescription( const QString & _new_description );
|
||||
|
||||
const QPixmap & syncIcon();
|
||||
void setSyncIcon( const QPixmap & _new_pix );
|
||||
|
||||
TempoSyncKnobModel * model()
|
||||
{
|
||||
return castModel<TempoSyncKnobModel>();
|
||||
}
|
||||
|
||||
void modelChanged() override;
|
||||
|
||||
|
||||
signals:
|
||||
void syncDescriptionChanged( const QString & _new_description );
|
||||
void syncIconChanged();
|
||||
|
||||
|
||||
protected:
|
||||
void contextMenuEvent( QContextMenuEvent * _me ) override;
|
||||
|
||||
|
||||
protected slots:
|
||||
void updateDescAndIcon();
|
||||
void showCustom();
|
||||
|
||||
|
||||
private:
|
||||
QPixmap m_tempoSyncIcon;
|
||||
QString m_tempoSyncDescription;
|
||||
|
||||
QPointer<MeterDialog> m_custom;
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
} // namespace lmms::gui
|
||||
|
||||
#endif // LMMS_GUI_TEMPO_SYNC_BAR_MODEL_EDITOR_H
|
||||
@@ -82,6 +82,9 @@ public:
|
||||
|
||||
void setScale( float _new_scale );
|
||||
|
||||
MeterModel & getCustomMeterModel() { return m_custom; }
|
||||
MeterModel const & getCustomMeterModel() const { return m_custom; }
|
||||
|
||||
signals:
|
||||
void syncModeChanged( lmms::TempoSyncKnobModel::SyncMode _new_mode );
|
||||
void scaleChanged( float _new_scale );
|
||||
|
||||
@@ -166,11 +166,7 @@ void LadspaMatrixControlDialog::arrangeControls(QWidget * parent, QGridLayout* g
|
||||
QWidget * controlWidget = LadspaWidgetFactory::createWidget(ladspaControl, this);
|
||||
if (controlWidget)
|
||||
{
|
||||
// Align time based controls, i.e. knobs, in the center.
|
||||
// This defeats the purpose of the widget factory a bit but it makes the design look nicer.
|
||||
auto alignment = ladspaControl->port()->data_type == BufferDataType::Time ? Qt::AlignCenter : Qt::Alignment();
|
||||
|
||||
gridLayout->addWidget(controlWidget, currentRow, currentChannelColumn, alignment);
|
||||
gridLayout->addWidget(controlWidget, currentRow, currentChannelColumn);
|
||||
}
|
||||
|
||||
// Record the maximum row so that we add a vertical spacer after that row
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
// TODO Only for testing! Remove!
|
||||
#include "FloatModelEditorBase.h"
|
||||
#include "LedCheckBox.h"
|
||||
#include "TempoSyncKnob.h"
|
||||
#include "TempoSyncBarModelEditor.h"
|
||||
|
||||
#include <QLabel>
|
||||
|
||||
@@ -44,8 +44,6 @@ namespace lmms::gui
|
||||
|
||||
QWidget * LadspaWidgetFactory::createWidget(LadspaControl * ladspaControl, QWidget * parent)
|
||||
{
|
||||
Knob * knob = nullptr;
|
||||
|
||||
auto const * port = ladspaControl->port();
|
||||
|
||||
QString const name = port->name;
|
||||
@@ -66,21 +64,12 @@ QWidget * LadspaWidgetFactory::createWidget(LadspaControl * ladspaControl, QWidg
|
||||
return new BarModelEditor(name, ladspaControl->knobModel(), parent);
|
||||
|
||||
case BufferDataType::Time:
|
||||
knob = new TempoSyncKnob(KnobType::Bright26, parent, name);
|
||||
knob->setModel(ladspaControl->tempoSyncKnobModel());
|
||||
knob->setLabel(name);
|
||||
break;
|
||||
return new TempoSyncBarModelEditor(name, ladspaControl->tempoSyncKnobModel(), parent);
|
||||
|
||||
default:
|
||||
return new QLabel(QObject::tr("%1 (unsupported)").arg(name), parent);
|
||||
}
|
||||
|
||||
if (knob != nullptr)
|
||||
{
|
||||
knob->setHintText(QObject::tr("Value:"), "");
|
||||
return knob;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
@@ -117,6 +117,7 @@ SET(LMMS_SRCS
|
||||
gui/widgets/SimpleTextFloat.cpp
|
||||
gui/widgets/TabBar.cpp
|
||||
gui/widgets/TabWidget.cpp
|
||||
gui/widgets/TempoSyncBarModelEditor.cpp
|
||||
gui/widgets/TempoSyncKnob.cpp
|
||||
gui/widgets/TextFloat.cpp
|
||||
gui/widgets/TimeDisplayWidget.cpp
|
||||
|
||||
315
src/gui/widgets/TempoSyncBarModelEditor.cpp
Normal file
315
src/gui/widgets/TempoSyncBarModelEditor.cpp
Normal file
@@ -0,0 +1,315 @@
|
||||
/*
|
||||
* TempoSyncBarModelEditor.cpp - adds bpm to ms conversion for the bar editor class
|
||||
*
|
||||
* Copyright (c) 2005-2007 Danny McRae <khjklujn/at/yahoo.com>
|
||||
* Copyright (c) 2005-2009 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
* Copyright (c) 2023 Michael Gregorius
|
||||
*
|
||||
* This file is part of LMMS - https://lmms.io
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this program (see COPYING); if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <QMdiArea>
|
||||
|
||||
#include "TempoSyncBarModelEditor.h"
|
||||
#include "Engine.h"
|
||||
#include "CaptionMenu.h"
|
||||
#include "embed.h"
|
||||
#include "GuiApplication.h"
|
||||
#include "MainWindow.h"
|
||||
#include "MeterDialog.h"
|
||||
#include "Song.h"
|
||||
#include "SubWindow.h"
|
||||
|
||||
|
||||
namespace lmms::gui
|
||||
{
|
||||
|
||||
|
||||
|
||||
TempoSyncBarModelEditor::TempoSyncBarModelEditor(QString text, FloatModel * floatModel, QWidget * parent) :
|
||||
BarModelEditor(text, floatModel, parent ),
|
||||
m_tempoSyncIcon( embed::getIconPixmap( "tempo_sync" ) ),
|
||||
m_tempoSyncDescription( tr( "Tempo Sync" ) ),
|
||||
m_custom( nullptr )
|
||||
{
|
||||
modelChanged();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
TempoSyncBarModelEditor::~TempoSyncBarModelEditor()
|
||||
{
|
||||
if( m_custom )
|
||||
{
|
||||
delete m_custom->parentWidget();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void TempoSyncBarModelEditor::modelChanged()
|
||||
{
|
||||
if( model() == nullptr )
|
||||
{
|
||||
qWarning( "no TempoSyncKnobModel has been set!" );
|
||||
}
|
||||
if( m_custom != nullptr )
|
||||
{
|
||||
m_custom->setModel( &model()->getCustomMeterModel() );
|
||||
}
|
||||
connect(model(), &TempoSyncKnobModel::syncModeChanged, this, &TempoSyncBarModelEditor::updateDescAndIcon);
|
||||
connect( this, SIGNAL(sliderMoved(float)),
|
||||
model(), SLOT(disableSync()));
|
||||
updateDescAndIcon();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void TempoSyncBarModelEditor::contextMenuEvent( QContextMenuEvent * )
|
||||
{
|
||||
mouseReleaseEvent( nullptr );
|
||||
|
||||
CaptionMenu contextMenu( model()->displayName(), this );
|
||||
addDefaultActions( &contextMenu );
|
||||
contextMenu.addSeparator();
|
||||
|
||||
float limit = 60000.0f / ( Engine::getSong()->getTempo() *
|
||||
model()->scale() );
|
||||
|
||||
QMenu * syncMenu = contextMenu.addMenu( m_tempoSyncIcon,
|
||||
m_tempoSyncDescription );
|
||||
if( limit / 8.0f <= model()->maxValue() )
|
||||
{
|
||||
|
||||
connect( syncMenu, SIGNAL(triggered(QAction*)),
|
||||
model(), SLOT(setTempoSync(QAction*)));
|
||||
syncMenu->addAction( embed::getIconPixmap( "note_none" ),
|
||||
tr( "No Sync" ) )->setData( (int) TempoSyncKnobModel::SyncMode::None );
|
||||
if( limit / 0.125f <= model()->maxValue() )
|
||||
{
|
||||
syncMenu->addAction( embed::getIconPixmap( "note_double_whole" ),
|
||||
tr( "Eight beats" ) )->setData(
|
||||
(int) TempoSyncKnobModel::SyncMode::DoubleWholeNote );
|
||||
}
|
||||
if( limit / 0.25f <= model()->maxValue() )
|
||||
{
|
||||
syncMenu->addAction( embed::getIconPixmap( "note_whole" ),
|
||||
tr( "Whole note" ) )->setData(
|
||||
(int) TempoSyncKnobModel::SyncMode::WholeNote );
|
||||
}
|
||||
if( limit / 0.5f <= model()->maxValue() )
|
||||
{
|
||||
syncMenu->addAction( embed::getIconPixmap( "note_half" ),
|
||||
tr( "Half note" ) )->setData(
|
||||
(int) TempoSyncKnobModel::SyncMode::HalfNote );
|
||||
}
|
||||
if( limit <= model()->maxValue() )
|
||||
{
|
||||
syncMenu->addAction( embed::getIconPixmap( "note_quarter" ),
|
||||
tr( "Quarter note" ) )->setData(
|
||||
(int) TempoSyncKnobModel::SyncMode::QuarterNote );
|
||||
}
|
||||
if( limit / 2.0f <= model()->maxValue() )
|
||||
{
|
||||
syncMenu->addAction( embed::getIconPixmap( "note_eighth" ),
|
||||
tr( "8th note" ) )->setData(
|
||||
(int) TempoSyncKnobModel::SyncMode::EighthNote );
|
||||
}
|
||||
if( limit / 4.0f <= model()->maxValue() )
|
||||
{
|
||||
syncMenu->addAction( embed::getIconPixmap( "note_sixteenth" ),
|
||||
tr( "16th note" ) )->setData(
|
||||
(int) TempoSyncKnobModel::SyncMode::SixteenthNote );
|
||||
}
|
||||
syncMenu->addAction( embed::getIconPixmap( "note_thirtysecond" ),
|
||||
tr( "32nd note" ) )->setData(
|
||||
(int) TempoSyncKnobModel::SyncMode::ThirtysecondNote );
|
||||
syncMenu->addAction( embed::getIconPixmap( "dont_know" ),
|
||||
tr( "Custom..." ),
|
||||
this, SLOT(showCustom())
|
||||
)->setData(
|
||||
(int) TempoSyncKnobModel::SyncMode::Custom );
|
||||
contextMenu.addSeparator();
|
||||
|
||||
}
|
||||
contextMenu.exec( QCursor::pos() );
|
||||
|
||||
delete syncMenu;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void TempoSyncBarModelEditor::updateDescAndIcon()
|
||||
{
|
||||
if( model()->syncMode() != TempoSyncKnobModel::SyncMode::None )
|
||||
{
|
||||
switch( model()->syncMode() )
|
||||
{
|
||||
case TempoSyncKnobModel::SyncMode::Custom:
|
||||
m_tempoSyncDescription = tr( "Custom " ) +
|
||||
"(" +
|
||||
QString::number( model()->getCustomMeterModel().numeratorModel().value() ) +
|
||||
"/" +
|
||||
QString::number( model()->getCustomMeterModel().denominatorModel().value() ) +
|
||||
")";
|
||||
break;
|
||||
case TempoSyncKnobModel::SyncMode::DoubleWholeNote:
|
||||
m_tempoSyncDescription = tr(
|
||||
"Synced to Eight Beats" );
|
||||
break;
|
||||
case TempoSyncKnobModel::SyncMode::WholeNote:
|
||||
m_tempoSyncDescription = tr(
|
||||
"Synced to Whole Note" );
|
||||
break;
|
||||
case TempoSyncKnobModel::SyncMode::HalfNote:
|
||||
m_tempoSyncDescription = tr(
|
||||
"Synced to Half Note" );
|
||||
break;
|
||||
case TempoSyncKnobModel::SyncMode::QuarterNote:
|
||||
m_tempoSyncDescription = tr(
|
||||
"Synced to Quarter Note" );
|
||||
break;
|
||||
case TempoSyncKnobModel::SyncMode::EighthNote:
|
||||
m_tempoSyncDescription = tr(
|
||||
"Synced to 8th Note" );
|
||||
break;
|
||||
case TempoSyncKnobModel::SyncMode::SixteenthNote:
|
||||
m_tempoSyncDescription = tr(
|
||||
"Synced to 16th Note" );
|
||||
break;
|
||||
case TempoSyncKnobModel::SyncMode::ThirtysecondNote:
|
||||
m_tempoSyncDescription = tr(
|
||||
"Synced to 32nd Note" );
|
||||
break;
|
||||
default: ;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_tempoSyncDescription = tr( "Tempo Sync" );
|
||||
}
|
||||
if( m_custom != nullptr &&
|
||||
model()->syncMode() != TempoSyncKnobModel::SyncMode::Custom )
|
||||
{
|
||||
m_custom->parentWidget()->hide();
|
||||
}
|
||||
|
||||
switch( model()->syncMode() )
|
||||
{
|
||||
case TempoSyncKnobModel::SyncMode::None:
|
||||
m_tempoSyncIcon = embed::getIconPixmap( "tempo_sync" );
|
||||
break;
|
||||
case TempoSyncKnobModel::SyncMode::Custom:
|
||||
m_tempoSyncIcon = embed::getIconPixmap( "dont_know" );
|
||||
break;
|
||||
case TempoSyncKnobModel::SyncMode::DoubleWholeNote:
|
||||
m_tempoSyncIcon = embed::getIconPixmap( "note_double_whole" );
|
||||
break;
|
||||
case TempoSyncKnobModel::SyncMode::WholeNote:
|
||||
m_tempoSyncIcon = embed::getIconPixmap( "note_whole" );
|
||||
break;
|
||||
case TempoSyncKnobModel::SyncMode::HalfNote:
|
||||
m_tempoSyncIcon = embed::getIconPixmap( "note_half" );
|
||||
break;
|
||||
case TempoSyncKnobModel::SyncMode::QuarterNote:
|
||||
m_tempoSyncIcon = embed::getIconPixmap( "note_quarter" );
|
||||
break;
|
||||
case TempoSyncKnobModel::SyncMode::EighthNote:
|
||||
m_tempoSyncIcon = embed::getIconPixmap( "note_eighth" );
|
||||
break;
|
||||
case TempoSyncKnobModel::SyncMode::SixteenthNote:
|
||||
m_tempoSyncIcon = embed::getIconPixmap( "note_sixteenth" );
|
||||
break;
|
||||
case TempoSyncKnobModel::SyncMode::ThirtysecondNote:
|
||||
m_tempoSyncIcon = embed::getIconPixmap( "note_thirtysecond" );
|
||||
break;
|
||||
default:
|
||||
qWarning( "TempoSyncKnob::calculateTempoSyncTime:"
|
||||
"invalid TempoSyncMode" );
|
||||
break;
|
||||
}
|
||||
|
||||
emit syncDescriptionChanged( m_tempoSyncDescription );
|
||||
emit syncIconChanged();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
const QString & TempoSyncBarModelEditor::syncDescription()
|
||||
{
|
||||
return m_tempoSyncDescription;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void TempoSyncBarModelEditor::setSyncDescription( const QString & _new_description )
|
||||
{
|
||||
m_tempoSyncDescription = _new_description;
|
||||
emit syncDescriptionChanged( _new_description );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
const QPixmap & TempoSyncBarModelEditor::syncIcon()
|
||||
{
|
||||
return m_tempoSyncIcon;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void TempoSyncBarModelEditor::setSyncIcon( const QPixmap & _new_icon )
|
||||
{
|
||||
m_tempoSyncIcon = _new_icon;
|
||||
emit syncIconChanged();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void TempoSyncBarModelEditor::showCustom()
|
||||
{
|
||||
if( m_custom == nullptr )
|
||||
{
|
||||
m_custom = new MeterDialog( getGUI()->mainWindow()->workspace() );
|
||||
QMdiSubWindow * subWindow = getGUI()->mainWindow()->addWindowedWidget( m_custom );
|
||||
Qt::WindowFlags flags = subWindow->windowFlags();
|
||||
flags &= ~Qt::WindowMaximizeButtonHint;
|
||||
subWindow->setWindowFlags( flags );
|
||||
subWindow->setFixedSize( subWindow->size() );
|
||||
m_custom->setWindowTitle( "Meter" );
|
||||
m_custom->setModel( &model()->getCustomMeterModel() );
|
||||
}
|
||||
m_custom->parentWidget()->show();
|
||||
model()->setTempoSync( TempoSyncKnobModel::SyncMode::Custom );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
} // namespace lmms::gui
|
||||
Reference in New Issue
Block a user