Nulik
Nulik

Reputation: 7360

Qt: Throwing an exception from C++ to QML engine

When calling a Q_INVOKABLE method written in C++ from a JavaScript function in QML, how do you throw an exception ? The method is owned by an object of a type < MyApp > , registered with a call qmlRegisterType()

For example, I have the following QML code:

TextField {
    id: fld_recipient

    onEditingFinished: {
        try {
            var identity=myapp.identities.current_Identity;
            var company=identity.companies.current_Company;
            myapp.lookup_email(identity.identity_id,company.company_id,fld_recipient.text)
        } catch(e) {
            console.log(e);
        }
    }
}

Here, the method MyApp::lookup_email() goes to the server and searches for matching email addresses. This process can be stopped by a large amount of errors and I want the catch() statement to show that error.

How is this done on the C++ side ? Kind of like this:

void MyApp::lookup_email(int identity_id,int company_id,QString email) {

    ....

    error_code=server->lookup_email(identity_id,company_id,email);

    if (error_code) { /// throw an exception to QML engine, 
         ????? <= what goes here ?
    }
}

Upvotes: 8

Views: 2830

Answers (2)

Stephen Quan
Stephen Quan

Reputation: 25891

The following code snippet shows how you may use QQmlEngine::throwError:

#ifndef __MathTools__
#define __MathTools__
#include <QObject>
#include <QQmlEngine>
#include <QString>
class MathTools : public QObject
{
    Q_OBJECT
public:
    MathTools(QObject* parent = nullptr) : QObject(parent) { }
    Q_INVOKABLE double divide(double a, double b)
    {
        if (b == 0.0)
        {
            qmlEngine(this)->throwError(tr("Division by zero error"));
            return 0.0;
        }
        return a / b;
    }
};
#endif

When used in QML:

    ColumnLayout {
        TextField { id: first; text: "1" }
        TextField { id: second; text: "0" }
        Button {
            text: qsTr("Divide")
            onClicked: {
                try {
                    const f = parseFloat(first.text);
                    const s = parseFloat(second.text);
                    result.text = mathTools.divide(f, s);
                } catch (err) {
                    result.text = err.message;
                }
            }
        }
        TextField { id: result }
    }```

I see a QML/Javascript error being thrown when attempting to divide by zero:

qrc:/main.qml:58: Error: Division by zero error


Reference:
 - https://doc.qt.io/qt-5/qjsengine.html#throwError

Upvotes: 3

Th. Thielemann
Th. Thielemann

Reputation: 2825

Qml should not include any business logic but just display any results. In case your application runs into an exception state catch the exception in the business logic and present the resulting/new state to the user.

In case you assume your (UI) code will be called with incomplete data you should just ignore it. Or use assertions on debug level.

Upvotes: 3

Related Questions