Tremolo customizations lost on second save/reload
The new facility to set placement and stroke style for tremolo unfortunately doesn't survive save & reload - at least, not two of them. Steps to reproduce:
1) create score with two quarter notes
2) add tremolo between them
3) set to stroke to attached to stems
4) save / close / reload
5) change anything else in the score
6) save / close / reload
Result: the customization is lost. What is happening is that on the read at step 4, we are setting the stroke style, so it appears to have survived the save and reload, but the property flag never got set to UNSTYLED. So the customization is lost on the write at step 6, since STYLED properties are not written.
Same for the placement.
Normally, the fix would be to replace the explicit handling of these two tags in Tremolo::read() with a single call to readStyledProperty() - see for example how it's done in Hairpin::read() or Stem::read() or any of the other uses of readStyledProperty().
However, that actually doesn't work here. That's because when it comes time for readStyledProperty() to actually set the property it just read, it calls setProperty(), and Tremolo::setProperty() refuses to set the stroke style because it is checking customStrokeStyleApplicable() to see if it's worth the trouble, and it's deciding no it isn't, because the duration actually has not yet been set.
So either Tremolo::read() needs to handle the property flags itself (just setting them to UNSTYLED should be good), or if we do switch to using readStyledProperty(), somehow we need to make sure it can actually set the property. Like, by changing customStrokeStyleApplicable() to accept a duration of V_INVALID. No idea if that breaks anything else. Or just ripping that code out - does it really hurt for setProperty() to actually allow the property to be set even not not applicable? Not sure if there was a user-visible bug that that (recent) change fixed.
Comments
Thanks for the analysis!
No it actually doesn't hurt to not check customStrokeStyleApplicable() in setProperty(), at least not now, because in the actual layout I made sure to check it too, if it isn't applicable the default layout is forced. It's just with the new inspector logic for 4.0, it will eventually become possible for those which don't accept custom stroke styles to have redundant information, if we don't check when doing setProperty(). As far as I can think of, this kind of redundancy might cause problems for exports to other formats, for example if MusicXML supports tremolo stroke styles (I don't know if it does), those which don't support custom ones may get a tag of a custom style too. Regardless, this kind of redundancy is never good, so I think we need to do best to avoid it.
I think I prefer the second solution (switch to readStyledProperty() and allow V_INVALID).
Well, turns out if I allow V_INVALID, staffType() can be nullptr and therefore crashes the app when executing (staffType()->group() != StaffGroup::TAB). I'll switch to the first solution to see if it works.
See https://github.com/musescore/MuseScore/pull/6564.
Fixed in branch 3.x, commit 1f25c776ab
_fix #310603: tremolo customizations lost on second save/reload
See more in https://musescore.org/en/node/310603, also https://musescore.org/en/node/310603#comment-1027967._
Fixed in branch master, commit 84d05f3cd7
_fix #310603: tremolo customizations lost on second save/reload
See more in https://musescore.org/en/node/310603, particularly https://musescore.org/en/node/310603#comment-1027967._
Automatically closed -- issue fixed for 2 weeks with no activity.