[Solved] Disable the exit button with the C++ SDK

Java, C++, C#, Delphi... - Using the UNO bridges
Post Reply
dom19191
Posts: 6
Joined: Sat Apr 08, 2023 12:45 am

[Solved] Disable the exit button with the C++ SDK

Post by dom19191 »

Hi !

There is a way to disable the exit button with the C++ SDK when LibreOffice 7.5.2 is embebed in QT.

------------------------------

Reference< XComponentContext > xContext( ::cppu::bootstrap() );
Reference< XMultiComponentFactory > xServiceManager(xContext->getServiceManager() );
Reference<XDesktop2> xDesktop = Desktop::create(xContext);
Reference<XComponentLoader> xComponentLoader(xDesktop, UNO_QUERY);
Sequence<PropertyValue> loadProps;
Reference<XComponent> xComponent = xComponentLoader->loadComponentFromURL("private:factory/scalc", start_document, 0, loadProps);
Reference<XModel> xModel(xComponent, UNO_QUERY);
Reference<XFrame> xFrame = xModel->getCurrentController()->getFrame();
Reference<XWindow> xWindow = xFrame->getContainerWindow();

Reference<XSystemDependentWindowPeer> xWindowPeer;
css::uno::Any windowPeer = xWindow->queryInterface(XSystemDependentWindowPeer::static_type());
windowPeer >>= xWindowPeer;

-->> xComponent ? disable exit button ?

------------------------------

Thank you
Attachments
disable_button.png
disable_button.png (65.65 KiB) Viewed 7383 times
Last edited by Hagar Delest on Thu Apr 13, 2023 7:54 am, edited 1 time in total.
Reason: tagged solved.
LibreOffice 7.5.2 WINDOWS
JeJe
Volunteer
Posts: 2923
Joined: Wed Mar 09, 2016 2:40 pm

Re: Disable the exit button with the C++ SDK

Post by JeJe »

You can disable menu items, remove them, hide them, via the frame's layoutmanager. Look for the element with the ResourceURL "private:resource/menubar/menubar" (in OO - I presume it will be the same URL in LO)
Windows 10, Openoffice 4.1.11, LibreOffice 7.4.0.3 (x64)
dom19191
Posts: 6
Joined: Sat Apr 08, 2023 12:45 am

Re: Disable the exit button with the C++ SDK

Post by dom19191 »

Thank you, JeJe, for your prompt response.

I have tried multiple methods, but in the end, either the object used to set the property is null or the property is not being considered.

Do you have any ideas about the object path I need to take and how to set the property? Any suggestions you could offer?
LibreOffice 7.5.2 WINDOWS
JeJe
Volunteer
Posts: 2923
Joined: Wed Mar 09, 2016 2:40 pm

Re: Disable the exit button with the C++ SDK

Post by JeJe »

I don't know C++. All I can do is tell you how to access that menu item in the frame using Basic (for all frames a different route is needed). You'll need to replace that item with one with the disabled property value and update settings which isn't done below.

Code: Select all

els=thiscomponent.currentcontroller.frame.layoutmanager.elements
for i = 0 to ubound(els)
if right(els(i).resourceurl,7) = "menubar" then
sets = els(i).getsettings(true)
menuitems= sets.getbyindex(0)(2).value
mri menuitems
for j=0 to  menuitems.count -1
itm = menuitems.getbyindex(j)
for k = 0 to ubound(itm)
if itm(k).name = "CommandURL" then 
if itm(k).value = ".uno:Quit" then 
mri itm(k)
exit sub
end if
end if
next
next
end if
next
You can use MRI to see what code it produces for the objects for C++
eg MRI thiscomponent followed by clicking on currentcontroller frame and layout manager produces.

Code: Select all

#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/frame/XController.hpp>
#include <com/sun/star/frame/XFrame.hpp>
#include <com/sun/star/frame/XLayoutManager.hpp>
#include <com/sun/star/uno/XComponentContext.hpp>
#include <com/sun/star/uno/XInterface.hpp>

using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::frame;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::uno;
using namespace ::rtl;

void snippet(const Reference< XComponentContext > &xContext, const Reference< XInterface > &oInitialTarget)
{
    try
    {
        Reference< XController > xController = oInitialTarget->getCurrentController();
        
        Reference< XFrame > xFrame = xController->getFrame();
        
        Reference< XPropertySet > xPropSet(xFrame, UNO_QUERY);
        XLayoutManager xLayoutManager;
        xPropSet->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("LayoutManager"))) >>= xLayoutManager;
        
    }
    catch (WrappedTargetException &e)
    {
        // getPropertyValue
        //printf(OUStringToOString(e.Message, RTL_TEXTENCODING_ASCII_US).getStr());
    }
    catch (UnknownPropertyException &e)
    {
        // getPropertyValue
        //printf(OUStringToOString(e.Message, RTL_TEXTENCODING_ASCII_US).getStr());
    }
}

