pyotherside
pyotherside copied to clipboard
[RFC] No support for model implementations in Python
In C++, I can write an AbstractItemModel
implementation. I'd like to do the same thing in Python so that I can have Pythonic data structures that can be manipulated naturally by a Python backend and the data reflected naturally with a QML frontend.
I have a basic implementation of this working. It needs considerable cleaning up and isn't ready yet, but I thought it would be useful to get some initial review and feedback on the basic design and API at this stage. I've pushed it to https://github.com/basak/pyotherside/tree/models. Some rudimentary documentation is at https://github.com/basak/pyotherside/blob/models/docs/models including an example, along with a basic model implementation in Python in https://github.com/basak/pyotherside/blob/models/docs/pymodel.py. Here are some notes copied from my initial documentation for your reference:
- This is still a work in progress and the API between the QML PythonItemModel object and Python will change, so please do not merge this yet.
- I expect to rebase this branch before submission.
- There end up being three "faces" in Python. Suggestions for better names
appreciated:
- The Python data object that reflects the data and manipulated from Python Pythonically. The availability of this object is the goal, and I'm currently calling this the "Python Side". This is how a Python backend speaks in Python about the model.
- The Python data object that is passed through to the QML PythonItemModel object that it can query for data as required. This is an API I've invented that quite closely matches the AbstractItemModel Qt API and I'm currently calling this the "Other Side". This is how QML speaks to Python about the model.
- The Python data object that is presented by the QML PythonItemModel and is used to call the PythonItemModel back, for example to inform it when changes. I'm currently calling this the "bridge". Again this is an API I've invented. This is how Python speaks to QML about the model.
- Symmetry suggests that there should be a fourth face. I suppose this is the PythonItemModel object in QML itself. This is how a QML frontend speaks in QML about the model.
- I wonder if there will be a significant performance impact in putting the model into Python. I guess I'll need to try it and see.
- pymodel currently provides ListModel and SortedListModel. Other things like hierarchical models and allowing users to write their own entirely in Python are possible with the current C++ implementation.
- In Qt, AbstractItemModel's API isn't thread-safe in that the model must not be modified except from the UI thread, so that while a view is retrieving data the data remains consistent. This requirement is passed on to the Python model implementation. I have done this using the in_ui_thread decorator in my example (which we should ship).
- Currently in the Python API provided by PythonItemModel there are two ways of representing a QModelIndex - using integer references and using lists of (row, column) tuples. The latter seems more consistent (since signal_dataChanged must use it) so the other method should be removed and the C++ side adapted.
- signal_dataChanged should be called emit_dataChanged.
- The C++ end is a complete mess and needs significant cleaning up.
- Naming conventions are all over the place since python_uses_underscores and C++ uses camelCase. Consistency could be improved even if using both by deciding when it is appropriate to use each.
- pymodel.py should be called something else and perhaps just be made available as part of the pyotherside module import. This needs build system thought since pyotherside currently doesn't ship any Python.
- I want to keep the use of pymodel.py optional, and maintain the API between PythonItemModel and Python formally. Then pyotherside users will have maximum flexbility in maintaining their own custom models written in Python.
- Feedback appreciated!
If you turn it in to a pull request, I think it's easier to comment on the changes.
I think it's good to have that as another option, and if the performance is bad, we can always try to make it more efficient, or people just user other methods for interfacing QML with Python (I've done it in my projects by sending objects back and forth between QML and Python and manually syncing the QML state with the Python state). For a first version, I think it's okay to possibly trade performance for convenience (having the Python state sync automatically with QML is a nice thing to have).
Can you turn this into a pull request?
Any news there?
Sorry, I've been busy. I do intend to finish this at some point, but I don't expect to get to it for a month or two at least.
FYI, I've resumed this effort. I'll send a pull request soon, even if it's just my mess of work in progress so that you can comment inline. Probably best to get an idea of where you want things to go before I polish it up.
Any update @basak on your commit ?