LCOV - code coverage report
Current view: top level - src/project/internal - projectmigrator.cpp Coverage Total Hit
Test: filtered_coverage.info Lines: 0.0 % 77 0
Test Date: 2026-11-05 04:07:02

            Line data    Source code
       1              : /*
       2              :  * SPDX-License-Identifier: GPL-3.0-only
       3              :  * MuseScore-Studio-CLA-applies
       4              :  *
       5              :  * MuseScore Studio
       6              :  * Music Composition & Notation
       7              :  *
       8              :  * Copyright (C) 2021 MuseScore Limited and others
       9              :  *
      10              :  * This program is free software: you can redistribute it and/or modify
      11              :  * it under the terms of the GNU General Public License version 3 as
      12              :  * published by the Free Software Foundation.
      13              :  *
      14              :  * This program is distributed in the hope that it will be useful,
      15              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      16              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17              :  * GNU General Public License for more details.
      18              :  *
      19              :  * You should have received a copy of the GNU General Public License
      20              :  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
      21              :  */
      22              : #include "projectmigrator.h"
      23              : 
      24              : #include <QVersionNumber>
      25              : 
      26              : #include "io/path.h"
      27              : #include "mdlmigrator.h"
      28              : 
      29              : #include "engraving/dom/excerpt.h"
      30              : #include "engraving/dom/masterscore.h"
      31              : #include "engraving/editing/editscoreproperties.h"
      32              : #include "engraving/editing/editstyle.h"
      33              : #include "engraving/editing/transaction/transaction.h"
      34              : #include "engraving/rw/compat/readstyle.h"
      35              : #include "engraving/types/constants.h"
      36              : 
      37              : #include "io/file.h"
      38              : 
      39              : #include "muse_framework_config.h"
      40              : 
      41              : #include "log.h"
      42              : 
      43              : using namespace mu;
      44              : using namespace mu::project;
      45              : using namespace mu::engraving;
      46              : using namespace mu::engraving::compat;
      47              : using namespace muse;
      48              : 
      49              : static const Uri MIGRATION_DIALOG_URI("musescore://project/migration");
      50              : static const io::path_t LELAND_STYLE_PATH(":/engraving/styles/migration-306-style-Leland.mss");
      51              : static const io::path_t EDWIN_STYLE_PATH(":/engraving/styles/migration-306-style-Edwin.mss");
      52              : 
      53            0 : static MigrationType migrationTypeFromMscVersion(int mscVersion)
      54              : {
      55            0 :     if (mscVersion < 302) {
      56            0 :         return MigrationType::Pre_3_6;
      57              :     }
      58              : 
      59            0 :     if (mscVersion < 400) {
      60            0 :         return MigrationType::Ver_3_6;
      61              :     }
      62              : 
      63            0 :     UNREACHABLE;
      64              :     return MigrationType::Unknown;
      65              : }
      66              : 
      67            0 : Ret ProjectMigrator::migrateEngravingProjectIfNeed(engraving::EngravingProjectPtr project)
      68              : {
      69            0 :     if (project->mscVersion() >= 400) {
      70            0 :         return true;
      71              :     }
      72              :     //! NOTE If the migration is not done, then the default style for the score is determined by the version.
      73              :     //! When migrating, the version becomes the current one, so remember the version of the default style before migrating
      74            0 :     project->masterScore()->style().setDefaultStyleVersion(ReadStyleHook::styleDefaultByMscVersion(project->mscVersion()));
      75            0 :     MigrationType migrationType = migrationTypeFromMscVersion(project->mscVersion());
      76              : 
      77            0 :     MigrationOptions migrationOptions = configuration()->migrationOptions(migrationType);
      78            0 :     if (migrationOptions.isAskAgain) {
      79            0 :         Ret ret = askAboutMigration(migrationOptions, project->appVersion(), migrationType);
      80              : 
      81            0 :         if (!ret) {
      82            0 :             return ret;
      83              :         }
      84              : 
      85            0 :         configuration()->setMigrationOptions(migrationType, migrationOptions);
      86            0 :     }
      87              : 
      88            0 :     if (!migrationOptions.isApplyMigration) {
      89            0 :         return true;
      90              :     }
      91              : 
      92            0 :     Ret ret = migrateProject(project, migrationOptions);
      93            0 :     if (!ret) {
      94            0 :         LOGE() << "failed migration";
      95              :     } else {
      96            0 :         LOGI() << "success migration";
      97              :     }
      98              : 
      99            0 :     return ret;
     100            0 : }
     101              : 
     102            0 : Ret ProjectMigrator::askAboutMigration(MigrationOptions& out, const QString& appVersion, MigrationType migrationType)
     103              : {
     104            0 :     UriQuery query(MIGRATION_DIALOG_URI);
     105            0 :     query.addParam("appVersion", Val(appVersion));
     106            0 :     query.addParam("migrationType", Val(migrationType));
     107            0 :     query.addParam("isApplyLeland", Val(out.isApplyLeland));
     108            0 :     query.addParam("isApplyEdwin", Val(out.isApplyEdwin));
     109            0 :     query.addParam("isRemapPercussion", Val(out.isRemapPercussion));
     110              : 
     111              : #ifndef MUSE_MODULE_INTERACTIVE_SYNC_SUPPORTED
     112              :     //! NOTE If there is no support for synchronous interactivity (web)
     113              :     //! Then we will migrate without questions
     114              : 
     115              :     out.appVersion = mu::engraving::Constants::MSC_VERSION;
     116              :     out.isApplyMigration = true;
     117              :     out.isAskAgain = false;
     118              :     out.isApplyLeland = true;
     119              :     out.isApplyEdwin = true;
     120              :     out.isRemapPercussion = true;
     121              : #else
     122            0 :     RetVal<Val> rv = interactive()->openSync(query);
     123            0 :     if (!rv.ret) {
     124            0 :         return rv.ret;
     125              :     }
     126              : 
     127            0 :     QVariantMap vals = rv.val.toQVariant().toMap();
     128            0 :     out.appVersion = mu::engraving::Constants::MSC_VERSION;
     129            0 :     out.isApplyMigration = vals.value("isApplyMigration").toBool();
     130            0 :     out.isAskAgain = vals.value("isAskAgain").toBool();
     131            0 :     out.isApplyLeland = vals.value("isApplyLeland").toBool();
     132            0 :     out.isApplyEdwin = vals.value("isApplyEdwin").toBool();
     133            0 :     out.isRemapPercussion = vals.value("isRemapPercussion").toBool();
     134              : #endif
     135              : 
     136            0 :     return true;
     137            0 : }
     138              : 
     139            0 : Ret ProjectMigrator::migrateProject(engraving::EngravingProjectPtr project, const MigrationOptions& opt)
     140              : {
     141            0 :     TRACEFUNC;
     142              : 
     143            0 :     mu::engraving::MasterScore* score = project->masterScore();
     144            0 :     IF_ASSERT_FAILED(score) {
     145            0 :         return make_ret(Ret::Code::InternalError);
     146              :     }
     147              : 
     148            0 :     score->startCmd(TranslatableString("undoableAction", "Migrate project"));
     149              : 
     150            0 :     bool ok = true;
     151            0 :     if (opt.isApplyLeland) {
     152            0 :         ok = applyLelandStyle(score);
     153              :     }
     154              : 
     155            0 :     if (ok && opt.isApplyEdwin) {
     156            0 :         ok = applyEdwinStyle(score);
     157              :     }
     158              : 
     159            0 :     if (ok && opt.isRemapPercussion) {
     160            0 :         MdlMigrator(score).remapPercussion();
     161              :     }
     162              : 
     163            0 :     score->endCmd();
     164              : 
     165            0 :     return ok ? make_ret(Ret::Code::Ok) : make_ret(Ret::Code::InternalError);
     166            0 : }
     167              : 
     168            0 : bool ProjectMigrator::applyLelandStyle(mu::engraving::MasterScore* score)
     169              : {
     170            0 :     muse::io::File styleFile(LELAND_STYLE_PATH);
     171            0 :     mu::engraving::Transaction& tx = score->transactionManager()->currentOrDummyTransaction();
     172            0 :     for (mu::engraving::Excerpt* excerpt : score->excerpts()) {
     173            0 :         if (!mu::engraving::EditStyle::loadStyle(tx, excerpt->excerptScore(), styleFile, /*ign*/ false, /*overlap*/ true)) {
     174            0 :             return false;
     175              :         }
     176              :     }
     177              : 
     178            0 :     return mu::engraving::EditStyle::loadStyle(tx, score, styleFile, /*ign*/ false, /*overlap*/ true);
     179            0 : }
     180              : 
     181            0 : bool ProjectMigrator::applyEdwinStyle(mu::engraving::MasterScore* score)
     182              : {
     183            0 :     muse::io::File styleFile(EDWIN_STYLE_PATH);
     184            0 :     mu::engraving::Transaction& tx = score->transactionManager()->currentOrDummyTransaction();
     185            0 :     for (mu::engraving::Excerpt* excerpt : score->excerpts()) {
     186            0 :         if (!mu::engraving::EditStyle::loadStyle(tx, excerpt->excerptScore(), styleFile, /*ign*/ false, /*overlap*/ true)) {
     187            0 :             return false;
     188              :         }
     189              :     }
     190              : 
     191            0 :     return mu::engraving::EditStyle::loadStyle(tx, score, styleFile, /*ign*/ false, /*overlap*/ true);
     192            0 : }
        

Generated by: LCOV version 2.0-1