[Qt-qml] Hiding slots from QML

51 views
Skip to first unread message

Sven Anderson

unread,
Mar 12, 2012, 7:33:16 AM3/12/12
to qt-...@qt.nokia.com
Hi all,

if I implement QML types in C++, all slots are invokable from QML.
Usually I don't want that, because the slots are for C++ internal
communication. I found out (see older mail), that declaring the slots as
private makes them inaccessible from QML, but I can still connect to
them in the C++ world. My question is: can I rely on this, or is this an
unsupported feature? And a second question is: are there other good ways
of hiding slots from QML?

Thanks and best regards

Sven
_______________________________________________
Qt-qml mailing list
Qt-...@qt.nokia.com
http://lists.qt.nokia.com/mailman/listinfo/qt-qml

André Somers

unread,
Mar 13, 2012, 3:47:35 AM3/13/12
to qt-...@qt.nokia.com
Op 12-3-2012 12:33, Sven Anderson schreef:

> Hi all,
>
> if I implement QML types in C++, all slots are invokable from QML.
> Usually I don't want that, because the slots are for C++ internal
> communication. I found out (see older mail), that declaring the slots as
> private makes them inaccessible from QML, but I can still connect to
> them in the C++ world. My question is: can I rely on this, or is this an
> unsupported feature? And a second question is: are there other good ways
> of hiding slots from QML?
>
> Thanks and best regards
>
You could define a proxy QObject who's only purpose is to expose the API
you want to expose to QML, and nothing more than that. All it would do
would be forwarding the needed signals and slots to the real C++
implementation, that can be as complicated as you want as you don't
expose it outside of the C++ context. This is also basically how you
expose an interface for scripting, or for DBus.

I would not recommend making slots private just to hide them from QML.
While you can still connect to those slots from within that class, you
can no longer connect to it from outside the class itself. That may hurt
the API of that class.

André

Sven Anderson

unread,
Mar 13, 2012, 7:04:18 AM3/13/12
to qt-...@qt.nokia.com, an...@familiesomers.nl
Hi Andre,

On 13.03.2012 08:47, André Somers wrote:
> Op 12-3-2012 12:33, Sven Anderson schreef:

>> if I implement QML types in C++, all slots are invokable from QML.
>> Usually I don't want that, because the slots are for C++ internal
>> communication. I found out (see older mail), that declaring the slots as
>> private makes them inaccessible from QML, but I can still connect to
>> them in the C++ world. My question is: can I rely on this, or is this an
>> unsupported feature? And a second question is: are there other good ways
>> of hiding slots from QML?
>>
>> Thanks and best regards
>>
> You could define a proxy QObject who's only purpose is to expose the API
> you want to expose to QML, and nothing more than that. All it would do
> would be forwarding the needed signals and slots to the real C++
> implementation, that can be as complicated as you want as you don't
> expose it outside of the C++ context. This is also basically how you
> expose an interface for scripting, or for DBus.

Thanks a lot for your answer. I'm used to getting ignored on this list
most of the time. ;-)

So, you mean similar to a PIMPL pattern, like having a backend QObject,
that is created pairwise? Having two QObjects sounds quite heavy for a
simple QML item. And also the "proxy" Object would have to instantiate
the backend Object, not the other way around, since it is directly
instantiated by the QML engine. So it seems a bit weird to me.

> I would not recommend making slots private just to hide them from QML.
> While you can still connect to those slots from within that class, you
> can no longer connect to it from outside the class itself. That may hurt
> the API of that class.

Huh? I can perfectly connect to private slots from outside the class. I
just tested it to be sure.


Best regards,

Sven

Bo Thorsen

unread,
Mar 13, 2012, 11:11:55 AM3/13/12
to qt-...@qt.nokia.com
Den 13-03-2012 12:04, Sven Anderson skrev:
> Hi Andre,
>
> On 13.03.2012 08:47, André Somers wrote:
>> Op 12-3-2012 12:33, Sven Anderson schreef:
>>> if I implement QML types in C++, all slots are invokable from QML.
>>> Usually I don't want that, because the slots are for C++ internal
>>> communication. I found out (see older mail), that declaring the slots as
>>> private makes them inaccessible from QML, but I can still connect to
>>> them in the C++ world. My question is: can I rely on this, or is this an
>>> unsupported feature? And a second question is: are there other good ways
>>> of hiding slots from QML?
>>>
>>> Thanks and best regards
>>>
>> You could define a proxy QObject who's only purpose is to expose the API
>> you want to expose to QML, and nothing more than that. All it would do
>> would be forwarding the needed signals and slots to the real C++
>> implementation, that can be as complicated as you want as you don't
>> expose it outside of the C++ context. This is also basically how you
>> expose an interface for scripting, or for DBus.
>
> Thanks a lot for your answer. I'm used to getting ignored on this list
> most of the time. ;-)

No, not ignored. But sometimes people just don't have answers here. QML
is still quite new and it's so complex that few people truly understand
what's going on when a problem becomes very involved.

If you don't receive an answer, you should probably interpret that as "I
need to make my problem clearer".

> So, you mean similar to a PIMPL pattern, like having a backend QObject,
> that is created pairwise? Having two QObjects sounds quite heavy for a
> simple QML item. And also the "proxy" Object would have to instantiate
> the backend Object, not the other way around, since it is directly
> instantiated by the QML engine. So it seems a bit weird to me.

But it is the only way to truly control what is exposed. We had the same
problems, questions and answers years ago with QtScript.

