Select Chord Levels (top/bottom/cardinal level 2-5)

• Jan 25, 2022 - 03:42

I had use for attempting the PruneStack plugin ( today.

It seems that changing voices wasn't working well. For example, selecting only the first level (lowest notes of chords in a range) and effectively determining to want these to be in voice-2, the provided functionality didn't actually do this. The plugin was only selecting the end of the selection or something funny, and the code itself had similar comments mentioning such due to some limitations. Pruning worked great though.

I went ahead and altered the QML so that the levels can be switched to a selected voice. After getting that to work, I realized that sometimes maybe I or another might want to not just switch the voice of whatever level of chords in a range, but rather perform some other task like octave shift, visibility, change notehead style, etc. Who knows? So I also put in another button that merely selects the results from a given range and checked level(s), resulting in list-selection (of noteheads) without any other action taken. Further commands can be issued within MS from there. Hopefully it may find some use besides meself.

BTW, I've seen plenty of posts in the past asking to be able to select all bottom notes or top notes of chords. I'm not sure if this will be the exact type of thing since "top" here is sort of relativistic depending on the amount of notes in each chord in the range, but this potentially could help someone. Bottom is always level 1.

If anyone tests it and finds something funny going on, it would be appreciated if some responses were made here. Lucky ducky Dorico 4 users have this stuff already built-in...

P.S. This kind of plugin is benefited from having a shortcut assigned to it when doing some arrangements or whatever.

P.P.S. Download @


And here's a screen-cast of some things related to this plugin. Notice that if in the selection multiple voices already exist, a "level 1" still picks up both, as they are both independent chords:


Update: "Top" is such a desirable level to select (rather than some specific layer as a number), and figuring that it must be easy to accomplish, I got that taken care of in an update and reworded the buttons so that they read as [select only], [revoice], [delete]. In essence, [select only] is the main function with [revoice] and [delete] being mere helper functions. That is, a user can easily press DEL on keyboard or use the voice buttons/shortcuts after making a selection, but figured might as well keep those in the plugin anyways. Should've done this back in 2016 when the plugin was initially offered (thanks again to OP)! Also, I sacrificed level 8 for Top and level 1 for Bottom as available options:


Update 2: Apparently you can use keyboard input with the QML plugins (didn't upload the qml to forum yet), but it seems that focus has to be set manually for it to operate. So, setting a button's focus property to true prepares the QML window for keyboard input and can receive key strokes. Point is, you can 1) set a plugin like this to be invoked by a shortcut through musescore, and then 2) use keys like 0-7 for layers of selection... This is pretty slick compared to not having it at all. Again, it's too bad MS didn't have this already built in. MS4's gotta have this in it natively or at least as a plugin in its beginning releases

Allowed for formation of a chord or a sequence from a range selection (staves + voices taken into account). Although this is different functionality and could be separate, I figured why not since it's easier to make use of all this in one plugin for me personally.

So now: keyboard shortcuts work for levels (0 for top and 1 for bottom I think it was) + 8 forms a chord + 9 forms a sequence. They get stored into the clipboard so a paste will apply the results: a chord will default to a quarter duration and a sequence will default to an eighth duration. I hope someone finds some sort of practical use, but even if not, I'll use it on occasion. Here's a demonstration (made use of retrograde plugin also for the hell of it):


In reply to by worldwideweary

Hmm, I don't seem to be able to get this new version to work on my system (Windows 10). It doesn't show up in Plugin Manager so I can't even attempt to select it. (Previous versions have been fine.)

I've tried loading it into Plugin Creator and running it from there but it fails with an error message:
Creating component failed
line 190: Expected token ;'
line 190: Expected token
Looking at it in a text editor, line 190 seems to be the line:
let uniquePitches = [ Set(pitches)];
but I don't know enough about QML coding to know what might be wrong with that. I've had a quick search on the web looking for information on QML syntax but I didn't find anything that seemed to be useful.

I've found the previous versions very useful and a nice extension of the original PruneStack concept so it is a shame that I can't get this new version to work for me. I wonder if you have any ideas what might be going wrong for me.

In reply to by MarkWWW

Thanks for the feedback. Off hand, I don't know what could be wrong, as it works fine for me on my Linux distribution. That particular line is to avoid duplication within an array of pitches for the extra two functions as shown in the most recent demonstration. Sets don't allow for duplicates, so the conversion from an array to a set and back to array is a quick/easy way to do so.

