[Development] QAction-like API for QML

Bache-Wiig Jens Jens.Bache-Wiig at digia.com
Sun Dec 16 15:32:33 CET 2012


> Having a common base class was something I thought of last summer or
> so.  I still think maybe it can work.  But we won't get the benefit of
> it unless we change the QWidget menu system to take the base class
> pointers, and deal with them polymorphically; or deprecate the old
> QAction and have the widget menus also take the new class.  Then it
> would be possible to create one kind of actions which can be used to
> build both declarative-based and widget-based UIs.  If nobody thinks
> that will ever be useful, then we might as well just have an
> independent action class which is only for use in declarative UIs.

I did not say the idea was not useful. My point was that it is not required since we already have access to everything the common base class would give you. Action is a QObject, so when we expose it to QML, we can already access text, toolTip, statusTip, triggered and all of those core properties even without sharing the implementation. The only issue we have is when we try to make direct use of unknown data types like QIcon, or QKeySequence. Since these are anyway not going to be part of CoreAction, there was really no added benefit. Of course we would need a shared implementation to support QML-declared actions directly in C++ widgets, but this would essentially be like writing a QML backend to a C++ application, which I don't see as a realistic use case.

> I like the idea but I'm not sure it's possible.  QIcon would have to
> come along for the ride, for one thing.  (But we will need some
> mechanism like that in declarative anyway.)  Last time I tried to
> trace the dependency chain, I think it turned out there were some
> inescapable dependencies on QWidget stuff which we cannot break
> without changing the API (not to mention binary compatibility).

> 
>> Problem: QAction is in QtWidgets. Either we have to somehow move it
>> out, or this new Action class goes in a plugin which depends on
>> QtWidgets (a dependency we generally like to avoid). This is the
>> primary advantage of the QGuiAction approach - it can go in QtGui.
>> It's not like a QtWidgetEnablers import in QML would be terrible, it's
>> just that it increases the weight of other modules using it (very
>> undesirable for embedded).

What is so terrible about it? QtWidgetEnables would be private API, only used by components internally and we would not need to load the module on embedded, or am I missing something? 

Worst case scenario is anyway that we simply do not support QIcon and QKeySequence but we will still have all the benefits of coreAction.

>> Actually I was under the impression we wanted to do something better
>> (ergo, different) to widgets. The widget approach of grouping menus
>> separately from actions means that the common case is to fill the menu
>> with the actions in the exact same order you declared the actions.

But QAction and collapsible groups is not the right abstraction for this. First of all it means nothing in QToolBar. (what is a collapsed group or sub-menu doing there?)

When you want to re-use a menu, I would argue the appropriate abstraction would be to make a QMenu subclass using a subset of actions. An action group should not be assumed to be a menu since it can be used in any context.

Similarly in QML, I would create a Menu component and re-use that. When I use the same actions in a toolbar I would anyway have to re-order and handpick the ones that make sense in that context. An action by itsel should not care if it is used in a menu, toolbar or button.
> 
> But if you can end up with a very terse menu declaration in QML at the
> end, I think that's very worthwhile.
> 
> MenuBar { MyMenuGroup { } }

As I said I don't think ActionGroup is the correct abstraction. You are already treating it as if it was a menu. If it was, then you should be able to put it in a ToolBar as well. How meaningful is this:  ToolBar { MyMenuGroup{} }

I would prefer: MenuBar { EditMenu { } } where EditMenu is a carefully crafted Menu, built using a subset of actions.
> 
>>> By default all properties like text, shortcut and iconSource are taken from the action but can still be overridden when used in context. This makes the API more explicit (as well as readable) and also allow you to override for instance the iconSource if you have a smaller pixmap that is more suitable for menu use,
> 
> I don't think being able to override the iconSource is convenient
> enough, because this will be quite routine when building conventional
> desktop apps.  If icons are looked up by the action's name, then the
> image provider should be able to look up any size that a particular
> component wants.

Remember that the iconSource can use any image loader. I already did an icon-name loader in the qt4 branch to provide support for logical icon names such as iconSource: "image://desktopicon/edit-copy" }".

To ease up the syntax i also added an "iconName" convenience function to Button, ToolButton and MenuItem. I haven't yet added this in the qt5 branch yet as it still depends on widgets.

Jens




More information about the Development mailing list