GSoC 2020: Tree Model - Week 3 (Finished my first PR)

Posted 5 months ago

Work planned to do:

This week I had planned that I will finish all my work on the current PR and make it ready to merge.

Work done last week:

  1. I figured out a way to add spanner elements (Beams, ties, lines etc.) to the model. I have connected the spanners to their starting elements in the model. I used the SpannerMap in the Score class to find out whether a spanner begins at any element and added it to its children from there. Then I changed the parent of the spanner to its starting element. Spanners can be anchored to either individual notes, chords, segments, or measures, so I had to modify the tree function in those four classes and I had to handle each case in the treeParent() function in the Spanner class. I had to refactor the code in the spanner class a little bit to make it work.

    I also found there is a class SpannerSegments, which is the part of the spanner that exists in each system. (This is totally different from the Segment class, which confused me a bit ;). Each spanner has a list of SpannerSegments, so it makes sense to make SpannerSegment the child of Spanner, and so I did that. (Earlier parent of SpannerSegment was System, and Spanners themselves appeared nowhere in the model).

    There are some weaknesses in this method, for example, we do not know the end element of the spanner within the model. This method is probably just a temporary solution and we might change it later.

  2. I added the tree debugger to debug menu so it doesn't show up in the release builds. I moved the debugger from scoreview.cpp to musescore.cpp.

  3. I cleaned up the code and marked the PR as ready for review. I made all the changes as suggested by my mentor.

  4. Upon a suggestion of my mentor, I have changed the scoreItemModel slightly so that it shows the accessibility text for the element in the tree view. Here's what it looks like now.

    Screenshot from 2020-06-22 16-46-51.png

As you can see it has a lot of information! Earlier it used to only show "Measure", "Note" etc, but now it shows the pitch, duration, etc for the note too. All this information could be available for accessibility for visually impaired users, if we are able to redesign the score view in terms of this model.

  1. I created a test for checking consistency in the tree model. It basically loads a score and goes through each element in the model starting from Score. It checks whether the parent of the element is correct or not. That means that if I go to the children of element A -> element B1, B2, B3, then B1.treeParent(), B2.treeParent(), B3.treeParent() should all return A.

    It helped me find a few bugs related to the handling of Grace Notes and Trill Lines which I fixed.

Work to be done next:

This week, I plan to work on refactoring the scanElements function. I can replace it with a function that does a tree traversal in the ScoreElement class. In most of the classes scanElements only called itself recursively on the children, so everything will remain mostly the same. However, in some classes, scanElements also had to decide which elements are visible and which are not, and there is some custom logic for that in some places. For example, here in system.cpp, this code decides whether or not to show a spanner element depending on whether chords at both its ends are visible or not.

Screenshot from 2020-06-22 16-41-40.png

So I'm planning to keep scanElements as a virtual function, but override it in the derived classes only where custom logic is required.

After changing this we could start refactoring ScoreView too, we could make it a QAbstractItemView based on the tree model. That would allow all the accessibility info shown here to be available to all the screen readers, and there could be some other benefits too like better keyboard navigation.

Other links

Pull Request:

Previous Blog:…
Next Blog:…