Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Share list model between two gridview



  • I need to share a model list of items between two gridview because I need to move items between the two controls using drag and drop. The obvious solution is to use Package but in my case I have the problem the GridView show an empty space where an items should be also if the item is placed on the other view. A screen shot will crarify the problem. As you can see I add the block by disposing in the two view even and odd but this create the columns you can see. Someone know hwo to make the block to appear in the view in the "normal" order without the spaces?

    alt text

    Follow the example code:

    GridView {
        id: grid1
        cellWidth: 80
        cellHeight: 80
        model: visualDelegateModel.parts.grid1
    }
    
    GridView {
        id: grid2
        cellWidth: 80
        cellHeight: 80
        model: visualDelegateModel.parts.grid2
    }
    
    ListModel {
        id: blocksListModel
        ListElement { color: "blue" }
        ListElement { color: "green" }
        ListElement { color: "red" }
        ListElement { color: "yellow" }
        ListElement { color: "orange" }
        ListElement { color: "purple" }
        ListElement { color: "cyan" }
        ListElement { color: "magenta" }
        ListElement { color: "chartreuse" }
        ListElement { color: "aquamarine" }
        ListElement { color: "indigo" }
        ListElement { color: "black" }
        ListElement { color: "lightsteelblue" }
        ListElement { color: "violet" }
        ListElement { color: "grey" }
        ListElement { color: "springgreen" }
        ListElement { color: "salmon" }
        ListElement { color: "blanchedalmond" }
        ListElement { color: "forestgreen" }
        ListElement { color: "pink" }
        ListElement { color: "navy" }
        ListElement { color: "goldenrod" }
        ListElement { color: "crimson" }
        ListElement { color: "teal" }
    }
    
    DelegateModel {
        id: visualDelegateModel
        delegate: Block {}
        model: blocksListModel
    }
    

    And this is the Block delegate:

    Package {
        id: packageRoot
    
        Item { id: grid1Delegate; Package.name: "grid1"}
        Item { id: grid2Delegate; Package.name: "grid2" }
    
        Rectangle {
            id: block
            width: 72; height: 72
            anchors {
                horizontalCenter: parent.horizontalCenter;
                verticalCenter: parent.verticalCenter
            }
            color: model.color
            radius: 3
    
            state: (index % 2) ? "grid1" : "grid2"
    
            states: [
                State {
                    name: "grid1"
                    ParentChange { target: block; parent: grid1Delegate }
                },
                State {
                    name: "grid2"
                    ParentChange { target: block; parent: grid2Delegate }
                }
            ]
        }
    }
    


  • @Suppaman
    Your problem is very easy to solve with a proxy model.
    https://github.com/oKcerG/SortFilterProxyModel

    I wouldn't know how to solve your problem using the Package approach though. It would seem that there must be a simple solution to it, but I'm not very familiar with the Package construct.

    This proxy model library above is super easy to install and use, and it solves your problem like this:

    To each element in your ListModel, add an additional property e.g. grid which identifies your grid, 0 or 1, e.g.

    ListModel {
        id: blocksListModel
        ListElement { color: "blue"; grid: 0 }
        ListElement { color: "green"; grid: 1 }
        ...
    }
    

    Then, define each of your GridViews as follows:

      GridView {
                width: parent.width
                height: parent.height/2
                id: grid1
                cellWidth: 80
                cellHeight: 80
    
                model: SortFilterProxyModel  {
                    sourceModel: blocksListModel
                    filters: ValueFilter {
                        roleName: "grid"
                        value: 0
                    }
                }
    
                delegate: blockComp
            }
    
      GridView {
                width: parent.width
                height: parent.height/2
                id: grid2
                cellWidth: 80
                cellHeight: 80
    
                model: SortFilterProxyModel  {
                    sourceModel: blocksListModel
                    filters: ValueFilter {
                        roleName: "grid"
                        value: 1
                    }
                }
    
                delegate: blockComp
            }
    

    where blockComp is your delegate:

        Component {
            id: blockComp
            Item {
                Rectangle {
                    id: block
                    width: 72
                    height: 72
                    x: 4
                    y: 4
                    color: model.color
                    radius: 3
    
                    MouseArea {
                        anchors.fill: parent
                        onClicked: {
                            model.grid = !model.grid
                        }
                    }
                }
            }
    

    As you can see, in the example above, clicking the delegate will move it to the other grid. In your case, you will do it by drag/drop.

    P.S. the above trick model.grid = !model.grid will generate warnings, because grid is interpreted as Number and not a Bool, but that's easy to solve.



  • Hi

    At first thank you for your reply. Unfortunately your solution can not be applied in my case since I need to use a DelegateModel for move the intem inside the gridview and, just verified, SortFilterProxyModel can't work cause DelegateModel have both model and delegate and SortFilterProxyModel filter model only.



  • @Suppaman
    You're right. I didn't think about also moving the delegate.
    In that case, maybe you can use two ObjectModel, one per GridView and then dynamically move a model item from one model to the other? I.e. when you drop it onto the other GridView, remove it from the parent model, then dynamically create a copy of it to add to the other model.

    But, hopefully, someone will come up with a way to make the Package method work...



  • Hi

    Yes, the solution you proposed is the obvious way to proceed but the project I have in mind is more complicated unfortunately. I'll try to explain as my best. Do you know the Qt example draganddrop provided with Qt Creator? I guess yes, but in case this example software show a way to fill a GridView control with colored blocks, like in the picture I posted here. If you drag one of these block and moving around the control all other blocks under the corrent draggred move away and leave the space for drop the block. In this way you can order the block as you prefer. I want to make a project containing two GridView and want to move the blocks between these two controls but keeping this "effect" or reordering in both gridview with the same dragged block. The problem is if I drag a block and move on the other gridview I don't have the "effect" of blocks moving away cause the dragged block is in the range of the origin gridview. Adding the block to the target gridview and removing the original dragged will have a consequence that I lost my current dragged block cause removing from the module delete the object. As everything in programming there are various solution to each problem but I'm looking for the correct way to reach such result and still didn't find. Hope to explained well the project I have in mind...



  • @Suppaman
    In the example below, I didn't have the time to get the details right, but it shows you that the approach outlined previously works.
    I just took the original drag and drop example and split it into two GridView, each with their own DelegateModel.

    0_1536298004618_dragdrop.gif

    So you could try yourself. The implementation details to make it work correctly are up to you. Good luck.



  • Interesting. With the "approach outlined previously" you mean using SortFilterProxyModel? Because the main problem is the empry space that happear under the dragged block is basically the "invisible" part of the dragged block item (the MouseArea in this case) moved in position under the point where the deagged block is currently. However moving in another view, as the case, the same item is not present cause is still on the original view list. In your example how did you managed to create the empty space under the dragged block without destory and recreate the blok item as effect to move it between the two view list?



  • @Suppaman said in Share list model between two gridview:

    you mean using SortFilterProxyModel?

    No. I just use the exact same approach as in the Qt Drag and Drop example, the GridView part.

    how did you managed to create the empty space under the dragged block

    I used a transparent dummy which I added to the model of the 2nd grid and which is made to track the movement of the dragged tile until the other one is dropped onto it. at which point the dummy is destroyed. As you can see from the animation above, I didn't get the tracking part quite right yet. But that was not the point of the exercise to me :-). At least, you get the idea.

    Also, I don't really like the way the empty square in the first grid remains until the drop is complete. I rather would have the grid collapse immediately as soon as the tile is undocked. Maybe I'll try again later.

    I still hope though that someone can come up with a better solution...



  • Hi
    I really thank you for your time. About issue regarding the problem of grid collapse immediately as soon as the tile is undocked don't worry, I fixed by tracking the exit from DropArea and move the empy item of the last position of the grid. Currently I'm making some test by set the dragged item to the inPersistedItems group that allow to remove the item from the model without automatically destory it, hope to reach some result following this way...



  • @Suppaman said in Share list model between two gridview:

    hope to reach some result following this way...

    I hope you will post a snapshot of your result. It would be nice to see.


Log in to reply