[Development] QAction-like API for QML

André Somers andre at familiesomers.nl
Thu Dec 20 11:43:11 CET 2012


Op 20-12-2012 11:10, Bache-Wiig Jens schreef:
>>> 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.
>> Well, I disagree with that view of what an action represents. To me, the
>> core of an action really is bundling a bit of state with a trigger for
>> something to happen (I try to avoid the word 'action' here) in a
>> convenient API. That piece of state includes at minimum if that action
>> is available right now, and can also contain a value ('checked' is the
>> value that QAction can currently carry, so basically a boolean). That by
>> itself is already a very useful thing to have, as it provides a very
>> nice and clean way to expose functions on an API, especially for code in
>> a core layer of the application.
> Action has clear semantics in Qt. It is a GUI concept to describe properties that belong in a specific implementation of a UI. What you are proposing should not be called CoreAction as it has nothing todo with QAction. You are proposing a new concept to Qt. I still find it redundant since it is trivial to implement yourself,  but if your backend needs a signal that can be disabled I would suggest that we introduce it as a different class called QTrigger and keep it outside of this discussion.
>
> If you have doubts that Action is a GUI concept, take a  look at the properties:
> autoRepeat, checkable, checked, enabled, font, icon, iconText, iconVisibleInMenu, menuRole, priority, shortcut, shortcutContext, softKeyRole, statusTip, text, toolTip, visible, whatsThis. How many of those belong in a backend? How many can you reuse in both mobile and desktop UI's?
Right. So, because of the way QAction is implemented (tightly bound to 
QtWidgets), you conclude that it is a GUI concept. Why not conclude it 
is a QtWidgets concept then, and from that, conclude that is has no role 
in QML? That's just as silly.

Of course none of the GUI properties it carries belong in a backend. Did 
you even look at the quick draft I posted? Did it contain *any* of those 
properties? Call it what you want. If you call it QTrigger instead of 
QCoreAction, fine. I don't care. The point says the same: it can and 
should (IMnsHO) the core can common base of QAction and a QML equivalent.
>> You claim that you'd have to "redefine" the shortcuts and other GUI
>> related properties every time you use the (core) action. Why so? Your
>> GUI layer can simply get these core actions and re-expose them once,
>> right? At the moment, you frequently see methods that are responsible
>> for creating all the actions in the application. You'd have the same,
>> only instead of having to manage multiple connections to keep track of
>> state in the core and the action that represents that, you set a
>> coreAction on the action and have that part taken care of. Then, you set
>> the QAction you created on your toolbar, your menu and whatever else you
>> fancy.
> So you redeclare your Actions in your fronted and somehow associate them with CoreAction?
Yes.
> QGuiAction openAction(Core::openCoreAction):
> openAction.setShortcut();
> openAction.setIcon()
> openAction.setToolTip, setEtc…
>
> Again, I gain nothing from this apart from having to declare all my actions twice. Though if the concept is worth implementing we can alway add a setTrigger function to QGuiAction in the future.
No, you do *not* declare all your actions twice. Why would you think so? 
You are just _able_ to split the declaration of the core stuff of the 
action (trigger, if you prefer) in another place, application layer or 
library than the GUI representation of it. If you don't want that, you 
don't have to.

If you are talking about it being different for QML and QtWidgets, and 
having to re-declare this stuff for both gui types: that is true. The 
GUI is likely to be different as well, including having different icons, 
so what's the point?

Or are you just complaining about the legacy case, where a user might 
have existing, already completely defined QActions, and the user wants 
to expose these to QML, and then has to re-declare the GUI-parts of it? 
There, you might have a point. Could be easy to fix for the most part in 
the implementation though, I think. For instance, one could use a tactic 
where if a QAction is declared not using a QCoreAction/QTrigger, QAction 
just sets as many of the other properties as possible on the 
QCoreAction/QTrigger (perhaps using a set of dynamic properties), and 
QGuiAction just sees what it can use from these. That could make most 
data available transparently (thus easing using legacy), without binding 
the class to the GUI lib.

>
>> The benefit is in the way that you bundle the relevant bit of state, a
>> handle to an action and a value into one convenient abstraction. Instead
>> of having to expose and connect to these separately to keep your GUI
>> consistent with application state, you only need to reference a single
>> object. And that single object can be used both in the widget world as
>> well as in the QML world. At the same time, if you like.
>>> 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++.
>> As mentioned by others, this would mean that any C++ core that you write
>> would *have* to pull in QtWidgets in order to be able to use actions.
>> Even if you only have a QML gui. Not very attractive, if you ask me.
> No it does not. QtWidgets is in a separate library. We will put the new C++ class in QtGui and expose it to QtQuick. This would then be just as available to widgets as it is in QtQuick. But I am not a sure how much effort we should use to make it usable in widgets. I would like it to be optimised for QtQuick. QAction already works great for widgets. Making QQuick also support QAction seems more important to existing users.
>
Ah, so you want to end up with a one-way compatibility again. QML can 
use stuff from the Qt/C++/Widgets world, but the other way around is not 
important. Good to know that the claim that "QtWidgets is and remains a 
first-class citizen" is being upheld so nicely.

André




More information about the Development mailing list