How to insert ListElement in a QML ListModel using C++?

15,991

Solution 1

Alright. I think you can do something like this:

In your main QML-file add simple function.

Rectangle {
    // ...

    function append(newElement) {
        view.model.append(newElement)
    }

    PathView {
        id: view

        // ...

        model: Menu1 {} //First QML showed

        // ...
    }
}

This method will just call a corresponding method from ListModel. More supported methods you can find there.

Then all you need is to call this method from C++ code. You can do this in such manner:

MainForm::MainForm(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::MainForm)
{
    ui->setupUi(this);
    this->resize(1024, 576);

    QDeclarativeView *myQMLTest = new QDeclarativeView(QUrl::fromLocalFile    ("myMainQML.qml"));
    myQMLTest->setStyleSheet(QString("background: transparent; width: 600px"));

    QVariantMap newElement;  // QVariantMap will implicitly translates into JS-object
    newElement.insert("name",       "Image 13"         );
    newElement.insert("iconSource", "pics/image_13.jpg");

    QMetaObject::invokeMethod(
        myQMLTest->rootObject(),                          // for this object we will call method
        "append",                                         // actually, name of the method to call
        Q_ARG(QVariant, QVariant::fromValue(newElement))  // method parameter
    );

    this->ui->frameListVideoGallery->layout()->addWidget(myQMLTest);
    myQMLTest->setFocus();
    myQMLTest->installEventFilter(this);
}

You should check this for more information.

Also you can choose another approach: to pass some data via qml properties (using QDeclarativeEngine and QDeclarativeContext) and then handle this data and your list-model right in JavaScript code.

Solution 2

I want to make the answer from @GooRoo more complete/usefull to Qt beginners. If you use the Qt Creator, you will start with a template using QmlApplicationViewer. To apply the answer from GooRoo you have to do something like this (thanks to http://www.lothlorien.com/kf6gpe/?p=309):

CPP:

Q_DECL_EXPORT int main(int argc, char *argv[])
{
    QScopedPointer<QApplication> app(createApplication(argc, argv));
    QScopedPointer<QmlApplicationViewer> viewer(QmlApplicationViewer::create());

    viewer->setOrientation(QmlApplicationViewer::ScreenOrientationAuto);
    viewer->setMainQmlFile(QLatin1String("qml/mydemo/main.qml"));
    viewer->showExpanded();

    QMetaObject::invokeMethod(
        (QObject *)viewer->rootObject()->findChild<QObject *>("myModel"), // QML item
        "test"                           // name of the method to call
                                         // without parameters
    );

    return app->exec();
}

QML:

PageStackWindow {
    id: mainApp
    ...

    ListModel {
        id: myModel
        objectName: myModel //THIS IS NEEDED BY findChild()
        ...
        function test() {
            console.log("TEST OK");
        }
    }

    Page {
        ...
    }
}
Share:
15,991
Adriano Leal
Author by

Adriano Leal

I have worked with development systems since 2007 during my first trainee job. Here in Brazil I did a technical course focused in development systems (2005-2008). Currently I have a degree in IT by State University of Campinas (Unicamp), from 2009 to 2013, and have worked developing solutions for Digital TV at EiTV (www.eitv.com.br) company. At EiTV I have worked with C, C++ with Qt Framework, Ruby On Rails, Ginga NCL + Lua script on the Linux environment and some projects with C#. I like to play soccer, drink beer with friends, national pop rock and it's enough! =D Any doubt or interest let me know sending me a message to [email protected] Thanks, see you and don't worry... Be happy! =]

Updated on June 06, 2022

Comments

  • Adriano Leal
    Adriano Leal about 2 years

    Well, i'm learning to work with QML and i have one doubt. In my example, i have a ListModel with ListElements at QML and i have a QML main file with a rectangle, PathView etc.

    I have a QWidget also, than is my main window. In this QWidget i include the QML UI like a component. Ok!

    How can I handle QML ListElements by using C++?
    Note: when I say "to handle", I want to say include an element for example.

    Below are some parts of my code...

    QML containing my ListElement, called "Menu1":

    import QtQuick 1.0
    
    ListModel {
        id: listMovieModel
        ListElement { name: "Image 1"; iconSource: "pics/image_1.jpg" }
        ListElement { name: "Image 2"; iconSource: "pics/image_2.jpg" }
        ListElement { name: "Image 3"; iconSource: "pics/image_3.jpg" }
        ListElement { name: "Image 4"; iconSource: "pics/image_4.jpg" }
        ListElement { name: "Image 5"; iconSource: "pics/image_5.jpg" }
        ListElement { name: "Image 6"; iconSource: "pics/image_6.jpg" }
    }
    

    My main QML:

    Rectangle {
        width: 500
        height: 600
        color: "transparent"
    
        PathView {
            id: view
            focus: true
            width: parent.width
            height: parent.height + y
            y: -150
            model: Menu1 {} //First QML showed
            delegate: Image {
                source: iconSource
                width: 64
                height: 90
                scale: PathView.isCurrentItem ? 3.5 * y / parent.height : 2.0 * y / parent.height
                z: y
                smooth: true
            }
            path: MyGeometricFigure { //This a another file, but is confidential
                width: view.width
                height: view.height
            }
            preferredHighlightBegin: 0
            preferredHighlightEnd: 0
            highlightRangeMode: PathView.StrictlyEnforceRange
            Keys.onLeftPressed: decrementCurrentIndex()
            Keys.onRightPressed: incrementCurrentIndex()
        }
    }
    

    And as I use QML like a component for my QWidget:

    MainForm::MainForm(QWidget *parent) :
        QWidget(parent),
        ui(new Ui::MainForm)
    {
        ui->setupUi(this);
        this->resize(1024, 576);
    
        QDeclarativeView *myQMLTest = new QDeclarativeView(QUrl::fromLocalFile("myMainQML.qml"));
        myQMLTest->setStyleSheet(QString("background: transparent; width: 600px"));
    
        this->ui->frameListVideoGallery->layout()->addWidget(myQMLTest);
        myQMLTest->setFocus();
        myQMLTest->installEventFilter(this);
    }
    

    I saw some articles about this, but I am not able to change my LisModel using C++. I saw here http://doc.qt.nokia.com/4.7/qdeclarativemodels.html#c-data-models and here in examples using PathView http://doc.qt.nokia.com/4.7/qdeclarativeexamples.html

    Can someone help me?

    Thanks!