Управление главным меню из макроса

Автор Narrnika, 28 декабря 2022, 15:12

0 Пользователи и 1 гость просматривают эту тему.

Narrnika

Подвесил запуск макросов в главное меню (через Настройки). И озадачился следующим вопросом: возможно ли теперь как-то повлиять на эти пункты меню из макроса? Например, в зависимости от контекста делать их активными/неактивными (это интересует в первую очередь), или сделать их флажками/радиокнопками?

Пока докопался до такой цепочки
ThisComponent.CurrentController.Frame.LayoutManager.getElements()(3).getRealInterface()
Дальше, вероятно, должно быть
.getMenuHandle(ProcessId, SystemType)
но тут я уже завяз.. в SystemType скорее всего пойдёт что-то вроде com.sun.star.lang.SystemDependent.SYSTEM_XWINDOW, а вот где брать ProcessId - ни как не разберу.

Пробовал посмотреть на эту ветку, но там вроде потрошат конфиг-файл, динамическое поведение через который вряд ли организуешь, максимум - подпись поменять можно будет.

Ах да, чуть не забыл:
Version: 7.4.3.2 / LibreOffice Community
Build ID: 1048a8393ae2eeec98dff31b5c133c5f1d08b890
CPU threads: 2; OS: Linux 5.15; UI render: default; VCL: gtk3
Locale: ru-RU (ru_RU.UTF-8); UI: ru-RU
Calc: threaded
Ubuntu 20.04 / LibreOffice 6.4.7.2 / OpenOffice 4.1.7

sokol92

Я бы предложил более привычный путь enableItem.
Владимир.

Narrnika

Цитата: sokol92 от 28 декабря 2022, 18:06более привычный путь enableItem.
Да я не против, собственно.. Вопрос только, куда этот enableItem приложить, чтоб заработало )
Т.е. - как получить ссылку на объект главного меню (не уровня диалога, а уровня приложения Calc). Там уже да, должно быть что-то вроде enableItem, setItemText и прочие потроха от XMenu. Наверное... Я на это сильно надеюсь.
Ubuntu 20.04 / LibreOffice 6.4.7.2 / OpenOffice 4.1.7

sokol92

Попробовал этот путь - не сработало. Ладно, есть запасные (прогулка часа на два)...  :)
Владимир.

sokol92

#4
Вот что получилось на скорую "ногу" (необходимо проверить). Дорожные карты взяты отсюда.
Option Explicit
Const MenuResource As String="private:resource/menubar/menubar"
Const DocType As String="com.sun.star.sheet.SpreadsheetDocument"

' В Calc отключаем первый пункт (индекс 0) пользовательского меню с индексом 11 (после "Справка").
Sub test()
  setItemEnabled 11, 0, False
End Sub

' Отключение/включение пунктов основного меню Calc.
' Параметры:
' PopupIx Индекс пункта главного меню (от 0)
' ItemIx  Индекс пункта вложенного меню (от 0)
' Enable  True - включить (отблокировать) пункт меню, False - выключить (заблокировать)
Sub setItemEnabled (Byval PopupIx As Long, _
                    Byval ItemIx  As  Long, _
                    Byval Enable  As Boolean)_
  Dim oCfgMng, Settings, ItemContainer, Item
  Dim Prop As New com.sun.star.beans.PropertyValue
  Dim i As Long, Exist As  Boolean
  oCfgMng=GetDefaultContext.getValueByName("/singletons/com.sun.star.ui.theModuleUIConfigurationManagerSupplier").getUIConfigurationManager(DocType)
  Settings = oCfgMng.getSettings(MenuResource, True)
  ItemContainer = getItemContainer (PopupIx, Settings)
  Item = ItemContainer.getByIndex (ItemIx)
  ' Ищем свойство Enabled
  For i = 0 TO uBound(Item)
    If Item(i).Name = "Enabled" Then
      Item(i).Value = Enable
      Exist = True
      Exit  For
    End If
  Next i   
       
  IF Not Exist Then
    ReDim Preserve  Item(uBound(Item) + 1)
    Prop.Name = "Enabled"
    Prop.Value = Enable
    Item(uBound(Item)) = Prop
  End If

  ItemContainer.replaceByIndex ItemIx, Item
  oCfgMng.replaceSettings MenuResource, Settings