Maybe there's something up with Javascript version compatibility in MuseScore's build system for an older Qt version...

Try the following attachment and see if it works, as it appears to work for me. I'm just using
= new set(); instead of [... new set()]; here.

If that works for you, I'll replace the main attachment with this one.

P.S. I kind of ran out of room, which is why I removed the "delete" button instead of trying to move things around. I figured since delete is so easy to execute (literally press delete) after making a level selection, that it's not important to have as a button that does both at the same time). So now this is even lesser a "pruning" plugin and more of a selection filter besides the extra two functions

Edit: Attachment removed for the sake of having reference to the main plugin page instead for download

In reply to by Jojo-Schmitz

Aha! That's got it.

Yep, all working nicely now on my Windows 10 system using the version of the syntax without "let". Many thanks both of you for finding and resolving it so quickly. In truth I'm not sure if I will ever find a need for the new chord/arpeggio feature, but you never know and it's always better to have a tool and not need it than the other way around.

And as I said, the other features of the PruneStack/ChordLevels idea have been very helpful, so many thanks again.

One thing I will just mention while I'm here - I notice that if I run it from the Plugin Creator there are a lot of "Warning: QFontEngineFT: Failed to create FreeType font engine" in the bottom window after the plugin is closed. I don't know if this is indicating a real problem or is merely cosmetic (it doesn't seem to stop the plugin working in any way) but I just thought I'd mention it in case it is important.

In reply to by Jojo-Schmitz

Apparently "let" was introduced in 2015, so that means whatever version of Qt the Windows build used was older than that... (5.9). Not that important, as it only keeps a variable in the particular context only (otherwise var gives those warnings of already being declared in the same function even if in different code blocks, unlike C/C++). Useful when testing when not in different functions. JoJo's probably right about ECMA6 (ES6).

As far as the font engine,... maybe similar situation. Non of these problems or warnings are in my local build using Qt 5.12.12.

In reply to by MarkWWW

P.S. The plugin has its own little project page -

MarkWWW, if you would, try out the file attached over there instead of here. Apparently the extra chord/passage functions needed an update also after testing a few things. Even though you don't find a use case now, better to have them functional if and when you desire to use them :)

And thanks again for the help.

In reply to by worldwideweary

I've now had a chance to look at the latest version from the project page and it does now work as far as the original functions (0-7) are concerned, but unfortunately neither of the new functions (8 or 9) seem to work properly for me - they both just seem to cut the notes in the selected range to the clipboard. You can then paste them back, but they come back just as they were before, rather than assembled into a chord or spread into a sequence as they are intended to be.

Let me know if there is anything else you want me to try and I'll see what I can make of it.

Thanks again

In reply to by MarkWWW

Weird. It's working for me. I will attempt to get access to an older build built with Qt 5.9 and test within Windows. Thanks for the feedback.

By the way, are you using MuseScore 3.6.2? Also, make sure that that's the behavior when running the plugin as an actual plugin and not in the Plugin Creator mode, since I've found that in dev mode the shortcuts require to click-focus onto the plugin's interface when running first, otherwise quite literally whatever MuseScore's 9 or 8 or whatever will end up being run rather than the plugin's shortcut, which might be merely selecting a duration.

In reply to by worldwideweary

While I'm up, I found a scenario of a problem: I'm doing:
1) Copy of range selection
2) Delete it
3) Perform the create function(s) and apply results to score
4) Then form a range selection around the results
5) Perform a swap of the original with the results on the score
This seemed to work just fine for most situations, but I realize now that swap only swaps to a certain degree. That is, the length of the original range-selection and up to that is as far as it'll go. If the results were past that, then swapping will end up keeping them there which is not desirable. I switched out swapping to just do a series of undos after a cut, and it is working better on my end

But I haven't tested on Windows + Qt 5.9 so not sure. If you have extra time, a test would be appreciated until I can try a Windows system! Thanks

In reply to by worldwideweary

Yep, I'm using MuseScore v.3.6.2 and testing with it running as a real plugin in Plugin Manager (not in the Plugin Creator window). I've just downloaded the latest version on the project site (ChordLevels3x_4.qml) but I'm still getting the same behaviour - pressing 8 or 9 cuts the notes from the selection but when you come to paste them somewhere you just exactly whatever was in the original selection, not a chord or sequence of 8th notes as is intended.

In reply to by worldwideweary

