How to dynamically enable/disable menu actions on-demand

Hamish Rodda rodda at kde.org
Fri Apr 3 10:22:43 UTC 2009


On Friday 03 April 2009 07:04:55 Andreas Pakulat wrote:
> 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).

I agree with Andreas, the system is only designed for keeping the 
enable/disable attribute current all the time, not just on menu show, unless 
the action is only ever meant for the menu.  The problem here is that if we 
only check on menu show, when you try to invoke the action via its shortcut, 
there cannot be a check to see if it should be enabled or not, it will only 
invoke if the action is enabled at the time the keypress is made.

So, we either keep the action enabled at all times, or we keep it up-to-date.

Cheers,
Hamish.




More information about the KDevelop-devel mailing list