Extensible context menus

Jakob Petsovits jpetso at gmx.at
Mon Mar 10 12:19:15 UTC 2008

On Saturday, 8. March 2008, Andreas Pakulat wrote:
> Hi,
> the recent mail from David (thanks for kicking me) made me think again
> about how we currently provide extensible context menu.
> Currently each plugin can contribute by overriding a virtual method and
> then provide a name and list of actions, which results in a submenu
> entry in the context menu that has the given name as title.
> Now this works quite well for plugins that only need to be in "their
> own" group, however there are some plugins for which it makes a lot of
> sense to have multiple groups. One example is the project management
> view, this plugin should provide renaming/moving files in a project, as
> well as building and configuring a project. And the former actions are
> pretty much separate from the building and should be in a submenu like
> "refactor" as thats really what it does.
> So I'm currently trying to think about how we get really extendable
> context menus, where a plugin can contribute to existing submenus as
> well as top-level menu items and its own new submenu.
> Something that came to my mind is having a small structure like:
> class ContextMenuContribution
> {
> public:
>   /** user visible string for the submenu */
>   QString subMennuName();
>   /** id to uniquely identify the submenu */
>   QString subMenuId();
>   /** list of actions to append to the submenu */
>   QList<QAction*> actions();
> };
> And then a plugin would simply return a list of such instances. We could
> either have an id of "ContextMenu" for adding the actions to the context
> menu, or use an empty id to do that.
> One problem I see with this is order of actions. Basically the order of
> the actions might change after each start of kdevelop, as other plugins
> might get loaded that might contribute to an already populated menu.
> Ideas how to solve that?

The classic Drupal influenced mindset's approach: weights.

class ContextMenuContribution
   virtual int subMenuWeight() { return 0; }

Then sort all menus by weight (for example, -20 as first sub-menu, 0 as second 
one, 17 as third one) and you've got a persistent order - assuming that 
plugins try to keep their weights reasonable in comparison to other modules.

If a ContextMenuContribution is supposed to be used in multiple contexts, that 
context (QString uniqueContextIdentifier?) would probably need to be passed 
as parameter for the weight method.

More information about the KDevelop-devel mailing list