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. It's possible to call c++ function from qml and update a ListModel?
Qt 6.11 is out! See what's new in the release blog

It's possible to call c++ function from qml and update a ListModel?

Scheduled Pinned Locked Moved Unsolved QML and Qt Quick
15 Posts 3 Posters 6.4k Views 2 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.
  • V vladstelmahovsky

    Have thought about your list gets out of scope?
    Cant see full sources, so cant say 100% sure, but it looks like it is

    sdsoldiS Offline
    sdsoldiS Offline
    sdsoldi
    wrote on last edited by sdsoldi
    #6

    I feel the delay in answering...

    I can't paste my code here... I have this error message when I post it: Post content was flagged as spam by Akismet.com

    Edit:

    I suppose that I need "refresh" main.qml or reload it.

    Here is my main.cpp

    #include <QGuiApplication>
    #include <QQmlApplicationEngine>
    #include <QtQml>
    
    #include "Excel.h"
    
    int main(int argc, char *argv[])
    {
        QGuiApplication app(argc, argv);
    
        qmlRegisterType<Excel>("com.myself", 1, 0, "Excel");
    
        QQmlApplicationEngine engine;
        engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    
        QStringList dataList;
        dataList.append("wololo");
    
        engine.rootContext()->setContextProperty( "cppModel", QVariant::fromValue(dataList) );
    
        return app.exec();
    }
    

    Class of excel file. I'm loading xlsxdocument plugin.
    Excel.h

    #ifndef EXCEL_H
    #define EXCEL_H
    
    #include <QObject>
    #include "xlsx/xlsxdocument.h"
    #include "xlsx/xlsxabstractsheet.h"
    
    class Excel : public QObject
    {
        Q_OBJECT
    public:
        Q_INVOKABLE getExcel(QString path);
    
    signals:
    
    public slots:
    };
    
    #endif // EXCEL_H
    

    Here is my function that I'm trying to update my combobox model.
    Excel.cpp

    #include "Excel.h"
    #include <QDebug>
    #include <QQmlApplicationEngine>
    #include <QtQml>
    
    Excel::getExcel(QString path)
    {
        path.remove(0,8);
        qDebug() << path;
        QXlsx::Document xlsx(path);
        xlsx.selectSheet("MOULD DIMENSIONS");
        //etc..
    
        QQmlApplicationEngine engine;
        QStringList dataList;
        dataList.append("Item 2");
        engine.rootContext()->setContextProperty( "cppModel", QVariant::fromValue(dataList) );
    }
    

    And here is my main qml.
    main.qml

    import QtQuick 2.5
    import QtQuick.Window 2.2
    import QtQuick.Controls 1.4
    import QtQuick.Dialogs 1.2
    import com.myself 1.0
    
    
    Window {
        visible: true
    
        Excel {
            id: excel
        }
    
        Button {
            id: btnOpen
            width: 125
            text: qsTr("Open Excel")
            clip: false
        }
    
        ComboBox {
            id: combo
            model: cppModel
        }
    
        FileDialog {
            id: fileDialog
            title: "Please choose a file"
            folder: shortcuts.home
            onAccepted: {
                excel.getExcel(fileDialog.fileUrls.toString());
    
            }
        }
        Connections {
            target: btnOpen
            onClicked: fileDialog.visible = true
        }
    }
    

    When I run, the combobox has only 1 item. 'wololo' item.
    And when I open a Excel file, I need to change the combobox items. In this example I need to add 'Item 2' item to combobox.

    But is not working.

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

      The 'engine' you create in getExcel() is not the same object as the one you create in main.cpp... so you are setting the root property on a different engine than the one you use to display QML :-)

      To fix this, just pass the engine (or the root context) pointer to your Excel class and use it in getExcel().

      (Z(:^

      sdsoldiS 1 Reply Last reply
      1
      • sierdzioS Offline
        sierdzioS Offline
        sierdzio
        Moderators
        wrote on last edited by sierdzio
        #8

        Another option is to use parent-child hierarchy instead of root properties.

        So, in QML:

        Excel {
          ComboBox {
            id: combo
            objectName: "combo"
          }
        }
        

        And then set model from CPP:

        // Pseudocode, written from memory. Please check the docs to be sure:
        QObject *combo = findChildren<QQuickItem*>("combo"); // combo is a child of Excel in QML!
        if (combo) {
          combo->setProperty("model", QVariant::fromValue(dataList) );
        }
        

        Not sure which one you'll find more aesthetic (also not sure if the second option would work at all ;-) ).

        (Z(:^

        1 Reply Last reply
        1
        • sierdzioS sierdzio

          The 'engine' you create in getExcel() is not the same object as the one you create in main.cpp... so you are setting the root property on a different engine than the one you use to display QML :-)

          To fix this, just pass the engine (or the root context) pointer to your Excel class and use it in getExcel().

          sdsoldiS Offline
          sdsoldiS Offline
          sdsoldi
          wrote on last edited by
          #9

          @sierdzio said:

          The 'engine' you create in getExcel() is not the same object as the one you create in main.cpp... so you are setting the root property on a different engine than the one you use to display QML :-)

          To fix this, just pass the engine (or the root context) pointer to your Excel class and use it in getExcel().

          Oh!! It's true... I supose that If I create a engine on main, I can use It on another cpp or h class...

          But now I have a another question... How I can pass engine, or root from main to qml and them from qml to function?

          Anyway, I will try the parent-child

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

            @sdsoldi said:

            How I can pass engine, or root from main to qml and them from qml to function?

            You can create a singleton class in C++, pass the engine pointer to it in main.cpp, and then simply access it in your Excel class. This is probably the simplest solution, although singletons do have their drawbacks.

            Or add the engine as a context property to QML, then assign it to Excel object... although that seems awkward.

            (Z(:^

            1 Reply Last reply
            1
            • V Offline
              V Offline
              vladstelmahovsky
              wrote on last edited by
              #11

              or use
              QQmlEngine *qmlEngine(const QObject *object)

              sdsoldiS 1 Reply Last reply
              2
              • V vladstelmahovsky

                or use
                QQmlEngine *qmlEngine(const QObject *object)

                sdsoldiS Offline
                sdsoldiS Offline
                sdsoldi
                wrote on last edited by
                #12

                @vladstelmahovsky Can you explain it please?

                sierdzioS 1 Reply Last reply
                0
                • sdsoldiS sdsoldi

                  @vladstelmahovsky Can you explain it please?

                  sierdzioS Offline
                  sierdzioS Offline
                  sierdzio
                  Moderators
                  wrote on last edited by
                  #13

                  @sdsoldi

                  It is a static method of the engine. SO you can probably use it like this (in Excel class):

                      QQmlEngine *engine = qmlEngine(this); // because "this" is an item you have added to QML
                      QStringList dataList;
                      dataList.append("Item 2");
                      engine.rootContext()->setContextProperty( "cppModel", QVariant::fromValue(dataList) );
                  

                  (Z(:^

                  sdsoldiS 1 Reply Last reply
                  1
                  • sierdzioS sierdzio

                    @sdsoldi

                    It is a static method of the engine. SO you can probably use it like this (in Excel class):

                        QQmlEngine *engine = qmlEngine(this); // because "this" is an item you have added to QML
                        QStringList dataList;
                        dataList.append("Item 2");
                        engine.rootContext()->setContextProperty( "cppModel", QVariant::fromValue(dataList) );
                    
                    sdsoldiS Offline
                    sdsoldiS Offline
                    sdsoldi
                    wrote on last edited by
                    #14

                    @sierdzio @vladstelmahovsky
                    Oh my god! It's as simple as that...

                    Thank you very much!

                    1 Reply Last reply
                    0
                    • V Offline
                      V Offline
                      vladstelmahovsky
                      wrote on last edited by
                      #15

                      yep, but dont forget to check for null

                      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