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.3k 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.
  • sdsoldiS Offline
    sdsoldiS Offline
    sdsoldi
    wrote on last edited by
    #1

    I'm trying to update my ListModel but it is impossible.

    If I set on my main.cpp

    QStringList dataList;
    dataList.append("Item 222");
    QQmlContext *ctxt = engine.rootContext();
    ctxt->setContextProperty("myModel",  QVariant::fromValue(dataList));
    

    It's working.

    But if a do the same on a excel.h doesn't work

    QStringList dataList;
    dataList.append("Item 222");
    QQmlApplicationEngine engine;
    QQmlContext *classContext = engine.rootContext();
    classContext->setContextProperty("myModel", QVariant::fromValue(dataList));
    

    It is not updating my combobox.

    I need to open a excel and set combobox items but I can't.

    Thanks and sorry for my bad english

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

      This is described in depth in the documentation: link

      Quoting:

      Note: There is no way for the view to know that the contents of a QStringList have changed. If the QStringList changes, it will be necessary to reset the model by calling QQmlContext::setContextProperty() again.

      (Z(:^

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

        Hm actually you are calling setContextProperty() again, so it should work. Are you sure you are updating correct model ("myModel" - is it correct)?

        (Z(:^

        sdsoldiS 1 Reply Last reply
        1
        • sierdzioS sierdzio

          Hm actually you are calling setContextProperty() again, so it should work. Are you sure you are updating correct model ("myModel" - is it correct)?

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

          @sierdzio Yep because if I do on Main.cpp it's working. But when I call from qml to this function on excel.h doesn't work.

          No errors, and no info on debugger.

          Also I've got a

          qmlRegisterType<Excel>("com.myself", 1, 0, "Excel");
          

          line on main.cpp to call those functions on excel.h

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

            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 1 Reply Last reply
            1
            • 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