summaryrefslogtreecommitdiffstats
path: root/odk/examples/python
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 05:54:39 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 05:54:39 +0000
commit267c6f2ac71f92999e969232431ba04678e7437e (patch)
tree358c9467650e1d0a1d7227a21dac2e3d08b622b2 /odk/examples/python
parentInitial commit. (diff)
downloadlibreoffice-267c6f2ac71f92999e969232431ba04678e7437e.tar.xz
libreoffice-267c6f2ac71f92999e969232431ba04678e7437e.zip
Adding upstream version 4:24.2.0.upstream/4%24.2.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'odk/examples/python')
-rw-r--r--odk/examples/python/DocumentHandling/DocumentConverter.py91
-rw-r--r--odk/examples/python/DocumentHandling/DocumentLoader.py68
-rw-r--r--odk/examples/python/DocumentHandling/DocumentPrinter.py71
-rw-r--r--odk/examples/python/DocumentHandling/DocumentSaver.py81
-rw-r--r--odk/examples/python/DocumentHandling/README.md56
-rw-r--r--odk/examples/python/DocumentHandling/tests/hello.odtbin0 -> 8471 bytes
-rw-r--r--odk/examples/python/Spreadsheet/ChartTypeChange.py101
-rw-r--r--odk/examples/python/Spreadsheet/EuroAdaption.py164
-rw-r--r--odk/examples/python/Spreadsheet/SCalc.py225
-rw-r--r--odk/examples/python/Text/BookmarkInsertion.py160
-rw-r--r--odk/examples/python/Text/GraphicsInserter.py100
-rw-r--r--odk/examples/python/Text/HardFormatting.py110
-rw-r--r--odk/examples/python/Text/SWriter.py210
-rw-r--r--odk/examples/python/Text/StyleCreation.py94
-rw-r--r--odk/examples/python/Text/StyleInitialization.py109
-rw-r--r--odk/examples/python/Text/TextDocumentStructure.py79
-rw-r--r--odk/examples/python/Text/TextReplace.py106
-rw-r--r--odk/examples/python/Text/WriterSelector.py67
-rw-r--r--odk/examples/python/toolpanel/CalcWindowState.xcu29
-rw-r--r--odk/examples/python/toolpanel/Factory.xcu34
-rw-r--r--odk/examples/python/toolpanel/META-INF/manifest.xml23
-rw-r--r--odk/examples/python/toolpanel/Makefile29
-rw-r--r--odk/examples/python/toolpanel/description.xml13
-rw-r--r--odk/examples/python/toolpanel/readme13
-rw-r--r--odk/examples/python/toolpanel/toolPanelPocBasic/Module1.xba29
-rw-r--r--odk/examples/python/toolpanel/toolPanelPocBasic/dialog.xlb3
-rw-r--r--odk/examples/python/toolpanel/toolPanelPocBasic/script.xlb5
-rw-r--r--odk/examples/python/toolpanel/toolpanel.component16
-rw-r--r--odk/examples/python/toolpanel/toolpanel.py139
-rw-r--r--odk/examples/python/toolpanel/toolpanels/poc.xdl11
30 files changed, 2236 insertions, 0 deletions
diff --git a/odk/examples/python/DocumentHandling/DocumentConverter.py b/odk/examples/python/DocumentHandling/DocumentConverter.py
new file mode 100644
index 0000000000..a1f54fca91
--- /dev/null
+++ b/odk/examples/python/DocumentHandling/DocumentConverter.py
@@ -0,0 +1,91 @@
+# -*- tab-width: 4; indent-tabs-mode: nil; py-indent-offset: 4 -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+import argparse
+import os
+import sys
+from os.path import abspath, basename, isdir, join, splitext
+
+import uno
+import unohelper
+from com.sun.star.beans import PropertyValue
+from com.sun.star.connection import NoConnectException
+
+PROG = "$OFFICE_PROGRAM_PATH/python {}".format(basename(sys.argv[0]))
+SOFFICE_CONNECTION_URI = "uno:socket,host=localhost,port=2083;urp;StarOffice.ComponentContext"
+
+
+def connect_soffice():
+ """Connect to remote running LibreOffice"""
+ local_context = uno.getComponentContext()
+ resolver = local_context.ServiceManager.createInstanceWithContext(
+ "com.sun.star.bridge.UnoUrlResolver", local_context
+ )
+ try:
+ remote_context = resolver.resolve(SOFFICE_CONNECTION_URI)
+ except NoConnectException:
+ raise Exception("Cannot establish a connection to LibreOffice.")
+
+ return remote_context.ServiceManager.createInstanceWithContext(
+ "com.sun.star.frame.Desktop", remote_context
+ )
+
+
+def convert(src_file, dest_file, to_type):
+ src_url = "file://{}".format(src_file).replace("\\", "/")
+ dest_url = "file://{}".format(dest_file).replace("\\", "/")
+
+ soffice = connect_soffice()
+ doc = soffice.loadComponentFromURL(
+ src_url, "_blank", 0, (PropertyValue(Name="Hidden", Value=True),)
+ )
+
+ opts = (
+ PropertyValue(Name="Overwrite", Value=True),
+ PropertyValue(Name="FilterName", Value=to_type),
+ )
+ try:
+ doc.storeAsURL(dest_url, opts);
+ finally:
+ doc.dispose()
+
+
+def is_dir(value):
+ if not isdir(value):
+ raise argparse.ArgumentTypeError("{} is not a directory.".format(value))
+ return value
+
+
+def main():
+ parser = argparse.ArgumentParser(description="Document Converter", prog=PROG)
+ parser.add_argument("from_dir",
+ type=is_dir,
+ help="Convert documents searched from this directory recursively")
+ parser.add_argument("to_type", help="Type to convert to, example: MS Word 97.")
+ parser.add_argument("extension",
+ help="Extension of the converted document, examples: doc, docx")
+ parser.add_argument("output_dir",
+ type=is_dir,
+ help="Converted document is stored into this directory")
+
+ args = parser.parse_args()
+
+ for dir_path, dir_names, file_names in os.walk(args.from_dir):
+ for name in file_names:
+ src_file = join(abspath(dir_path), name)
+ dest_file = "{}.{}".format(join(args.output_dir, splitext(name)[0]), args.extension)
+ convert(src_file, dest_file, args.to_type)
+ print("Converted", src_file, "to", dest_file)
+
+
+if __name__ == "__main__":
+ main()
+
+
+# vim: set shiftwidth=4 softtabstop=4 expandtab:
diff --git a/odk/examples/python/DocumentHandling/DocumentLoader.py b/odk/examples/python/DocumentHandling/DocumentLoader.py
new file mode 100644
index 0000000000..a88f3ad0d7
--- /dev/null
+++ b/odk/examples/python/DocumentHandling/DocumentLoader.py
@@ -0,0 +1,68 @@
+# -*- tab-width: 4; indent-tabs-mode: nil; py-indent-offset: 4 -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+import argparse
+import uno
+from com.sun.star.connection import NoConnectException
+from os.path import isfile, abspath, basename
+from sys import argv
+
+
+def is_file(value):
+ if not isfile(value):
+ raise argparse.ArgumentTypeError("{} could not be opened".format(value))
+ return value
+
+
+PROG = "$OFFICE_PROGRAM_PATH/python {}".format(basename(argv[0]))
+
+
+if __name__ == "__main__":
+ parser = argparse.ArgumentParser(prog=PROG)
+ parser.add_argument("--writer", action="store_true", required=False, help="Open an empty Writer document")
+ parser.add_argument("--calc", action="store_true", required=False, help="Open an empty Calc document")
+ parser.add_argument("--draw", action="store_true", required=False, help="Open an empty Draw document")
+ parser.add_argument("path",
+ type=is_file,
+ nargs="?",
+ help="Path to a document to load. If omitted, an empty document is opened accordingly.")
+ args = parser.parse_args()
+
+ # UNO component context for initializing the Python runtime
+ localContext = uno.getComponentContext()
+
+ # Create an instance of a service implementation
+ resolver = localContext.ServiceManager.createInstanceWithContext(
+ "com.sun.star.bridge.UnoUrlResolver", localContext)
+
+ try:
+ context = resolver.resolve(
+ "uno:socket,host=localhost,"
+ "port=2083;urp;StarOffice.ComponentContext")
+ except NoConnectException:
+ raise Exception("Error: cannot establish a connection to LibreOffice.")
+
+ desktop = context.ServiceManager.createInstanceWithContext(
+ "com.sun.star.frame.Desktop", context)
+
+ if args.path:
+ url = uno.systemPathToFileUrl(abspath(args.path))
+ elif args.writer:
+ url = "private:factory/swriter"
+ elif args.calc:
+ url = "private:factory/scalc"
+ elif args.draw:
+ url = "private:factory/sdraw"
+ else:
+ url = "private:factory/swriter"
+
+ # Load a LibreOffice document, and automatically display it on the screen
+ xComp = desktop.loadComponentFromURL(url, "_blank", 0, tuple([]))
+
+# vim: set shiftwidth=4 softtabstop=4 expandtab:
diff --git a/odk/examples/python/DocumentHandling/DocumentPrinter.py b/odk/examples/python/DocumentHandling/DocumentPrinter.py
new file mode 100644
index 0000000000..d9a4e29632
--- /dev/null
+++ b/odk/examples/python/DocumentHandling/DocumentPrinter.py
@@ -0,0 +1,71 @@
+# -*- tab-width: 4; indent-tabs-mode: nil; py-indent-offset: 4 -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+import argparse
+import sys
+from os.path import abspath, basename
+
+import uno
+import unohelper
+from com.sun.star.beans import PropertyValue
+from com.sun.star.connection import NoConnectException
+
+PROG = "$OFFICE_PROGRAM_PATH/python {}".format(basename(sys.argv[0]))
+SOFFICE_CONNECTION_URI = "uno:socket,host=localhost,port=2083;urp;StarOffice.ComponentContext"
+
+
+def connect_soffice():
+ """Connect to remote running LibreOffice
+
+ :return: an object representing the remote LibreOffice instance.
+ """
+ local_context = uno.getComponentContext()
+ resolver = local_context.ServiceManager.createInstanceWithContext(
+ "com.sun.star.bridge.UnoUrlResolver", local_context
+ )
+ try:
+ remote_context = resolver.resolve(SOFFICE_CONNECTION_URI)
+ except NoConnectException:
+ raise Exception("Cannot establish a connection to LibreOffice.")
+
+ return remote_context.ServiceManager.createInstanceWithContext(
+ "com.sun.star.frame.Desktop", remote_context
+ )
+
+
+def print_(doc_path, printer, pages):
+ soffice = connect_soffice()
+ doc_url = "file://{}".format(abspath(doc_path)).replace("\\", "/")
+ # Load a Writer document, which will be automatically displayed
+ doc = soffice.loadComponentFromURL(doc_url, "_blank", 0, tuple([]))
+ try:
+ doc.setPrinter((PropertyValue(Name="Name", Value=printer),))
+ print_opts = (
+ PropertyValue(Name="Pages", Value=pages),
+ )
+ doc.print(print_opts)
+ finally:
+ doc.dispose()
+
+
+def main():
+ parser = argparse.ArgumentParser(description="Document Printer", prog=PROG)
+ parser.add_argument("printer", help="Printer name")
+ parser.add_argument("doc_path", help="Path to a document to be printed")
+ parser.add_argument("pages", help="Page range to be printed, e.g. 1-3")
+
+ args = parser.parse_args()
+ print_(args.doc_path, args.printer, args.pages)
+
+
+if __name__ == "__main__":
+ main()
+
+
+# vim: set shiftwidth=4 softtabstop=4 expandtab:
diff --git a/odk/examples/python/DocumentHandling/DocumentSaver.py b/odk/examples/python/DocumentHandling/DocumentSaver.py
new file mode 100644
index 0000000000..e7d8010a23
--- /dev/null
+++ b/odk/examples/python/DocumentHandling/DocumentSaver.py
@@ -0,0 +1,81 @@
+# -*- tab-width: 4; indent-tabs-mode: nil; py-indent-offset: 4 -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+import argparse
+import sys
+from os.path import basename, abspath
+
+import uno
+import unohelper
+from com.sun.star.beans import PropertyValue
+from com.sun.star.connection import NoConnectException
+
+"""
+The purpose of this example is to open a specified text document and save this
+file to a specified URL. The type of the saved file is "writer8".
+"""
+
+PROG = "$OFFICE_PROGRAM_PATH/python {}".format(basename(sys.argv[0]))
+SOFFICE_CONNECTION_URI = "uno:socket,host=localhost,port=2083;urp;StarOffice.ComponentContext"
+
+
+def connect_soffice():
+ """Connect to remote running LibreOffice
+
+ :return: an object representing the remote LibreOffice instance.
+ """
+ local_context = uno.getComponentContext()
+ resolver = local_context.ServiceManager.createInstanceWithContext(
+ "com.sun.star.bridge.UnoUrlResolver", local_context
+ )
+ try:
+ remote_context = resolver.resolve(SOFFICE_CONNECTION_URI)
+ except NoConnectException:
+ raise Exception("Cannot establish a connection to LibreOffice.")
+
+ return remote_context.ServiceManager.createInstanceWithContext(
+ "com.sun.star.frame.Desktop", remote_context
+ )
+
+
+def save_doc(src, dest):
+ src_url = "file://{}".format(abspath(src)).replace("\\", "/")
+ dest_url = "file://{}".format(abspath(dest)).replace("\\", "/")
+
+ soffice = connect_soffice()
+ doc = soffice.loadComponentFromURL(
+ src_url, "_blank", 0, (PropertyValue(Name="Hidden", Value=True),)
+ )
+
+ save_opts = (
+ PropertyValue(Name="Overwrite", Value=True),
+ PropertyValue(Name="FilterName", Value="writer8"),
+ )
+ try:
+ doc.storeAsURL(dest_url, save_opts)
+ print("Document", src, "saved under", dest)
+ finally:
+ doc.dispose()
+ print("Document closed!")
+
+
+def main():
+ parser = argparse.ArgumentParser(description="Document Saver", prog=PROG)
+ parser.add_argument("src", help="Path to a Word document to be saved, e.g. path/to/hello.doc")
+ parser.add_argument("dest", help="Save the document to here, e.g. path/to/hello.odt")
+
+ args = parser.parse_args()
+ save_doc(args.src, args.dest)
+
+
+if __name__ == "__main__":
+ main()
+
+
+# vim: set shiftwidth=4 softtabstop=4 expandtab:
diff --git a/odk/examples/python/DocumentHandling/README.md b/odk/examples/python/DocumentHandling/README.md
new file mode 100644
index 0000000000..7e0e8aa43e
--- /dev/null
+++ b/odk/examples/python/DocumentHandling/README.md
@@ -0,0 +1,56 @@
+# Document Handling Examples
+
+These examples are somehow similar to DocumentLoader in C++ and Java.
+To get started, first start LibreOffice listening on port 2083
+
+ $OFFICE_PROGRAM_PATH/soffice "--accept=socket,port=2083;urp;"
+
+Each example script accepts `-h` to show the usage, e.g.
+
+ $OFFICE_PROGRAM_PATH/python DocumentLoader.py -h
+
+You should use `setsdkenv_unix` for Unix/Linux and `setsdkenv_windows.bat` for
+Windows. In this way, the LibreOffice internal Python interpreter will be used.
+
+## Document Converter
+
+```bash
+$OFFICE_PROGRAM_PATH/python DocumentConverter.py ./tests/ "MS Word 97" doc /tmp/
+```
+
+This command searches LibreOffice documents recursively under directory
+`./tests` and convert every found document to format Microsoft Word 97. The
+converted document can be found under directory `/tmp`.
+
+## Document Loader
+
+```bash
+$OFFICE_PROGRAM_PATH/python DocumentLoader.py ./tests/hello.odt
+```
+
+This command opens document `./tests/hello.odt` in a separate window.
+
+This script also accepts option to open an empty document. For example, to open
+an empty spreadsheet document:
+
+```bash
+$OFFICE_PROGRAM_PATH/python DocumentLoader.py --calc
+```
+
+## Document Printer
+
+```bash
+$OFFICE_PROGRAM_PATH/python DocumentPrinter.py myprinter ./tests/hello.odt "1-3"
+```
+
+This command prints the first three pages of document `./tests/hello.odt` on
+printer `myprinter `. You can also specify the page range in various format,
+e.g. `1,3-5`.
+
+## Document Saver
+
+```bash
+$OFFICE_PROGRAM_PATH/python DocumentSaver.py path/to/hello.doc path/to/hello.odt
+```
+
+This command saves a Word document `hello.doc` as an OpenDocument file `hello.odt`.
diff --git a/odk/examples/python/DocumentHandling/tests/hello.odt b/odk/examples/python/DocumentHandling/tests/hello.odt
new file mode 100644
index 0000000000..dd72ae9ec4
--- /dev/null
+++ b/odk/examples/python/DocumentHandling/tests/hello.odt
Binary files differ
diff --git a/odk/examples/python/Spreadsheet/ChartTypeChange.py b/odk/examples/python/Spreadsheet/ChartTypeChange.py
new file mode 100644
index 0000000000..6ee2c31d67
--- /dev/null
+++ b/odk/examples/python/Spreadsheet/ChartTypeChange.py
@@ -0,0 +1,101 @@
+# -*- tab-width: 4; indent-tabs-mode: nil; py-indent-offset: 4 -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+import sys
+import time
+import traceback
+from typing import Union
+
+import officehelper
+from com.sun.star.awt import Rectangle
+
+
+def main():
+ try:
+ remote_context = officehelper.bootstrap()
+ srv_mgr = remote_context.getServiceManager()
+ desktop = srv_mgr.createInstanceWithContext(
+ "com.sun.star.frame.Desktop", remote_context
+ )
+ doc = desktop.loadComponentFromURL("private:factory/scalc", "_blank", 0, tuple())
+ sheet = doc.Sheets[0]
+
+ cell_values = (
+ ("", "Jan", "Feb", "Mar", "Apr", "Mai"),
+ ("Profit", 12.3, 43.2, 5.1, 76, 56.8),
+ ("Rival in business", 12.2, 12.6, 17.7, 20.4, 100),
+ )
+
+ # Write the data into spreadsheet.
+ for row, row_data in enumerate(cell_values):
+ for column, cell_value in enumerate(row_data):
+ insert_into_cell(column, row, cell_value, sheet)
+
+ # Create a rectangle, which holds the size of the chart.
+ rect = Rectangle()
+ rect.X, rect.Y, rect.Width, rect.Height = 500, 3000, 25000, 11000
+
+ # Create the Unicode of the character for the column name.
+ char_rect = chr(65 + len(cell_values[0]) - 1)
+ # Get the cell range of the written values.
+ chart_cell_range = sheet[f"A1:{char_rect}{len(cell_values)}"]
+ # Create a table chart with all written values
+ chart_data_source = [chart_cell_range.RangeAddress]
+
+ sheet.Charts.addNewByName("Example", rect, chart_data_source, True, True)
+
+ # Get the newly created chart
+ table_chart = sheet.Charts["Example"]
+
+ # Change chart types one by one
+ chart_types = (
+ "com.sun.star.chart.LineDiagram",
+ "com.sun.star.chart.BarDiagram",
+ "com.sun.star.chart.PieDiagram",
+ "com.sun.star.chart.NetDiagram",
+ "com.sun.star.chart.XYDiagram",
+ "com.sun.star.chart.StockDiagram",
+ "com.sun.star.chart.AreaDiagram",
+ )
+ total = len(chart_types)
+
+ for i, type_name in enumerate(chart_types, start=1):
+ time.sleep(3)
+ print("Change chart type to:", f"[{i}/{total}]", type_name)
+ try:
+ chart_doc = table_chart.EmbeddedObject
+ chart_doc.Title.String = f"Chart Type: {type_name}"
+ diagram = chart_doc.createInstance(type_name)
+ diagram.Dim3D = False
+ chart_doc.Diagram = diagram
+ except Exception as e:
+ print(f"Fail to change chart type to {type_name}: {e}", file=sys.stderr)
+ traceback.print_exc()
+ except Exception as e:
+ print(f"Fail to change chart type: {e}", file=sys.stderr)
+ traceback.print_exc()
+
+
+def insert_into_cell(column: int, row: int, value: Union[str, float], sheet):
+ try:
+ cell = sheet[row, column]
+ except com.sun.star.lang.IndexOutOfBoundsException:
+ print("Could not get Cell", file=sys.stderr)
+ traceback.print_exc()
+ else:
+ if isinstance(value, str):
+ cell.String = value
+ else:
+ cell.Value = value
+
+
+if __name__ == "__main__":
+ main()
+
+# vim: set shiftwidth=4 softtabstop=4 expandtab:
diff --git a/odk/examples/python/Spreadsheet/EuroAdaption.py b/odk/examples/python/Spreadsheet/EuroAdaption.py
new file mode 100644
index 0000000000..dc3cbbfb47
--- /dev/null
+++ b/odk/examples/python/Spreadsheet/EuroAdaption.py
@@ -0,0 +1,164 @@
+# -*- tab-width: 4; indent-tabs-mode: nil; py-indent-offset: 4 -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+import sys
+import traceback
+
+import officehelper
+from com.sun.star.lang import Locale
+from com.sun.star.util import NumberFormat
+from com.sun.star.sheet import CellFlags
+
+
+def get_desktop():
+ desktop = None
+ try:
+ remote_context = officehelper.bootstrap()
+ srv_mgr = remote_context.getServiceManager()
+ if srv_mgr is None:
+ print("Can't create a desktop. No connection, no remote office servicemanager available!")
+ else:
+ desktop = srv_mgr.createInstanceWithContext("com.sun.star.frame.Desktop", remote_context)
+ except:
+ traceback.print_exc()
+ sys.exit(1)
+ return desktop
+
+
+def get_number_format_key(number_formats, format: str, language) -> int:
+ """Get number format key, create one if not exist yet.
+
+ :param number_formats: object managing number formats. It implements XNumberFormats interface.
+ :param str format: the number format.
+ :param language: language locale.
+ :type language: com.sun.star.lang.Locale
+ :return: key of the number format specific to the given language and format.
+ """
+ key = 0
+ try:
+ # Try to query the existing number format
+ if (key := number_formats.queryKey(format, language, True)) == -1:
+ # If not exist, create a new one
+ if (key := number_formats.addNew(format, language)) == -1:
+ key == 0
+ except:
+ traceback.print_exc()
+ return key
+
+
+def create_example_data(sheet, number_formats):
+ """Create example data with specific number format.
+
+ :param sheet: spreadsheet object. It implements XSpreadsheet interface.
+ :param number_formats: object managing number formats. It implements XNumberFormats interface.
+ """
+ try:
+ language = Locale()
+ language.Country = "de" # Germany -> DM
+ language.Language = "de" # German
+
+ # Numberformat string from DM
+ simple = "0 [$DM]"
+ number_format_key = get_number_format_key(number_formats, simple, language)
+
+ for counter in range(1, 10):
+ cell = sheet[1 + counter, 2]
+ cell.Value = float(counter * 2)
+ cell.NumberFormat = number_format_key
+ cell_range = sheet[counter + 1:counter + 2, 2:3]
+ cell_range.NumberFormat = number_format_key
+ except:
+ traceback.print_exc()
+
+
+def convert(sheet, number_formats, old_symbol: str, new_symbol: str, factor: float):
+ """Convert the currency
+
+ :param sheet: spreadsheet object. It implements XSpreadsheet interface.
+ :param number_formats: object managing number formats. It implements XNumberFormats interface.
+ :param str old_symbol: the old number format symbol.
+ :param str new_symbol: convert to this the new one.
+ :param float factor: conversion factor.
+ """
+ try:
+ language = Locale()
+ language.Country = "de" # Germany -> DM
+ language.Language = "de" # German
+
+ simple = f"0 [${new_symbol}]"
+ simple_key = get_number_format_key(number_formats, simple, language)
+
+ for cell_range in sheet.CellFormatRanges:
+ format = number_formats.getByKey(cell_range.NumberFormat)
+ format_type = format.Type
+ currency_symbol = format.CurrencySymbol
+ if format_type & NumberFormat.CURRENCY and currency_symbol == old_symbol:
+ thousands_sep = format.ThousandsSeparator
+ negative_red = format.NegativeRed
+ decimals = format.Decimals
+ leading_zeros = format.LeadingZeros
+ locale = format.Locale
+ # create a new numberformat string
+ new_number_format = number_formats.generateFormat(
+ simple_key, locale, thousands_sep, negative_red, decimals, leading_zeros
+ )
+ # get the NumberKey from the numberformat
+ new_number_format_key = get_number_format_key(number_formats, new_number_format, locale)
+ # set the new numberformat to the cellrange DM->EUR
+ cell_range.NumberFormat = new_number_format_key
+
+ # iterate over all cells from the cellrange with a
+ # content and use the DM/EUR factor
+ sheet_cell_ranges = cell_range.queryContentCells(CellFlags.VALUE)
+ if sheet_cell_ranges.getCount() > 0:
+ for cell in sheet_cell_ranges.getCells():
+ cell.Value = cell.Value / factor
+ except:
+ traceback.print_exc()
+
+
+def main():
+ desktop = get_desktop()
+ if desktop is None:
+ return
+
+ try:
+ doc = desktop.loadComponentFromURL("private:factory/scalc", "_blank", 0, tuple())
+ print("Create a new Spreadsheet")
+ except:
+ traceback.print_exc()
+ return
+
+ # the Action Interface provides methods to hide actions,
+ # like inserting data, on a sheet, that increase the performance
+ doc.addActionLock()
+
+ try:
+ sheet = doc.Sheets[0]
+ except:
+ traceback.print_exc()
+ return
+
+ # insert some example data in a sheet
+ create_example_data(sheet, doc.NumberFormats)
+ print("Insert example data and use the number format with the currency 'DM'")
+
+ # Change the currency from the cells from DM to Euro
+ convert(sheet, doc.NumberFormats, "DM", "EUR", 1.95583)
+ print("Change the number format to EUR and divide the values with the factor 1.95583")
+
+ # remove all locks, the user see all changes
+ doc.removeActionLock()
+ print("done")
+
+
+if __name__ == "__main__":
+ main()
+
+# vim: set shiftwidth=4 softtabstop=4 expandtab:
diff --git a/odk/examples/python/Spreadsheet/SCalc.py b/odk/examples/python/Spreadsheet/SCalc.py
new file mode 100644
index 0000000000..c016b96ef1
--- /dev/null
+++ b/odk/examples/python/Spreadsheet/SCalc.py
@@ -0,0 +1,225 @@
+# -*- tab-width: 4; indent-tabs-mode: nil; py-indent-offset: 4 -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+import sys
+import time
+import traceback
+
+import officehelper
+from com.sun.star.awt import Rectangle
+
+"""
+Step 1: get the remote component context from the office
+Step 2: open an empty calc document
+Step 3: create cell styles
+Step 4: get the sheet an insert some data
+Step 5: apply the created cell styles
+Step 6: insert a 3D Chart
+"""
+
+
+def main():
+ # oooooooooooooooooooooooooooStep 1oooooooooooooooooooooooooooooooooooooooooo
+ # call UNO bootstrap method and get the remote component context form
+ # the a running office (office will be started if necessary)
+ try:
+ remote_context = officehelper.bootstrap()
+ print("Connected to a running office ...")
+ srv_mgr = remote_context.getServiceManager()
+ desktop = srv_mgr.createInstanceWithContext(
+ "com.sun.star.frame.Desktop", remote_context
+ )
+ except:
+ traceback.print_exc()
+ sys.exit(1)
+
+ # oooooooooooooooooooooooooooStep 2oooooooooooooooooooooooooooooooooooooooooo
+ # open an empty document. In this case it's a calc document.
+ # For this purpose an instance of com.sun.star.frame.Desktop
+ # is created. The desktop provides the XComponentLoader interface,
+ # which is used to open the document via loadComponentFromURL
+ print("Opening an empty Calc document")
+ doc_url = "private:factory/scalc"
+ try:
+ doc = desktop.loadComponentFromURL(doc_url, "_blank", 0, tuple())
+ except:
+ traceback.print_exc()
+ return
+
+ # oooooooooooooooooooooooooooStep 3oooooooooooooooooooooooooooooooooooooooooo
+ # create cell styles.
+ # For this purpose get the StyleFamiliesSupplier and the family CellStyle.
+ # Create an instance of com.sun.star.style.CellStyle and add it to the family.
+ # Now change some properties
+
+ try:
+ cell_styles = doc.StyleFamilies["CellStyles"]
+ cell_style = doc.createInstance("com.sun.star.style.CellStyle")
+ cell_styles["My Style"] = cell_style
+ cell_style.IsCellBackgroundTransparent = False
+ cell_style.CellBackColor = 6710932
+ cell_style.CharColor = 16777215
+ cell_style = doc.createInstance("com.sun.star.style.CellStyle")
+ cell_styles["My Style2"] = cell_style
+ cell_style.IsCellBackgroundTransparent = False
+ cell_style.CellBackColor = 13421823
+ except:
+ traceback.print_exc()
+
+ # oooooooooooooooooooooooooooStep 4oooooooooooooooooooooooooooooooooooooooooo
+ # get the sheet an insert some data.
+ # Get the sheets from the document and then the first from this container.
+ # Now some data can be inserted. For this purpose get a Cell via
+ # getCellByPosition and insert into this cell via setValue() (for floats)
+ # or setFormula() for formulas and Strings.
+ # As a Python example, those calls are made in equivalent Pythonic ways.
+
+ print("Getting spreadsheet")
+ try:
+ sheet = doc.Sheets[0]
+ except Exception as e:
+ print(f"Couldn't get Sheet: {e}")
+ traceback.print_exc()
+ sys.exit(1)
+
+ print("Creating the Header")
+
+ insert_into_cell(1, 0, "JAN", sheet, "")
+ insert_into_cell(2, 0, "FEB", sheet, "")
+ insert_into_cell(3, 0, "MAR", sheet, "")
+ insert_into_cell(4, 0, "APR", sheet, "")
+ insert_into_cell(5, 0, "MAI", sheet, "")
+ insert_into_cell(6, 0, "JUN", sheet, "")
+ insert_into_cell(7, 0, "JUL", sheet, "")
+ insert_into_cell(8, 0, "AUG", sheet, "")
+ insert_into_cell(9, 0, "SEP", sheet, "")
+ insert_into_cell(10, 0, "OCT", sheet, "")
+ insert_into_cell(11, 0, "NOV", sheet, "")
+ insert_into_cell(12, 0, "DEC", sheet, "")
+ insert_into_cell(13, 0, "SUM", sheet, "")
+
+ print("Fill the lines")
+
+ insert_into_cell(0, 1, "Smith", sheet, "")
+ insert_into_cell(1, 1, "42", sheet, "V")
+ insert_into_cell(2, 1, "58.9", sheet, "V")
+ insert_into_cell(3, 1, "-66.5", sheet, "V")
+ insert_into_cell(4, 1, "43.4", sheet, "V")
+ insert_into_cell(5, 1, "44.5", sheet, "V")
+ insert_into_cell(6, 1, "45.3", sheet, "V")
+ insert_into_cell(7, 1, "-67.3", sheet, "V")
+ insert_into_cell(8, 1, "30.5", sheet, "V")
+ insert_into_cell(9, 1, "23.2", sheet, "V")
+ insert_into_cell(10, 1, "-97.3", sheet, "V")
+ insert_into_cell(11, 1, "22.4", sheet, "V")
+ insert_into_cell(12, 1, "23.5", sheet, "V")
+ insert_into_cell(13, 1, "=SUM(B2:M2)", sheet, "")
+
+ insert_into_cell(0, 2, "Jones", sheet, "")
+ insert_into_cell(1, 2, "21", sheet, "V")
+ insert_into_cell(2, 2, "40.9", sheet, "V")
+ insert_into_cell(3, 2, "-57.5", sheet, "V")
+ insert_into_cell(4, 2, "-23.4", sheet, "V")
+ insert_into_cell(5, 2, "34.5", sheet, "V")
+ insert_into_cell(6, 2, "59.3", sheet, "V")
+ insert_into_cell(7, 2, "27.3", sheet, "V")
+ insert_into_cell(8, 2, "-38.5", sheet, "V")
+ insert_into_cell(9, 2, "43.2", sheet, "V")
+ insert_into_cell(10, 2, "57.3", sheet, "V")
+ insert_into_cell(11, 2, "25.4", sheet, "V")
+ insert_into_cell(12, 2, "28.5", sheet, "V")
+ insert_into_cell(13, 2, "=SUM(B3:M3)", sheet, "")
+
+ insert_into_cell(0, 3, "Brown", sheet, "")
+ insert_into_cell(1, 3, "31.45", sheet, "V")
+ insert_into_cell(2, 3, "-20.9", sheet, "V")
+ insert_into_cell(3, 3, "-117.5", sheet, "V")
+ insert_into_cell(4, 3, "23.4", sheet, "V")
+ insert_into_cell(5, 3, "-114.5", sheet, "V")
+ insert_into_cell(6, 3, "115.3", sheet, "V")
+ insert_into_cell(7, 3, "-171.3", sheet, "V")
+ insert_into_cell(8, 3, "89.5", sheet, "V")
+ insert_into_cell(9, 3, "41.2", sheet, "V")
+ insert_into_cell(10, 3, "71.3", sheet, "V")
+ insert_into_cell(11, 3, "25.4", sheet, "V")
+ insert_into_cell(12, 3, "38.5", sheet, "V")
+ insert_into_cell(13, 3, "=SUM(A4:L4)", sheet, "")
+
+ # oooooooooooooooooooooooooooStep 5oooooooooooooooooooooooooooooooooooooooooo
+ # apply the created cell style.
+ # For this purpose get the PropertySet of the Cell and change the
+ # property CellStyle to the appropriate value.
+
+ change_backcolor(1, 0, 13, 0, "My Style", sheet)
+ change_backcolor(0, 1, 0, 3, "My Style", sheet)
+ change_backcolor(1, 1, 13, 3, "My Style2", sheet)
+
+ # oooooooooooooooooooooooooooStep 6oooooooooooooooooooooooooooooooooooooooooo
+ # insert a 3D chart.
+ # get the CellRange which holds the data for the chart and its RangeAddress
+ # get the TableChartSupplier from the sheet and then the TableCharts from it.
+ # add a new chart based on the data to the TableCharts.
+ # get the ChartDocument, which provide the Diagram. Change the properties
+ # Dim3D (3 dimension) and String (the title) of the diagram.
+
+ rect = Rectangle()
+ rect.X, rect.Y, rect.Width, rect.Height = 500, 3000, 25000, 11000
+
+ print("Insert Chart")
+ data_range = (sheet["A1:N4"].RangeAddress,)
+ sheet.Charts.addNewByName("Example", rect, data_range, True, True)
+
+ # get the diagram and change some of the properties
+ try:
+ chart = sheet.Charts["Example"]
+ # chart object implements XEmbeddedObjectSupplier interface
+ diagram = chart.EmbeddedObject.Diagram
+ print("Change Diagram to 3D")
+ diagram.Dim3D = True
+
+ print("Change the title")
+ time.sleep(.2)
+ chart.EmbeddedObject.Title.String = "The new title"
+ except Exception as e:
+ print(f"Changing Properties failed: {e}", file=sys.stderr)
+ traceback.print_exc()
+
+ print("done")
+
+
+def insert_into_cell(column: int, row: int, value: str, sheet, flag: str):
+ try:
+ cell = sheet[row, column]
+ except com.sun.star.lang.IndexOutOfBoundsException:
+ print("Could not get Cell", file=sys.stderr)
+ traceback.print_exc()
+ else:
+ if flag == "V":
+ cell.Value = float(value)
+ else:
+ cell.Formula = value
+
+
+def change_backcolor(left: int, top: int, right: int, bottom: int, template: str, sheet):
+ try:
+ cell_range = sheet[top:bottom + 1, left:right + 1]
+ cell_range.CellStyle = template
+ except com.sun.star.lang.IndexOutOfBoundsException:
+ print("Could not get CellRange", file=sys.stderr)
+ traceback.print_exc()
+ except Exception as e:
+ print(f"Can't change colors chgbColor: {e}", file=sys.stderr)
+ traceback.print_exc()
+
+
+if __name__ == "__main__":
+ main()
+
+
+# vim: set shiftwidth=4 softtabstop=4 expandtab:
diff --git a/odk/examples/python/Text/BookmarkInsertion.py b/odk/examples/python/Text/BookmarkInsertion.py
new file mode 100644
index 0000000000..5b801f6121
--- /dev/null
+++ b/odk/examples/python/Text/BookmarkInsertion.py
@@ -0,0 +1,160 @@
+# -*- tab-width: 4; indent-tabs-mode: nil; py-indent-offset: 4 -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+import officehelper
+import sys
+import traceback
+
+
+FIRST_PARAGRAPH = (
+ "He heard quiet steps behind him. That didn't bode well. Who could be following "
+ "him this late at night and in this deadbeat part of town? And at this "
+ "particular moment, just after he pulled off the big time and was making off "
+ "with the greenbacks. Was there another crook who'd had the same idea, and was "
+ "now watching him and waiting for a chance to grab the fruit of his labor?"
+)
+
+SECOND_PARAGRAPH = (
+ "Or did the steps behind him mean that one of many bloody officers in town was "
+ "on to him and just waiting to pounce and snap those cuffs on his wrists? He "
+ "nervously looked all around. Suddenly he saw the alley. Like lightning he "
+ "darted off to the left and disappeared between the two warehouses almost "
+ "falling over the trash can lying in the middle of the sidewalk. He tried to "
+ "nervously tap his way along in the inky darkness and suddenly stiffened: it was "
+ "a dead-end, he would have to go back the way he had come"
+)
+
+THIRD_PARAGRAPH = (
+ "The steps got louder and louder, he saw the black outline of a figure coming "
+ "around the corner. Is this the end of the line? he thought pressing himself "
+ "back against the wall trying to make himself invisible in the dark, was all "
+ "that planning and energy wasted? He was dripping with sweat now, cold and wet, "
+ "he could smell the brilliant fear coming off his clothes. Suddenly next to him, "
+ "with a barely noticeable squeak, a door swung quietly to and fro in the night's "
+ "breeze."
+)
+
+
+def create_example_text(component):
+ """Create example text
+
+ :param component: object which implements com.sun.star.text.XTextDocument interface.
+ """
+ try:
+ cursor = component.getText().createTextCursor()
+ cursor.setString(FIRST_PARAGRAPH)
+ cursor.collapseToEnd()
+ cursor.setString(SECOND_PARAGRAPH)
+ cursor.collapseToEnd()
+ cursor.setString(THIRD_PARAGRAPH)
+ cursor.gotoStart(False)
+ except:
+ traceback.print_exc()
+
+
+def find_first(document, search_str):
+ """Find the text
+
+ :param document: object which implements com.sun.star.text.XTextDocument interface.
+ :param str search_str: the search string.
+ :return: object representing the searched text, which implements com.sun.star.text.XTextRange interface.
+ :rtype: com.sun.star.uno.XInterface
+ """
+ try:
+ descriptor = document.createSearchDescriptor()
+ descriptor.setSearchString(search_str)
+ descriptor.setPropertyValue("SearchRegularExpression", True)
+ return document.findFirst(descriptor)
+ except:
+ traceback.print_exc()
+ return None
+
+
+def insert_bookmark(document, text_range, bookmark_name):
+ """Insert bookmark
+
+ :param document: object which implements om.sun.star.text.XTextDocument interface.
+ :param text_range: object representing the text range bookmark is inserted for.
+ This object should implement com.sun.star.text.XTextRange interface.
+ :param str bookmark_name: bookmark name.
+ """
+ try:
+ bookmark = document.createInstance("com.sun.star.text.Bookmark")
+ bookmark.setName(bookmark_name)
+ document.getText().insertTextContent(text_range, bookmark, True)
+ print("Insert bookmark:", bookmark_name)
+ except:
+ traceback.print_exc()
+
+
+def mark_list(component, mlist, prefix):
+ """Mark the matched text
+
+ :param component: object which implements com.sun.star.text.XTextDocument interface.
+ :param list[str] mlist: list of patterns to search text from document.
+ :param str prefix: prefix used to construct bookmark name.
+ """
+ try:
+ for i, search_str in enumerate(mlist):
+ search = find_first(component, search_str)
+ if not search:
+ continue
+ insert_bookmark(component, search, f"{prefix}{i}")
+ except:
+ traceback.print_exc()
+ sys.exit(1)
+
+
+def get_desktop():
+ desktop = None
+ try:
+ remote_context = officehelper.bootstrap()
+ srv_mgr = remote_context.getServiceManager()
+ if srv_mgr is None:
+ print("Can't create a desktop. No connection, no remote office servicemanager available!")
+ else:
+ desktop = srv_mgr.createInstanceWithContext("com.sun.star.frame.Desktop", remote_context)
+ print("Connected to a running office ...")
+ except:
+ traceback.print_exc()
+ sys.exit(1)
+ return desktop
+
+
+def main():
+ desktop = get_desktop()
+ if desktop is None:
+ return
+
+ # Open an empty text document.
+ try:
+ doc = desktop.loadComponentFromURL("private:factory/swriter", "_blank", 0, tuple([]))
+ except:
+ traceback.print_exc()
+ sys.exit(1)
+
+ create_example_text(doc)
+
+ mOffending = ["negro(e|es)?", "bor(ed|ing)?", "bloody?", "bleed(ing)?"]
+ mBad = ["possib(le|ilit(y|ies))", "real(ly)+", "brilliant"]
+
+ sOffendPrefix = "Offending"
+ sBadPrefix = "BadStyle"
+
+ mark_list(doc, mOffending, sOffendPrefix)
+ mark_list(doc, mBad, sBadPrefix)
+
+ print("Done")
+
+
+if __name__ == "__main__":
+ main()
+
+
+# vim: set shiftwidth=4 softtabstop=4 expandtab:
diff --git a/odk/examples/python/Text/GraphicsInserter.py b/odk/examples/python/Text/GraphicsInserter.py
new file mode 100644
index 0000000000..3d09aedd5a
--- /dev/null
+++ b/odk/examples/python/Text/GraphicsInserter.py
@@ -0,0 +1,100 @@
+# -*- tab-width: 4; indent-tabs-mode: nil; py-indent-offset: 4 -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+import argparse
+import sys
+import traceback
+from os.path import isfile, dirname, join
+
+import officehelper
+from com.sun.star.beans import PropertyValue
+from com.sun.star.text.TextContentAnchorType import AT_PARAGRAPH
+
+LOG_FILE = join(dirname(__file__), "log.txt")
+
+
+def insert_graphic(filename):
+ remote_context = officehelper.bootstrap()
+ srv_mgr = remote_context.getServiceManager()
+ desktop = srv_mgr.createInstanceWithContext("com.sun.star.frame.Desktop", remote_context)
+
+ doc_url = "private:factory/swriter"
+ doc = desktop.loadComponentFromURL(doc_url, "_blank", 0, tuple())
+
+ log_file = open(LOG_FILE, "w")
+
+ text = doc.getText()
+ cursor = text.createTextCursor()
+
+ try:
+ graphic = doc.createInstance("com.sun.star.text.TextGraphicObject")
+ except:
+ traceback.print_exc(file=log_file)
+ return
+
+ log_file.write("inserting graphic\n")
+ try:
+ text.insertTextContent(cursor, graphic, True)
+ except:
+ print("Could not insert Content")
+ traceback.print_exc()
+ return
+
+ log_file.write("adding graphic\n")
+ try:
+ graphic_url = f"file://{filename}".replace("\\", "/")
+ print("insert graphic: %s", graphic_url)
+ graphic_provider = srv_mgr.createInstanceWithContext(
+ "com.sun.star.graphic.GraphicProvider", remote_context
+ )
+ loaded_graphic = graphic_provider.queryGraphic(
+ (PropertyValue(Name="URL", Value=graphic_url),)
+ )
+
+ # Setting the graphic url
+ graphic.setPropertyValue("Graphic", loaded_graphic)
+
+ # Set properties for the inserted graphic
+ graphic.setPropertyValue("AnchorType", AT_PARAGRAPH)
+ # Setting the horizontal position
+ graphic.setPropertyValue("HoriOrientPosition", 5500)
+ # Setting the vertical position
+ graphic.setPropertyValue("VertOrientPosition", 4200)
+ # Setting the width
+ graphic.setPropertyValue("Width", 4400)
+ # Setting the height
+ graphic.setPropertyValue("Height", 4000)
+ except:
+ print("Couldn't set property 'GraphicURL'")
+ traceback.print_exc(file=log_file)
+
+ log_file.close()
+
+
+def is_file(value):
+ if not isfile(value):
+ raise argparse.ArgumentTypeError(f"File {value} is not an image file.")
+ return value
+
+
+def main():
+ parser = argparse.ArgumentParser()
+ parser.add_argument("image", type=is_file, help="Path to an image file.")
+ args = parser.parse_args()
+ try:
+ insert_graphic(args.image)
+ except:
+ traceback.print_exc()
+ sys.exit(1)
+
+
+if __name__ == "__main__":
+ main()
+
+# vim: set shiftwidth=4 softtabstop=4 expandtab:
diff --git a/odk/examples/python/Text/HardFormatting.py b/odk/examples/python/Text/HardFormatting.py
new file mode 100644
index 0000000000..9a9734c60b
--- /dev/null
+++ b/odk/examples/python/Text/HardFormatting.py
@@ -0,0 +1,110 @@
+# -*- tab-width: 4; indent-tabs-mode: nil; py-indent-offset: 4 -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+import officehelper
+import sys
+import traceback
+
+from com.sun.star.awt import Size
+from com.sun.star.awt.FontWeight import BOLD
+from com.sun.star.beans.PropertyState import AMBIGUOUS_VALUE
+from com.sun.star.beans.PropertyState import DEFAULT_VALUE
+from com.sun.star.beans.PropertyState import DIRECT_VALUE
+from com.sun.star.text.ControlCharacter import PARAGRAPH_BREAK
+
+
+def get_desktop():
+ desktop = None
+ try:
+ remote_context = officehelper.bootstrap()
+ srv_mgr = remote_context.getServiceManager()
+ if srv_mgr is None:
+ print("Can't create a desktop. No connection, no remote office servicemanager available!")
+ else:
+ desktop = srv_mgr.createInstanceWithContext("com.sun.star.frame.Desktop", remote_context)
+ except:
+ traceback.print_exc()
+ sys.exit(1)
+ return desktop
+
+
+def main():
+ desktop = get_desktop()
+ if desktop is None:
+ return
+
+ try:
+ doc = desktop.loadComponentFromURL("private:factory/swriter", "_blank", 0, tuple())
+
+ text = doc.getText()
+ cursor = text.createTextCursor()
+
+ text.insertString(cursor, "Headline", False)
+ text.insertControlCharacter(cursor, PARAGRAPH_BREAK, False)
+ text.insertString(cursor, "A very short paragraph for illustration only", False)
+
+ # Start 'Hard formatting'
+ # the text range not the cursor contains the 'parastyle' property
+ text_range = text.getEnd()
+ text_range.gotoStart(False)
+ text_range.gotoEndOfParagraph(True)
+
+ # Later, we will go through words in this text range
+ text_range = text_range.getText().getStart()
+ # Display the current text attributes
+ print("Parastyle:", text_range.getPropertyValue("ParaStyleName"))
+ print("Fontname: ", text_range.getPropertyValue("CharFontName"))
+ print("Weight: ", text_range.getPropertyValue("CharWeight"))
+
+ # Move around
+ text_range.gotoNextWord(False)
+ text_range.gotoNextWord(False)
+ text_range.gotoEndOfWord(True)
+ # And set text attributes
+ text_range.setPropertyValue("CharWeight", BOLD)
+ text_range.setPropertyValue("CharColor", 255)
+ # Then, display the text attributes
+ print("Parastyle:", text_range.getPropertyValue("ParaStyleName"))
+ print("Fontname: ", text_range.getPropertyValue("CharFontName"))
+ print("Weight: ", text_range.getPropertyValue("CharWeight"))
+
+ # the PropertyState contains information where the attribute is set,
+ # is a text part hard formatted or not.
+ check_property_state(text_range, text_range.getPropertyState("CharWeight"))
+
+ print("Increase the selection with three characters")
+ text_range.goRight(3, True)
+ check_property_state(text_range, text_range.getPropertyState("CharWeight"))
+
+ print("Set the default value on the selection")
+ text_range.setPropertyToDefault("CharWeight")
+ # Then, check again
+ check_property_state(text_range, text_range.getPropertyState("CharWeight"))
+ except:
+ traceback.print_exc()
+ sys.exit(1)
+
+ print("Done")
+
+
+def check_property_state(text_range, prop_state):
+ if prop_state == DIRECT_VALUE:
+ print("-> The selection", f"'{text_range.getString()}'", "completely hard formatted")
+ elif prop_state == DEFAULT_VALUE:
+ print("-> The selection", f"'{text_range.getString()}'", "isn't hard formatted")
+ elif prop_state == AMBIGUOUS_VALUE:
+ print("-> The selection", f"'{text_range.getString()}'", "isn't completely hard formatted")
+ else:
+ print("No PropertyState found")
+
+
+if __name__ == "__main__":
+ main()
+
+# vim: set shiftwidth=4 softtabstop=4 expandtab:
diff --git a/odk/examples/python/Text/SWriter.py b/odk/examples/python/Text/SWriter.py
new file mode 100644
index 0000000000..3af42f352e
--- /dev/null
+++ b/odk/examples/python/Text/SWriter.py
@@ -0,0 +1,210 @@
+# -*- tab-width: 4; indent-tabs-mode: nil; py-indent-offset: 4 -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+import officehelper
+import sys
+import traceback
+
+from com.sun.star.awt import Size
+from com.sun.star.text.ControlCharacter import PARAGRAPH_BREAK
+from com.sun.star.text.TextContentAnchorType import AS_CHARACTER
+
+
+def main():
+ try:
+ # Step 1: bootstrap UNO and get the remote component context. The
+ # context can be used to get the service manager.
+ remote_context = officehelper.bootstrap()
+ print("Connected to a running office ...")
+ srv_mgr = remote_context.getServiceManager()
+ desktop = srv_mgr.createInstanceWithContext("com.sun.star.frame.Desktop", remote_context)
+
+ # Step 2: open an empty document. In this case it's a writer document.
+ # For this purpose an instance of com.sun.star.frame.Desktop is
+ # created. It's interface XDesktop provides the XComponentLoader,
+ # which is used to open the document via loadComponentFromURL
+ print("Opening an empty Writer document")
+ doc_url = "private:factory/swriter"
+ doc = desktop.loadComponentFromURL(doc_url, "_blank", 0, tuple())
+ except Exception as e:
+ print(f"d", file=sys.stderr)
+ traceback.print_exc()
+ sys.exit(1)
+
+ generate(doc)
+
+
+def generate(doc):
+ # Step 3: insert some text
+ text = doc.getText()
+ cursor = text.createTextCursor()
+
+ text.insertString(cursor, "The first line in the newly created text document.\n", False)
+ text.insertString(cursor, "Now we're in the second line\n", False)
+
+ # Step 4: insert a text table
+ insert_table(doc, text, cursor)
+
+ # Step 5: insert a colored text
+ try:
+ cursor.setPropertyValue("CharColor", 255)
+ cursor.setPropertyValue("CharShadowed", True)
+ except:
+ print("Couldn't change the color", file=sys.stderr)
+ traceback.print_exc()
+
+ try:
+ text.insertControlCharacter(cursor, PARAGRAPH_BREAK, False)
+ except Exception as e:
+ print(f"Couldn't insert break: {e}", file=sys.stderr)
+ traceback.print_exc()
+
+ print("Inserting colored Text")
+ text.insertString(cursor, " This is a colored Text - blue with shadow\n", False)
+
+ try:
+ text.insertControlCharacter(cursor, PARAGRAPH_BREAK, False)
+ except Exception as e:
+ print(f"Couldn't insert break: {e}", file=sys.stderr)
+ traceback.print_exc()
+
+ # Step 6: insert a text frame
+ insert_frame_with_text(doc, text, cursor)
+
+ try:
+ text.insertControlCharacter(cursor, PARAGRAPH_BREAK, False)
+ except Exception as e:
+ print(f"Couldn't insert break: {e}", file=sys.stderr)
+ traceback.print_exc()
+
+ try:
+ cursor.setPropertyValue("CharColor", 65536)
+ cursor.setPropertyValue("CharShadowed", False)
+ except Exception as e:
+ print(f"Couldn't change the color: {e}", file=sys.stderr)
+
+ text.insertString(cursor, " That's all for now !!", False)
+
+ print("done")
+
+
+def insert_table(doc, text, cursor):
+ print("Inserting a text table")
+ try:
+ text_table = doc.createInstance("com.sun.star.text.TextTable")
+ except Exception as e:
+ print(f"Couldn't create instance of TextTable: {e}", file=sys.stderr)
+ traceback.print_exc()
+ return
+
+ # initialize the text table with 4 columns an 4 rows
+ text_table.initialize(4, 4)
+
+ try:
+ text.insertTextContent(cursor, text_table, False)
+ except Exception as e:
+ print(f"Couldn't insert the table: {e}", file=sys.stderr)
+ traceback.print_exc()
+ return
+
+ # Get the first row
+ rows = text_table.getRows()
+ first_row = rows[0]
+
+ try:
+ # Set properties of the text table
+ text_table.setPropertyValue("BackTransparent", False)
+ text_table.setPropertyValue("BackColor", 13421823)
+ # Set properties of the first row
+ first_row.setPropertyValue("BackTransparent", False)
+ first_row.setPropertyValue("BackColor", 6710932)
+ except Exception as e:
+ print(f"Couldn't change the color: {e}", file=sys.stderr)
+ traceback.print_exc()
+
+ print("Write text in the table headers")
+ insert_into_cell("A1", "FirstColumn", text_table)
+ insert_into_cell("B1", "SecondColumn", text_table)
+ insert_into_cell("C1", "ThirdColumn", text_table)
+ insert_into_cell("D1", "SUM", text_table)
+
+ print("Insert something in the text table")
+ data = (
+ ("A2", 22.5, False),
+ ("B2", 5615.3, False),
+ ("C2", -2315.7, False),
+ ("D2", "sum <A2:C2>", True),
+ ("A3", 21.5, False),
+ ("B3", 615.3, False),
+ ("C3", -315.7, False),
+ ("D3", "sum <A3:C3>", True),
+ ("A4", 121.5, False),
+ ("B4", -615.3, False),
+ ("C4", 415.7, False),
+ ("D4", "sum <A4:C4>", True),
+ )
+ for cell_name, value, is_formula in data:
+ cell = text_table.getCellByName(cell_name)
+ if is_formula:
+ cell.setFormula(value)
+ else:
+ cell.setValue(value)
+
+
+def insert_frame_with_text(doc, text, cursor):
+ try:
+ text_frame = doc.createInstance("com.sun.star.text.TextFrame")
+ frame_size = Size()
+ frame_size.Height = 400
+ frame_size.Width = 15000
+ text_frame.setSize(frame_size)
+ except Exception as e:
+ print(f"Couldn't create instance: {e}", file=sys.stderr)
+ traceback.print_exc()
+ return
+
+ # Change the AnchorType
+ try:
+ text_frame.setPropertyValue("AnchorType", AS_CHARACTER)
+ except Exception as e:
+ print(f"Couldn't change the color: {e}", file=sys.stderr)
+ traceback.print_exc()
+
+ print("Insert the text frame")
+
+ try:
+ text.insertTextContent(cursor, text_frame, False)
+ except Exception as e:
+ print(f"Couldn't insert the frame: {e}", file=sys.stderr)
+ traceback.print_exc()
+
+ frame_text = text_frame.getText()
+ frame_cursor = frame_text.createTextCursor()
+ s = "The first line in the newly created text frame."
+ text_frame.insertString(frame_cursor, s, False)
+ s = "\nWith this second line the height of the frame raises."
+ text_frame.insertString(frame_cursor, s, False)
+
+
+def insert_into_cell(cell_name: str, content: str, text_table):
+ cell = text_table.getCellByName(cell_name)
+ cursor = cell.createTextCursor()
+ try:
+ cursor.setPropertyValue("CharColor", 16777215)
+ except Exception as e:
+ print(f"Fail to set CharColor property: {e}", file=sys.stderr)
+ traceback.print_exc()
+ # inserting some Text
+ cell.setString(content)
+
+
+if __name__ == "__main__":
+ main()
+
+# vim: set shiftwidth=4 softtabstop=4 expandtab:
diff --git a/odk/examples/python/Text/StyleCreation.py b/odk/examples/python/Text/StyleCreation.py
new file mode 100644
index 0000000000..629b530e9f
--- /dev/null
+++ b/odk/examples/python/Text/StyleCreation.py
@@ -0,0 +1,94 @@
+# -*- tab-width: 4; indent-tabs-mode: nil; py-indent-offset: 4 -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+import officehelper
+import sys
+import traceback
+
+from com.sun.star.awt.FontWeight import BOLD
+from com.sun.star.style.BreakType import PAGE_AFTER
+from com.sun.star.style.ParagraphAdjust import CENTER
+
+NEW_STYLE_NAME = "myheading"
+
+
+def create_style(component):
+ properties = component.createInstance("com.sun.star.style.ParagraphStyle")
+ properties.setPropertyValue("CharFontName", "Liberation Sans")
+ print("set name of the font to 'Liberation Sans'")
+
+ properties.setPropertyValue("CharHeight", float(36))
+ print("Change the height of th font to 36")
+
+ properties.setPropertyValue("CharWeight", float(BOLD))
+ print("set the font attribute 'Bold'")
+
+ properties.setPropertyValue("CharAutoKerning", True)
+ print("set the paragraph attribute 'AutoKerning'")
+
+ properties.setPropertyValue("ParaAdjust", CENTER)
+ print("set the paragraph adjust to LEFT")
+
+ properties.setPropertyValue("ParaFirstLineIndent", 0)
+ print("set the first line indent to 0 cm")
+
+ properties.setPropertyValue("BreakType", PAGE_AFTER)
+ print("set the paragraph attribute Breaktype to PageAfter")
+
+ # insert the new Paragraph style in the Paragraph style collection
+ style_families = component.getStyleFamilies()
+ paragraph_style_col = style_families["ParagraphStyles"]
+ paragraph_style_col[NEW_STYLE_NAME] = properties
+ print("create new paragraph style, with the values from the Propertyset")
+
+
+def apply_style(component):
+ text_range = component.getText().getStart()
+ # change the value from the property 'ParaStyle' to apply the Paragraph style
+ # To run the sample with StarOffice 5.2 you'll have to change
+ # 'ParaStyleName' to 'ParaStyle' in the next line
+ text_range.setPropertyValue("ParaStyleName", NEW_STYLE_NAME)
+ print("apply the new paragraph style")
+
+
+def get_desktop():
+ desktop = None
+ try:
+ remote_context = officehelper.bootstrap()
+ srv_mgr = remote_context.getServiceManager()
+ if srv_mgr is None:
+ print("Can't create a desktop. No connection, no remote office servicemanager available!")
+ else:
+ desktop = srv_mgr.createInstanceWithContext("com.sun.star.frame.Desktop", remote_context)
+ except:
+ traceback.print_exc()
+ sys.exit(1)
+ return desktop
+
+
+def main():
+ desktop = get_desktop()
+ if desktop is None:
+ return
+
+ try:
+ doc = desktop.loadComponentFromURL("private:factory/swriter", "_blank", 0, tuple())
+ create_style(doc)
+ apply_style(doc)
+ except:
+ traceback.print_exc()
+ sys.exit(1)
+
+ print("Done")
+
+
+if __name__ == "__main__":
+ main()
+
+# vim: set shiftwidth=4 softtabstop=4 expandtab:
diff --git a/odk/examples/python/Text/StyleInitialization.py b/odk/examples/python/Text/StyleInitialization.py
new file mode 100644
index 0000000000..a4d29b3443
--- /dev/null
+++ b/odk/examples/python/Text/StyleInitialization.py
@@ -0,0 +1,109 @@
+# -*- tab-width: 4; indent-tabs-mode: nil; py-indent-offset: 4 -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+import officehelper
+import sys
+import traceback
+
+from com.sun.star.text.ControlCharacter import PARAGRAPH_BREAK
+
+
+def get_desktop():
+ desktop = None
+ try:
+ remote_context = officehelper.bootstrap()
+ srv_mgr = remote_context.getServiceManager()
+ if srv_mgr is None:
+ print("Can't create a desktop. No connection, no remote office servicemanager available!")
+ else:
+ desktop = srv_mgr.createInstanceWithContext("com.sun.star.frame.Desktop", remote_context)
+ except:
+ traceback.print_exc()
+ sys.exit(1)
+ return desktop
+
+
+def main():
+ desktop = get_desktop()
+ if desktop is None:
+ return
+
+ try:
+ doc_url = "private:factory/swriter"
+ doc = desktop.loadComponentFromURL(doc_url, "_blank", 0, tuple())
+
+ text = doc.getText()
+ cursor = text.createTextCursor()
+
+ try:
+ cursor.setPropertyValue("CharFontName", "Arial")
+ except:
+ pass
+ text.insertString(cursor, "Headline", False)
+
+ try:
+ cursor.setPropertyValue("CharFontName", "Liberation Sans")
+ except:
+ pass
+ text.insertControlCharacter(cursor, PARAGRAPH_BREAK, False)
+ text.insertString(cursor, "A very short paragraph for illustration only", False)
+
+ # The text range not the cursor contains the 'ParaStyleName' property
+ text_range = text.getEnd()
+ # To run the sample with StarOffice 5.2 you'll have to change
+ # 'ParaStyleName' to 'ParaStyle' in the next line
+ print("Current Parastyle:", text_range.getPropertyValue("ParaStyleName"))
+
+ # There are two way to travel through the paragraphs, with a paragraph
+ # cursor, or an enumeration. You find both ways in this example
+
+ # The first way, with the paragraph cursor
+ # Object text_range supports interface com.sun.star.text.XParagraphCursor
+ text_range.gotoStart(False)
+ text_range.gotoEndOfParagraph(True)
+
+ # The second way, with the paragraph enumeration
+ paragraph_enumeration = text.createEnumeration()
+ while paragraph_enumeration.hasMoreElements():
+ paragraph = paragraph_enumeration.nextElement()
+ paragraph_text = paragraph.getAnchor().getString()
+ # Create a cursor from this paragraph
+ paragraph_cursor = paragraph.getAnchor().getText().createTextCursor()
+
+ # Goto the start and end of the paragraph
+ paragraph_cursor.gotoStart(False)
+ paragraph_cursor.gotoEnd(True)
+
+ portion_enumeration = paragraph.createEnumeration()
+ while portion_enumeration.hasMoreElements():
+ word = portion_enumeration.nextElement()
+ print("Content of the paragraph:", word.getString())
+
+ # Find a paragraph style by a specific font name and apply the found
+ # style to paragraph.
+ style_families = doc.getStyleFamilies()
+ styles = style_families["ParagraphStyles"]
+ for style_name in styles.getElementNames():
+ style = styles[style_name]
+ font_name = style.getPropertyValue("CharFontName").lower()
+ if font_name == "liberation mono":
+ text_range.setPropertyValue("ParaStyleName", style_name)
+ print("Apply the paragraph style:", style_name)
+ break
+ except:
+ traceback.print_exc()
+
+ print("Done")
+
+
+if __name__ == "__main__":
+ main()
+
+
+# vim: set shiftwidth=4 softtabstop=4 expandtab:
diff --git a/odk/examples/python/Text/TextDocumentStructure.py b/odk/examples/python/Text/TextDocumentStructure.py
new file mode 100644
index 0000000000..da677113a1
--- /dev/null
+++ b/odk/examples/python/Text/TextDocumentStructure.py
@@ -0,0 +1,79 @@
+# -*- tab-width: 4; indent-tabs-mode: nil; py-indent-offset: 4 -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+import officehelper
+import sys
+import traceback
+
+from com.sun.star.awt.FontWeight import BOLD
+from com.sun.star.beans.PropertyState import AMBIGUOUS_VALUE
+from com.sun.star.beans.PropertyState import DEFAULT_VALUE
+from com.sun.star.beans.PropertyState import DIRECT_VALUE
+
+
+def main():
+ try:
+ remote_context = officehelper.bootstrap()
+ srv_mgr = remote_context.getServiceManager()
+ desktop = srv_mgr.createInstanceWithContext("com.sun.star.frame.Desktop", remote_context)
+
+ doc_url = "private:factory/swriter"
+ doc = desktop.loadComponentFromURL(doc_url, "_blank", 0, tuple())
+ text = doc.getText()
+ create_example_data(text)
+ display_structure(text)
+ except:
+ traceback.print_exc()
+ sys.exit(1)
+
+ print("done")
+
+
+def create_example_data(text):
+ try:
+ text.setString("This is an example sentence")
+ cursor = text.getStart()
+ cursor.gotoNextWord(False)
+ cursor.gotoNextWord(False)
+ cursor.gotoEndOfWord(True)
+ cursor.setPropertyValue("CharWeight", BOLD)
+ print("create example data")
+ except:
+ traceback.print_exc()
+
+
+def display_structure(text):
+ print("Document structure:")
+ # Create an enumeration of all paragraphs
+ paragraph_enum = text.createEnumeration()
+ # Loop through all paragraphs of the document
+ for element in paragraph_enum:
+ if not element.supportsService("com.sun.star.text.Paragraph"):
+ print("The text portion isn't a text paragraph")
+ continue
+
+ print("This is a Paragraph")
+ for portion in element.createEnumeration():
+ print("Text from the portion:", f"{portion.getString()}")
+ print("Name of the font:", portion.getPropertyValue("CharFontName"))
+ char_weight = portion.getPropertyState("CharWeight")
+ if char_weight == AMBIGUOUS_VALUE:
+ print(" - The text range contains more than one different attributes")
+ elif char_weight == DIRECT_VALUE:
+ print(" - The text range contains hard formats")
+ elif char_weight == DEFAULT_VALUE:
+ print(" - The text range doesn't contains hard formats")
+ else:
+ pass # Do nothing
+
+
+if __name__ == "__main__":
+ main()
+
+# vim: set shiftwidth=4 softtabstop=4 expandtab:
diff --git a/odk/examples/python/Text/TextReplace.py b/odk/examples/python/Text/TextReplace.py
new file mode 100644
index 0000000000..78d301998f
--- /dev/null
+++ b/odk/examples/python/Text/TextReplace.py
@@ -0,0 +1,106 @@
+# -*- tab-width: 4; indent-tabs-mode: nil; py-indent-offset: 4 -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+import officehelper
+import sys
+import traceback
+
+from com.sun.star.awt import Size
+from com.sun.star.text.ControlCharacter import PARAGRAPH_BREAK
+from com.sun.star.text.TextContentAnchorType import AS_CHARACTER
+
+
+def get_desktop():
+ desktop = None
+ try:
+ remote_context = officehelper.bootstrap()
+ srv_mgr = remote_context.getServiceManager()
+ if srv_mgr is None:
+ print("Can't create a desktop. No connection, no remote office servicemanager available!")
+ else:
+ desktop = srv_mgr.createInstanceWithContext("com.sun.star.frame.Desktop", remote_context)
+ except:
+ traceback.print_exc()
+ sys.exit(1)
+ return desktop
+
+
+def main():
+ desktop = get_desktop()
+ if desktop is None:
+ return
+
+ print("Opening an empty Writer document")
+
+ try:
+ doc = desktop.loadComponentFromURL("private:factory/swriter", "_blank", 0, tuple())
+ except:
+ traceback.print_exc()
+ sys.exit(1)
+
+ create_example_data(doc)
+
+ british_words = ["colour", "neighbour", "centre", "behaviour", "metre", "through"]
+ us_words = ["color", "neighbor", "center", "behavior", "meter", "thru"]
+
+ try:
+ replace_descriptor = doc.createReplaceDescriptor()
+ print("Change all occurrences of ...")
+ for british_word, us_word in zip(british_words, us_words):
+ replace_descriptor.setSearchString(british_word)
+ replace_descriptor.setReplaceString(us_word)
+ # Replace all words
+ replaced_cnt = doc.replaceAll(replace_descriptor)
+ if replaced_cnt > 0:
+ print("Replaced", british_word, "with", us_word)
+ except:
+ traceback.print_exc()
+
+ print("Done")
+
+
+def create_example_data(doc):
+ try:
+ text = doc.getText()
+ cursor = text.createTextCursor()
+ text.insertString(cursor, "He nervously looked all around. Suddenly he saw his ", False)
+
+ text.insertString(cursor, "neighbour ", True)
+ cursor.setPropertyValue("CharColor", 255) # Set the word blue
+
+ cursor.gotoEnd(False) # Go to last character
+ cursor.setPropertyValue("CharColor", 0)
+ content = (
+ "in the alley. Like lightning he darted off to the left and disappeared between the "
+ "two warehouses almost falling over the trash can lying in the "
+ )
+ text.insertString(cursor, content, False)
+
+ text.insertString(cursor, "centre ", True)
+ cursor.setPropertyValue("CharColor", 255) # Set the word blue
+
+ cursor.gotoEnd(False) # Go to last character
+ cursor.setPropertyValue("CharColor", 0)
+ text.insertString(cursor, "of the sidewalk.", False)
+
+ text.insertControlCharacter(cursor, PARAGRAPH_BREAK, False)
+ content = (
+ "He tried to nervously tap his way along in the inky darkness and suddenly stiffened: "
+ "it was a dead-end, he would have to go back the way he had come."
+ )
+ text.insertString(cursor, content, False)
+ cursor.gotoStart(False)
+ except:
+ traceback.print_exc()
+
+
+if __name__ == "__main__":
+ main()
+
+# vim: set shiftwidth=4 softtabstop=4 expandtab:
diff --git a/odk/examples/python/Text/WriterSelector.py b/odk/examples/python/Text/WriterSelector.py
new file mode 100644
index 0000000000..f822fded06
--- /dev/null
+++ b/odk/examples/python/Text/WriterSelector.py
@@ -0,0 +1,67 @@
+# -*- tab-width: 4; indent-tabs-mode: nil; py-indent-offset: 4 -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+import sys
+import traceback
+import officehelper
+
+
+def main():
+ try:
+ remote_context = officehelper.bootstrap()
+ print("Connected to a running office ...")
+ srv_mgr = remote_context.getServiceManager()
+ desktop = srv_mgr.createInstanceWithContext("com.sun.star.frame.Desktop", remote_context)
+
+ print("Opening an empty Writer document")
+ doc_url = "private:factory/swriter"
+ doc = desktop.loadComponentFromURL(doc_url, "_blank", 0, tuple())
+
+ text = doc.getText()
+ text.setString("Please select something in this text and press then \"return\" in the shell "
+ "where you have started the example.\n")
+
+ # Returned object supports service com.sun.star.text.TextDocumentView and com.sun.star.view.OfficeDocumentView
+ # Both of them implements interface com::sun::star::view::XViewSettingsSupplier
+ obj = doc.getCurrentController()
+ obj.getViewSettings().setPropertyValue("ZoomType", 0)
+
+ print()
+ input("Please select something in the test document and press "
+ "then \"return\" to continues the example ... ")
+
+ frame = desktop.getCurrentFrame()
+ selection = frame.getController().getSelection()
+
+ if selection.supportsService("com.sun.star.text.TextRanges"):
+ for selected in selection:
+ print("You have selected a text range:", f'"{selected.getString()}".')
+
+ if selection.supportsService("com.sun.star.text.TextGraphicObject"):
+ print("You have selected a graphics.")
+
+ if selection.supportsService("com.sun.star.text.TexttableCursor"):
+ print("You have selected a text table.")
+
+ # When object returned from loadComponentFromURL does not support a service
+ # that implements XCloseable interface, fallback to call
+ # XComponent.dispose.
+ try:
+ doc.close(False)
+ except:
+ doc.dispose()
+ except:
+ traceback.print_exc()
+ sys.exit(1)
+
+
+if __name__ == "__main__":
+ main()
+
+# vim: set shiftwidth=4 softtabstop=4 expandtab:
diff --git a/odk/examples/python/toolpanel/CalcWindowState.xcu b/odk/examples/python/toolpanel/CalcWindowState.xcu
new file mode 100644
index 0000000000..9abb827d8f
--- /dev/null
+++ b/odk/examples/python/toolpanel/CalcWindowState.xcu
@@ -0,0 +1,29 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!--
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+-->
+<oor:component-data
+ oor:name="CalcWindowState"
+ oor:package="org.openoffice.Office.UI"
+ xmlns:install="http://openoffice.org/2004/installation"
+ xmlns:oor="http://openoffice.org/2001/registry"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <node oor:name="UIElements">
+ <node oor:name="States">
+ <node oor:name="private:resource/toolpanel/myToolPanelPoc" oor:op="replace">
+ <prop oor:name="UIName" oor:type="xs:string">
+ <value> ToolPanel Proof of Concept</value>
+ </prop>
+ <prop oor:name="Visible" oor:type="xs:boolean">
+ <value>true</value>
+ </prop>
+ </node>
+ </node>
+ </node>
+</oor:component-data>
diff --git a/odk/examples/python/toolpanel/Factory.xcu b/odk/examples/python/toolpanel/Factory.xcu
new file mode 100644
index 0000000000..bc9b5feef1
--- /dev/null
+++ b/odk/examples/python/toolpanel/Factory.xcu
@@ -0,0 +1,34 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!--
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+-->
+<oor:component-data
+ oor:name="Factories"
+ oor:package="org.openoffice.Office.UI"
+ xmlns:oor="http://openoffice.org/2001/registry"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <node oor:name="Registered">
+ <node oor:name="UIElementFactories">
+ <node oor:name="org.libreoffice.example.sdk.CustomToolPanel" oor:op="replace">
+ <prop oor:name="Type">
+ <value>toolpanel</value>
+ </prop>
+ <prop oor:name="Name">
+ <value>myToolPanelPoc</value>
+ </prop>
+ <prop oor:name="Module">
+ <value/>
+ </prop>
+ <prop oor:name="FactoryImplementation">
+ <value>org.libreoffice.example.toolpanel.pocFactory</value>
+ </prop>
+ </node>
+ </node>
+ </node>
+</oor:component-data>
diff --git a/odk/examples/python/toolpanel/META-INF/manifest.xml b/odk/examples/python/toolpanel/META-INF/manifest.xml
new file mode 100644
index 0000000000..300501b7fe
--- /dev/null
+++ b/odk/examples/python/toolpanel/META-INF/manifest.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+-->
+<manifest:manifest xmlns:manifest="http://openoffice.org/2001/manifest">
+ <manifest:file-entry
+ manifest:media-type="application/vnd.sun.star.uno-components"
+ manifest:full-path="toolpanel.component"/>
+ <manifest:file-entry
+ manifest:media-type="application/vnd.sun.star.configuration-data"
+ manifest:full-path="CalcWindowState.xcu"/>
+ <manifest:file-entry
+ manifest:media-type="application/vnd.sun.star.configuration-data"
+ manifest:full-path="Factory.xcu"/>
+ <manifest:file-entry
+ manifest:full-path="toolPanelPocBasic/"
+ manifest:media-type="application/vnd.sun.star.basic-library"/>
+</manifest:manifest>
diff --git a/odk/examples/python/toolpanel/Makefile b/odk/examples/python/toolpanel/Makefile
new file mode 100644
index 0000000000..a2e77f057c
--- /dev/null
+++ b/odk/examples/python/toolpanel/Makefile
@@ -0,0 +1,29 @@
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+PRJ = ../../..
+SETTINGS = $(PRJ)/settings
+
+include $(SETTINGS)/settings.mk
+include $(SETTINGS)/std.mk
+
+FILES = \
+ CalcWindowState.xcu \
+ Factory.xcu \
+ META-INF/manifest.xml \
+ description.xml \
+ toolPanelPocBasic/Module1.xba \
+ toolPanelPocBasic/dialog.xlb \
+ toolPanelPocBasic/script.xlb \
+ toolpanel.component \
+ toolpanel.py \
+ toolpanels/poc.xdl
+
+$(OUT_BIN)/toolpanel.$(UNOOXT_EXT): $(FILES)
+ -$(MKDIR) $(subst /,$(PS),$(@D))
+ $(SDK_ZIP) $@ $^
diff --git a/odk/examples/python/toolpanel/description.xml b/odk/examples/python/toolpanel/description.xml
new file mode 100644
index 0000000000..c448e8541b
--- /dev/null
+++ b/odk/examples/python/toolpanel/description.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+-->
+<description xmlns="http://openoffice.org/extensions/description/2006" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <version value="0.1.0"/>
+ <identifier value="org.libreoffice.example.toolpanel"/>
+</description>
diff --git a/odk/examples/python/toolpanel/readme b/odk/examples/python/toolpanel/readme
new file mode 100644
index 0000000000..5dedd9385a
--- /dev/null
+++ b/odk/examples/python/toolpanel/readme
@@ -0,0 +1,13 @@
+
+This extension is a Proof of concept on implementing Toolpanel in Python
+
+- make will create the oxt
+ - provided sdk environment is set
+ - alternatively zip the files and name it toolpanel.oxt
+- install it
+- activate Task Panes in menu (check View > Task Pane menu)
+- enjoy!
+
+The events of the controls (Click me button) in the task panel are handled by basic macro code to illustrate that Toolpanel definition and events codes are independent. One could use any language to react on events
+
+Then focus only on .py and xml files for the toolpanel activation analysis
diff --git a/odk/examples/python/toolpanel/toolPanelPocBasic/Module1.xba b/odk/examples/python/toolpanel/toolPanelPocBasic/Module1.xba
new file mode 100644
index 0000000000..9d44f7f011
--- /dev/null
+++ b/odk/examples/python/toolpanel/toolPanelPocBasic/Module1.xba
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE script:module PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "module.dtd">
+<script:module xmlns:script="http://openoffice.org/2000/script" script:name="Module1" script:language="StarBasic">
+global theDialog
+
+
+Sub dialogOnLoad(event)
+
+ theDialog = event.source
+
+End Sub
+
+sub buttonClick(event)
+
+
+ theButton = theDialog.getControl(&quot;CommandButton1&quot;)
+ theTextField = theDialog.getControl(&quot;TextInfo&quot;)
+
+ colors = Array(rgb(255,0,0),rgb(0,255,0),rgb(0,0,255))
+ rank = getSystemTicks() mod 3
+
+ theDialog.Model.BackgroundColor = colors(rank)
+ theTextField.text = cstr(Now) + chr(10)+&quot;Color &quot; + cstr(rank) + &quot; randomly applied&quot;
+
+ theButton.label = &quot;Click Me to change color&quot;
+
+
+end sub
+</script:module> \ No newline at end of file
diff --git a/odk/examples/python/toolpanel/toolPanelPocBasic/dialog.xlb b/odk/examples/python/toolpanel/toolPanelPocBasic/dialog.xlb
new file mode 100644
index 0000000000..a738363ea7
--- /dev/null
+++ b/odk/examples/python/toolpanel/toolPanelPocBasic/dialog.xlb
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE library:library PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "library.dtd">
+<library:library xmlns:library="http://openoffice.org/2000/library" library:name="toolPanelPocBasic" library:readonly="false" library:passwordprotected="false"/> \ No newline at end of file
diff --git a/odk/examples/python/toolpanel/toolPanelPocBasic/script.xlb b/odk/examples/python/toolpanel/toolPanelPocBasic/script.xlb
new file mode 100644
index 0000000000..4d9cc4d515
--- /dev/null
+++ b/odk/examples/python/toolpanel/toolPanelPocBasic/script.xlb
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE library:library PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "library.dtd">
+<library:library xmlns:library="http://openoffice.org/2000/library" library:name="toolPanelPocBasic" library:readonly="false" library:passwordprotected="false">
+ <library:element library:name="Module1"/>
+</library:library> \ No newline at end of file
diff --git a/odk/examples/python/toolpanel/toolpanel.component b/odk/examples/python/toolpanel/toolpanel.component
new file mode 100644
index 0000000000..d7fde35457
--- /dev/null
+++ b/odk/examples/python/toolpanel/toolpanel.component
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+-->
+<components xmlns="http://openoffice.org/2010/uno-components">
+ <component loader="com.sun.star.loader.Python" uri="./toolpanel.py">
+ <implementation name="org.libreoffice.example.toolpanel.pocFactory">
+ <service name="org.libreoffice.example.toolpanel.pocFactory"/>
+ </implementation>
+ </component>
+</components>
diff --git a/odk/examples/python/toolpanel/toolpanel.py b/odk/examples/python/toolpanel/toolpanel.py
new file mode 100644
index 0000000000..8fcfb3f322
--- /dev/null
+++ b/odk/examples/python/toolpanel/toolpanel.py
@@ -0,0 +1,139 @@
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This file incorporates work covered by the following license notice:
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed
+# with this work for additional information regarding copyright
+# ownership. The ASF licenses this file to you under the Apache
+# License, Version 2.0 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.apache.org/licenses/LICENSE-2.0 .
+#
+# inspired by core/testautomation/extensions/optional/input/extension_sources/TaskPaneComponent
+#
+
+import uno
+import unohelper
+
+from com.sun.star.ui import XUIElementFactory
+from com.sun.star.ui import XUIElement
+from com.sun.star.ui.UIElementType import TOOLPANEL as unoTOOLPANEL
+from com.sun.star.ui import XToolPanel
+
+implementation_name = "org.libreoffice.example.toolpanel.pocFactory" # as defined in Factory.xcu
+implementation_services = ("org.libreoffice.example.toolpanel.pocFactory",)
+
+xdlPath = "toolpanels/poc.xdl" # the path inside the oxt
+extensionID = "org.libreoffice.example.toolpanel" # as defined in description.xml
+
+########################################################################
+########################################################################
+
+class pocToolPanel( unohelper.Base, XToolPanel ):
+
+ def __init__ ( self, xPanelWindow, ctx ):
+
+ self.ctx = ctx
+ self.PanelWindow = xPanelWindow
+ self.Window = xPanelWindow
+
+ def createAccessible( self, i_parentAccessible ):
+
+ return self.PanelWindow
+
+########################################################################
+########################################################################
+
+class pyPanel( unohelper.Base, XUIElement ):
+
+ def __init__ ( self, ctx, xFrame, xParentWindow, url ):
+
+ self.ctx = ctx
+ self.xParentWindow = xParentWindow
+ self.toolpanel = None
+ self.m_panelRootWindow = None
+
+ self.Frame = xFrame
+ self.ResourceURL = url
+ self.Type = unoTOOLPANEL
+
+
+ def getRealInterface( self ):
+
+ if not self.toolpanel:
+ rootWindow = self.getOrCreatePanelRootWindow()
+ self.toolpanel = pocToolPanel(rootWindow, self.ctx)
+
+ return self.toolpanel
+
+ def getOrCreatePanelRootWindow( self ):
+
+ pip = self.ctx.getValueByName("/singletons/com.sun.star.deployment.PackageInformationProvider" )
+ s = pip.getPackageLocation(extensionID)
+ dialogUrl = s + "/" + xdlPath
+
+ provider = self.ctx.ServiceManager.createInstanceWithContext("com.sun.star.awt.ContainerWindowProvider",self.ctx)
+ self.m_panelRootWindow = provider.createContainerWindow(dialogUrl,"",self.xParentWindow, None)
+
+ return self.m_panelRootWindow
+
+ def postDisposing( self ):
+
+ super.postDisposing()
+
+ if self.m_panelRootWindow:
+ self.m_panelRootWindow.dispose()
+ self.m_panelRootWindow = None
+
+ self.toolpanel = None
+
+ return
+
+#######################################################################
+#######################################################################
+
+class pocFactory( unohelper.Base, XUIElementFactory ):
+
+ def __init__ ( self, ctx ):
+
+ self.ctx = ctx
+
+ def createUIElement( self, url, properties ):
+
+ xParentWindow = None
+ xFrame = None
+ xUIElement = None
+
+ for arg in properties:
+ if arg.Name == "Frame":
+ xFrame = arg.Value
+ elif arg.Name == "ParentWindow":
+ xParentWindow = arg.Value
+
+ if xFrame and xParentWindow:
+ try:
+ xUIElement = pyPanel(self.ctx, xFrame, xParentWindow, url)
+ except Exception as e:
+ print(e)
+
+ return xUIElement
+
+########################################################################
+########################################################################
+
+# pythonloader looks for a static g_ImplementationHelper variable
+g_ImplementationHelper = unohelper.ImplementationHelper ()
+
+# add the FormatFactory class to the implementation container,
+# which the loader uses to register/instantiate the component.
+g_ImplementationHelper.addImplementation (pocFactory,
+ implementation_name,
+ implementation_services,
+ )
+
diff --git a/odk/examples/python/toolpanel/toolpanels/poc.xdl b/odk/examples/python/toolpanel/toolpanels/poc.xdl
new file mode 100644
index 0000000000..2e07cd6287
--- /dev/null
+++ b/odk/examples/python/toolpanel/toolpanels/poc.xdl
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE dlg:window PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "dialog.dtd">
+<dlg:window xmlns:dlg="http://openoffice.org/2000/dialog" xmlns:script="http://openoffice.org/2000/script" dlg:id="MyDialog" dlg:left="192" dlg:top="127" dlg:width="174" dlg:height="147" dlg:closeable="true" dlg:moveable="true" dlg:help-url="customcontrol1" dlg:withtitlebar="false">
+ <script:event script:event-name="on-focus" script:macro-name="vnd.sun.star.script:toolPanelPocBasic.Module1.dialogOnLoad?language=Basic&amp;location=application" script:language="Script"/>
+ <dlg:bulletinboard>
+ <dlg:button dlg:id="CommandButton1" dlg:tab-index="0" dlg:left="6" dlg:top="8" dlg:width="80" dlg:height="30" dlg:value="The button label">
+ <script:event script:event-name="on-performaction" script:macro-name="vnd.sun.star.script:toolPanelPocBasic.Module1.buttonClick?language=Basic&amp;location=application" script:language="Script"/>
+ </dlg:button>
+ <dlg:textfield dlg:id="TextInfo" dlg:textarea-vertical-align="top" dlg:tab-index="1" dlg:left="6" dlg:top="48" dlg:width="80" dlg:height="59" dlg:value="a sample text" dlg:multiline="true"/>
+ </dlg:bulletinboard>
+</dlg:window>