[Development] QAction-like API for QML

Stephen Kelly stephen.kelly at kdab.com
Tue Dec 18 12:55:50 CET 2012

On Thursday, December 13, 2012 13:18:35 you wrote:
> On Thu, Dec 13, 2012 at 8:18 AM, Stephen Kelly <stephen.kelly at kdab.com> 
> > The reason for the split is not clear to me. Do you suggest that UIAction
> > would be a QML element, not a creatable C++ class? Do you suggest that
> > CoreAction would be a creatable C++ class? Why does it not have a text?
> The split is because there is a need for a usable element in two
> separate worlds, widget-land and QML-topia. 

I know you like QML, but this kind of thing is just distracting. It reads as 
if you don't care at all about getting the API right for people who don't 
create QML only applications. I know you don't think that as you have said so, 
but that's how it reads.

> The details of the split
> was just following Andre's suggestion. text/secondaryText might fit
> into CoreAction, icon will not.

Why not? Because QML doesn't do QIcons? The reason for that is not clear 
either to me.

> There is a concrete need for an Action like class which you can
> create, manage and use in QML to implement your QML menus and toolbars
> for desktop, mobile and cross-platform UIs. 

There is a need to use them certainly. I'm not certain what you mean by 
manage. I think creating them in QML is useful enough to be done, but as any 
useful QML application has a c++ part where they can also be created, it's not 
as big a need as the need to use them.

> There is an existing need
> for a QAction because it's used in QWidget UIs. These cannot be the
> same class for already explained reasons.

The reasons already explained are quite fuzzy. To be specific, the reason is 
that QAction has these APIs, right? :

 - QList<QGraphicsWidget *> associatedGraphicsWidgets () const
 - QList<QWidget *> associatedWidgets () const
 - QMenu * menu () const
 - QWidget * parentWidget () const
 - void setMenu ( QMenu * menu )
 - bool showStatusText ( QWidget * widget = 0 )

Those are not necessarily 'always used, primary' APIs required for 'an Action 
API which can be used from both C++ and QML'.

> There is no concrete need
> for the CoreAction type, we're just considering it now because it
> might prove a useful abstraction to bridge the gap. If it is a useful
> abstraction to bridge gaps, then it makes sense to make it a usable
> C++ class so that other separate worlds can also interact easily.

Interact and have a common codebase etc, yes.

> The QML Action class would be a QML type, and not exposed C++ API.
> This is to add flexibility, in case we need to add or remove a
> QGuiAction subclass later.

If we get it right, we won't need to add other classes in the inheritance 
heirarchy later. Most of Qt is written in C++ where that need is present, so 
we have a lot of experience with getting it right. 

I don't think this is a good reason to make the API QML only.

> If you'll accept this, then we could
> actually focus on the QML API now and deal with the C++/QAction
> integration later (although perhaps it will still help to think about
> it now).

Yes, I think it still helps to think about it now.

> >> CoreAction may not even need a QML API. QML users either implicitly
> >> use one through UIAction, or explicitly use one from C++.
> > 
> > I think the goal should be not to have such a split at all.
> > 
> > Presumably you suggest that UIAction is not a visible element, but its
> > properties need to be bound to Text {} elsewhere?
> > 
> > Rectangle {
> > 
> >   UIAction {
> >   
> >     id : uiAction
> >     action : _cpp_exported_action
> >   
> >   }
> >   Text {
> >   
> >     text : uiAction.text
> >   
> >   }
> >   MouseArea {
> >   
> >     onClicked : uiAction.trigger()
> >   
> >   }
> > 
> > }
> > 
> > Why not just this:
> > 
> > Rectangle {
> > 
> > property QtObject action :
> > _cpp_exported_action_manager.get("_cpp_exported_action")
> > 
> >   Text {
> >   
> >     text : action.text
> >   
> >   }
> >   MouseArea {
> >   
> >     onClicked : action.trigger()
> >   
> >   }
> > 
> > }
> Because this isn't a realistic usecase for Actions.

