The future of KAction
Simon Hausmann
hausmann at kde.org
Tue Nov 15 13:02:42 GMT 2005
On Friday 11 November 2005 20:06, David Faure wrote:
> On Friday 11 November 2005 07:38, Hamish Rodda wrote:
> > The other big change that I can see is that the plugging and unplugging
> > moves to be each widget's responsibility.
>
> That's the huge change, which I'm not too comfortable with.
> If you want a special action in a toolbar, like say a koffice-color-chooser
> toolbar button with popup, the solution was to inherit from KAction and
> reimplement plug. But if now the responsibility is in the widget, how do we
> do that? Subclassing QToolbar in an application sounds like the really
> wrong way to attack the problem, doesn't it?
>
> (Of course this example has other solutions, like a way to set a popup to a
> standard toolbar button, but there are many other cases of custom
> actions...)
The reason why we have KWidgetAction is because of the way the toolbars are
built, using xmlgui which only accepts xml and actions as input.
So we have KAction used for two different things:
1) Centralizing properties for user actions
2) As a way to pass a widget to a toolbar because the API for populating
doesn't permit specifying a widget directly anywhere.
The latter is strange if you think about it, it's not using any of the
properties of an action. You don't get an activated signal, it doesn't use
the text(), icon() or toolTip() property. It's essentially not an action in
the original sense of it.
Now I agree that requiring subclassing of QToolBar is the wrong solution,
especially given that QToolBar has a addWidget() method.
A much better solution IMHO is to provide a better API for populating the
menus and toolbars, an API that also allows specifying actions and widgets
but still provides features like place holders which plugins can populate
with their actions for example.
Here's an example of a quite stateful API that I have in mind (with
improvements thanks to a discussion with Benjamin):
GuiEditor editor(this);
editor.startMenuBar();
editor.startMenu("file", "&File");
editor.addAction(newDocumentAction);
editor.addAction(fileOpenAction);
editor.addSeparator();
editor.startMenu("printTo", "&Print To");
editor.addActions(KPrinter::printToActions());
editor.menuFinished();
editor.addSeparator();
editor.addAction(quitAction);
editor.menuFinished();
...
editor.startMenu("settings", "&Settings");
...
editor.addActionGroup("plugin settings");
...
editor.menuFinished();
...
editor.menuFinished();
editor.startToolBar();
editor.addAction(newDocumentAction);
editor.addSeparator();
editor.addWidget(searchComboBox);
editor.show();
For a plugin the concept of providing a actions and its desired locations in
menus and toolbars is very similar to painting: Called on-demand it can be
asked to describe what it would like. Hence the idea of plugins implementing
a simple interface that consists of a method looking similar to a paintEvent:
void Plugin::buildGui()
{
GuiEditor editor(this);
editor.startMenuBar();
// .. in case the application doesn't want us to populate
// the settings menu or doesn't provide one in the first place
if (editor.tryToEditMenu("settings")) {
editor.addActionToGroup("plugin settings", mySettingsAction);
}
....
editor.menuFinished();
editor.startToolBar("plugin toolbar");
editor.addAction(...);
editor.addWidget(...);
editor.toolBarFinished();
}
How does that look?
Simon
More information about the kde-core-devel
mailing list