[Development] QAction-like API for QML

Alan Alpert 416365416c at gmail.com
Tue Dec 11 18:10:27 CET 2012

On Mon, Dec 10, 2012 at 9:05 PM, Martin Jones
<martin.jones at qinetic.com.au> wrote:
> On Tue, Dec 11, 2012 at 1:39 PM, Alan Alpert <416365416c at gmail.com> wrote:
>> QAction served widgets well as an abstraction for an "Action" which is
>> exposed to the UI in a platform specific manner. This was shared
>> between menus and toolbars and some other things. I think we'll need
>> something similar for QML, so that the QtQuick controls can provide
>> platform styled menus, toolbars, and perhaps some other things. This
>> is particularly important for those working on the modern
>> cross-platform challenge of scaling to different devices - we need the
>> actions generic enough to fit a phone's itty bitty little menu as well
>> as the unifed menubar that spans over 2000px on today's Macs.
>> QAction can't be used straight, it's in the QtWidgets library (and has
>> QWidget* in the public API - it's not moving), so we need a new API
>> for this. Ideally though it would be fairly similar to allow for
>> developers to easily move to it, maybe to make it easier to integrate
>> the two better later. There was a discussion at Dev Days, here's what
>> we came up with initially. Note that I'm using QML to prototype the
>> API ;).
>> Action type:
>> QtObject {
>>     property string text
>>     property url imageSource
>>     property string shortcut
>>     property bool checkable: false
>>     property bool checked: false
>>     signal triggered(bool checked)
>> }
> Where are you proposing this goes?  To me it looks like a candidate
> for Qt Components (or is it Controls now).

QtQuickControls would implement the menus, toolbars, etc. using an
Action API. I think the API itself needs to be a bit lower level,
because it's supposed to be a gui-related primitive that all component
sets could use in their implementation. If there ends up being no Gui
dependencies it could go in QtQml, but that's unlikely due to the
shortcut support so it would more likely go in QtQuick (in both cases
a submodule, like QtQuick.GuiEnablers but with a better name).

> [snip]
>> In addition to the API review of that prototype, the following
>> questions that come to mind:
>> ActionGroup could be dropped in favor of adding a subactions property
>> to Action. But Aaron brought up a good point that this makes it a lot
>> more discoverable how to implement nested menus/actions. Is it worth
>> it to split up Action/ActionGroup?
> I don't like the idea of subactions.  Nested menus are the only case I
> can think of that uses it, but its always there in the API.
>> Given that that UIs from the '90s can be implemented with widgets
>> still, are exclusive and checkable used by modern UIs? i.e. Is it
>> worth putting them in a new API?
> Probably not very common in menus now, but an action is also useful
> for checkboxes and they are quite checkable.

Okay, you've convinced me for leaving in checkable.

>> The QMenu API allows for adding menu separators too, but I haven't
>> seen those in apps for a while. Is it worth adding another type or
>> flag to integrate separators into the Action API?
> A separator needs none of the API present in an Action.  They are unrelated.

The related part was that you'd ideally want to express them in the
same list, e.g.

Menu {
    actions: [ActionGroup { a1, a2, a3 }
    ,Separator {}

But for menus supporting that they could just use a more generic type
for their actions list. It doesn't actually have to be an Action
itself. I'm now inclined to leave separators wholly up to the menu
implementation itself, perhaps they could just generate them
heuristically like Samuel suggested.

>> In that example all the ActionGroups set collapsible to true, but that
>> could just be because that's the functionality the example is
>> demonstrating. ActionGroups can also be used for grouping actions and
>> in that case you may not want collapsible. Should collapsible be true
>> by default?
> "collapsible" is another property which seems to be quite tied to a
> menu's implementation.  What is the overall goal of these types?  Are
> they to be added somewhere quite core, e.g. QtQuick, or are they to be
> added to Components?

Collapsible is not tied too tightly to a menu's implementation. It's
just supposed to be a hint that for some implementations (like menus)
these can be folded into one entry on the UI. This could theoretically
be used by future UI elements, like a toolbar which progressively
collapses groups to adapt to varying form factors or orientations.

The goal of these types is to be a shared utility type across all
component sets, so it would have to be somewhere quite core. It's also
currently the only way to implement application global shortcuts. The
need for a shared utility type is so that you can take your core UI
logic (actions are a large chunk of that) and feed it into varying
platform component sets or custom components with ease. Defining all
of your actions into one list, you could pass that to a
QtQuickControls.Menu on desktop, or a PlatformComponents.Menu on
another platform, or provide your own visualization in a custom look
and feel. Just like QtWidgets you might even use it multiple times in
the one application; e.g. use the list of actions on a Menu, a
Toolbar, and a custom UI widget to provide constant easy access to all
UI actions.

Alan Alpert

More information about the Development mailing list