Best practice for plugin UI
I'm trying to put together a small set of simple plugins that will mostly need dialog boxes with one or two controls and OK/Cancel buttons. Looking at the existing plugins, they are kind of all over the map in terms of how they create their UI. Most don't really handle sizing well (the dialog is either too big or more often too small for its contents), and also, keyboard navigation within these seems to be largely non-existent (e.g., click in a spin box and press Up or Down and nothing happens. I'm trying to figure out if there is a good solution to these basic problems, so I can do a good job in my own plugins, and maybe we can collectively aim for a similar approach across the board.
Note: I am an absolute beginner when it comes to QML, all I know is what little I've gleaned from looking at other code and reading a couple of specific help pages.
I gather for plugins that want a dialog, one way is to use pluginType: dialog. It's not clear to me how OK & Cancel buttons are supposed to be handled if so - it looks like we have to build these ourselves, which makes this seem much less desirable than actually creating and showing a QML Dialog, which knows already how to build, position, label, and hook up these buttons. But probably there is some other advantage to using pluginType I am not aware of. Right now I have a plugin working equally well (functionality-wise) and equally badly (UI-wise) either way.
Any suggestions?
Comments
edit: removed : rereading your question makes me realize you may be asking for suggestion of a balanced ui building capability of future plugin engine instead of asking for advice to build a good ui. I'm gonna reply more to the point in a new comment.
In reply to Working with ui in qml makes… by msfp
Commenting on ms3 as not experienced in ms4
> collectively aim for a similar approach across the board.
For plugin dev, determining good ui includes
1) item/component size
2) item/component pos
3) plugin window size
Difficulties
Making these accessible 'd be useful or create a guideline in dev handbook if exist already
the plugin window size may not be a problem if devs can create dockable plugin
Alternative 1
dockable
pros:
cons:
Dockable plugin has the advantage of dialog plugin, the opposite is not true. This makes dockable more useful for ambitious dev but confusing for those aiming for to provide simple function.
Dockable should be picked as the main parent component of a generalize plugin ui framework, dialog as a optional descendent popup component. Considering dialog's nature, complex sizing of it is usually not needed.
Then offer devs some one-click templates/functions that one can setup simple UI and write a simple plugin quickly.
Alternative2
REAPER plugins separate concerns: plugin dev create "actions", users are required to manually create new custom toolbar buttons that have unified style in the app and then attached a action to it .
> keyboard
For your plugin, ms3 plugin and QML tutorial especially the boilerplates gathered clever codes shared selflessly on this forum.
There's no centralized simple keyboard navigation profile to set on plugin scope, which is disappointing, as I assumed a plugin scripting language for hobbyist coder should have. I then searched for the designated qml object to attach keyboard handlers but also found none, so I'm using a basic component with focus:true (it is a property, not the current focus state) to grab the focus. There's a capture property too, to
stop propagation
but I'm yet find a good use.Upon
curScore.endcmd()
, the plugin window's focus and hence the key capture may lossThere's one musescore scope handler but requires caution to use nicely, as matt28 did nicely in his workaround, find that in the link.
> actually creating and showing a QML Dialog,
I didn't realize I can wrap the whole app, I'll try that out. Thanks for the idea.
In reply to solution wise i'd do similar… by msfp
Thanks for the comments I'm afraid most of it is over my head since I'm a QML newbie. But, the overall impression I am getting is, maybe there actually isn't a good solution already known, and that's why the current state of plugins is so bad. I mean, no way should individual plugin developers have to be worrying about font sizes or element sizes or dialog sizes. In any UI-building system I've ever used, you say what controls you want, and the system chooses appropriate defaults. The buttons are automatically made big enough for the text within them, and the dialog is automatically made big enough for the buttons within them, etc. This just doesn't seem to be the case with QML - or at least, with QML as current plugins seem to be using it. I have to believe QML itself is capable of it and we're all just missing something...
Regarding keyboard focus, I have seen documentation on the focus property, also forceActiveFocus. I have just so far failed in any effort to get it to actually work. If someone knows of a plugin with a working spin box - where you can click in the field and use cursor keys - let me know so I can study the code!
In reply to Thanks for the comments I'm… by Marc Sabatella
> no way should individual plugin developers have to be worrying about font sizes or element sizes or dialog sizes.
Totally agree. Who would expect they need to build app-level UI pixel by pixel when they only want to run some "script" or "macro"? And the language limited to the unpopular QML?
This problem could easily be fixed by harnessing the ready-to-use and most popular css / html by making Webengine + WebChannel module available. I thought I cleared out that hurdle for ms3, only be told later that Webengine only works on win built of ms3.
In reply to solution wise i'd do similar… by msfp
To be honest, I never worry about font size. The only cases when I worry about font size is when I use exotic fonts such as Fiati or music fonts such as Bravura, MScore.
My base boilerplate for writing dialog plugins
It includes the following feature:
SystemPalette.Active
andSystemPalette.Disabled
for proper color managementThe latter can be tricky because translations structure differs from MS3 and MS4.
E.g. for a "title" label:
Remarks
My plugin boilerplate
In reply to To be honest, I never worry… by parkingb
edit: qmllearning.qml see https://musescore.org/en/node/345720
> Marc Sabatella : ...the system chooses appropriate defaults...
shall we slay that QML dragon for future plugin devs? though, I truly believe allowing css / html is the proper way
> parkingb: ...DialogButtonBox...
Thank you, that's very useful. I cannot understand SystemPalette, how do you use it?
progress (outdated version):
In reply to > Marc Sabatella : ...the… by msfp
> Marc Sabatella: ... dialog is automatically made big enough for the buttons within them...
Absolutely right. That simplifies uibuilding and make life easier for almost all of the time, though I recall an old version of adobe reader had a silly bug that the preference window is bigger than my screen so that I cannot scroll to other options, and see and click ok or quit!
My previous post's dockable plugin suggestion is all about this.
What do you think is safe for the window size? 800x600 pixel? is there any guideline?
edit: after several tries, the automatic window dimension based on UI content method by parkingb GridLayout { } definitely works
In reply to > Marc Sabatella: ... dialog… by msfp
Added devhandbook page https://musescore.org/en/node/345720
Feel free to edit the qmllearning code there, no need to ask for permission
In reply to Added devhandbook page https… by msfp
@Marc Sabatella
Opps, there is a type for key navigation afterall, sorry for misleading eariler.
And it's conveniently named KeyNavigation
https://doc.qt.io/qt-5/qml-qtquick-keynavigation.html
https://youtu.be/sv2e7Dogk68?t=143
In reply to @Marc Sabatella Opps, there… by msfp
Nice; right now though I can get even a single spinbox to respond to keyboard input, much less to be able to navigate. So my problem I think is more about getting focus, and finding the magic combination of "focus" and "forceActivefocus" just to get started. But I'm slowly finding my way around thanks to the help here!
In reply to > Marc Sabatella : ...the… by msfp
> I cannot understand SystemPalette, how do you use it?
I'm using it to ensure the right and colour matching in light and dark mode (and also tweak the dark mode whom RadioButton and CheckBox have an invalid text colour unless you force it
SystemPalette.Active.Text
).Some examples
BatchConvert
Status bar
(PS: this example is under "palette-ization" and the I haven't applied the right colour to the text themselves)
In reply to > I cannot understand… by parkingb
so SystemPalette is the musescore theme status, I thought it was inaccessible because I didn't find in API documentation. Thanks.
In reply to > Marc Sabatella : ...the… by msfp
Looking at this more closely, it seems it still relies on having to guess at arbitrary numbers for width and height of certain elements rather than let QML figure it out automatically. Is there truly no way to avoid this?
In reply to Looking at this more closely… by Marc Sabatella
Hi Marc, my UI boilerplate does not require any dimension !
The only one presents are those 4 ones and are only set for the sake of the demo. You can get rid of these in a working UI.
In reply to Hi Marc, my UI boilerplate… by parkingb
Confirmed, thank you so much! I see now two things of interest that presumably are the key - setting fillWidth to true for the components within the dialog, and perhaps also the line where you explicitly set the width of the dialog itself to the implicitWidth of the components. But also some other interesting things like the id: mainWindow that seems intriguing...
In reply to Confirmed, thank you so much… by Marc Sabatella
id: mainWindow
(or whatever id name you'd like to give) is used forIn reply to id: mainWindow (or whatever… by parkingb
Thanks, I see this. I was previously thinking somehow it allowed to to ac cess the actual main window's properties :-)
The main thing I am still struggling with is getting any form of keyboard focus. Nothing I do seem to allow allow focus to go to the dialog. It always remains in the main application window, so Tab etc simply moves around the controls there. I've tried all sorts of variations on setting focus: true for different elements, calling forceActiveFocus(), calling requestActivate(), setting up a FocusScope - nothing seems to result in keyboard input ever being passed to the plugin.
In reply to Thanks, I see this. I was… by Marc Sabatella
> do seem to allow allow focus to go to the dialog. It always remains in the main application window,
seems to be a regression in ms4, did you try in ms3?
In reply to > do seem to allow allow… by msfp
No, because the plugins wouldn't be needed in MU3 :-). But I just checked, and at least one plugin that doesn't accept keyboard input in MU4 does in MU3. I'm assuming it's still possible, just perhaps needs to be done differently due to how the whole UI uses QML now.
In reply to To be honest, I never worry… by parkingb
Thanks, this looks very helpful! I know this is asking a lot, but - would it be possible to have a more minimal example? A simple dialog with a single control (say, a spinbox), plus and OK and Cancel buttons? If it's possible to get that working without 100+ lines of code, that would be a great starting place.
In reply to Thanks, this looks very… by Marc Sabatella
The QML in this simple plugin does not have much code: in fact most of it is the UI definition. It's a quick and easy UI design where I chose the number of columns then let Qt take care of the sizing. It doesn't have a spinner but has text input fields and a dropdown input. It has buttons for Apply and Undo.
https://musescore.org/en/project/recorder-fingering-0
In reply to The QML in this simple… by yonah_ag
Oh i see
In reply to The QML in this simple… by yonah_ag
Thanks for this! It seems that you are also still needing to rely on hard-coded width & height settings. Is there really no alternative?
In reply to Thanks for this! It seems… by Marc Sabatella
The hard-coding was to achieve a small dialogue since it's not docked but it would be better if Qt could size this too. I'll remove the sizes and see what happens.
In reply to Thanks, this looks very… by Marc Sabatella
No problem, but what is a spinbox? an image of turntable ?
https://www.google.com/search?q=spinbox
In reply to No problem, but what is a… by msfp
Thanks to parkingb's tips, it seems DialogButtonBox response to TAB and the Button{} response to SPACE so I iddn't use KeyNavigation
In reply to No problem, but what is a… by msfp
Spinbox:
https://doc.qt.io/qt-6/qtwidgets-widgets-spinboxes-example.html
In reply to Spinbox: https://doc.qt.io… by yonah_ag
https://doc.qt.io/qt-6/qml-qtquick-controls2-spinbox.html
https://doc.qt.io/qt-5/qml-qtquick-controls2-spinbox.html
Also see Tap tempo
In reply to https://doc.qt.io/qt-6/qml… by msfp
qmllearning updated
In reply to qmllearning updated show… by msfp
@Marc Sabatella
adapt the spinbox.qml to the latest https://musescore.org/en/node/345720#qmllearning-Dialog
or share more details about the layout of your project?
In reply to @Marc Sabatella adapt the… by msfp
spinbox2.qml