Skip to content

Conversation

@manolo
Copy link
Contributor

@manolo manolo commented Nov 16, 2025

Problem:

While Issue #27204 and PR #1006 fixed property delegation from SpannerSegment to parent Spanner objects, plugins still have no way to iterate through or access the spanners collection in a score preventing plugins from:

  • Finding hairpins to disable playback
  • Modifying slur properties across the score
  • Accessing other spanner types (ottavas, pedal lines, etc.)

Currently, spanners cannot be accessed via:

  • note.spannerForward (only works for tied/slurred notes)
  • segment.annotations (only contains dynamics, expressions, etc.)
  • segment.elementAt() (doesn't return spanners)
  • system.spannerSegments (not exposed to Plugin API)

Solution:

Expose the spanners collection as a QML property on Score, similar to existing collections (parts, staves, pages, systems).

Changes:

  1. Implemented Score::spannerList() in dom/score.cpp to convert internal multimap to vector
  2. Declared spannerList() in dom/score.h (declaration already existed)
  3. Added Q_PROPERTY spanners to api/v1/score.h
  4. Implemented QML wrapper in api/v1/score.cpp
  5. Comprehensive test validating access and properties in spanners_tests.cpp

Usage in plugins:

Remove slurs when adapting violin part to bandurria (bandurria is plucked, cannot do legato like violin)

    for (var i = 0; i < curScore.spanners.length; i++) {
        var spanner = curScore.spanners[i];
        if (spanner.type === Element.SLUR &&
            spanner.track >= bandurriaPart.startTrack &&
            spanner.track < bandurriaPart.endTrack) {
            removeElement(spanner);
        }
    }

Related:

  • Issue #27204: Property delegation fix for SpannerSegment
  • PR #1006i: Added SPANNER_TICK/SPANNER_TICKS to propertyDelegate

Resolves: #31061

  • 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)

    Problem:
    --------
    While Issue [musescore#27204](musescore#27204) and
    PR [musescore#1006](Jojo-Schmitz#1006) fixed property delegation from
    SpannerSegment to parent Spanner objects, plugins still have no way
    to iterate through or access the spanners collection in a score
    preventing plugins from:

    - Finding hairpins to disable playback
    - Modifying slur properties across the score
    - Accessing other spanner types (ottavas, pedal lines, etc.)

    Currently, spanners cannot be accessed via:
    - note.spannerForward (only works for tied/slurred notes)
    - segment.annotations (only contains dynamics, expressions, etc.)
    - segment.elementAt() (doesn't return spanners)
    - system.spannerSegments (not exposed to Plugin API)

    Solution:
    ---------
    Expose the spanners collection as a QML property on Score, similar
    to existing collections (parts, staves, pages, systems).

    Changes:
    1. Implemented Score::spannerList() in dom/score.cpp to convert internal multimap to vector
    2. Declared spannerList() in dom/score.h (declaration already existed)
    3. Added Q_PROPERTY spanners to api/v1/score.h
    4. Implemented QML wrapper in api/v1/score.cpp
    5. Comprehensive test validating access and properties in spanners_tests.cpp

    Usage in plugins:
    -----------------
    // Remove slurs when adapting violin part to bandurria (bandurria is plucked, cannot do legato like violin)
    for (var i = 0; i < curScore.spanners.length; i++) {
        var spanner = curScore.spanners[i];
        if (spanner.type === Element.SLUR &&
            spanner.track >= bandurriaPart.startTrack &&
            spanner.track < bandurriaPart.endTrack) {
            removeElement(spanner);
        }
    }

    Related:
    --------
    - Issue [musescore#27204](musescore#27204): Property delegation fix for SpannerSegment
    - PR [#1006i](Jojo-Schmitz#1006): Added SPANNER_TICK/SPANNER_TICKS to propertyDelegate
@manolo
Copy link
Contributor Author

manolo commented Nov 16, 2025

Ups, it's nice that two people were working on this at the same time.
Visiting PRs I saw that there is another PR previous to this exposing the same thing to the API, so I can close this.

@manolo manolo closed this Nov 16, 2025
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.

Plugin API: Cannot access spanners collection

1 participant