Note: For solution, see end of message under highlighted "Solved".
Hello, this is my first post in the Inkscape Community Forums.
I have been looking over the
PythonEffectTutorial & the
Python modules for extensions pages on the wiki. What I want to do is create a Python extension that simply calls the menu functions
Path -> Combine | Path -> Union | Path -> Simplify | Path -> Break Apart in that order on the selected objects in the document.
I am familiar with scripting in Python, but I'm pretty lost in creating this extension as this is all I have so far:
#!/usr/bin/env python
# This script is licensed under CC0
import inkex
class SimplePathOptimize(inkex.Effect):
def run(self):
svg = self.document.getroot()
SimplePathOptimize().run()
I'm not sure if I'm even on the right trail. If anyone could show me how to access & execute the menu functions from within a Python extension, I would really appreciate it.
I am using Inkscape version 0.92.2 on Windows 10 64-bit.
Edit: Forgot to mention that I have been looking in the pre-installed extensions to try to get an idea as well.
Edit: I've gotten a little closer:
class SimplePathOptimize(inkex.Effect):
def __init__(self):
inkex.Effect.__init__(self)
def effect(self):
selected = self.selected
if not selected:
inkex.errormsg('Please select an object')
return
# TODO: call functions on selected objects
if __name__ == '__main__':
SimplePathOptimize().affect()
Edit: I've been told to use
verbs for what I want to do. So my script now creates a temporary copy of the currently opened SVG document. But I'm not sure how pass the selected objects to Inkscape to select them in the temporary document:
#!/usr/bin/env python
# This work is released under Creative Commons Zero (CC0).
#
# The author hereby waives all copyright and related or
# neighboring rights together with all associated claims
# and causes of action with respect to this work to the
# extent possible under the law.
#
# See: https://creativecommons.org/publicdomain/zero/1.0/legalcode
import inkex, os, subprocess, sys, tempfile, traceback
# in case run outside of Inkscape's extensions directory on Linux/Unix-like systems
sys.path.append('/usr/share/inkscape/extensions')
# helper function for calling inkscape commands
def execute(params=None):
cmd = ['inkscape']
if sys.platform == 'win32':
# support stdout on Windows
cmd[0] = 'inkscape.com'
if not params:
params = cmd
else:
if type(params) == str:
params = params.split(' ')
elif type(params) == tuple:
params = list(params)
params = cmd + params
proc = subprocess.Popen(params, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = proc.communicate()
if err:
# clean up error message
err = err.strip(' \t\n\r')
inkex.errormsg('Error: {}'.format(err))
return
# clean up output
return out.strip(' \t\n\r')
# main class
class SimplePathOptimize(inkex.Effect):
def __init__(self):
inkex.Effect.__init__(self)
def effect(self):
selected = self.selected
if not selected:
inkex.errormsg('Please select object(s)')
return
# create a temp SVG document
temp_file = tempfile.mktemp('temp.svg')
self.document.write(temp_file)
verb_list = (
'SelectionCombine',
'SelectionUnion',
'SelectionSimplify',
'SelectionBreakApart',
'FileSave',
'FileQuit',
)
cmd_list = []
for V in verb_list:
cmd_list.append('--verb={}'.format(V))
cmd_list += ['-f', temp_file]
execute(cmd_list)
# delete temporary file
try:
os.remove(temp_file)
except:
msg = 'Error removing temporary file: {}\n\n'.format(temp_file)
msg += traceback.format_exc()
# clean up message
msg = msg.strip(' \t\n\r')
inkex.errormsg(msg)
if __name__ == '__main__':
SimplePathOptimize().affect()
Solved: Okay, figured out that I needed to use the "--select" parameter. Then I read the information from the saved temp file & update the open document. Here is the full extension script:
simple_path_optimize.py:#!/usr/bin/env python
# This work is released under Creative Commons Zero (CC0).
#
# The author hereby waives all copyright and related or
# neighboring rights together with all associated claims
# and causes of action with respect to this work to the
# extent possible under the law.
#
# See: https://creativecommons.org/publicdomain/zero/1.0/legalcode
import inkex, os, subprocess, sys, tempfile, traceback
# in case run outside of Inkscape's extensions directory on Linux/Unix-like systems
sys.path.append('/usr/share/inkscape/extensions')
# helper function for calling inkscape commands
def execute(params=None):
# verbs require GUI so cannot use '-z' paramater?
#cmd = ['inkscape', '-z',]
cmd = ['inkscape',]
if sys.platform == 'win32':
# support stdout on Windows
cmd[0] = 'inkscape.com'
if not params:
params = cmd
else:
if type(params) == str:
params = params.split(' ')
elif type(params) == tuple:
params = list(params)
params = cmd + params
proc = subprocess.Popen(params, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = proc.communicate()
if err:
# clean up error message
err = err.strip(' \t\n\r')
inkex.errormsg('Error: {}'.format(err))
return
# clean up output
return out.strip(' \t\n\r')
# main class
class SimplePathOptimize(inkex.Effect):
def __init__(self):
inkex.Effect.__init__(self)
def effect(self):
selected = self.selected
if not selected:
inkex.errormsg('Please select object(s) for path optimization')
return
# create a temp SVG document
temp_file = tempfile.mktemp('temp.svg')
self.document.write(temp_file)
# get all selected paths for selection in temp document
cmd_list = []
for S in selected:
cmd_list.append('--select={}'.format(S))
verb_list = (
'SelectionCombine',
'SelectionUnion',
'SelectionSimplify',
'SelectionBreakApart',
'FileSave',
'FileQuit',
)
for V in verb_list:
cmd_list.append('--verb={}'.format(V))
cmd_list += ['-f', temp_file]
execute(cmd_list)
# get results
BUFFER = open(temp_file, 'r')
new_document = inkex.etree.parse(BUFFER)
BUFFER.close()
# delete temporary file
try:
os.remove(temp_file)
except:
msg = 'Error removing temporary file: {}\n\n'.format(temp_file)
msg += traceback.format_exc()
# clean up message
msg = msg.strip(' \t\n\r')
inkex.errormsg(msg)
# update open document
self.document = new_document
if __name__ == '__main__':
SimplePathOptimize().affect()
simple_path_optimize.inx:<?xml version="1.0" encoding="UTF-8"?>
<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
<_name>Simple Path Optimize</_name>
<id>org.inkscape.modify_path.simple_path_optimize</id>
<effect>
<object-type>all</object-type>
<effects-menu>
<submenu _name="Modify Path"/>
</effects-menu>
</effect>
<script>
<command reldir="extensions" interpreter="python">simple_path_optimize.py</command>
</script>
</inkscape-extension>
Uploaded the extension for anyone that might like to use it:
Simple Path Optimize