1

I want to connect a signal which is created by a C++ QObject to a function in a QML item. The signal is the "activated" signal from a QSystemTrayIcon and its argument is ActivationReason (an enum value).

Unfortunately it seems I can't connect a signal with this signature to a slot which seems to only be able to receive QVariant.

In the QML file

function trayIconClicked(reason) { ... }

In the C++ code

QObject::connect(trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), rootObject, SLOT(trayIconClicked(QVariant)));

And this is what I get

QObject::connect: Incompatible sender/receiver arguments
        QSystemTrayIcon::activated(QSystemTrayIcon::ActivationReason) --> ApplicationWindow_QMLTYPE_11_QML_60::trayIconClicked(QVariant)

If I completely drop the argument on the slot side, the event calls the function. But then I have no idea what ActivationReason triggred it.

A full working version of the code above is here, except that I can't hand in the reason parameter https://github.com/sturmf/qt_samples/tree/master/trayicon

Fabian
  • 5,476
  • 4
  • 35
  • 46
  • maybe this page help you: http://stackoverflow.com/questions/8834147/c-signal-to-qml-slot-in-qt – Farhad Apr 29 '16 at 11:53
  • unfortunately not, I read this answer before. He is lucky that both sides, signal and slot can be changed to QVariant. I have the fixed parameter from the QSystemTrayIcon. I also know about an intermediate slot which could be used for translation. But my code lives in the main function of the C++ code where I don't have a QObject that could work as an intermediate. – Fabian Apr 29 '16 at 12:10
  • @Fabian - conversion to `QVariant` is needed for QML-C++ interop, you can register the custom type to as a meta type so it can be wrapped by a variant so it can be passed to the QML side. – dtech Apr 29 '16 at 12:38
  • @ddriver Hmm my problem is that ActivationReason is not a custom type and I can't register it in my main.cpp at least I get the compile error please use the Q_DECLARE_METATYPE. And I can't use Q_DECLARE_METATYPE outside of an QObject. – Fabian Apr 29 '16 at 13:22
  • Yes you can: Ideally, this macro should be placed below the declaration of the class or struct. If that is not possible, it can be put in a private header file which has to be included every time that type is used in a QVariant. – dtech Apr 29 '16 at 14:20
  • @ddriver I really tried, but to no avail, I now added a link to a small sample app, maybe you can show how it would need to be done? – Fabian Apr 29 '16 at 14:40
  • OK, so it is just an enum, that's why it can't be registered as a meta type, and it is basically just an int. So you could connect it to signal on the C++ side that re-emits it cast as an integer, and you connect the QML function to that. – dtech Apr 29 '16 at 15:11
  • 1
    ... can't you just implement a trampoline slot performing the wrapping and re-emitting the signal as a QVariant? – peppe May 02 '16 at 00:11
  • @peppe See my answer below, this is my idea of a trampoline slot. Is there even a more elegant or shorter version without subclassing? – Fabian May 10 '16 at 18:50

2 Answers2

0

I now subclassed the QSystemTrayicon and added a slot which emits another signal without the parameter.

#ifndef TRAYICON_H
#define TRAYICON_H
#include <iostream>
#include <QObject>
#include <QSystemTrayIcon>

class TrayIcon : public QSystemTrayIcon
{
    Q_OBJECT
public:
    explicit TrayIcon(QObject *parent = 0) : QSystemTrayIcon(parent){}

signals:
    void triggered();

public slots:
    void trayIconActivated(QSystemTrayIcon::ActivationReason reason) {
        std::cout << "activated" << std::endl;
        if (reason == QSystemTrayIcon::Trigger) {
            std::cout << "tiggered" << std::endl;
            emit triggered();
        }
    }
};

#endif // TRAYICON_H
Fabian
  • 5,476
  • 4
  • 35
  • 46
0

In Qt5 you can connect to an anonymous function, by the way.

QObject::connect(trayIcon
    , SIGNAL(activated(QSystemTrayIcon::ActivationReason))
    , [=](QSystemTrayIcon::ActivationReason r){
              rootObject->trayIconClicked(r);
          });
bipll
  • 11,747
  • 1
  • 18
  • 32
  • How to emit an arbitrary signal in rootObject? – Sassan Aug 15 '16 at 02:09
  • Do you mean how can an arbitrary signal from an object be emitted from inside a method of rootObject? You can connect a rootObject's signal to that signal and the emit the latter. – bipll Aug 15 '16 at 21:55