GSoC 2020 - Tree Model - Work Product
Week 12 / Final Report
We have come to the end of the GSoC season for 2020, and this is my final report summarizing the results of my project, Tree Model for libmscore.
The main aim of the project was to formalise the tree structure of MuseScore’s objects and classes by adding a generic way to access children of an element (i.e. add a
getChild(n) function to ScoreElement and derived classes). The secondary goal was to make use of this model in areas such as:
- Reading and writing files
- Drawing elements on the screen
- Accessibility of the ScoreView
For more information, see:
Here are the pull requests I made and a brief summary of the work done in each one:
PR #6174 - GSoC 2020: Add tree hierarchy functions to ScoreElements (Merged)
a. Added treeChild(int n) and treeChildCount() functions to ScoreElement and most derived classes.
b. Created the initial QAbstractItemModel (this used some code written by my mentor prior to this project)
c. Also created a simple debugger to see the score tree in the debug builds.
d. Created a test to ensure consistency of the tree model.
PR #6274 - GSoC 2020: scanElements refactoring based on tree model (Merged)
a. Refactored scanElements function to traverse the score using a generic traversal on the score tree instead of case by case in each class. This function was responsible for drawing elements on the screen, expanding repeats, etc.
b. Ensured consistency with original scanElements function by comprehensive automatic testing.
PR #6045 - GSoC 2020: TreeWrite refactor (In-Progress)
a. Attempted to refactor the score file write/read functions using the tree model. Was able to achieve about 80% similarity with existing mscx format, with only a fraction of the code.
b. Since time was limited, and the code was becoming complex again if we tried to match the existing format exactly, so after discussing with my mentor I decided to move to the next task.
PR #6464 - GSoC 2020: Change ScoreView to QAbstractItemView (Also adds tooltips) (In-progress)
a. Made ScoreView inherit from QAbstractItemView, connected it to the QAbstractItemModel created earlier.
b. This also added tooltips, Qt automatically finds the correct element and uses
Qt::ToolTipRoleto fetch the tooltip information from the model.
The main deliverables of this project (the treeChild(n) functions and the QAbstractItemModel) have been completed. I also managed to refactor the scanElements drawing functions based on this new model, and made some progress towards writing MSCX files and accessibility of the ScoreView. There are still many areas that could take advantage of the new tree model to make the code simpler and more structured over time.
Work left to do
I have left the file read/write refactor as a draft PR for now. The new write function is much simpler than the old one, yet it is already able to reproduce about 80% of the lines in an MSCX-formatted file. However, I don’t think that it is possible to match the current format to 100% without introducing additional complexity that would make the refractor pointless. Instead, I think we should work with this partial implementation, and perhaps in Musescore 4 we could introduce some changes to the MSCX file format to make it resemble the internal model of libmscore more closely. This would enable us to simplify the read/write code even further, and make it easier to add new features. There are also other reasons to change the format, such as the fact that storing layout information for parts currently involves duplicating the element tags.
We had hoped in the beginning that using Qt’s model-view pattern for our score editor will lead to automatic accessibility improvements. It did add tooltips by itself but to get screen reader support, apparently, still some more work is left to do. We will have to probably make an instance of QAccessibleInterface for each element in the score. I am still working with my mentor to get screen reader support working, and will hopefully be able to add it very soon.