End Sub

Function getItemContainer(ByVal PopupIndex As  Long, Byval Settings) As Object
  Dim Popup, i As Long
  Popup = Settings.getByIndex (PopupIndex)
  For i = 0 TO uBound (Popup)
    If Popup(i).Name = "ItemDescriptorContainer" Then
      getItemContainer = Popup(i).Value
      Exit Function
    End If
  Next i
End Function
Владимир.

Narrnika

Забористо, но...

во-первых, похоже, что в ?коллекцию? confManager.getSettings() не попадают пользовательские меню (только стандартные .uno:PickList ... .uno:HelpMenu);
во-вторых, ?свойство? "Enabled" ему до лампочки от слова совсем;
в-третьих, в текущем документе ему подобные изменения в принципе до лампочки, а вот созданный после них новый документ изменение "Label" таки подхватывает.. но только до тех пор, пока не перезапустишь LO - потом изменения слетают.

В любом случае - спасибо за наводку, тут есть ещё что пощупать, так что будем посмотреть.
Хоть и странно такие вещи через конфиг делать.
Ubuntu 20.04 / LibreOffice 6.4.7.2 / OpenOffice 4.1.7

mikekaganski

Цитата: sokol92 от 28 декабря 2022, 20:49oCfgMng=GetDefaultContext.getValueByName("/singletons/com.sun.star.ui.theModuleUIConfigurationManagerSupplier").getUIConfigurationManager(DocType)
Или немного проще:

oCfgMng=com.sun.star.ui.theModuleUIConfigurationManagerSupplier.get().getUIConfigurationManager(DocType)
С уважением,
Михаил Каганский

sokol92

#7
Цитата: Narrnika от 28 декабря 2022, 15:12Подвесил запуск макросов в главное меню (через Настройки).
Давайте проведем эксперимент вместе.
1. Записываем в любой модуль библиотеки Мои макросы / Standard макросы:
Sub Show1()
  Msgbox "Первый пункт меню"
End Sub

Sub Show2()
  Msgbox "Второй пункт меню"
End Sub

2. Создаем в Calc новое меню после пункта "Справка" (Сервис / Настройки / Меню / кнопка справа от элемента "Цель" / Добавить). В это меню добавляем два пункта, на которые назначаем макросы из пункта 1. Проверяем работоспособность этих пунктов меню. Перестартуем LibreOffice и еше раз проверяем работоспособность пунктов нового меню. Новое меню должно быть 12м по счету ("Файл" - 1, ..., "Справка" - 11).

3. Выполняем макрос Test из #4. В новом меню первый пункт должен быть выключен (disabled). Второй - работает.

4. Перестартуем LO. Оба пункта меню включены, поскольку мы не сохранили изменения, внесенные в пункте 3.

Проверял на системах Win10 LO 7.4.2.3, AstraLinux LO 7.3.6.2.

Владимир.

mikekaganski

Цитата: Narrnika от 28 декабря 2022, 22:47похоже, что в ?коллекцию? confManager.getSettings() не попадают пользовательские меню (только стандартные .uno:PickList ... .uno:HelpMenu)

Возможно, проблема в хранилище кастомизации меню. Синглетон theModuleUIConfigurationManagerSupplier предоставляет доступ к менеджерам компонентов. А если Вы сохраняете кастомизацию в документе, то Вам понадобится интерфейс XUIConfigurationManagerSupplier, реализуемый моделями документов - т.е. Вы можете выполнить

oCfgMng=thisComponent.getUIConfigurationManager()
С уважением,
Михаил Каганский

sokol92

