How to dynamically enable/disable menu actions on-demand

Andreas Pakulat apaku at gmx.de
Thu Apr 2 20:04:55 UTC 2009


On 02.04.09 16:38:15, David Nolden wrote:
> Am Donnerstag 02 April 2009 15:53:08 schrieb Andreas Pakulat:
> > The usual way to do this (apart from the state stuff above) is by
> > enabling/disabling the action whenever the state of the IDE changes, i.e.
> > if a file is opened check wether its part of any project. If not enable the
> > action, else disable it. Then also check for closing documents. All that in
> > the plugin where the action is provided.
> Yeah but I need this for at least 5 different places already, and the checks 
> that would need to be done permanently are quite complex. For example the 
> "Open project for current file" action would need to be updated when:
> - A project was opened
> - A project was closed
> - A different file was activated

Thats all pretty easy to get at.
 
> And it's even worse for actions that do stuff based on the item currently 
> under the cursor.

Why?

> That would extremely uglify the code, and also lead to a lot of permanent 
> activity(updating the states), that would be needed only exactly once in the 
> moment the menu is shown.

Well, the problem with that is, you may end up showing that menu even if
the user doesn't care about the action or even the menu. There are quite
a lot of people out there I think that click on some menu to open it up
and then notice that its the wrong one, moving the mouse along to check
which is the right one. I'm doing that constantly if I'm not 100% sure
where an action is. If you update each time the menu is shown, then
you've got a _lot_ of ui blocking and showing menus will be incredibly
slow.

If updating the action each time the cursor moves, maybe that should be
done with a timer, so its only updated once the cursor has stopped for
at least a few msec (maybe even a second).

> > > If there is no such mechanism yet, I'm proposing we use something like
> > > this: Create a subclass of KAction, called KDevAction, that has a signal
> > > "showing(KAction*)", that should always be emitted when a menu containing
> > > the action is shown, and that can be used by the action owners to check
> > > the context, and enable/disable it.
> >
> > I don't like that at all, simply because we'd most probably end up with 2
> > or three such classes as we'd need it not just for KAction but possibly
> > also some of its subclasses.
> But it would save us from a lot of state-watching all over the code. I don't 
> even want to do that watching, because I already smell the bugs coming from 
> all the needed code and signal/slot connections.

Another alternative is to not do the watching and inform the user when
he triggers an action that is missing some information (selection etc).

If the problem is missing signal/slot connections when changing the api,
then my answer is two-fold:

- you do get a warning on stdout and its fairly easy to catch
- we can switch to a different observer pattern (java listener-way)
  which makes the connections more explicit and will cause compiler
  errors when changing the API

> Another option would be using some system similar to our context menu stuff, 
> where the actions also do their checks in the moment the menu is shown.

Its actually the plugin and the checks should be as fast as possible as
users don't like to wait. In this case its also pretty safe to assume
that the user does want to see the menu and not just clicked on the
wrong menubar entry.

> There's one problem with my proposal that comes into my mind: I'm not sure if 
> the shortcuts still work while the action is disabled. So I'm waiting for 
> better proposals. :)

There's also another: Any action in any menu can (IIRC) be moved to a
toolbar, which means you'll get into inconsistent state as then the
action will only be "shown" once.

Not to mention that actions actually have no clue that they're shown, so
its technically only possible by hacking KMenu and KToolBar (or at least
connecting to their aboutToShow signal if there is one).

Andreas

-- 
You have taken yourself too seriously.




More information about the KDevelop-devel mailing list