Ok, after checking the default build in a Windows environment, the error messages show me that apparently ES5 (pre-2015 javascript) doesn't have includes() function nor sets. Gotta remove duplicate pitches by hand, it seems. If you've the time, please try the new attachment in the project link! If you get any error messages or something, please mention it.

Thanks again for your co-operation.

In reply to by worldwideweary

Using the new version (ChordLevels3x_5.qml) I now get different behaviour, but still not what I am expecting.

When I select a range of notes and run the plugin and choose 8 (or 9) I now get apparently nothing happening at all. The range of selected notes is now left as it was (previously it was as though the selection had been Cut), and the Plugin windows closes. Moving to an empty bar and choosing Paste now pastes nothing (where with earlier versions it pasted a copy of what had originally been selected).

There are no error messages.

In reply to by MarkWWW

Shucks. On my Windows 10 running Musescore 3.6.2, the paste works just fine. Also on my Qt 5.12.12 build for Linux distro. I'm not sure I'll be able to figure out what's wrong without being able to reproduce no pasting. Thanks again though for your testing the plugin. At least the level selectors are working on your setup machine. Would be nice if others can reproduce no pasting occurring with 8/9 functionality, out of curiosity.

Worst case, if you ever wanted that functionality, you could add c-style comments around the cut and undo commands. Results should be that it replaces what you have originally range-selected with the results, but it could overwrite something so it's riskier. Then again, ctrl-z [undo] should be able to be performed without a problem if something undesirable occurs. In other words:

Without a space between / and * (forum acts funny otherwise)
@ line 223 add / *
@ line 228 add * /
@ line 296 add / *
@ line 302 add * /

In reply to by worldwideweary

OK, I've just tried modifying ChordLevels3x_5.qml in that way, commenting out the cut and undo commands and the modified version now behaves similarly to the way it did in the earlier versions. That is, pressing either 8 or 9 now cuts the selected range out of the score and choosing paste pastes it back, but exactly as it was before, i.e. the notes are not assembled into a single chord or distributed into a sequence of eighth-notes as they are meant to be.

It's all a bit of a puzzle.

In reply to by MarkWWW

Weird man, I can't get the behavior you described on my Windows 10 Pro system + MS 3.6.2, and the code reads okay to me so I'm at a loss for now. If I can emulate your results sometime in the future, I'll reply here.

Tell ya what though, I made another pass through the code and made sure to include some semicolons + ()s that weren't there. Maybe that makes a difference depending on system versions or something, as I'm not too familiar with JavaScript and its relation to how Qt's QML functions appropriately. I also verified a few other things that needed an update on the side, and the console prints out the pitches [0-88] that are formed for verification purposes.

If you have the time, (sounds like a broken record), maybe try the new file at the project page.

In reply to by worldwideweary

Curioser and curioser.

I've now tried it with the latest version from the project page (ChordLevels3x_6.qml) and the behaviour is as before with ChordLevels3x_5.qml - nothing appears to happen to the selected range of notes and moving to an empty bar and choosing paste does not paste anything at the new location.

So I next tried it in the Plugin Creator window. I used a two bar string of quarter-notes up and down a CMaj7 arpeggio (C E G B C G E C) as my test range and when I ran the plugin and chose 8 (after first clicking on the plugin's window to make sure it had focus, as you pointed out previously) I got the line:

     Debug: Clipboard chord consists of pitches: 60,64,67,71,72

appearing in the console pane. This seems correct to me - the plugin has correctly determined that there are 5 distinct pitches in the selected range and has ordered them correctly from low to high. BUT, when I attempt to paste it somewhere, nothing appears.

My hypothesis is that the contents of the clipboard are being lost on my system for some reason when the plugin closes, so that there is nothing there to paste. But unfortunately I don't know enough about writing QML code to really investigate this hypothesis properly. And while I can believe that differences like this might occur between say Linux and Windows version due to different QML versions being used, it doesn't explain the difference between what I am seeing and what you are seeing on your Windows 10 system.

All rather confusing, really.

In reply to by MarkWWW

Update: I have another machine with a clean install of WIndows 10 + new download of MuseScore 3.6.2 from the website recently, and now I can reproduce dysfunctional behavior (oh boy). Quick check verifies that it has something to do with the way the cursor is operating. I'll see what I can do to figure it out. As to why this is inconsistent, I have no idea for now.

Update: On said system, I managed to get it to function as intended by changing the rewind expressions to explicitly store the begin tick before performing any further operations, and making use of that storage instead of relying on the current selection's begin tick, so I think maybe the nth-time might be the charm, Alice. Put it this way, I'll be ever-so-slightly-pissed if you say it doesn't work. Check it out if you have the chance.

Still can't explain why older version functions just fine on another Win and Linux system elsewhere (it could be that the other Win system has Qt Creator and newer libraries present on the machine, but that's an uneducated guess). I've also verified this new one performs as intended on the other systems (this time though I'm getting audio playback when forming chords before pasting). Once again, insert message here about appreciation of feedback - otherwise wouldn't have known about the problem. File is updated on the project page (the _7 at the end of the filename is added by the website functionality, not by me).

