Skip to content

Conversation

@manolo
Copy link
Contributor

@manolo manolo commented Jan 11, 2026

Resolves #31656
Supersedes #31658

Summary

Part name changes in the Parts dialog now persist after save/reload, even for parts that were never opened as tabs.

This implements the "lightweight excerpts" approach suggested in the review of #31658: instead of fully initializing excerpts just to save their names, we store minimal metadata (~400 bytes) without creating a full Score (several KB per excerpt) saving resources.

Changes

Engraving layer:

  • Add MasterScore::addLightweightExcerpt() to add excerpts without initialization
  • Add lightweight excerpt write support in MscSaver (name, parts, tracksMapping, initialPartId)
  • Add lightweight excerpt read support in MscLoader with <lightweight> marker detection
  • Add null checks in initParts(), rebuildExcerptsMidiMapping(), and onWriteExcerpts302() for excerpts without excerptScore
  • Add Excerpt::setInited() public setter for deinit support

Notation layer:

  • Add MasterNotation::promotePotentialExcerptToLightweight() to promote renamed potential excerpts
  • Skip lightweight excerpts when applying styles to all parts
  • Skip lightweight excerpts when collecting parts for operations
  • Skip writing viewsettings/audiosettings for lightweight excerpts
  • Add ExcerptNotation::deinit() and MasterNotation::deinitExcerpts() to restore lightweight state after export
  • I signed the CLA
  • The title of the PR describes the problem it addresses
  • Each commit's message describes its purpose and effects, and references the issue it resolves
  • If changes are extensive, there is a sequence of easily reviewable commits
  • The code in the PR follows the coding rules
  • There are no unnecessary changes
  • The code compiles and runs on my machine, preferably after each commit individually
  • I created a unit test or vtest to verify the changes I made (if applicable)

@manolo manolo force-pushed the fix/potential-excerpt-rename-persistence branch from 707e3d9 to 26c498e Compare January 11, 2026 21:39
@manolo
Copy link
Contributor Author

manolo commented Jan 11, 2026

@cbjeukendrup let me know if the implementation fits your suggestions. If so, I can continue with the two issues you mentioned regarding reset and delete functionality, probably in a separate PR once this is accepted.

…1656)

Add tests to verify that excerpt properties can be stored and persisted:

- uninitializedExcerptProperties: verifies that an Excerpt without
  excerptScore can store name and parts
- renamePotentialExcerpt: verifies that excerpt names persist through
  save/reload (baseline test using initialized excerpt)

These tests establish the foundation for lightweight excerpt support,
which will enable renaming potential excerpts without opening them.

Related: musescore#31656
Add support for saving lightweight excerpts (potential excerpts without
excerptScore) in MSCZ format:

- MasterScore::addLightweightExcerpt(): adds excerpt without initParts
- writeLightweightExcerpt(): writes minimal XML containing only:
  - lightweight marker
  - name
  - tracksMapping
  - initialPartId
  - part references

This enables persisting renamed potential excerpts without creating
full excerptScore, reducing file size from ~16KB to ~400 bytes per
lightweight excerpt.

Related: musescore#31656
Add support for loading lightweight excerpts from MSCZ format:

- isLightweightExcerpt(): detects lightweight format by checking for
  <lightweight> element in excerpt XML
- readLightweightExcerpt(): parses minimal XML and reconstructs Excerpt
  with name, tracksMapping, initialPartId, and part references
- Parts are resolved by ID from the master score's parts list

Lightweight excerpts are loaded without creating excerptScore, preserving
their lightweight nature until the user opens them.

Related: musescore#31656
Integrate lightweight excerpt support into the notation layer:

MasterNotation:
- promotePotentialExcerptToLightweight(): moves ExcerptNotation from
  potentialExcerpts to excerpts when renamed, ensuring consistency
  between notation and engraving layers
- initExcerptNotations(): creates ExcerptNotation without init() for
  lightweight excerpts
- updateExcerpts(): handles lightweight excerpts in excerpt list updates

ExcerptNotation:
- setName(): calls promotePotentialExcerptToLightweight() for potential
  excerpts and marks project as unsaved

NotationProject:
- Skip writing viewsettings.json and audiosettings.json for lightweight
  excerpts (they have no meaningful settings)

Related: musescore#31656
@manolo manolo force-pushed the fix/potential-excerpt-rename-persistence branch from 26c498e to 0aa9a45 Compare January 12, 2026 06:49
Add null checks when iterating over excerpts to prevent crashes when
lightweight excerpts (with no excerptScore) are present:

NotationStyle::applyToAllParts():
- Skip excerpts without excerptScore when applying style to all parts

MasterNotationParts::excerptsParts():
- Skip lightweight excerpts when collecting parts for operations

MasterNotationParts::replaceInstrument():
- Handle lightweight excerpts separately when renaming excerpt after
  instrument replacement (use direct rename instead of undo-based)

These fixes ensure that code iterating over excerpts doesn't crash
when the list includes lightweight (potential) excerpts.
Add saveLightweightExcerpt test that verifies:
- Lightweight excerpts can be saved to MSCZ format
- Name, parts, initialPartId persist through save/reload
- Excerpt remains lightweight after reload (no excerptScore)
- No unnecessary files (viewsettings.json, audiosettings.json)
- XML content is minimal (has <lightweight> marker, no Staff/Measure)
- File size is small (< 1KB vs ~16KB for full excerpt)

This test ensures the lightweight excerpt implementation works
correctly end-to-end.

Related: musescore#31656
When exporting parts that were temporarily initialized for export,
they would remain initialized and get saved as full excerpts on
subsequent save operations. This fix adds deinitExcerpts() which
restores excerpts to their lightweight state after export completes.

Changes:
- Add ExcerptNotation::deinit() to reset excerpt to lightweight state
- Add MasterNotation::deinitExcerpts() interface method
- Call deinitExcerpts in export DEFER block after export completes
- Make Excerpt::setInited() public for use by deinit
- Add test for lightweight excerpt init/deinit cycle
@manolo manolo force-pushed the fix/potential-excerpt-rename-persistence branch from 0aa9a45 to 04c2133 Compare January 12, 2026 08:34
@manolo manolo force-pushed the fix/potential-excerpt-rename-persistence branch from 03d4df1 to c0dc1af Compare January 12, 2026 09:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Part name changes in Parts dialog not saved until part is opened as tab

1 participant