QML api: "Select an element" needed so plugins can search

• Aug 5, 2019 - 19:34
Reported version
S5 - Suggestion

The desirability of having plugins to look for a specific thing, e.g., a certain harmonic or contrapuntal feature, or, most significantly, a word or string of lyric or text, seems self-evident.

All that is needed (as far as I can tell) is the ability to select an extant element (as does clicking single on it) exposed to QML.


The ability to select elements from plugins could certainly be useful but I believe it should be added with some caution. While preparing 3.0 release (and perhaps some time after it) we had a lot of issues related to wrong elements being somehow added to a selection, for example, some elements that may get deleted during a re-layout (Brackets for example). Such elements are better not to be added to a selection. Other elements (like Measure, Segment) cannot normally be directly added to a selection, and it is not clear what can happen if we put such an element to the selected elements list.

Unfortunately libmscore does not currently have any mechanism to determine which elements can be added to a selection and which cannot. Some information on which elements are probably safe to be selected programmatically can be found in UndoStack implementation as we try to make selection undoable in the cases when it is most necessary and safe to implement. Maybe for the time being the same set of restrictions (maybe with some exceptions like Chord type) could be applied for plugins too.

What should be probably safer to implement is allowing a range selection: it is enough just to define its boundaries and all the relevant elements will be found automatically.

So, to sum up, for now it seems to be better to an ability to select only a limited subset of elements and/or an ability to select a range of a score. Does this make sense for this feature request?

By the way, concerning the "so plugins can search" part, it should be also needed to allow plugins to adjust score view position (either by specifying a position directly or by going to a specific element), otherwise it may happen to be not easy to figure out what exactly a plugin has found.

These are reasonable reservations; the rest of "search" (e.g., position the score) is needed. The largest "search" thing I currently find missing is find text, extremely important to me because I write (to the joy of many) pamphlet/book texts in many of my scores and cannot find text I have entered. But a lot is missing for that, including QML visibility of frames, words within text, and more. Finding a particular chord or stack of notes (in a part or the score) would be great, too. I had hoped that this would be the start for experimentation, but so much more is needed (and I am studying the source). This should not be on a 3.3 timeframe, obviously.

dmitrio95 Your concerns are understandable, but these are plugins. It should be made clear to plugin developpers that selecting elements is risky, but that PR doesn't change anything to non-plugin users, doesn't it?

@BSG have you tried cmd("select-all") and looping through the selection?
Summary of what you could do:
2.find your element
3.loop through the element's parent (recursion?) to find a measure.
4.cmd("select-next-measure") until you find the measure (the tick is the only thing I could compare here to check if i had found my measure)
5. cmd("staff-text") to scroll down to your element. then cmd("escape") to exit staff text entering mode. or maybe cmd("play"), so the cursor show you where you are.

for the cmd commands, this thing is pretty useful: https://github.com/calculuswhiz/musescore-utils/blob/master/ValidComman…
Of course, this is unconvenient, it it still gives some possibilities...

Type Functional Plugins

Deselecting elements should probably be a lot safer to implement in plugins API. In fact I believe it should probably be relatively safe to implement the following operations:
- Clearing selection;
- Removing elements from a selection;
- Selecting a range of a score (defined by ticks and staves range);
- Selecting elements from a limited set of types, as it is unclear how to handle selection of elements that may potentially be deleted a bit later.

Concerning your second comment, as I mentioned above, it would indeed be logical to expose to plugins some part of ScoreView's functionality in the context of this feature request, maybe it could indeed be some functions like gotoMeasure() or adjustCanvasPosition() or even just something to simply set a viewport for a score view (maybe something similar to this).

For now the easiest method to add a command to the API looks to be adding it to the cmd commands. Maybe gotoMeasure could be implemented that way...
Ex: cmd("go-to-measure-22") would call searchMeasure(22)
but that would be better implemented directly in the plugin api: override the cmd function by creating a callCmd which would filter the cmd call and transfer it the usual cmd if needed.
The cmd called by plugins would look like (sorry, can't do any c++ recently, so i don't remember all these function names so well...)

void callCmd(const Srtring* command) {
// filter command ex:
if (command.startswith("go-to-measure-"))
// Keep filtering with other commands
//delegate to normal cmd:

In reply to by [DELETED] 1831606

@BSG Just tried the technique above. Unfortunately, cmd select all selects the whole range of the score. This means text, barlines, etc. are not part of the selection...
In my case it worked because I had to look only into rehearsal marks, so I could ask the user to select one and use cmd("select-similar") but that wouldn't work to loop through all text elements...

Yes, texts are included. It is the same list of types which is used to preserve selection on undo/redo operations (defined here): currently notes, rests, most of text elements (except for instrument names which are probably not accessible yet from plugins anyway) and fretboard diagrams. This list can certainly be changed in future but probably only by including more element types in it.

Fix version