Expose text styles to plugins

• Feb 2, 2016 - 14:51
S5 - Suggestion

This came up at https://musescore.org/en/node/9383#comment-422741. If plugins could be allowed to access text styles, rather than being restricted to staff text, then at the very least a certain TempoChanges plugin would be able to make a large advance.


Who would I be if I didn't try to help out 'the life-saver of MuseScore' ;-)
As mentioned before, I'm still fairly new with the codebase, so my attempt might turn out to be void. But it's better to try than not have lived at all, isn't it?

Status (old) active needs info

One of the issues with implementing this is that TextStyleType is currently not part of a class of the QObject type, which doesn't allow it to be exposed.

I propose to move it either into MScore class (it's already part of that file and comment on L273 in mscore.h already seems to indicate this would be the logical place) or the Text class.

I think I prefer the Text class because that is also where the related property exists.

EDIT: to lessen impact on existing sources referencing this enum, we could use the technique described here to create a copy-enum for QML-exposure. The obvious disadvantage would be that keeping the copy up to date with the real one is a manual and error-prone job…

I did not found a good solution for enums yet. With the introduction of c++11 it is possible to convert normal enums into enum classes. This is typesafe and allows forward declarations of this enum types. Forward declarations allow to remove dependencies between header files which results in shorter recompilation times after some source changes.
To access enums in qml they must be part of a QObject derived class. Unfortunately enums in a class cannot be forward declared.

For this reasons i believe its best to make a copy of an enum for the purpose of exposing it to qml. Example is in accidental.h for "AccidentalType" which is copied and exposed to qml als "QmlAccidentalType".

Small progress report, as it seems not my enumeration is wrong, but possibly its location.
I've made a very simple enumeration within Ms::Note, which is perfectly accessible from within the plugins. However creating a similar enum (slight namechange and prefixed values) in a seemingly identical matter within Ms::Text doesn't work.

I'll see if I can figure out what's preventing this, but if anyone has a hunch about the reason, please step in :)
EDIT: reading through the moc_*.cpp files for both the working and non-working enum doesn't really show any noteworthy differences. I'm stumped at the moment and unsure on where to look for differences next.

OK, I was very much missing the obvious. The Ms::Text class is exposed as MText, most likely to not collide with QtQuick.Text.

What threw me off is that the PluginDocs mentions Ms::Text as a class called "Text", while that should've been "MText".

So here's the real related question: How does MuseScore wish to handle possible collisions? Normally you shouldn't be bothered by that and call your own text elements simply "Text". The one using it should then differentiate which element to use by aliasing the Import.
I don't know if this is desired behavior. It would result in a plugin like this:

import QtQuick 2.0
import MuseScore 1.0
import MuseScore 1.0 as Ms //ambiguous types can be accessed by this prefix

MuseScore {
      menuPath: "Plugins.pluginName"
      onRun: {
            console.log("Qt Text", Text);
            console.log("MuseScore Text", Ms.Text);
            console.log("MuseScore Note direct", Note);
            console.log("MuseScore Note aliased", Ms.Note);

If collision avoidance is a design goal, then I'm wondering why not all Types are prefixed?
Any further thoughts on collision avoidance (specifically by werner)?

This fix introduces the string "You can't create an enum" shown in the Plugin Creator console when you try to use the enumeration as a class.

var a = new TextStyleType; is illegal usage.

This text is not translated in the 2.0.3 release, but will be in later releases.