├── __init__.py ├── pythonpath ├── __init__.py ├── config.py ├── simple_dialogs.py ├── embed_packer.py ├── generator.py └── sidebar.py ├── templates ├── script_ext │ ├── 3_license.txt │ ├── 5_title.txt │ ├── 4_description_en.txt │ ├── 6_Addons.xcu │ ├── 1_manifest.xml │ ├── 2_description.xml │ ├── 7_Addons_submenu.xcu │ ├── 3_license_lgpl3.txt │ └── 3_license_apache2.txt ├── sidebar_convert_ext │ ├── 3_license.txt │ ├── 5_title.txt │ ├── 9_icon1.png │ ├── 9_icon2.png │ ├── 9_icon3.png │ ├── 4_description_en.txt │ ├── 7_ProtocolHandler.xcu │ ├── 8_empty_dialog.xdl │ ├── 1_manifest.xml │ ├── 6_Factory.xcu │ ├── 11_sidebar_panels.txt │ ├── 10_Sidebar.xcu │ ├── 2_description.xml │ ├── 3_license_lgpl3.txt │ └── 3_license_apache2.txt ├── convert │ ├── 2_dialog_properties.txt │ ├── 4_control_properties.txt │ ├── 7_event_action.txt │ ├── 5_control_insert.txt │ ├── 3_control_model.txt │ ├── 11_event_callbacks.txt │ ├── 6_control_event_action.txt │ ├── 1_main_ui.txt │ └── 10_main.txt ├── embeded │ ├── 2_dialog_properties.txt │ ├── 4_control_properties.txt │ ├── 7_event_action.txt │ ├── 5_control_insert.txt │ ├── 3_control_model.txt │ ├── 11_event_callbacks.txt │ ├── 6_control_event_action.txt │ └── 1_main_ui.txt ├── sidebar_convert │ ├── 2_dialog_properties.txt │ ├── 4_control_properties.txt │ ├── 7_event_action.txt │ ├── 5_control_insert.txt │ ├── 3_control_model.txt │ ├── 11_event_callbacks.txt │ ├── 6_control_event_action.txt │ ├── 101_sidebar_show_panels.txt │ ├── 102_show_menu_command.txt │ ├── 1_main_ui.txt │ ├── 10_main.txt │ └── 100_sidebar_main.txt ├── connect │ ├── 2_controls.txt │ ├── 4_event_action.txt │ ├── 3_control_event.txt │ ├── 5_event_action_callbaks.txt │ └── 1_connect_main.txt └── dialogs │ └── 2_dialogs_main.txt ├── examples ├── convert dialog │ ├── description │ │ ├── title.txt │ │ └── description.txt │ ├── Test_convert_Devel.oxt │ ├── Addons.xcu │ ├── META-INF │ │ └── manifest.xml │ ├── description.xml │ ├── src │ │ └── Test_convert.py │ └── registration │ │ └── license.txt ├── simple dialogs │ ├── description │ │ ├── title.txt │ │ └── description.txt │ ├── Test_dialogs_Devel.oxt │ ├── Addons.xcu │ ├── META-INF │ │ └── manifest.xml │ ├── src │ │ └── Test_dialogs.py │ ├── description.xml │ └── registration │ │ └── license.txt ├── embed dialog │ ├── Text document.odt │ └── Text document_MACRO.odt └── connect to dialog │ └── src │ └── Test_connect.py ├── resource ├── images │ ├── unodit.png │ ├── unodit.xcf │ ├── unodit2.png │ ├── unodit2.xcf │ ├── unodit3.png │ └── unodit3.xcf ├── embed │ ├── Calc Document.ods │ ├── Draw Document.odg │ ├── Impress Document.odp │ └── Writer Document.odt ├── screenshot │ ├── Button_event.png │ ├── Example_dialog.png │ ├── Macros_connect.png │ ├── Sidebar_panels.png │ ├── Macros_embed_all.png │ ├── Macros_script_all.png │ └── Macros_simple_dialogs.png ├── simpe_dialogs │ ├── ActionBox.png │ ├── DateBox.png │ ├── NumberBox.png │ ├── OptionBox.png │ ├── SelectBox.png │ ├── TextBox.png │ ├── FilePathBox.png │ ├── MessageBox.png │ └── FolderPathBox.png └── xdl │ ├── empty_dialog.xdl │ ├── text_dialog.xdl │ ├── option_dialog.xdl │ ├── list_dialog.xdl │ └── test_dialog.xdl ├── .idea ├── misc.xml ├── vcs.xml ├── modules.xml └── unodit.iml ├── config.ini ├── README.md └── unodit.py /__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /pythonpath/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /templates/script_ext/3_license.txt: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /templates/sidebar_convert_ext/3_license.txt: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /templates/script_ext/5_title.txt: -------------------------------------------------------------------------------- 1 | MyScriptExtension v 0.1.0 2 | -------------------------------------------------------------------------------- /templates/sidebar_convert_ext/5_title.txt: -------------------------------------------------------------------------------- 1 | MySidebarExtension v 0.1.0 2 | -------------------------------------------------------------------------------- /examples/convert dialog/description/title.txt: -------------------------------------------------------------------------------- 1 | MyScriptExtension v 0.1.0 2 | -------------------------------------------------------------------------------- /examples/simple dialogs/description/title.txt: -------------------------------------------------------------------------------- 1 | MyScriptExtension v 0.1.0 2 | -------------------------------------------------------------------------------- /templates/convert/2_dialog_properties.txt: -------------------------------------------------------------------------------- 1 | self.DialogModel.${PROPERTIES} = ${VALUE} 2 | -------------------------------------------------------------------------------- /templates/embeded/2_dialog_properties.txt: -------------------------------------------------------------------------------- 1 | self.DialogModel.${PROPERTIES} = ${VALUE} 2 | -------------------------------------------------------------------------------- /resource/images/unodit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kelsa-pi/unodit/HEAD/resource/images/unodit.png -------------------------------------------------------------------------------- /resource/images/unodit.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kelsa-pi/unodit/HEAD/resource/images/unodit.xcf -------------------------------------------------------------------------------- /templates/convert/4_control_properties.txt: -------------------------------------------------------------------------------- 1 | 2 | self.${CONTROL_NAME}.${PROPERTIES} = ${VALUE} -------------------------------------------------------------------------------- /templates/embeded/4_control_properties.txt: -------------------------------------------------------------------------------- 1 | 2 | self.${CONTROL_NAME}.${PROPERTIES} = ${VALUE} -------------------------------------------------------------------------------- /templates/sidebar_convert/2_dialog_properties.txt: -------------------------------------------------------------------------------- 1 | self.DialogModel.${PROPERTIES} = ${VALUE} 2 | -------------------------------------------------------------------------------- /resource/images/unodit2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kelsa-pi/unodit/HEAD/resource/images/unodit2.png -------------------------------------------------------------------------------- /resource/images/unodit2.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kelsa-pi/unodit/HEAD/resource/images/unodit2.xcf -------------------------------------------------------------------------------- /resource/images/unodit3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kelsa-pi/unodit/HEAD/resource/images/unodit3.png -------------------------------------------------------------------------------- /resource/images/unodit3.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kelsa-pi/unodit/HEAD/resource/images/unodit3.xcf -------------------------------------------------------------------------------- /templates/connect/2_controls.txt: -------------------------------------------------------------------------------- 1 | ${CONTROL_NAME} = self.DialogModel.getByName("${CONTROL_NAME}") 2 | -------------------------------------------------------------------------------- /templates/sidebar_convert/4_control_properties.txt: -------------------------------------------------------------------------------- 1 | 2 | self.${CONTROL_NAME}.${PROPERTIES} = ${VALUE} -------------------------------------------------------------------------------- /resource/embed/Calc Document.ods: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kelsa-pi/unodit/HEAD/resource/embed/Calc Document.ods -------------------------------------------------------------------------------- /resource/embed/Draw Document.odg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kelsa-pi/unodit/HEAD/resource/embed/Draw Document.odg -------------------------------------------------------------------------------- /resource/embed/Impress Document.odp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kelsa-pi/unodit/HEAD/resource/embed/Impress Document.odp -------------------------------------------------------------------------------- /resource/embed/Writer Document.odt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kelsa-pi/unodit/HEAD/resource/embed/Writer Document.odt -------------------------------------------------------------------------------- /resource/screenshot/Button_event.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kelsa-pi/unodit/HEAD/resource/screenshot/Button_event.png -------------------------------------------------------------------------------- /resource/simpe_dialogs/ActionBox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kelsa-pi/unodit/HEAD/resource/simpe_dialogs/ActionBox.png -------------------------------------------------------------------------------- /resource/simpe_dialogs/DateBox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kelsa-pi/unodit/HEAD/resource/simpe_dialogs/DateBox.png -------------------------------------------------------------------------------- /resource/simpe_dialogs/NumberBox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kelsa-pi/unodit/HEAD/resource/simpe_dialogs/NumberBox.png -------------------------------------------------------------------------------- /resource/simpe_dialogs/OptionBox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kelsa-pi/unodit/HEAD/resource/simpe_dialogs/OptionBox.png -------------------------------------------------------------------------------- /resource/simpe_dialogs/SelectBox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kelsa-pi/unodit/HEAD/resource/simpe_dialogs/SelectBox.png -------------------------------------------------------------------------------- /resource/simpe_dialogs/TextBox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kelsa-pi/unodit/HEAD/resource/simpe_dialogs/TextBox.png -------------------------------------------------------------------------------- /resource/screenshot/Example_dialog.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kelsa-pi/unodit/HEAD/resource/screenshot/Example_dialog.png -------------------------------------------------------------------------------- /resource/screenshot/Macros_connect.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kelsa-pi/unodit/HEAD/resource/screenshot/Macros_connect.png -------------------------------------------------------------------------------- /resource/screenshot/Sidebar_panels.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kelsa-pi/unodit/HEAD/resource/screenshot/Sidebar_panels.png -------------------------------------------------------------------------------- /resource/simpe_dialogs/FilePathBox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kelsa-pi/unodit/HEAD/resource/simpe_dialogs/FilePathBox.png -------------------------------------------------------------------------------- /resource/simpe_dialogs/MessageBox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kelsa-pi/unodit/HEAD/resource/simpe_dialogs/MessageBox.png -------------------------------------------------------------------------------- /examples/embed dialog/Text document.odt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kelsa-pi/unodit/HEAD/examples/embed dialog/Text document.odt -------------------------------------------------------------------------------- /resource/screenshot/Macros_embed_all.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kelsa-pi/unodit/HEAD/resource/screenshot/Macros_embed_all.png -------------------------------------------------------------------------------- /resource/screenshot/Macros_script_all.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kelsa-pi/unodit/HEAD/resource/screenshot/Macros_script_all.png -------------------------------------------------------------------------------- /resource/simpe_dialogs/FolderPathBox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kelsa-pi/unodit/HEAD/resource/simpe_dialogs/FolderPathBox.png -------------------------------------------------------------------------------- /templates/sidebar_convert_ext/9_icon1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kelsa-pi/unodit/HEAD/templates/sidebar_convert_ext/9_icon1.png -------------------------------------------------------------------------------- /templates/sidebar_convert_ext/9_icon2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kelsa-pi/unodit/HEAD/templates/sidebar_convert_ext/9_icon2.png -------------------------------------------------------------------------------- /templates/sidebar_convert_ext/9_icon3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kelsa-pi/unodit/HEAD/templates/sidebar_convert_ext/9_icon3.png -------------------------------------------------------------------------------- /examples/convert dialog/Test_convert_Devel.oxt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kelsa-pi/unodit/HEAD/examples/convert dialog/Test_convert_Devel.oxt -------------------------------------------------------------------------------- /examples/embed dialog/Text document_MACRO.odt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kelsa-pi/unodit/HEAD/examples/embed dialog/Text document_MACRO.odt -------------------------------------------------------------------------------- /examples/simple dialogs/Test_dialogs_Devel.oxt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kelsa-pi/unodit/HEAD/examples/simple dialogs/Test_dialogs_Devel.oxt -------------------------------------------------------------------------------- /resource/screenshot/Macros_simple_dialogs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kelsa-pi/unodit/HEAD/resource/screenshot/Macros_simple_dialogs.png -------------------------------------------------------------------------------- /templates/connect/4_event_action.txt: -------------------------------------------------------------------------------- 1 | 2 | if oActionEvent.ActionCommand == "${CONTROL_NAME}_OnClick": 3 | self.${CONTROL_NAME}_OnClick() 4 | -------------------------------------------------------------------------------- /templates/convert/7_event_action.txt: -------------------------------------------------------------------------------- 1 | 2 | if oActionEvent.ActionCommand == '${CONTROL_NAME}_OnClick': 3 | self.${CONTROL_NAME}_OnClick() 4 | -------------------------------------------------------------------------------- /templates/embeded/7_event_action.txt: -------------------------------------------------------------------------------- 1 | 2 | if oActionEvent.ActionCommand == '${CONTROL_NAME}_OnClick': 3 | self.${CONTROL_NAME}_OnClick() 4 | -------------------------------------------------------------------------------- /templates/sidebar_convert/7_event_action.txt: -------------------------------------------------------------------------------- 1 | 2 | if oActionEvent.ActionCommand == '${CONTROL_NAME}_OnClick': 3 | self.${CONTROL_NAME}_OnClick() 4 | -------------------------------------------------------------------------------- /templates/convert/5_control_insert.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | # inserts the control model into the dialog model 4 | self.DialogModel.insertByName("${CONTROL_NAME}", self.${CONTROL_NAME}) 5 | -------------------------------------------------------------------------------- /templates/embeded/5_control_insert.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | # inserts the control model into the dialog model 4 | self.DialogModel.insertByName("${CONTROL_NAME}", self.${CONTROL_NAME}) 5 | -------------------------------------------------------------------------------- /templates/sidebar_convert/5_control_insert.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | # inserts the control model into the dialog model 4 | self.DialogModel.insertByName("${CONTROL_NAME}", self.${CONTROL_NAME}) 5 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /templates/script_ext/4_description_en.txt: -------------------------------------------------------------------------------- 1 | Script description Script description Script description 2 | Script description Script description Script description 3 | Script description Script description Script description 4 | -------------------------------------------------------------------------------- /examples/convert dialog/description/description.txt: -------------------------------------------------------------------------------- 1 | Script description Script description Script description 2 | Script description Script description Script description 3 | Script description Script description Script description 4 | -------------------------------------------------------------------------------- /examples/simple dialogs/description/description.txt: -------------------------------------------------------------------------------- 1 | Script description Script description Script description 2 | Script description Script description Script description 3 | Script description Script description Script description 4 | -------------------------------------------------------------------------------- /templates/connect/3_control_event.txt: -------------------------------------------------------------------------------- 1 | self.DialogContainer.getControl("${CONTROL_NAME}").addActionListener(self) 2 | self.DialogContainer.getControl("${CONTROL_NAME}").setActionCommand("${CONTROL_NAME}_OnClick") 3 | 4 | -------------------------------------------------------------------------------- /templates/sidebar_convert_ext/4_description_en.txt: -------------------------------------------------------------------------------- 1 | Sidebar description Sidebar description Sidebar description 2 | Sidebar description Sidebar description Sidebar description 3 | Sidebar description Sidebar description Sidebar description 4 | -------------------------------------------------------------------------------- /templates/convert/3_control_model.txt: -------------------------------------------------------------------------------- 1 | 2 | # --------- create an instance of ${UNOCONTROL} control, set properties --- 3 | self.${CONTROL_NAME} = self.DialogModel.createInstance("com.sun.star.awt.UnoControl${UNOCONTROL}Model") 4 | -------------------------------------------------------------------------------- /templates/embeded/3_control_model.txt: -------------------------------------------------------------------------------- 1 | 2 | # --------- create an instance of ${UNOCONTROL} control, set properties --- 3 | self.${CONTROL_NAME} = self.DialogModel.createInstance("com.sun.star.awt.UnoControl${UNOCONTROL}Model") 4 | -------------------------------------------------------------------------------- /templates/sidebar_convert/3_control_model.txt: -------------------------------------------------------------------------------- 1 | 2 | # --------- create an instance of ${UNOCONTROL} control, set properties --- 3 | self.${CONTROL_NAME} = self.DialogModel.createInstance("com.sun.star.awt.UnoControl${UNOCONTROL}Model") 4 | -------------------------------------------------------------------------------- /templates/convert/11_event_callbacks.txt: -------------------------------------------------------------------------------- 1 | 2 | def ${CONTROL_NAME}_OnClick(self): 3 | self.DialogModel.Title = "It's Alive! - ${CONTROL_NAME}" 4 | self.messageBox("It's Alive! - ${CONTROL_NAME}", "Event: OnClick", INFOBOX) 5 | # TODO: not implemented 6 | -------------------------------------------------------------------------------- /templates/convert/6_control_event_action.txt: -------------------------------------------------------------------------------- 1 | 2 | # add the action listener 3 | self.DialogContainer.getControl('${CONTROL_NAME}').addActionListener(self) 4 | self.DialogContainer.getControl('${CONTROL_NAME}').setActionCommand('${CONTROL_NAME}_OnClick') 5 | -------------------------------------------------------------------------------- /templates/embeded/11_event_callbacks.txt: -------------------------------------------------------------------------------- 1 | 2 | def ${CONTROL_NAME}_OnClick(self): 3 | self.DialogModel.Title = "It's Alive! - ${CONTROL_NAME}" 4 | self.messageBox("It's Alive! - ${CONTROL_NAME}", "Event: OnClick", INFOBOX) 5 | # TODO: not implemented 6 | -------------------------------------------------------------------------------- /templates/embeded/6_control_event_action.txt: -------------------------------------------------------------------------------- 1 | 2 | # add the action listener 3 | self.DialogContainer.getControl('${CONTROL_NAME}').addActionListener(self) 4 | self.DialogContainer.getControl('${CONTROL_NAME}').setActionCommand('${CONTROL_NAME}_OnClick') 5 | -------------------------------------------------------------------------------- /templates/connect/5_event_action_callbaks.txt: -------------------------------------------------------------------------------- 1 | 2 | def ${CONTROL_NAME}_OnClick(self): 3 | self.DialogContainer.Title = "It's Alive! - ${CONTROL_NAME}" 4 | self.messageBox("It's Alive! - ${CONTROL_NAME}", "Event: OnClick", INFOBOX) 5 | # TODO: not implemented 6 | -------------------------------------------------------------------------------- /templates/sidebar_convert/11_event_callbacks.txt: -------------------------------------------------------------------------------- 1 | 2 | def ${CONTROL_NAME}_OnClick(self): 3 | self.DialogModel.Title = "It's Alive! - ${CONTROL_NAME}" 4 | self.messageBox("It's Alive! - ${CONTROL_NAME}", "Event: OnClick", INFOBOX) 5 | # TODO: not implemented 6 | -------------------------------------------------------------------------------- /templates/sidebar_convert/6_control_event_action.txt: -------------------------------------------------------------------------------- 1 | 2 | # add the action listener 3 | self.DialogContainer.getControl('${CONTROL_NAME}').addActionListener(self) 4 | self.DialogContainer.getControl('${CONTROL_NAME}').setActionCommand('${CONTROL_NAME}_OnClick') 5 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /templates/sidebar_convert/101_sidebar_show_panels.txt: -------------------------------------------------------------------------------- 1 | if url == 'private:resource/toolpanel/${EXTENSION_IDENTIFIER_APP}/${PANEL_NAME}': 2 | 3 | pos_y = 20 4 | 5 | app = ${PANEL_NAME}(context=ctx, dialog=panelWin) 6 | app.showDialog() 7 | panel_height = app.getHeight() 8 | 9 | return panel_height + pos_y 10 | 11 | -------------------------------------------------------------------------------- /templates/sidebar_convert/102_show_menu_command.txt: -------------------------------------------------------------------------------- 1 | if featureURL.Path == '${PANEL_NAME}': 2 | panel_option_name = '${PANEL_OPTION_NAME}' 3 | if panel_option_name: 4 | app = ${PANEL_OPTION_NAME}(ctx, dialog) 5 | app.showDialog() 6 | else: 7 | messageBox(featureURL.Path, 'DefaultMenuCommand', MsgType=MESSAGEBOX, MsgButtons=BUTTONS_OK) 8 | 9 | -------------------------------------------------------------------------------- /resource/xdl/empty_dialog.xdl: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/unodit.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 14 | -------------------------------------------------------------------------------- /templates/sidebar_convert_ext/7_ProtocolHandler.xcu: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 10 | 11 | ${EXTENSION_IDENTIFIER_DOMAIN}:* 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /templates/sidebar_convert_ext/8_empty_dialog.xdl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 13 | 14 | -------------------------------------------------------------------------------- /templates/sidebar_convert_ext/1_manifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 11 | 12 | 15 | 16 | 19 | 20 | 21 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /templates/sidebar_convert_ext/6_Factory.xcu: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 10 | 11 | 12 | 13 | toolpanel 14 | 15 | 16 | ${EXTENSION_IDENTIFIER_APP} 17 | 18 | 19 | 20 | 21 | 22 | ${EXTENSION_IDENTIFIER_DOMAIN}.${EXTENSION_IDENTIFIER_APP} 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /resource/xdl/text_dialog.xdl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /resource/xdl/option_dialog.xdl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /templates/sidebar_convert_ext/11_sidebar_panels.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ${PANEL_TITLE} 5 | 6 | 7 | Panel_${PANEL_ID} 8 | 9 | 10 | ${DECK_ID} 11 | 12 | 13 | 14 | ${PANEL_CONTEXT} 15 | 16 | 17 | 18 | private:resource/toolpanel/${EXTENSION_IDENTIFIER_APP}/${PANEL_NAME} 19 | 20 | 21 | ${PANEL_ORDER_INDEX} 22 | 23 | 24 | false 25 | 26 | 27 | ${EXTENSION_IDENTIFIER_DOMAIN}:${PANEL_NAME} 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /resource/xdl/list_dialog.xdl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /templates/sidebar_convert_ext/10_Sidebar.xcu: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 12 | 13 | 14 | ${DECK_TITLE} 15 | 16 | 17 | true 18 | 19 | 20 | ${DECK_ID} 21 | 22 | 23 | vnd.sun.star.extension://${EXTENSION_IDENTIFIER_DOMAIN}.${EXTENSION_IDENTIFIER_APP}/${SIDEBAR_ICON_DIR}/${SIDEBAR_ICON} 24 | 25 | 26 | 27 | ${SIDEBAR_CONTEXT} 28 | 29 | 30 | 31 | 32 | 33 | 34 | ${SIDEBAR_PANELS} 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /examples/convert dialog/Addons.xcu: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | Test_convert 22 | 23 | 24 | 29 | 30 | 31 | vnd.sun.star.script:Test_convert_Devel.oxt|src|Test_convert.py$Run_Test_convert?language=Python&location=user:uno_packages 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /examples/simple dialogs/Addons.xcu: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | Test_dialogs 22 | 23 | 24 | 29 | 30 | 31 | vnd.sun.star.script:Test_dialogs_Devel.oxt|src|Test_dialogs.py$Run_Test_dialogs?language=Python&location=user:uno_packages 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /templates/script_ext/6_Addons.xcu: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | ${TITLE} 22 | 23 | 24 | 29 | 30 | 31 | vnd.sun.star.script:${OXT_NAME}|${SOURCE}|${EXEC_FILE_NAME}$$${EXEC_FUNCTION}?language=Python&location=${INSTALL} 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /examples/convert dialog/META-INF/manifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 14 | 15 | 22 | 23 | 25 | 27 | 28 | 32 | 33 | 34 | 36 | 37 | 38 | 39 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /examples/simple dialogs/META-INF/manifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 14 | 15 | 22 | 23 | 25 | 27 | 28 | 32 | 33 | 34 | 36 | 37 | 38 | 39 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /templates/script_ext/1_manifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 14 | 15 | 22 | 23 | 25 | 27 | 28 | 32 | 33 | 34 | 36 | 37 | 38 | 39 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /templates/convert/1_main_ui.txt: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | #!/usr/bin/env python 3 | 4 | # ============================================================================= 5 | # 6 | # Dialog implementation generated from a XDL file. 7 | # 8 | # Created: ${GENERATED_DATETIME} 9 | # by: ${UNODIT_VERSION} 10 | # 11 | # WARNING! All changes made in this file will be overwritten 12 | # if the file is generated again! 13 | # 14 | # ============================================================================= 15 | 16 | import uno 17 | import unohelper 18 | from com.sun.star.awt import XActionListener 19 | from com.sun.star.task import XJobExecutor 20 | 21 | 22 | class ${APP_NAME}_UI(unohelper.Base, XActionListener, XJobExecutor): 23 | """ 24 | Class documentation...AAAAAAAAAAAAAAAAAAAAAAA 25 | """ 26 | def __init__(self, ctx=uno.getComponentContext()): 27 | self.LocalContext = ctx 28 | self.ServiceManager = self.LocalContext.ServiceManager 29 | self.Toolkit = self.ServiceManager.createInstanceWithContext("com.sun.star.awt.ExtToolkit", self.LocalContext) 30 | 31 | # ----------------------------------------------------------- 32 | # Create dialog and insert controls 33 | # ----------------------------------------------------------- 34 | 35 | # --------------create dialog container and set model and properties 36 | self.DialogContainer = self.ServiceManager.createInstanceWithContext("com.sun.star.awt.UnoControlDialog", self.LocalContext) 37 | self.DialogModel = self.ServiceManager.createInstance("com.sun.star.awt.UnoControlDialogModel") 38 | self.DialogContainer.setModel(self.DialogModel) 39 | 40 | ${GEN_DIALOG_PROPERTIES} 41 | ${GEN_CONTROLS} 42 | # ----------------------------------------------------------- 43 | # Action events 44 | # ----------------------------------------------------------- 45 | 46 | def actionPerformed(self, oActionEvent): 47 | ${GEN_ACTIONS_EVENTS} 48 | 49 | # ----------------- END GENERATED CODE ---------------------------------------- -------------------------------------------------------------------------------- /pythonpath/config.py: -------------------------------------------------------------------------------- 1 | # This file is part of UNO Dialog Tools - UNODIT 2 | # Copyright © 2016-2019 Sasa Kelecevic 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with UNODIT. If not, see 16 | 17 | """ 18 | UNODIT configuration module. 19 | 20 | """ 21 | 22 | 23 | import configparser 24 | import time 25 | import os 26 | 27 | full_path = os.path.dirname(__file__) 28 | path, ldir = os.path.split(full_path) 29 | 30 | 31 | class ReadINI(object): 32 | """ 33 | Read ini file 34 | """ 35 | 36 | def __init__(self, *dir_paths): 37 | self.config = configparser.ConfigParser() 38 | self.config.optionxform = str 39 | # section_names = [] 40 | for d in dir_paths: 41 | f = os.path.join(d, "config.ini") 42 | # print(f) 43 | if os.path.exists(f): 44 | self.config.read(f) 45 | # TODO log paths 46 | 47 | def get(self, section_name, prop_name): 48 | if section_name not in self.config.sections(): # we don't want KeyError 49 | return None # just return None if not found 50 | 51 | return self.config.get(section_name, prop_name) 52 | 53 | 54 | # GENERAL 55 | # ================= 56 | 57 | # library version 58 | VERSION = "unodit 0.8.0" 59 | 60 | # creation time 61 | NOW = time.strftime("%c") 62 | 63 | # LOGGING 64 | # ================= 65 | 66 | # logger name 67 | LOGGER_NAME = "unodit" 68 | 69 | # log file 70 | LOG_FILE = "log.log" 71 | 72 | # DIRECTORIES 73 | # ================= 74 | 75 | # unodit dir 76 | MAIN_DIR = path 77 | 78 | # templates dir 79 | TEMPLATES_DIR = os.path.join(MAIN_DIR, "templates") 80 | 81 | # pythopath directory - do not change! 82 | IMPORT_DIR = "pythonpath" 83 | -------------------------------------------------------------------------------- /examples/simple dialogs/src/Test_dialogs.py: -------------------------------------------------------------------------------- 1 | from simple_dialogs import SelectBox, OptionBox, TextBox, NumberBox, DateBox, FolderPathBox, FilePathBox, MessageBox, ActionBox 2 | 3 | def xray(myObject): 4 | try: 5 | sm = uno.getComponentContext().ServiceManager 6 | mspf = sm.createInstanceWithContext("com.sun.star.script.provider.MasterScriptProviderFactory", uno.getComponentContext()) 7 | scriptPro = mspf.createScriptProvider("") 8 | xScript = scriptPro.getScript("vnd.sun.star.script:XrayTool._Main.Xray?language=Basic&location=application") 9 | xScript.invoke((myObject,), (), ()) 10 | return 11 | except: 12 | raise _rtex("Basic library Xray is not installed", uno.getComponentContext()) 13 | 14 | 15 | def Run_Test_dialogs(*args): 16 | 17 | # SelectBox(message="Select one item", title="SelectBox", choices=['a','b','c']) 18 | # s = SelectBox(message="Select your favorite city", title="My choice", choices=["New York","London", "Paris", "Berlin"]) 19 | # print(s) 20 | 21 | # OptionBox(message="Select multiple items", title="OptionBox", choices=['a','b','c']) 22 | # o = OptionBox(message="Select one or multiple cities", title="My choices", choices=["New York","London", "Paris", "Berlin"]) 23 | # print(o) 24 | 25 | # TextBox(message="Enter your input", title="TextBox", text="") 26 | # t = TextBox(message="Enter your e-mail address", title="E-mail") 27 | # print(t) 28 | 29 | # NumberBox(message="Enter a number", title="NumberBox", default_value=0, min_=-10000, max_=10000, decimals=0) 30 | # n = NumberBox(message="Year", title="Year of birth", default_value=1999, min_=1950, max_=2020, decimals=0) 31 | # print(n) 32 | 33 | # DateBox(message="Choose a date", title='DateBox') 34 | # d = DateBox(message="Date of birth", title="BirthDay") 35 | # print(d) 36 | 37 | # FolderPathBox(title='Get directory path') 38 | # fop = FolderPathBox(title='Get directory path') 39 | # print(fop) 40 | 41 | # FilePathBox(title='Get file path') 42 | # fip = FilePathBox(title='Get file path') 43 | # print(fip) 44 | 45 | # MessageBox(message="Message", title="MessageBox") 46 | # m = MessageBox(message="Message to you Message to you Message to you Message to you Message to you Message to you", title="MessageBox") 47 | # print(m) 48 | 49 | # ActionBox(message="Message", title="ActionBox") 50 | a = ActionBox(message="What's Your Decision?", title="ActionBox") 51 | print(a) 52 | 53 | 54 | g_exportedScripts = Run_Test_dialogs, 55 | -------------------------------------------------------------------------------- /templates/sidebar_convert/1_main_ui.txt: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | #!/usr/bin/env python 3 | 4 | # ============================================================================= 5 | # 6 | # Dialog implementation generated from a XDL file. 7 | # 8 | # Created: ${GENERATED_DATETIME} 9 | # by: ${UNODIT_VERSION} 10 | # 11 | # WARNING! All changes made in this file will be overwritten 12 | # if the file is generated again! 13 | # 14 | # ============================================================================= 15 | 16 | import uno 17 | import unohelper 18 | from com.sun.star.awt import XActionListener 19 | from com.sun.star.awt import XWindowListener 20 | from com.sun.star.task import XJobExecutor 21 | 22 | 23 | class ${APP_NAME}_UI(unohelper.Base, XActionListener, XWindowListener, XJobExecutor): 24 | """ 25 | Class documentation... 26 | """ 27 | def __init__(self, ctx=uno.getComponentContext(), dialog=None): 28 | self.LocalContext = ctx 29 | self.dlg = dialog 30 | self.ServiceManager = self.LocalContext.ServiceManager 31 | self.Toolkit = self.ServiceManager.createInstanceWithContext("com.sun.star.awt.ExtToolkit", self.LocalContext) 32 | 33 | # ----------------------------------------------------------- 34 | # Create dialog and insert controls 35 | # ----------------------------------------------------------- 36 | 37 | # --------------create dialog container and set model and properties 38 | self.DialogContainer = self.dlg 39 | self.DialogModel = self.ServiceManager.createInstance("com.sun.star.awt.UnoControlDialogModel") 40 | self.DialogContainer.setModel(self.DialogModel) 41 | ${GEN_DIALOG_PROPERTIES} 42 | ${GEN_CONTROLS} 43 | 44 | # add the window listener 45 | self.DialogContainer.addWindowListener(self) 46 | 47 | # ----------------------------------------------------------- 48 | # Action events 49 | # ----------------------------------------------------------- 50 | 51 | def actionPerformed(self, oActionEvent): 52 | ${GEN_ACTIONS_EVENTS} 53 | 54 | # ----------------------------------------------------------- 55 | # Window (dialog/panel) events 56 | # ----------------------------------------------------------- 57 | 58 | def windowResized(self, oWindowEvent): 59 | # print(dir(oWindowEvent.Source)) 60 | self.resizeControls(dialog=oWindowEvent.Source) 61 | 62 | # ----------------- END GENERATED CODE ---------------------------------------- 63 | -------------------------------------------------------------------------------- /examples/convert dialog/description.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 16 | 17 | 18 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | PublisherName 30 | 31 | 32 | 38 | 39 | 44 | 45 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 60 | 61 | 62 | Test_convert 63 | 64 | 65 | 73 | 74 | 78 | 79 | 80 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /examples/simple dialogs/description.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 16 | 17 | 18 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | PublisherName 30 | 31 | 32 | 38 | 39 | 44 | 45 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 60 | 61 | 62 | Test_dialogs 63 | 64 | 65 | 73 | 74 | 78 | 79 | 80 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /templates/sidebar_convert_ext/2_description.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 16 | 17 | 18 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | ${EXTENSION_PUBLISHER} 30 | 31 | 32 | 38 | 39 | 44 | 45 | 55 | 56 | 61 | 62 | 63 | ${DISPLAY_NAME} 64 | 65 | 66 | 74 | 75 | 79 | 80 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /templates/script_ext/2_description.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 16 | 17 | 18 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | ${EXTENSION_PUBLISHER} 30 | 31 | 32 | 38 | 39 | 44 | 45 | 55 | 56 | 61 | 62 | 63 | ${DISPLAY_NAME} 64 | 65 | 66 | 74 | 75 | 79 | 80 | 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /templates/script_ext/7_Addons_submenu.xcu: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | ${TITLE} 26 | 27 | 28 | 29 | 30 | com.sun.star.text.TextDocument 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | ${TITLE} Submenu 45 | 46 | 47 | 52 | 53 | vnd.sun.star.script:Test_controls.oxt|${SOURCE}|${EXEC_FILE_NAME}$$${EXEC_FUNCTION}?language=Python&location=user:uno_packages 54 | 55 | 56 | 57 | _self 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /examples/convert dialog/src/Test_convert.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | #!/usr/bin/env python 3 | 4 | import uno 5 | from com.sun.star.awt.MessageBoxButtons import BUTTONS_OK, BUTTONS_OK_CANCEL, BUTTONS_YES_NO, BUTTONS_YES_NO_CANCEL, BUTTONS_RETRY_CANCEL, BUTTONS_ABORT_IGNORE_RETRY 6 | from com.sun.star.awt.MessageBoxButtons import DEFAULT_BUTTON_OK, DEFAULT_BUTTON_CANCEL, DEFAULT_BUTTON_RETRY, DEFAULT_BUTTON_YES, DEFAULT_BUTTON_NO, DEFAULT_BUTTON_IGNORE 7 | from com.sun.star.awt.MessageBoxType import MESSAGEBOX, INFOBOX, WARNINGBOX, ERRORBOX, QUERYBOX 8 | 9 | from Test_convert_UI import Test_convert_UI 10 | 11 | 12 | # ----------------- helper code for API_inspector tool MRI ---------- 13 | # def mri(ctx, target): 14 | # mri = ctx.ServiceManager.createInstanceWithContext("mytools.Mri", ctx) 15 | # mri.inspect(target) 16 | # ------------------------------------------------------------------- 17 | 18 | 19 | class Test_convert(Test_convert_UI): 20 | """ 21 | Class documentation... 22 | """ 23 | def __init__(self): 24 | Test_convert_UI.__init__(self) 25 | 26 | # --------- my code --------------------- 27 | self.DialogModel.Title = "Test_convert" 28 | # mri(self.LocalContext, self.DialogContainer) 29 | 30 | def myFunction(self): 31 | # TODO: not implemented 32 | pass 33 | 34 | # --------- helpers --------------------- 35 | 36 | def messageBox(self, MsgText, MsgTitle, MsgType=MESSAGEBOX, MsgButtons=BUTTONS_OK): 37 | sm = self.LocalContext.ServiceManager 38 | si = sm.createInstanceWithContext("com.sun.star.awt.Toolkit", self.LocalContext) 39 | mBox = si.createMessageBox(self.Toolkit, MsgType, MsgButtons, MsgTitle, MsgText) 40 | mBox.execute() 41 | 42 | # ----------------------------------------------------------- 43 | # Execute dialog 44 | # ----------------------------------------------------------- 45 | 46 | def showDialog(self): 47 | self.DialogContainer.setVisible(True) 48 | self.DialogContainer.createPeer(self.Toolkit, None) 49 | self.DialogContainer.execute() 50 | 51 | # ----------------------------------------------------------- 52 | # Action events 53 | # ----------------------------------------------------------- 54 | 55 | 56 | def CommandButton3_OnClick(self): 57 | self.DialogModel.Title = "It's Alive! - CommandButton3" 58 | self.messageBox("It's Alive! - CommandButton3", "Event: OnClick", INFOBOX) 59 | # TODO: not implemented 60 | 61 | def CommandButton1_OnClick(self): 62 | self.DialogModel.Title = "It's Alive! - CommandButton1" 63 | self.messageBox("It's Alive! - CommandButton1", "Event: OnClick", INFOBOX) 64 | # TODO: not implemented 65 | 66 | def CommandButton2_OnClick(self): 67 | self.DialogModel.Title = "It's Alive! - CommandButton2" 68 | self.messageBox("It's Alive! - CommandButton2", "Event: OnClick", INFOBOX) 69 | # TODO: not implemented 70 | 71 | 72 | 73 | def Run_Test_convert(*args): 74 | app = Test_convert() 75 | app.showDialog() 76 | 77 | g_exportedScripts = Run_Test_convert, 78 | -------------------------------------------------------------------------------- /pythonpath/simple_dialogs.py: -------------------------------------------------------------------------------- 1 | # This file is part of UNO Dialog Tools - UNODIT 2 | # Copyright © 2016-2019 Sasa Kelecevic 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with UNODIT. If not, see 16 | 17 | """ 18 | Provides a simple dialog boxes for interaction with a user: 19 | 20 | - make choices (SelectBox, OptionBox) 21 | - enter new data (TextBox, NumberBox, DateBox) 22 | - get paths (FolderPathBox, FilePathBox) 23 | - show information (MessageBox) 24 | - make a decision (ActionBox) 25 | 26 | """ 27 | 28 | import os 29 | import string 30 | import logging 31 | 32 | try: 33 | import config as conf 34 | except ImportError: 35 | import pythonpath.config as conf 36 | 37 | 38 | class EasyDialog: 39 | def __init__(self, pydir, app="MyApp", indent=4): 40 | self.pydir = pydir 41 | self.app = app 42 | self.code = {} 43 | self.config = conf.ReadINI(conf.MAIN_DIR, self.pydir) 44 | self.ext_tmpl_dir = os.path.join(conf.TEMPLATES_DIR, "dialogs") 45 | self.logger = logging.getLogger("unodit.simple_dialogs.EasyDialog") 46 | self.logger.info("NEW LOGGER: unodit.simple_dialogs.EasyDialog") 47 | 48 | if indent == 0: 49 | self.indent = "\t" 50 | else: 51 | self.indent = indent * " " 52 | 53 | def get_template(self, ex_tmpl_dir, template): 54 | templ = os.path.join(ex_tmpl_dir, template) 55 | with open(templ, "rt") as t: 56 | tt = t.read() 57 | return tt 58 | 59 | def create_template(self): 60 | # ui file 61 | d = os.path.join( 62 | self.pydir, 63 | self.config.get("directories", "source_dir"), 64 | "pythonpath", 65 | ) 66 | if not os.path.exists(d): 67 | os.makedirs(d) 68 | 69 | s = { 70 | "I": self.indent, 71 | "GENERATED_DATETIME": conf.NOW, 72 | "UNODIT_VERSION": conf.VERSION, 73 | } 74 | 75 | f = os.path.join(d, "simple_dialogs.py") 76 | t = string.Template( 77 | self.get_template(self.ext_tmpl_dir, "1_dialogs_ui.txt") 78 | ) 79 | ext_text = t.substitute(s) 80 | self.logger.info("simple dialogs file " + f + " " + str(s)) 81 | 82 | ef = open(f, "w") 83 | ef.write(ext_text) 84 | ef.close() 85 | 86 | # exec file 87 | d = os.path.join( 88 | self.pydir, self.config.get("directories", "source_dir") 89 | ) 90 | if not os.path.exists(d): 91 | os.makedirs(d) 92 | 93 | s = { 94 | "I": self.indent, 95 | "APP_NAME": self.app, 96 | "EXEC_FUNCTION_PREFIX": self.config.get("exec_function", "prefix"), 97 | } 98 | 99 | f = os.path.join(d, self.app + ".py") 100 | t = string.Template( 101 | self.get_template(self.ext_tmpl_dir, "2_dialogs_main.txt") 102 | ) 103 | ext_text = t.substitute(s) 104 | self.logger.info("application file " + f + " " + str(s)) 105 | 106 | ef = open(f, "w") 107 | ef.write(ext_text) 108 | ef.close() 109 | -------------------------------------------------------------------------------- /templates/dialogs/2_dialogs_main.txt: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | #!/usr/bin/env python 3 | 4 | import uno 5 | 6 | try: 7 | from simple_dialogs import SelectBox, OptionBox, TextBox, NumberBox, DateBox, FolderPathBox, FilePathBox, MessageBox, ActionBox 8 | except: 9 | from pythonpath.simple_dialogs import SelectBox, OptionBox, TextBox, NumberBox, DateBox, FolderPathBox, FilePathBox, MessageBox, ActionBox 10 | 11 | 12 | # ------------------------------------- 13 | # HELPERS FOR MRI AND XRAY 14 | # ------------------------------------- 15 | 16 | # Uncomment for MRI 17 | # def mri(ctx, target): 18 | # mri = ctx.ServiceManager.createInstanceWithContext("mytools.Mri", ctx) 19 | # mri.inspect(target) 20 | 21 | # Uncomment for Xray 22 | # def xray(myObject): 23 | # try: 24 | # sm = uno.getComponentContext().ServiceManager 25 | # mspf = sm.createInstanceWithContext("com.sun.star.script.provider.MasterScriptProviderFactory", uno.getComponentContext()) 26 | # scriptPro = mspf.createScriptProvider("") 27 | # xScript = scriptPro.getScript("vnd.sun.star.script:XrayTool._Main.Xray?language=Basic&location=application") 28 | # xScript.invoke((myObject,), (), ()) 29 | # return 30 | # except: 31 | # raise _rtex("\nBasic library Xray is not installed", uno.getComponentContext()) 32 | # ------------------------------------------------------------------- 33 | 34 | 35 | def ${EXEC_FUNCTION_PREFIX}${APP_NAME}(*args): 36 | 37 | try: 38 | ctx = remote_ctx # IDE 39 | except: 40 | ctx = uno.getComponentContext() # UI 41 | 42 | # get desktop 43 | desktop = ctx.getByName("/singletons/com.sun.star.frame.theDesktop") 44 | 45 | # get document 46 | document = desktop.getCurrentComponent() 47 | 48 | # s = SelectBox(message="Select your favorite city", title="My choice", choices=["New York","London", "Paris", "Berlin"]) 49 | # print(s) 50 | 51 | # o = OptionBox(message="Select one or multiple cities", title="My choices", choices=["New York","London", "Paris", "Berlin"]) 52 | # print(o) 53 | 54 | # t = TextBox(message="Enter your e-mail address", title="E-mail") 55 | # print(t) 56 | 57 | # n = NumberBox(message="Year", title="Year of birth", default_value=1999, min_=1950, max_=2020, decimals=0) 58 | # print(n) 59 | 60 | # d = DateBox(message="Date of birth", title="BirthDay") 61 | # print(d) 62 | 63 | # fop = FolderPathBox(title='Get directory path') 64 | # print(fop) 65 | 66 | # fip = FilePathBox(title='Get file path') 67 | # print(fip) 68 | 69 | # m = MessageBox(message="Message to you Message to you Message to you Message to you Message to you Message to you", title="MessageBox") 70 | # print(m) 71 | 72 | a = ActionBox(message="What's Your Decision?", title="ActionBox") 73 | print(a) 74 | 75 | 76 | g_exportedScripts = ${EXEC_FUNCTION_PREFIX}${APP_NAME}, 77 | 78 | 79 | # ------------------------------------- 80 | # HELPER FOR AN IDE 81 | # ------------------------------------- 82 | 83 | if __name__ == "__main__": 84 | """ Connect to LibreOffice proccess. 85 | 1) Start the office in shell with command: 86 | soffice "--accept=socket,host=127.0.0.1,port=2002,tcpNoDelay=1;urp;StarOffice.ComponentContext" --norestore 87 | 2) Run script 88 | """ 89 | import os 90 | import sys 91 | 92 | sys.path.append(os.path.join(os.path.dirname(__file__), 'pythonpath')) 93 | 94 | local_ctx = uno.getComponentContext() 95 | resolver = local_ctx.ServiceManager.createInstance("com.sun.star.bridge.UnoUrlResolver") 96 | try: 97 | remote_ctx = resolver.resolve("uno:socket," 98 | "host=localhost," 99 | "port=2002," 100 | "tcpNoDelay=1;" 101 | "urp;" 102 | "StarOffice.ComponentContext") 103 | except Exception as err: 104 | print(err) 105 | 106 | ${EXEC_FUNCTION_PREFIX}${APP_NAME}() -------------------------------------------------------------------------------- /templates/convert/10_main.txt: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | #!/usr/bin/env python 3 | 4 | import uno 5 | from com.sun.star.awt.MessageBoxButtons import BUTTONS_OK, BUTTONS_OK_CANCEL, BUTTONS_YES_NO, BUTTONS_YES_NO_CANCEL, BUTTONS_RETRY_CANCEL, BUTTONS_ABORT_IGNORE_RETRY 6 | from com.sun.star.awt.MessageBoxButtons import DEFAULT_BUTTON_OK, DEFAULT_BUTTON_CANCEL, DEFAULT_BUTTON_RETRY, DEFAULT_BUTTON_YES, DEFAULT_BUTTON_NO, DEFAULT_BUTTON_IGNORE 7 | from com.sun.star.awt.MessageBoxType import MESSAGEBOX, INFOBOX, WARNINGBOX, ERRORBOX, QUERYBOX 8 | try: 9 | from ${APP_NAME}_UI import ${APP_NAME}_UI 10 | except: 11 | from pythonpath.${APP_NAME}_UI import ${APP_NAME}_UI 12 | 13 | 14 | # ------------------------------------- 15 | # HELPERS FOR MRI AND XRAY 16 | # ------------------------------------- 17 | 18 | # Uncomment for MRI 19 | # def mri(ctx, target): 20 | # mri = ctx.ServiceManager.createInstanceWithContext("mytools.Mri", ctx) 21 | # mri.inspect(target) 22 | 23 | # Uncomment for Xray 24 | # def xray(myObject): 25 | # try: 26 | # sm = uno.getComponentContext().ServiceManager 27 | # mspf = sm.createInstanceWithContext("com.sun.star.script.provider.MasterScriptProviderFactory", uno.getComponentContext()) 28 | # scriptPro = mspf.createScriptProvider("") 29 | # xScript = scriptPro.getScript("vnd.sun.star.script:XrayTool._Main.Xray?language=Basic&location=application") 30 | # xScript.invoke((myObject,), (), ()) 31 | # return 32 | # except: 33 | # raise _rtex("\nBasic library Xray is not installed", uno.getComponentContext()) 34 | # ------------------------------------------------------------------- 35 | 36 | 37 | class ${APP_NAME}(${APP_NAME}_UI): 38 | ''' 39 | Class documentation... 40 | ''' 41 | def __init__(self, ctx=uno.getComponentContext(), **kwargs): 42 | 43 | self.ctx = ctx 44 | ${APP_NAME}_UI.__init__(self, self.ctx) 45 | 46 | # for key, value in kwargs.items(): 47 | # if key == 'document': 48 | # self.document = value 49 | 50 | # --------- my code --------------------- 51 | 52 | self.DialogModel.Title = "${APP_NAME}" 53 | # mri(self.ctx, self.DialogContainer) 54 | 55 | def myFunction(self): 56 | # TODO: not implemented 57 | pass 58 | 59 | # --------- helpers --------------------- 60 | 61 | def messageBox(self, MsgText, MsgTitle, MsgType=MESSAGEBOX, MsgButtons=BUTTONS_OK): 62 | sm = self.ctx.ServiceManager 63 | si = sm.createInstanceWithContext("com.sun.star.awt.Toolkit", self.ctx) 64 | mBox = si.createMessageBox(self.Toolkit, MsgType, MsgButtons, MsgTitle, MsgText) 65 | mBox.execute() 66 | 67 | # ----------------------------------------------------------- 68 | # Execute dialog 69 | # ----------------------------------------------------------- 70 | 71 | def showDialog(self): 72 | self.DialogContainer.setVisible(True) 73 | self.DialogContainer.createPeer(self.Toolkit, None) 74 | self.DialogContainer.execute() 75 | 76 | # ----------------------------------------------------------- 77 | # Action events 78 | # ----------------------------------------------------------- 79 | ${GEN_ACTIONS_CALLBACKS} 80 | 81 | def ${EXEC_FUNCTION_PREFIX}${APP_NAME}(*args): 82 | 83 | try: 84 | ctx = remote_ctx # IDE 85 | except: 86 | ctx = uno.getComponentContext() # UI 87 | 88 | # get desktop 89 | desktop = ctx.getByName("/singletons/com.sun.star.frame.theDesktop") 90 | 91 | # get document 92 | document = desktop.getCurrentComponent() 93 | 94 | app = ${APP_NAME}(ctx=ctx) 95 | app.showDialog() 96 | 97 | 98 | # Execute macro from LibreOffice UI (Tools - Macro) 99 | g_exportedScripts = ${EXEC_FUNCTION_PREFIX}${APP_NAME}, 100 | 101 | 102 | # ------------------------------------- 103 | # HELPER FOR AN IDE 104 | # ------------------------------------- 105 | 106 | if __name__ == "__main__": 107 | """ Connect to LibreOffice proccess. 108 | 1) Start the office in shell with command: 109 | soffice "--accept=socket,host=127.0.0.1,port=2002,tcpNoDelay=1;urp;StarOffice.ComponentContext" --norestore 110 | 2) Run script 111 | """ 112 | import os 113 | import sys 114 | 115 | sys.path.append(os.path.join(os.path.dirname(__file__), 'pythonpath')) 116 | 117 | local_ctx = uno.getComponentContext() 118 | resolver = local_ctx.ServiceManager.createInstance("com.sun.star.bridge.UnoUrlResolver") 119 | try: 120 | remote_ctx = resolver.resolve("uno:socket," 121 | "host=127.0.0.1," 122 | "port=2002," 123 | "tcpNoDelay=1;" 124 | "urp;" 125 | "StarOffice.ComponentContext") 126 | except Exception as err: 127 | print(err) 128 | 129 | ${EXEC_FUNCTION_PREFIX}${APP_NAME}() 130 | -------------------------------------------------------------------------------- /pythonpath/embed_packer.py: -------------------------------------------------------------------------------- 1 | # This file is part of UNO Dialog Tools - UNODIT 2 | # Copyright © 2016-2019 Sasa Kelecevic 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with UNODIT. If not, see 16 | 17 | """ 18 | Convert dialog file .xdl to python code and embed in document. 19 | 20 | """ 21 | 22 | import zipfile 23 | import logging 24 | import os 25 | import shutil 26 | 27 | try: 28 | import config as conf 29 | except ImportError: 30 | import pythonpath.config as conf 31 | 32 | 33 | class EmbedScript: 34 | def __init__(self, pydir, app="MyApp"): 35 | self.pydir = pydir 36 | self.app = app 37 | self.language = "python" 38 | self.config = conf.ReadINI(conf.MAIN_DIR, self.pydir) 39 | self.logger = logging.getLogger("unodit.embed_packer.EmbedScript") 40 | self.logger.info("NEW LOGGER: unodit.embed_packer.EmbedScript") 41 | 42 | def extract_document(self, fname, dest): 43 | 44 | fh = open(fname, "rb") 45 | z = zipfile.ZipFile(fh) 46 | for name in z.namelist(): 47 | z.extract(name, dest) 48 | fh.close() 49 | 50 | def create_dirs(self, path): 51 | if not os.path.exists(path): 52 | os.makedirs(path) 53 | 54 | def new_manifest_text(self, folder, macro): 55 | proj_name_dir = "Scripts/python/" + folder + "/" 56 | new_line = "" 57 | for path in ["Scripts/", "Scripts/python/", proj_name_dir]: 58 | new_line += ( 59 | ' \n' 60 | % path 61 | ) 62 | 63 | p = proj_name_dir + macro 64 | new_line += ( 65 | ' \n' 66 | % p 67 | ) 68 | self.logger.info("edit manifest.xml " + new_line) 69 | return new_line 70 | 71 | def edit_manifest(self, mfs, newtext): 72 | doc = open(mfs, "r") 73 | dr = doc.read() 74 | newdoc = dr.replace("", newtext) 75 | doc.close() 76 | 77 | doc = open(mfs, "w") 78 | doc.write(newdoc) 79 | doc.write("") 80 | doc.close() 81 | 82 | def pack_script(self): 83 | 84 | extract_dir = os.path.join(self.pydir, "temp") 85 | new_dirs = os.path.join(extract_dir, "Scripts", "python", self.app) 86 | macro_src = os.path.join( 87 | self.pydir, 88 | self.config.get("directories", "source_dir"), 89 | self.app + ".py", 90 | ) 91 | macro_dest = os.path.join( 92 | extract_dir, "Scripts", "python", self.app, self.app + ".py" 93 | ) 94 | manifest_path = os.path.join(extract_dir, "META-INF", "manifest.xml") 95 | 96 | for file in os.listdir(self.pydir): 97 | if file.endswith((".odt", ".ods", ".odp", ".odg")): 98 | file_name = os.path.join(self.pydir, file) 99 | # extract document in extract dir 100 | self.extract_document(file_name, extract_dir) 101 | self.logger.info( 102 | "extracted " + file_name + " in temp dir " + extract_dir 103 | ) 104 | 105 | # create new scripts directories 106 | self.create_dirs(new_dirs) 107 | 108 | # copy macro 109 | shutil.copy(macro_src, macro_dest) 110 | 111 | # new manifest text 112 | new_mnf_dir = self.app 113 | new_mnf_macro = self.app + ".py" 114 | new_text = self.new_manifest_text(new_mnf_dir, new_mnf_macro) 115 | 116 | # edit manifest 117 | self.edit_manifest(manifest_path, new_text) 118 | 119 | # zip new file 120 | file_name_parts = file.split(".") 121 | new_odf = os.path.join( 122 | self.pydir, 123 | file_name_parts[0] + "_MACRO." + file_name_parts[1], 124 | ) 125 | self.logger.info("created new odt document " + new_odf) 126 | zf = zipfile.ZipFile(new_odf, "w", zipfile.ZIP_DEFLATED) 127 | 128 | for dirname, subdirs, files in os.walk(extract_dir): 129 | for filename in files: 130 | fullpath = os.path.join(dirname, filename) 131 | zippath = fullpath.replace(extract_dir, "") 132 | self.logger.info(fullpath + " " + zippath) 133 | zf.write(fullpath, zippath, zipfile.ZIP_DEFLATED) 134 | zf.close() 135 | 136 | # remove temp dir 137 | shutil.rmtree(extract_dir) 138 | self.logger.info("removed temp dir " + extract_dir) 139 | -------------------------------------------------------------------------------- /templates/embeded/1_main_ui.txt: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | #!/usr/bin/env python 3 | 4 | # ============================================================================= 5 | # 6 | # Dialog implementation generated from a XDL file. 7 | # 8 | # Created: ${GENERATED_DATETIME} 9 | # by: ${UNODIT_VERSION} 10 | # 11 | # WARNING! All changes made in this file will be overwritten 12 | # if the file is generated again! 13 | # 14 | # ============================================================================= 15 | 16 | import uno 17 | import unohelper 18 | from com.sun.star.awt import XActionListener 19 | from com.sun.star.task import XJobExecutor 20 | 21 | from com.sun.star.awt.MessageBoxButtons import BUTTONS_OK, BUTTONS_OK_CANCEL, BUTTONS_YES_NO, BUTTONS_YES_NO_CANCEL, BUTTONS_RETRY_CANCEL, BUTTONS_ABORT_IGNORE_RETRY 22 | from com.sun.star.awt.MessageBoxButtons import DEFAULT_BUTTON_OK, DEFAULT_BUTTON_CANCEL, DEFAULT_BUTTON_RETRY, DEFAULT_BUTTON_YES, DEFAULT_BUTTON_NO, DEFAULT_BUTTON_IGNORE 23 | from com.sun.star.awt.MessageBoxType import MESSAGEBOX, INFOBOX, WARNINGBOX, ERRORBOX, QUERYBOX 24 | 25 | # ------------------------------------- 26 | # HELPERS FOR MRI AND XRAY 27 | # ------------------------------------- 28 | 29 | # Uncomment for MRI 30 | # def mri(ctx, target): 31 | # mri = ctx.ServiceManager.createInstanceWithContext("mytools.Mri", ctx) 32 | # mri.inspect(target) 33 | 34 | # Uncomment for Xray 35 | # def xray(myObject): 36 | # try: 37 | # sm = uno.getComponentContext().ServiceManager 38 | # mspf = sm.createInstanceWithContext("com.sun.star.script.provider.MasterScriptProviderFactory", uno.getComponentContext()) 39 | # scriptPro = mspf.createScriptProvider("") 40 | # xScript = scriptPro.getScript("vnd.sun.star.script:XrayTool._Main.Xray?language=Basic&location=application") 41 | # xScript.invoke((myObject,), (), ()) 42 | # return 43 | # except: 44 | # raise _rtex("\nBasic library Xray is not installed", uno.getComponentContext()) 45 | # ------------------------------------------------------------------- 46 | 47 | 48 | class ${APP_NAME}(unohelper.Base, XActionListener, XJobExecutor): 49 | """ 50 | Class documentation... 51 | """ 52 | def __init__(self, ctx=uno.getComponentContext()): 53 | self.LocalContext = ctx 54 | self.ServiceManager = self.LocalContext.ServiceManager 55 | self.Toolkit = self.ServiceManager.createInstanceWithContext("com.sun.star.awt.ExtToolkit", self.LocalContext) 56 | 57 | # ----------------------------------------------------------- 58 | # Create dialog and insert controls 59 | # ----------------------------------------------------------- 60 | 61 | # --------------create dialog container and set model and properties 62 | self.DialogContainer = self.ServiceManager.createInstanceWithContext("com.sun.star.awt.UnoControlDialog", self.LocalContext) 63 | self.DialogModel = self.ServiceManager.createInstance("com.sun.star.awt.UnoControlDialogModel") 64 | self.DialogContainer.setModel(self.DialogModel) 65 | ${GEN_DIALOG_PROPERTIES} 66 | ${GEN_CONTROLS} 67 | def showDialog(self): 68 | self.DialogContainer.setVisible(True) 69 | self.DialogContainer.createPeer(self.Toolkit, None) 70 | self.DialogContainer.execute() 71 | 72 | # --------- functions ----------------------- 73 | 74 | def myFunction(self): 75 | # TODO: not implemented 76 | pass 77 | 78 | # --------- helpers ------------------------- 79 | 80 | def messageBox(self, MsgText, MsgTitle, MsgType=MESSAGEBOX, MsgButtons=BUTTONS_OK): 81 | sm = self.LocalContext.ServiceManager 82 | si = sm.createInstanceWithContext("com.sun.star.awt.Toolkit", self.LocalContext) 83 | mBox = si.createMessageBox(self.Toolkit, MsgType, MsgButtons, MsgTitle, MsgText) 84 | mBox.execute() 85 | 86 | # ----------------------------------------------------------- 87 | # Action events 88 | # ----------------------------------------------------------- 89 | 90 | def actionPerformed(self, oActionEvent): 91 | ${GEN_ACTIONS_EVENTS} 92 | ${GEN_CALLBAKS} 93 | 94 | def ${EXEC_FUNCTION_PREFIX}${APP_NAME}(*args): 95 | 96 | try: 97 | ctx = remote_ctx # IDE 98 | except: 99 | ctx = uno.getComponentContext() # UI 100 | 101 | # get desktop 102 | desktop = ctx.getByName("/singletons/com.sun.star.frame.theDesktop") 103 | 104 | # get document 105 | document = desktop.getCurrentComponent() 106 | 107 | app = ${APP_NAME}(ctx=ctx) 108 | app.showDialog() 109 | 110 | 111 | # Execute macro from LibreOffice UI (Tools - Macro) 112 | g_exportedScripts = ${EXEC_FUNCTION_PREFIX}${APP_NAME}, 113 | 114 | # ------------------------------------- 115 | # HELPER FOR AN IDE 116 | # ------------------------------------- 117 | 118 | if __name__ == "__main__": 119 | """ Connect to LibreOffice proccess. 120 | 1) Start the office in shell with command: 121 | soffice "--accept=socket,host=127.0.0.1,port=2002,tcpNoDelay=1;urp;StarOffice.ComponentContext" --norestore 122 | 2) Run script 123 | """ 124 | import os 125 | import sys 126 | 127 | sys.path.append(os.path.join(os.path.dirname(__file__), 'pythonpath')) 128 | 129 | local_ctx = uno.getComponentContext() 130 | resolver = local_ctx.ServiceManager.createInstance("com.sun.star.bridge.UnoUrlResolver") 131 | try: 132 | remote_ctx = resolver.resolve("uno:socket," 133 | "host=127.0.0.1," 134 | "port=2002," 135 | "tcpNoDelay=1;" 136 | "urp;" 137 | "StarOffice.ComponentContext") 138 | except Exception as err: 139 | print(err) 140 | 141 | ${EXEC_FUNCTION_PREFIX}${APP_NAME}() 142 | -------------------------------------------------------------------------------- /templates/connect/1_connect_main.txt: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # ============================================================================= 4 | # 5 | # Connect Python and XDL file. 6 | # 7 | # Created: ${GENERATED_DATETIME} 8 | # by: ${UNODIT_VERSION} 9 | # 10 | # WARNING! All changes made in this file will be overwritten 11 | # if the file is generated again! 12 | # 13 | # ============================================================================= 14 | 15 | import uno 16 | import unohelper 17 | from com.sun.star.awt import XActionListener 18 | from com.sun.star.task import XJobExecutor 19 | 20 | from com.sun.star.awt.MessageBoxButtons import BUTTONS_OK, BUTTONS_OK_CANCEL, BUTTONS_YES_NO, BUTTONS_YES_NO_CANCEL, BUTTONS_RETRY_CANCEL, BUTTONS_ABORT_IGNORE_RETRY 21 | from com.sun.star.awt.MessageBoxButtons import DEFAULT_BUTTON_OK, DEFAULT_BUTTON_CANCEL, DEFAULT_BUTTON_RETRY, DEFAULT_BUTTON_YES, DEFAULT_BUTTON_NO, DEFAULT_BUTTON_IGNORE 22 | from com.sun.star.awt.MessageBoxType import MESSAGEBOX, INFOBOX, WARNINGBOX, ERRORBOX, QUERYBOX 23 | 24 | # ------------------------------------- 25 | # HELPERS FOR MRI AND XRAY 26 | # ------------------------------------- 27 | 28 | # Uncomment for MRI 29 | # def mri(ctx, target): 30 | # mri = ctx.ServiceManager.createInstanceWithContext("mytools.Mri", ctx) 31 | # mri.inspect(target) 32 | 33 | # Uncomment for Xray 34 | # def xray(myObject): 35 | # try: 36 | # sm = uno.getComponentContext().ServiceManager 37 | # mspf = sm.createInstanceWithContext("com.sun.star.script.provider.MasterScriptProviderFactory", uno.getComponentContext()) 38 | # scriptPro = mspf.createScriptProvider("") 39 | # xScript = scriptPro.getScript("vnd.sun.star.script:XrayTool._Main.Xray?language=Basic&location=application") 40 | # xScript.invoke((myObject,), (), ()) 41 | # return 42 | # except: 43 | # raise _rtex("\nBasic library Xray is not installed", uno.getComponentContext()) 44 | # ------------------------------------------------------------------- 45 | 46 | 47 | class ${APP_NAME}_UI(unohelper.Base, XActionListener, XJobExecutor): 48 | """ 49 | Class documentation... 50 | """ 51 | def __init__(self, ctx=uno.getComponentContext()): 52 | self.LocalContext = ctx 53 | self.ServiceManager = self.LocalContext.ServiceManager 54 | self.Toolkit = self.ServiceManager.createInstanceWithContext("com.sun.star.awt.ExtToolkit", self.LocalContext) 55 | 56 | # --------------connect dialog container and set model -- 57 | 58 | dlg_path = "vnd.sun.star.script:${GEN_DIALOG_ADDRESS}?location=application" 59 | self.Dialog = self.ServiceManager.createInstanceWithContext("com.sun.star.awt.DialogProvider", self.LocalContext) 60 | self.DialogContainer = self.Dialog.createDialog(dlg_path) 61 | self.DialogModel = self.DialogContainer.getModel() 62 | 63 | # ------------- define all controls models -------------- 64 | 65 | ${GEN_ALL_CONTROLS} 66 | # ------------- add the action listener to buttons ------ 67 | 68 | ${GEN_ACTIONS_EVENTS} 69 | # --------- my code --------------------- 70 | self.DialogModel.Title = "${APP_NAME}" 71 | # mri(self.LocalContext, self.DialogContainer) 72 | 73 | # --------- functions ----------------------- 74 | 75 | def myFunction(self): 76 | # TODO: not implemented 77 | pass 78 | 79 | # --------- helpers ------------------------- 80 | 81 | def messageBox(self, MsgText, MsgTitle, MsgType=MESSAGEBOX, MsgButtons=BUTTONS_OK): 82 | sm = self.LocalContext.ServiceManager 83 | si = sm.createInstanceWithContext("com.sun.star.awt.Toolkit", self.LocalContext) 84 | mBox = si.createMessageBox(self.Toolkit, MsgType, MsgButtons, MsgTitle, MsgText) 85 | mBox.execute() 86 | 87 | # ----------------------------------------------------------- 88 | # Action events 89 | # ----------------------------------------------------------- 90 | 91 | def actionPerformed(self, oActionEvent): 92 | ${GEN_ACTIONS} 93 | 94 | ${GEN_CALLBAKS} 95 | 96 | def showDialog(self): 97 | self.DialogContainer.execute() 98 | 99 | 100 | def ${EXEC_FUNCTION_PREFIX}${APP_NAME}(*args): 101 | 102 | try: 103 | ctx = remote_ctx # IDE 104 | except: 105 | ctx = uno.getComponentContext() # UI 106 | 107 | # get desktop 108 | desktop = ctx.getByName("/singletons/com.sun.star.frame.theDesktop") 109 | 110 | # get document 111 | document = desktop.getCurrentComponent() 112 | 113 | app = ${APP_NAME}_UI(ctx=ctx) 114 | app.showDialog() 115 | 116 | # Execute macro from LibreOffice UI (Tools - Macro) 117 | g_exportedScripts = ${EXEC_FUNCTION_PREFIX}${APP_NAME}, 118 | 119 | # ------------------------------------- 120 | # HELPER FOR AN IDE 121 | # ------------------------------------- 122 | 123 | if __name__ == "__main__": 124 | """ Connect to LibreOffice proccess. 125 | 1) Start the office in shell with command: 126 | soffice "--accept=socket,host=127.0.0.1,port=2002,tcpNoDelay=1;urp;StarOffice.ComponentContext" --norestore 127 | 2) Run script 128 | """ 129 | import os 130 | import sys 131 | 132 | sys.path.append(os.path.join(os.path.dirname(__file__), 'pythonpath')) 133 | 134 | local_ctx = uno.getComponentContext() 135 | resolver = local_ctx.ServiceManager.createInstance("com.sun.star.bridge.UnoUrlResolver") 136 | try: 137 | remote_ctx = resolver.resolve("uno:socket," 138 | "host=127.0.0.1," 139 | "port=2002," 140 | "tcpNoDelay=1;" 141 | "urp;" 142 | "StarOffice.ComponentContext") 143 | except Exception as err: 144 | print(err) 145 | 146 | ${EXEC_FUNCTION_PREFIX}${APP_NAME}() 147 | 148 | # ----------------- END GENERATED CODE ---------------------------------------- 149 | -------------------------------------------------------------------------------- /resource/xdl/test_dialog.xdl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /templates/sidebar_convert/10_main.txt: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | #!/usr/bin/env python 3 | 4 | # ============================================================================= 5 | # 6 | # Write your code here 7 | # 8 | # ============================================================================= 9 | 10 | import uno 11 | from com.sun.star.awt.PosSize import POSSIZE 12 | from com.sun.star.awt.MessageBoxButtons import BUTTONS_OK, BUTTONS_OK_CANCEL, BUTTONS_YES_NO, BUTTONS_YES_NO_CANCEL, BUTTONS_RETRY_CANCEL, BUTTONS_ABORT_IGNORE_RETRY 13 | from com.sun.star.awt.MessageBoxButtons import DEFAULT_BUTTON_OK, DEFAULT_BUTTON_CANCEL, DEFAULT_BUTTON_RETRY, DEFAULT_BUTTON_YES, DEFAULT_BUTTON_NO, DEFAULT_BUTTON_IGNORE 14 | from com.sun.star.awt.MessageBoxType import MESSAGEBOX, INFOBOX, WARNINGBOX, ERRORBOX, QUERYBOX 15 | 16 | try: 17 | from ${UI_DIR}.${APP_NAME}_UI import ${APP_NAME}_UI 18 | except: 19 | from pythonpath.${UI_DIR}.${APP_NAME}_UI import ${APP_NAME}_UI 20 | 21 | # ------------------------------------- 22 | # HELPERS FOR MRI AND XRAY 23 | # ------------------------------------- 24 | 25 | # Uncomment for MRI 26 | # def mri(ctx, target): 27 | # mri = ctx.ServiceManager.createInstanceWithContext("mytools.Mri", ctx) 28 | # mri.inspect(target) 29 | 30 | # Uncomment for Xray 31 | # def xray(myObject): 32 | # try: 33 | # sm = uno.getComponentContext().ServiceManager 34 | # mspf = sm.createInstanceWithContext("com.sun.star.script.provider.MasterScriptProviderFactory", uno.getComponentContext()) 35 | # scriptPro = mspf.createScriptProvider("") 36 | # xScript = scriptPro.getScript("vnd.sun.star.script:XrayTool._Main.Xray?language=Basic&location=application") 37 | # xScript.invoke((myObject,), (), ()) 38 | # return 39 | # except: 40 | # raise _rtex("\nBasic library Xray is not installed", uno.getComponentContext()) 41 | # ------------------------------------------------------------------- 42 | 43 | 44 | class ${APP_NAME}(${APP_NAME}_UI): 45 | """ 46 | Class documentation... 47 | """ 48 | def __init__(self, ctx=uno.getComponentContext(), dialog=None, **kwargs): # (self, panelWin, context=uno.getComponentContext()): 49 | 50 | self.ctx = ctx 51 | self.dialog = dialog 52 | 53 | ${APP_NAME}_UI.__init__(self, ctx=self.ctx, dialog=self.dialog) 54 | 55 | # get desktop 56 | desktop = ctx.getByName("/singletons/com.sun.star.frame.theDesktop") 57 | # get document 58 | self.document = desktop.getCurrentComponent() 59 | 60 | def getHeight(self): 61 | return self.DialogContainer.Size.Height 62 | 63 | # --------- my code --------------------- 64 | # mri(self.LocalContext, self.DialogContainer) 65 | # xray(self.DialogContainer) 66 | 67 | def myFunction(self): 68 | # TODO: not implemented 69 | pass 70 | 71 | # --------- helpers --------------------- 72 | 73 | def messageBox(self, MsgText, MsgTitle, MsgType=MESSAGEBOX, MsgButtons=BUTTONS_OK): 74 | sm = self.ctx.ServiceManager 75 | si = sm.createInstanceWithContext("com.sun.star.awt.Toolkit", self.ctx) 76 | mBox = si.createMessageBox(self.Toolkit, MsgType, MsgButtons, MsgTitle, MsgText) 77 | mBox.execute() 78 | 79 | # ----------------------------------------------------------- 80 | # Execute dialog 81 | # ----------------------------------------------------------- 82 | 83 | def showDialog(self): 84 | self.DialogContainer.setVisible(True) 85 | self.DialogContainer.createPeer(self.Toolkit, None) 86 | self.DialogContainer.execute() 87 | 88 | # ----------------------------------------------------------- 89 | # Action events 90 | # ----------------------------------------------------------- 91 | 92 | ${GEN_ACTIONS_CALLBACKS} 93 | 94 | # ----------------------------------------------------------- 95 | # Window (dialog/panel) events 96 | # ----------------------------------------------------------- 97 | 98 | def resizeControls(self, dialog): 99 | # # see https://forum.openoffice.org/en/forum/viewtopic.php?f=45&t=85181# 100 | # ratio = 1.1 101 | # margin = 5 102 | # dlg_width = dialog.Size.Width 103 | # # add control names 104 | # controls = ['btnOK', 'lbList', 'cbPrinters'] 105 | # for c in controls: 106 | # cntr = dialog.getControl(c) 107 | # width = (dlg_width / ratio) - margin 108 | # cntr.setPosSize(cntr.PosSize.X, cntr.PosSize.Y, width, cntr.PosSize.Height, POSSIZE) 109 | pass 110 | 111 | def ${EXEC_FUNCTION_PREFIX}${APP_NAME}(*args): 112 | """ 113 | Intended to be used in a development environment only 114 | Copy this file in src dir and run with (Tools - Macros - MyMacros) 115 | After development copy this file back 116 | """ 117 | try: 118 | ctx = remote_ctx # IDE 119 | except: 120 | ctx = uno.getComponentContext() # UI 121 | 122 | # dialog 123 | dialog = ctx.ServiceManager.createInstanceWithContext("com.sun.star.awt.UnoControlDialog", ctx) 124 | 125 | app = ${APP_NAME}(ctx=ctx, dialog=dialog) 126 | app.showDialog() 127 | 128 | 129 | g_exportedScripts = ${EXEC_FUNCTION_PREFIX}${APP_NAME}, 130 | 131 | # ------------------------------------- 132 | # HELPER FOR AN IDE 133 | # ------------------------------------- 134 | 135 | if __name__ == "__main__": 136 | """ Connect to LibreOffice proccess. 137 | 1) Start the office in shell with command: 138 | soffice "--accept=socket,host=127.0.0.1,port=2002,tcpNoDelay=1;urp;StarOffice.ComponentContext" --norestore 139 | 2) Run script 140 | """ 141 | import os 142 | import sys 143 | 144 | sys.path.append(os.path.join(os.path.dirname(__file__), 'pythonpath')) 145 | 146 | local_ctx = uno.getComponentContext() 147 | resolver = local_ctx.ServiceManager.createInstance("com.sun.star.bridge.UnoUrlResolver") 148 | try: 149 | remote_ctx = resolver.resolve("uno:socket," 150 | "host=127.0.0.1," 151 | "port=2002," 152 | "tcpNoDelay=1;" 153 | "urp;" 154 | "StarOffice.ComponentContext") 155 | except Exception as err: 156 | print(err) 157 | 158 | ${EXEC_FUNCTION_PREFIX}${APP_NAME}() 159 | -------------------------------------------------------------------------------- /templates/sidebar_convert/100_sidebar_main.txt: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | #!/usr/bin/env python 3 | 4 | # ============================================================================= 5 | # Source: 6 | # https://wiki.openoffice.org/wiki/Sidebar_for_Developers 7 | # https://forum.openoffice.org/en/forum/viewtopic.php?f=20&t=70747 8 | # 9 | # ============================================================================= 10 | 11 | import uno 12 | import unohelper 13 | 14 | from com.sun.star.awt.MessageBoxButtons import BUTTONS_OK, BUTTONS_OK_CANCEL, BUTTONS_YES_NO, BUTTONS_YES_NO_CANCEL, BUTTONS_RETRY_CANCEL, BUTTONS_ABORT_IGNORE_RETRY 15 | from com.sun.star.awt.MessageBoxButtons import DEFAULT_BUTTON_OK, DEFAULT_BUTTON_CANCEL, DEFAULT_BUTTON_RETRY, DEFAULT_BUTTON_YES, DEFAULT_BUTTON_NO, DEFAULT_BUTTON_IGNORE 16 | from com.sun.star.awt.MessageBoxType import MESSAGEBOX, INFOBOX, WARNINGBOX, ERRORBOX, QUERYBOX 17 | 18 | from com.sun.star.ui import XUIElementFactory 19 | from com.sun.star.lang import XComponent 20 | from com.sun.star.ui import XUIElement, XToolPanel,XSidebarPanel, LayoutSize 21 | from com.sun.star.frame import XDispatch,XDispatchProvider 22 | from com.sun.star.ui.UIElementType import TOOLPANEL as UET_TOOLPANEL 23 | 24 | ${IMPORT_PANELS} 25 | 26 | 27 | def messageBox(MsgText, MsgTitle, MsgType=MESSAGEBOX, MsgButtons=BUTTONS_OK): 28 | ctx = uno.getComponentContext() 29 | sm = ctx.ServiceManager 30 | si = sm.createInstanceWithContext("com.sun.star.awt.Toolkit", ctx) 31 | toolkit = sm.createInstanceWithContext("com.sun.star.awt.ExtToolkit", ctx) 32 | mBox = si.createMessageBox(toolkit, MsgType, MsgButtons, MsgTitle, MsgText) 33 | mBox.execute() 34 | 35 | 36 | class ElementFactory( unohelper.Base, XUIElementFactory): 37 | """ 38 | UNO service that implements the com/sun/star/ui/XUIElementFactory interface. 39 | If you write a new factory then add it to Factories.xcu 40 | Method createUIElement(URL,arguments) is called for URLs defined in Sidebar.xcu. 41 | """ 42 | 43 | def __init__(self, ctx): 44 | self.ctx = uno.getComponentContext() 45 | 46 | def createUIElement(self, url, args): 47 | 48 | try: 49 | xParentWindow = None 50 | xFrame = None 51 | xUIElement = None 52 | 53 | for arg in args: 54 | if arg.Name == "Frame": 55 | xFrame = arg.Value 56 | elif arg.Name == "ParentWindow": 57 | xParentWindow = arg.Value 58 | 59 | xUIElement = XUIPanel(self.ctx, xFrame, xParentWindow, url) 60 | 61 | # getting the real panel window 62 | # for setting the content 63 | xUIElement.getRealInterface() 64 | panelWin = xUIElement.Window 65 | 66 | # panelWin has to be set visible 67 | panelWin.Visible = True 68 | 69 | # get and set height to receive a working scrollbar 70 | height = showPanels(panelWin, url) 71 | xUIElement.height = height 72 | 73 | return xUIElement 74 | 75 | except Exception as e: 76 | print(e) 77 | tb() 78 | 79 | 80 | g_ImplementationHelper = unohelper.ImplementationHelper() 81 | g_ImplementationHelper.addImplementation( 82 | ElementFactory, 83 | "${EXTENSION_IDENTIFIER_DOMAIN}.${EXTENSION_IDENTIFIER_APP}", 84 | ("com.sun.star.task.Job",),) 85 | 86 | 87 | class XUIPanel( unohelper.Base, XSidebarPanel, XUIElement, XToolPanel, XComponent): 88 | 89 | def __init__(self, ctx, frame, xParentWindow, url): 90 | 91 | self.ctx = ctx 92 | self.xParentWindow = xParentWindow 93 | self.window = None 94 | self.height = 100 95 | 96 | # XUIElement 97 | def getRealInterface(self): 98 | 99 | if not self.window: 100 | dialogUrl = "vnd.sun.star.extension://${EXTENSION_IDENTIFIER_DOMAIN}.${EXTENSION_IDENTIFIER_APP}/empty_dialog.xdl" 101 | # smgr = self.ctx.ServiceManager 102 | 103 | provider = self.ctx.ServiceManager.createInstanceWithContext("com.sun.star.awt.ContainerWindowProvider", self.ctx) 104 | self.window = provider.createContainerWindow(dialogUrl, "", self.xParentWindow, None) 105 | 106 | return self 107 | 108 | @property 109 | def Frame(self): 110 | self.frame = frame 111 | 112 | @property 113 | def ResourceURL(self): 114 | return self.name 115 | 116 | @property 117 | def Type(self): 118 | return UET_TOOLPANEL 119 | 120 | # XComponent 121 | def dispose(self): 122 | pass 123 | 124 | def addEventListener(self, ev): pass 125 | 126 | def removeEventListener(self, ev): pass 127 | 128 | # XToolPanel 129 | def createAccessible(self, parent): 130 | return self 131 | 132 | @property 133 | def Window(self): 134 | return self.window 135 | 136 | # XSidebarPanel 137 | def getHeightForWidth(self, width): 138 | # print("getHeightForWidth: %s" % width) 139 | # return LayoutSize(0, -1, 0) # full height 140 | return LayoutSize(self.height, self.height, self.height) 141 | 142 | # LO 5.1+ 143 | def getMinimalWidth(self): 144 | return 300 145 | 146 | class test(unohelper.Base, XDispatch, XDispatchProvider): 147 | 148 | IMPLE_NAME = "${EXTENSION_IDENTIFIER_DOMAIN}.${SIDEBAR_PROTOCOL}" 149 | SERVICE_NAMES = IMPLE_NAME, 150 | 151 | @classmethod 152 | def get_imple(klass): 153 | #pydevBrk() 154 | return klass, klass.IMPLE_NAME, klass.SERVICE_NAMES 155 | 156 | def __init__(self, *args): 157 | pass 158 | 159 | def queryDispatches(self, *args): 160 | return 161 | 162 | def queryDispatch(self, featureURL, frameName, searchFlag): 163 | return self 164 | 165 | def dispatch(self, featureURL, args): 166 | self.showDefaultMenuCommand(featureURL) 167 | 168 | def addStatusListener(self, listener, featureURL): 169 | #print('addStatusListener', featureURL.Path) 170 | return 171 | 172 | def removeStatusListener(self, listener, featureURL): 173 | #print('removeStatusListener', featureURL.Path) 174 | return 175 | 176 | def showDefaultMenuCommand(self, featureURL): 177 | """ 178 | Command that is dispatched when the user clicks on 179 | the "More Options" button in the panel title bar 180 | """ 181 | 182 | ctx = uno.getComponentContext() 183 | sm = ctx.ServiceManager 184 | dialog = sm.createInstanceWithContext("com.sun.star.awt.UnoControlDialog", ctx) 185 | 186 | ${RUN_DEFAULT_MENU_COMMAND} 187 | g_ImplementationHelper.addImplementation(*test.get_imple()) 188 | 189 | 190 | def showPanels(panelWin, url): 191 | """ 192 | Create a new panel object when the sidebar is initialized 193 | or whenever a panel becomes visible 194 | """ 195 | 196 | ctx = uno.getComponentContext() 197 | # url is set in Sidebar.xcu 198 | ${RUN_PANELS} 199 | -------------------------------------------------------------------------------- /config.ini: -------------------------------------------------------------------------------- 1 | # This file is part of UNO Dialog Tools 2 | # Copyright © 2016-2019 Sasa Kelecevic 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see 16 | 17 | # COPY THIS FILE IN YOUR PROJECT ROOT AND 18 | # EDIT SECTIONS TO REFLECT YOUR NEEDS 19 | 20 | 21 | # --------------------------- 22 | # GENERAL 23 | # --------------------------- 24 | 25 | # --------------------------- 26 | [directories] 27 | 28 | # Unodit template dir 29 | templates_dir = templates 30 | 31 | # Dir in project root where unodit generate code 32 | source_dir = src 33 | 34 | # --------------------------- 35 | # Name sufix for file generated from a XDL file. 36 | # All changes made in this file will be overwritten 37 | # if the file is generated again! 38 | [ui_file] 39 | sufix = _UI 40 | 41 | # --------------------------- 42 | # Prefix for exe script. Write your code in this file. 43 | [exe_file] 44 | prefix = '' 45 | 46 | # --------------------------- 47 | # Prefix for exe function in exe script. 48 | [exec_function] 49 | prefix = Run_ 50 | 51 | # --------------------------- 52 | [oxt] 53 | # Sufix for extension name 54 | name_sufix = _Devel 55 | # Exlude this files when generate extension 56 | exclude = log.log,config.ini 57 | exclude_dir = .git,.idea 58 | 59 | # --------------------------- 60 | # EXTENSION 61 | # --------------------------- 62 | 63 | # https://wiki.openoffice.org/wiki/Documentation/DevGuide/Extensions/description.xml 64 | # identifier = identifier_domain.identifier_app 65 | [extension] 66 | identifier_domain = my.identifier.value.for.myaddons 67 | identifier_app = MyAddOn 68 | version = 0.1.0 69 | platform = all 70 | publisher = PublisherName 71 | mailto = publisher.name@publisher.com 72 | 73 | # SCRIPT EXTENSION FILES 74 | # --------------------------- 75 | 76 | [script_install] 77 | location = user:uno_packages 78 | 79 | # dir = empty (generate file in root directory) or 80 | # dir name (create directory and generate file in it) 81 | # file = file name 82 | # templates = templates name using to generate file 83 | 84 | # manifest.xml 85 | [script_ext_meta] 86 | dir = META-INF 87 | file = manifest.xml 88 | template = 1_manifest.xml 89 | 90 | # description.xml 91 | [script_ext_description] 92 | dir = 93 | file = description.xml 94 | template = 2_description.xml 95 | 96 | # license text 97 | [script_app_license] 98 | dir = registration 99 | file = license.txt 100 | template = 3_license.txt 101 | 102 | # small text for extension 103 | # in the Extension Manager 104 | [script_app_description] 105 | dir = description 106 | file = description.txt 107 | template = 4_description_en.txt 108 | 109 | [script_app_title] 110 | dir = description 111 | file = title.txt 112 | template = 5_title.txt 113 | 114 | [script_add_on_menu] 115 | dir = 116 | file = Addons.xcu 117 | template = 6_Addons.xcu 118 | 119 | 120 | # SIDEBAR 121 | # --------------------------- 122 | # FIRTS READ 123 | # https://wiki.openoffice.org/wiki/Sidebar_for_Developers 124 | # https://forum.openoffice.org/en/forum/viewtopic.php?f=20&t=70747&p=317152&hilit=sidebar#p317152 125 | 126 | # sidebar directories 127 | [sdb_directories] 128 | # Dir where unodit generate UI code 129 | sdb_ui = ui 130 | sdb_ui_logic = ui_logic 131 | sdb_xdl = xdl 132 | sdb_image = images 133 | 134 | 135 | # DECK 136 | # --------------------------- 137 | [deck] 138 | name = ExampleSidebarDeck 139 | title = "My New Deck" 140 | id = MyDeck1 141 | icon_URL = image/icon1.png 142 | context = Writer, any, visible ; 143 | order_index = 600 144 | 145 | # PANELS 146 | # --------------------------- 147 | 148 | # For each panels in sidebar 149 | # define section in conf.ini file 150 | # using pattern: [panel+number] eg.[panel1] 151 | 152 | [panel1] 153 | name = Panel1 154 | title = "My Panel One" 155 | title_bar_is_optional = True 156 | id = panel0001 157 | context = Writer, any, visible ; 158 | order_index = 700 159 | xdl_ui = /path/to/Dialog1.xdl 160 | # Options Dialog 161 | # option_name = empty or options dialog name 162 | option_name = "Option 1 Dialog" 163 | # xdl_option_ui = empty or options dialog path 164 | xdl_option_ui = /path/to/Dialog1_Option.xdl 165 | 166 | [panel2] 167 | name = Panel2 168 | title = "My Panel Title" 169 | title_bar_is_optional = True 170 | id = panel0002 171 | context = any, any, visible ; 172 | order_index = 800 173 | xdl_ui = /path/to/Dialog2.xdl 174 | # Options Dialog 175 | # option_name = empty or options dialog name 176 | option_name = 177 | # xdl_option_ui = empty or options dialog path 178 | xdl_option_ui = 179 | 180 | [panel3] 181 | name = Panel3 182 | title = "My Panel" 183 | title_bar_is_optional = True 184 | id = panel0003 185 | context = any, any, visible ; 186 | order_index = 900 187 | xdl_ui = /path/to/MyNewDialog.xdl 188 | # Options Dialog 189 | # option_name = empty or options dialog name 190 | option_name = 191 | # xdl_option_ui = empty or options dialog path 192 | xdl_option_ui = 193 | 194 | # SIDEBAR EXTENSION FILES 195 | # --------------------------- 196 | [sidebar] 197 | protocol = ProtocolHandler 198 | 199 | # [sidebar_install] 200 | # location = user:uno_packages 201 | 202 | # dir = empty (generate file in root directory) or 203 | # dir name (create directory and generate file in it) 204 | # file = file name 205 | # templates = templates name using to generate file 206 | 207 | [sidebar_ext_meta] 208 | dir = META-INF 209 | file = manifest.xml 210 | template = 1_manifest.xml 211 | 212 | [sidebar_ext_description] 213 | dir = 214 | file = description.xml 215 | template = 2_description.xml 216 | 217 | [sidebar_app_license] 218 | dir = registration 219 | file = license.txt 220 | template = 3_license.txt 221 | 222 | [sidebar_app_description] 223 | dir = description 224 | file = description.txt 225 | template = 4_description_en.txt 226 | 227 | [sidebar_app_title] 228 | dir = description 229 | file = title.txt 230 | template = 5_title.txt 231 | 232 | [sidebar_panel_factory] 233 | dir = 234 | file = Factory.xcu 235 | template = 6_Factory.xcu 236 | 237 | [sidebar_protocol_handler] 238 | dir = 239 | file = ProtocolHandler.xcu 240 | template = 7_ProtocolHandler.xcu 241 | 242 | [sidebar_empty_xdl] 243 | dir = 244 | file = empty_panel.xdl 245 | template = 8_empty_panel.xcu 246 | 247 | [sidebar_icon] 248 | dir = image 249 | # icon 250 | # 24x24 pixels 251 | file = icon.png 252 | template = 9_icon1.png 253 | 254 | [sidebar_configuration] 255 | dir = 256 | file = Sidebar.xcu 257 | template = 10_Sidebar.xcu 258 | 259 | [sidebar_panel] 260 | dir = 261 | file = 262 | template = 11_sidebar_panels.txt 263 | -------------------------------------------------------------------------------- /pythonpath/generator.py: -------------------------------------------------------------------------------- 1 | # This file is part of UNO Dialog Tools - UNODIT 2 | # Copyright © 2016-2019 Sasa Kelecevic 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with UNODIT. If not, see 16 | 17 | """ 18 | Write generated code in files 19 | """ 20 | import os 21 | import logging 22 | 23 | try: 24 | # extension 25 | import pyuno_generator as pcg 26 | import config as conf 27 | 28 | except ImportError: 29 | # command line 30 | import pythonpath.pyuno_generator as pcg 31 | import pythonpath.config as conf 32 | 33 | IMPORT_DIR = conf.IMPORT_DIR 34 | 35 | 36 | class CodeGenerator: 37 | """ 38 | Generate code from uno context dict 39 | """ 40 | 41 | def __init__( 42 | self, mode, pydir, xdlfile, context, app="MyApp", indent=4, **kwargs 43 | ): 44 | self.xdlfile = xdlfile 45 | self.context = context 46 | self.pydir = pydir 47 | self.app = app 48 | self.mode = mode 49 | self.indent = indent 50 | self.kwargs = kwargs 51 | self.code = {} 52 | self.config = conf.ReadINI(conf.MAIN_DIR, self.pydir) 53 | self.SOURCE_DIR = self.config.get("directories", "source_dir") 54 | self.logger = logging.getLogger("unodit.generator.CodeGenerator") 55 | self.logger.info("NEW LOGGER: unodit.generator.CodeGenerator") 56 | 57 | def generate_code(self): 58 | 59 | # convert 60 | if self.mode == "script_convert" or self.mode == "script_all": 61 | py_code = pcg.PythonGenerator( 62 | self.mode, 63 | self.pydir, 64 | self.xdlfile, 65 | self.context, 66 | self.app, 67 | self.indent, 68 | ) 69 | ui, logic = py_code.generate_py_code() 70 | self.write_app_exec_file(logic) 71 | self.write_main_ui_file(ui) 72 | 73 | # connect 74 | elif self.mode == "connect": 75 | py_code = pcg.PythonGenerator( 76 | self.mode, 77 | self.pydir, 78 | self.xdlfile, 79 | self.context, 80 | self.app, 81 | self.indent, 82 | ) 83 | ui = py_code.generate_py_code() 84 | self.write_app_exec_file(ui) 85 | 86 | # embed 87 | elif self.mode == "embed_convert" or self.mode == "embed_all": 88 | py_code = pcg.PythonGenerator( 89 | self.mode, 90 | self.pydir, 91 | self.xdlfile, 92 | self.context, 93 | self.app, 94 | self.indent, 95 | ) 96 | ui = py_code.generate_py_code() 97 | self.write_app_exec_file(ui) 98 | 99 | # sidebar 100 | elif self.mode == "sidebar_convert" or self.mode == "sidebar_all": 101 | for name, value in self.kwargs.items(): 102 | if name == "panel_name": 103 | pn = value 104 | 105 | py_code = pcg.PythonGenerator( 106 | self.mode, 107 | self.pydir, 108 | self.xdlfile, 109 | self.context, 110 | self.app, 111 | self.indent, 112 | panel_name=pn, 113 | ) 114 | ui, logic = py_code.generate_py_code() 115 | self.write_app_exec_file(logic) 116 | self.write_main_ui_file(ui) 117 | 118 | def write_main_ui_file(self, sui): 119 | """ 120 | write generated python main ui file 121 | :param sui: 122 | """ 123 | ui_file_name = self.app + self.config.get("ui_file", "sufix") + ".py" 124 | py_file_path = os.path.join( 125 | self.pydir, self.SOURCE_DIR, IMPORT_DIR, ui_file_name 126 | ) 127 | 128 | # if not exist create 'pythopath' dir 129 | if not os.path.exists( 130 | os.path.join(self.pydir, self.SOURCE_DIR, IMPORT_DIR) 131 | ): 132 | os.makedirs(os.path.join(self.pydir, self.SOURCE_DIR, IMPORT_DIR)) 133 | 134 | if self.mode == "sidebar_convert" or self.mode == "sidebar_all": 135 | 136 | for name, value in self.kwargs.items(): 137 | if name == "panel_name": 138 | ui_file_name = ( 139 | value + self.config.get("ui_file", "sufix") + ".py" 140 | ) 141 | 142 | # if not exist create ui directory 143 | uidir = self.config.get("sdb_directories", "sdb_ui") 144 | SDB_UI_DIR = os.path.join( 145 | self.pydir, self.SOURCE_DIR, IMPORT_DIR, uidir 146 | ) 147 | if not os.path.exists(SDB_UI_DIR): 148 | os.makedirs(SDB_UI_DIR) 149 | 150 | # if the main ui file exists, remove it 151 | py_file_path = os.path.join(SDB_UI_DIR, ui_file_name) 152 | 153 | # if the main ui file exists, remove it 154 | if os.path.exists(py_file_path): 155 | os.remove(py_file_path) 156 | 157 | py_main_ui_file = open(py_file_path, "w") 158 | py_main_ui_file.write(sui) 159 | py_main_ui_file.close() 160 | 161 | def write_app_exec_file(self, lg): 162 | 163 | """ 164 | write generated python app exec file 165 | 166 | :param lg: 167 | :return: 168 | """ 169 | exec_file_name = self.app + ".py" 170 | py_file_path = os.path.join(self.pydir, self.SOURCE_DIR, exec_file_name) 171 | 172 | if self.mode == "sidebar_convert": 173 | 174 | for name, value in self.kwargs.items(): 175 | if name == "panel_name": 176 | # same in sidebar.py 177 | exec_file_name = value + ".py" 178 | 179 | # if not exist create ui_logic directory 180 | uilogic = self.config.get("sdb_directories", "sdb_ui_logic") 181 | SDB_LOGIC_DIR = os.path.join( 182 | self.pydir, self.SOURCE_DIR, IMPORT_DIR, uilogic 183 | ) 184 | if not os.path.exists(SDB_LOGIC_DIR): 185 | os.makedirs(SDB_LOGIC_DIR) 186 | 187 | py_file_path = os.path.join(SDB_LOGIC_DIR, exec_file_name) 188 | 189 | if not os.path.exists(self.pydir): 190 | os.makedirs(self.pydir) 191 | 192 | # source dir 193 | sdir = os.path.join(self.pydir, self.SOURCE_DIR) 194 | if not os.path.exists(sdir): 195 | os.makedirs(sdir) 196 | 197 | # if the logic file exists, do not remove it 198 | if os.path.exists(py_file_path): 199 | if os.path.isfile(py_file_path): 200 | pass 201 | else: 202 | py_main_ui_file = open(py_file_path, "w") 203 | py_main_ui_file.write(lg) 204 | py_main_ui_file.close() 205 | -------------------------------------------------------------------------------- /examples/connect to dialog/src/Test_connect.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | #!/usr/bin/env python 3 | 4 | # ============================================================================= 5 | # 6 | # Connect Python and XDL file. 7 | # 8 | # Created: Sat Jul 9 15:12:55 2016 9 | # by: unodit 0.5 10 | # 11 | # WARNING! All changes made in this file will be overwritten 12 | # if the file is generated again! 13 | # 14 | # ============================================================================= 15 | 16 | import uno 17 | import unohelper 18 | from com.sun.star.awt import XActionListener 19 | from com.sun.star.task import XJobExecutor 20 | 21 | from com.sun.star.awt.MessageBoxButtons import BUTTONS_OK, BUTTONS_OK_CANCEL, BUTTONS_YES_NO, BUTTONS_YES_NO_CANCEL, BUTTONS_RETRY_CANCEL, BUTTONS_ABORT_IGNORE_RETRY 22 | from com.sun.star.awt.MessageBoxButtons import DEFAULT_BUTTON_OK, DEFAULT_BUTTON_CANCEL, DEFAULT_BUTTON_RETRY, DEFAULT_BUTTON_YES, DEFAULT_BUTTON_NO, DEFAULT_BUTTON_IGNORE 23 | from com.sun.star.awt.MessageBoxType import MESSAGEBOX, INFOBOX, WARNINGBOX, ERRORBOX, QUERYBOX 24 | 25 | 26 | # ----------------- helper code for API_inspector tool MRI ---------- 27 | def mri(ctx, target): 28 | mri = ctx.ServiceManager.createInstanceWithContext("mytools.Mri", ctx) 29 | mri.inspect(target) 30 | # ------------------------------------------------------------------- 31 | 32 | 33 | class Test_connect_UI(unohelper.Base, XActionListener, XJobExecutor): 34 | """ 35 | Class documentation... 36 | """ 37 | def __init__(self): 38 | self.LocalContext = uno.getComponentContext() 39 | self.ServiceManager = self.LocalContext.ServiceManager 40 | self.Toolkit = self.ServiceManager.createInstanceWithContext("com.sun.star.awt.ExtToolkit", self.LocalContext) 41 | 42 | # --------------connect dialog container and set model -- 43 | 44 | dlg_path = "vnd.sun.star.script:DialogLib.Default?location=application" 45 | self.Dialog = self.ServiceManager.createInstanceWithContext("com.sun.star.awt.DialogProvider", self.LocalContext) 46 | self.DialogContainer = self.Dialog.createDialog(dlg_path) 47 | self.DialogModel = self.DialogContainer.getModel() 48 | 49 | # ------------- define all controls models -------------- 50 | 51 | Label7 = self.DialogModel.getByName("Label7") 52 | Label9 = self.DialogModel.getByName("Label9") 53 | ListBox1 = self.DialogModel.getByName("ListBox1") 54 | TextField1 = self.DialogModel.getByName("TextField1") 55 | Label8 = self.DialogModel.getByName("Label8") 56 | CommandButton2 = self.DialogModel.getByName("CommandButton2") 57 | Label4 = self.DialogModel.getByName("Label4") 58 | PatternField1 = self.DialogModel.getByName("PatternField1") 59 | Label1 = self.DialogModel.getByName("Label1") 60 | FixedLine2 = self.DialogModel.getByName("FixedLine2") 61 | Label13 = self.DialogModel.getByName("Label13") 62 | TimeField1 = self.DialogModel.getByName("TimeField1") 63 | FixedLine1 = self.DialogModel.getByName("FixedLine1") 64 | CommandButton3 = self.DialogModel.getByName("CommandButton3") 65 | Label11 = self.DialogModel.getByName("Label11") 66 | ProgressBar1 = self.DialogModel.getByName("ProgressBar1") 67 | FrameControl1 = self.DialogModel.getByName("FrameControl1") 68 | CurrencyField1 = self.DialogModel.getByName("CurrencyField1") 69 | FixedLine3 = self.DialogModel.getByName("FixedLine3") 70 | CommandButton1 = self.DialogModel.getByName("CommandButton1") 71 | Label3 = self.DialogModel.getByName("Label3") 72 | DateField1 = self.DialogModel.getByName("DateField1") 73 | Label2 = self.DialogModel.getByName("Label2") 74 | Label12 = self.DialogModel.getByName("Label12") 75 | ComboBox1 = self.DialogModel.getByName("ComboBox1") 76 | Label10 = self.DialogModel.getByName("Label10") 77 | OptionButton1 = self.DialogModel.getByName("OptionButton1") 78 | ImageControl1 = self.DialogModel.getByName("ImageControl1") 79 | FileControl1 = self.DialogModel.getByName("FileControl1") 80 | OptionButton2 = self.DialogModel.getByName("OptionButton2") 81 | FormattedField1 = self.DialogModel.getByName("FormattedField1") 82 | CheckBox1 = self.DialogModel.getByName("CheckBox1") 83 | Label6 = self.DialogModel.getByName("Label6") 84 | Label5 = self.DialogModel.getByName("Label5") 85 | SpinButton1 = self.DialogModel.getByName("SpinButton1") 86 | NumericField1 = self.DialogModel.getByName("NumericField1") 87 | TreeControl1 = self.DialogModel.getByName("TreeControl1") 88 | 89 | # ------------- add the action listener to buttons ------ 90 | 91 | self.DialogContainer.getControl("CommandButton2").addActionListener(self) 92 | self.DialogContainer.getControl("CommandButton2").setActionCommand("CommandButton2_OnClick") 93 | 94 | self.DialogContainer.getControl("CommandButton3").addActionListener(self) 95 | self.DialogContainer.getControl("CommandButton3").setActionCommand("CommandButton3_OnClick") 96 | 97 | self.DialogContainer.getControl("CommandButton1").addActionListener(self) 98 | self.DialogContainer.getControl("CommandButton1").setActionCommand("CommandButton1_OnClick") 99 | 100 | 101 | # --------- my code --------------------- 102 | self.DialogModel.Title = "Test_connect" 103 | # mri(self.LocalContext, self.DialogContainer) 104 | 105 | # --------- functions ----------------------- 106 | 107 | def myFunction(self): 108 | # TODO: not implemented 109 | pass 110 | 111 | # --------- helpers ------------------------- 112 | 113 | def messageBox(self, MsgText, MsgTitle, MsgType=MESSAGEBOX, MsgButtons=BUTTONS_OK): 114 | sm = self.LocalContext.ServiceManager 115 | si = sm.createInstanceWithContext("com.sun.star.awt.Toolkit", self.LocalContext) 116 | mBox = si.createMessageBox(self.Toolkit, MsgType, MsgButtons, MsgTitle, MsgText) 117 | mBox.execute() 118 | 119 | # ----------------------------------------------------------- 120 | # Action events 121 | # ----------------------------------------------------------- 122 | 123 | def actionPerformed(self, oActionEvent): 124 | 125 | if oActionEvent.ActionCommand == "CommandButton2_OnClick": 126 | self.CommandButton2_OnClick() 127 | 128 | if oActionEvent.ActionCommand == "CommandButton3_OnClick": 129 | self.CommandButton3_OnClick() 130 | 131 | if oActionEvent.ActionCommand == "CommandButton1_OnClick": 132 | self.CommandButton1_OnClick() 133 | 134 | 135 | 136 | def CommandButton2_OnClick(self): 137 | self.DialogContainer.Title = "It's Alive! - CommandButton2" 138 | self.messageBox("It's Alive! - CommandButton2", "Event: OnClick", INFOBOX) 139 | # TODO: not implemented 140 | 141 | def CommandButton3_OnClick(self): 142 | self.DialogContainer.Title = "It's Alive! - CommandButton3" 143 | self.messageBox("It's Alive! - CommandButton3", "Event: OnClick", INFOBOX) 144 | # TODO: not implemented 145 | 146 | def CommandButton1_OnClick(self): 147 | self.DialogContainer.Title = "It's Alive! - CommandButton1" 148 | self.messageBox("It's Alive! - CommandButton1", "Event: OnClick", INFOBOX) 149 | # TODO: not implemented 150 | 151 | 152 | def showDialog(self): 153 | self.DialogContainer.execute() 154 | 155 | 156 | def Run_Test_connect_UI(*args): 157 | app = Test_connect_UI() 158 | app.showDialog() 159 | 160 | g_exportedScripts = Run_Test_connect_UI, 161 | 162 | # ----------------- END GENERATED CODE ---------------------------------------- 163 | -------------------------------------------------------------------------------- /pythonpath/sidebar.py: -------------------------------------------------------------------------------- 1 | # This file is part of UNO Dialog Tools - UNODIT 2 | # Copyright © 2016-2019 Sasa Kelecevic 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with UNODIT. If not, see 16 | 17 | """ 18 | Write sidebars code in files 19 | """ 20 | 21 | import os 22 | import string 23 | import logging 24 | 25 | try: 26 | import config as conf 27 | except ImportError: 28 | import pythonpath.config as conf 29 | 30 | 31 | class SidebarGenerator: 32 | """ 33 | Generate python code 34 | """ 35 | 36 | def __init__( 37 | self, mode, pydir, xdlfile, context, app="MyApp", indent=4, **kwargs 38 | ): 39 | self.xdlfile = xdlfile 40 | self.context = context 41 | self.pydir = pydir 42 | self.app = app 43 | self.mode = mode 44 | self.kwargs = kwargs 45 | self.panel_list = self.get_panel_list() 46 | self.config = conf.ReadINI(conf.MAIN_DIR, self.pydir) 47 | self.SOURCE_DIR = self.config.get("directories", "source_dir") 48 | self.logger = logging.getLogger("unodit.sidebar.SidebarGenerator") 49 | self.logger.info("NEW LOGGER: unodit.sidebar.SidebarGenerator") 50 | 51 | if self.config.get("directories", "templates_dir") == "templates": 52 | self.tempates_dir = os.path.join(conf.MAIN_DIR, "templates") 53 | else: 54 | self.tempates_dir = self.config.get("directories", "templates_dir") 55 | self.logger.info("templates directory: " + self.tempates_dir) 56 | 57 | if indent == 0: 58 | self.indent = "\t" 59 | else: 60 | self.indent = indent * " " 61 | 62 | # read all templates 63 | if self.mode == "sidebar_convert" or self.mode == "sidebar_all": 64 | # sidebar main exe file 65 | py_tmpl_dir = os.path.join(self.tempates_dir, "sidebar_convert") 66 | self.sidebar_main = string.Template( 67 | self.get_template(py_tmpl_dir, "100_sidebar_main.txt") 68 | ) 69 | self.sidebar_run_default_menu_command = string.Template( 70 | self.get_template(py_tmpl_dir, "102_show_menu_command.txt") 71 | ) 72 | self.sidebar_run_panels = string.Template( 73 | self.get_template(py_tmpl_dir, "101_sidebar_show_panels.txt") 74 | ) 75 | 76 | self.logger.info("successfully read all templates for script files") 77 | 78 | def get_template(self, py_tmpl_dir, template): 79 | templ = os.path.join(py_tmpl_dir, template) 80 | with open(templ, "rt") as t: 81 | tt = t.read() 82 | return tt 83 | 84 | def get_panel_list(self): 85 | for name, value in self.kwargs.items(): 86 | if name == "all_panels": 87 | pl = value # .split(',') 88 | 89 | return pl 90 | 91 | # def get_option_panel_list(self): 92 | # panel_option_name_list = [] 93 | # for i in range(0, 20): 94 | # panel_section = 'panel' + str(i + 1) 95 | # panel_name = self.config.get(panel_section, 'name') 96 | # if panel_name: 97 | # panel_option_name = self.config.get(panel_section, 'option_name') 98 | # if panel_option_name: 99 | # panel_option_name_list.append(panel_option_name) 100 | # 101 | # return panel_option_name_list 102 | 103 | def generate_sidebar_code(self): 104 | 105 | sdb_main = { 106 | "I": self.indent, 107 | "IMPORT_PANELS": self._get_import_panels(), 108 | "EXTENSION_IDENTIFIER_DOMAIN": self.config.get( 109 | "extension", "identifier_domain" 110 | ), 111 | "EXTENSION_IDENTIFIER_APP": self.config.get( 112 | "extension", "identifier_app" 113 | ), 114 | "SIDEBAR_PROTOCOL": self.config.get("sidebar", "protocol"), 115 | "RUN_DEFAULT_MENU_COMMAND": self._run_default_menu_command(), 116 | "RUN_PANELS": self._run_panels(), 117 | } 118 | sidebar_main = self.sidebar_main.substitute(sdb_main) 119 | self.write_sidebar_main_file(sidebar_main) 120 | 121 | def _get_import_panels(self): 122 | 123 | logic_dir = self.config.get("sdb_directories", "sdb_ui_logic") 124 | panels = "" 125 | 126 | # op = self.get_option_panel_list() 127 | # if op: 128 | # self.panel_list = self.panel_list + op 129 | 130 | for panel, option in self.panel_list.items(): 131 | exec_file_name = panel 132 | panels = ( 133 | panels 134 | + "from " 135 | + logic_dir 136 | + "." 137 | + exec_file_name 138 | + " import " 139 | + exec_file_name 140 | + "\n" 141 | ) 142 | if option: 143 | exec_option_file_name = option 144 | panels = ( 145 | panels 146 | + "from " 147 | + logic_dir 148 | + "." 149 | + exec_option_file_name 150 | + " import " 151 | + exec_option_file_name 152 | + "\n" 153 | ) 154 | 155 | return panels 156 | 157 | def _run_panels(self): 158 | code = "" 159 | 160 | for i in self.panel_list: 161 | pn = { 162 | "I": self.indent, 163 | "EXTENSION_IDENTIFIER_APP": self.config.get( 164 | "extension", "identifier_app" 165 | ), 166 | "PANEL_NAME": i, 167 | } 168 | code += self.sidebar_run_panels.substitute(pn) 169 | 170 | return code 171 | 172 | def _run_default_menu_command(self): 173 | 174 | panels = {} 175 | for i in range(0, 20): 176 | panel_section = "panel" + str(i + 1) 177 | panel_name = self.config.get(panel_section, "name") 178 | if panel_name: 179 | panel_option_name = self.config.get( 180 | panel_section, "option_name" 181 | ) 182 | if panel_option_name: 183 | panels[panel_name] = panel_option_name 184 | else: 185 | panels[panel_name] = "" 186 | 187 | code = "" 188 | 189 | for panel, option in panels.items(): 190 | pn = { 191 | "I": self.indent, 192 | "EXTENSION_IDENTIFIER_APP": self.config.get( 193 | "extension", "identifier_app" 194 | ), 195 | "PANEL_NAME": panel, 196 | "PANEL_OPTION_NAME": option, 197 | } 198 | code += self.sidebar_run_default_menu_command.substitute(pn) 199 | 200 | return code 201 | 202 | def write_sidebar_main_file(self, sdb_text): 203 | 204 | sdb_main = self.app + ".py" 205 | py_file_path = os.path.join(self.pydir, self.SOURCE_DIR, sdb_main) 206 | 207 | py_main_ui_file = open(py_file_path, "w") 208 | py_main_ui_file.write(sdb_text) 209 | py_main_ui_file.close() 210 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # unodit 2 | 3 | **UNO** **Di**alog **T**ools is a Python3 command-line tool which takes a `.xdl` file written in the Basic Dialog Editor and generates dialog code in PyUNO (Python) in order to create LibreOffice extension, sidebar extension or embed in ODF documents. Unodit was developed with a focus on rapid prototyping in order to lower the barrier of entry for newcomers. 4 | 5 | ## Features 6 | 7 | `unodit` main features are: 8 | 9 | - **Convert a `.xdl` file written with Basic Dialog Editor into a PyUNO (Python):** 10 | 11 | `unodit` create file `MyAppName_UI.py` with actual python code. It defines a class called `MyAppName_UI` with dialog and dialog controls properties. Each button in your dialog is connected with action listener. **New:** window listener was added in sidebar. All changes made in this file will be overwritten if the file is generated again 12 | 13 | 14 | - **Allows you to customize code according to your needs:** 15 | 16 | In order to help you to add your own functionality to dialog `unodit` generates another file `MyAppName.py`. There is a new class `MyAppName` which extend `MyAppName_UI`. You can change dialog properties with eg. `self.DialogModel.Title = 'Hello world'` or control properties with eg.`self.TextField1.Text = "My New Text"`. Each button in your dialog is connected with action event which execute callback function `ButtonName_OnClick()`. **New:** `resizeControls` event handler has been added, which will be called when sidebar has been resized. This allows you to resize/reposition controls in the sidebar dialog. 17 | Now you can write down the code to actually do something :) 18 | 19 | - **Object inspection and debugging:** 20 | 21 | The file `MyAppName.py` provide convenient code, depending on your requirements and development practices, for easy object inspection and debugging with extension or in the IDE. 22 | 23 | Extension: One can use installed extension ([MRI](https://github.com/hanya/MRI/releases) or [Xray](http://berma.pagesperso-orange.fr/index2.html)) by uncommenting code in section `HELPERS FOR MRI AND XRAY`. 24 | 25 | IDE: First start LibreOffice with the command `soffice "--accept=socket,host=127.0.0.1,port=2002,tcpNoDelay=1;urp;StarOffice.ComponentContext" --norestore` as described in code section `HELPER FOR AN IDE`. Then step through code (tested with: [PyCharm](https://www.jetbrains.com/pycharm/), [Pyzo](https://pyzo.org/) with [PyUNO Workspace](https://github.com/kelsa-pi/PyUNO_Workspace) plugin). 26 | 27 | - **Pack your code as extension, sidebar extension or embed in ODF documents:** 28 | 29 | After finishing coding you can decide to distribute your code. `unodit` can create necessary files and generate extension or file for you. After installation, in some cases, user can start extension with `Tools - AddOns - My App`. 30 | 31 | - **Provides simple dialog boxes for interaction with a user:** 32 | 33 | If you only want simple GUI for your macros `unodit` provides simple dialog boxes for interaction with a user. In script interactions are invoked by simple function calls. If you decide to distribute your code `unodit` can create necessary files and generate extension for you. 34 | 35 | Other features are: 36 | - all steps are logged to `log.log` file in project root 37 | - per project customization with ini file (copy `config.ini` in project root) 38 | - boilerplate code in `templates` directory 39 | - conversion `.xdl` to `.py` defined in `schema.py` 40 | - diff `.xdl` vs. `schema.py` 41 | 42 | Your comments, feedback and patches are welcomed and appreciated. 43 | 44 | NOTE: 45 | This is a project that targets LibreOffice 6+ and Python3. 46 | Tested with Xubuntu 18.04. and LibreOffice 6+. 47 | 48 | ## Installation 49 | 50 | Place the unodit directory somewhere on your Python path. 51 | 52 | ## Usage 53 | python3 ./unodit.py -m -d [-f ] [-a] [-p] [-i] 54 | 55 | m - mode 56 | 57 | d - full path to the output directory (project root) 58 | 59 | f - full path to the xdl file 60 | 61 | a - application name 62 | 63 | p - number of panels in deck 64 | 65 | i - number of spaces used for indentation in the generated code. If 0, \t is used as indent 66 | 67 | 68 | ## Quick start 69 | 70 | This section gives a general overview, for more information see [documentation](https://github.com/kelsa-pi/unodit/wiki). 71 | 72 | - create dialog eg. `Default.xdl` in Dialog Editor 73 | - create project directory eg. `TestLib` in `LIBREOFFICE_PATH/4/user/Scripts/python/` 74 | - run `unodit` to create extension in project directory 75 | 76 | python3 ./unodit.py -m 'script_all' 77 | -d 'LIBREOFFICE_PATH/4/user/Scripts/python/TestLib' 78 | -f 'LIBREOFFICE_PATH/4/user/basic/DialogLib/Default.xdl' 79 | -a 'Test_convert' 80 | 81 | - install extension using Tools - Extension Manager or command-line `/usr/bin/unopkg add ./Test_convert_Devel.oxt` (Ubuntu) 82 | 83 | ## Projects using unodit 84 | Libreoffice-Addon for Qualitative Data Analysis ![Office-QDA-TagTree](https://github.com/jdittrich/Office-QDA-TagTree) 85 | 86 | ## Screenshot 87 | 88 | Test dialog created at runtime 89 | 90 | ![Test dialog](resource/screenshot/Example_dialog.png) 91 | 92 | The action event listener is registered for all button controls. 93 | 94 | ![Callback functions](resource/screenshot/Button_event.png) 95 | 96 | Pack dialogs in Sidebar 97 | 98 | ![Test dialog](resource/screenshot/Sidebar_panels.png) 99 | 100 | Run simple dialogs 101 | 102 | ![Embed all](resource/screenshot/Macros_simple_dialogs.png) 103 | 104 | ## Unodit directory structure 105 | 106 | unodit/ 107 | 108 | pythonpath/ > submodules dir 109 | config.py > config file 110 | embed_packer.py > embed script in ODF file 111 | extractor.py > extract context from ui file 112 | generator.py > code generator 113 | oxt_creator.py > create .oxt extension 114 | pyuno_generator.py > python code generator 115 | schema.py > supported properties 116 | sidebar.py > write sidebars code 117 | simple_dialogs.py > like easygui dialogs 118 | 119 | resource/ > resources dir 120 | embed/ > odf files 121 | images/ > unodit icons 122 | screanshoot/ > screanshoot images 123 | simple_dialogs/ > dialog images 124 | xdl/ > examples .xdl 125 | 126 | templates/ > tempaltes dir 127 | connect/ 128 | convert/ 129 | dialogs/ 130 | embeded/ 131 | script_ext/ 132 | sidebar_convert/ 133 | sidebar_convert_ext/ 134 | config.ini > config file 135 | LICENSE.txt 136 | README.md 137 | unodit.py > main script 138 | 139 | 140 | ## Similar projects 141 | 142 | The following is an incomplete lists of a few projects that share some similarity with `unodit`. 143 | 144 | [Gladex](https://launchpad.net/gladex): Gladex is a Python application which takes a .glade file written in the Glade User Interface Builder and generates code in Perl, Python, or Ruby. 145 | 146 | [pyuic4](http://pyqt.sourceforge.net/Docs/PyQt4/designer.html#the-uic-module): Convert a .ui file written with Qt Designer into a Python script. 147 | 148 | [EasyGUI](https://sourceforge.net/projects/easygui): Very easy GUI programming in Python and Tkinter 149 | 150 | [EasyGUI_Qt](https://github.com/aroberge/easygui_qt): Inspired by EasyGUI, designed for PyQt 151 | -------------------------------------------------------------------------------- /templates/script_ext/3_license_lgpl3.txt: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | 5 | Copyright (C) 2007 Free Software Foundation, Inc. 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | 10 | This version of the GNU Lesser General Public License incorporates 11 | the terms and conditions of version 3 of the GNU General Public 12 | License, supplemented by the additional permissions listed below. 13 | 14 | 0. Additional Definitions. 15 | 16 | As used herein, "this License" refers to version 3 of the GNU Lesser 17 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 18 | General Public License. 19 | 20 | "The Library" refers to a covered work governed by this License, 21 | other than an Application or a Combined Work as defined below. 22 | 23 | An "Application" is any work that makes use of an interface provided 24 | by the Library, but which is not otherwise based on the Library. 25 | Defining a subclass of a class defined by the Library is deemed a mode 26 | of using an interface provided by the Library. 27 | 28 | A "Combined Work" is a work produced by combining or linking an 29 | Application with the Library. The particular version of the Library 30 | with which the Combined Work was made is also called the "Linked 31 | Version". 32 | 33 | The "Minimal Corresponding Source" for a Combined Work means the 34 | Corresponding Source for the Combined Work, excluding any source code 35 | for portions of the Combined Work that, considered in isolation, are 36 | based on the Application, and not on the Linked Version. 37 | 38 | The "Corresponding Application Code" for a Combined Work means the 39 | object code and/or source code for the Application, including any data 40 | and utility programs needed for reproducing the Combined Work from the 41 | Application, but excluding the System Libraries of the Combined Work. 42 | 43 | 1. Exception to Section 3 of the GNU GPL. 44 | 45 | You may convey a covered work under sections 3 and 4 of this License 46 | without being bound by section 3 of the GNU GPL. 47 | 48 | 2. Conveying Modified Versions. 49 | 50 | If you modify a copy of the Library, and, in your modifications, a 51 | facility refers to a function or data to be supplied by an Application 52 | that uses the facility (other than as an argument passed when the 53 | facility is invoked), then you may convey a copy of the modified 54 | version: 55 | 56 | a) under this License, provided that you make a good faith effort to 57 | ensure that, in the event an Application does not supply the 58 | function or data, the facility still operates, and performs 59 | whatever part of its purpose remains meaningful, or 60 | 61 | b) under the GNU GPL, with none of the additional permissions of 62 | this License applicable to that copy. 63 | 64 | 3. Object Code Incorporating Material from Library Header Files. 65 | 66 | The object code form of an Application may incorporate material from 67 | a header file that is part of the Library. You may convey such object 68 | code under terms of your choice, provided that, if the incorporated 69 | material is not limited to numerical parameters, data structure 70 | layouts and accessors, or small macros, inline functions and templates 71 | (ten or fewer lines in length), you do both of the following: 72 | 73 | a) Give prominent notice with each copy of the object code that the 74 | Library is used in it and that the Library and its use are 75 | covered by this License. 76 | 77 | b) Accompany the object code with a copy of the GNU GPL and this license 78 | document. 79 | 80 | 4. Combined Works. 81 | 82 | You may convey a Combined Work under terms of your choice that, 83 | taken together, effectively do not restrict modification of the 84 | portions of the Library contained in the Combined Work and reverse 85 | engineering for debugging such modifications, if you also do each of 86 | the following: 87 | 88 | a) Give prominent notice with each copy of the Combined Work that 89 | the Library is used in it and that the Library and its use are 90 | covered by this License. 91 | 92 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 93 | document. 94 | 95 | c) For a Combined Work that displays copyright notices during 96 | execution, include the copyright notice for the Library among 97 | these notices, as well as a reference directing the user to the 98 | copies of the GNU GPL and this license document. 99 | 100 | d) Do one of the following: 101 | 102 | 0) Convey the Minimal Corresponding Source under the terms of this 103 | License, and the Corresponding Application Code in a form 104 | suitable for, and under terms that permit, the user to 105 | recombine or relink the Application with a modified version of 106 | the Linked Version to produce a modified Combined Work, in the 107 | manner specified by section 6 of the GNU GPL for conveying 108 | Corresponding Source. 109 | 110 | 1) Use a suitable shared library mechanism for linking with the 111 | Library. A suitable mechanism is one that (a) uses at run time 112 | a copy of the Library already present on the user's computer 113 | system, and (b) will operate properly with a modified version 114 | of the Library that is interface-compatible with the Linked 115 | Version. 116 | 117 | e) Provide Installation Information, but only if you would otherwise 118 | be required to provide such information under section 6 of the 119 | GNU GPL, and only to the extent that such information is 120 | necessary to install and execute a modified version of the 121 | Combined Work produced by recombining or relinking the 122 | Application with a modified version of the Linked Version. (If 123 | you use option 4d0, the Installation Information must accompany 124 | the Minimal Corresponding Source and Corresponding Application 125 | Code. If you use option 4d1, you must provide the Installation 126 | Information in the manner specified by section 6 of the GNU GPL 127 | for conveying Corresponding Source.) 128 | 129 | 5. Combined Libraries. 130 | 131 | You may place library facilities that are a work based on the 132 | Library side by side in a single library together with other library 133 | facilities that are not Applications and are not covered by this 134 | License, and convey such a combined library under terms of your 135 | choice, if you do both of the following: 136 | 137 | a) Accompany the combined library with a copy of the same work based 138 | on the Library, uncombined with any other library facilities, 139 | conveyed under the terms of this License. 140 | 141 | b) Give prominent notice with the combined library that part of it 142 | is a work based on the Library, and explaining where to find the 143 | accompanying uncombined form of the same work. 144 | 145 | 6. Revised Versions of the GNU Lesser General Public License. 146 | 147 | The Free Software Foundation may publish revised and/or new versions 148 | of the GNU Lesser General Public License from time to time. Such new 149 | versions will be similar in spirit to the present version, but may 150 | differ in detail to address new problems or concerns. 151 | 152 | Each version is given a distinguishing version number. If the 153 | Library as you received it specifies that a certain numbered version 154 | of the GNU Lesser General Public License "or any later version" 155 | applies to it, you have the option of following the terms and 156 | conditions either of that published version or of any later version 157 | published by the Free Software Foundation. If the Library as you 158 | received it does not specify a version number of the GNU Lesser 159 | General Public License, you may choose any version of the GNU Lesser 160 | General Public License ever published by the Free Software Foundation. 161 | 162 | If the Library as you received it specifies that a proxy can decide 163 | whether future versions of the GNU Lesser General Public License shall 164 | apply, that proxy's public statement of acceptance of any version is 165 | permanent authorization for you to choose that version for the 166 | Library. 167 | 168 |  169 | -------------------------------------------------------------------------------- /examples/convert dialog/registration/license.txt: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | 5 | Copyright (C) 2007 Free Software Foundation, Inc. 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | 10 | This version of the GNU Lesser General Public License incorporates 11 | the terms and conditions of version 3 of the GNU General Public 12 | License, supplemented by the additional permissions listed below. 13 | 14 | 0. Additional Definitions. 15 | 16 | As used herein, "this License" refers to version 3 of the GNU Lesser 17 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 18 | General Public License. 19 | 20 | "The Library" refers to a covered work governed by this License, 21 | other than an Application or a Combined Work as defined below. 22 | 23 | An "Application" is any work that makes use of an interface provided 24 | by the Library, but which is not otherwise based on the Library. 25 | Defining a subclass of a class defined by the Library is deemed a mode 26 | of using an interface provided by the Library. 27 | 28 | A "Combined Work" is a work produced by combining or linking an 29 | Application with the Library. The particular version of the Library 30 | with which the Combined Work was made is also called the "Linked 31 | Version". 32 | 33 | The "Minimal Corresponding Source" for a Combined Work means the 34 | Corresponding Source for the Combined Work, excluding any source code 35 | for portions of the Combined Work that, considered in isolation, are 36 | based on the Application, and not on the Linked Version. 37 | 38 | The "Corresponding Application Code" for a Combined Work means the 39 | object code and/or source code for the Application, including any data 40 | and utility programs needed for reproducing the Combined Work from the 41 | Application, but excluding the System Libraries of the Combined Work. 42 | 43 | 1. Exception to Section 3 of the GNU GPL. 44 | 45 | You may convey a covered work under sections 3 and 4 of this License 46 | without being bound by section 3 of the GNU GPL. 47 | 48 | 2. Conveying Modified Versions. 49 | 50 | If you modify a copy of the Library, and, in your modifications, a 51 | facility refers to a function or data to be supplied by an Application 52 | that uses the facility (other than as an argument passed when the 53 | facility is invoked), then you may convey a copy of the modified 54 | version: 55 | 56 | a) under this License, provided that you make a good faith effort to 57 | ensure that, in the event an Application does not supply the 58 | function or data, the facility still operates, and performs 59 | whatever part of its purpose remains meaningful, or 60 | 61 | b) under the GNU GPL, with none of the additional permissions of 62 | this License applicable to that copy. 63 | 64 | 3. Object Code Incorporating Material from Library Header Files. 65 | 66 | The object code form of an Application may incorporate material from 67 | a header file that is part of the Library. You may convey such object 68 | code under terms of your choice, provided that, if the incorporated 69 | material is not limited to numerical parameters, data structure 70 | layouts and accessors, or small macros, inline functions and templates 71 | (ten or fewer lines in length), you do both of the following: 72 | 73 | a) Give prominent notice with each copy of the object code that the 74 | Library is used in it and that the Library and its use are 75 | covered by this License. 76 | 77 | b) Accompany the object code with a copy of the GNU GPL and this license 78 | document. 79 | 80 | 4. Combined Works. 81 | 82 | You may convey a Combined Work under terms of your choice that, 83 | taken together, effectively do not restrict modification of the 84 | portions of the Library contained in the Combined Work and reverse 85 | engineering for debugging such modifications, if you also do each of 86 | the following: 87 | 88 | a) Give prominent notice with each copy of the Combined Work that 89 | the Library is used in it and that the Library and its use are 90 | covered by this License. 91 | 92 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 93 | document. 94 | 95 | c) For a Combined Work that displays copyright notices during 96 | execution, include the copyright notice for the Library among 97 | these notices, as well as a reference directing the user to the 98 | copies of the GNU GPL and this license document. 99 | 100 | d) Do one of the following: 101 | 102 | 0) Convey the Minimal Corresponding Source under the terms of this 103 | License, and the Corresponding Application Code in a form 104 | suitable for, and under terms that permit, the user to 105 | recombine or relink the Application with a modified version of 106 | the Linked Version to produce a modified Combined Work, in the 107 | manner specified by section 6 of the GNU GPL for conveying 108 | Corresponding Source. 109 | 110 | 1) Use a suitable shared library mechanism for linking with the 111 | Library. A suitable mechanism is one that (a) uses at run time 112 | a copy of the Library already present on the user's computer 113 | system, and (b) will operate properly with a modified version 114 | of the Library that is interface-compatible with the Linked 115 | Version. 116 | 117 | e) Provide Installation Information, but only if you would otherwise 118 | be required to provide such information under section 6 of the 119 | GNU GPL, and only to the extent that such information is 120 | necessary to install and execute a modified version of the 121 | Combined Work produced by recombining or relinking the 122 | Application with a modified version of the Linked Version. (If 123 | you use option 4d0, the Installation Information must accompany 124 | the Minimal Corresponding Source and Corresponding Application 125 | Code. If you use option 4d1, you must provide the Installation 126 | Information in the manner specified by section 6 of the GNU GPL 127 | for conveying Corresponding Source.) 128 | 129 | 5. Combined Libraries. 130 | 131 | You may place library facilities that are a work based on the 132 | Library side by side in a single library together with other library 133 | facilities that are not Applications and are not covered by this 134 | License, and convey such a combined library under terms of your 135 | choice, if you do both of the following: 136 | 137 | a) Accompany the combined library with a copy of the same work based 138 | on the Library, uncombined with any other library facilities, 139 | conveyed under the terms of this License. 140 | 141 | b) Give prominent notice with the combined library that part of it 142 | is a work based on the Library, and explaining where to find the 143 | accompanying uncombined form of the same work. 144 | 145 | 6. Revised Versions of the GNU Lesser General Public License. 146 | 147 | The Free Software Foundation may publish revised and/or new versions 148 | of the GNU Lesser General Public License from time to time. Such new 149 | versions will be similar in spirit to the present version, but may 150 | differ in detail to address new problems or concerns. 151 | 152 | Each version is given a distinguishing version number. If the 153 | Library as you received it specifies that a certain numbered version 154 | of the GNU Lesser General Public License "or any later version" 155 | applies to it, you have the option of following the terms and 156 | conditions either of that published version or of any later version 157 | published by the Free Software Foundation. If the Library as you 158 | received it does not specify a version number of the GNU Lesser 159 | General Public License, you may choose any version of the GNU Lesser 160 | General Public License ever published by the Free Software Foundation. 161 | 162 | If the Library as you received it specifies that a proxy can decide 163 | whether future versions of the GNU Lesser General Public License shall 164 | apply, that proxy's public statement of acceptance of any version is 165 | permanent authorization for you to choose that version for the 166 | Library. 167 | 168 |  169 | -------------------------------------------------------------------------------- /examples/simple dialogs/registration/license.txt: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | 5 | Copyright (C) 2007 Free Software Foundation, Inc. 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | 10 | This version of the GNU Lesser General Public License incorporates 11 | the terms and conditions of version 3 of the GNU General Public 12 | License, supplemented by the additional permissions listed below. 13 | 14 | 0. Additional Definitions. 15 | 16 | As used herein, "this License" refers to version 3 of the GNU Lesser 17 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 18 | General Public License. 19 | 20 | "The Library" refers to a covered work governed by this License, 21 | other than an Application or a Combined Work as defined below. 22 | 23 | An "Application" is any work that makes use of an interface provided 24 | by the Library, but which is not otherwise based on the Library. 25 | Defining a subclass of a class defined by the Library is deemed a mode 26 | of using an interface provided by the Library. 27 | 28 | A "Combined Work" is a work produced by combining or linking an 29 | Application with the Library. The particular version of the Library 30 | with which the Combined Work was made is also called the "Linked 31 | Version". 32 | 33 | The "Minimal Corresponding Source" for a Combined Work means the 34 | Corresponding Source for the Combined Work, excluding any source code 35 | for portions of the Combined Work that, considered in isolation, are 36 | based on the Application, and not on the Linked Version. 37 | 38 | The "Corresponding Application Code" for a Combined Work means the 39 | object code and/or source code for the Application, including any data 40 | and utility programs needed for reproducing the Combined Work from the 41 | Application, but excluding the System Libraries of the Combined Work. 42 | 43 | 1. Exception to Section 3 of the GNU GPL. 44 | 45 | You may convey a covered work under sections 3 and 4 of this License 46 | without being bound by section 3 of the GNU GPL. 47 | 48 | 2. Conveying Modified Versions. 49 | 50 | If you modify a copy of the Library, and, in your modifications, a 51 | facility refers to a function or data to be supplied by an Application 52 | that uses the facility (other than as an argument passed when the 53 | facility is invoked), then you may convey a copy of the modified 54 | version: 55 | 56 | a) under this License, provided that you make a good faith effort to 57 | ensure that, in the event an Application does not supply the 58 | function or data, the facility still operates, and performs 59 | whatever part of its purpose remains meaningful, or 60 | 61 | b) under the GNU GPL, with none of the additional permissions of 62 | this License applicable to that copy. 63 | 64 | 3. Object Code Incorporating Material from Library Header Files. 65 | 66 | The object code form of an Application may incorporate material from 67 | a header file that is part of the Library. You may convey such object 68 | code under terms of your choice, provided that, if the incorporated 69 | material is not limited to numerical parameters, data structure 70 | layouts and accessors, or small macros, inline functions and templates 71 | (ten or fewer lines in length), you do both of the following: 72 | 73 | a) Give prominent notice with each copy of the object code that the 74 | Library is used in it and that the Library and its use are 75 | covered by this License. 76 | 77 | b) Accompany the object code with a copy of the GNU GPL and this license 78 | document. 79 | 80 | 4. Combined Works. 81 | 82 | You may convey a Combined Work under terms of your choice that, 83 | taken together, effectively do not restrict modification of the 84 | portions of the Library contained in the Combined Work and reverse 85 | engineering for debugging such modifications, if you also do each of 86 | the following: 87 | 88 | a) Give prominent notice with each copy of the Combined Work that 89 | the Library is used in it and that the Library and its use are 90 | covered by this License. 91 | 92 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 93 | document. 94 | 95 | c) For a Combined Work that displays copyright notices during 96 | execution, include the copyright notice for the Library among 97 | these notices, as well as a reference directing the user to the 98 | copies of the GNU GPL and this license document. 99 | 100 | d) Do one of the following: 101 | 102 | 0) Convey the Minimal Corresponding Source under the terms of this 103 | License, and the Corresponding Application Code in a form 104 | suitable for, and under terms that permit, the user to 105 | recombine or relink the Application with a modified version of 106 | the Linked Version to produce a modified Combined Work, in the 107 | manner specified by section 6 of the GNU GPL for conveying 108 | Corresponding Source. 109 | 110 | 1) Use a suitable shared library mechanism for linking with the 111 | Library. A suitable mechanism is one that (a) uses at run time 112 | a copy of the Library already present on the user's computer 113 | system, and (b) will operate properly with a modified version 114 | of the Library that is interface-compatible with the Linked 115 | Version. 116 | 117 | e) Provide Installation Information, but only if you would otherwise 118 | be required to provide such information under section 6 of the 119 | GNU GPL, and only to the extent that such information is 120 | necessary to install and execute a modified version of the 121 | Combined Work produced by recombining or relinking the 122 | Application with a modified version of the Linked Version. (If 123 | you use option 4d0, the Installation Information must accompany 124 | the Minimal Corresponding Source and Corresponding Application 125 | Code. If you use option 4d1, you must provide the Installation 126 | Information in the manner specified by section 6 of the GNU GPL 127 | for conveying Corresponding Source.) 128 | 129 | 5. Combined Libraries. 130 | 131 | You may place library facilities that are a work based on the 132 | Library side by side in a single library together with other library 133 | facilities that are not Applications and are not covered by this 134 | License, and convey such a combined library under terms of your 135 | choice, if you do both of the following: 136 | 137 | a) Accompany the combined library with a copy of the same work based 138 | on the Library, uncombined with any other library facilities, 139 | conveyed under the terms of this License. 140 | 141 | b) Give prominent notice with the combined library that part of it 142 | is a work based on the Library, and explaining where to find the 143 | accompanying uncombined form of the same work. 144 | 145 | 6. Revised Versions of the GNU Lesser General Public License. 146 | 147 | The Free Software Foundation may publish revised and/or new versions 148 | of the GNU Lesser General Public License from time to time. Such new 149 | versions will be similar in spirit to the present version, but may 150 | differ in detail to address new problems or concerns. 151 | 152 | Each version is given a distinguishing version number. If the 153 | Library as you received it specifies that a certain numbered version 154 | of the GNU Lesser General Public License "or any later version" 155 | applies to it, you have the option of following the terms and 156 | conditions either of that published version or of any later version 157 | published by the Free Software Foundation. If the Library as you 158 | received it does not specify a version number of the GNU Lesser 159 | General Public License, you may choose any version of the GNU Lesser 160 | General Public License ever published by the Free Software Foundation. 161 | 162 | If the Library as you received it specifies that a proxy can decide 163 | whether future versions of the GNU Lesser General Public License shall 164 | apply, that proxy's public statement of acceptance of any version is 165 | permanent authorization for you to choose that version for the 166 | Library. 167 | 168 |  169 | -------------------------------------------------------------------------------- /templates/sidebar_convert_ext/3_license_lgpl3.txt: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | 5 | Copyright (C) 2007 Free Software Foundation, Inc. 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | 10 | This version of the GNU Lesser General Public License incorporates 11 | the terms and conditions of version 3 of the GNU General Public 12 | License, supplemented by the additional permissions listed below. 13 | 14 | 0. Additional Definitions. 15 | 16 | As used herein, "this License" refers to version 3 of the GNU Lesser 17 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 18 | General Public License. 19 | 20 | "The Library" refers to a covered work governed by this License, 21 | other than an Application or a Combined Work as defined below. 22 | 23 | An "Application" is any work that makes use of an interface provided 24 | by the Library, but which is not otherwise based on the Library. 25 | Defining a subclass of a class defined by the Library is deemed a mode 26 | of using an interface provided by the Library. 27 | 28 | A "Combined Work" is a work produced by combining or linking an 29 | Application with the Library. The particular version of the Library 30 | with which the Combined Work was made is also called the "Linked 31 | Version". 32 | 33 | The "Minimal Corresponding Source" for a Combined Work means the 34 | Corresponding Source for the Combined Work, excluding any source code 35 | for portions of the Combined Work that, considered in isolation, are 36 | based on the Application, and not on the Linked Version. 37 | 38 | The "Corresponding Application Code" for a Combined Work means the 39 | object code and/or source code for the Application, including any data 40 | and utility programs needed for reproducing the Combined Work from the 41 | Application, but excluding the System Libraries of the Combined Work. 42 | 43 | 1. Exception to Section 3 of the GNU GPL. 44 | 45 | You may convey a covered work under sections 3 and 4 of this License 46 | without being bound by section 3 of the GNU GPL. 47 | 48 | 2. Conveying Modified Versions. 49 | 50 | If you modify a copy of the Library, and, in your modifications, a 51 | facility refers to a function or data to be supplied by an Application 52 | that uses the facility (other than as an argument passed when the 53 | facility is invoked), then you may convey a copy of the modified 54 | version: 55 | 56 | a) under this License, provided that you make a good faith effort to 57 | ensure that, in the event an Application does not supply the 58 | function or data, the facility still operates, and performs 59 | whatever part of its purpose remains meaningful, or 60 | 61 | b) under the GNU GPL, with none of the additional permissions of 62 | this License applicable to that copy. 63 | 64 | 3. Object Code Incorporating Material from Library Header Files. 65 | 66 | The object code form of an Application may incorporate material from 67 | a header file that is part of the Library. You may convey such object 68 | code under terms of your choice, provided that, if the incorporated 69 | material is not limited to numerical parameters, data structure 70 | layouts and accessors, or small macros, inline functions and templates 71 | (ten or fewer lines in length), you do both of the following: 72 | 73 | a) Give prominent notice with each copy of the object code that the 74 | Library is used in it and that the Library and its use are 75 | covered by this License. 76 | 77 | b) Accompany the object code with a copy of the GNU GPL and this license 78 | document. 79 | 80 | 4. Combined Works. 81 | 82 | You may convey a Combined Work under terms of your choice that, 83 | taken together, effectively do not restrict modification of the 84 | portions of the Library contained in the Combined Work and reverse 85 | engineering for debugging such modifications, if you also do each of 86 | the following: 87 | 88 | a) Give prominent notice with each copy of the Combined Work that 89 | the Library is used in it and that the Library and its use are 90 | covered by this License. 91 | 92 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 93 | document. 94 | 95 | c) For a Combined Work that displays copyright notices during 96 | execution, include the copyright notice for the Library among 97 | these notices, as well as a reference directing the user to the 98 | copies of the GNU GPL and this license document. 99 | 100 | d) Do one of the following: 101 | 102 | 0) Convey the Minimal Corresponding Source under the terms of this 103 | License, and the Corresponding Application Code in a form 104 | suitable for, and under terms that permit, the user to 105 | recombine or relink the Application with a modified version of 106 | the Linked Version to produce a modified Combined Work, in the 107 | manner specified by section 6 of the GNU GPL for conveying 108 | Corresponding Source. 109 | 110 | 1) Use a suitable shared library mechanism for linking with the 111 | Library. A suitable mechanism is one that (a) uses at run time 112 | a copy of the Library already present on the user's computer 113 | system, and (b) will operate properly with a modified version 114 | of the Library that is interface-compatible with the Linked 115 | Version. 116 | 117 | e) Provide Installation Information, but only if you would otherwise 118 | be required to provide such information under section 6 of the 119 | GNU GPL, and only to the extent that such information is 120 | necessary to install and execute a modified version of the 121 | Combined Work produced by recombining or relinking the 122 | Application with a modified version of the Linked Version. (If 123 | you use option 4d0, the Installation Information must accompany 124 | the Minimal Corresponding Source and Corresponding Application 125 | Code. If you use option 4d1, you must provide the Installation 126 | Information in the manner specified by section 6 of the GNU GPL 127 | for conveying Corresponding Source.) 128 | 129 | 5. Combined Libraries. 130 | 131 | You may place library facilities that are a work based on the 132 | Library side by side in a single library together with other library 133 | facilities that are not Applications and are not covered by this 134 | License, and convey such a combined library under terms of your 135 | choice, if you do both of the following: 136 | 137 | a) Accompany the combined library with a copy of the same work based 138 | on the Library, uncombined with any other library facilities, 139 | conveyed under the terms of this License. 140 | 141 | b) Give prominent notice with the combined library that part of it 142 | is a work based on the Library, and explaining where to find the 143 | accompanying uncombined form of the same work. 144 | 145 | 6. Revised Versions of the GNU Lesser General Public License. 146 | 147 | The Free Software Foundation may publish revised and/or new versions 148 | of the GNU Lesser General Public License from time to time. Such new 149 | versions will be similar in spirit to the present version, but may 150 | differ in detail to address new problems or concerns. 151 | 152 | Each version is given a distinguishing version number. If the 153 | Library as you received it specifies that a certain numbered version 154 | of the GNU Lesser General Public License "or any later version" 155 | applies to it, you have the option of following the terms and 156 | conditions either of that published version or of any later version 157 | published by the Free Software Foundation. If the Library as you 158 | received it does not specify a version number of the GNU Lesser 159 | General Public License, you may choose any version of the GNU Lesser 160 | General Public License ever published by the Free Software Foundation. 161 | 162 | If the Library as you received it specifies that a proxy can decide 163 | whether future versions of the GNU Lesser General Public License shall 164 | apply, that proxy's public statement of acceptance of any version is 165 | permanent authorization for you to choose that version for the 166 | Library. 167 | 168 |  169 | -------------------------------------------------------------------------------- /templates/script_ext/3_license_apache2.txt: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. 10 | 11 | "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. 12 | 13 | "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. 14 | 15 | "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. 16 | 17 | "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. 18 | 19 | "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. 20 | 21 | "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). 22 | 23 | "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. 24 | 25 | "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." 26 | 27 | "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 28 | 29 | 2. Grant of Copyright License. 30 | 31 | Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 32 | 33 | 3. Grant of Patent License. 34 | 35 | Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 36 | 37 | 4. Redistribution. 38 | 39 | You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: 40 | 41 | You must give any other recipients of the Work or Derivative Works a copy of this License; and 42 | You must cause any modified files to carry prominent notices stating that You changed the files; and 43 | You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and 44 | If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. 45 | 46 | You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 47 | 48 | 5. Submission of Contributions. 49 | 50 | Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 51 | 52 | 6. Trademarks. 53 | 54 | This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 55 | 56 | 7. Disclaimer of Warranty. 57 | 58 | Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 59 | 60 | 8. Limitation of Liability. 61 | 62 | In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 63 | 64 | 9. Accepting Warranty or Additional Liability. 65 | 66 | While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. 67 | 68 | END OF TERMS AND CONDITIONS 69 | -------------------------------------------------------------------------------- /templates/sidebar_convert_ext/3_license_apache2.txt: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. 10 | 11 | "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. 12 | 13 | "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. 14 | 15 | "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. 16 | 17 | "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. 18 | 19 | "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. 20 | 21 | "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). 22 | 23 | "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. 24 | 25 | "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." 26 | 27 | "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 28 | 29 | 2. Grant of Copyright License. 30 | 31 | Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 32 | 33 | 3. Grant of Patent License. 34 | 35 | Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 36 | 37 | 4. Redistribution. 38 | 39 | You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: 40 | 41 | You must give any other recipients of the Work or Derivative Works a copy of this License; and 42 | You must cause any modified files to carry prominent notices stating that You changed the files; and 43 | You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and 44 | If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. 45 | 46 | You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 47 | 48 | 5. Submission of Contributions. 49 | 50 | Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 51 | 52 | 6. Trademarks. 53 | 54 | This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 55 | 56 | 7. Disclaimer of Warranty. 57 | 58 | Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 59 | 60 | 8. Limitation of Liability. 61 | 62 | In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 63 | 64 | 9. Accepting Warranty or Additional Liability. 65 | 66 | While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. 67 | 68 | END OF TERMS AND CONDITIONS 69 | -------------------------------------------------------------------------------- /unodit.py: -------------------------------------------------------------------------------- 1 | # This file is part of UNO Dialog Tools - UNODIT 2 | # Copyright © 2016-2019 Sasa Kelecevic 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with UNODIT. If not, see 16 | 17 | """ 18 | UNODIT executable module. 19 | 20 | """ 21 | 22 | 23 | import argparse 24 | import logging 25 | import os 26 | 27 | try: 28 | # extension 29 | import extractor 30 | import generator 31 | import oxt_creator as script 32 | import simple_dialogs as dialogs 33 | import embed_packer as ep 34 | import sidebar 35 | from config import LOGGER_NAME, LOG_FILE, VERSION, NOW, MAIN_DIR, ReadINI 36 | 37 | except ImportError: 38 | # command line 39 | import pythonpath.extractor as extractor 40 | import pythonpath.generator as generator 41 | import pythonpath.oxt_creator as script 42 | import pythonpath.simple_dialogs as dialogs 43 | import pythonpath.embed_packer as ep 44 | import pythonpath.sidebar as sidebar 45 | from pythonpath.config import ( 46 | LOGGER_NAME, 47 | LOG_FILE, 48 | VERSION, 49 | NOW, 50 | MAIN_DIR, 51 | ReadINI, 52 | ) 53 | 54 | 55 | def create_logger(lname, ldir, lfile): 56 | """Create logger 57 | 58 | :param lname:logger name 59 | :param ldir: logger directory 60 | :param lfile: logger file 61 | 62 | """ 63 | 64 | logger = logging.getLogger(lname) 65 | logger.setLevel(logging.DEBUG) 66 | # create file handler which logs even debug messages 67 | logfile = os.path.join(ldir, lfile) 68 | fh = logging.FileHandler(logfile, mode="w") 69 | fh.setLevel(logging.DEBUG) 70 | # create formatter and add it to the handlers 71 | formatter = logging.Formatter( 72 | "%(module)s - %(funcName)s - %(levelname)s - %(message)s" 73 | ) 74 | fh.setFormatter(formatter) 75 | # add the handlers to the logger 76 | logger.addHandler(fh) 77 | return logger 78 | 79 | 80 | def unodit(mode, pydir, xdlfile="", app="MyApp", panel=2, indent=4): 81 | """ 82 | UNODialogTools automate some of the tedious tasks with dialogs in order to help you write your own extension for LibreOffice in Python(PyUNO). 83 | 84 | :param mode: 85 | :param pydir: full path to the output directory 86 | :param xdlfile: full path to the xdl file 87 | :param app: application name 88 | :param panel: number od panels in sidebar, work with mode sidebar_convert 89 | :param indent: number of spaces used for indentation in the generated code. If 0, \t is used as indent 90 | 91 | """ 92 | logger = logging.getLogger("unodit") 93 | 94 | start_log = """ 95 | Version: {} Created: {} 96 | 97 | unodit directory = {} 98 | --------------------------------------------------------------------- 99 | mode = {} 100 | pydir = {} 101 | xdlfile = {} 102 | app name = {} 103 | panel = {} 104 | indent = {} 105 | --------------------------------------------------------------------- 106 | """.format( 107 | VERSION, NOW, MAIN_DIR, mode, pydir, xdlfile, app, panel, indent 108 | ) 109 | 110 | logger.info(start_log) 111 | 112 | def mode_script_convert(): 113 | logger.info( 114 | "\nMODE: ---------- script_convert ----------------------------------" 115 | ) 116 | ctx = extractor.ContextGenerator(xdlfile) 117 | ctx.get_xdl_context() 118 | uno_ctx = ctx.get_uno_context() 119 | cg = generator.CodeGenerator( 120 | mode, pydir, xdlfile, uno_ctx, app, indent=4 121 | ) 122 | cg.generate_code() 123 | 124 | def mode_script_files(): 125 | logger.info( 126 | "\nMODE: ---------- script_files ------------------------------------" 127 | ) 128 | sef = script.ScriptExtensionFiles(mode, pydir, app) 129 | sef.create() 130 | 131 | def mode_script_oxt(): 132 | logger.info( 133 | "\nMODE: ---------- script_oxt --------------------------------------" 134 | ) 135 | cse = script.CreateScriptExtension(mode, pydir, app) 136 | cse.create() 137 | 138 | def mode_script_all(): 139 | mode_script_convert() 140 | mode_script_files() 141 | mode_script_oxt() 142 | 143 | def mode_connect(): 144 | logger.info( 145 | "\nMODE: ---------- connect -----------------------------------------" 146 | ) 147 | ctx = extractor.ContextGenerator(xdlfile) 148 | ctx.get_xdl_context() 149 | uno_ctx = ctx.get_uno_context() 150 | cg = generator.CodeGenerator( 151 | mode, pydir, xdlfile, uno_ctx, app, indent=4 152 | ) 153 | cg.generate_code() 154 | 155 | def mode_embed_convert(): 156 | logger.info( 157 | "\nMODE: ---------- embed_convert -----------------------------------" 158 | ) 159 | ctx = extractor.ContextGenerator(xdlfile) 160 | ctx.get_xdl_context() 161 | uno_ctx = ctx.get_uno_context() 162 | cg = generator.CodeGenerator( 163 | mode, pydir, xdlfile, uno_ctx, app, indent=4 164 | ) 165 | cg.generate_code() 166 | 167 | def mode_embed_pack(): 168 | logger.info( 169 | "\nMODE: ---------- embed_pack --------------------------------------" 170 | ) 171 | e = ep.EmbedScript(pydir, app) 172 | e.pack_script() 173 | 174 | def mode_embed_all(): 175 | mode_embed_convert() 176 | mode_embed_pack() 177 | 178 | def mode_dialogs_create(): 179 | logger.info( 180 | "\nMODE: ---------- dialogs_create ----------------------------------" 181 | ) 182 | e = dialogs.EasyDialog(pydir, app) 183 | e.create_template() 184 | 185 | def mode_dialogs_files(): 186 | logger.info( 187 | "\nMODE: ---------- dialogs_files -----------------------------------" 188 | ) 189 | sef = script.ScriptExtensionFiles(mode, pydir, app) 190 | sef.create() 191 | 192 | def mode_dialogs_oxt(): 193 | logger.info( 194 | "\nMODE: ---------- dialogs_oxt -------------------------------------" 195 | ) 196 | cse = script.CreateScriptExtension(mode, pydir, app) 197 | cse.create() 198 | 199 | def mode_dialogs_all(): 200 | logger.info( 201 | "\nMODE: ---------- dialogs_all -------------------------------------" 202 | ) 203 | mode_dialogs_create() 204 | mode_dialogs_files() 205 | mode_dialogs_oxt() 206 | 207 | def mode_sidebar_convert(): 208 | logger.info( 209 | "\nMODE: ---------- sidebar_convert ---------------------------------" 210 | ) 211 | p_names = "" 212 | 213 | panel_names = {} 214 | 215 | # read config.ini for xdl file 216 | read_conf = ReadINI(MAIN_DIR, pydir) 217 | 218 | for i in range(0, panel): 219 | panel_section = "panel" + str(i + 1) 220 | file_xdl = read_conf.get(panel_section, "xdl_ui") 221 | panel_name = read_conf.get(panel_section, "name") 222 | # generate panel files 223 | ctx = extractor.ContextGenerator(file_xdl) 224 | ctx.get_xdl_context() 225 | uno_ctx = ctx.get_uno_context() 226 | cg = generator.CodeGenerator( 227 | mode, 228 | pydir, 229 | file_xdl, 230 | uno_ctx, 231 | app, 232 | indent=4, 233 | panel_name=panel_name, 234 | ) 235 | cg.generate_code() 236 | # generate panel options files 237 | panel_option_name = read_conf.get(panel_section, "option_name") 238 | file_option_xdl = read_conf.get(panel_section, "xdl_option_ui") 239 | if file_option_xdl: 240 | panel_names[panel_name] = panel_option_name 241 | ctx_option = extractor.ContextGenerator(file_option_xdl) 242 | ctx_option.get_xdl_context() 243 | uno_ctx_option = ctx_option.get_uno_context() 244 | cg_option = generator.CodeGenerator( 245 | mode, 246 | pydir, 247 | file_option_xdl, 248 | uno_ctx_option, 249 | app, 250 | indent=4, 251 | panel_name=panel_option_name, 252 | ) 253 | cg_option.generate_code() 254 | else: 255 | panel_names[panel_name] = "" 256 | 257 | p_names = p_names + panel_name + "," 258 | 259 | # generate sidebar main file 260 | p_names = p_names[:-1] 261 | # print(str(panel_names)) 262 | sb = sidebar.SidebarGenerator( 263 | mode, 264 | pydir, 265 | file_xdl, 266 | uno_ctx, 267 | app, 268 | indent=4, 269 | all_panels=panel_names, 270 | ) 271 | sb.generate_sidebar_code() 272 | 273 | def mode_sidebar_files(): 274 | logger.info( 275 | "\nMODE: ---------- dialogs_files -----------------------------------" 276 | ) 277 | sef = script.SidebarExtensionFiles(mode, pydir, app, panel) 278 | sef.create() 279 | 280 | def mode_sidebar_oxt(): 281 | logger.info( 282 | "\nMODE: ---------- sidebar_oxt -------------------------------------" 283 | ) 284 | cse = script.CreateSidebarExtension(mode, pydir, app, panel) 285 | cse.create() 286 | 287 | # def get_sidebar_panels(): 288 | # 289 | # for i in range(0, panel): 290 | # # read config.ini for xdl file 291 | # read_conf = ReadINI(MAIN_DIR, pydir) 292 | # panel_section = 'panel' + str(i + 1) 293 | # file_xdl = read_conf.get(panel_section, 'xdl_ui') 294 | # panel_name = read_conf.get(panel_section, 'name') 295 | # p_names = p_names + panel_name + ',' 296 | # 297 | # p_names = p_names[:-1] 298 | # return p_names 299 | 300 | # script - convert xdl file (1) 301 | if mode == "script_convert": 302 | mode_script_convert() 303 | 304 | # script - create script extension files (2) 305 | elif mode == "script_files": 306 | mode_script_files() 307 | 308 | # script - create script exstension (3) 309 | elif mode == "script_oxt": 310 | mode_script_oxt() 311 | 312 | # script all |1+2+3| (4) 313 | elif mode == "script_all": 314 | mode_script_all() 315 | 316 | # connect - connect to xdl file (5) 317 | elif mode == "connect": 318 | mode_connect() 319 | 320 | # embed dialog in document - convert xdl file (6) 321 | elif mode == "embed_convert": 322 | mode_embed_convert() 323 | 324 | # embed dialog in document - pack script in document (7) 325 | elif mode == "embed_pack": 326 | mode_embed_pack() 327 | 328 | # embed dialog in document all |6+7| (8) 329 | elif mode == "embed_all": 330 | mode_embed_all() 331 | 332 | # simple dialogs - create (9) 333 | elif mode == "dialogs_create": 334 | mode_dialogs_create() 335 | 336 | # simple dialogs - create script extension files (10) 337 | elif mode == "dialogs_files": 338 | mode_dialogs_files() 339 | 340 | # simple dialogs - create script exstension (11) 341 | elif mode == "dialogs_oxt": 342 | mode_dialogs_oxt() 343 | 344 | # simple dialogs all |9+10+11| (12) 345 | elif mode == "dialogs_all": 346 | mode_dialogs_all() 347 | 348 | # sidebar - convert xdl files (13) 349 | elif mode == "sidebar_convert": 350 | mode_sidebar_convert() 351 | 352 | # sidebar - create extension files (14) 353 | elif mode == "sidebar_files": 354 | mode_sidebar_files() 355 | 356 | # sidebar - create script exstension (15) 357 | elif mode == "sidebar_oxt": 358 | mode_sidebar_oxt() 359 | 360 | # sidebar all |13+14+15| (16) 361 | elif mode == "sidebar_all": 362 | mode_sidebar_convert() 363 | mode_sidebar_files() 364 | mode_sidebar_oxt() 365 | 366 | paths = "" 367 | for path, subdirs, files in os.walk(pydir): 368 | for name in files: 369 | paths = paths + os.path.join(path, name) + ",\n" 370 | # print(os.path.join(path, name)) 371 | 372 | logger.info("\nCONTENT:" + pydir + " directory:\n" + paths) 373 | 374 | print("Finished", " mode " + mode) 375 | return 0 376 | 377 | 378 | def create_parser(): 379 | """ 380 | Parses and returns arguments passed in 381 | """ 382 | 383 | desc = """ 384 | 385 | Example: 386 | 387 | Create python project TestLib in LIBREOFFICE_PATH/4/user/Scripts/python/ 388 | Replace LIBREOFFICE_PATH with actual path. 389 | 390 | """ 391 | 392 | # assign description to the help doc 393 | parser = argparse.ArgumentParser( 394 | prog="unodit", 395 | formatter_class=argparse.RawDescriptionHelpFormatter, 396 | epilog=desc, 397 | description="UNO Dialog Tools - unodit", 398 | ) 399 | 400 | # add arguments 401 | parser.add_argument( 402 | "-m", 403 | "--mode", 404 | type=str, 405 | help="choose mode", 406 | choices=[ 407 | "script_convert", 408 | "script_files", 409 | "script_oxt", 410 | "script_all", 411 | "connect", 412 | "embed_convert", 413 | "embed_pack", 414 | "embed_all", 415 | "dialogs_create", 416 | "dialogs_files", 417 | "dialogs_oxt", 418 | "dialogs_all", 419 | "sidebar_convert", 420 | "sidebar_files", 421 | "sidebar_oxt", 422 | "sidebar_all", 423 | ], 424 | required=True, 425 | ) 426 | 427 | parser.add_argument( 428 | "-d", 429 | "--dir", 430 | type=str, 431 | help="full path to the output directory", 432 | default=os.getcwd(), 433 | required=True, 434 | ) 435 | 436 | parser.add_argument( 437 | "-f", 438 | "--file", 439 | type=str, 440 | help="full path to the xdl file", 441 | required=False, 442 | ) 443 | 444 | parser.add_argument( 445 | "-a", 446 | "--appname", 447 | type=str, 448 | default="MyApp", 449 | help="application name", 450 | required=False, 451 | ) 452 | 453 | parser.add_argument( 454 | "-p", 455 | "--panel", 456 | type=int, 457 | default=2, 458 | help="number of panels in sidebar", 459 | required=False, 460 | ) 461 | 462 | parser.add_argument( 463 | "-i", 464 | "--indent", 465 | type=int, 466 | default=4, 467 | help="number of spaces used for indentation in the generated code. If 0, \t is used as indent", 468 | choices=[0, 1, 2, 3, 4], 469 | required=False, 470 | ) 471 | 472 | return parser 473 | 474 | 475 | def main(): 476 | """Run unodit.""" 477 | 478 | # parse arguments 479 | parser = create_parser() 480 | args = parser.parse_args() 481 | 482 | # normalize path 483 | args.dir = args.dir.rstrip(os.sep) 484 | # project directory 485 | if not os.path.exists(args.dir): 486 | os.makedirs(args.dir) 487 | 488 | # start logging 489 | create_logger(LOGGER_NAME, args.dir, LOG_FILE) 490 | 491 | unodit( 492 | args.mode, args.dir, args.file, args.appname, args.panel, args.indent 493 | ) 494 | 495 | 496 | if __name__ == "__main__": 497 | main() 498 | --------------------------------------------------------------------------------