Crash when switching scores, both in text editing mode, where the caret is on a line that the other score's text box doesn't hav

• Jan 27, 2016 - 22:38
S2 - Critical

Steps to produce (basic example):
1. Have two scores.
2. Have both in text editing mode (Add > text to create text boxes)
3. Press enter in one of the boxes to go to the next line.
4. Switch to the other score.
5. Crash.

Example 2:
1. Have two scores
2. Have both in text editing mode
3. Enter text in both (make sure both have same number of lines)
4. Press enter at the very bottom of one box and enter more text.
5. Switch score.
6. Crash

No crash.


Revision 59f3f29 on Linux

I think this crash happens because the caret stays in its "line number" even when switching scores. For clarity, say the caret is on line 2 of score 1. When the user switches to score 2, the caret goes to line 2 of the text box of the new score. When the other text box doesn't have a line 2, as in the basic example, it crashes.


Your analysis is spot on. We save the current cursor information in a "static" variable Text::_cursor, so it is common to all scores. It's conceivable we could fix this by simply removing the word "static" from that declaration, which would hopefully keep this separate for each score. Or we could prevent the crash at least by still keeping it global but fixing Text::curLine() to check the value of _cursor.line() before using it to index the _layout list.

Interesting other aspect to this. Follow the same basic procedure, but leave the cursor on the first line in both texts. After switching scores, make an edit, hit Esc to leave edit mode, then hit Ctrl+Z to undo the edit. The text text is replaced by the original text of the *other* score. That is because the original text we restore after after an undo is also a "static" variable, so there is only one undo buffer for text shared between scores as well.

The undo code for text is delicate enough that I'd rather not mess with it. But just fixing the crash here by doing a santify check on _cursor.line() in Text::curLine() seems not really good enough given the undo weirdness. I think the most sensible thing to do for now is force the edit to be completed when the user switches tabs. I will see how feasible that is. It seems we already the force and end to note input mode.

Status (old) active patch (code needs review)

This implements the behavior I suggested above: forcing an end to edit mode when switching scores. This solves the crash. Still leaves us with the undo glitch, so ultimately we may wish to look at that as well.

FWIW, I just got a crash on startup (?), in Text::changeSelectionFormat(), first line - presumably _cursor was null. Not really sure how I got here, I was maniuplting multiple windows at once (2.02, nightly, self-built master). Can't reproduce currently.

Happened again, switching windows but not otherwise actually *doing* anything. The stack shows changeSelectionFormat() being called by setFormat(), called by TextTools::fontChanged(), called from TextTools::qt_static_metacall(). Will try to figure out how to reproduce and open new issue if I can.

I'm getting it on startup now again, but I can't quite tell why this is being called at all. I guess it happens during initialization, but I see now that the problem isn't necessary that _cursor is null - I think the problem is that TextTools::_textElement is null. So we are trying to call Text::setFormat() on a null element. Maybe this just happened to work before because it was manipulating _cursor which was static and no longer is, but I think we really need to fix TextTools::fontChanged() to not do anything if_textElement is null, or perhaps address whether this needs to be called during initiailization at all (still not sure why it seems like it sometimes is, sometimes isn't).

EDIT: I should have looked further down the stack. I guess it is being called - after a few more levels of Qt event loop stuff - as a result of generating thumbnail for a recently accessed 1.3 score for the Start Center.

I don't have time to verify right now so I'll hold off on submitting a new issue, but I *think* the steps will be:

1) start MuseScore with "-F"
2) open a 1.3 score (probably should be one that contains text)
3) close MuseScore
4) start MuseScore *without* "-F"

I *think* it is something like this that is leading to the crash.