[Development] QAction-like API for QML

Alan Alpert 416365416c at gmail.com
Fri Dec 14 20:06:59 CET 2012


On Thu, Dec 13, 2012 at 11:45 PM, Bache-Wiig Jens
<Jens.Bache-Wiig at digia.com> wrote:
> I have been lurking in the discussion a bit but I guess it is time for me to pitch in. It is hard to keep up with 10 different threads at once. :)
>
> I find the idea of adding a new QCoreAction base class that is shared between QML Action and QAction and only carries a small subset of properties an unnecessary layer of abstraction. The idea of QAction is to have the convenience of icons, text and shortcuts predefined for you in a shared location. If you remove most of those properties, you anyway have to redefine the shortcuts and icon every time you use them and quite frankly I see no added benefit of this core action class that I cannot cover by simply having a shared signal that my MenuItem connects to.

Me neither, but I was getting feedback from some guys that the
grouping and enablement logic alone can get pretty hairy for some
apps.

> What I would propose is that we keep the QAction exactly as it is and make it possible to use it from QML as well as introduce a new slightly simplified QML Action component as previously suggested. The only drawback to this approach is that actions you declare in QML won't be immediately usable from C++, but I don't see this as a big issue. You will either keep everything in QML or have your business logic including your QActions defined in in C++.

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).

> The previously proposed menu API looked something like this:
>
> Menu {
>     Action {}
>     Action {}
> }
>
> This is not a good idea and different from how actions are working with widgets.

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.

> We should not declare actions inline like this since it doesn't encourage sharing in QML, but rather declare them from a central location or from the C++ backend.

Actually it works both ways. While prototyping you write them inline
for convenience, when you need to share them you copy that text out
into a central type, and replace it with
Menu {
    actions: globalActionStore.actions
}

It may not explicitly encourage a global store, but for small apps it
doesn't matter, and large apps will probably have a central C++ store.
Medium apps can easily move to using a central store (or even have the
second menu/toolbar bind its actions to the actions property of the
first menu).

>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, or if your globally defined shortcut does not work in the current context. It also happens to be exactly what we do for widgets. :)
>
> Action { id: fileAction … }
>
> Menu {
>     MenuItem { action: fileAction }
>     MenuSeparator { }
>     MenuItem { action: backend.someAction }
> }
>
> The added benefit of this approach is that we can transparently make it work for C++ action as well. I will simply ignore the properties that are not used, and I could even make an image provider plugin that makes QIcon readable from qml.

We could make it transparently work with the Action in Menu approach
as well. Menu's default property could accept Action, MenuItem or
MenuSeparator children (or even Menu/ActionGroup, however you want to
do sub-menus).

--
Alan Alpert



More information about the Development mailing list