In reply to by worldwideweary


The _7 version is now working for me as expected - 8 and 9 now correctly read the notes in the selected range and allow a corresponding chord or sequence of eighth-notes to be pasted elsewhere.

Once again, many thanks for making this plugin available, and for having the persistence to keep on at it until finally arriving at a resolution.

I tried to use the Chord Levels plugin as it is in MS4. Although it is recognised and it runs, whenever I try to apply it MS4 crashes. Any chance it could be modified to work in MS4? (It is a very useful plugin!)

Edit: Nevermind, I found the 4x version on the Github. Thanks a lot!
Unfortunately the option of Select only is missing. It was also useful.

In reply to by worldwideweary

The only change required to make the plugin work on MU4 is replacing Qt.quit() with quit() - same as many other plugins. It's also nice, though, to set the title property, as menuPath is no longer used. I made those changes here. I encourage people to try it out, and if it seems to work for you, we can add this to the official page, or make further changes as needed.

Attachment Size
ChordLevels3x_0.qml 11.62 KB

In reply to by Marc Sabatella

I'm all for it, as long as it works in 3.x which it looks like it should. Haven't tested it yet though.

P.S. checked out your recently posted [align] plugin.

It's a nice alternative compared with using the Inspector + Y-offsetting until items "level out" upon a staff and then re-offset again. Works well in conjunction with the [Select all same staff] command (but some c++ codebase changes were required to get [same system + same staff] as one command to taste) since most of the time the y-offset changes I make are per-system when dealing with stuff like that rather than an entire score's staff.

In reply to by worldwideweary

I did test and it works on 3.6.2. Looks like Jojo already updated it, thanks!

Regarding alignment, I personally never saw any big need for a plugin in MU3 as the offset controls were readily available, but nevertheless it was a common request. MU4 pushes those offset controls behind the Appearance button though making it just enough extra work to make the plugin worthwhile.

And yes, a quick select-all-same-staff-and-system would be nice. It can be via the More dialog, but that's less convenient. I suppose the plugin could be enhanced to provide that functionality - if only a single element is selected, automatically select all similar on same staff/system, assuming that's possible.

Meanwhile, the plugin does work on range selections and that helps if you don't mind all elements aligned regardless of type - eg, articulations and staff text will all be aligned together. Also, the relatively new ability to click on one element and Shift+click another to select all similar in that range covers most cases as well.

Hi everyone, I fixed some issues with the plugin for MS4 as follows:
1. you can now delete multiple levels at the same time correctly. (it was deleting wrong levels when multiple ones selected)
2. The plugin can now identify the top note and the level number corresponding to it, so no issues occur when deleting both top note and the corresponding level number.
3. A new copy option is added, well, for copying selected levels.
4. A new "crop to levels" option is added for quicker pruning.
5. level buttons were rearranged vertically and "bottom note" is now , well, at the bottom (seemed more intuitive to me)..hope you like it.

check it out here:

I also, just released a new plugin for filtering chord levels via direct staff selections (no UI).
Check it out!…

In reply to by .ash86

Hey, just checked your filter select for MuseScore 4 without the need of a gui. Looks neat for MS4 users.

One suggestion is to convert a top note selection to be "top" instead of being a cardinal level. That is... if you select the top note of a three note triad.... let that be interpreted as "top" rather than level 3 so that if there is a four-note chord, to select also its top note. That's just an opinion though, and not sure if you'd want to go along with it.

In reply to by worldwideweary

Hey man, I'm glad you liked it.
About the top level selection, You have a good point! I actually thought of that [really, i had to sacrifice one for the other; either cardinal level selection or top level] but since I wanted the plugin to work without a ui. I couldn't think of a way to do both.. maybe add a separate plugin just for top notes?

