Menus/toolbar management with Python/Basic

Hello,

I’m writing a big macro with Python on LibreOffice.

I found plenty of resources in this forum (and others too).

But I can’t find informations on menus/toolbar management with Python or Basic.
What I’m searching is how to enable/disable my own created menu, maybe LibreOffice standard menus. For example, I want to disable this menu when this condition is true, then after some actions on the document, the condition become false => the menu will be enable.

Can you please help me ?

Regards

OOO Development Tools (OooDev), also available as an extension, has the GUI class that handles Menus. Although there is not much for documention on it yet it is worth looking at to see if it might meet your needs.

Toolbar: If you make extension, then it is possible to use Complex Toolbar

Hello,

Your extension is very interesting.
I’ll use it (your code) because it’s great.

But that doesn’t answer to my first question : how to enable/disable dynamically menus as the user uses LO ?

With the next code we add a new menu.

import easymacro as app


def hello():
    app.msgbox('Hello World')
    return


def main():
    menu_name = 'zaz.my.menu'
    new_menu = {
        'Label': 'My Menu',
        'CommandURL': menu_name,
        'Submenu': [
            {
                'Label': 'Open Macros Dialog...',
                'CommandURL': 'MacroDialog',
            },
            {
                'Label': '-',
            },
            {
                'Label': 'My macro',
                'CommandURL': {'library': 'test', 'name': 'hello'},
            },
            {
                'Label': 'Execute macro...',
                'CommandURL': 'RunMacro',
                'ShortCut': 'Shift+Ctrl+Alt+E',
            },
        ]
    }

    app.menus['calc'].insert(new_menu)

    return

image

You can see how I do it in the next link:

Hello,

Thank you for your response.

I look in your code and it’s a very very good job…

I tried to use it, but it’s not very dynamic. I don’t know how to enable/disable menus as the context change.

Maybe LibreOffice don’t act like this.

For example, I click on menu “Connect”, then the menu “Disconnect” will be visible or activated, in the same LibreOffice document.

Is it possible ?

Regards

As the answers show: It is possible, but YOU as the programmer and the only person who knows the rules must provide the code to

  • deactivate “Connect” and activate “Disconnect” in the Macro called on Menu-button “Connect”
  • deactivate “Disconnect” and activate “Connect” in the Macro called on Menu-button “Disconnect”
  • check current state, when you create your menu and adapt setting.
  • maybe add code/notification routines at other places where you could Connect/Disconnect.

“The computer”/OS/LibreOffice will not read or understand your buttons, so will not know Connect/Disconnect are mutually exclusive.
.
An alternative would be “radio buttons” where only one state can be selected. This can be maintained by libre-office but the buttons can not update for example on lost connection unless you code it like this…

Hello,

Sorry I was in Holliday and after, too many work with my office. This project is a personal and secret project.
I agree with you : I have to manage the state enable/disable of the menu by code, as usual. But I can’t find a solution to disable a menu in my Python script. My Python project has more than 5500 lines (yes, I will parse this big script in multiple files), calls web services, have 20 dialogs with grids, use timers, etc… Everuthing works fine, I always find solutions when I had a pb. In my project, I’ve created menus, sub-menus and sub-menus of sub-menus. My script react normally when user clicks on it.
But now, I’m stuck because of the user interface => enable/disable menus.
My problem isn’t to understand that I’ve to manage enable/disable or visibilty of a menu but how to code that and, as other user interface, reacte when user does things.

I’m very sorry to bother you, but I need something like this:
if (a condition)
MyMenu01.enable = false
else
MyMenu01.enable = true
MyMenu02.enable = true

If I can code that, I think I’ll bother you with toolbar buttons. KamilLanda sended a very interesting extenstion. Many thanks to him.

Regards

The Menu service can be used to create and remove menus from the menubar of a LibreOffice document window. Each menu entry can be associated with a script or with a UNO command. This service provides the following capabilities:

Creation of menus with custom entries, checkboxes, radio buttons and separators.

Decoration of menu items with icons and tooltips.
1 Like

Hello,

Thank you for your response.

As I said upper, I’m seraching for something much dynamic.

Maybe it’s not possible.

Regards

One can disable commands dynamically as detailed in “Disabling commands”

Disabled commands are packed all together as a Registry key which one can update dynamically. You need to define enableCmds() and disableCmds() methods to achieve your requirements.

This Basic snippet disables the ‘About’ menu without recovering it:

Sub disableAboutCommand()
	disableCommand("About")
End Sub

Function disableCommand( cmd As String )
	Dim keyNode As Object ' com.sun.star.configuration.Configuration(Update)Access '
  	' Set the root path for our configuration access
    keyNode = Tools.Misc.GetRegistryKeyContent("org.openoffice.Office.Commands/Execute/Disabled", True)

	newCmd = keyNode.CreateInstanceWithArguments( Array() )		
	newCmd.setPropertyValue( "Command", cmd ) ' Add cmd to disabled command list 
	keyNode.insertByName( "Command-" & cmd, newCmd) ' name must be unique
	
	keyNode.commitChanges ' flush changes
End Function 

You can check disabled commands via Tools - Options - LibreOffice - Advanced - Open Expert Configuration. Beware your code gets error-proofed !!

Hello,
That is exactly what I was searching for. I just add this code :

' Set the root path for our configuration access
With GlobalScope.Basiclibraries
    If Not .IsLibraryLoaded("Tools") Then .LoadLibrary("Tools")
End With

and write enableCommand.

But when I execute disableCommand or enableCommand in LibreOffice 7.5.3.2, there is an error on this line :

keyNode.commitChanges() ’ flush changes

image

Then I click on OK button.
Menu About is still visible in LO. It disappears when I restart LibreOffice. It’s the same thing for the enableAboutCommand.

  1. Check for a superfluous ‘)’ sign in .InsertByName line …
  2. Remove ‘()’ parentheses in the faulty line

I corrected the snippet accordingly

PS: I intend to update the Wiki Disabling commands page with Basic and Python codes. Please be kind to share your remarks in this thread.

On my PC this causes the crash of the app.

Version: 7.5.7.1 (X86_64) / LibreOffice Community
Build ID: 50(Build:1)
CPU threads: 16; OS: Linux 6.5; UI render: default; VCL: gtk3
Locale: es-MX (en_US.UTF-8); UI: en-US
7.5.7-3
Calc: threaded

Even the the new code, I get the same error :
image

I’m working on Windows 10, OO is in french.

works in this context:
Version: 7.2.5.2 (x86) / LibreOffice Community
Build ID: 499f9727c189e6ef3471021d6132d4c694f357e5
CPU threads: 4; OS: Windows 10.0 Build 19045; UI render: Skia/Raster; VCL: win
Locale: fr-FR (fr_FR); UI: en-US
Calc: CL

.commitChanges() behaviour suffers from a regression …

NEW: Basic code example added to Disable Commands wiki page.

Disabling Commands.odt (12.7 KB)

strange.
Maybe I’m wrong but this code change:

image

to

image

Done this :
https://bugs.documentfoundation.org/show_bug.cgi?id=157915

Wiki: Python code example added to Disable Commands wiki page.

It operates fine in this context:
Version: 7.2.5.2 (x86) / LibreOffice Community
Build ID: 499f9727c189e6ef3471021d6132d4c694f357e5
CPU threads: 4; OS: Windows 10.0 Build 19045; UI render: Skia/Raster; VCL: win
Locale: fr-FR (fr_FR); UI: en-US
Calc: CL