From a80798b63f3799e64cc3cc14952ddedda37651a0 Mon Sep 17 00:00:00 2001 From: Kenji Noguchi Date: Sun, 14 Jun 2026 19:51:59 -0700 Subject: [PATCH] Fix appendPart not applying tablature staff type from template Score::appendPart(const InstrumentTemplate*) was passing the freshly- created default StaffType into Staff::init as the explicit preset, which shadowed t->staffTypePreset and forced every appended staff to a default standard 5-line, breaking tablature templates via the plugin API. Passing nullptr lets Staff::init fall through to t->staffTypePreset, as the post-#29478 refactor intended. Adds regression tests: - AppendPartFromTablatureTemplate: asserts appendPart of a TAB instrument yields a TAB-group, 6-line staff. - AppendPartFromStandardTemplatePreservesClefs: asserts piano gets treble + bass default clefs across its two staves. --- src/engraving/dom/score.cpp | 3 +- src/engraving/tests/scoreutils_tests.cpp | 52 ++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 2 deletions(-) diff --git a/src/engraving/dom/score.cpp b/src/engraving/dom/score.cpp index a95bfa9a59988..fd0ad477cae24 100644 --- a/src/engraving/dom/score.cpp +++ b/src/engraving/dom/score.cpp @@ -4374,8 +4374,7 @@ void Score::appendPart(const InstrumentTemplate* t) part->initFromInstrTemplate(t); for (staff_idx_t i = 0; i < t->staffCount; ++i) { Staff* staff = Factory::createStaff(part); - StaffType* stt = staff->staffType(Fraction(0, 1)); - staff->init(t, stt, int(i)); + staff->init(t, nullptr, int(i)); undoInsertStaff(staff, i); } undoInsertPart(part, m_parts.size()); diff --git a/src/engraving/tests/scoreutils_tests.cpp b/src/engraving/tests/scoreutils_tests.cpp index 82dc442230ddf..f203df4c418e6 100644 --- a/src/engraving/tests/scoreutils_tests.cpp +++ b/src/engraving/tests/scoreutils_tests.cpp @@ -23,9 +23,12 @@ #include #include "engraving/compat/scoreaccess.h" +#include "engraving/dom/clef.h" #include "engraving/dom/factory.h" +#include "engraving/dom/instrtemplate.h" #include "engraving/dom/part.h" #include "engraving/dom/staff.h" +#include "engraving/dom/stafftype.h" using namespace mu::engraving; @@ -119,3 +122,52 @@ TEST_F(Engraving_ScoreUtilsTests, StaffTestMergeMatchingRests) delete score; } + +TEST_F(Engraving_ScoreUtilsTests, AppendPartFromTablatureTemplate) +{ + // [GIVEN] A score and the Classical Guitar (tablature) instrument template + MasterScore* score = compat::ScoreAccess::createMasterScore(nullptr); + const InstrumentTemplate* t = searchTemplate(String(u"guitar-nylon-tablature")); + ASSERT_NE(t, nullptr); + ASSERT_NE(t->staffTypePreset, nullptr); + ASSERT_EQ(t->staffTypePreset->group(), StaffGroup::TAB); + + // [WHEN] The part is appended via the engraving API used by the plugin layer + score->appendPart(t); + + // [THEN] The resulting staff is a TAB staff, not a default standard staff + ASSERT_EQ(score->parts().size(), 1u); + Part* part = score->parts().front(); + EXPECT_TRUE(part->hasTabStaff()); + EXPECT_FALSE(part->hasPitchedStaff()); + + ASSERT_EQ(part->nstaves(), 1u); + const StaffType* stt = part->staff(0)->staffType(Fraction(0, 1)); + EXPECT_EQ(stt->group(), StaffGroup::TAB); + EXPECT_EQ(stt->lines(), 6); + + delete score; +} + +TEST_F(Engraving_ScoreUtilsTests, AppendPartFromStandardTemplatePreservesClefs) +{ + // [GIVEN] A score and the Piano template (two staves, treble + bass) + MasterScore* score = compat::ScoreAccess::createMasterScore(nullptr); + const InstrumentTemplate* t = searchTemplate(String(u"piano")); + ASSERT_NE(t, nullptr); + + // [WHEN] The part is appended + score->appendPart(t); + + // [THEN] Both staves are standard, with the template's per-staff clefs applied + ASSERT_EQ(score->parts().size(), 1u); + Part* part = score->parts().front(); + EXPECT_TRUE(part->hasPitchedStaff()); + EXPECT_FALSE(part->hasTabStaff()); + + ASSERT_EQ(part->nstaves(), 2u); + EXPECT_EQ(part->staff(0)->defaultClefType().concertClef, ClefType::G); + EXPECT_EQ(part->staff(1)->defaultClefType().concertClef, ClefType::F); + + delete score; +}