In reply to by .ash86

I think it makes a lot more sense to just always use the top note, that's what other notation programs do at least. I havent looked at your code, but you could store the layer across chords of different sizes? So, if I select the 2nd highest note in a four note chord, cross a 3 note chord, and then select a 4 note chord again, the plugin selects again the 2nd highest note instead of the top

In reply to by XiaoMigros

It does make sense to have an option to select the top notes (you would want to select/copy the melody line). However i opted for cardinal levels because more often than not you have same size block chords and you want to double a particular level to another instrument.

If i understood your question correctly, the code does store a particular layer across different chord sizes, however, the layers are counted from the bottom up. (with a bunch of 3-note and 4-note chords for example, selecting a level 4 note would only select the top notes of the 4-note chords; selecting a level 3 note would select level 3 notes across all chords since they all contain level 3).

To achieve what you want the code should count the levels downwards (i think the code can be easily adapted to work that way, thus also solving the issue with selecting top notes) but we will run into the same problem, now with the bottom notes (when there are multiple chord sizes, that is).

I can think of a couple of option to solve this:

  1. Make the code count the levels from the the top down (as you are thinking) and add a "select bottom notes" action in a different qml file so it can be mapped to a different shortcut. (dorico's approach)
  2. Leave the plugin counting from the bottom up and add a "select top notes" action, again in a different qml.
  3. Adapt the code to select top notes iff the top note of biggest chord size is selected. (following the above example with 3 and 4 note chords, selecting level 4 note would select all top notes) - Not sure i like this idea but i'm brainstorming here.
  4. have 2 qmls with one code counting downwards and another upwards. (solves all problems, but might be confusing...?)

Any thoughts?

In reply to by .ash86

I don't see why a different qml is needed for this specifically, just parse chord.notes[chord.notes.length-1] as such and not as a fixed integer. whether the code counts bottom-up or top-down is irrelevant here. do you really think that selecting the top note is less common than selecting specifically the 3rd or 4th note? no way is that the case

In reply to by XiaoMigros

The way the code counts levels, bottom-up or top-down, is not irrelevant at all unless you only want to select top or bottom notes! The code stores level numbers. So, to select 2nd, or 3rd note from the top, no matter the chord sizes, you really need to be counting levels top-down. In which case you end up with the same earlier problem now in the bottom notes, so you'll have to add a "select bottom notes" function.

So, it's either counting up and adding "select top notes" function, or counting down and adding "select bottom notes". If you choose the former, you cant select 2nd notes from the top. If you choose the latter, you won't be able to select 2nd notes from the bottom.

In either case, you will have to leave out the option of selecting cardinal 3 (following the earlier example) across all chords. It was only in the spirit of keeping both options available that I thought of an extra qml, but you are right, you don't really need it if you don't care about selecting cardinal 3.

(we could just have 2 qmls, each counting cardinals in a particular direction, then you can make all types of selections.)

Anyway, I think it comes down to what makes more musical sense. I, personally came across situations where both were needed. As I've said before, selecting top notes is indeed useful. but so is selecting cardinal levels (think of doubling a chord level to a certain instrument). Nevertheless I'm happy to adapt the code to whatever the majority thinks is more useful. (that's why we are having this conversation, right? :))

In reply to by .ash86

if you want to select specifically the 3rd note in a chord, you could still select the 3rd note in a chord of 4 or more notes. adding a 'save the top note' function doesnt impact anything not otherwise possible, but makes the general experience much more logical. for this specifically, whether the plugin counts bottom-up or top-down is irrelevant, like I said in the above message.

In reply to by XiaoMigros

yes I agreed that the counting direction is irrelevant to selecting top or bottom notes, but not if you want to select second notes from the top. So, the question is what is more helpful, to have it select 2nd notes from the top, or select second notes from the bottom? We can't do both.

In reply to by XiaoMigros

Quoting your first reply:

I think it makes a lot more sense to just always use the top note, that's what other notation programs do at 
least. I havent looked at your code, but you could store the layer across chords of different sizes? So, if I 
select the 2nd highest note in a four note chord, cross a 3 note chord, and then select a 4 note chord again, 
the plugin selects again the 2nd highest note instead of the top

You were asking about selecting 2nd notes from the top. Or did I not understand your question correctly?

Do you still have an unanswered question? Please log in first to post your question.