Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. How do I form a Listview containing mixed items
Forum Updated to NodeBB v4.3 + New Features

How do I form a Listview containing mixed items

Scheduled Pinned Locked Moved Unsolved QML and Qt Quick
2 Posts 2 Posters 856 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • C Offline
    C Offline
    culyun
    wrote on last edited by
    #1

    I'm new to QML and have been struggling with building a ListView from data of varying content. I have a UI requirement to display content of varying type, ie. where the delegate changes depending on the type of the item. Now the actual data to display comes from a C++ "node" list (QAbstractItemModel). Some of the nodes have peripheral devices. The desire is to display both the nodes and any peripherals in a flat list with a custom sort.

    I've managed to cook up a solution that involves inspecting the node list using onCompleted handlers, and creating lightweight javascript objects that hold the underlying data (be that a node or a peripheral). These "proxy" model items are dynamically added to a ListModel property on the view with the (node / peripheral) delegate being selected by a Loader.

    The whole thing feels wrong, and importantly does not handle changes to the underlying C++ model (eg. firmware update flag).

    So the question is how do I create a proxy model for a ListView where the model items are not of the same type, eg. where the model items are a mixture of nodes and peripherals?

    ========================

    QML code snippet of what I currently have follows

    ListView {

    id : listView
    property ListModel nodesModel: ListModel {}
    property var nodeInfo : []
    
    Repeater {  // <<========== Purely here to provide an imperative-like hook to process the underlying mode
    
        model: nodesData.nodesModel   // <<============  C++ QAbstractItemModel
        delegate: Item {
            Component.onCompleted: {
                listView.nodeInfo.push({
                    "section": hwVariant < 200 ? "chair" : "tools",
                    "heading": moduleFamily,
                    "hwVariant" : hwVariant,
                    "rowType": "system_node",  // <<============ Used to dynamically choose delegate
                    "itemModel" : model,   // <<=========== C++ individual nodes complete with notifyable QPROPERTYs .  Yes they work in a simple context
                });
    
                // Add a peripheral if this node has an associated function key
                if (model.functionKeyInfo.hasOwnProperty("required") && model.functionKeyInfo.required) {
                    listView.nodeInfo.push({
                        "section" : "chair",
                        "heading" : model.functionKeyInfo.heading,
                        "rowType" : "function_key",
                        "itemModel" : model.functionKeyInfo,
                    });
                }
            }
        }
    
        Component.onCompleted: {
            // sort nodesInfo by section, then rowType, then hwVariant, then serial number
            listView.nodeInfo.sort(Helpers.fieldSorter([
               {field : 'section', order : ["chair", "tools"]},
               {field : 'rowType', order : ['system_node', 'function_key']},
               'hwVariant',
               'serial'
            ]));
    
            listView.nodeInfo.forEach( function (ni) {
                // translate fields then append to the listView model
                ni.section = qsTrId("gui.systemSummary." + ni.section);
                listView.nodesModel.append(ni);
            });
        }
    }
    

    // Actual delegates down here...
    // The "system_node" rowTypes use a delegate that queries the C++ model directly
    // The "function_key" rowTypes use a delegate that queries the peripheral model

    }

    1 Reply Last reply
    0
    • sierdzioS Offline
      sierdzioS Offline
      sierdzio
      Moderators
      wrote on last edited by
      #2

      I think you should:

      • make your Model more flexible
      • make a delegate which adjusts automatically
      • remove all that unnecessary logic from QML, move as much to C++ as possible

      How to go about it?

      • define common API for both peripheral and node model
      • use that common API to create single C++ ItemModel which you will pass to QML
      • make a Delegate which will change it's look depending on values returned by the API. Use a Loader if you must (to load either NodeDelegate or PeripheralDelegate), or if possible use single component which adjusts dynamically

      Sorry for being rather vague, but I don't now your system.

      (Z(:^

      1 Reply Last reply
      0

      • Login

      • Login or register to search.
      • First post
        Last post
      0
      • Categories
      • Recent
      • Tags
      • Popular
      • Users
      • Groups
      • Search
      • Get Qt Extensions
      • Unsolved