Accessing blind data in a base object via external view objects



  • This is probably more of a philosophical discussion kick-off / bikeshed problem than an actual question, but here goes:

    I've got an fairly generic QML object that acts as a base class for more complex nodes (both C++ and QML). This object is called "Node" and has a QJSValue property called "details" that is used for blind data. The only thing Node knows about its details property is that it is a list (QJSValue.isList() == true). Derived classes generate and store data in the details property. While Node doesn't know anything else about the data stored in details, derived nodes must be able to communicate with each other, so there are schemas which they follow. For example, a node dealing with files expects each element in details to have "pattern" and (optionally) "frames" properties, e.g.

    @fileNode.details[0].pattern == "/path/to/somefile.d.jpg"
    fileNode.details[0].frames[0].frame == 1
    fileNode.details[0].frames[1].frame == 2
    ...
    fileNode.details[0].frames[1].frame == 10

    or

    fileNode.details[0].pattern = "/path/to/somefile.jpg"@

    I would like to encapsulate the code that reads and writes data to a nodes details so that changing the schema is a matter of changing code in one place, rather than in dozens of nodes.

    I don't want to put these methods in the Node class itself; they don't belong there. Using an inheritance hierarchy is not an option.

    I've experimented with a few different methods, but frankly all of them feel clunky.

    1. Via a separate QObject property that has a target attribute, e.g.

    @SomeNode {
    id: self
    ...
    property FileView fv: FileView { target: self}
    ...
    function doStuff() {
    fv.element[0].pattern = "/path/to/some/file.d.jpg";
    fv.element[0].scanForFrames(); // fill in details[0].frames array with frames found on disk
    }
    }
    @

    This was my first attempt. It works okay... However, this pattern doesn't easily extend to accessing an array of nodes:

    @SomeNodeWithArrayInputs {
    id: self
    var inputs: []
    ...
    list<FileView> inputFvs: []
    onInputsChanged: {
    // make sure inputFvs has the same number of FileViews as elements in inputs
    // ...ew
    }
    ...
    }@

    1. By using an attached properties object

    @SomeNode {
    ...
    function doStuff() {
    FileView.element[0].pattern = "/path/to/some/file.d.jpg";
    FileView.element[0].scanForFrames(); // fill in details[0].frames array with frames found on disk
    }
    }
    @

    This pattern easily extends to accessing an array of nodes:
    @
    ...
    function doStuff() {
    for (var i = 0; i < self.inputs.length; i++) {
    // do something with inputs[i].FileView.element[0].pattern
    }
    ...@

    1. Creating FileView objects with a factory method on demand

    @SomeNode {
    id: self
    ...
    function doStuff() {
    var fv = Utils.createFileView(self);
    fv.element[0].pattern = "/path/to/some/file.d.jpg";
    fv.element[0].scanForFrames(); // fill in details[0].frames array with frames found on disk
    }
    }
    @

    This also works with the array pattern, and is what I'm using now.

    1. I haven't tried this, but I guess it's also possible to use a QQmlPropertyValueSource

    @SomeNode {
    ....
    FileView on details { id: fv }
    ....
    function doStuff() {
    fv.element[0].pattern = "/path/to/some/file.d.jpg";
    fv.element[0].scanForFrames(); // fill in details[0].frames array with frames found on disk
    }
    }
    @

    This also doesn't work with the array-of-inputs pattern. Also, it's not really what QQmlPropertyValueSource is for, so it scores high on the "ew, hack" scale.

    So, the questions:

    • am I on the right track? or is there a better way of providing "views"? (or are those facades?)
    • is using an attached properties object idiomatically correct? It feels like the cleanest option so far.
    • what exactly should I call the "view" object classes? FileView/FileAccessor/FileEditor/FileDelegate/FileFacade/other? I want it to be clear that they manage an aspect of the node's details.

    cheers,
    -Mark


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.