From 665d1633c9e08da85fae179e62923211bc07c480 Mon Sep 17 00:00:00 2001 From: Chenxiong Qi Date: Wed, 14 Sep 2022 09:29:25 +0800 Subject: [PATCH] tdf#143123 port DocumentHandling examples to Python This port keeps the similarity with Java ones as much as possible. examples.html is also updated by adding the Python examples. Signed-off-by: Chenxiong Qi Change-Id: I2af26aaf42f5408bf254a4e0507442200f843661 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/139887 Tested-by: Jenkins Reviewed-by: Hossein --- odk/Package_examples.mk | 6 ++ odk/examples/examples.html | 36 +++++++ .../DocumentHandling/DocumentConverter.py | 91 ++++++++++++++++++ .../DocumentLoader.py | 42 ++++++-- .../DocumentHandling/DocumentPrinter.py | 71 ++++++++++++++ .../python/DocumentHandling/DocumentSaver.py | 81 ++++++++++++++++ .../python/DocumentHandling/README.md | 56 +++++++++++ .../python/DocumentHandling/tests/hello.odt | Bin 0 -> 8471 bytes odk/examples/python/DocumentLoader/README.md | 12 --- 9 files changed, 374 insertions(+), 21 deletions(-) create mode 100644 odk/examples/python/DocumentHandling/DocumentConverter.py rename odk/examples/python/{DocumentLoader => DocumentHandling}/DocumentLoader.py (51%) create mode 100644 odk/examples/python/DocumentHandling/DocumentPrinter.py create mode 100644 odk/examples/python/DocumentHandling/DocumentSaver.py create mode 100644 odk/examples/python/DocumentHandling/README.md create mode 100644 odk/examples/python/DocumentHandling/tests/hello.odt delete mode 100644 odk/examples/python/DocumentLoader/README.md diff --git a/odk/Package_examples.mk b/odk/Package_examples.mk index 6749bcdcc798..457aea37e166 100644 --- a/odk/Package_examples.mk +++ b/odk/Package_examples.mk @@ -541,6 +541,12 @@ $(eval $(call gb_Package_add_files_with_dir,odk_examples,$(SDKDIRNAME)/examples, python/toolpanel/toolpanel.component \ python/toolpanel/toolpanel.py \ python/toolpanel/toolpanels/poc.xdl \ + python/DocumentHandling/DocumentConverter.py \ + python/DocumentHandling/DocumentLoader.py \ + python/DocumentHandling/DocumentPrinter.py \ + python/DocumentHandling/DocumentSaver.py \ + python/DocumentHandling/README.md \ + python/DocumentHandling/tests/hello.odt \ )) # vim: set noet sw=4 ts=4: diff --git a/odk/examples/examples.html b/odk/examples/examples.html index 9a1bf3de6b3a..2b23080961fb 100644 --- a/odk/examples/examples.html +++ b/odk/examples/examples.html @@ -423,6 +423,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + +
Document Handling ExamplesDescription
+ DocumentConverter + The program offers a service that converts arbitrary documents to a favored document type.
+ DocumentLoader + The DocumentLoader can open a new or an existing document.
+ DocumentPrinter + The DocumentPrinter allows you to print the favored pages of a specified document on your favored printer.
+ DocumentSaver + The DocumentSaver shows how to save a document and how you can change the type of your document.
+ + diff --git a/odk/examples/python/DocumentHandling/DocumentConverter.py b/odk/examples/python/DocumentHandling/DocumentConverter.py new file mode 100644 index 000000000000..a1f54fca9102 --- /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/DocumentLoader/DocumentLoader.py b/odk/examples/python/DocumentHandling/DocumentLoader.py similarity index 51% rename from odk/examples/python/DocumentLoader/DocumentLoader.py rename to odk/examples/python/DocumentHandling/DocumentLoader.py index 521b63ce9066..a88f3ad0d724 100644 --- a/odk/examples/python/DocumentLoader/DocumentLoader.py +++ b/odk/examples/python/DocumentHandling/DocumentLoader.py @@ -7,18 +7,32 @@ # 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 -from sys import argv, exit +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__": - if len(argv) < 2: - print("usage: $OFFICE_PROGRAM_PATH/python DocumentLoader.py ") - exit(1) - if not isfile(argv[1]): - print("%s could not be opened" % argv[1]) - exit(1) + 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() @@ -36,7 +50,17 @@ if __name__ == "__main__": desktop = context.ServiceManager.createInstanceWithContext( "com.sun.star.frame.Desktop", context) - url = uno.systemPathToFileUrl(abspath(argv[1])) + + 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([])) diff --git a/odk/examples/python/DocumentHandling/DocumentPrinter.py b/odk/examples/python/DocumentHandling/DocumentPrinter.py new file mode 100644 index 000000000000..d9a4e29632c7 --- /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 000000000000..e7d8010a231a --- /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 000000000000..7e0e8aa43e4f --- /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 0000000000000000000000000000000000000000..dd72ae9ec4aa4dc54fef6a7e298a1f31828f6053 GIT binary patch literal 8471 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 - -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.