Edit: note the file menu is called Picklist and the index to get it may be different than the one I used. I've also used OO not LO - but it should be similar.
Windows 10, Openoffice 4.1.11, LibreOffice 7.4.0.3 (x64)
dom19191
Posts: 6
Joined: Sat Apr 08, 2023 12:45 am

Re: Disable the exit button with the C++ SDK

Post by dom19191 »

Thank you again JeJe...you will become my best friend!

Your comment was very helpful! MRI is a great tool and it has changed the way I understand the object path.

I think I have found exactly what I need, except that when I remove the exit button, the FileMenu looks disabled and the popup never appears.

I believe there are two possible reasons:

1) It seems that I made some changes to the interface and I need a specific refresh call.

2) Perhaps my cast is incorrect in this line? Reference<XPopupMenu> xFileMenu = xMenuBar->getPopupMenu(menu_file_id);

Note: When I removed the "Window Menu" from the menuBar, everything looked good.
Note: I tried removing the exit button using the MRI interface and it worked!

Do you have any suggestions?

Code: Select all

Reference<XLayoutManager> xLayoutManager;
{
	Reference< XPropertySet > xPropSet(xFrame, UNO_QUERY);                
	xPropSet->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("LayoutManager"))) >>= xLayoutManager;
}

Sequence<Reference<XUIElement>> elements = xLayoutManager->getElements();

for (auto & e : elements)
{
	OUString url = e.get()->getResourceURL();

	if (url == "private:resource/menubar/menubar")
	{
		
		Reference<XMenuBar> xMenuBar;
		{
			Reference< XPropertySet > xPropSet(e, UNO_QUERY);                
			xPropSet->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("XMenuBar"))) >>= xMenuBar;
		}

		xMenuBar->removeItem(9,1); // Remove the Window Menu (10e) in the menubar (Working Good !)


		int xMenuBar_count = xMenuBar->getItemCount();

		::sal_Int16 menu_file_pos = 0; // First Position in the MenuBar
		::sal_Int16 menu_file_id = xMenuBar->getItemId(menu_file_pos);

		Reference<XPopupMenu> xFileMenu = xMenuBar->getPopupMenu(menu_file_id);

		::sal_Int16 action_exit_pos = 34; // 35e Exit Button in the FileMenu
		::sal_Int16 action_exit_pos_id = xFileMenu->getItemId(action_exit_pos);

		xFileMenu->removeItem(action_exit_pos, 1); // Error >> FileMenu look disable and the popup doens't work 

		// Need a refresh ?

		int error = 0;
	}
}
LibreOffice 7.5.2 WINDOWS
JeJe
Volunteer
Posts: 2923
Joined: Wed Mar 09, 2016 2:40 pm

Re: Disable the exit button with the C++ SDK

Post by JeJe »

Here's the full Basic code to remove that item, works for me in OO

Code: Select all

els=thiscomponent.currentcontroller.frame.layoutmanager.elements
for i = 0 to ubound(els)
if right(els(i).resourceurl,7) = "menubar" then
sets = els(i).getsettings(true)
menuitems= sets.getbyindex(0)(2).value
for j=0 to  menuitems.count -1
itm = menuitems.getbyindex(j)

for k = 0 to ubound(itm)
if itm(k).name = "CommandURL" then 
if itm(k).value = ".uno:Quit" then 
menuitems.removeByIndex(j)
els(i).setsettings(sets)
els(i).update
exit sub
end if
end if
next
next
end if
next
Windows 10, Openoffice 4.1.11, LibreOffice 7.4.0.3 (x64)
dom19191
Posts: 6
Joined: Sat Apr 08, 2023 12:45 am

Re: Disable the exit button with the C++ SDK

Post by dom19191 »

Thank you again again JeJe...

Working with the object's complexity, it will be a little more complicated in C++. However, everything is functioning properly! See below >>

Initially, my mistake was using a readonly interface, but I have now followed your last comment exactly.

Thank you, JeJe!

Code: Select all


Reference<XLayoutManager> xLayoutManager;
{
	Reference< XPropertySet > xPropSet(xFrame, UNO_QUERY);                
	xPropSet->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("LayoutManager"))) >>= xLayoutManager;
}

Sequence<Reference<XUIElement>> elements = xLayoutManager->getElements();

