Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

c++

qt

qt5

qml

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 ?
    }
}
like image 505
Nulik Avatar asked Dec 30 '16 18:12

Nulik


2 Answers

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.

like image 94
Th. Thielemann Avatar answered Nov 10 '22 07:11

Th. Thielemann


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:

        Flickable {
            id: flickable

            anchors.fill: parent
            anchors.margins: 10

            contentWidth: columnLayout.width
            contentHeight: columnLayout.height
            clip: true

            ColumnLayout {
                id: columnLayout

                width: flickable.width

                TextEdit {
                    id: firstTextEdit
                    Layout.fillWidth: true
                    font.pointSize: styles.textPointSize
                    selectByMouse: true
                }

                TextEdit {
                    id: secondTextEdit
                    Layout.fillWidth: true
                    font.pointSize: styles.textPointSize
                    selectByMouse: true
                }

                Button {
                    text: qsTr("Divide")
                    font.pointSize: styles.textPointSize
                    onClicked: {
                        resultTextEdit.text = "";
                        const first = parseFloat(firstTextEdit.text);
                        const second = parseFloat(secondTextEdit.text);
                        const result = mathTools.divide(first, second);
                        resultTextEdit.text = result;
                    }
                }

                Text {
                    id: resultTextEdit
                    Layout.fillWidth: true
                    font.pointSize: styles.textPointSize
                }
            }
        }

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
like image 1
Stephen Quan Avatar answered Nov 10 '22 06:11

Stephen Quan