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. How should errors in C++ slots be communicated to QML?
Forum Updated to NodeBB v4.3 + New Features

How should errors in C++ slots be communicated to QML?

Scheduled Pinned Locked Moved Solved QML and Qt Quick
5 Posts 4 Posters 766 Views 3 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.
  • T Offline
    T Offline
    thierryhenry14
    wrote on last edited by
    #1

    Let's say you have a QML app which invokes slots on a C++ object. Like for example:

    typedef int JobID;
    public slots:
    	JobID createAndBeginJob(jobarg1, jobarg2);
    	void cancelOngoingJob(JobID);
    

    QML calls createAndBeginJob to start a job, and can also call cancelOngoingJob.

    Button {
            id: createJobButton
            text: "try me"
            onClicked: {
    			var jobid = jobCreator.createAndBeginJob("called from QML", 123);
    			joblist.append(jobid);
    		}
        }
    

    If the QML provides invalid arguments to createAndBeginJob, how am I supposed to communicate this to the QML, so it can show a message like "jobarg2 is invalid because blah blah". The options I can see are:

    • Return a "magic value" like -1 for the JobID. Gets messy quick, and still doesn't communicate the actual reason for failure to QML. I'd probably need a generic "errorHappened(QString errmsg)" signal in my objects that QML connects to and shows popups. It totally decouples the call from the error which feels wrong.
    • Replace every slot's return value with a "CallResult" container with the members "bool successful; QString errrmsg; RealReturnValue returnvalue;" and have QML check successful + errmsg first. Very boilerplatey.
    • Throw an exception from the slot. Qt says exceptions are not supported in slots, and try/catch doesn't seem to work from QML so it just crashes the application.
    JKSHJ 1 Reply Last reply
    0
    • SGaistS Offline
      SGaistS Offline
      SGaist
      Lifetime Qt Champion
      wrote on last edited by
      #2

      Hi and welcome to devnet,

      Another option more in line with what Qt uses: have an errorOccured signal. Then depending on your design you can pass an enum as parameter with the corresponding error code, or have an error method that returns the error code or even both.

      Interested in AI ? www.idiap.ch
      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

      1 Reply Last reply
      4
      • T thierryhenry14

        Let's say you have a QML app which invokes slots on a C++ object. Like for example:

        typedef int JobID;
        public slots:
        	JobID createAndBeginJob(jobarg1, jobarg2);
        	void cancelOngoingJob(JobID);
        

        QML calls createAndBeginJob to start a job, and can also call cancelOngoingJob.

        Button {
                id: createJobButton
                text: "try me"
                onClicked: {
        			var jobid = jobCreator.createAndBeginJob("called from QML", 123);
        			joblist.append(jobid);
        		}
            }
        

        If the QML provides invalid arguments to createAndBeginJob, how am I supposed to communicate this to the QML, so it can show a message like "jobarg2 is invalid because blah blah". The options I can see are:

        • Return a "magic value" like -1 for the JobID. Gets messy quick, and still doesn't communicate the actual reason for failure to QML. I'd probably need a generic "errorHappened(QString errmsg)" signal in my objects that QML connects to and shows popups. It totally decouples the call from the error which feels wrong.
        • Replace every slot's return value with a "CallResult" container with the members "bool successful; QString errrmsg; RealReturnValue returnvalue;" and have QML check successful + errmsg first. Very boilerplatey.
        • Throw an exception from the slot. Qt says exceptions are not supported in slots, and try/catch doesn't seem to work from QML so it just crashes the application.
        JKSHJ Online
        JKSHJ Online
        JKSH
        Moderators
        wrote on last edited by
        #3

        @thierryhenry14 said in How should errors in C++ slots be communicated to QML?:

        • Return a "magic value" like -1 for the JobID. Gets messy quick, and still doesn't communicate the actual reason for failure to QML. I'd probably need a generic "errorHappened(QString errmsg)" signal in my objects that QML connects to and shows popups. It totally decouples the call from the error which feels wrong.

        You could use a "magic value" to indicate that the job failed to start, coupled with a separate function that you can call to retrieve the error:

        var jobid = jobCreator.createAndBeginJob("called from QML", 123);
        if (jobid >= 0)
            joblist.append(jobid);
        else
            console.log(jobCreator.lastError())
        
        • Replace every slot's return value with a "CallResult" container with the members "bool successful; QString errrmsg; RealReturnValue returnvalue;" and have QML check successful + errmsg first. Very boilerplatey.

        This is actually quite a common technique in RESTful APIs, where the return value is a complex JSON document that contains both diagnostic information and "actual" data.

        {
            "success": false,
            "errorMessage": "Server busy",
            "jobID": -1
        }
        

        Granted, this is less common in C++ APIs.

        Let's say you have a QML app which invokes slots on a C++ object.

        FYI: Slots are functions that are designed to be connected to signals, and they usually return void because there is no reliable way to get the slot's return value when emitting a signal.

        Your example shows an invokable function. You can declare these using the Q_INVOKABLE macro: https://doc.qt.io/qt-5/qobject.html#Q_INVOKABLE

        All slots are invokable functions, but not all invokable functions are slots.

        Qt Doc Search for browsers: forum.qt.io/topic/35616/web-browser-extension-for-improved-doc-searches

        1 Reply Last reply
        3
        • I Offline
          I Offline
          Igor Baidiuk
          wrote on last edited by
          #4

          @thierryhenry14
          You will have most probably to stick with manual solution suggested by @SGaist. You see, Qt simply doesn't have some common error handling strategy. There are default values, magic values, status methods, and no common ground for them. Same goes with QML, even worse.

          With QWidgets, we could override QCoreApplication::notify, catch our exceptions there and do something reasonable. And that strategy was rather effective, since each event usually constituted single operation which could succeed as a whole.

          With QML, we have neither notify (since QML runtime isn't exception-neutral) nor anything similar to override. Code which invokes native slot from QML expression is buried deep in implementation details. C++ API for creating JS exceptions is severely limited - you can obtain engine pointer only in a limited set of situations (namely from objects owned by QML) - or have to store it manually in some global variable.

          Lastly, the only way to do something to unhandled exceptions is QQmlEngine::warnings signal. But due to info loss when exception is converted to QQmlError, and due to nature of that type, the capabilities we have here are also limited.

          @SGaist
          Well yes, you're right that it seems to be the only way in vanilla Qt. Though it really saddens me that such a magnificent framework with such a long and prominent history has one of the worst error handling stories I've seen so far. It means that when one develops application, he must invent his own way of propagating and handling errors since Qt provides none.

          1 Reply Last reply
          3
          • T Offline
            T Offline
            thierryhenry14
            wrote on last edited by
            #5

            Thanks for explaining this.

            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