for (auto & xUIElement : elements)
{
	OUString url = xUIElement.get()->getResourceURL();

	if (url == "private:resource/menubar/menubar")
	{
		Reference<XUIElementSettings> xUIElementSettings(xUIElement, UNO_QUERY);
		if (xUIElementSettings.is())
		{
			Reference<XIndexAccess> xIndexAccess = xUIElementSettings->getSettings(true);

			int c =xIndexAccess->getCount();

			Sequence<PropertyValue> menuBarSequencePropertyValue;
			::css::uno::Any menuBarSequencePropertyValueAny = xIndexAccess->getByIndex(0);
			menuBarSequencePropertyValueAny >>= menuBarSequencePropertyValue;

			Reference<XIndexAccess> xIndexAccess_menuBar_item;
			::css::uno::Any xIndexAccess_menuBar_item_any = menuBarSequencePropertyValue[2].Value;
			xIndexAccess_menuBar_item_any >>= xIndexAccess_menuBar_item;

			// Access i=0 to the first Menu of the menu bar
			int i=0; //for (int i=0;i<xIndexAccess_menuBar_item->getCount();i++)
			{
				Sequence<PropertyValue> menuBarFileMenuSequencePropertyValue;
				::css::uno::Any menuBarfileMenuSequencePropertyValueAny = xIndexAccess->getByIndex(i); 
				menuBarfileMenuSequencePropertyValueAny >>= menuBarFileMenuSequencePropertyValue;

				Reference<XIndexAccess> xIndexAccess_action_item;
				::css::uno::Any action_items_any = menuBarFileMenuSequencePropertyValue[2].Value;
				action_items_any >>= xIndexAccess_action_item;

				int key_to_erase = -1;

				for(int j=0;j<xIndexAccess_action_item->getCount();j++)
				{
					Sequence<PropertyValue> action_item;
					::css::uno::Any action_item_any = xIndexAccess_action_item->getByIndex(j);
					action_item_any >>= action_item;

					for (int k = 0; k < action_item.getLength(); k++)
					{
						if (action_item[k].Name == "CommandURL")
						{
							::css::uno::Any value = action_item[k].Value;
							OUString data;
							value >>= data;
							if (data == ".uno:Quit")
							{
								key_to_erase = j;
								break;
							}
						}
						if (key_to_erase != -1){break;}
					}
				}

				if (key_to_erase != -1)
				{
					Reference<XIndexContainer> xReplace(xIndexAccess_action_item, UNO_QUERY);
					if (xReplace.is())
					{
						xReplace->removeByIndex(key_to_erase);
					}                                    

					xUIElementSettings->setSettings(xIndexAccess);
					xUIElementSettings->updateSettings();
				}                                
			}
		}                        
	}
}


LibreOffice 7.5.2 WINDOWS
dom19191
Posts: 6
Joined: Sat Apr 08, 2023 12:45 am

Re: Disable the exit button with the C++ SDK

Post by dom19191 »

For info only :

I found the refresh function to solve the previous readonly interface problem.
The solution is better and doesn't affect the other LibreOffice instances.

Code: Select all

Reference<XLayoutManager> xLayoutManager;
{
	Reference< XPropertySet > xPropSet(xFrame, UNO_QUERY);                
	xPropSet->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("LayoutManager"))) >>= xLayoutManager;
}

Sequence<Reference<XUIElement>> elements = xLayoutManager->getElements();

for (auto & e : elements)
{
	OUString url = e.get()->getResourceURL();

	if (url == "private:resource/menubar/menubar")
	{
		
		Reference<XMenuBar> xMenuBar;
		{
			Reference< XPropertySet > xPropSet(e, UNO_QUERY);                
			xPropSet->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("XMenuBar"))) >>= xMenuBar;
		}

		xMenuBar->removeItem(9,1); // Remove the Window Menu (10e) in the menubar (Working Good !)


		int xMenuBar_count = xMenuBar->getItemCount();

		::sal_Int16 menu_file_pos = 0; // First Position in the MenuBar
		::sal_Int16 menu_file_id = xMenuBar->getItemId(menu_file_pos);

		Reference<XPopupMenu> xFileMenu = xMenuBar->getPopupMenu(menu_file_id);

		::sal_Int16 action_exit_pos = 34; // 35e Exit Button in the FileMenu
		::sal_Int16 action_exit_pos_id = xFileMenu->getItemId(action_exit_pos);

		xFileMenu->removeItem(action_exit_pos, 1); // Error >> FileMenu look disable and the popup doens't work 

		// Need a refresh ? 
		
		xMenuBar->setPopupMenu(menu_file_id,xFileMenu); // Refresh the current menu
	}
}
LibreOffice 7.5.2 WINDOWS
Post Reply