Цитата: mikekaganski от 29 декабря 2022, 11:06Или немного проще:
Чтобы не писать "com.sun.star" я использую функцию:
' Возвращает ссылку на экземпляр сервиса или синглтон, имена которых начинаются на "com.sun.star.".
' Если параметр не начинается на "com.sun.star." ' то к нему слева добавляется "com.sun.star.".
' - ServiceName: имя сервиса или синглтона.
' Имя, которое начинается на "the" (регистронезависимо) интерпретируется как имя синглтона.
' При неудаче возвращается Nothing.
Function Service_Create(Byval ServiceName As String) As Object
  Const prf As String="com.sun.star."
  Dim arr
  Service_Create=Nothing
  If Left(lcase(ServiceName), len(prf))<>prf Then ServiceName=prf & ServiceName
 
  On Error GoTo errLabel
  arr=Split(ServiceName, ".")
  If Lcase(Left(arr(Ubound(arr)), 3))="the" Then
    Service_Create=GetDefaultContext.getValueByName("/singletons/" & ServiceName)
  Else
    Service_Create=CreateUnoService(ServiceName)
  End If 

ErrLabel:
End Function

Sub Test_Service_Create()
  Dim v
  v=Service_Create("ui.theModuleUIConfigurationManagerSupplier")
End Sub
Владимир.

Narrnika

Цитата: mikekaganski от 29 декабря 2022, 13:00Возможно, проблема в хранилище кастомизации меню.

Да, вы правы, после
oCfgMng=thisComponent.getUIConfigurationManager()стало повеселее. Состояние не сохраняется, но это и не требуется, всё равно его на изменение выделения подвешивать.

Сейчас ещё потестирую, а пока вынужден задать вопрос - у меня одного на LO-7.4.3.2 следующая проблема: в Настройки/Меню задаём область видимости на файл, в поле Цель создаём новое меню, закидываем в него любой пункт (макрос или команда LO), жмём Ок - всё, LO уходит в себя и не на что не реагирует, через пару минут предлагает закрыться или подождать ещё. Проверял для Calc/Writer/Impress. При этом AOO-4.1.12 и родной для системы LO-6.4.7.2 ведут себя нормально.
Пока это касалось только создания меню - меня это не сильно напрягало - создал в LO6, переоткрыл тот же файл в LO7 и всё, норм. Но теперь LO7 ещё и при попытке изменить состояние пункта меню завис, а в LO6 всё нормально сработало - сдаётся мне, эта та же проблема с другой стороны вылезла. Не пойму, то ли в 7-ой версии баг, то ли она у меня встала неудачно.
Ubuntu 20.04 / LibreOffice 6.4.7.2 / OpenOffice 4.1.7

Narrnika

Цитата: sokol92 от 29 декабря 2022, 12:35Давайте проведем эксперимент вместе.

Да, именно в такой конфигурации всё сходится. В смысле, результат такой же, как у вас.

Меня вчера сбило с толку то, что моё меню действительно записано в файл и через theModuleUIConfigurationManagerSupplier не отобразилось - из-за чего я начал пытаться прощупать хотя бы то, что есть - т.е. стандартные меню Calc'а, а на них скрипт почти никак не влияет.
Ubuntu 20.04 / LibreOffice 6.4.7.2 / OpenOffice 4.1.7

sokol92

Цитата: Narrnika от 29 декабря 2022, 16:59следующая проблема: в Настройки/Меню задаём область видимости на файл, в поле Цель создаём новое меню, закидываем в него любой пункт (макрос или команда LO), жмём Ок - всё, LO уходит в себя и не на что не реагирует
В "родной" версии

Version: 7.3.6.2 / LibreOffice Community
Build ID: 30(Build:2)
CPU threads: 4; OS: Linux 5.15; UI render: default; VCL: kf5 (cairo+xcb)
Locale: ru-RU (ru_RU.UTF-8); UI: ru-RU
Debian package version: 1:7.3.6-0ubuntu0.22.04.1~bpo20.04.1+ci202210040905+astra5
Calc: threaded

проблемы нет.
Владимир.