diff --git a/include/Song.h b/include/Song.h index d88a59e2b40..32ead7181f5 100644 --- a/include/Song.h +++ b/include/Song.h @@ -65,6 +65,17 @@ class LMMS_EXPORT Song : public TrackContainer Mode_Count } ; + struct SaveOptions { + /** + * Should we discard MIDI ControllerConnections from project files? + */ + BoolModel discardMIDIConnections{false}; + + void setDefaultOptions() { + discardMIDIConnections.setValue(false); + } + }; + void clearErrors(); void collectError( const QString error ); bool hasErrors(); @@ -322,6 +333,11 @@ class LMMS_EXPORT Song : public TrackContainer void exportProjectMidi(QString const & exportFileName) const; inline void setLoadOnLauch(bool value) { m_loadOnLaunch = value; } + SaveOptions &getSaveOptions() { + return m_saveOptions; + } + + bool isSavingProject() const; public slots: void playSong(); @@ -419,9 +435,12 @@ private slots: volatile bool m_playing; volatile bool m_paused; + bool m_savingProject; bool m_loadingProject; bool m_isCancelled; + SaveOptions m_saveOptions; + QStringList m_errors; PlayModes m_playMode; diff --git a/include/VersionedSaveDialog.h b/include/VersionedSaveDialog.h index 781c6b71cb6..2e30e9f095c 100644 --- a/include/VersionedSaveDialog.h +++ b/include/VersionedSaveDialog.h @@ -29,15 +29,25 @@ #define VERSIONEDSAVEDIALOG_H #include "FileDialog.h" +#include "Song.h" class QLineEdit; +class LedCheckBox; +class SaveOptionsWidget : public QWidget { +public: + SaveOptionsWidget(Song::SaveOptions &saveOptions); + +private: + LedCheckBox *m_discardMIDIConnectionsCheckbox; +}; class VersionedSaveDialog : public FileDialog { Q_OBJECT public: explicit VersionedSaveDialog( QWidget *parent = 0, + QWidget *saveOptionsWidget = nullptr, const QString &caption = QString(), const QString &directory = QString(), const QString &filter = QString() ); diff --git a/src/core/AutomatableModel.cpp b/src/core/AutomatableModel.cpp index 1780da5e186..9b52ce8fe61 100644 --- a/src/core/AutomatableModel.cpp +++ b/src/core/AutomatableModel.cpp @@ -31,6 +31,7 @@ #include "LocaleHelper.h" #include "Mixer.h" #include "ProjectJournal.h" +#include "Song.h" long AutomatableModel::s_periodCounter = 0; @@ -131,8 +132,15 @@ void AutomatableModel::saveSettings( QDomDocument& doc, QDomElement& element, co } } - if( m_controllerConnection && m_controllerConnection->getController()->type() - != Controller::DummyController ) + // Skip saving MIDI connections if we're saving project and + // the discardMIDIConnections option is true. + auto controllerType = m_controllerConnection + ? m_controllerConnection->getController()->type() + : Controller::DummyController; + bool skipMidiController = Engine::getSong()->isSavingProject() + && Engine::getSong()->getSaveOptions().discardMIDIConnections.value(); + if (m_controllerConnection && controllerType != Controller::DummyController + && !(skipMidiController && controllerType == Controller::MidiController)) { QDomElement controllerElement; diff --git a/src/core/Song.cpp b/src/core/Song.cpp index 2809c61adb1..336aa3df273 100644 --- a/src/core/Song.cpp +++ b/src/core/Song.cpp @@ -1212,6 +1212,7 @@ void Song::loadProject( const QString & fileName ) bool Song::saveProjectFile( const QString & filename ) { DataFile dataFile( DataFile::SongProject ); + m_savingProject = true; m_tempoModel.saveSettings( dataFile, dataFile.head(), "bpm" ); m_timeSigModel.saveSettings( dataFile, dataFile.head(), "timesig" ); @@ -1233,6 +1234,8 @@ bool Song::saveProjectFile( const QString & filename ) saveControllerStates( dataFile, dataFile.content() ); + m_savingProject = false; + return dataFile.writeFile( filename ); } @@ -1265,7 +1268,11 @@ bool Song::guiSaveProjectAs( const QString & _file_name ) m_oldFileName = m_fileName; setProjectFileName(_file_name); - if(!guiSaveProject()) + bool saveResult = guiSaveProject(); + // After saving as, restore default save options. + m_saveOptions.setDefaultOptions(); + + if(!saveResult) { // Saving failed. Restore old filenames. setProjectFileName(m_oldFileName); @@ -1434,3 +1441,7 @@ QString Song::errorSummary() return errors; } + +bool Song::isSavingProject() const { + return m_savingProject; +} diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index 424c23d26e6..5d1dbf66673 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -922,7 +922,8 @@ bool MainWindow::saveProject() bool MainWindow::saveProjectAs() { - VersionedSaveDialog sfd( this, tr( "Save Project" ), "", + auto optionsWidget = new SaveOptionsWidget(Engine::getSong()->getSaveOptions()); + VersionedSaveDialog sfd( this, optionsWidget, tr( "Save Project" ), "", tr( "LMMS Project" ) + " (*.mmpz *.mmp);;" + tr( "LMMS Project Template" ) + " (*.mpt)" ); QString f = Engine::getSong()->projectFileName(); diff --git a/src/gui/dialogs/VersionedSaveDialog.cpp b/src/gui/dialogs/VersionedSaveDialog.cpp index e2acff590c4..18993c23bf4 100644 --- a/src/gui/dialogs/VersionedSaveDialog.cpp +++ b/src/gui/dialogs/VersionedSaveDialog.cpp @@ -28,13 +28,15 @@ #include #include #include +#include +#include #include "VersionedSaveDialog.h" - - +#include "LedCheckbox.h" VersionedSaveDialog::VersionedSaveDialog( QWidget *parent, + QWidget *saveOptionsWidget, const QString &caption, const QString &directory, const QString &filter ) : @@ -63,6 +65,17 @@ VersionedSaveDialog::VersionedSaveDialog( QWidget *parent, hLayout->addWidget( minusButton ); layout->addLayout( hLayout, 2, 1 ); + if (saveOptionsWidget) { + auto groupBox = new QGroupBox(tr("Save Options")); + auto optionsLayout = new QGridLayout; + + optionsLayout->addWidget(saveOptionsWidget, 0, 0, Qt::AlignLeft); + + groupBox->setLayout(optionsLayout); + + layout->addWidget(groupBox, layout->rowCount() + 1, 0, 1, -1); + } + // Connect + and - buttons connect( plusButton, SIGNAL( clicked() ), this, SLOT( incrementVersion() )); connect( minusButton, SIGNAL( clicked() ), this, SLOT( decrementVersion() )); @@ -160,3 +173,14 @@ bool VersionedSaveDialog::fileExistsQuery( QString FileName, QString WindowTitle } return fileExists; } + +SaveOptionsWidget::SaveOptionsWidget(Song::SaveOptions &saveOptions) { + auto *layout = new QVBoxLayout(); + + m_discardMIDIConnectionsCheckbox = new LedCheckBox(nullptr); + m_discardMIDIConnectionsCheckbox->setText(tr("Discard MIDI connections")); + m_discardMIDIConnectionsCheckbox->setModel(&saveOptions.discardMIDIConnections); + layout->addWidget(m_discardMIDIConnectionsCheckbox); + + setLayout(layout); +} diff --git a/src/tracks/InstrumentTrack.cpp b/src/tracks/InstrumentTrack.cpp index 6c95f3c9a23..a7809a077ef 100644 --- a/src/tracks/InstrumentTrack.cpp +++ b/src/tracks/InstrumentTrack.cpp @@ -749,7 +749,14 @@ void InstrumentTrack::saveTrackSpecificSettings( QDomDocument& doc, QDomElement m_soundShaping.saveState( doc, thisElement ); m_noteStacking.saveState( doc, thisElement ); m_arpeggio.saveState( doc, thisElement ); - m_midiPort.saveState( doc, thisElement ); + + // Don't save midi port info if the user chose to. + if (Engine::getSong()->isSavingProject() + && !Engine::getSong()->getSaveOptions().discardMIDIConnections.value()) + { + m_midiPort.saveState( doc, thisElement ); + } + m_audioPort.effects()->saveState( doc, thisElement ); }