title: How can I listen to a C++ signal from QML?
body: <p>I have what I'm calling a C++ "service" who's interface I want to expose to QML.  I'm trying to use <a href="http://doc.qt.io/qt-5/qqmlcontext.html#setContextProperty" rel="nofollow"><code>QQmlContext</code>'s <code>setContextProperty</code></a> to link the object into the QML and connect to it from a <a href="http://doc.qt.io/qt-5/qtqml-syntax-signals.html" rel="nofollow">QML <code>Connections</code> block</a>.</p>
  
  <p>QML isn't complaining with a reference error as it did previously when I hadn't registered the service in the QML context:</p>
  
  <pre><code>qrc:/main.qml:13: ReferenceError: service is not defined
  </code></pre>
  
  <p>So, QML seems to find the <code>service</code> object now, however the QML slot javascript function is not getting invoked.  I see this in Qt Creator:</p>
  
  <pre><code>Debugging starts
  QML debugging is enabled. Only use this in a safe environment.
  QML Debugger: Waiting for connection on port 62301...
  Calling the clbk signal
  Debugging has finished
  </code></pre>
  
  <p>There should be an <code>In onClbk</code> message per <code>console.log("In onClbk");</code>  I know that I can use <a href="http://doc.qt.io/qt-5/qtqml-cppintegration-interactqmlfromcpp.html#invoking-qml-methods" rel="nofollow"><code>QMetaObject::invokeMethod</code></a> to invoke a QML object's function directly, but I am trying to have a little looser coupling through the use of signals and slots.</p>
  
  <p>I would like to avoid creating a <code>QQuickItem</code> and instantiating the service in the QML, if at all possible.</p>
  
  <p><em>Unfortunately, the boilerplate code is legion and this is my <a href="http://sscce.org/" rel="nofollow">SSCCE</a>.</em></p>
  
  <p><a href="https://dl.dropboxusercontent.com/u/35617147/qt_test.zip" rel="nofollow"><strong>Here is a zip file of all the project directory as created through Qt Creator 5.4.</strong></a></p>
  
  <h1>main.cpp</h1>
  
  <pre class="lang-c++ prettyprint-override"><code>int main(int argc, char *argv[])
  {
      QGuiApplication app(argc, argv);
      QQmlApplicationEngine engine;
      auto rc = engine.rootContext();
      auto service = new Service();
      engine.rootContext()-&gt;setContextProperty(QStringLiteral("service"), service);
      engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
  
      // invoke the trigger arbitrarily
      QTimer *timer = new QTimer();
      timer-&gt;setSingleShot(true);
      QObject::connect(timer, SIGNAL(timeout()), service, SLOT(trigger_clbk()));
      timer-&gt;start(4000);
      return app.exec();
  }
  </code></pre>
  
  <h1>service.h</h1>
  
  <pre><code>class Service : public QQuickItem {
      Q_OBJECT
  
  public:
      virtual ~Service(){}
  signals:
      void clbk();
  public slots:
      void trigger_clbk() {
          qDebug()&lt;&lt;"Calling the clbk signal";
          clbk();
      }
  };
  </code></pre>
  
  <h1>main.qml</h1>
  
  <pre><code>import QtQuick 2.4
  import QtQuick.Window 2.2
  
  Window {
      visible: true
      MainForm {
          anchors.fill: parent
          mouseArea.onClicked: {
              Qt.quit();
          }
          // subscribe to a signal
          Connections {
              target: service
              onClbk: function(){
                  console.log("In onClbk");
              }
          }
      }
  }
  </code></pre>
  
  <h1>Main.ui.qml</h1>
  
  <pre><code>import QtQuick 2.3
  
  Rectangle {
      property alias mouseArea: mouseArea
  
      width: 360
      height: 360
  
      MouseArea {
          id: mouseArea
          anchors.fill: parent
      }
  
      Text {
          anchors.centerIn: parent
          text: "Hello World"
      }
  }
  </code></pre>