I think it is. Especially in touch applications where menu bars and toolbars 
are not common (especially not in the 'desktop paradigm' sense).

> It's like hooking
> up a QAction to a QPushButton (a usecase I'm suprised doesn't have its
> own convenience API).

QPushButton is worlds apart from what QML provides and is used for. I think 
that the QML code I wrote above is equivalent to the C++ code:

 QAction *action = actionManager->getAction("_cpp_exported_action");
 QPushButton *button = new QPushButton;
 connect(button, SIGNAL(clicked()), SLOT(trigger()));

See also QToolButton. Such buttons can be made outside of toolbars, just like 
is more common on touch screens. Consider also the 'play' button on media 
players, which is often in a more prominent location than the toolbar 
(consider also Qt creator).

> The realistic usecase is to have a Menu or
> ToolBar control with a property list<Action> powering it. 

For touch applications, do you think that is still true? Or do you imagine a 
menubar and a toolbar which are very different to the ones we use on a 
desktop? Do you imagine them to come as standard components with a 
QtComponents library, or built into QtQuick itself?

> For example:
> MenuBar {
>     Action { text: "Quit"; onTriggered: Qt.quit(); }
>     Action { text: "Don't Quit"; onTriggered: Qt.quit(); }
> }

I think quit is unlikely to ever be simply connected to Qt.quit() in a real-
world application. There will need to be logic for example for checking 
unsaved open documents, finishing in-progress uploads of the email you're 
sending, possibly sending goodbye notifications on sockets etc etc. So 
realistically, you'll implement that quit action stuff in C++. You'll also not 
want to define the 'Quit' text and icon twice, have it translated twice, 
define the shortcut twice etc. 

I don't see any problem with making it possible to create an Action{} in QML 
as you did above, but you need to keep in mind that it doesn't solve all of or 
many of the important problems.

> Theoretically the Action type could just be part of the same controls
> module as MenuBar is. This mirrors widgets and QAction after all.

I don't think mirroring the widget and QAction API or their split is a good 
idea. That was designed when widget was the only possibility for creating UIs. 
Todays goals are to have ui concepts which are not tied to a particular ui 

> There's no problem with Action being a type you can create from C++ as
> well, leading to
> MenuBar {
>     actions: [
> _cpp_exported_action_manager.get("_cpp_exported_action1"),
> _cpp_exported_action_manager.get("_cpp_exported_action2") ]
> }
> But neither is there any benefit from that for the previous usecase.

Exactly - many use-cases need to be considered as first-class.

> >> Theoretically a new QAction could be written to use CoreAction
> >> internally too, and then a QAction and a UIAction could share the same
> >> CoreAction instance.
> > 
> > If CoreAction and UIAction are merged (as QGuiAction for example), then
> > QAction can the implemented in terms of that too.
> That is possible.
> >> Does this API solve the hybrid problems the previous one was having?
> > 
> > How does my counter proposal sound?
> How does it handle the imageSource or other future non-QAction
> properties?

QML was made to not allow use of images from C++ in Qt 4. The reason for that 
is unclear to me, but should be re-visited now in Qt 5.

> Are you suggesting that the QGuiAction would have all the
> properties the QML Action wants, and then some are ignored in the
> QAction implementation?

What would QML Action have that QAction would ignore?

> And then likewise, if you pass a bunch of
> QAction*s (assuming it subclasses QGuiAction) the Widget parts just
> get ignored?

QAction can't be made to subclass QGuiAction because of BC concerns.

Some of this came up before by the way, so it's another discussion to review 
when designing this:



Stephen Kelly <stephen.kelly at kdab.com> | Software Engineer
KDAB (Deutschland) GmbH & Co.KG, a KDAB Group Company
www.kdab.com || Germany +49-30-521325470 || Sweden (HQ) +46-563-540090
KDAB - Qt Experts - Platform-Independent Software Solutions
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 198 bytes
Desc: This is a digitally signed message part.
URL: <http://lists.qt-project.org/pipermail/development/attachments/20121218/cd3bd710/attachment.sig>

More information about the Development mailing list