Added export dialog
This commit is contained in:
parent
983c9a56e8
commit
9a22d98b47
31 changed files with 1640 additions and 1 deletions
|
@ -32,6 +32,10 @@ FocusScope {
|
|||
property alias text: label.text
|
||||
property alias font: label.font
|
||||
property alias wrapMode: label.wrapMode
|
||||
property alias font: label.font
|
||||
|
||||
property alias checkBoxWidth: box.width
|
||||
property alias checkBoxHeight: box.height
|
||||
|
||||
property alias navigation: navCtrl
|
||||
|
||||
|
|
|
@ -36,13 +36,16 @@ public:
|
|||
|
||||
// Pdf
|
||||
virtual int exportPdfDpiResolution() const = 0;
|
||||
virtual void setExportPdfDpiResolution(int dpi) = 0;
|
||||
|
||||
// Png
|
||||
virtual float exportPngDpiResolution() const = 0;
|
||||
virtual bool exportPngWithTransparentBackground() const = 0;
|
||||
|
||||
//! NOTE Maybe set from command line
|
||||
virtual void setExportPngDpiResolution(std::optional<float> dpi) = 0;
|
||||
|
||||
virtual bool exportPngWithTransparentBackground() const = 0;
|
||||
virtual void setExportPngWithTransparentBackground(bool transparent) = 0;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -44,6 +44,11 @@ int ImagesExportConfiguration::exportPdfDpiResolution() const
|
|||
return settings()->value(EXPORT_PDF_DPI_RESOLUTION_KEY).toInt();
|
||||
}
|
||||
|
||||
void ImagesExportConfiguration::setExportPdfDpiResolution(int dpi)
|
||||
{
|
||||
settings()->setValue(EXPORT_PDF_DPI_RESOLUTION_KEY, Val(dpi));
|
||||
}
|
||||
|
||||
void ImagesExportConfiguration::setExportPngDpiResolution(std::optional<float> dpi)
|
||||
{
|
||||
m_customExportPngDpi = dpi;
|
||||
|
@ -62,3 +67,8 @@ bool ImagesExportConfiguration::exportPngWithTransparentBackground() const
|
|||
{
|
||||
return settings()->value(EXPORT_PNG_USE_TRASNPARENCY_KEY).toBool();
|
||||
}
|
||||
|
||||
void ImagesExportConfiguration::setExportPngWithTransparentBackground(bool transparent)
|
||||
{
|
||||
settings()->setValue(EXPORT_PNG_USE_TRASNPARENCY_KEY, Val(transparent));
|
||||
}
|
||||
|
|
|
@ -31,11 +31,13 @@ public:
|
|||
void init();
|
||||
|
||||
int exportPdfDpiResolution() const override;
|
||||
void setExportPdfDpiResolution(int dpi) override;
|
||||
|
||||
void setExportPngDpiResolution(std::optional<float> dpi) override;
|
||||
float exportPngDpiResolution() const override;
|
||||
|
||||
bool exportPngWithTransparentBackground() const override;
|
||||
void setExportPngWithTransparentBackground(bool transparent) override;
|
||||
|
||||
private:
|
||||
|
||||
|
|
|
@ -40,6 +40,7 @@ class QRect;
|
|||
namespace mu::notation {
|
||||
class INotation;
|
||||
using INotationPtr = std::shared_ptr<INotation>;
|
||||
using INotationPtrList = std::vector<INotationPtr>;
|
||||
|
||||
class INotation
|
||||
{
|
||||
|
|
|
@ -36,6 +36,8 @@ public:
|
|||
|
||||
virtual void reg(const std::vector<std::string>& suffixes, INotationWriterPtr writer) = 0;
|
||||
virtual INotationWriterPtr writer(const std::string& suffix) const = 0;
|
||||
|
||||
virtual std::vector<std::string> registeredSuffixes() const = 0;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -40,3 +40,14 @@ INotationWriterPtr NotationWritersRegister::writer(const std::string& suffix) co
|
|||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::vector<std::string> NotationWritersRegister::registeredSuffixes() const
|
||||
{
|
||||
std::vector<std::string> suffixes;
|
||||
|
||||
for (auto& it : m_writers) {
|
||||
suffixes.push_back(it.first);
|
||||
}
|
||||
|
||||
return suffixes;
|
||||
}
|
||||
|
|
|
@ -32,6 +32,8 @@ public:
|
|||
void reg(const std::vector<std::string>& suffixes, INotationWriterPtr writer) override;
|
||||
INotationWriterPtr writer(const std::string& suffix) const override;
|
||||
|
||||
std::vector<std::string> registeredSuffixes() const override;
|
||||
|
||||
private:
|
||||
std::map<std::string, INotationWriterPtr> m_writers;
|
||||
};
|
||||
|
|
|
@ -30,6 +30,7 @@ set(MODULE_SRC
|
|||
${CMAKE_CURRENT_LIST_DIR}/iuserscoresconfiguration.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/iuserscoresservice.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/ifilescorecontroller.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/iexportscoreservice.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/userscorestypes.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/view/recentscoresmodel.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/view/recentscoresmodel.h
|
||||
|
@ -43,6 +44,12 @@ set(MODULE_SRC
|
|||
${CMAKE_CURRENT_LIST_DIR}/view/templatesmodel.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/view/templatepaintview.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/view/templatepaintview.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/view/exportscoremodel.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/view/exportscoremodel.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/view/exportscoresuffixmodel.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/view/exportscoresuffixmodel.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/view/exportscoresettingsmodel.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/view/exportscoresettingsmodel.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/internal/filescorecontroller.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/internal/filescorecontroller.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/internal/userscoresconfiguration.cpp
|
||||
|
@ -54,6 +61,8 @@ set(MODULE_SRC
|
|||
${CMAKE_CURRENT_LIST_DIR}/internal/templatesrepository.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/internal/userscoresuiactions.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/internal/userscoresuiactions.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/internal/exportscoreservice.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/internal/exportscoreservice.h
|
||||
)
|
||||
|
||||
set(MODULE_LINK notation)
|
||||
|
|
36
src/userscores/iexportscoreservice.h
Normal file
36
src/userscores/iexportscoreservice.h
Normal file
|
@ -0,0 +1,36 @@
|
|||
//=============================================================================
|
||||
// MuseScore
|
||||
// Music Composition & Notation
|
||||
//
|
||||
// Copyright (C) 2020 MuseScore BVBA and others
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License version 2.
|
||||
//
|
||||
// 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; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//=============================================================================
|
||||
|
||||
#ifndef MU_USERSCORES_IEXPORTSCORESERVICE_H
|
||||
#define MU_USERSCORES_IEXPORTSCORESERVICE_H
|
||||
|
||||
#include "modularity/imoduleexport.h"
|
||||
#include "notation/inotation.h"
|
||||
|
||||
namespace mu::userscores {
|
||||
class IExportScoreService : MODULE_EXPORT_INTERFACE
|
||||
{
|
||||
INTERFACE_ID(IExportScoreService)
|
||||
|
||||
public:
|
||||
virtual void exportScores(notation::INotationPtrList& notations, io::path& basePath) = 0;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // MU_USERSCORES_IEXPORTSCORESERVICE_H
|
152
src/userscores/internal/exportscoreservice.cpp
Normal file
152
src/userscores/internal/exportscoreservice.cpp
Normal file
|
@ -0,0 +1,152 @@
|
|||
//=============================================================================
|
||||
// MuseScore
|
||||
// Music Composition & Notation
|
||||
//
|
||||
// Copyright (C) 2020 MuseScore BVBA and others
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License version 2.
|
||||
//
|
||||
// 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; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//=============================================================================
|
||||
|
||||
#include "exportscoreservice.h"
|
||||
|
||||
#include "translation.h"
|
||||
|
||||
using namespace mu::userscores;
|
||||
using namespace mu::notation;
|
||||
using namespace mu::framework;
|
||||
|
||||
void ExportScoreService::exportScores(INotationPtrList& notations, io::path& exportPath)
|
||||
{
|
||||
std::string suffix = io::syffix(exportPath);
|
||||
|
||||
auto writer = writers()->writer(suffix);
|
||||
if (!writer) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (INotationPtr currentNotation : notations) {
|
||||
if (shouldExportIndividualPage(suffix)) {
|
||||
for (int page = 0; page < currentNotation->elements()->msScore()->pages().size(); page++) {
|
||||
exportSingleScore(writer, exportPath, currentNotation, page);
|
||||
}
|
||||
} else {
|
||||
exportSingleScore(writer, exportPath, currentNotation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ExportScoreService::FileConflictPolicy ExportScoreService::getConflictPolicy(std::string filename)
|
||||
{
|
||||
switch (m_currentConflictPolicy) {
|
||||
case Replace:
|
||||
case Skip:
|
||||
askConflictPolicy(filename);
|
||||
}
|
||||
|
||||
return getEffectivePolicy(m_currentConflictPolicy);
|
||||
}
|
||||
|
||||
bool ExportScoreService::askForRetry(std::string filename) const
|
||||
{
|
||||
int btn = interactive()->question("Error", "An error occured while exporting the file " + filename, {
|
||||
interactive()->buttonData(IInteractive::Button::Retry),
|
||||
interactive()->buttonData(IInteractive::Button::Abort)
|
||||
});
|
||||
|
||||
return btn == static_cast<int>(IInteractive::Button::Retry);
|
||||
}
|
||||
|
||||
ExportScoreService::FileConflictPolicy ExportScoreService::getEffectivePolicy(ExportScoreService::FileConflictPolicy policy) const
|
||||
{
|
||||
switch (policy) {
|
||||
case ReplaceAll:
|
||||
return FileConflictPolicy::Replace;
|
||||
case SkipAll:
|
||||
return FileConflictPolicy::Skip;
|
||||
default:
|
||||
return policy;
|
||||
}
|
||||
}
|
||||
|
||||
void ExportScoreService::askConflictPolicy(std::string filename)
|
||||
{
|
||||
int replace = static_cast<int>(IInteractive::Button::CustomButton) + 1;
|
||||
int replaceAll = static_cast<int>(IInteractive::Button::CustomButton) + 2;
|
||||
int skip = static_cast<int>(IInteractive::Button::CustomButton) + 3;
|
||||
int skipAll = static_cast<int>(IInteractive::Button::CustomButton) + 4;
|
||||
|
||||
int btn = interactive()->question("File already exists", "A file already exists with the filename " + filename, {
|
||||
IInteractive::ButtonData(replace, "Replace"),
|
||||
IInteractive::ButtonData(replaceAll, "Replace All"),
|
||||
IInteractive::ButtonData(skip, "Skip"),
|
||||
IInteractive::ButtonData(skipAll, "Skip All")
|
||||
});
|
||||
|
||||
m_currentConflictPolicy = static_cast<FileConflictPolicy>(btn - replace);
|
||||
}
|
||||
|
||||
bool ExportScoreService::exportSingleScore(INotationWriterPtr writer, io::path exportPath, INotationPtr notation, int page)
|
||||
{
|
||||
io::path outPath
|
||||
= configuration()->completeExportPath(exportPath, notation, isMainNotation(notation), shouldExportIndividualPage(io::syffix(
|
||||
exportPath)),
|
||||
page);
|
||||
QString outPathString = outPath.toQString();
|
||||
std::string completeFileName = io::filename(outPath).toStdString();
|
||||
|
||||
if (fileSystem()->exists(outPathString)) {
|
||||
if (getConflictPolicy(completeFileName)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
INotationWriter::Options options({
|
||||
{ INotationWriter::OptionKey::PAGE_NUMBER, Val(page) },
|
||||
{ INotationWriter::OptionKey::TRANSPARENT_BACKGROUND, Val(imagesExportConfiguration()->exportPngWithTransparentBackground()) }
|
||||
});
|
||||
|
||||
while (true) {
|
||||
QFile outFile(outPath.toQString());
|
||||
if (!outFile.open(QFile::WriteOnly)) {
|
||||
if (askForRetry(completeFileName)) {
|
||||
continue;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!writer->write(notation, outFile, options)) {
|
||||
outFile.close();
|
||||
if (askForRetry(completeFileName)) {
|
||||
continue;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
outFile.close();
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ExportScoreService::shouldExportIndividualPage(io::path suffix) const
|
||||
{
|
||||
return suffix == "png" || suffix == "svg";
|
||||
}
|
||||
|
||||
bool ExportScoreService::isMainNotation(INotationPtr notation) const
|
||||
{
|
||||
return context()->currentMasterNotation()->notation() == notation;
|
||||
}
|
70
src/userscores/internal/exportscoreservice.h
Normal file
70
src/userscores/internal/exportscoreservice.h
Normal file
|
@ -0,0 +1,70 @@
|
|||
//=============================================================================
|
||||
// MuseScore
|
||||
// Music Composition & Notation
|
||||
//
|
||||
// Copyright (C) 2020 MuseScore BVBA and others
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License version 2.
|
||||
//
|
||||
// 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; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//=============================================================================
|
||||
|
||||
#ifndef MU_USERSCORES_EXPORTSCORESERVICE_H
|
||||
#define MU_USERSCORES_EXPORTSCORESERVICE_H
|
||||
|
||||
#include "modularity/ioc.h"
|
||||
|
||||
#include "iexportscoreservice.h"
|
||||
#include "iuserscoresconfiguration.h"
|
||||
#include "iinteractive.h"
|
||||
#include "notation/inotationwritersregister.h"
|
||||
#include "importexport/imagesexport/iimagesexportconfiguration.h"
|
||||
#include "context/iglobalcontext.h"
|
||||
#include "notation/inotation.h"
|
||||
#include "system/ifilesystem.h"
|
||||
|
||||
namespace mu::userscores {
|
||||
class ExportScoreService : public IExportScoreService
|
||||
{
|
||||
INJECT(userscores, IUserScoresConfiguration, configuration);
|
||||
INJECT(userscores, framework::IInteractive, interactive);
|
||||
INJECT(userscores, notation::INotationWritersRegister, writers)
|
||||
INJECT(userscores, iex::imagesexport::IImagesExportConfiguration, imagesExportConfiguration)
|
||||
INJECT(userscores, context::IGlobalContext, context)
|
||||
INJECT(userscores, system::IFileSystem, fileSystem)
|
||||
|
||||
public:
|
||||
void exportScores(notation::INotationPtrList& notations, io::path& exportPath) override;
|
||||
|
||||
private:
|
||||
enum FileConflictPolicy {
|
||||
Replace,
|
||||
ReplaceAll,
|
||||
Skip,
|
||||
SkipAll
|
||||
};
|
||||
|
||||
bool isMainNotation(notation::INotationPtr notation) const;
|
||||
|
||||
FileConflictPolicy getConflictPolicy(std::string filename);
|
||||
FileConflictPolicy getEffectivePolicy(FileConflictPolicy policy) const;
|
||||
void askConflictPolicy(std::string filename);
|
||||
|
||||
bool askForRetry(std::string filename) const;
|
||||
|
||||
bool exportSingleScore(notation::INotationWriterPtr writer, io::path exportPath, notation::INotationPtr score, int page = 0);
|
||||
bool shouldExportIndividualPage(io::path suffix) const;
|
||||
|
||||
FileConflictPolicy m_currentConflictPolicy;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // MU_USERSCORES_EXPORTSCORESERVICE_H
|
|
@ -45,6 +45,8 @@ void FileScoreController::init()
|
|||
dispatcher()->reg(this, "file-save-a-copy", this, &FileScoreController::saveScoreCopy);
|
||||
dispatcher()->reg(this, "file-save-selection", this, &FileScoreController::saveSelection);
|
||||
|
||||
dispatcher()->reg(this, "file-export", this, &FileScoreController::exportScore);
|
||||
|
||||
dispatcher()->reg(this, "file-import-pdf", this, &FileScoreController::importPdf);
|
||||
|
||||
dispatcher()->reg(this, "clear-recent", this, &FileScoreController::clearRecentScores);
|
||||
|
@ -213,6 +215,11 @@ void FileScoreController::continueLastSession()
|
|||
openScore(lastScorePath);
|
||||
}
|
||||
|
||||
void FileScoreController::exportScore()
|
||||
{
|
||||
interactive()->open("musescore://userscores/export");
|
||||
}
|
||||
|
||||
io::path FileScoreController::selectScoreOpenningFile(const QStringList& filter)
|
||||
{
|
||||
QString filterStr = filter.join(";;");
|
||||
|
|
|
@ -74,6 +74,8 @@ private:
|
|||
Ret doOpenScore(const io::path& filePath);
|
||||
void doSaveScore(const io::path& filePath = io::path(), notation::SaveMode saveMode = notation::SaveMode::Save);
|
||||
|
||||
void exportScore();
|
||||
|
||||
io::path defaultSavingFilePath() const;
|
||||
|
||||
void prependToRecentScoreList(const io::path& filePath);
|
||||
|
|
|
@ -37,6 +37,7 @@ static const Settings::Key USER_SCORES_PATH(module_name, "application/paths/mySc
|
|||
static const Settings::Key PREFERRED_SCORE_CREATION_MODE_KEY(module_name, "userscores/preferedScoreCreationMode");
|
||||
|
||||
const QString UserScoresConfiguration::DEFAULT_FILE_SUFFIX(".mscz");
|
||||
const QString UserScoresConfiguration::DEFAULT_EXPORT_SUFFIX(".pdf");
|
||||
|
||||
static const std::string TEMPLATES_PATH("/templates");
|
||||
|
||||
|
@ -193,6 +194,26 @@ io::path UserScoresConfiguration::defaultSavingFilePath(const io::path& fileName
|
|||
return scoresPath().val + "/" + fileName + DEFAULT_FILE_SUFFIX;
|
||||
}
|
||||
|
||||
io::path UserScoresConfiguration::defaultExportPath(const std::string& fileName) const
|
||||
{
|
||||
return scoresPath().val + "/" + fileName + DEFAULT_EXPORT_SUFFIX;
|
||||
}
|
||||
|
||||
io::path UserScoresConfiguration::completeExportPath(io::path basePath, INotationPtr notation, bool isMain, bool singlePage,
|
||||
int pageNumber) const
|
||||
{
|
||||
io::path suffix = io::syffix(basePath);
|
||||
io::path exportDirectory = io::dirpath(basePath);
|
||||
io::path baseFilename = io::basename(basePath);
|
||||
|
||||
std::string notationNameExtension
|
||||
= (isMain ? "" : "-" + io::escapeFileName(notation->metaInfo().title).toStdString());
|
||||
std::string pageNameExtension = (singlePage ? "-" + std::to_string(pageNumber) : "");
|
||||
std::string completeFileName = baseFilename.toStdString() + notationNameExtension + pageNameExtension + "." + suffix.toStdString();
|
||||
|
||||
return exportDirectory + "/" + completeFileName;
|
||||
}
|
||||
|
||||
QColor UserScoresConfiguration::templatePreviewBackgroundColor() const
|
||||
{
|
||||
return notationConfiguration()->backgroundColor();
|
||||
|
|
|
@ -40,6 +40,7 @@ class UserScoresConfiguration : public IUserScoresConfiguration
|
|||
|
||||
public:
|
||||
static const QString DEFAULT_FILE_SUFFIX;
|
||||
static const QString DEFAULT_EXPORT_SUFFIX;
|
||||
|
||||
void init();
|
||||
|
||||
|
@ -57,6 +58,9 @@ public:
|
|||
void setScoresPath(const io::path& path) override;
|
||||
|
||||
io::path defaultSavingFilePath(const io::path& fileName) const override;
|
||||
io::path defaultExportPath(const std::string& fileName) const override;
|
||||
io::path completeExportPath(io::path basePath, notation::INotationPtr notation, bool isMain, bool singlePage,
|
||||
int pageNumber) const override;
|
||||
|
||||
QColor templatePreviewBackgroundColor() const override;
|
||||
async::Notification templatePreviewBackgroundChanged() const override;
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "retval.h"
|
||||
#include "io/path.h"
|
||||
#include "userscorestypes.h"
|
||||
#include "notation/inotation.h"
|
||||
|
||||
namespace mu::userscores {
|
||||
class IUserScoresConfiguration : MODULE_EXPORT_INTERFACE
|
||||
|
@ -52,6 +53,9 @@ public:
|
|||
virtual void setScoresPath(const io::path& path) = 0;
|
||||
|
||||
virtual io::path defaultSavingFilePath(const io::path& fileName) const = 0;
|
||||
virtual io::path defaultExportPath(const std::string& fileName) const = 0;
|
||||
virtual io::path completeExportPath(io::path basePath, notation::INotationPtr notation, bool isMain, bool singlePage,
|
||||
int pageNumber) const = 0;
|
||||
|
||||
virtual QColor templatePreviewBackgroundColor() const = 0;
|
||||
virtual async::Notification templatePreviewBackgroundChanged() const = 0;
|
||||
|
|
235
src/userscores/qml/MuseScore/UserScores/ExportDialog.qml
Normal file
235
src/userscores/qml/MuseScore/UserScores/ExportDialog.qml
Normal file
|
@ -0,0 +1,235 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.15
|
||||
|
||||
import MuseScore.Ui 1.0
|
||||
import MuseScore.UiComponents 1.0
|
||||
import MuseScore.UserScores 1.0
|
||||
|
||||
import "internal"
|
||||
|
||||
QmlDialog {
|
||||
id: root
|
||||
|
||||
width: 640
|
||||
height: 480
|
||||
|
||||
modal: true
|
||||
|
||||
title: qsTrc("userscores", "Export Score")
|
||||
|
||||
Rectangle {
|
||||
id: content
|
||||
|
||||
anchors.fill: parent
|
||||
|
||||
color: ui.theme.popupBackgroundColor
|
||||
|
||||
ExportScoreModel {
|
||||
id: scoresModel
|
||||
}
|
||||
|
||||
ExportScoreSuffixModel {
|
||||
id: suffixModel
|
||||
}
|
||||
|
||||
ExportScoreSettingsModel {
|
||||
id: settingsModel
|
||||
}
|
||||
|
||||
QtObject {
|
||||
id: privateProperties
|
||||
|
||||
readonly property int sideMargin: 24
|
||||
readonly property int buttonsMargin: 24
|
||||
readonly property int rectangleRadius: 4
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
scoresModel.load();
|
||||
suffixModel.load();
|
||||
settingsModel.load();
|
||||
|
||||
settingsModel.changeType(fileTypeSelect.value)
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
|
||||
anchors.fill: parent
|
||||
|
||||
spacing: 0
|
||||
|
||||
StyledTextLabel {
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: privateProperties.sideMargin
|
||||
Layout.topMargin: privateProperties.sideMargin
|
||||
|
||||
text: qsTrc("global", "Export")
|
||||
font: ui.theme.headerBoldFont
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Layout.alignment: Qt.AlignLeft | Qt.AlignTop
|
||||
Layout.preferredHeight: childrenRect.height
|
||||
spacing: 12
|
||||
|
||||
width: parent.width - spacing
|
||||
Layout.bottomMargin: privateProperties.sideMargin
|
||||
Layout.topMargin: privateProperties.sideMargin
|
||||
|
||||
ExportScoresListView {
|
||||
id: scoresList
|
||||
|
||||
model: scoresModel
|
||||
|
||||
Layout.preferredWidth: parent.width / 2 - parent.spacing / 2 - Layout.leftMargin
|
||||
Layout.fillHeight: true
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: rightRectangle
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
|
||||
color: ui.theme.popupBackgroundColor
|
||||
|
||||
Column {
|
||||
Layout.fillHeight: true
|
||||
Layout.fillWidth: true
|
||||
|
||||
spacing: 12
|
||||
|
||||
Column {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: childrenRect.height
|
||||
|
||||
spacing: 6
|
||||
|
||||
StyledTextLabel {
|
||||
Layout.fillWidth: true
|
||||
text: qsTrc("userscores", "Export To:")
|
||||
font.capitalization: Font.AllUppercase
|
||||
}
|
||||
|
||||
Row {
|
||||
id: exportToPath
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: childrenRect.height
|
||||
|
||||
spacing: 6
|
||||
|
||||
TextInputField {
|
||||
id: fileExportPathInput
|
||||
|
||||
height: 30
|
||||
width: rightRectangle.width * 0.8
|
||||
|
||||
currentText: scoresModel.exportPath()
|
||||
|
||||
onCurrentTextEdited: {
|
||||
scoresModel.setExportPath(newTextValue);
|
||||
}
|
||||
}
|
||||
|
||||
FlatButton {
|
||||
id: browsePathButton
|
||||
|
||||
icon: IconCode.NEW_FILE
|
||||
|
||||
height:30
|
||||
width: rightRectangle.width * 0.1
|
||||
|
||||
onClicked: {
|
||||
fileExportPathInput.currentText = scoresModel.chooseExportPath();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
id: exportSuffixSelection
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: childrenRect.height
|
||||
|
||||
spacing: 6
|
||||
|
||||
StyledTextLabel {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 24
|
||||
|
||||
text: qsTrc("userscores", "Export As: ")
|
||||
font.capitalization: Font.AllUppercase
|
||||
}
|
||||
|
||||
StyledComboBox {
|
||||
id: fileTypeSelect
|
||||
|
||||
property var currValue: suffixModel.getDefaultRow()
|
||||
|
||||
width: rightRectangle.width * 0.8
|
||||
|
||||
textRoleName: "suffix"
|
||||
valueRoleName: "value"
|
||||
|
||||
model: suffixModel
|
||||
|
||||
currentIndex: indexOfValue(currValue)
|
||||
|
||||
onValueChanged: {
|
||||
currValue = value;
|
||||
scoresModel.setExportSuffix(valueFromModel(indexOfValue(value), "suffix"));
|
||||
fileExportPathInput.currentText = scoresModel.exportPath();
|
||||
|
||||
settingsModel.changeType(valueFromModel(indexOfValue(value), "suffix"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
id: exportSettingsContainer
|
||||
|
||||
anchors.top: exportSuffixSelection.bottom
|
||||
|
||||
ExportFilePages {
|
||||
model: settingsModel
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
Layout.preferredHeight: childrenRect.height
|
||||
Layout.bottomMargin: privateProperties.buttonsMargin
|
||||
Layout.rightMargin: privateProperties.buttonsMargin
|
||||
Layout.alignment: Qt.AlignRight | Qt.AlignBottom
|
||||
|
||||
spacing: 12
|
||||
|
||||
FlatButton {
|
||||
text: qsTrc("global", "Close")
|
||||
|
||||
onClicked: {
|
||||
root.hide()
|
||||
}
|
||||
}
|
||||
|
||||
FlatButton {
|
||||
id: exportButton
|
||||
|
||||
text: qsTrc("global", "Export")
|
||||
|
||||
accentButton: true
|
||||
|
||||
onClicked: {
|
||||
scoresModel.exportScores();
|
||||
root.hide();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,187 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.15
|
||||
import QtQuick.Dialogs 1.2
|
||||
|
||||
import MuseScore.Ui 1.0
|
||||
import MuseScore.UiComponents 1.0
|
||||
import MuseScore.UserScores 1.0
|
||||
|
||||
Item {
|
||||
id: exportPageStack
|
||||
|
||||
property var model
|
||||
|
||||
height: 450
|
||||
|
||||
Column {
|
||||
id: pdfPage
|
||||
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
|
||||
spacing: 12
|
||||
|
||||
ListView {
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
|
||||
orientation: Qt.Vertical
|
||||
|
||||
model: exportPageStack.model
|
||||
|
||||
delegate: Column {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: childrenRect.height
|
||||
|
||||
spacing: 6
|
||||
|
||||
StyledTextLabel {
|
||||
Layout.fillWidth: true
|
||||
height: 30
|
||||
|
||||
text: friendlyNameRole
|
||||
font.capitalization: Font.AllUppercase
|
||||
}
|
||||
|
||||
Item {
|
||||
id: control
|
||||
height: 30
|
||||
width: 150
|
||||
|
||||
Loader {
|
||||
id: loader
|
||||
property var val: valRole
|
||||
anchors.fill: parent
|
||||
sourceComponent: exportPageStack.componentByType(typeRole)
|
||||
onLoaded: loader.item.val = loader.val
|
||||
onValChanged: {
|
||||
if (loader.item) {
|
||||
loader.item.val = loader.val
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: loader.item
|
||||
function onChanged(newVal) {
|
||||
exportPageStack.model.changeVal(model.index, newVal)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function componentByType(type) {
|
||||
switch (type) {
|
||||
case "Undefined": return textComp;
|
||||
case "Bool": return boolComp;
|
||||
case "Int": return intComp;
|
||||
case "Double": return doubleComp;
|
||||
case "String": return textComp;
|
||||
case "Color": return colorComp;
|
||||
}
|
||||
|
||||
return textComp;
|
||||
}
|
||||
|
||||
Component {
|
||||
id: textComp
|
||||
|
||||
TextInputField {
|
||||
id: textControl
|
||||
anchors.fill: parent
|
||||
|
||||
property var val
|
||||
|
||||
currentText: val
|
||||
|
||||
signal changed(var newVal)
|
||||
|
||||
onCurrentTextEdited: {
|
||||
changed(newVal)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: colorComp
|
||||
|
||||
Rectangle {
|
||||
id: colorControl
|
||||
property var val
|
||||
signal changed(var newVal)
|
||||
anchors.fill: parent
|
||||
color: val
|
||||
|
||||
ColorDialog {
|
||||
id: colorDialog
|
||||
title: "Please choose a color"
|
||||
onAccepted: colorControl.changed(colorDialog.color)
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: colorDialog.open()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: intComp
|
||||
|
||||
IncrementalPropertyControl {
|
||||
iconMode: iconModeEnum.hidden
|
||||
|
||||
property var val
|
||||
currentValue: val.toString()
|
||||
|
||||
step: 1
|
||||
minValue: 72
|
||||
maxValue: 2400
|
||||
|
||||
signal changed(var newVal)
|
||||
|
||||
onValueEdited: {
|
||||
currentValue = newValue
|
||||
changed(newValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: doubleComp
|
||||
|
||||
IncrementalPropertyControl {
|
||||
iconMode: iconModeEnum.hidden
|
||||
|
||||
property var val
|
||||
currentValue: val.toString()
|
||||
|
||||
step: 1
|
||||
minValue: 72
|
||||
maxValue: 2400
|
||||
|
||||
signal changed(var newVal)
|
||||
|
||||
onValueEdited: {
|
||||
currentValue = newValue
|
||||
changed(newValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: boolComp
|
||||
|
||||
CheckBox {
|
||||
id: checkbox
|
||||
property var val
|
||||
signal changed(var newVal)
|
||||
anchors.fill: parent
|
||||
checked: val ? true : false
|
||||
onClicked: checkbox.changed(!checkbox.checked)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
import QtQuick 2.15
|
||||
|
||||
import MuseScore.Ui 1.0
|
||||
import MuseScore.UiComponents 1.0
|
||||
|
||||
ListItemBlank {
|
||||
id: root
|
||||
|
||||
property string title: ""
|
||||
property bool isMain: false
|
||||
|
||||
signal scoreClicked()
|
||||
|
||||
height: 30
|
||||
|
||||
onClicked: {
|
||||
root.scoreClicked();
|
||||
}
|
||||
|
||||
CheckBox {
|
||||
id: scoreCheckBox
|
||||
|
||||
checked: isSelected
|
||||
|
||||
width: parent.width * 1 / 6
|
||||
height: checkBoxHeight
|
||||
|
||||
onClicked: {
|
||||
root.scoreClicked();
|
||||
}
|
||||
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: (width - checkBoxWidth) / 2
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
StyledTextLabel {
|
||||
text: root.title
|
||||
|
||||
horizontalAlignment: Qt.AlignLeft
|
||||
font: ui.theme.bodyFont
|
||||
|
||||
width: parent.width * 5 / 6
|
||||
height: parent.height
|
||||
|
||||
anchors.left: scoreCheckBox.right
|
||||
}
|
||||
}
|
|
@ -0,0 +1,121 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.15
|
||||
|
||||
import MuseScore.Ui 1.0
|
||||
import MuseScore.UiComponents 1.0
|
||||
import MuseScore.UserScores 1.0
|
||||
|
||||
Item {
|
||||
id:root
|
||||
|
||||
property var model
|
||||
|
||||
QtObject {
|
||||
id: privateProperties
|
||||
|
||||
property var leftMargin: 12
|
||||
}
|
||||
|
||||
Column {
|
||||
id: header
|
||||
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.leftMargin: privateProperties.leftMargin
|
||||
|
||||
spacing: 16
|
||||
|
||||
Row {
|
||||
width: parent.width
|
||||
height: childrenRect.height
|
||||
|
||||
CheckBox {
|
||||
id: selectAllScores
|
||||
|
||||
onClicked: {
|
||||
checked = !checked
|
||||
isIndeterminate = false
|
||||
|
||||
root.model.toggleAllSelections(checked);
|
||||
}
|
||||
|
||||
width: parent.width * 1 / 6
|
||||
height: checkBoxHeight
|
||||
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: (width - checkBoxWidth) / 2
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
StyledTextLabel {
|
||||
text: "Scores to export"
|
||||
|
||||
width: parent.width * 5 / 6
|
||||
|
||||
font.family: ui.theme.bodyBoldFont
|
||||
horizontalAlignment: Qt.AlignLeft
|
||||
font.capitalization: Font.AllUppercase
|
||||
|
||||
anchors.left: selectAllScores.right
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RoundedRectangle {
|
||||
anchors.top: header.bottom
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.leftMargin: privateProperties.leftMargin
|
||||
anchors.rightMargin: 8
|
||||
anchors.topMargin: 6
|
||||
|
||||
color: ui.theme.backgroundPrimaryColor
|
||||
|
||||
ListView {
|
||||
id: scoresButtonGroup
|
||||
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
width: parent.width
|
||||
|
||||
spacing: 0
|
||||
|
||||
model: root.model
|
||||
|
||||
boundsBehavior: Flickable.StopAtBounds
|
||||
interactive: height < contentHeight
|
||||
clip: true
|
||||
|
||||
ScrollBar.vertical: StyledScrollBar {
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 8
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: root.model
|
||||
|
||||
function onSelectionChanged() {
|
||||
var selections = root.model.selectionLength();
|
||||
|
||||
selectAllScores.checked = selections === root.model.rowCount();
|
||||
selectAllScores.isIndeterminate = selections > 0 && !selectAllScores.checked;
|
||||
}
|
||||
}
|
||||
|
||||
delegate: ExportScoreListDelegate {
|
||||
title: model.title
|
||||
isSelected: model.isSelected
|
||||
isMain: model.isMain
|
||||
|
||||
onScoreClicked: {
|
||||
root.model.toggleSelection(model.index);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,3 +1,4 @@
|
|||
module MuseScore.UserScores
|
||||
ScoresPage 1.0 ScoresPage.qml
|
||||
NewScoreDialog 1.0 NewScoreDialog.qml
|
||||
ExportDialog 1.0 ExportDialog.qml
|
||||
|
|
|
@ -44,6 +44,8 @@ public:
|
|||
MOCK_METHOD(void, setScoresPath, (const io::path&), (override));
|
||||
|
||||
MOCK_METHOD(io::path, defaultSavingFilePath, (const io::path&), (const, override));
|
||||
MOCK_METHOD(io::path, defaultExportPath, (const std::string&), (const, override));
|
||||
MOCK_METHOD(io::path, completeExportPath, (io::path, notation::INotationPtr, bool, bool, int), (const, override));
|
||||
|
||||
MOCK_METHOD(QColor, templatePreviewBackgroundColor, (), (const, override));
|
||||
MOCK_METHOD(async::Notification, templatePreviewBackgroundChanged, (), (const, override));
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
<file>qml/MuseScore/UserScores/qmldir</file>
|
||||
<file>qml/MuseScore/UserScores/NewScoreDialog.qml</file>
|
||||
<file>qml/MuseScore/UserScores/ScoresPage.qml</file>
|
||||
<file>qml/MuseScore/UserScores/ExportDialog.qml</file>
|
||||
<file>qml/MuseScore/UserScores/internal/AdditionalInfoView.qml</file>
|
||||
<file>qml/MuseScore/UserScores/internal/GeneralInfoItem.qml</file>
|
||||
<file>qml/MuseScore/UserScores/internal/KeySignatureListView.qml</file>
|
||||
|
@ -21,5 +22,8 @@
|
|||
<file>qml/MuseScore/UserScores/internal/ChooseInstrumentsAndTemplatesPage.qml</file>
|
||||
<file>qml/MuseScore/UserScores/internal/ChooseTemplatePage.qml</file>
|
||||
<file>qml/MuseScore/UserScores/internal/ScoreInfoPage.qml</file>
|
||||
<file>qml/MuseScore/UserScores/internal/ExportFilePages.qml</file>
|
||||
<file>qml/MuseScore/UserScores/internal/ExportScoresListView.qml</file>
|
||||
<file>qml/MuseScore/UserScores/internal/ExportScoreListDelegate.qml</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
|
|
@ -32,9 +32,13 @@
|
|||
#include "view/scorethumbnail.h"
|
||||
#include "view/templatesmodel.h"
|
||||
#include "view/templatepaintview.h"
|
||||
#include "view/exportscoremodel.h"
|
||||
#include "view/exportscoresuffixmodel.h"
|
||||
#include "view/exportscoresettingsmodel.h"
|
||||
#include "internal/filescorecontroller.h"
|
||||
#include "internal/userscoresconfiguration.h"
|
||||
#include "internal/userscoresservice.h"
|
||||
#include "internal/exportscoreservice.h"
|
||||
#include "internal/templatesrepository.h"
|
||||
#include "internal/userscoresuiactions.h"
|
||||
|
||||
|
@ -48,6 +52,7 @@ using namespace mu::ui;
|
|||
static std::shared_ptr<FileScoreController> s_fileController = std::make_shared<FileScoreController>();
|
||||
static std::shared_ptr<UserScoresConfiguration> s_userScoresConfiguration = std::make_shared<UserScoresConfiguration>();
|
||||
static std::shared_ptr<UserScoresService> s_userScoresService = std::make_shared<UserScoresService>();
|
||||
static std::shared_ptr<ExportScoreService> s_exportScoreService = std::make_shared<ExportScoreService>();
|
||||
|
||||
static void userscores_init_qrc()
|
||||
{
|
||||
|
@ -65,6 +70,7 @@ void UserScoresModule::registerExports()
|
|||
ioc()->registerExport<IUserScoresService>(moduleName(), s_userScoresService);
|
||||
ioc()->registerExport<ITemplatesRepository>(moduleName(), new TemplatesRepository());
|
||||
ioc()->registerExport<IFileScoreController>(moduleName(), s_fileController);
|
||||
ioc()->registerExport<IExportScoreService>(moduleName(), s_exportScoreService);
|
||||
}
|
||||
|
||||
void UserScoresModule::resolveImports()
|
||||
|
@ -78,6 +84,9 @@ void UserScoresModule::resolveImports()
|
|||
if (ir) {
|
||||
ir->registerUri(Uri("musescore://userscores/newscore"),
|
||||
ContainerMeta(ContainerType::QmlDialog, "MuseScore/UserScores/NewScoreDialog.qml"));
|
||||
|
||||
ir->registerUri(Uri("musescore://userscores/export"),
|
||||
ContainerMeta(ContainerType::QmlDialog, "MuseScore/UserScores/ExportDialog.qml"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -91,6 +100,9 @@ void UserScoresModule::registerUiTypes()
|
|||
qmlRegisterType<RecentScoresModel>("MuseScore.UserScores", 1, 0, "RecentScoresModel");
|
||||
qmlRegisterType<NewScoreModel>("MuseScore.UserScores", 1, 0, "NewScoreModel");
|
||||
qmlRegisterType<AdditionalInfoModel>("MuseScore.UserScores", 1, 0, "AdditionalInfoModel");
|
||||
qmlRegisterType<ExportScoreModel>("MuseScore.UserScores", 1, 0, "ExportScoreModel");
|
||||
qmlRegisterType<ExportScoreSuffixModel>("MuseScore.UserScores", 1, 0, "ExportScoreSuffixModel");
|
||||
qmlRegisterType<ExportScoreSettingsModel>("MuseScore.UserScores", 1, 0, "ExportScoreSettingsModel");
|
||||
|
||||
qmlRegisterType<ScoreThumbnail>("MuseScore.UserScores", 1, 0, "ScoreThumbnail");
|
||||
qmlRegisterType<TemplatesModel>("MuseScore.UserScores", 1, 0, "TemplatesModel");
|
||||
|
|
234
src/userscores/view/exportscoremodel.cpp
Normal file
234
src/userscores/view/exportscoremodel.cpp
Normal file
|
@ -0,0 +1,234 @@
|
|||
//=============================================================================
|
||||
// MuseScore
|
||||
// Music Composition & Notation
|
||||
//
|
||||
// Copyright (C) 2020 MuseScore BVBA and others
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License version 2.
|
||||
//
|
||||
// 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; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//=============================================================================
|
||||
|
||||
#include "exportscoremodel.h"
|
||||
|
||||
#include "translation.h"
|
||||
#include "uicomponents/view/itemmultiselectionmodel.h"
|
||||
|
||||
using namespace mu::userscores;
|
||||
using namespace mu::notation;
|
||||
using namespace mu::uicomponents;
|
||||
|
||||
ExportScoreModel::ExportScoreModel(QObject* parent)
|
||||
: QAbstractListModel(parent), m_selectionModel(new ItemMultiSelectionModel(this))
|
||||
, m_exportPath(configuration()->defaultExportPath(masterNotation()->metaInfo().title.toStdString()))
|
||||
{
|
||||
connect(m_selectionModel, &ItemMultiSelectionModel::selectionChanged, this, &ExportScoreModel::selectionChanged);
|
||||
}
|
||||
|
||||
void ExportScoreModel::load()
|
||||
{
|
||||
beginResetModel();
|
||||
|
||||
IMasterNotationPtr masterNotation = this->masterNotation();
|
||||
if (!masterNotation) {
|
||||
endResetModel();
|
||||
return;
|
||||
}
|
||||
|
||||
m_notations << masterNotation->notation();
|
||||
for (IExcerptNotationPtr excerpt : masterNotation->excerpts().val) {
|
||||
m_notations << excerpt->notation();
|
||||
}
|
||||
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
QVariant ExportScoreModel::data(const QModelIndex& index, int role) const
|
||||
{
|
||||
if (!index.isValid()) {
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
INotationPtr notation = m_notations[index.row()];
|
||||
|
||||
switch (role) {
|
||||
case RoleTitle:
|
||||
return notation->metaInfo().title;
|
||||
case RoleIsSelected:
|
||||
return m_selectionModel->isSelected(index);
|
||||
case RoleIsMain:
|
||||
return isMainNotation(notation);
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
int ExportScoreModel::rowCount(const QModelIndex&) const
|
||||
{
|
||||
return m_notations.size();
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> ExportScoreModel::roleNames() const
|
||||
{
|
||||
static const QHash<int, QByteArray> roles {
|
||||
{ RoleTitle, "title" },
|
||||
{ RoleIsSelected, "isSelected" },
|
||||
{ RoleIsMain, "isMain" }
|
||||
};
|
||||
|
||||
return roles;
|
||||
}
|
||||
|
||||
void ExportScoreModel::toggleSelection(int scoreIndex)
|
||||
{
|
||||
if (!isNotationIndexValid(scoreIndex)) {
|
||||
return;
|
||||
}
|
||||
|
||||
QModelIndex modelIndex = index(scoreIndex);
|
||||
m_selectionModel->QItemSelectionModel::select(modelIndex, QItemSelectionModel::Toggle);
|
||||
|
||||
emit dataChanged(modelIndex, modelIndex);
|
||||
}
|
||||
|
||||
void ExportScoreModel::toggleAllSelections(bool select)
|
||||
{
|
||||
QModelIndexList previousSelectedIndexes = m_selectionModel->selectedIndexes();
|
||||
m_selectionModel->QItemSelectionModel::select(QItemSelection(index(0), index(m_notations.size() - 1)),
|
||||
select ? QItemSelectionModel::Select : QItemSelectionModel::Deselect);
|
||||
QModelIndexList newSelectedIndexes = m_selectionModel->selectedIndexes();
|
||||
|
||||
QSet<QModelIndex> indexesToUpdate(previousSelectedIndexes.begin(), previousSelectedIndexes.end());
|
||||
indexesToUpdate = indexesToUpdate.unite(QSet<QModelIndex>(newSelectedIndexes.begin(), newSelectedIndexes.end()));
|
||||
|
||||
for (const QModelIndex& indexToUpdate : indexesToUpdate) {
|
||||
emit dataChanged(indexToUpdate, indexToUpdate);
|
||||
}
|
||||
}
|
||||
|
||||
IMasterNotationPtr ExportScoreModel::masterNotation() const
|
||||
{
|
||||
return context()->currentMasterNotation();
|
||||
}
|
||||
|
||||
bool ExportScoreModel::isMainNotation(INotationPtr notation) const
|
||||
{
|
||||
return notation == masterNotation()->notation();
|
||||
}
|
||||
|
||||
bool ExportScoreModel::isNotationIndexValid(int index) const
|
||||
{
|
||||
return index >= 0 && index < m_notations.size();
|
||||
}
|
||||
|
||||
QList<int> ExportScoreModel::selectedRows() const
|
||||
{
|
||||
QList<int> result;
|
||||
|
||||
for (const QModelIndex& index: m_selectionModel->selectedIndexes()) {
|
||||
result << index.row();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int ExportScoreModel::selectionLength() const
|
||||
{
|
||||
return selectedRows().size();
|
||||
}
|
||||
|
||||
QString ExportScoreModel::exportPath() const
|
||||
{
|
||||
return m_exportPath.toQString();
|
||||
}
|
||||
|
||||
void ExportScoreModel::setExportPath(QString path)
|
||||
{
|
||||
m_exportPath = io::path(path);
|
||||
}
|
||||
|
||||
QString ExportScoreModel::chooseExportPath()
|
||||
{
|
||||
io::path requestedPath = interactive()->selectSavingFile(qtrc("userscores", "Export Score"), m_exportPath, exportFliter());
|
||||
|
||||
if (!requestedPath.empty()) {
|
||||
m_exportPath = requestedPath;
|
||||
}
|
||||
|
||||
return m_exportPath.toQString();
|
||||
}
|
||||
|
||||
void ExportScoreModel::setExportSuffix(QString suffix)
|
||||
{
|
||||
m_exportPath = dirpath(m_exportPath) + "/" + basename(m_exportPath) + "." + suffix;
|
||||
}
|
||||
|
||||
void ExportScoreModel::exportScores()
|
||||
{
|
||||
INotationPtrList notations;
|
||||
|
||||
for (int i : selectedRows()) {
|
||||
notations.push_back(m_notations[i]);
|
||||
}
|
||||
|
||||
exportScoreService()->exportScores(notations, m_exportPath);
|
||||
}
|
||||
|
||||
int ExportScoreModel::pdfResolution() const
|
||||
{
|
||||
return imageExportConfiguration()->exportPdfDpiResolution();
|
||||
}
|
||||
|
||||
void ExportScoreModel::setPdfResolution(const int& resolution)
|
||||
{
|
||||
imageExportConfiguration()->setExportPdfDpiResolution(resolution);
|
||||
}
|
||||
|
||||
int ExportScoreModel::pngResolution() const
|
||||
{
|
||||
return imageExportConfiguration()->exportPngDpiResolution();
|
||||
}
|
||||
|
||||
void ExportScoreModel::setPngResolution(const int& resolution)
|
||||
{
|
||||
imageExportConfiguration()->setExportPngDpiResolution(resolution);
|
||||
}
|
||||
|
||||
bool ExportScoreModel::pngTransparentBackground() const
|
||||
{
|
||||
return imageExportConfiguration()->exportPngWithTransparentBackground();
|
||||
}
|
||||
|
||||
void ExportScoreModel::setPngTransparentBackground(const bool& transparent)
|
||||
{
|
||||
imageExportConfiguration()->setExportPngWithTransparentBackground(transparent);
|
||||
}
|
||||
|
||||
QString ExportScoreModel::exportFliter() const
|
||||
{
|
||||
io::path suffix = io::syffix(m_exportPath);
|
||||
|
||||
QString filter;
|
||||
|
||||
if (suffix == "pdf") {
|
||||
filter = QObject::tr("PDF files") + " (*.pdf)";
|
||||
} else if (suffix == "png") {
|
||||
filter = QObject::tr("PNG images") + " (*.png)";
|
||||
} else if (suffix == "svg") {
|
||||
filter = QObject::tr("SVG images") + " (*.svg)";
|
||||
} else if (suffix == "mp3") {
|
||||
filter = QObject::tr("mp3 audio") + " (*.mp3)";
|
||||
} else if (suffix == "midi") {
|
||||
filter = QObject::tr("midi file") + " (*.mid, *.midi)";
|
||||
}
|
||||
|
||||
return filter;
|
||||
}
|
108
src/userscores/view/exportscoremodel.h
Normal file
108
src/userscores/view/exportscoremodel.h
Normal file
|
@ -0,0 +1,108 @@
|
|||
//=============================================================================
|
||||
// MuseScore
|
||||
// Music Composition & Notation
|
||||
//
|
||||
// Copyright (C) 2020 MuseScore BVBA and others
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License version 2.
|
||||
//
|
||||
// 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; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//=============================================================================
|
||||
|
||||
#ifndef MU_USERSCORES_EXPORTSCOREMODEL_H
|
||||
#define MU_USERSCORES_EXPORTSCOREMODEL_H
|
||||
|
||||
#include "modularity/ioc.h"
|
||||
|
||||
#include "iinteractive.h"
|
||||
#include "context/iglobalcontext.h"
|
||||
#include "iuserscoresconfiguration.h"
|
||||
#include "notation/inotationwritersregister.h"
|
||||
#include "importexport/imagesexport/iimagesexportconfiguration.h"
|
||||
#include "iexportscoreservice.h"
|
||||
|
||||
namespace mu::uicomponents {
|
||||
class ItemMultiSelectionModel;
|
||||
}
|
||||
|
||||
namespace mu::userscores {
|
||||
class ExportScoreModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
INJECT(userscores, framework::IInteractive, interactive)
|
||||
INJECT(userscores, context::IGlobalContext, context)
|
||||
INJECT(userscores, IUserScoresConfiguration, configuration)
|
||||
INJECT(userscores, notation::INotationWritersRegister, writers)
|
||||
INJECT(userscores, iex::imagesexport::IImagesExportConfiguration, imageExportConfiguration)
|
||||
INJECT(userscores, IExportScoreService, exportScoreService)
|
||||
|
||||
Q_PROPERTY(int pdfResolution READ pdfResolution WRITE setPdfResolution)
|
||||
Q_PROPERTY(int pngResolution READ pngResolution WRITE setPngResolution)
|
||||
Q_PROPERTY(bool pngTransparentBackground READ pngTransparentBackground WRITE setPngTransparentBackground)
|
||||
|
||||
public:
|
||||
explicit ExportScoreModel(QObject* parent = nullptr);
|
||||
|
||||
QVariant data(const QModelIndex& index, int role) const override;
|
||||
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
|
||||
QHash<int, QByteArray> roleNames() const override;
|
||||
|
||||
Q_INVOKABLE void load();
|
||||
|
||||
Q_INVOKABLE void toggleSelection(int scoreIndex);
|
||||
Q_INVOKABLE void toggleAllSelections(bool select);
|
||||
Q_INVOKABLE int selectionLength() const;
|
||||
|
||||
Q_INVOKABLE QString exportPath() const;
|
||||
Q_INVOKABLE void setExportPath(QString path);
|
||||
Q_INVOKABLE QString chooseExportPath();
|
||||
|
||||
Q_INVOKABLE void setExportSuffix(QString suffix);
|
||||
|
||||
Q_INVOKABLE void exportScores();
|
||||
|
||||
int pdfResolution() const;
|
||||
void setPdfResolution(const int& resolution);
|
||||
|
||||
int pngResolution() const;
|
||||
void setPngResolution(const int& resolution);
|
||||
|
||||
bool pngTransparentBackground() const;
|
||||
void setPngTransparentBackground(const bool& transparent);
|
||||
|
||||
signals:
|
||||
void selectionChanged();
|
||||
|
||||
private:
|
||||
enum Roles {
|
||||
RoleTitle = Qt::UserRole + 1,
|
||||
RoleIsSelected,
|
||||
RoleIsMain
|
||||
};
|
||||
|
||||
bool isMainNotation(notation::INotationPtr notation) const;
|
||||
|
||||
bool isNotationIndexValid(int index) const;
|
||||
|
||||
notation::IMasterNotationPtr masterNotation() const;
|
||||
QList<int> selectedRows() const;
|
||||
|
||||
uicomponents::ItemMultiSelectionModel* m_selectionModel = nullptr;
|
||||
QList<notation::INotationPtr> m_notations;
|
||||
|
||||
QString exportFliter() const;
|
||||
|
||||
io::path m_exportPath;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // MU_USERSCORES_EXPORTSCOREMODEL_H
|
138
src/userscores/view/exportscoresettingsmodel.cpp
Normal file
138
src/userscores/view/exportscoresettingsmodel.cpp
Normal file
|
@ -0,0 +1,138 @@
|
|||
//=============================================================================
|
||||
// MuseScore
|
||||
// Music Composition & Notation
|
||||
//
|
||||
// Copyright (C) 2020 MuseScore BVBA and others
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License version 2.
|
||||
//
|
||||
// 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; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//=============================================================================
|
||||
|
||||
#include "exportscoresettingsmodel.h"
|
||||
|
||||
#include <QRegularExpression>
|
||||
|
||||
using namespace mu::userscores;
|
||||
using namespace mu::framework;
|
||||
|
||||
ExportScoreSettingsModel::ExportScoreSettingsModel(QObject* parent)
|
||||
: QAbstractListModel(parent)
|
||||
{
|
||||
}
|
||||
|
||||
QVariant ExportScoreSettingsModel::data(const QModelIndex& index, int role) const
|
||||
{
|
||||
if (!index.isValid() || index.row() >= rowCount()) {
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
const Settings::Item& item = m_currentItems.at(index.row());
|
||||
switch (role) {
|
||||
case SectionRole:
|
||||
return QString::fromStdString(item.key.moduleName);
|
||||
case KeyRole:
|
||||
return QString::fromStdString(item.key.key);
|
||||
case FriendlyNameRole:
|
||||
return friendlyNameFromKey(QString::fromStdString(item.key.key));
|
||||
case TypeRole:
|
||||
return typeToString(item.value.type());
|
||||
case ValRole:
|
||||
return item.value.toQVariant();
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
int ExportScoreSettingsModel::rowCount(const QModelIndex&) const
|
||||
{
|
||||
return m_currentItems.size();
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> ExportScoreSettingsModel::roleNames() const
|
||||
{
|
||||
static const QHash<int, QByteArray> roles = {
|
||||
{ SectionRole, "sectionRole" },
|
||||
{ KeyRole, "keyRole" },
|
||||
{ FriendlyNameRole, "friendlyNameRole" },
|
||||
{ TypeRole, "typeRole" },
|
||||
{ ValRole, "valRole" }
|
||||
};
|
||||
|
||||
return roles;
|
||||
}
|
||||
|
||||
void ExportScoreSettingsModel::load()
|
||||
{
|
||||
beginResetModel();
|
||||
|
||||
m_completeItems.clear();
|
||||
m_currentItems.clear();
|
||||
|
||||
Settings::Items items = settings()->items();
|
||||
|
||||
for (auto it = items.cbegin(); it != items.cend(); ++it) {
|
||||
if (it->second.key.key.find("export") != std::string::npos) {
|
||||
m_completeItems << it->second;
|
||||
m_currentItems << it->second;
|
||||
}
|
||||
}
|
||||
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
void ExportScoreSettingsModel::changeVal(int idx, QVariant newVal)
|
||||
{
|
||||
Settings::Item& item = m_currentItems[idx];
|
||||
Val::Type type = item.value.type();
|
||||
item.value = Val::fromQVariant(newVal);
|
||||
item.value.setType(type);
|
||||
|
||||
settings()->setValue(item.key, item.value);
|
||||
|
||||
emit dataChanged(index(idx), index(idx));
|
||||
}
|
||||
|
||||
void ExportScoreSettingsModel::changeType(QString type)
|
||||
{
|
||||
m_currentItems.clear();
|
||||
|
||||
beginResetModel();
|
||||
|
||||
for (auto item : m_completeItems) {
|
||||
if (item.key.key.find(type.toStdString()) != std::string::npos) {
|
||||
m_currentItems << item;
|
||||
}
|
||||
}
|
||||
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
QString ExportScoreSettingsModel::typeToString(Val::Type t) const
|
||||
{
|
||||
switch (t) {
|
||||
case Val::Type::Undefined: return "Undefined";
|
||||
case Val::Type::Bool: return "Bool";
|
||||
case Val::Type::Int: return "Int";
|
||||
case Val::Type::Double: return "Double";
|
||||
case Val::Type::String: return "String";
|
||||
case Val::Type::Color: return "Color";
|
||||
case Val::Type::Variant: return "Variant";
|
||||
}
|
||||
return "Undefined";
|
||||
}
|
||||
|
||||
QString ExportScoreSettingsModel::friendlyNameFromKey(QString key) const
|
||||
{
|
||||
QString name = key.split("/", Qt::SkipEmptyParts).last();
|
||||
name.replace(QRegularExpression("([A-Z](?=[a-z]+)|[A-Z]+(?![a-z]))"), " \\1");
|
||||
return name;
|
||||
}
|
64
src/userscores/view/exportscoresettingsmodel.h
Normal file
64
src/userscores/view/exportscoresettingsmodel.h
Normal file
|
@ -0,0 +1,64 @@
|
|||
//=============================================================================
|
||||
// MuseScore
|
||||
// Music Composition & Notation
|
||||
//
|
||||
// Copyright (C) 2020 MuseScore BVBA and others
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License version 2.
|
||||
//
|
||||
// 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; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//=============================================================================
|
||||
|
||||
#ifndef MU_USERSCORES_EXPORTSCORESETTINGSMODEL_H
|
||||
#define MU_USERSCORES_EXPORTSCORESETTINGSMODEL_H
|
||||
|
||||
#include "modularity/ioc.h"
|
||||
|
||||
#include "settings.h"
|
||||
|
||||
#include <QAbstractListModel>
|
||||
|
||||
namespace mu::userscores {
|
||||
class ExportScoreSettingsModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ExportScoreSettingsModel(QObject* parent = nullptr);
|
||||
|
||||
QVariant data(const QModelIndex& index, int role) const override;
|
||||
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
|
||||
QHash<int, QByteArray> roleNames() const override;
|
||||
|
||||
Q_INVOKABLE void load();
|
||||
Q_INVOKABLE void changeVal(int index, QVariant newVal);
|
||||
|
||||
Q_INVOKABLE void changeType(QString type);
|
||||
|
||||
private:
|
||||
enum Roles {
|
||||
SectionRole = Qt::UserRole + 1,
|
||||
KeyRole,
|
||||
FriendlyNameRole,
|
||||
TypeRole,
|
||||
ValRole
|
||||
};
|
||||
|
||||
QString typeToString(Val::Type t) const;
|
||||
|
||||
QString friendlyNameFromKey(QString key) const;
|
||||
|
||||
QList<framework::Settings::Item> m_completeItems;
|
||||
QList<framework::Settings::Item> m_currentItems;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // MU_USERSCORES_EXPORTSCORESETTINGSMODEL_H
|
85
src/userscores/view/exportscoresuffixmodel.cpp
Normal file
85
src/userscores/view/exportscoresuffixmodel.cpp
Normal file
|
@ -0,0 +1,85 @@
|
|||
//=============================================================================
|
||||
// MuseScore
|
||||
// Music Composition & Notation
|
||||
//
|
||||
// Copyright (C) 2020 MuseScore BVBA and others
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License version 2.
|
||||
//
|
||||
// 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; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//=============================================================================
|
||||
|
||||
#include "exportscoresuffixmodel.h"
|
||||
|
||||
#include "log.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
using namespace mu::userscores;
|
||||
|
||||
const std::string ExportScoreSuffixModel::DEFAULT_EXPORT_SUFFIX("pdf");
|
||||
|
||||
ExportScoreSuffixModel::ExportScoreSuffixModel(QObject* parent)
|
||||
: QAbstractListModel(parent)
|
||||
, m_defaultSuffix(0)
|
||||
{
|
||||
}
|
||||
|
||||
void ExportScoreSuffixModel::load()
|
||||
{
|
||||
beginResetModel();
|
||||
|
||||
auto suffixes = writers()->registeredSuffixes();
|
||||
|
||||
m_defaultSuffix = static_cast<int>(std::find(suffixes.begin(), suffixes.end(), DEFAULT_EXPORT_SUFFIX) - suffixes.begin());
|
||||
|
||||
for (std::string suffix : suffixes) {
|
||||
m_suffixes << QString::fromStdString(suffix);
|
||||
}
|
||||
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
QVariant ExportScoreSuffixModel::data(const QModelIndex& index, int role) const
|
||||
{
|
||||
if (!index.isValid()) {
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
switch (role) {
|
||||
case RoleSuffix:
|
||||
return m_suffixes[index.row()];
|
||||
case RoleValue:
|
||||
return index.row();
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
int ExportScoreSuffixModel::rowCount(const QModelIndex&) const
|
||||
{
|
||||
return m_suffixes.size();
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> ExportScoreSuffixModel::roleNames() const
|
||||
{
|
||||
static const QHash<int, QByteArray> roles {
|
||||
{ RoleSuffix, "suffix" },
|
||||
{ RoleValue, "value" }
|
||||
};
|
||||
|
||||
return roles;
|
||||
}
|
||||
|
||||
int ExportScoreSuffixModel::getDefaultRow() const
|
||||
{
|
||||
return m_defaultSuffix;
|
||||
}
|
60
src/userscores/view/exportscoresuffixmodel.h
Normal file
60
src/userscores/view/exportscoresuffixmodel.h
Normal file
|
@ -0,0 +1,60 @@
|
|||
//=============================================================================
|
||||
// MuseScore
|
||||
// Music Composition & Notation
|
||||
//
|
||||
// Copyright (C) 2020 MuseScore BVBA and others
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License version 2.
|
||||
//
|
||||
// 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; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//=============================================================================
|
||||
|
||||
#ifndef MU_USERSCORES_EXPORTSCORESUFFIXMODEL_H
|
||||
#define MU_USERSCORES_EXPORTSCORESUFFIXMODEL_H
|
||||
|
||||
#include "modularity/ioc.h"
|
||||
#include "notation/inotationwritersregister.h"
|
||||
|
||||
#include <QAbstractListModel>
|
||||
|
||||
namespace mu::userscores {
|
||||
class ExportScoreSuffixModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
INJECT(scores, notation::INotationWritersRegister, writers)
|
||||
|
||||
public:
|
||||
static const std::string DEFAULT_EXPORT_SUFFIX;
|
||||
|
||||
explicit ExportScoreSuffixModel(QObject* parent = nullptr);
|
||||
|
||||
QVariant data(const QModelIndex& index, int role) const override;
|
||||
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
|
||||
QHash<int, QByteArray> roleNames() const override;
|
||||
|
||||
Q_INVOKABLE void load();
|
||||
|
||||
Q_INVOKABLE int getDefaultRow() const;
|
||||
|
||||
private:
|
||||
enum Roles {
|
||||
RoleSuffix = Qt::UserRole + 1,
|
||||
RoleValue
|
||||
};
|
||||
|
||||
QList<QString> m_suffixes;
|
||||
|
||||
int m_defaultSuffix;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // MU_USERSCORES_EXPORTSCORESUFFIXMODEL_H
|
Loading…
Reference in a new issue