1

I’m working on a QUL / Qt Quick Ultralite application (targeting ESP32, using QUL 2.9.0) where I have:

  • A CharacterSelectors.qml component that uses a Repeater to render multiple character-selector subcomponents.

  • A TextEditVM (C++ / QUL view-model) with getWord() method, which is supposed to concatenate the currently selected characters from each CharacterSelector. and a setter setChar(int index, const std::string& data)

  • From the logs (via idf.py monitor), I see that when I select individual characters, those delegate components are created and some logging occurs. However, when I call getWord() from the VM, the returned word is incomplete (often empty).

Below are simplified / trimmed but representative versions of my .qml and C++ VM code. I hope someone can spot what I’m doing wrong or suggest a better pattern.

CharacterSelectors.qml

import QtQuick 2.15
import QtQuick.Controls 2.15
import Constants 1.0
import "../BaseControl"

Row {
  id: root
  spacing: 10
  
  property string currentWord: ""
  
  TextEditVM {
    id: textEditVM
    Component.onCompleted: {
      textEditVM.init(5)
    }
  }

  Repeater {
    id: repeater
    model: 5
    CharacterSelector {
      property int index: 0
      property string chararcter: " "

      onSelectedCharChanged: {
        chararcter = selectedChar;

        if (selectedChar !== "") {
          console.log("CharacterSelectors - Setting char at index", index, "to", selectedChar)
          textEditVM.setChar(index, selectedChar)
          // Force update the currentWord property
          root.currentWord = textEditVM.getWord()
        }
      }
    }
  }

  function getWord() : string {
    return textEditVM.getWord();
  }
}

(There is also some parent QML or C++ code that instantiates CharacterSelectors, passes textEditVM as vm, etc.)

TextEditVM (C++ / QUL side)

text_edit_vm.h

#pragma once
#include <QObject>
#include <QString>
#include <vector>

class TextEditVM : public QObject {
    Q_OBJECT
    Q_PROPERTY(QString word READ getWord WRITE setWord NOTIFY wordChanged)
public:
    explicit TextEditVM(QObject *parent = nullptr);

    QString getWord() const;
    void setWord(const QString &w);

signals:
    void wordChanged();

private:
    QString m_word;
};

text_edit_vm.cpp

#include "text_edit_vm.h"
#include <QDebug>

TextEditVM::TextEditVM(QObject *parent) : QObject(parent), m_word("") {
    qDebug() << "TextEditVM initialized";
}

QString TextEditVM::getWord() const {
    qDebug() << "TextEditVM::getWord returning:" << m_word;
    return m_word;
}

void TextEditVM::setWord(const QString &w) {
    if (m_word != w) {
        m_word = w;
        qDebug() << "TextEditVM::setWord, new word =" << m_word;
        emit wordChanged();
    }
}

getWord() from the view model never runs (or returns empty) even though setChar() logs show the character was set. What am I missing? Is this a timing / delegate-creation issue, a problem exposing the C++ object to QML, or a QUL-specific string/notify issue?

As the characterselectors changed characters, they should be visible on the textdialog. But it didn't

3
  • textEditVM does not have a setChar method, only a setWord method. Commented Sep 28 at 19:37
  • If I'm not mistaken, the documentation shows that defining QML properties on QUL is very different from desktop C++/QML integration. Commented Sep 28 at 23:12
  • If you want getWord() / setWord() methods accessible from QML, you should make them public and add Q_INVOKABLE, else the only way you can access them is via the Q_PROPERTY, but, I cannot see any evidence that you're using the Q_PROPERTY. Commented Sep 29 at 21:12

1 Answer 1

2

To read the content of m_word in QML, you can use the Q_PROPERTY you defined, by simply doing

  function getWord() : string {
    return textEditVM.word;
  }

You can use this just like you would any other property in qml. Internally, this will use your defined getter function getWord in c++, which you're declaring with the READ keyword in the Q_PROPERTY statement. You can also assign a new value to the property which will call the setter for you.

If you want to be able to call the cpp function getWord directly, you should mark it with Q_INVOKABLE:

Q_INVOKABLE QString getWord() const;

The same goes for the setter which you are also calling in your QML code. Hope this helps.

Sign up to request clarification or add additional context in comments.

3 Comments

The problem I get is that on QUL 2.9.0 that we are currently using for this project does not support Q_INVOKABLE and Q_PROPERTY on the C++ side
the vm runs fine when called on the repeater but tried to when it's time to call the getWord function from the text_edit_vm. It seems not being run. As you can see on the text dialog, it didn't get updated...but initially when I hardcoded the getWord from the view model to return a string it will be updated.
This documentation for Qt for MCUs 2.9.1 seems to indicate that your TextEditVM has to derive from Qul::Object, not QObject: doc.qt.io/archives/QtForMCUs-2.9/qtul-integratecppqml.html and properties are declared differently. Does this also apply to 2.9.0?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.