Only transpose when instrument transposition has changed#32951
Only transpose when instrument transposition has changed#32951miiizen wants to merge 1 commit intomusescore:masterfrom
Conversation
📝 WalkthroughWalkthroughThe 🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/notation/internal/masternotationparts.cpp`:
- Around line 202-207: oldTranspose is being read after the part's instrument is
mutated so it may already reflect newInstrument.transpose(), causing the
equality check with newTranspose to incorrectly skip calling
engraving::Transpose::transpositionChanged(...). Fix by capturing
mu::engraving::Interval oldTranspose = part ? part->instrument()->transpose() :
mu::engraving::Interval(0,0) before you replace the part's instrument (before
the code that assigns or swaps in newInstrument), keep newTranspose =
newInstrument.transpose() as is, and then perform the oldTranspose !=
newTranspose check and call engraving::Transpose::transpositionChanged(score(),
part, Part::MAIN_INSTRUMENT_TICK, oldTranspose) afterward.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: fc9f7437-df79-4d82-9e35-b09deaf5c277
📒 Files selected for processing (1)
src/notation/internal/masternotationparts.cpp
| mu::engraving::Interval oldTranspose = part ? part->instrument()->transpose() : mu::engraving::Interval(0, 0); | ||
| mu::engraving::Interval newTranspose = newInstrument.transpose(); | ||
| // this also transposes all linked parts | ||
| engraving::Transpose::transpositionChanged(score(), part, Part::MAIN_INSTRUMENT_TICK, oldTranspose); | ||
| if (oldTranspose != newTranspose) { | ||
| engraving::Transpose::transpositionChanged(score(), part, Part::MAIN_INSTRUMENT_TICK, oldTranspose); | ||
| } |
There was a problem hiding this comment.
Capture oldTranspose before instrument replacement to avoid skipping required transposition.
oldTranspose on Line 202 is read after Line 196 mutates the part instrument, so it can already be the new value. In real transposition changes, this can make the Line 205 guard false and incorrectly skip transpositionChanged(...).
💡 Proposed fix
- NotationParts::replaceInstrument(instrumentKey, newInstrument, newStaffType);
-
- for (const INotationPartsPtr& parts : excerptsParts()) {
- parts->replaceInstrument(instrumentKey, newInstrument, newStaffType);
- }
-
- mu::engraving::Interval oldTranspose = part ? part->instrument()->transpose() : mu::engraving::Interval(0, 0);
- mu::engraving::Interval newTranspose = newInstrument.transpose();
+ mu::engraving::Interval oldTranspose = part ? part->instrument()->transpose() : mu::engraving::Interval(0, 0);
+ mu::engraving::Interval newTranspose = newInstrument.transpose();
+
+ NotationParts::replaceInstrument(instrumentKey, newInstrument, newStaffType);
+
+ for (const INotationPartsPtr& parts : excerptsParts()) {
+ parts->replaceInstrument(instrumentKey, newInstrument, newStaffType);
+ }
// this also transposes all linked parts
- if (oldTranspose != newTranspose) {
+ if (part && oldTranspose != newTranspose) {
engraving::Transpose::transpositionChanged(score(), part, Part::MAIN_INSTRUMENT_TICK, oldTranspose);
}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/notation/internal/masternotationparts.cpp` around lines 202 - 207,
oldTranspose is being read after the part's instrument is mutated so it may
already reflect newInstrument.transpose(), causing the equality check with
newTranspose to incorrectly skip calling
engraving::Transpose::transpositionChanged(...). Fix by capturing
mu::engraving::Interval oldTranspose = part ? part->instrument()->transpose() :
mu::engraving::Interval(0,0) before you replace the part's instrument (before
the code that assigns or swaps in newInstrument), keep newTranspose =
newInstrument.transpose() as is, and then perform the oldTranspose !=
newTranspose check and call engraving::Transpose::transpositionChanged(score(),
part, Part::MAIN_INSTRUMENT_TICK, oldTranspose) afterward.
6add974 to
170bd98
Compare
There was a problem hiding this comment.
♻️ Duplicate comments (1)
src/notation/internal/masternotationparts.cpp (1)
206-208:⚠️ Potential issue | 🔴 CriticalAdd a null guard for
partbefore callingtranspositionChanged.
transpositionChanged()dereferencespart; current guard allows a nullpartpath whenoldTranspose != newTranspose, which can crash.Proposed fix
- if (oldTranspose != newTranspose) { + if (part && oldTranspose != newTranspose) { engraving::Transpose::transpositionChanged(score(), part, Part::MAIN_INSTRUMENT_TICK, oldTranspose); }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/notation/internal/masternotationparts.cpp` around lines 206 - 208, The call to engraving::Transpose::transpositionChanged(score(), part, Part::MAIN_INSTRUMENT_TICK, oldTranspose) can dereference a nullptr because we only check oldTranspose != newTranspose; add a null guard for the part pointer before invoking transpositionChanged (e.g., check that part is non-null with if (part) or bail out/return when part is null) so that transpositionChanged is only called when part is valid.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Duplicate comments:
In `@src/notation/internal/masternotationparts.cpp`:
- Around line 206-208: The call to
engraving::Transpose::transpositionChanged(score(), part,
Part::MAIN_INSTRUMENT_TICK, oldTranspose) can dereference a nullptr because we
only check oldTranspose != newTranspose; add a null guard for the part pointer
before invoking transpositionChanged (e.g., check that part is non-null with if
(part) or bail out/return when part is null) so that transpositionChanged is
only called when part is valid.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: ea70b09b-1aeb-4e03-b273-3a29816ad6ef
📒 Files selected for processing (1)
src/notation/internal/masternotationparts.cpp
|
@miiizen Screencast.from.2026-04-09.11-43-24.webmAlso, could we refine this further to not reset spelling when changing to an octave transposing instrument with the same transposition pitch class? E.g. Clar. in Bb -> Bass Clarinet in Bb, Alto Sax -> Baritone Sax, etc. (This behaviour is already in place for octave transposing instruments in C, e.g. Flute -> Piccolo in C). |
Resolves: #32393