Search code examples
delegatesqmlqtdeclarative

2 identical ListViews with small differences inside delegate


I've got two almost identical qml files. I list one of them here, the differences of the other one shown with the comment lines:

// MessageView.qml; diff. to ThreadView.qml is shown with comment lines
import QtQuick 2.0

Item {
    property var model
    property var selectedThread: threadsList.currentItem.myThread
    property alias spacing: threadsList.spacing
    signal activated(var selectedThread)
    id: root

    ListView {
        anchors.fill: parent

        id: threadsList
        model: root.model
        delegate: Rectangle {
            property var myThread: message // the other file contains `thread` instead of `message` here

            color: threadsList.currentItem == this ? "cyan"
                                                     : index % 2 ? "lightblue" : "lightsteelblue"
            width: parent.width
            height: ti.implicitHeight

            MessageItem { // the other file contains `ThreadItem` instead of `MessageItem` here
                id: ti
                anchors.left: parent.left
                anchors.right: parent.right
                anchors.verticalCenter: parent.verticalCenter
                anchors.margins: 8
            }

            MouseArea {
                anchors.fill: parent
                onClicked: {
                    threadsList.currentIndex = index
                    activated(root.selectedThread)
                }
            }
        }
    }
}

These 2 components are intended to be similar-looking list views with minor differences in delegate appearance. How do I merge these two files into one to be able to use them like this?

MerdedView { 
    MessageItem {
        // more property customization
    }
}
MerdedView { 
    ThreadItem {
        // more property customization
    }
}

Solution

  • There are only small differences inside delegate, so you need to extract the common codes. For example, MerdedViewDelegate.qml:

    Rectangle {
        id: viewItem
    
        property var myThread
        //other properties: color, width, height, ...
    
        MouseArea {
            anchors.fill: parent
            onClicked: {
                //use the attached property in ListView
                viewItem.ListView.view.currentIndex = index
            }
        }
    }
    

    Then create the MergedView.qml just like your MessageView.qml, except the delegate is now changed to an alias property:

    //MergedView.qml
    Item {
        property alias delegate: threadsList.delegate
        //other properties
    
        ListView {
            anchors.fill: parent
    
            id: threadsList
            model: root.model 
        }
    }
    

    Finally, you can write your QML like this:

    MergedView {
        delegate: MergedViewDelegate{ 
            myThread: message    //or something similar
            MessageItem { /* ... */ }
        }
    }
    
    MergedView {
        delegate: MergedViewDelegate{ 
            myThread: thread
            ThreadItem { /* ... */ }
        }
    }