Skip to content

Commit

Permalink
Feature: Pattern import/export (LMMS#5891)
Browse files Browse the repository at this point in the history
* Init

* Suggested changes by @IanCaio, thanks!

* Selecting one file to import is enough.

* Explicit use of TimePos in favour of int where expected, as suggested.

* Make pattern import/export future proof with using DataFile instead of custom code to read/write the pattern file.

* Remove unused/duplicate imports

* Make import/export dialogs file-ext filter consistent.

Co-authored-by: CYBERDEViL <cyberdevil@notabug.org>
  • Loading branch information
cyber-bridge and CYBERDEViL authored Mar 21, 2021
1 parent ae69743 commit 4626952
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 2 deletions.
1 change: 1 addition & 0 deletions include/DataFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ class LMMS_EXPORT DataFile : public QDomDocument
ClipboardData,
JournalData,
EffectSettings,
NotePattern,
TypeCount
} ;
typedef Types Type;
Expand Down
4 changes: 4 additions & 0 deletions include/PianoRoll.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ class QPixmap;
class QScrollBar;
class QString;
class QMenu;
class QToolButton;

class ComboBox;
class NotePlayHandle;
Expand Down Expand Up @@ -530,6 +531,8 @@ class PianoRollWindow : public Editor, SerializingObject
private slots:
void updateAfterPatternChange();
void ghostPatternSet( bool state );
void exportPattern();
void importPattern();

private:
void patternRenamed();
Expand All @@ -539,6 +542,7 @@ private slots:

PianoRoll* m_editor;

QToolButton* m_fileToolsButton;
ComboBox * m_zoomingComboBox;
ComboBox * m_zoomingYComboBox;
ComboBox * m_quantizeComboBox;
Expand Down
12 changes: 10 additions & 2 deletions src/core/DataFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,8 @@ DataFile::typeDescStruct
{ DataFile::DragNDropData, "dnddata" },
{ DataFile::ClipboardData, "clipboard-data" },
{ DataFile::JournalData, "journaldata" },
{ DataFile::EffectSettings, "effectsettings" }
{ DataFile::EffectSettings, "effectsettings" },
{ DataFile::NotePattern, "pattern" }
} ;


Expand Down Expand Up @@ -185,6 +186,12 @@ bool DataFile::validate( QString extension )
return true;
}
break;
case Type::NotePattern:
if (extension == "xpt" || extension == "xptz")
{
return true;
}
break;
case Type::UnknownType:
if (! ( extension == "mmp" || extension == "mpt" || extension == "mmpz" ||
extension == "xpf" || extension == "xml" ||
Expand Down Expand Up @@ -286,7 +293,8 @@ bool DataFile::writeFile( const QString& filename )
return false;
}

if( fullName.section( '.', -1 ) == "mmpz" )
const QString extension = fullName.section('.', -1);
if (extension == "mmpz" || extension == "xptz")
{
QString xml;
QTextStream ts( &xml );
Expand Down
107 changes: 107 additions & 0 deletions src/gui/editors/PianoRoll.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include <QKeyEvent>
#include <QLabel>
#include <QLayout>
#include <QMessageBox>
#include <QMdiArea>
#include <QPainter>
#include <QPointer>
Expand Down Expand Up @@ -66,6 +67,7 @@
#include "StepRecorderWidget.h"
#include "TextFloat.h"
#include "TimeLineWidget.h"
#include "FileDialog.h"


using std::move;
Expand Down Expand Up @@ -4736,6 +4738,29 @@ PianoRollWindow::PianoRollWindow() :
notesActionsToolBar->addSeparator();
notesActionsToolBar->addWidget(quantizeButton);

// -- File actions
DropToolBar* fileActionsToolBar = addDropToolBarToTop(tr("File actions"));

// -- File ToolButton
m_fileToolsButton = new QToolButton(m_toolBar);
m_fileToolsButton->setIcon(embed::getIconPixmap("file"));
m_fileToolsButton->setPopupMode(QToolButton::InstantPopup);

// Import / export
QAction* importAction = new QAction(embed::getIconPixmap("project_import"),
tr("Import pattern"), m_fileToolsButton);

QAction* exportAction = new QAction(embed::getIconPixmap("project_export"),
tr("Export pattern"), m_fileToolsButton);

m_fileToolsButton->addAction(importAction);
m_fileToolsButton->addAction(exportAction);
fileActionsToolBar->addWidget(m_fileToolsButton);

connect(importAction, SIGNAL(triggered()), this, SLOT(importPattern()));
connect(exportAction, SIGNAL(triggered()), this, SLOT(exportPattern()));
// -- End File actions

// Copy + paste actions
DropToolBar *copyPasteActionsToolBar = addDropToolBarToTop( tr( "Copy paste controls" ) );

Expand Down Expand Up @@ -4987,12 +5012,14 @@ void PianoRollWindow::setCurrentPattern( Pattern* pattern )
if ( pattern )
{
setWindowTitle( tr( "Piano-Roll - %1" ).arg( pattern->name() ) );
m_fileToolsButton->setEnabled(true);
connect( pattern->instrumentTrack(), SIGNAL( nameChanged() ), this, SLOT( updateAfterPatternChange()) );
connect( pattern, SIGNAL( dataChanged() ), this, SLOT( updateAfterPatternChange() ) );
}
else
{
setWindowTitle( tr( "Piano-Roll - no pattern" ) );
m_fileToolsButton->setEnabled(false);
}
}

Expand Down Expand Up @@ -5158,10 +5185,12 @@ void PianoRollWindow::patternRenamed()
if ( currentPattern() )
{
setWindowTitle( tr( "Piano-Roll - %1" ).arg( currentPattern()->name() ) );
m_fileToolsButton->setEnabled(true);
}
else
{
setWindowTitle( tr( "Piano-Roll - no pattern" ) );
m_fileToolsButton->setEnabled(false);
}
}