It's so rare that you really need to control it, that you have to use a
facade pattern or proxy object for it. It doesn't make any sense to try
and add something like "Q_INVOKABLE NON_QML_EXPORTABLE" for those few cases.

>> I would not recommend making slots private just to hide them from QML.
>> While you can still connect to those slots from within that class, you
>> can no longer connect to it from outside the class itself. That may hurt
>> the API of that class.
>
> Huh? I can perfectly connect to private slots from outside the class. I
> just tested it to be sure.

Just because it works doesn't mean it's a good idea. Slots can be called
as any other methods, so making it private has different meanings too.
Use public, private and protected as you would in a non-Qt C++ class and
live with the QML exposure.

Personally, I've never accepted that you can connect to private slots
from other objects, but that's a different (and not worth having again)
discussion.

Bo Thorsen,
Fionia Software.

--

Expert Qt and C++ developer for hire
Contact me if you need expert Qt help
http://www.fioniasoftware.dk

Sven Anderson

unread,
Mar 14, 2012, 9:50:41 AM3/14/12
to qt-...@qt.nokia.com
Hi Bo,

On 13.03.2012 16:11, Bo Thorsen wrote:
>> Thanks a lot for your answer. I'm used to getting ignored on this list
>> most of the time. ;-)
>
> No, not ignored. But sometimes people just don't have answers here. QML
> is still quite new and it's so complex that few people truly understand
> what's going on when a problem becomes very involved.

Sure, I was not really serious here as the smiley indicates. I fully
understand that it's my subjective perception when I have the impression
that I hardly get any reaction (even when I answer questions) while
others get reactions immediately. But I think it's a fact, that the
responsiveness of the QML community is a lot lower than that of the
general Qt community, which makes it sometimes hard to find solutions. I
always thought, Qt Quick is a hot topic and very popular. So, maybe we
can improve the interaction somehow? Someone on #qt-qml even believed,
that this list doesn't exist anymore and suggested moving it to
lists.qt-project.org.

> It's so rare that you really need to control it, that you have to use a
> facade pattern or proxy object for it. It doesn't make any sense to try
> and add something like "Q_INVOKABLE NON_QML_EXPORTABLE" for those few cases.

Is it really so rare to have QML and non-QML slots in one QObject? I
thought it's even the normal case? Or do you mean it's rare, that the
exposure of the non-QML slots is not acceptable?

> Just because it works doesn't mean it's a good idea. Slots can be called
> as any other methods, so making it private has different meanings too.
> Use public, private and protected as you would in a non-Qt C++ class and
> live with the QML exposure.
>
> Personally, I've never accepted that you can connect to private slots
> from other objects, but that's a different (and not worth having again)
> discussion.

The problem is, that the semantics of the access modifiers are only
clear for the case of the direct call (pure C++), as you can see at the
confusion. As soon as you bound these semantics to other call systems
(metobject calls, calls from JS, ...) you run into problems, where you
don't want the same access rights for all call systems. To solve this in
a clean way you would have to introduce access keywords for each system,
like Q_PRIVATE, Q_PUBLIC regarding QMetaObject::invoke() and Q_JS_EXPORT
for JS/QS/QML calls. That way I could avoid a slot to be called directly
by declaring it 'private Q_PUBLIC' (behavior at the moment), or have a
real private slot with 'private Q_PRIVATE'. But probably that would be
over-engineered.

Cheers,

Sven

Sven Anderson

unread,
Mar 14, 2012, 2:24:48 PM3/14/12
to Bo Thorsen, qt-...@qt.nokia.com
Hi Bo,

On 14.03.2012 17:50, Bo Thorsen wrote:
> You have to split this discussion, though. For a library package, it
> could very well be that you have to keep a clean interface. If something
> is available in a Qt class, you can be absolutely sure someone like me
> will find a hack that needs to use it :) But in other cases, it's
> usually not a problem.

in my case it's a device (VoIP Phone) for which we also want to offer
our customers to build their own GUI in QML, and therefore the API to
the device is somehow public. So it's a thing somewhere between a
library and an internal interface. But there is not only the problem
that it's possible to call all slots from QML. The problem why I came to
this topic is, that I want to automatically create a qmltypes file and
documentation for the API, so if I can't mark the internal slots
somehow, they will appear in the qmltypes file and documentation and I
would have to remove them afterwards.


Best regards,

Sven

________________________________

* Join our Partner program: http://www.snom.com/partner<http://www.snom.com/partners>
* Subscribe to our snom support RSS Feed<http://wiki.snom.com/wiki/index.php?title=RSS&action=feed&feed=rss> and get first-hand technical news about snom products, e.g. Firmware updates, FAQ updates, troubleshooting hints, etc.

Follow us on Facebook<http://www.facebook.com/snom.VoIP.phones>, Twitter<http://twitter.com/snom>, YouTube<http://www.youtube.com/user/snomvoip>, Linkedin<http://www.linkedin.com/groups?gid=1773766>


Sitz/Domicile: Charlottenstr. 68-71, 10117 Berlin, Germany
Handelsregistereintrag/Register of Corporations entry: Berlin-Charlottenburg HRB 61842 B
Vorstand/Executive Board: Dr. Christian Stredicke, Dr. Michael Knieling, Alexander Khan
Vorsitzender des Aufsichtsrates/Chairman of the Supervisory Board: Stefan Friese

snom technology AG<http://www.snom.com>

Reply all
Reply to author
Forward
0 new messages