Added the ability to store and retrieve macros in the document macro storage.
This commit is contained in:
parent
763703b96a
commit
a47e65a50c
@ -256,6 +256,13 @@ LIBRARY The name of the Basic library. Default to the same
|
||||
Run he specific macro after synchronization, for
|
||||
convenience.
|
||||
|
||||
--user Store the macros in the user macro storage. (default)
|
||||
|
||||
--doc Store the macros in the document macro storage.
|
||||
|
||||
--target TARGET The target storage document if there are more than one
|
||||
opened documents. A partial path is OK.
|
||||
|
||||
-h, --help Show the help message and exit
|
||||
|
||||
-v, --version Show program’s version number and exit
|
||||
@ -264,7 +271,7 @@ LIBRARY The name of the Basic library. Default to the same
|
||||
COPYRIGHT
|
||||
---------
|
||||
|
||||
Copyright (c) 2016 imacat.
|
||||
Copyright (c) 2016-2017 imacat.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
242
bin/obasync
242
bin/obasync
@ -3,7 +3,7 @@
|
||||
# Office Basic macro source synchronizer.
|
||||
# by imacat <imacat@mail.imacat.idv.tw>, 2016-08-31
|
||||
|
||||
# Copyright (c) 2016 imacat.
|
||||
# Copyright (c) 2016-2017 imacat.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
@ -86,6 +86,13 @@ LIBRARY The name of the Basic library. Default to the same
|
||||
Run he specific macro after synchronization, for
|
||||
convenience.
|
||||
|
||||
--user Store the macros in the user macro storage. (default)
|
||||
|
||||
--doc Store the macros in the document macro storage.
|
||||
|
||||
--target TARGET The target storage document if there are more than one
|
||||
opened documents. A partial path is OK.
|
||||
|
||||
-h, --help Show the help message and exit
|
||||
|
||||
-v, --version Show program’s version number and exit
|
||||
@ -133,9 +140,8 @@ def main():
|
||||
# Downloads the macros from OpenOffice/LibreOffice Basic
|
||||
if args.get:
|
||||
oo = Office(args.port)
|
||||
libraries = oo.service_manager.createInstance(
|
||||
"com.sun.star.script.ApplicationScriptLibraryContainer")
|
||||
modules = read_basic_modules(libraries, args.library)
|
||||
storage = find_storage(oo, args.storage_type, args.target)
|
||||
modules = read_basic_modules(storage, args.library)
|
||||
if len(modules) == 0:
|
||||
print("ERROR: Library %s does not exist" % args.library,
|
||||
file=sys.stderr)
|
||||
@ -153,19 +159,10 @@ def main():
|
||||
file=sys.stderr)
|
||||
return
|
||||
oo = Office(args.port)
|
||||
libraries = oo.service_manager.createInstance(
|
||||
"com.sun.star.script.ApplicationScriptLibraryContainer")
|
||||
update_basic_modules(libraries, args.library, modules, oo)
|
||||
storage = find_storage(oo, args.storage_type, args.target)
|
||||
update_basic_modules(storage, args.library, modules)
|
||||
if args.run is not None:
|
||||
factory = oo.service_manager.DefaultContext.getByName(
|
||||
"/singletons/com.sun.star.script.provider."
|
||||
"theMasterScriptProviderFactory")
|
||||
provider = factory.createScriptProvider("")
|
||||
script = provider.getScript(
|
||||
"vnd.sun.star.script:%s.%s"
|
||||
"?language=Basic&location=application" %
|
||||
(args.library, args.run))
|
||||
script.invoke((), (), ())
|
||||
run_macro(storage, args.library, args.run)
|
||||
|
||||
print("Done. %02d:%02d elapsed." %
|
||||
(int((time.time() - t_start) / 60),
|
||||
@ -206,6 +203,18 @@ def parse_args():
|
||||
parser.add_argument(
|
||||
"-r", "--run", metavar="MODULE.MACRO",
|
||||
help="The macro to run after the upload, if any.")
|
||||
parser.add_argument(
|
||||
"--user", dest="storage_type",
|
||||
action="store_const", const="user",
|
||||
help="Store the macros in the user macro storage. (default)")
|
||||
parser.add_argument(
|
||||
"--doc", dest="storage_type",
|
||||
action="store_const", const="doc",
|
||||
help="Store the macros in the document macro storage.")
|
||||
parser.add_argument(
|
||||
"--target", metavar="TARGET",
|
||||
help=("The target storage document if there are more than one"
|
||||
" opened documents. A partial path is OK."))
|
||||
parser.add_argument(
|
||||
"-v", "--version", action="version", version="%(prog)s 0.4")
|
||||
args = parser.parse_args()
|
||||
@ -219,9 +228,117 @@ def parse_args():
|
||||
if args.ext[0] != ".":
|
||||
args.ext = "." + args.ext
|
||||
|
||||
if args.storage_type is None:
|
||||
args.storage_type = "user"
|
||||
# Paths are understood locally, despite of the content encoding.
|
||||
if args.target is not None:
|
||||
args.target = args.target.decode(locale.getpreferredencoding())
|
||||
return
|
||||
|
||||
|
||||
def find_storage(oo, type, target):
|
||||
"""Finds the macro storage to store the macros.
|
||||
|
||||
Arguments:
|
||||
type: The storage type, either "user" or "doc".
|
||||
target: The file path to locate the storing document if there
|
||||
are more than one opened documents. A partial path
|
||||
is OK.
|
||||
|
||||
Returns:
|
||||
The storage to save the macros, as a Storage object.
|
||||
"""
|
||||
if type == "user":
|
||||
storage = Storage()
|
||||
storage.type = type
|
||||
storage.oo = oo
|
||||
storage.doc = None
|
||||
storage.libs = oo.service_manager.createInstance(
|
||||
"com.sun.star.script.ApplicationScriptLibraryContainer")
|
||||
return storage
|
||||
elif type == "doc":
|
||||
storage = Storage()
|
||||
storage.type = type
|
||||
storage.oo = oo
|
||||
storage.doc = find_doc(oo, target)
|
||||
storage.libs = storage.doc.getPropertyValue("BasicLibraries")
|
||||
return storage
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
def find_doc(oo, target):
|
||||
"""Find the target opened document by a partial path.
|
||||
|
||||
Arguments:
|
||||
target: A partial path of the document.
|
||||
|
||||
Returns:
|
||||
If there is only one opened document, it is returned. If
|
||||
there are more than one opened document, the document whose
|
||||
file path matches the "target" is returned. Otherwise, if
|
||||
no matching document or more than one matching document are
|
||||
found, the program exists with an error.
|
||||
"""
|
||||
# Checks the opened documents
|
||||
enum = oo.desktop.getComponents().createEnumeration()
|
||||
opened = []
|
||||
while enum.hasMoreElements():
|
||||
component = enum.nextElement()
|
||||
if component.supportsService(
|
||||
"com.sun.star.document.OfficeDocument"):
|
||||
opened.append(component)
|
||||
if len(opened) == 0:
|
||||
print("ERROR: Found no opened document to store the macros",
|
||||
file=sys.stderr)
|
||||
sys.exit(1)
|
||||
# There are opened documents.
|
||||
if target is None:
|
||||
if len(opened) == 1:
|
||||
return opened[0]
|
||||
print("ERROR: There are more than one opened documens."
|
||||
" Please specify the file path.",
|
||||
file=sys.stderr)
|
||||
sys.exit(1)
|
||||
file_content_provider = oo.service_manager.createInstance(
|
||||
"com.sun.star.ucb.FileContentProvider")
|
||||
matched = []
|
||||
for doc in opened:
|
||||
if doc.hasLocation():
|
||||
path = file_content_provider.getSystemPathFromFileURL(
|
||||
doc.getLocation())
|
||||
else:
|
||||
path = doc.getTitle()
|
||||
if path.find(target) >= 0:
|
||||
matched.append(doc)
|
||||
if len(matched) == 1:
|
||||
return matched[0]
|
||||
elif len(matched) == 0:
|
||||
print("ERROR: Found no matching document to store the macros.",
|
||||
file=sys.stderr)
|
||||
print("Opened documents:", file=sys.stderr)
|
||||
for doc in opened:
|
||||
if doc.hasLocation():
|
||||
path = file_content_provider.getSystemPathFromFileURL(
|
||||
doc.getLocation())
|
||||
else:
|
||||
path = doc.getTitle()
|
||||
print("* %s" % path, file=sys.stderr)
|
||||
sys.exit(1)
|
||||
else:
|
||||
print("ERROR: There are more than one matching documents.",
|
||||
file=sys.stderr)
|
||||
print("Matching documents:", file=sys.stderr)
|
||||
for doc in matched:
|
||||
if doc.hasLocation():
|
||||
path = file_content_provider.getSystemPathFromFileURL(
|
||||
doc.getLocation())
|
||||
else:
|
||||
path = doc.getTitle()
|
||||
print("* %s" % path, file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def read_in_source_dir(projdir, ext, encoding):
|
||||
"""Read-in the source files.
|
||||
|
||||
@ -289,15 +406,13 @@ def update_source_dir(projdir, modules, ext, encoding):
|
||||
return
|
||||
|
||||
|
||||
def read_basic_modules(libraries, libname):
|
||||
def read_basic_modules(storage, libname):
|
||||
"""
|
||||
Read the OpenOffice/LibreOffice Basic macros from the macro
|
||||
storage.
|
||||
|
||||
Arguments:
|
||||
libraries: The Basic library storage, as a
|
||||
com.sun.star.script.ApplicationScriptLibraryContainer
|
||||
service object.
|
||||
storage: The Basic macro storage, as a Storage object.
|
||||
libname: The name of the Basic library.
|
||||
|
||||
Returns:
|
||||
@ -306,41 +421,44 @@ def read_basic_modules(libraries, libname):
|
||||
dictionary are the module contents.
|
||||
"""
|
||||
modules = {}
|
||||
if not libraries.hasByName(libname):
|
||||
if not storage.libs.hasByName(libname):
|
||||
return modules
|
||||
libraries.loadLibrary(libname)
|
||||
library = libraries.getByName(libname)
|
||||
storage.libs.loadLibrary(libname)
|
||||
library = storage.libs.getByName(libname)
|
||||
for modname in library.getElementNames():
|
||||
modules[modname] = library.getByName(modname)
|
||||
return modules
|
||||
|
||||
|
||||
def update_basic_modules(libraries, libname, modules, oo):
|
||||
def update_basic_modules(storage, libname, modules):
|
||||
"""Update the OpenOffice/LibreOffice Basic macro storage.
|
||||
|
||||
Arguments:
|
||||
libraries: The Basic library storage, as a
|
||||
com.sun.star.script.ApplicationScriptLibraryContainer
|
||||
service object.
|
||||
storage: The Basic macro storage, as a Storage object.
|
||||
libname: The name of the Basic library.
|
||||
modules: The Basic modules, as a dictionary. The keys of
|
||||
the dictionary are the module names, and the values of
|
||||
the dictionary are the module contents.
|
||||
oo: The OpenOffice/LibreOffice connection, as an Office
|
||||
object.
|
||||
"""
|
||||
if not libraries.hasByName(libname):
|
||||
libraries.createLibrary(libname)
|
||||
if not storage.libs.hasByName(libname):
|
||||
storage.libs.createLibrary(libname)
|
||||
print("Script library %s created." % libname, file=sys.stderr)
|
||||
create_dialog_library(oo, libname)
|
||||
library = libraries.getByName(libname)
|
||||
create_dialog_library(storage, libname)
|
||||
library = storage.libs.getByName(libname)
|
||||
for modname in sorted(modules.keys()):
|
||||
library.insertByName(modname, modules[modname])
|
||||
print("Module %s added." % modname, file=sys.stderr)
|
||||
else:
|
||||
libraries.loadLibrary(libname)
|
||||
library = libraries.getByName(libname)
|
||||
curmods = sorted(library.getElementNames())
|
||||
storage.libs.loadLibrary(libname)
|
||||
library = storage.libs.getByName(libname)
|
||||
# As of OpenOffice 4.1.3, when there is no modules in the
|
||||
# document storage, it returns a zero-length byte sequence
|
||||
# instead of an empty string list.
|
||||
# The byte sequence cannot be sorted directly.
|
||||
curmods = library.getElementNames()
|
||||
if len(curmods) == 0:
|
||||
curmods = []
|
||||
curmods = sorted(curmods)
|
||||
for modname in sorted(modules.keys()):
|
||||
if modname not in curmods:
|
||||
library.insertByName(modname, modules[modname])
|
||||
@ -352,28 +470,57 @@ def update_basic_modules(libraries, libname, modules, oo):
|
||||
if modname not in modules:
|
||||
library.removeByName(modname)
|
||||
print("Module %s removed." % modname, file=sys.stderr)
|
||||
if libraries.isModified():
|
||||
libraries.storeLibraries()
|
||||
if storage.libs.isModified():
|
||||
storage.libs.storeLibraries()
|
||||
else:
|
||||
print("Everything is in sync.", file=sys.stderr)
|
||||
return
|
||||
|
||||
|
||||
def create_dialog_library(oo, libname):
|
||||
def create_dialog_library(storage, libname):
|
||||
"""Create the dialog library.
|
||||
|
||||
Arguments:
|
||||
oo: The OpenOffice/LibreOffice connection, as an Office
|
||||
object.
|
||||
storage: The Basic macro storage, as a Storage object.
|
||||
libname: The name of the dialog library.
|
||||
"""
|
||||
libraries = oo.service_manager.createInstance(
|
||||
if storage.type is "user":
|
||||
libraries = storage.oo.service_manager.createInstance(
|
||||
"com.sun.star.script.ApplicationDialogLibraryContainer")
|
||||
else:
|
||||
libraries = storage.doc.getPropertyValue("DialogLibraries")
|
||||
libraries.createLibrary(libname)
|
||||
print("Dialog library %s created." % libname, file=sys.stderr)
|
||||
libraries.storeLibraries()
|
||||
|
||||
|
||||
def run_macro(storage, libname, macro):
|
||||
"""Run a Basic macro.
|
||||
|
||||
Arguments:
|
||||
storage: The Basic macro storage, as a Storage object.
|
||||
libname: The name of the dialog library.
|
||||
macro: The The macro to run.
|
||||
"""
|
||||
if storage.type is "user":
|
||||
factory = storage.oo.service_manager.DefaultContext.getByName(
|
||||
"/singletons/com.sun.star.script.provider."
|
||||
"theMasterScriptProviderFactory")
|
||||
provider = factory.createScriptProvider("")
|
||||
script = provider.getScript(
|
||||
"vnd.sun.star.script:%s.%s"
|
||||
"?language=Basic&location=application" %
|
||||
(args.library, args.run))
|
||||
script.invoke((), (), ())
|
||||
else:
|
||||
provider = storage.doc.getScriptProvider()
|
||||
script = provider.getScript(
|
||||
"vnd.sun.star.script:%s.%s"
|
||||
"?language=Basic&location=document" %
|
||||
(args.library, args.run))
|
||||
script.invoke((), (), ())
|
||||
|
||||
|
||||
def read_file(path, encoding):
|
||||
"""Read a file, and deals with Python 3 / 2 compatibility.
|
||||
|
||||
@ -448,6 +595,17 @@ def update_file(path, content, encoding):
|
||||
return is_updated
|
||||
|
||||
|
||||
class Storage:
|
||||
"""A Basic macro storage.
|
||||
|
||||
Attributes:
|
||||
oo: The office connection, as an Office() object.
|
||||
doc: The office document component to store the macros.
|
||||
libs: The Basic macro storage of the document.
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
class Office:
|
||||
"""The OpenOffice/LibreOffice connection.
|
||||
|
||||
|
2
setup.py
2
setup.py
@ -3,7 +3,7 @@
|
||||
# Python setuptools installer for the obasync project.
|
||||
# by imacat <imacat@mail.imacat.idv.tw>, 2016-12-20
|
||||
|
||||
# Copyright (c) 2016 imacat.
|
||||
# Copyright (c) 2016-2017 imacat.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
Loading…
Reference in New Issue
Block a user