Expand All @@ -5176,6 +5205,84 @@ void PianoRollWindow::ghostPatternSet( bool state )



void PianoRollWindow::exportPattern()
{
FileDialog exportDialog(this, tr("Export pattern"), "",
tr("XML pattern file (*.xpt *.xptz)"));

exportDialog.setAcceptMode(FileDialog::AcceptSave);

if (exportDialog.exec() == QDialog::Accepted &&
!exportDialog.selectedFiles().isEmpty() &&
!exportDialog.selectedFiles().first().isEmpty())
{
QString suffix =
ConfigManager::inst()->value("app", "nommpz").toInt() == 0
? "xptz"
: "xpt";
exportDialog.setDefaultSuffix(suffix);

const QString fullPath = exportDialog.selectedFiles()[0];
DataFile dataFile(DataFile::NotePattern);
m_editor->m_pattern->saveSettings(dataFile, dataFile.content());

if (dataFile.writeFile(fullPath))
{
TextFloat::displayMessage(tr("Export pattern success"),
tr("Pattern saved to %1").arg(fullPath),
embed::getIconPixmap("project_export"), 4000);
}
}
}




void PianoRollWindow::importPattern()
{
// Overwrite confirmation.
if (!m_editor->m_pattern->empty() &&
QMessageBox::warning(
NULL,
tr("Import pattern."),
tr("You are about to import a pattern, this will "
"overwrite your current pattern. Do you want to "
"continue?"),
QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes
) != QMessageBox::Yes)
{
return;
}

FileDialog importDialog(this, tr("Open pattern"), "",
tr("XML pattern file (*.xpt *.xptz)"));
importDialog.setFileMode(FileDialog::ExistingFile);

if (importDialog.exec() == QDialog::Accepted &&
!importDialog.selectedFiles().isEmpty())
{
const QString fullPath = importDialog.selectedFiles()[0];
DataFile dataFile(fullPath);

if (dataFile.head().isNull())
{
return;
}

TimePos pos = m_editor->m_pattern->startPosition(); // Backup position in timeline.

m_editor->m_pattern->loadSettings(dataFile.content());
m_editor->m_pattern->movePosition(pos);

TextFloat::displayMessage(tr("Import pattern success"),
tr("Imported pattern %1!").arg(fullPath),
embed::getIconPixmap("project_import"), 4000);
}
}




void PianoRollWindow::focusInEvent( QFocusEvent * event )
{
// when the window is given focus, also give focus to the actual piano roll
Expand Down

0 comments on commit 4626952

Please sign in to comment.