Editing QML ListView using Javascript functions



  • Hi all,

    I am trying to remove items from a ListView using on-screen GUI buttons that exist within QML.

    I have found this link: https://forum.qt.io/topic/24159/manipulating-a-model-inside-a-listview-with-javascript/3

    Which seems to be a similar question to mine, EXCEPT for the fact that I have loaded my ListView using a context property from C++, rather than an actual QML model.

    That being said, how would I go about editing a ListView that exists within QML from the press of a button, and have the screen update in real time?

    For example, pressing the "+" button with a particular item highlighted from an additional on-screen list of names should pull the item with that name from the context property and visually load it into my ListView.

    My 2 current theories as to how I would do this are:

    1. Edit the list within C++, and make a forceLayout() call within QML.

    2. IF the ListView's model mirrors the C++ context property, try to use Javascript array functions to interact with the model. For example:

    myListView.model.unshift(item);
    

    I am going to run some experiments when I work on this tomorrow; I just thought I'd leave this here to get some feedback on my thinking, and to see if there were any other alternatives.

    Thank you!



  • @devDawg said in Editing QML ListView using Javascript functions:

    rticular item highlighted from an additional on-screen list of names should pull the item with that name from the context property and visually load it into my ListView.

    If the items in your second ListView (for the selected names) are a strict subset of the items in your first one then you could also achieve what you want by assigning the same model to the 2nd ListView and simply controlling the visibility of the delegate: in a ListView, setting a delegate's visible to false will "remove" it from the list. So you could set the 'visible' property to false by default and to true when selected from the first list, etc.

    Another way to achieve this is to use a DelegateModel for your 2nd ListView, setting its model to your original model, and defining an "Included" or "Selected" group to which you would add/remove the names you select/deselect

    If you are willing to modify your C++ model to add a "selected" property to each item, then you could also use a QML proxy model for your second ListView, and filter on the selected property. A very convenient and simple to use custom QML type to do this is:
    https://github.com/oKcerG/SortFilterProxyModel
    This custom proxy type even allows you to define that "selected" property in your delegate instead, and filter on that delegate property.



  • So you could set the 'visible' property to false by default and to true when selected from the first list, etc.

    Holy cow.. That is so simplistic, yet brilliant! Now while I do like that solution, I don't believe it will work in my case.. This is my fault; I did not provide you will enough detail as to how my ListView is structured.

    The structure is as follows:

    -The second ListView (let's call it selectView) , where you have the list of total available items, is actually a list of outputs from a system.

    -The first ListView (let's call it plotView) is a scrollable container of plots, where each plot may contain up to 5 outputs.

    -This means that any given item, or plot, in plotView can contain up to 5 items from selectView.

    It would be super fantastic to just mirror the 2 views & make an item in plotView visible when I want to view it, but the problem there is that I have designed the delegate to be able to house multiple items.

    In terms of your proxy model idea, I like this as well. However, rather than hosting the selected variable in the C++ model class, wouldn't it be easier/lighter to host that variable within the delegate of my QML ListView?

    My thinking behind this, is that a user can click on a plot to select it, then add an output from selectView. If the user has "added" an output without a plot selected, then it is simply added as a standalone into plotView. This is the next thing on my list to implement once I get my "add" & "remove" buttons working.

    What do you think of this?

    Thank you for the feedback!



  • Okay, so I have made a fair amount of progress since I last commented.

    For either of my strategies, I would come across this Javascript error:

    TypeError: property of object such and such is not a function.

    I realized, with the help of a colleague, that my assignment of the model was what was screwing me. Instead of creating a .qml file to serve as my custom model, I was using the length of a QVector within a context property from C++, meaning that my model was nothing but a number! Hence, zero access to the Javascript array functions.

    So, my new approach is pre-load my models in .qml, rather than constantly make Q_INVOKABLE method calls from a C++ context property class.



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