Alternative script organizer for Python macro
Posted: Sun Jul 22, 2012 7:27 pm
When I execute Python macro even through Script Organizer for Python entry in the main menu, all script providers are instantiated. All language engine for macro are initialized and script provider for each context for all language engine are instantiated. Because script organizer uses css.script.browse.theBrowseNodeFactory singleton to create MACROORGANIZER view and to load script nodes.
This does not happen when I execute Python macro from menu item. I wrote a toy, alternative script organizer dialog for Python.
Store above script in user_preference/Scripts/python/aso.py and assign "user" or "doc" function to use this in somewhere you want.
Supported functions:
- Create new script file or directory
- Substitute script file embedded in a document
- Delete script file and directory
- Rename script file and directory
Any Python macros installed by extensions are not shown now.
This does not happen when I execute Python macro from menu item. I wrote a toy, alternative script organizer dialog for Python.
Code: Select all
import uno
import unohelper
import traceback
import sys
try:
import pythonscript
except:
import pythonloader
pythonscript = None
for url, module in pythonloader.g_loadedComponents.iteritems():
if url.endswith("script-provider-for-python/pythonscript.py"):
pythonscript = module
if pythonscript is None:
raise Exception("Failed to find pythonscript module.")
from com.sun.star.awt import XActionListener, XMouseListener, \
XKeyListener, Rectangle, Selection
from com.sun.star.awt.tree import XTreeExpansionListener
from com.sun.star.uno import Exception as UNOException
# Default content of the new file.
TEMPLATE = """"""
class DialogBase(object):
""" Base class for dialog. """
def __init__(self, ctx):
self.ctx = ctx
def create(self, name):
""" Create service instance. """
return self.ctx.getServiceManager().createInstanceWithContext(
name, self.ctx)
class RuntimeDialogBase(DialogBase):
""" Runtime dialog base. """
def __init__(self, ctx):
DialogBase.__init__(self, ctx)
self.dialog = None
def _result(self):
""" Returns result. """
return None
def _init(self):
""" Initialize, create dialog and controls. """
def execute(self):
""" Execute to show this dialog.
None return value should mean canceled.
"""
self._init()
result = None
self.dialog.setVisible(True)
if self.dialog.execute():
result = self._result()
self.dialog.dispose()
return result
def create_control(self, name, type, pos, size,
prop_names, prop_values, full_name=False):
""" Create and insert control. """
if not full_name:
type = "com.sun.star.awt.UnoControl" + type + "Model"
dialog_model = self.dialog.getModel()
model = dialog_model.createInstance(type)
if prop_names and prop_values:
model.setPropertyValues(prop_names, prop_values)
dialog_model.insertByName(name, model)
ctrl = self.dialog.getControl(name)
ctrl.setPosSize(pos[0], pos[1], size[0], size[1], 15)
return ctrl
def create_dialog(self, title, pos=None, size=None, parent=None):
""" Create base dialog. """
dialog = self.create("com.sun.star.awt.UnoControlDialog")
dialog_model = self.create("com.sun.star.awt.UnoControlDialogModel")
dialog.setModel(dialog_model)
if isinstance(size, tuple) and len(size) == 2:
dialog.setPosSize(0, 0, size[0], size[1], 12)
if isinstance(pos, tuple) and len(pos) == 2:
dialog.setPosSize(pos[0], pos[1], 0, 0, 3)
elif parent:
pass
dialog.setTitle(title)
self.dialog = dialog
def create_label(self, name, command, pos, size,
prop_names=None, prop_values=None, action=None):
""" Create and add new label. """
label = self.create_control(name, "Label", pos, size,
prop_names, prop_values)
def create_button(self, name, command, pos, size,
prop_names=None, prop_values=None, action=None):
""" Create and add new button. """
btn = self.create_control(name, "Button", pos, size,
prop_names, prop_values)
btn.setActionCommand(command)
if action:
btn.addActionListener(action)
def create_edit(self, name, pos, size,
prop_names=None, prop_values=None):
""" Create and add new edit control. """
edit = self.create_control(name, "Edit", pos, size,
prop_names, prop_values)
def create_tree(self, name, pos, size,
prop_names=None, prop_values=None):
""" Create and add new tree. """
self.create_control(name,
"com.sun.star.awt.tree.TreeControlModel",
pos, size, prop_names, prop_values, full_name=True)
def get(self, name):
""" Returns specified control by name. """
return self.dialog.getControl(name)
def get_text(self, name):
""" Returns value of Text attribute specified by name. """
return self.dialog.getControl(name).getModel().Text
def set_focus(self, name):
""" Set focus to the control specified by the name. """
self.dialog.getControl(name).setFocus()
class NameInput(RuntimeDialogBase):
""" Input dialog. """
MARGIN = 3
BUTTON_WIDTH = 80
BUTTON_HEIGHT = 26
HEIGHT = MARGIN * 3 + BUTTON_HEIGHT * 2
WIDTH = 300
EDIT_NAME = "edit_name"
def __init__(self, ctx, title, default="", parent=None):
RuntimeDialogBase.__init__(self, ctx)
self.title = title
self.default = default
self.parent = parent
def _init(self):
margin = self.MARGIN
self.create_dialog(self.title, size=(self.WIDTH, self.HEIGHT))
self.create_edit(self.EDIT_NAME,
pos=(margin, margin),
size=(self.WIDTH - margin * 2, self.BUTTON_HEIGHT),
prop_names=("HideInactiveSelection", "Text",),
prop_values=(True, self.default,))
self.create_button("btn_ok", "ok",
pos=(self.WIDTH - self.BUTTON_WIDTH * 2 - margin * 2,
self.BUTTON_HEIGHT + margin * 2),
size=(self.BUTTON_WIDTH, self.BUTTON_HEIGHT),
prop_names=("DefaultButton", "Label", "PushButtonType",),
prop_values=(True, "OK", 1))
self.create_button("btn_cancel", "cancel",
pos=(self.WIDTH - self.BUTTON_WIDTH - margin,
self.BUTTON_HEIGHT + margin * 2),
size=(self.BUTTON_WIDTH, self.BUTTON_HEIGHT),
prop_names=("Label", "PushButtonType"), prop_values=("Cancel", 2))
self.set_focus(self.EDIT_NAME)
if self.parent:
self.dialog.createPeer(self.parent.getToolkit(), self.parent)
if self.default:
self.get(self.EDIT_NAME).setSelection(Selection(0, len(self.default)))
def _result(self):
return self.get_text("edit_name")
class FileOpenDialog(DialogBase):
""" To get file url to open. """
def __init__(self, ctx, **kwds):
DialogBase.__init__(self, ctx)
self.args = kwds
def execute(self):
fp = self.create("com.sun.star.ui.dialogs.FilePicker")
args = self.args
if "title" in args:
fp.setTitle(args["title"])
if "default" in args:
default = args["default"]
fp.setDefaultName(self._substitute_variables(default))
if "directory" in args:
fp.setDisplayDirectory(args["directory"])
if "filters" in args:
for title, filter in args["filters"]:
fp.appendFilter(title, filter)
result = None
if fp.execute():
result = fp.getFiles()[0]
return result
def _substitute_variables(self, uri):
return self.create("com.sun.star.util.PathSubstitution").\
substituteVariables(uri, True)
class MessageDialog(DialogBase):
""" Shows message in standard message box. """
def __init__(self, ctx, parent, **kwds):
DialogBase.__init__(self, ctx)
self.parent = parent
self.args = kwds
def execute(self):
args = self.args
type = args.get("type", "messbox")
buttons = args.get("buttons", 1)
title = args.get("title", "")
message = args.get("message", "")
toolkit = self.parent.getToolkit()
dialog = toolkit.createMessageBox(
self.parent, Rectangle(), type, buttons, title, message)
n = dialog.execute()
dialog.dispose()
return n
def join_url(base, name, name_encode=True):
""" Join name to base URL. """
if name_encode:
_name = name
else:
_name = unohelper.systemPathToFileUrl(name)
if base.endswith("/"):
return base + _name
return base + "/" + _name
def base_url(url):
""" Returns directory of URL. """
if url.startswith( OrganizerDialog.DOC_PROTOCOL):
return "/".join(url.split("/")[:-1])
else:
return unohelper.absolutize(url, "../")
class ErrorMessageDialog(RuntimeDialogBase):
""" Shows error message in custom dialog with selectable text. """
MARGIN = 3
BUTTON_WIDTH = 80
BUTTON_HEIGHT = 26
EDIT_HEIGHT = 300
HEIGHT = EDIT_HEIGHT + MARGIN * 5 + BUTTON_HEIGHT + MARGIN
WIDTH = 420
EDIT_NAME = "edit_name"
ERROR_ICON = "private:standardimage/error"
def __init__(self, ctx, **kwds):
RuntimeDialogBase.__init__(self, ctx)
self.args = kwds
def _init(self):
args = self.args
title = args.get("title", "")
message = args.get("message", "")
margin = self.MARGIN
self.create_dialog(title, size=(self.WIDTH, self.HEIGHT))
self.create_edit("edit_message",
pos=(margin * 4, margin * 4),
size=(self.WIDTH - margin * 8, self.EDIT_HEIGHT),
prop_names=("Border", "MultiLine", "PaintTransparent",
"ReadOnly", "VScroll"),
prop_values=(0, True, True, True, True))
self.get("edit_message").getModel().Text = message
self.create_button("btn_ok", "ok",
pos=((self.WIDTH - self.BUTTON_WIDTH)/2,
self.HEIGHT - self.BUTTON_HEIGHT - margin),
size=(self.BUTTON_WIDTH, self.BUTTON_HEIGHT),
prop_names=("DefaultButton", "Label", "PushButtonType",),
prop_values=(True, "OK", 1))
class ErrorAsMessage(Exception):
""" Tracked error message will be shown for user. """
pass
class NodeManager(object):
""" Maps between tree node and script node. """
LOADED = 0x100000
SCRIPT = 0x700000
MASK = 0xfffff
TYPE_MASK = 0xf00000
def __init__(self):
self.nodes = [] # to avoid adapter creation for each node
def _node_set(self, tree_node, node, script=False):
""" Set script node for tree_node. """
self.nodes.append(node)
i = len(self.nodes) -1
if script:
i |= self.SCRIPT
tree_node.DataValue = i
def _node_get(self, tree_node):
""" Get script node for tree_node. """
try:
i = tree_node.DataValue
if isinstance(i, int) or isinstance(i, long):
return self.nodes[i & self.MASK]
except:
pass
def _node_delete(self, tree_node):
""" Delete script node for tree_node. """
try:
i = tree_node.DataValue
if isinstance(i, int):
node = self.nodes[i & sel.MASK]
self.nodes[i] = None
except:
pass
def _node_is_script(self, tree_node):
""" Check the node is script for tree_node. """
return (tree_node.DataValue & self.TYPE_MASK) == self.SCRIPT
def _node_set_loaded(self, tree_node):
""" Set loaded flag. """
tree_node.DataValue = tree_node.DataValue | self.LOADED
def _node_is_loaded(self, tree_node):
""" Check loaded flag. """
return (tree_node.DataValue & self.TYPE_MASK) == self.LOADED
class OrganizerDialog(NodeManager, RuntimeDialogBase):
""" Alternative organizer dialog for Python scripts. """
TITLE = "Python Scripts"
TREE_NAME = "tree"
FILE_EXT = ".py"
DOC_PROTOCOL = "vnd.sun.star.tdoc"
SCRIPT_PROTOCOL = "vnd.sun.star.script"
DEFAULT_NAME = "macro"
DISK_ICON = "private:graphicrepository/res/harddisk_16.png"
DOC_ICON = "private:graphicrepository/res/sx03150.png"
DIR_ICON = "private:graphicrepository/res/fileopen.png"
FILE_ICON = "private:graphicrepository/res/im30820.png"
SCRIPT_ICON = "private:graphicrepository/res/im30821.png"
MARGIN = 3
BUTTON_WIDTH = 80
BUTTON_HEIGHT = 26
TREE_HEIGHT = 250
HEIGHT = TREE_HEIGHT + BUTTON_HEIGHT + MARGIN * 3
WIDTH = 300
ENABLE_EDIT = False
ENABLE_DEBUG = False
def __init__(self, ctx,
user_provider, share_provider, document_provider,
parent, show_icon=False):
NodeManager.__init__(self)
RuntimeDialogBase.__init__(self, ctx)
self.parent = parent
self.user_provider = user_provider
self.share_provider = share_provider
self.document_provider = document_provider
self.show_icon = show_icon
self.tree = None
self.menu = None
def execute(self, history=None):
""" Show dialog with history representes script in URI form. """
self._create_ui()
self._set_history(history)
result = None
self.dialog.setVisible(True)
n = self.dialog.execute()
if n:
result = self.tree_get_selected_node_uri()
self.tree = None
self.dialog.dispose()
return result
def button_pushed(self, command):
try:
tree_node = self.tree_get_selected_node()
if tree_node:
node = self._node_get(tree_node)
getattr(self, "exec_" + command)(tree_node, node)
except ErrorAsMessage, e:
MessageDialog(self.ctx, self.dialog.getPeer(),
type="errorbox", title="Error", message=str(e)).execute()
except Exception, e:
print(e)
traceback.print_exc()
def exec_execute(self, tree_node, node):
""" Execute selected macro. """
if self._node_is_script(tree_node):
self.dialog.endDialog(1)
def exec_menu(self, tree_node, node):
""" Shows dropdown menu. """
if not self.menu:
self._create_menu()
menu = self.menu
if tree_node:
if isinstance(node, pythonscript.ScriptBrowseNode):
states = (False, False, self.ENABLE_EDIT, False,
False, True, self.ENABLE_DEBUG)
elif isinstance(node, pythonscript.FileBrowseNode):
states = [False, False, self.ENABLE_EDIT, False,
True, True, False]
if node.uri.startswith(self.DOC_PROTOCOL):
states[3] = True
elif isinstance(node, pythonscript.DirBrowseNode):
states = (True, True, False, False, True, True, False)
else:
states = (True, True, False, False, False, False, False)
for i, state in enumerate(states):
menu.enableItem(i +1, state)
btn = self.dialog.getControl("btn_menu")
n = menu.execute(
btn.getContext().getPeer(), btn.getPosSize(), 0)
if n > 0:
self.button_pushed(menu.getCommand(n))
def exec_create_file(self, tree_node, node):
""" Create new file under selected node. """
if isinstance(node, pythonscript.PythonScriptProvider):
_node = node
node = node.dirBrowseNode
elif not isinstance(node, pythonscript.DirBrowseNode):
return
name = self._input_name("New File Name")
if not name is None and not name == "":
uri = join_url(node.rootUrl, name)
if not uri.endswith(self.FILE_EXT):
uri += self.FILE_EXT
sfa = node.provCtx.sfa
if sfa.exists(uri):
raise ErrorAsMessage("File already exists: \n" + name)
is_doc = uri.startswith(self.DOC_PROTOCOL)
try:
if is_doc:
io = self.create("com.sun.star.io.Pipe")
else:
io = sfa.openFileWrite(uri)
except Exception, e:
raise ErrorAsMessage(str(e))
try:
if TEMPLATE or is_doc:
text_out = self.create(
"com.sun.star.io.TextOutputStream")
text_out.setOutputStream(io)
text_out.setEncoding("UTF-8")
text_out.writeString(TEMPLATE)
if is_doc:
text_out.closeOutput()
sfa.writeFile(uri, io)
except Exception, e:
raise ErrorAsMessage(str(e))
finally:
if is_doc:
io.closeInput()
else:
io.closeOutput()
child_node = pythonscript.FileBrowseNode(
node.provCtx, uri, name)
self._create_new_tree_node(
tree_node, name, False, child_node)
def exec_create_dir(self, tree_node, node):
""" Create new directory under selected node. """
if isinstance(node, pythonscript.PythonScriptProvider):
_node = node
node = node.dirBrowseNode
elif not isinstance(node, pythonscript.DirBrowseNode):
return
name = self._input_name("New Directory Name", default="directory")
if not name is None and not name == "":
uri = join_url(node.rootUrl, name)
sfa = node.provCtx.sfa
if sfa.exists(uri):
raise ErrorAsMessage("Directory already exists: \n" + name)
try:
sfa.createFolder(uri)
child_node = pythonscript.DirBrowseNode(
node.provCtx, name, uri)
self._create_new_tree_node(
tree_node, name, False, child_node, True)
except Exception, e:
raise ErrorAsMessage(str(e))
def exec_substitute(self, tree_node, node):
""" Substitute script file in documents. """
if not isinstance(node, pythonscript.FileBrowseNode):
return
if not node.uri.startswith(self.DOC_PROTOCOL):
return
url = FileOpenDialog(self.ctx,
default="$(user)/Scripts/python",
filters=(("All Files (*.*)", "*.*"),
("Python Script (*.py)", "*.py"),)).execute()
if not url is None:
sfa = node.provCtx.sfa
if not sfa.exists(url):
raise ErrorAsMessage("File did not find: \n" + url)
try:
sfa.kill(node.uri)
sfa.copy(url, node.uri)
except Exception, e:
raise ErrorAsMessage(str(e))
def exec_rename(self, tree_node, node):
""" Rename selected file. """
if not (isinstance(node, pythonscript.FileBrowseNode) or \
isinstance(node, pythonscript.DirBrowseNode)):
return
current = node.getName()
name = self._input_name("Rename File", current)
if not name is None or not name == "":
if isinstance(node, pythonscript.FileBrowseNode):
uri = node.uri
elif isinstance(node, pythonscript.DirBrowseNode):
uri = node.rootUrl
new_uri = join_url(base_url(uri), name)
if not new_uri.endswith(self.FILE_EXT):
new_uri += self.FILE_EXT
sfa = node.provCtx.sfa
if not sfa.exists(uri):
raise ErrorAsMessage("Source file did not exist: \n" + current)
if sfa.exists(new_uri):
raise ErrorAsMessage("File exists: \n" + name)
try:
sfa.move(uri, new_uri)
tree_node.setDisplayValue(name)
node.name = name
except Exception, e:
raise ErrorAsMessage(str(e))
def exec_delete(self, tree_node, node):
""" Delete selected node. """
if not (isinstance(node, pythonscript.FileBrowseNode) or \
isinstance(node, pythonscript.DirBrowseNode)):
return
name = node.getName()
n = MessageDialog(self.ctx, self.dialog.getPeer(),
buttons=2, title="Delete File",
message="Do you want to delete file: \n" + name).execute()
if n == 1:
if isinstance(node, pythonscript.FileBrowseNode):
uri = node.uri
elif isinstance(node, pythonscript.DirBrowseNode):
uri = node.rootUrl
sfa = node.provCtx.sfa
try:
sfa.kill(uri)
self._node_delete(tree_node)
parent_node = tree_node.getParent()
parent_node.removeChildByIndex(
parent_node.getIndex(tree_node))
except Exception, e:
raise ErrorAsMessage(str(e))
def exec_edit(self, tree_node, node):
pass
def exec_debug(self, tree_node, node):
pass
class ListenerBase(unohelper.Base):
def __init__(self, act):
self.act = act
def disposing(self):
self.act = None
class ActionListener(ListenerBase, XActionListener):
def actionPerformed(self, ev):
self.act.button_pushed(ev.ActionCommand)
class KeyListener(ListenerBase, XKeyListener):
def keyPressed(self, ev): pass
def keyReleased(self, ev):
if ev.KeyCode == 1280:
self.act._key_pressed()
def _key_pressed(self):
node = self.tree_get_selected_node()
if node and self._node_is_script(node):
self.dialog.endDialog(1)
class MouseListener(ListenerBase, XMouseListener):
def mouseReleased(self, ev): pass
def mouseEntered(self, ev): pass
def mouseExited(self, ev): pass
def mousePressed(self, ev):
if ev.ClickCount == 2 and ev.Buttons == 1:
self.act._mouse_pressed(ev)
def _mouse_pressed(self, ev):
if ev.ClickCount == 2 and ev.Buttons == 1:
node = self.tree_get_selected_node()
if node and self._node_is_script(node):
self.dialog.endDialog(1)
class TreeExpansionListener(ListenerBase, XTreeExpansionListener):
def treeExpanding(self, ev): pass
def treeCollapsing(self, ev): pass
def treeExpanded(self, ev): pass
def treeCollapsed(self, ev): pass
def requestChildNodes(self, ev):
try:
node = ev.Node
if node:
self.act.node_requested(node)
except ErrorAsMessage, e:
MessageDialog(self.act.ctx, self.act.dialog.getPeer(),
type="errorbox", title="Error", message=str(e)).execute()
except Exception, e:
print(e)
traceback.print_exc()
def node_requested(self, tree_node):
""" Add children for the tree_node at expanding. """
data_model = self.tree.getModel().DataModel
node = self._node_get(tree_node)
try:
child_nodes = node.getChildNodes()
except Exception, e:
raise ErrorAsMessage(str(e))
if node and not tree_node.getChildCount() and child_nodes:
show_icon = self.show_icon
child_ondemand = True
is_script = False
if isinstance(node, pythonscript.ScriptBrowseNode):
return
elif isinstance(node, pythonscript.FileBrowseNode):
child_ondemand = False
is_script = True
nodes = [(child.getName(), child) for child in child_nodes]
for name, child in sorted(nodes):
tree_child = data_model.createNode(name, child_ondemand)
if show_icon:
if isinstance(child, pythonscript.ScriptBrowseNode):
icon = self.SCRIPT_ICON
elif isinstance(child, pythonscript.FileBrowseNode):
icon = self.FILE_ICON
elif isinstance(child, pythonscript.DirBrowseNode):
icon = self.DIR_ICON
else:
icon = self.FILE_ICON
self._set_node_icon(tree_child, icon)
tree_node.appendChild(tree_child)
self._node_set(tree_child, child, is_script)
self._node_set_loaded(tree_node)
def _input_name(self, title="", default=DEFAULT_NAME):
""" Let user input new name. """
return NameInput(self.ctx, title, default, self.dialog.getPeer()).execute()
def _set_history(self, history):
""" Show and select node by history. """
if history and history.startswith(self.SCRIPT_PROTOCOL):
parts = history[len(self.SCRIPT_PROTOCOL)+1:].split("?", 1)
if not len(parts) == 2 or parts[0].find("$") == -1:
return
params = parts[1].split("&")
if not "language=Python" in params:
return
location = None
for param in params:
if param.startswith("location="):
location = param[9:]
break
provider = None
if hasattr(self, location + "_provider"):
provider = getattr(self, location + "_provider")
if provider:
parent_node = self._get_tree_node(location)
self.node_requested(parent_node)
self._expand_node(parent_node)
path, func = parts[0].split("$", 1)
paths = path.split("|")
if paths[-1].endswith(self.FILE_EXT):
paths[-1] = paths[-1][:-len(self.FILE_EXT)]
paths.append(func)
tree_node = None
for path in paths:
for i in range(parent_node.getChildCount()):
tree_node = parent_node.getChildAt(i)
if tree_node.getDisplayValue() == \
uno.fileUrlToSystemPath(path):
parent_node = tree_node
self.node_requested(tree_node)
self._expand_node(parent_node)
break
if tree_node:
self.tree_select_node(tree_node)
def tree_get_selected_node(self):
""" Returns selected tree node. """
tree_node = self.tree.getSelection()
if not isinstance(tree_node, tuple):
return tree_node
return None
def tree_get_selected_node_uri(self):
""" Returns script uri if selected node is script node. """
tree_node = self.tree_get_selected_node()
if self._node_is_script(tree_node):
node = self._node_get(tree_node)
if node:
return node.getPropertyValue("URI")
def tree_select_node(self, tree_node):
""" Select tree node. """
self.tree.select(tree_node)
def _create_new_tree_node(self, tree_parent_node,
name, ondemand, node, directory=False, select=True):
""" Create new tree node under tree_parent_node. """
if not self._node_is_loaded(tree_parent_node):
self.node_requested(tree_parent_node)
return
tree_node = self.tree.getModel().DataModel.createNode(name, ondemand)
if self.show_icon:
if directory:
self._set_node_icon(tree_node, self.FILE_ICON)
else:
self._set_node_icon(tree_node, self.FILE_ICON)
tree_parent_node.appendChild(tree_node)
self._node_set(tree_node, node)
if select:
self.tree.select(tree_node)
def _create_menu(self):
""" Create popup menu. """
menu = self.create("com.sun.star.awt.PopupMenu")
menu.hideDisabledEntries(True)
self.menu = menu
items = (
(1, 0, 0, "Create File", "create_file"),
(2, 1, 0, "Create Directory", "create_dir"),
(None, 2),
(3, 3, 0, "Edit", "edit"),
(4, 4, 0, "Substitute", "substitute"),
(5, 5, 0, "Rename", "rename"),
(None, 6),
(6, 7, 0, "Delete", "delete"),
(None, 8),
(7, 9, 0, "Debug", "debug")
)
for i in items:
if i[0] is None or i[0] == -1:
menu.insertSeparator(i[1])
else:
menu.insertItem(i[0], i[3], i[2], i[1])
menu.setCommand(i[0], i[4])
def _set_node_icon(self, node, icon):
""" Set node icon. """
node.setExpandedGraphicURL(icon)
node.setCollapsedGraphicURL(icon)
def _expand_node(self, tree_node):
""" Request to expand node. """
self.tree.expandNode(tree_node)
def _get_tree_node(self, type):
tree_node = None
root_node = self.tree.getModel().DataModel.getRoot()
n = -1
if type == "user":
if self.user_provider:
n = 0
elif type == "share":
if self.share_provider:
n = 0
if self.user_provider:
n = 1
elif type == "document":
if self.document_provider:
n = 0
if self.user_provider:
n += 1
if self.share_provider:
n += 1
if n >= 0:
tree_node = root_node.getChildAt(n)
return tree_node
def _create_ui(self):
""" Create dialog ui. """
btn_action = self.ActionListener(self)
margin = self.MARGIN
btn_size = self.BUTTON_WIDTH, self.BUTTON_HEIGHT
btn_width, btn_height = btn_size
btn_prop_names = ("Label", "PushButtonType")
self.create_dialog(self.TITLE, size=(self.WIDTH, self.HEIGHT))
self.create_tree(self.TREE_NAME,
(margin, btn_height + margin * 2),
(self.WIDTH - 2 * margin, self.TREE_HEIGHT),
("Tabstop",), (True,))
self.create_button("btn_execute", "execute",
(margin, margin), btn_size,
btn_prop_names, ("Execute", 0), btn_action)
self.create_button("btn_menu", "menu",
(btn_width + margin * 2, margin), btn_size,
btn_prop_names, ("Menu", 0), btn_action)
self.create_button("btn_close", "",
(self.WIDTH - margin - btn_width, margin), btn_size,
btn_prop_names, ("Close", 2))
tree = self.dialog.getControl(self.TREE_NAME)
self.tree = tree
tree_model = tree.getModel()
data_model = self.create("com.sun.star.awt.tree.MutableTreeDataModel")
tree_model.DataModel = data_model
root = data_model.createNode("ROOT", False)
data_model.setRoot(root)
def add_node(name, provider, icon):
node = data_model.createNode(name, True)
if self.show_icon:
self._set_node_icon(node, icon)
root.appendChild(node)
self._node_set(node, provider)
if self.user_provider:
add_node("user", self.user_provider, self.DISK_ICON)
if self.share_provider:
add_node("share", self.share_provider, self.DISK_ICON)
if self.document_provider:
add_node("Document", self.document_provider, self.DOC_ICON)
tree_model.SelectionType = 1
tree_model.RootDisplayed = False
tree.addTreeExpansionListener(self.TreeExpansionListener(self))
tree.addMouseListener(self.MouseListener(self))
tree.addKeyListener(self.KeyListener(self))
tree.setFocus()
parent = self.parent
ps = parent.getPosSize()
self.dialog.setPosSize(
(ps.Width - self.WIDTH)/2, (ps.Height - self.HEIGHT)/2, 0, 0, 3)
self.dialog.createPeer(parent.getToolkit(), parent)
class PythonScriptOrganizer(object):
""" Alternative script organizer for Python scripting. """
History = None # URI of previous executed script
def __init__(self, ctx,
show_user=True, show_share=False, show_doc=True, show_icon=True):
self.ctx = ctx
self.show_icon = show_icon
self.show_user = show_user
self.show_share = show_share
self.doc = None
if show_doc:
self.doc = self._get_active_doc_uri()
self.user_sp = None
self.share_sp = None
self.document_sp = None
def _get_active_doc_uri(self):
""" Returns internal uri for the current document. """
doc = self._get_desktop().getCurrentComponent()
uri = self._get_document_uri(doc)
if uri:
return uri.rstrip("/")
def _get_desktop(self):
""" Returns desktop. """
return self.ctx.getServiceManager().createInstanceWithContext(
"com.sun.star.frame.Desktop", self.ctx)
def _get_active_frame(self):
""" Returns active frame. """
return self._get_desktop().ActiveFrame
def _store_history(self, result):
""" Store history. """
self.__class__.History = result
def _get_document_uri(self, doc):
""" Get document transient URI. """
tddc = self.ctx.getServiceManager().createInstanceWithContext(
"com.sun.star.frame.TransientDocumentsDocumentContentFactory", self.ctx)
try:
content = tddc.createDocumentContent(doc)
id = content.getIdentifier()
return id.getContentIdentifier()
except:
pass
def execute(self):
""" Show dialog. """
PythonScriptProvider = pythonscript.PythonScriptProvider
if self.show_user:
self.user_sp = PythonScriptProvider(self.ctx, u"user")
if self.show_share:
self.share_sp = PythonScriptProvider(self.ctx, u"share")
if self.doc:
self.document_sp = PythonScriptProvider(self.ctx, self.doc)
dialog = OrganizerDialog(
self.ctx,
self.user_sp, self.share_sp, self.document_sp,
self._get_active_frame().getContainerWindow(),
self.show_icon)
result = dialog.execute(self.__class__.History)
if result:
self._store_history(result)
self.run(result)
def _get_provider(self, uri):
""" Find specific provider. """
for p in uri.split("&"):
if p.startswith("location="):
try:
return getattr(self, p[9:] + "_sp")
except:
pass
def run(self, uri):
""" Run script specified by script uri. """
try:
sp = self._get_provider(uri)
if sp:
s = sp.getScript(uri)
if s:
s.invoke((), (), ())
else:
raise ErrorAsMessage("No script found for: \n" + uri)
else:
raise ErrorAsMessage("No provider found for: \n" + uri)
except UNOException, e:
ErrorMessageDialog(
self.ctx, title="Error", message=str(e)).execute()
except ErrorAsMessage, e:
MessageDialog(self.ctx, self._get_active_frame().getContainerWindow(),
type="errorbox", title="Error", message=str(e)).execute()
def user(*args):
""" User's script only. """
ctx = XSCRIPTCONTEXT.getComponentContext()
pso = PythonScriptOrganizer(ctx, True, False, False, True)
pso.execute()
def doc(*args):
""" Both user's and Document's scripts are shown. """
ctx = XSCRIPTCONTEXT.getComponentContext()
pso = PythonScriptOrganizer(ctx, True, False, True, True)
pso.execute()
g_exportedScripts = user, doc
Supported functions:
- Create new script file or directory
- Substitute script file embedded in a document
- Delete script file and directory
- Rename script file and directory
Any Python macros installed by extensions are not shown now.
Edit: Fix according to karolus's post. |