New implementation for writing links to file#27799
New implementation for writing links to file#27799DmitryArefiev merged 20 commits intomusescore:masterfrom
Conversation
| LOGW("EngravingItem::readProperties: could not link %s at staff %d", item->typeName(), mainLoc.staff() + 1); | ||
| } | ||
| } | ||
| } else if (tag == "lid") { |
There was a problem hiding this comment.
Is this safe to remove? Were <linked> tags used in addition to this id in pre 301 scores? read400/tread is used in all older readers
There was a problem hiding this comment.
Yes, as far as all I can tell this "lid" (which I assume is short for linkID) tag only ever existed in 2.x versions and was only meant as a debugging tool. For all I can tell it had no functional use whatsoever
src/engraving/rw/read206/read206.cpp
Outdated
| @@ -3463,10 +3454,6 @@ Ret Read206::readScore(Score* score, XmlReader& e, ReadInOutData* out) | |||
| } | |||
|
|
|||
| int id = 1; | |||
| @@ -1910,9 +1910,6 @@ static void convertDoubleArticulations(Chord* chord, XmlReader& e, ReadContext& | |||
| for (Articulation* a : pairableArticulations) { | |||
| chord->remove(a); | |||
| if (a != newArtic) { | |||
There was a problem hiding this comment.
ctx can be UNUSED or removed as an argument.
b77bc35 to
f9a2eec
Compare
| <Part id="1"> | ||
| <Staff id="1"> | ||
| <Staff> | ||
| <eid>C_C</eid> |
There was a problem hiding this comment.
Here, we write staves with the new ID system...
| @@ -73,115 +75,145 @@ | |||
| </Part> | |||
| <Staff id="1"> | |||
There was a problem hiding this comment.
But here, still with the old system. Is that desirable?
There was a problem hiding this comment.
Shouldn't make any difference, but nope thanks! Fixed
There was a problem hiding this comment.
@cbjeukendrup Sorry, I was wrong here. The first <Staff> tag writes the properties of the Staff itself, so it makes sense to write its EID and linking properties here. The second tag instead writes the content of the staff, so we don't need to repeat the EID and link properties. And here the "id" tag still serves as an index, it's basically how the reader knows where it is, so I can't just remove it at the moment. It would be probably quite trivial to do since both the write and the read are sequential, so writing a progressive staff ID is unnecessary. But I'd prefer to do that in a follow up
@DmitryArefiev the most important thing to test is that when saving and reopening a file with this new PR, all the linking is preserved correctly. Also taking old files, maybe orchestral scores with parts already generated, saving them in the new PR, reopening them, checking that all the linking is correct. That kind of stuff :) |
Because that's how it happens in reality. If the masterScore isn't saved EIDs may have not been yet created.
to also take into account situations with local key signatures
e104ba7 to
7da2bf8
Compare
7da2bf8 to
2b351b5
Compare
cbjeukendrup
left a comment
There was a problem hiding this comment.
Looks good to me; very elegant! The only thing is that we have to be very sure that all changes to read410 that happened in the meantime have been integrated into read460, and that all currently open PRs that touch read410 are updated to touch read460 as well.
|
Tested on Win10, Mac13.7.2, LinuxUbuntu24.04.2 LTS - PASS |
|
Trying to reproduce the corruption for this issue #26207 (I failed, which is good), I got a Crash on opening. crash_barline_parts.mp4 |
@mercuree Thanks! It's a new crash (I can't reproduce it in the previous nightly build) Logged as #27918 |
Resolves: the second part of #23688
Old implementation
As explained in the issue, our current way of writing linked elements in our files is by adding a

linkedMaintag to the element in the master scoreand a

linkedtag to the corresponding element in the part.The problem is that this method does not establish the actual relationship, it just states that the relationship exists. It says "this is linked", but it doesn't say to what. The way we actually reconstruct the link when reading the file is, practically, by guess: we search for an element of the same type at the same corresponding Location in the master score.
This is inadequate for many reasons:
New implementation
Now that we have unique EIDs, the new implementation is very trivial (see the third commit): for any element A we simply write
<linkedTo>EID_OF_B</linkedTo>. On read, we just retrieve B from its EID and link it to A. That's it.The less trivial part is that, as almost all of our unit tests consist of file comparisons, now we must make EIDs work in the unit tests too (so far, they don't get written to file in test mode). This brings an additional complication because the EIDs are randomly generated, which would make the tests non-repeatable. As discussed here, there is no "nice" solution to this.
The best solution I could find at the moment is to make EID generation sequential (as opposed to random) when in test mode, which guarantees test repeatability. But this is still not perfect. For instance, if I delete an element from a file and insert an identical one in the same place, I'd expect the end file to be identical to the starting one, but it isn't because the new element obviously has a different EID. A more drastic approach could be to exclude from the test results the diffs related to EIDs, but that has downsides too.