3

In Listview, I have popping up 100's of items using "delegate", assume that, listview already displayed populated value. Now I would like to extract already displayed values in QML List view from C++. How to achieve this? Note: I can not access datamodel directly, since I am doing filtration in delegate using hidden variable

        /*This is not working code, Please note,
        delegate will not display all model data.*/
        ListView
        {
        id:"listview"
           model:datamodel
           delegate:{
                      if(!hidden)
                      {
                        Text{        
                        text:value
                      }
                    }

        }


 //Can I access by using given approach?
 QObject * object =   m_qmlengine->rootObjects().at(0)->findChild<QObject* >("listview");

//Find objects
const QListObject& lists = object->children();

//0 to count maximum
//read the first property
QVarient value =  QQmlProperty::read(lists[0],"text");
Ashif
  • 1,652
  • 14
  • 30
  • You should start at least with a code that works. Also, you should keep access from C++ to QML to a minimum, most certainly not in this case. If you want the model data on the C++ side, use a C++ model. – dtech Apr 21 '16 at 11:03
  • I am doing automation testing, I cannot use model data for validation, so after display list view in qml, I need to extract the data from qml to C++ and validate. – Ashif Apr 21 '16 at 11:18
  • I doubt it will work as you expect, you will have better chances iterating the listview in QML and sending the text to C++ by passing it to a slot function. – dtech Apr 21 '16 at 11:22
  • Since i am doing automation testing, i canot edit/touch on qml, instead I use qml plugin, so that application wont be disturbed with automation testing code. – Ashif Apr 21 '16 at 11:33
  • 2
    Do your QML tests in QML: http://doc.qt.io/qt-5/qtquick-qtquicktest.html – dtech Apr 21 '16 at 11:39
  • I can manage to use QML for QML test, I have used QML plugin for the same. above comment is useful. – Ashif Apr 22 '16 at 09:00

1 Answers1

5

You can search for a specific item in QML with the objectName property. Let's take a look at a simple QML file:

//main.qml
Window {
    width: 1024; height: 768; visible: true
    Rectangle {
        objectName: "testingItem"
        width: 200; height: 40; color: "green"
    }
}

And in C++, assume engine is the QQmlApplicationEngine that loads main.qml, we can easily find testingItem by searching the QObject tree from QML root item using QObject::findChild:

//C++
void printTestingItemColor()
{
    auto rootObj = engine.rootObjects().at(0); //assume main.qml is loaded
    auto testingItem = rootObj->findChild<QQuickItem *>("testingItem");
    qDebug() << testingItem->property("color");
}

However, this method cannot find all items in QML since some items may not have QObject parent. For example, delegates in ListView or Repeater:

ListView {
    objectName: "view"
    width: 200; height: 80
    model: ListModel { ListElement { colorRole: "green" } }
    delegate: Rectangle {
        objectName: "testingItem" //printTestingItemColor() cannot find this!!
        width: 50; height: 50
        color: colorRole
    }
}

For delegates in ListView, we have to search the visual child instead of the object child. ListView delegates are parented to ListView's contentItem. So in C++ we have to search for the ListView first (with QObject::findChild), and then search for delegates in contentItem using QQuickItem::childItems:

//C++
void UIControl::printTestingItemColorInListView()
{
    auto view = m_rootObj->findChild<QQuickItem *>("view");
    auto contentItem = view->property("contentItem").value<QQuickItem *>();
    auto contentItemChildren = contentItem->childItems();
    for (auto childItem: contentItemChildren )
    {
        if (childItem->objectName() == "testingItem")
            qDebug() << childItem->property("color");
    }
}
mcchu
  • 3,309
  • 1
  • 20
  • 19