immediately dropping break onto vertical/text frame doesn't always get applied

• Dec 11, 2018 - 21:37
Reported version
P1 - High
Graphical (UI)
S4 - Minor

Example reproduction step:
1. Start with initial Untitled score
2. Drag & Drop a page or system break onto the initial title vertical frame

Result: break is not applied, but should be.

Bug also occurs if immediately drop a vertical/text frame and then immediately drop a page/system break ontop that frame. But for some reason, clicking around and doing other things in between may sometimes cause this bug to not happen. Also clicking the frame and then double-clicking a break element from inspector will often result in the correct desired behavior (and then even undoing that will then result in subsequent drops actually working).

Verified on master OS: Windows 10 (10.0), Arch.: x86_64, MuseScore version (64-bit): 3.0.0., revision: 3543170


investigating. I'm noticing that in Box::drop() when droping a page break onto that initial title box, for some strange reason, the box's flag for line break is set...which causes the "if (pageBreak() || lineBreak())" block to occur and then break out & return false in that block, when what should rather happen is to evalute that if statement to be false so the code performs the subsequent operation of adding the break.

So I need to determine why that flag was set in the first place.

Ok...well that flag is set to true in VBox::VBox()...and it makes sense that vertical boxes have a line break after them. So maybe that drop code is that it shouldn't be looking for the flag to be set, but should rather look for if there is an actual break element in the box.

looking at git blame, and I don't see any major changes to Box::drop() in the last couple years...although who knows maybe the problem started before 2 years ago but wasn't noticed.

Turns out what I mentioned in description is very indicative:

"Also clicking the frame and then double-clicking a break element from inspector will often result in the correct desired behavior (and then even undoing that will then result in subsequent drops actually working)."

Turn out the on subsequent drops, the line break flag is NOT set, which is why the rest of the code proceeds correctly. So it seems probably that initialization of the flag to true is what is causing the problem. I'm guessing it is not supposed to be initialized to true...

I guessing the only usefulness of having that flag set is to prevent users from adding unnecessary line break elements to vboxes. But even still, that code wouldn't function on it wasn't fully correct.

In the code during that time, the MeasureBase class had a _lineBreak which controlled that property (instead of using Element flags in current code), and werner had a comment "///< Forced line break" I'm guessing he's setting it to force a line break. But setting it seems unecessary in the current code...

Looking at the current code, the only other place where setLineBreak(true) is called is in MeasureBase::add(), inside of a "if (e->isLayoutBreak())" block. But that code is actually adding a line break element. So it seems the consistent interpretation of the line break flag being true is that that means that there is an actual line break element. Not simply an implicit line break (as naturally occurs at the end of a vbox).

Well the only problem with removing that setLineBreak is that it does indeed allow user to place line break elements on vboxes, even though they are unencessary. But then upon delete of that unenceesary line break, I can actually produce a crash:

MuseScore3.exe!abort() Line 77  C++
MuseScore3.exe!Ms::mscoreMessageHandler(QtMsgType type, const QMessageLogContext &amp; context, const QString &amp; msg) Line 3566  C++
[External Code] 
MuseScore3.exe!Ms::toMeasure(Ms::ScoreElement * e) Line 506 C++
MuseScore3.exe!Ms::Measure::mmRestLast() Line 3032  C++

> MuseScore3.exe!Ms::Score::deleteItem(Ms::Element * el) Line 1714 C++
MuseScore3.exe!Ms::Score::cmdDeleteSelection() Line 2182 C++
MuseScore3.exe!Ms::Score::cmd::__l2::() Line 3655 C++
[External Code]
MuseScore3.exe!Ms::Score::cmd(const QAction * a, Ms::EditData & ed) Line 3682 C++
MuseScore3.exe!Ms::ScoreView::cmd(const char * s) Line 2313 C++
MuseScore3.exe!Ms::ScoreView::cmd(const QAction * a) Line 1761 C++
MuseScore3.exe!Ms::MuseScore::cmd(QAction * a, const QString & cmd) Line 6086 C++
MuseScore3.exe!Ms::MuseScore::cmd(QAction * a) Line 5577 C++
MuseScore3.exe!Ms::MuseScore::qt_static_metacall(QObject * _o, QMetaObject::Call _c, int _id, void * * _a) Line 850 C++
[External Code]
MuseScore3.exe!Ms::ScoreTab::actionTriggered(QAction * _t1) Line 226 C++
MuseScore3.exe!Ms::ScoreTab::qt_static_metacall(QObject * _o, QMetaObject::Call _c, int _id, void * * _a) Line 110 C++
[External Code]
MuseScore3.exe!main(int argc, char * * av) Line 7455 C++
[External Code]

Note with the current master code, I can't actually produce a crash by deleting an unnecessary line break element (after performing the work around of using undo to get line break flag to be set false).

No crashes found with my PR so far...

However I should add...there is the additional question to ask: should MuseScore deliberately prohibit Line Break and Don'tBreak elements from being dropped (or added via double-clicking from palette) onto VBoxes? They don't actually do anything. So their presence is unnecessary. The current Box::acceptDrop() code does indeed return true for any LAYOUT_BREAK element (including line break elements) for any Box (which includes VBoxes), so that code would have to be changed. Anyway, although these line breaks are unnecessary, they also don't matter, so I guess their presence is not a problem.

Status PR created fixed

Fixed in branch master, commit 1416aa8557

_fix #279859 reallow drop break elements on vbox

MuseScore 2.3.2 behavior allowed dropping break elements onto a VBox. But some 3.0 code must have broke this functionality. Turns out the breaks were not being alowed to be dropped because VBox::Vbox() sets the line break flag to true, which the Box::drop() code deliberatly checks for with if (pageBreak() || lineBreak()) in order to handle dropping breaks specially when there was already a break element. That drop code does seem to be correct as far as I can tell.

So it seems to me the line break flag should not actually be set if there is not actual line break element, so this PR changes Vbox::Vbox() to not set the line break flag. It seems that line break flag should only be set if there is an actual line break element on the VBox (not simply the implicit line break that always occurs after a VBox). I'm not completely conviced this is correct, though because werner made the commit ab1723fc6f46feb05af737e5eab5039172d9613a two years ago which added that setLineBreak(true) maybe he should review this PR in case that line is actually intended._

Fixed in branch master, commit 5804b001ab

_Revert "fix #279859 reallow drop break elements on vbox"

This reverts commit 1416aa85575a7c8b201849c328507d210ef7eff2.
Tests on MusicXML export are failing with this commit._