diff --git a/include/TempoSyncBarModelEditor.h b/include/TempoSyncBarModelEditor.h new file mode 100644 index 000000000..84637f6e4 --- /dev/null +++ b/include/TempoSyncBarModelEditor.h @@ -0,0 +1,88 @@ +/* + * TempoSyncBarModelEditor.h - adds bpm to ms conversion for the bar editor class + * + * Copyright (c) 2005-2008 Danny McRae + * Copyright (c) 2009-2014 Tobias Doerffel + * 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 +#include + +#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(); + } + + 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 m_custom; + +} ; + + + +} // namespace lmms::gui + +#endif // LMMS_GUI_TEMPO_SYNC_BAR_MODEL_EDITOR_H diff --git a/include/TempoSyncKnobModel.h b/include/TempoSyncKnobModel.h index 5cd2db067..af92a58aa 100644 --- a/include/TempoSyncKnobModel.h +++ b/include/TempoSyncKnobModel.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 ); diff --git a/plugins/LadspaEffect/LadspaMatrixControlDialog.cpp b/plugins/LadspaEffect/LadspaMatrixControlDialog.cpp index a1836e8e3..d93d86613 100644 --- a/plugins/LadspaEffect/LadspaMatrixControlDialog.cpp +++ b/plugins/LadspaEffect/LadspaMatrixControlDialog.cpp @@ -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 diff --git a/plugins/LadspaEffect/LadspaWidgetFactory.cpp b/plugins/LadspaEffect/LadspaWidgetFactory.cpp index b09a061d1..a232ac955 100644 --- a/plugins/LadspaEffect/LadspaWidgetFactory.cpp +++ b/plugins/LadspaEffect/LadspaWidgetFactory.cpp @@ -34,7 +34,7 @@ // TODO Only for testing! Remove! #include "FloatModelEditorBase.h" #include "LedCheckBox.h" -#include "TempoSyncKnob.h" +#include "TempoSyncBarModelEditor.h" #include @@ -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; } diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index 0d15b1067..1e809e9d7 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -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 diff --git a/src/gui/widgets/TempoSyncBarModelEditor.cpp b/src/gui/widgets/TempoSyncBarModelEditor.cpp new file mode 100644 index 000000000..89e902256 --- /dev/null +++ b/src/gui/widgets/TempoSyncBarModelEditor.cpp @@ -0,0 +1,315 @@ +/* + * TempoSyncBarModelEditor.cpp - adds bpm to ms conversion for the bar editor class + * + * Copyright (c) 2005-2007 Danny McRae + * Copyright (c) 2005-2009 Tobias Doerffel + * 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 + +#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