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