Created
March 12, 2024 10:50
-
-
Save varshneydevansh/3f1df11f6b98820d768e8324012dcdb9 to your computer and use it in GitHub Desktop.
generated output for the https://gerrit.libreoffice.org/c/core/+/163382/ for this input - https://git.libreoffice.org/sdk-examples/+/a0e4edacc44b21e0477b758413228d30939f4e87/TuesdayPython/Addons.xcu
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[~/libreoffice] | |
devansh 97448_pyHelper_addons_generator cd /home/devansh/libreoffice ; /usr/bin/env /bin/python3 /home/devansh/.vscode/extensions/ms-python.debugpy-2024.2.0-linux-x64/bundled/libs/debugpy/adapter/../../debugpy/launcher 43529 -- /home/devansh/libreoffice/odk/source/helper/addon_console.py | |
Welcome to the LibreOffice Addons Configuration Tool! | |
Enter addon name (extID name, e.g., com.<companyname>.<company-namespace>.<extension-namespace>): org.libreoffice.TuesdayPrinter | |
Do you want to create the 'AddonMenu' item (Tools > Add-ons)? (y/n): n | |
Do you want to create the 'OfficeHelp' item (Help menu)? (y/n): n | |
Images attribute defines the icons that appear next to the text in the menu and toolbar items. | |
Do you want to provide images? (y/n): n | |
Enter merge type (menu or toolbar): menu | |
Enter merge name (m<No> name for menu, label[] for toolbar): menu1 | |
Enter merge point: .uno:PickList\.uno:Print | |
Enter merge command (possible merge commands are: AddAfter, AddBefore, Replace, Remove): Replace | |
Enter merge fallback (possible merge fallbacks are: AddAfter, AddBefore, Replace, Remove): AddAfter | |
Select the application module context for the merge instruction: | |
1. Writer | |
2. Spreadsheet | |
3. Presentation | |
4. Draw | |
5. Formula | |
6. Chart | |
7. Bibliography | |
Enter your choice (1-7): 1 | |
Enter menu item name (or 'done' to finish): submenu1 | |
Enter menu item item title (use '~' before the accelerator key, e.g., '~File'): Print on Tuesdays | |
Enter menu item URL (can be a macro path or dispatch command): service:org.libreoffice.TuesdayPrinter?printontuesday | |
Enter menu item target (_self, _default, _top, _parent, or _blank): _self | |
Enter path to menu item image (optional, or 'skip' to skip): skip | |
Add submenu for this menu item? (y/n): n | |
Enter menu item name (or 'done' to finish): done | |
Continue to modify Menu or Toolbar? ( y or n ): y | |
Enter merge type (menu or toolbar): toolbar | |
Enter merge name (m<No> name for menu, label[] for toolbar): toolbar1 | |
Enter merge point: .uno:PrintDefault | |
Enter merge command (possible merge commands are: AddAfter, AddBefore, Replace, Remove): Replace | |
Enter merge fallback (possible merge fallbacks are: AddAfter, AddBefore, Replace, Remove): | |
Select the application module context for the merge instruction: | |
1. Writer | |
2. Spreadsheet | |
3. Presentation | |
4. Draw | |
5. Formula | |
6. Chart | |
7. Bibliography | |
Enter your choice (1-7): 1 | |
Enter toolbar item name (or 'done' to finish): button1 | |
Enter toolbar item item title (use '~' before the accelerator key, e.g., '~File'): Print on Tuesdays | |
Enter toolbar item URL (can be a macro path or dispatch command): service:org.libreoffice.TuesdayPrinter?printontuesday | |
Enter toolbar item target (_self, _default, _top, _parent, or _blank): _self | |
Enter path to toolbar item image (optional, or 'skip' to skip): skip | |
Add submenu for this toolbar item? (y/n): n | |
Enter the Merge ToolBar name | |
(specifies the appearance of the floating toolbar reached via View > Toolbars > Add-on) : org.libreoffice.TuesdayPrinter.standardbar | |
Do you want to add a button separator? | |
1. Before the first button | |
2. Between the buttons | |
3. No separator | |
Enter your choice (1-3): 3 | |
Enter toolbar item name (or 'done' to finish): previewobjectbar | |
Enter toolbar item item title (use '~' before the accelerator key, e.g., '~File'): Print on Tuesdays | |
Enter toolbar item URL (can be a macro path or dispatch command): service:org.libreoffice.TuesdayPrinter?printontuesday | |
Enter toolbar item target (_self, _default, _top, _parent, or _blank): _self | |
Enter path to toolbar item image (optional, or 'skip' to skip): skip | |
Add submenu for this toolbar item? (y/n): n | |
Enter the Merge ToolBar name | |
(specifies the appearance of the floating toolbar reached via View > Toolbars > Add-on) : org.libreoffice.TuesdayPrinter.previewobjectbar | |
Do you want to add a button separator? | |
1. Before the first button | |
2. Between the buttons | |
3. No separator | |
Enter your choice (1-3): 3 | |
Enter toolbar item name (or 'done' to finish): done | |
Continue to modify Menu or Toolbar? ( y or n ): n | |
Save Addons.xcu file to desktop or specify a path to custom directory? (d/c): d | |
Thank you for using the Addons.xcu file generation. Have a Nice Day! | |
--------------------------------- | |
<?xml version='1.0' encoding='UTF-8'?> | |
<oor:component-data oor:package="org.openoffice.Office" oor:name="Addons" | |
xmlns:oor="http://openoffice.org/2001/registry" xmlns:xs="http://www.w3.org/2001/XMLSchema"> | |
<node oor:name="AddonUI"> | |
<node oor:name="OfficeMenuBar"> | |
<node oor:name="org.libreoffice.TuesdayPrinter" oor:op="replace" xmlns:oor="http://openoffice.org/2001/registry"> | |
<node oor:name="menu1" oor:op="replace"> | |
<prop oor:name="MergePoint"> | |
<value>.uno:PickList\.uno:Print</value> | |
</prop> | |
<prop oor:name="MergeCommand"> | |
<value>Replace</value> | |
</prop> | |
<prop oor:name="MergeFallback"> | |
<value>AddAfter</value> | |
</prop> | |
<prop oor:name="Context" oor:type="xs:string"> | |
<value>com.sun.star.text.TextDocument</value> | |
</prop> | |
<node oor:name="MenuItems"> | |
<node oor:name="submenu1" oor:op="replace"> | |
<prop oor:name="Title"> | |
<value xml:lang="en-US">Print on Tuesdays</value> | |
</prop> | |
<prop oor:name="URL"> | |
<value>service:org.libreoffice.TuesdayPrinter?printontuesday</value> | |
</prop> | |
<prop oor:name="ImageIdentifier"> | |
<value>None</value> | |
</prop> | |
<prop oor:name="Target" oor:type="xs:string"> | |
<value>_self</value> | |
</prop> | |
</node> | |
</node> | |
</node> | |
</node> | |
</node> | |
<node oor:name="OfficeToolBar"> | |
<node oor:name="org.libreoffice.TuesdayPrinter" oor:op="replace" xmlns:oor="http://openoffice.org/2001/registry"> | |
<node oor:name="toolbar1" oor:op="replace"> | |
<prop oor:name="MergeToolBar"> | |
<value>org.libreoffice.TuesdayPrinter.previewobjectbar</value> | |
</prop> | |
<prop oor:name="MergePoint"> | |
<value>.uno:PrintDefault</value> | |
</prop> | |
<prop oor:name="MergeCommand"> | |
<value>Replace</value> | |
</prop> | |
<prop oor:name="MergeFallback"> | |
<value></value> | |
</prop> | |
<prop oor:name="Context" oor:type="xs:string"> | |
<value>com.sun.star.text.TextDocument</value> | |
</prop> | |
<node oor:name="ToolBarItems"> | |
<node oor:name="button1" oor:op="replace" xmlns:oor="http://openoffice.org/2001/registry"> | |
<prop oor:name="Title" oor:type="xs:string"> | |
<value xml:lang="en-US">Print on Tuesdays</value> | |
</prop> | |
<prop oor:name="URL" oor:type="xs:string"> | |
<value>service:org.libreoffice.TuesdayPrinter?printontuesday</value> | |
</prop> | |
<prop oor:name="ImageIdentifier" oor:type="xs:string"> | |
<value>None</value> | |
</prop> | |
<prop oor:name="Target" oor:type="xs:string"> | |
<value>_self</value> | |
</prop> | |
</node> | |
<prop oor:name="SeparatorPosition"><value>none</value></prop> | |
<node oor:name="previewobjectbar" oor:op="replace" xmlns:oor="http://openoffice.org/2001/registry"> | |
<prop oor:name="Title" oor:type="xs:string"> | |
<value xml:lang="en-US">Print on Tuesdays</value> | |
</prop> | |
<prop oor:name="URL" oor:type="xs:string"> | |
<value>service:org.libreoffice.TuesdayPrinter?printontuesday</value> | |
</prop> | |
<prop oor:name="ImageIdentifier" oor:type="xs:string"> | |
<value>None</value> | |
</prop> | |
<prop oor:name="Target" oor:type="xs:string"> | |
<value>_self</value> | |
</prop> | |
</node> | |
<prop oor:name="SeparatorPosition"><value>none</value></prop> | |
</node> | |
</node> | |
</node> | |
</node> | |
</node> | |
</oor:component-data> |
Author
varshneydevansh
commented
Mar 12, 2024
This is working only problem is improper indentation and some repeating merging options as seen in the o/p file attaching at the last -
# -*- tab-width: 4; indent-tabs-mode: nil; py-indent-offset: 4 -*-
#
# This file is part of the LibreOffice project.
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
import argparse
import xml.etree.ElementTree as ET
import os
from prompt_toolkit import prompt
import xml.dom.minidom
# Template fragments for merging menu items
MERGE_MENU_TEMPLATE = """
<node oor:name="OfficeMenuBar">
<node oor:name="{addon_name}" oor:op="replace" xmlns:oor="http://openoffice.org/2001/registry">
<node oor:name="{merge_name}" oor:op="replace">
<prop oor:name="MergePoint">
<value>{merge_point}</value>
</prop>
<prop oor:name="MergeCommand">
<value>{merge_command}</value>
</prop>
<prop oor:name="MergeFallback">
<value>{merge_fallback}</value>
</prop>
<prop oor:name="Context" oor:type="xs:string">
<value>{merge_context}</value>
</prop>
<node oor:name="MenuItems">
{menu_items}
</node>
</node>
</node>
</node>
"""
# Template fragments for menu items
MENU_ITEM_TEMPLATE = """
<node oor:name="{item_name}" oor:op="replace">
<prop oor:name="Title">
<value xml:lang="en-US">{title}</value>
</prop>
<prop oor:name="URL">
<value>{url}</value>
</prop>
<prop oor:name="ImageIdentifier">
<value>{image_path}</value>
</prop>
<prop oor:name="Target" oor:type="xs:string">
<value>{target}</value>
</prop>
{submenus}
</node>
"""
SUBMENU_TEMPLATE = """
<node oor:name="Submenus">
{submenu_items}
</node>
"""
SUBMENU_ITEM_TEMPLATE = """
<node oor:name="{submenu_name}" oor:op="replace">
<prop oor:name="Title">
<value xml:lang="en-US">{title}</value>
</prop>
<prop oor:name="URL">
<value>{url}</value>
</prop>
<prop oor:name="ImageIdentifier">
<value>{image_path}</value>
</prop>
<prop oor:name="Target" oor:type="xs:string">
<value>{target}</value>
</prop>
</node>
"""
# Template fragments for merging toolbar items
MERGE_TOOLBAR_TEMPLATE = """
<node oor:name="OfficeToolBar">
<node oor:name="{addon_name}" oor:op="replace" xmlns:oor="http://openoffice.org/2001/registry">
<node oor:name="{merge_name}" oor:op="replace">
<prop oor:name="MergeToolBar">
<value>{merge_toolbar}</value>
</prop>
<prop oor:name="MergePoint">
<value>{merge_point}</value>
</prop>
<prop oor:name="MergeCommand">
<value>{merge_command}</value>
</prop>
<prop oor:name="MergeFallback">
<value>{merge_fallback}</value>
</prop>
<prop oor:name="Context" oor:type="xs:string">
<value>{merge_context}</value>
</prop>
<node oor:name="ToolBarItems">
{toolbar_items}
</node>
</node>
</node>
</node>
"""
# Template fragments for toolbar items
TOOLBAR_ITEM_TEMPLATE = """
<node oor:name="{item_name}" oor:op="replace" xmlns:oor="http://openoffice.org/2001/registry">
<prop oor:name="Title" oor:type="xs:string">
<value xml:lang="en-US">{title}</value>
</prop>
<prop oor:name="URL" oor:type="xs:string">
<value>{url}</value>
</prop>
<prop oor:name="ImageIdentifier" oor:type="xs:string">
<value>{image_path}</value>
</prop>
<prop oor:name="Target" oor:type="xs:string">
<value>{target}</value>
</prop>
</node>
"""
# Template fragment for images
IMAGES_TEMPLATE = """
<node oor:name="Images" oor:op="replace">
<prop oor:name="ImageSmall">
<value>{image_small}</value>
</prop>
<prop oor:name="ImageBig">
<value>{image_big}</value>
</prop>
<prop oor:name="ImageSmallHC">
<value>{image_small_hc}</value>
</prop>
<prop oor:name="ImageBigHC">
<value>{image_big_hc}</value>
</prop>
</node>
"""
# Template fragments for addon menu and help menu
ADDON_MENU_TEMPLATE = """
<node oor:name="{addon_menu_name}" oor:op="replace">
<prop oor:name="Title">
<value xml:lang="en-US">{title}</value>
</prop>
<prop oor:name="URL">
<value>{url}</value>
</prop>
<prop oor:name="ImageIdentifier">
<value>{image_path}</value>
</prop>
<prop oor:name="Target" oor:type="xs:string">
<value>{target}</value>
</prop>
</node>
"""
HELP_MENU_TEMPLATE = """
<node oor:name="{help_menu_name}" oor:op="replace">
<prop oor:name="Title">
<value xml:lang="en-US">{title}</value>
</prop>
<prop oor:name="URL">
<value>{url}</value>
</prop>
<prop oor:name="ImageIdentifier">
<value>{image_path}</value>
</prop>
<prop oor:name="Target" oor:type="xs:string">
<value>{target}</value>
</prop>
</node>
"""
#-------------------------- generating the xml functions --------------------------
def generate_menu_fragment(addon_name, merge_name, merge_point, merge_command, merge_fallback, merge_context, menu_items):
ns = {'oor': 'http://openoffice.org/2001/registry'}
ET.register_namespace('oor', 'http://openoffice.org/2001/registry')
merge_node = ET.Element('{http://openoffice.org/2001/registry}node', {'oor:name': 'OfficeMenuBar'})
addon_node = ET.SubElement(merge_node, '{http://openoffice.org/2001/registry}node', {'oor:name': addon_name, 'oor:op': 'replace'})
merge_item_node = ET.SubElement(addon_node, '{http://openoffice.org/2001/registry}node', {'oor:name': merge_name, 'oor:op': 'replace'})
if merge_point:
merge_point_node = ET.SubElement(merge_item_node, 'prop', {'oor:name': 'MergePoint'})
ET.SubElement(merge_point_node, 'value').text = merge_point
merge_command_node = ET.SubElement(merge_item_node, 'prop', {'oor:name': 'MergeCommand'})
ET.SubElement(merge_command_node, 'value').text = merge_command
if merge_fallback:
merge_fallback_node = ET.SubElement(merge_item_node, 'prop', {'oor:name': 'MergeFallback'})
ET.SubElement(merge_fallback_node, 'value').text = merge_fallback
merge_context_node = ET.SubElement(merge_item_node, 'prop', {'oor:name': 'Context', 'oor:type': 'xs:string'})
ET.SubElement(merge_context_node, 'value').text = merge_context
menu_items_node = ET.SubElement(merge_item_node, '{http://openoffice.org/2001/registry}node', {'oor:name': 'MenuItems'})
for menu_item in menu_items:
root = ET.fromstring(f"<root xmlns:oor='http://openoffice.org/2001/registry'>{menu_item}</root>")
menu_item_node = root.find('oor:node', ns)
if menu_item_node is not None:
menu_items_node.extend(menu_item_node)
return merge_node
def generate_menu_item_fragment(item_name, title, url, image_path, target, submenus=None):
menu_item_node = ET.Element('node', {'oor:name': item_name, 'oor:op': 'replace'})
if title:
title_node = ET.SubElement(menu_item_node, 'prop', {'oor:name': 'Title'})
ET.SubElement(title_node, 'value', {'xml:lang': 'en-US'}).text = title
if url:
url_node = ET.SubElement(menu_item_node, 'prop', {'oor:name': 'URL'})
ET.SubElement(url_node, 'value').text = url
if image_path:
image_node = ET.SubElement(menu_item_node, 'prop', {'oor:name': 'ImageIdentifier'})
ET.SubElement(image_node, 'value').text = image_path
target_node = ET.SubElement(menu_item_node, 'prop', {'oor:name': 'Target', 'oor:type': 'xs:string'})
ET.SubElement(target_node, 'value').text = target
if submenus:
submenu_node = ET.SubElement(menu_item_node, 'node', {'oor:name': 'Submenus'})
for submenu in submenus:
submenu_node.append(ET.fromstring(submenu))
return ET.tostring(menu_item_node, encoding='unicode')
def generate_submenu_item_fragment(submenu_name, title, url, image_path, target):
submenu_node = ET.Element('node', {'oor:name': submenu_name, 'oor:op': 'replace'})
if title:
title_node = ET.SubElement(submenu_node, 'prop', {'oor:name': 'Title'})
ET.SubElement(title_node, 'value', {'xml:lang': 'en-US'}).text = title
if url:
url_node = ET.SubElement(submenu_node, 'prop', {'oor:name': 'URL'})
ET.SubElement(url_node, 'value').text = url
if image_path:
image_node = ET.SubElement(submenu_node, 'prop', {'oor:name': 'ImageIdentifier'})
ET.SubElement(image_node, 'value').text = image_path
target_node = ET.SubElement(submenu_node, 'prop', {'oor:name': 'Target', 'oor:type': 'xs:string'})
ET.SubElement(target_node, 'value').text = target
return ET.tostring(submenu_node, encoding='unicode')
def generate_toolbar_fragment(addon_name, merge_name, merge_toolbar, merge_point, merge_command, merge_fallback, merge_context, toolbar_items):
ns = {'oor': 'http://openoffice.org/2001/registry'}
ET.register_namespace('oor', 'http://openoffice.org/2001/registry')
merge_node = ET.Element('{http://openoffice.org/2001/registry}node', {'oor:name': 'OfficeToolBar'})
addon_node = ET.SubElement(merge_node, '{http://openoffice.org/2001/registry}node', {'oor:name': addon_name, 'oor:op': 'replace'})
merge_item_node = ET.SubElement(addon_node, '{http://openoffice.org/2001/registry}node', {'oor:name': merge_name, 'oor:op': 'replace'})
if merge_toolbar:
merge_toolbar_node = ET.SubElement(merge_item_node, 'prop', {'oor:name': 'MergeToolBar'})
ET.SubElement(merge_toolbar_node, 'value').text = merge_toolbar
if merge_point:
merge_point_node = ET.SubElement(merge_item_node, 'prop', {'oor:name': 'MergePoint'})
ET.SubElement(merge_point_node, 'value').text = merge_point
merge_command_node = ET.SubElement(merge_item_node, 'prop', {'oor:name': 'MergeCommand'})
ET.SubElement(merge_command_node, 'value').text = merge_command
if merge_fallback:
merge_fallback_node = ET.SubElement(merge_item_node, 'prop', {'oor:name': 'MergeFallback'})
ET.SubElement(merge_fallback_node, 'value').text = merge_fallback
merge_context_node = ET.SubElement(merge_item_node, 'prop', {'oor:name': 'Context', 'oor:type': 'xs:string'})
ET.SubElement(merge_context_node, 'value').text = merge_context
toolbar_items_node = ET.SubElement(merge_item_node, '{http://openoffice.org/2001/registry}node', {'oor:name': 'ToolBarItems'})
for toolbar_item in toolbar_items:
root = ET.fromstring(f"<root xmlns:oor='http://openoffice.org/2001/registry'>{toolbar_item}</root>")
toolbar_item_node = root.find('oor:node', ns)
if toolbar_item_node is not None:
toolbar_items_node.extend(toolbar_item_node)
return merge_node
def generate_toolbar_item_fragment(item_name, title, url, image_path, target, separator_position=None):
toolbar_item_node = ET.Element('node', {'oor:name': item_name, 'oor:op': 'replace', 'xmlns:oor': 'http://openoffice.org/2001/registry'})
if title:
title_node = ET.SubElement(toolbar_item_node, 'prop', {'oor:name': 'Title', 'oor:type': 'xs:string'})
ET.SubElement(title_node, 'value', {'xml:lang': 'en-US'}).text = title
if url:
url_node = ET.SubElement(toolbar_item_node, 'prop', {'oor:name': 'URL', 'oor:type': 'xs:string'})
ET.SubElement(url_node, 'value').text = url
if image_path:
image_node = ET.SubElement(toolbar_item_node, 'prop', {'oor:name': 'ImageIdentifier', 'oor:type': 'xs:string'})
ET.SubElement(image_node, 'value').text = image_path
target_node = ET.SubElement(toolbar_item_node, 'prop', {'oor:name': 'Target', 'oor:type': 'xs:string'})
ET.SubElement(target_node, 'value').text = target
if separator_position:
separator_node = ET.SubElement(toolbar_item_node, 'prop', {'oor:name': 'SeparatorPosition'})
ET.SubElement(separator_node, 'value').text = separator_position
return ET.tostring(toolbar_item_node, encoding='unicode')
def generate_images_fragment(image_small, image_big, image_small_hc, image_big_hc):
images_node = ET.Element('node', {'oor:name': 'Images', 'oor:op': 'replace'})
if image_small:
small_node = ET.SubElement(images_node, 'prop', {'oor:name': 'ImageSmall'})
ET.SubElement(small_node, 'value').text = image_small
if image_big:
big_node = ET.SubElement(images_node, 'prop', {'oor:name': 'ImageBig'})
ET.SubElement(big_node, 'value').text = image_big
if image_small_hc:
small_hc_node = ET.SubElement(images_node, 'prop', {'oor:name': 'ImageSmallHC'})
ET.SubElement(small_hc_node, 'value').text = image_small_hc
if image_big_hc:
big_hc_node = ET.SubElement(images_node, 'prop', {'oor:name': 'ImageBigHC'})
ET.SubElement(big_hc_node, 'value').text = image_big_hc
return ET.tostring(images_node, encoding='unicode')
def generate_addon_menu_fragment(addon_menu_name, title, url, image_path, target):
addon_menu_node = ET.Element('node', {'oor:name': addon_menu_name, 'oor:op': 'replace'})
if title:
title_node = ET.SubElement(addon_menu_node, 'prop', {'oor:name': 'Title'})
ET.SubElement(title_node, 'value', {'xml:lang': 'en-US'}).text = title
if url:
url_node = ET.SubElement(addon_menu_node, 'prop', {'oor:name': 'URL'})
ET.SubElement(url_node, 'value').text = url
if image_path:
image_node = ET.SubElement(addon_menu_node, 'prop', {'oor:name': 'ImageIdentifier'})
ET.SubElement(image_node, 'value').text = image_path
target_node = ET.SubElement(addon_menu_node, 'prop', {'oor:name': 'Target', 'oor:type': 'xs:string'})
ET.SubElement(target_node, 'value').text = target
return ET.tostring(addon_menu_node, encoding='unicode')
def generate_help_menu_fragment(help_menu_name, title, url, image_path, target):
help_menu_node = ET.Element('node', {'oor:name': help_menu_name, 'oor:op': 'replace'})
if title:
title_node = ET.SubElement(help_menu_node, 'prop', {'oor:name': 'Title'})
ET.SubElement(title_node, 'value', {'xml:lang': 'en-US'}).text = title
if url:
url_node = ET.SubElement(help_menu_node, 'prop', {'oor:name': 'URL'})
ET.SubElement(url_node, 'value').text = url
if image_path:
image_node = ET.SubElement(help_menu_node, 'prop', {'oor:name': 'ImageIdentifier'})
ET.SubElement(image_node, 'value').text = image_path
target_node = ET.SubElement(help_menu_node, 'prop', {'oor:name': 'Target', 'oor:type': 'xs:string'})
ET.SubElement(target_node, 'value').text = target
return ET.tostring(help_menu_node, encoding='unicode')
def stitching_xcu(addon_name, merge_type, merge_name, merge_point, merge_command, merge_fallback, items, merge_toolbar, merge_context):
if merge_type == 'menu':
merge_fragment = generate_menu_fragment(addon_name, merge_name, merge_point, merge_command, merge_fallback, merge_context, menu_items=items)
elif merge_type == 'toolbar':
merge_fragment = generate_toolbar_fragment(addon_name, merge_name, merge_toolbar, merge_point, merge_command, merge_fallback, merge_context, toolbar_items=items)
else:
merge_fragment = ''
return ET.tostring(merge_fragment, encoding='unicode')
def generate_xcu(merge_fragment, output_dir, addon_menu_fragment, help_menu_fragment, images_fragment):
ns = {'oor': 'http://openoffice.org/2001/registry', 'xs': 'http://www.w3.org/2001/XMLSchema'}
ET.register_namespace('oor', 'http://openoffice.org/2001/registry')
ET.register_namespace('xs', 'http://www.w3.org/2001/XMLSchema')
# Determine the output directory
if not output_dir:
while True:
choice = input("\n\nSave Addons.xcu file to desktop or specify a path to custom directory? (d/c): ").lower()
if choice in ("d", "desktop"):
output_dir = os.path.join(os.path.expanduser('~'), 'Desktop')
break
elif choice == "c":
custom_dir = input("\nEnter custom directory path: ")
output_dir = validate_directory(custom_dir)
if output_dir:
break
else:
print("\nInvalid choice. Please choose 'd' or 'c'.")
root = ET.Element('{http://openoffice.org/2001/registry}oor:component-data', {
'oor:package': 'org.openoffice.Office',
'oor:name': 'Addons',
'xmlns:xs': 'http://www.w3.org/2001/XMLSchema'
})
addon_ui = ET.SubElement(root, '{http://openoffice.org/2001/registry}node', {'oor:name': 'AddonUI'})
if addon_menu_fragment:
root_addon_menu = ET.fromstring(f"<root xmlns:oor='http://openoffice.org/2001/registry'>{addon_menu_fragment}</root>")
addon_ui.extend(root_addon_menu.findall('oor:node', ns))
if merge_fragment:
root_merge = ET.fromstring(merge_fragment)
for node in root_merge.iter('{http://openoffice.org/2001/registry}node'):
addon_ui.append(node)
if help_menu_fragment:
root_help_menu = ET.fromstring(f"<root xmlns:oor='http://openoffice.org/2001/registry'>{help_menu_fragment}</root>")
addon_ui.extend(root_help_menu.findall('oor:node', ns))
if images_fragment:
root_images = ET.fromstring(f"<root xmlns:oor='http://openoffice.org/2001/registry'>{images_fragment}</root>")
addon_ui.extend(root_images.findall('oor:node', ns))
xml_tree = ET.ElementTree(root)
file_path = os.path.join(output_dir, 'Addons.xcu')
with open(file_path, 'wb') as file:
xml_tree.write(file, encoding='utf-8', xml_declaration=True)
#-------------------------- prompt message functions --------------------------
def prompt_merge_context():
print("\nSelect the application module context for the merge instruction:")
print("1. Writer")
print("2. Spreadsheet")
print("3. Presentation")
print("4. Draw")
print("5. Formula")
print("6. Chart")
print("7. Bibliography")
choice = input("Enter your choice (1-7): ").strip()
if choice == '1':
return "com.sun.star.text.TextDocument"
elif choice == '2':
return "com.sun.star.sheet.SpreadsheetDocument"
elif choice == '3':
return "com.sun.star.presentation.PresentationDocument"
elif choice == '4':
return "com.sun.star.drawing.DrawingDocument"
elif choice == '5':
return "com.sun.star.formula.FormulaProperties"
elif choice == '6':
return "com.sun.star.chart.ChartDocument"
elif choice == '7':
return "com.sun.star.frame.Bibliography"
else:
print("Invalid choice. Please select again.")
return prompt_merge_context()
def prompt_images():
print("\nPlease provide paths to the [ .bmp ] images (type 'skip' to skip providing an image):")
image_small = input("Path to small image: ").strip()
if image_small.lower() == 'skip':
image_small = None
else:
image_small = validate_image_path(image_small)
image_big = input("Path to big image: ").strip()
if image_big.lower() == 'skip':
image_big = None
else:
image_big = validate_image_path(image_big)
image_small_hc = input("Path to small high-contrast image: ").strip()
if image_small_hc.lower() == 'skip':
image_small_hc = None
else:
image_small_hc = validate_image_path(image_small_hc)
image_big_hc = input("Path to big high-contrast image: ").strip()
if image_big_hc.lower() == 'skip':
image_big_hc = None
else:
image_big_hc = validate_image_path(image_big_hc)
return image_small, image_big, image_small_hc, image_big_hc
def prompt_addon_name():
addon_name = prompt("\nEnter addon name (extID name, e.g., com.<companyname>.<company-namespace>.<extension-namespace>): ").strip()
return addon_name
def prompt_menu_title(menu_type):
title = prompt(f"\nEnter {menu_type} item title (use '~' before the accelerator key, e.g., '~File'): ").strip()
return title
def prompt_button_separator():
print("\nDo you want to add a button separator?")
print("1. Before the first button")
print("2. Between the buttons")
print("3. No separator")
choice = input("Enter your choice (1-3): ").strip()
if choice == '1':
return "before_first"
elif choice == '2':
return "between_buttons"
elif choice == '3':
return "none"
else:
print("Invalid choice. Please select again.")
return prompt_button_separator()
def prompt_image_path(merge_type):
while True:
image_path = prompt(f"\nEnter path to {merge_type} item image (optional, or 'skip' to skip): ").strip().lower()
if image_path == 'skip':
return None
image_path = validate_image_path(image_path)
if image_path:
return image_path
print("Invalid file type. Please try again or enter 'skip' to skip.")
#-------------------------- validating provided path --------------------------
def validate_directory(directory_path):
if not directory_path:
return None # No output directory provided
try:
if not os.path.isdir(directory_path):
raise ValueError("\nInvalid directory: Path is not a directory")
# Additional validations can be added here if needed
except ValueError as e:
print(f"Error: {e}")
return None
return directory_path
def validate_image_path(image_path):
if not image_path:
return None # No image path provided
try:
if not os.path.exists(image_path):
raise ValueError("\nInvalid path: Path does not exist")
_, ext = os.path.splitext(image_path)
if ext.lower() != '.bmp':
raise ValueError("\nInvalid file type: Only .bmp files are allowed")
# Additional validations can be added here if needed
except ValueError as e:
print(f"Error: {e}")
return None
return image_path
#-------------------------- MAIN --------------------------
def main():
print("\nWelcome to the LibreOffice Addons Configuration Tool!\n")
merge_fragment = ''
addon_name = prompt_addon_name()
addon_menu_fragment = ''
help_menu_fragment = ''
images_fragment = ''
# Prompt for addon menu item
choice = prompt("\nDo you want to create the 'AddonMenu' item (Tools > Add-ons)? (y/n): ").strip().lower()
if choice == 'y':
addon_menu_name = prompt("\nEnter addon menu item name (Tools > Add-ons): ").strip()
addon_menu_title = prompt_menu_title("addon menu")
addon_menu_url = prompt("\nEnter addon menu item URL: ").strip()
addon_menu_target = prompt("\nEnter addon menu item target (_self, _default, _top, _parent, or _blank): ").strip()
addon_menu_image_path = prompt("\nEnter path to addon menu item image (optional): ").strip()
addon_menu_image_path = validate_image_path(addon_menu_image_path)
addon_menu_fragment = generate_addon_menu_fragment(addon_menu_name, addon_menu_title, addon_menu_url, addon_menu_image_path, addon_menu_target)
# Prompt for help menu item
choice = prompt("\nDo you want to create the 'OfficeHelp' item (Help menu)? (y/n): ").strip().lower()
if choice == 'y':
help_menu_name = prompt("\nEnter help menu item name (Help menu): ").strip()
help_menu_title = prompt_menu_title("help menu")
help_menu_url = prompt("\nEnter help menu item URL: ").strip()
help_menu_target = prompt("\nEnter help menu item target (_self, _default, _top, _parent, or _blank): ").strip()
help_menu_image_path = prompt("\nEnter path to help menu item image (optional): ").strip()
help_menu_image_path = validate_image_path(help_menu_image_path)
help_menu_fragment = generate_help_menu_fragment(help_menu_name, help_menu_title, help_menu_url, help_menu_image_path, help_menu_target)
# Prompt for images
choice = prompt("\nImages attribute defines the icons that appear next to the text in the menu and toolbar items.\nDo you want to provide images? (y/n): ").strip().lower()
if choice == 'y':
image_small, image_big, image_small_hc, image_big_hc = prompt_images()
images_fragment = generate_images_fragment(image_small, image_big, image_small_hc, image_big_hc)
while True: # Outer loop for gathering input for each merge
items = [] # Initialize items list for each merge type
merge_type = prompt("\n\nEnter merge type (menu or toolbar): ").strip()
while merge_type not in ['menu', 'toolbar']:
merge_type = prompt("\nInvalid input. \nEnter merge type (menu or toolbar): ").strip()
# Gather input for merge
merge_name = prompt("\nEnter merge name (m<No> name for menu, label[] for toolbar): \nFor example:\nFor a menu merge operation, you could enter something like 'm1' or 'm_print_options'.\nFor a toolbar merge operation, you could enter something like [PrintButton] or [FormatToolbar]: ").strip()
merge_point = prompt("\nEnter merge point: ").strip()
merge_command = prompt("\nEnter merge command (possible merge commands are: AddAfter, AddBefore, Replace, Remove): ").strip()
merge_fallback = prompt("\nEnter merge fallback (possible merge fallbacks are: AddAfter, AddBefore, Replace, Remove): ").strip()
merge_toolbar = None
output_dir = None
merge_context = prompt_merge_context()
while True: # Inner loop for gathering input for items
item_name = prompt(f"\nEnter {merge_type} item name (or 'done' to finish): ").strip().lower()
if item_name.lower() == 'done':
break
title = prompt_menu_title(f"{merge_type} item")
url = prompt(f"\nEnter {merge_type} item URL (can be a macro path or dispatch command): ").strip()
target = prompt(f"\nEnter {merge_type} item target (_self, _default, _top, _parent, or _blank): ").strip()
image_path = prompt_image_path(merge_type)
# Prompt for submenus
submenus = []
add_submenu = prompt(f"\nAdd submenu for this {merge_type} item? (y/n): ").strip().lower()
if add_submenu == 'y':
while True:
submenu_name = prompt("\nEnter submenu name (or 'done' to finish): ").strip().lower()
if submenu_name.lower() == 'done':
break
submenu_title = prompt_menu_title("submenu")
submenu_url = prompt("\nEnter submenu URL: ").strip()
submenu_target = prompt("\nEnter submenu target (_self, _default, _top, _parent, or _blank): ").strip()
submenu_image_path = prompt("\nEnter path to submenu image (optional): ").strip()
submenu_image_path = validate_image_path(submenu_image_path)
submenus.append(generate_submenu_item_fragment(submenu_name, submenu_title, submenu_url, submenu_image_path, submenu_target))
# Generate item fragment based on merge type
if merge_type == 'menu':
items.append(generate_menu_item_fragment(item_name, title, url, image_path, target, submenus))
elif merge_type == 'toolbar':
merge_toolbar = prompt("\nEnter the Merge ToolBar name\n(specifies the appearance of the floating toolbar reached via View > Toolbars > Add-on) : ").strip()
separator_position = prompt_button_separator()
items.append(generate_toolbar_item_fragment(item_name, title, url, image_path, target, separator_position))
merge_fragment += stitching_xcu(addon_name, merge_type, merge_name, merge_point, merge_command, merge_fallback, items, merge_toolbar, merge_context)
keep_merging = prompt("\n\n\nContinue to modify Menu or Toolbar? ( y or n ): ").strip().lower()
if keep_merging == 'n':
# Generate .xcu file
generate_xcu(merge_fragment, output_dir, addon_menu_fragment, help_menu_fragment, images_fragment)
break
print("Thank you for using the Addons.xcu file generation. Have a Nice Day!")
if __name__ == "__main__":
main()
<?xml version='1.0' encoding='utf-8'?>
<oor:oor:component-data
xmlns:oor="http://openoffice.org/2001/registry" oor:package="org.openoffice.Office" oor:name="Addons"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<oor:node oor:name="AddonUI">
<oor:node oor:name="OfficeMenuBar">
<oor:node oor:name="org.libreoffice.TuesdayPrinter" oor:op="replace">
<oor:node oor:name="menu1" oor:op="replace">
<prop oor:name="MergePoint">
<value>point</value>
</prop>
<prop oor:name="MergeCommand">
<value>Replace</value>
</prop>
<prop oor:name="MergeFallback">
<value>AdAfter</value>
</prop>
<prop oor:name="Context" oor:type="xs:string">
<value>com.sun.star.sheet.SpreadsheetDocument</value>
</prop>
<oor:node oor:name="MenuItems" /></oor:node>
</oor:node>
</oor:node>
<oor:node oor:name="org.libreoffice.TuesdayPrinter" oor:op="replace">
<oor:node oor:name="menu1" oor:op="replace">
<prop oor:name="MergePoint">
<value>point</value>
</prop>
<prop oor:name="MergeCommand">
<value>Replace</value>
</prop>
<prop oor:name="MergeFallback">
<value>AdAfter</value>
</prop>
<prop oor:name="Context" oor:type="xs:string">
<value>com.sun.star.sheet.SpreadsheetDocument</value>
</prop>
<oor:node oor:name="MenuItems" /></oor:node>
</oor:node>
<oor:node oor:name="menu1" oor:op="replace">
<prop oor:name="MergePoint">
<value>point</value>
</prop>
<prop oor:name="MergeCommand">
<value>Replace</value>
</prop>
<prop oor:name="MergeFallback">
<value>AdAfter</value>
</prop>
<prop oor:name="Context" oor:type="xs:string">
<value>com.sun.star.sheet.SpreadsheetDocument</value>
</prop>
<oor:node oor:name="MenuItems" /></oor:node>
<oor:node oor:name="MenuItems" /></oor:node>
</oor:oor:component-data>
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment