Hello, I have started today at making a small extension for myself to help with a repetitive task I have to do from time to time:
Moving a selected object by a certain amount of pixels and printing to pdf. This is used to get full pdf prints of objects that are larger than one page.
Generally the moving and cycling through seems to work fine, but I just can't get the export to PDF to work and I am seriously struggling with documentation I either can't find or solutions that don't seem to work anymore.
For the export to PDF I am trying to use this line (where file_path grabs the currently opened temporary file)
In case that the issue might be somewhere else I will add the rest of my code. This is the first thing I've coded in years and the first thing in python ever, so please forgive the numerous inefficiencies and other issues.
#!/usr/bin/env python
import subprocess
import inkex
from inkex.transforms import Transform
class MoveAndPrint(inkex.EffectExtension):
def add_arguments(self, pars):
pars.add_argument(
"--pages_x",
type=int,
help="Number of horizontal pages",
)
pars.add_argument(
"--pages_y",
type=int,
help="Number of vertical pages",
)
pars.add_argument(
"--offset_x",
type=int,
help="Number of segments to divide the path into",
)
pars.add_argument(
"--offset_y",
type=int,
help="Number of segments to divide the path into",
)
pars.add_argument(
"--output_path",
help="Number of segments to divide the path into",
)
pars.add_argument("--tab")
def effect(self):
x_shift = self.options.offset_x
y_shift = self.options.offset_y
pdf_path = self.options.output_path
pages_x = self.options.pages_x
pages_y = self.options.pages_y
selected_items = self.svg.selected
base_x = ""
base_y = ""
for elem in selected_items:
bbox = elem.bounding_box()
base_x = elem.left
base_y = elem.top
for page_x in range(pages_x):
for page_y in range(pages_y):
for item in selected_items:
inkex.debug("Page " + str(page_x) + " " + str(page_y))
item.set('x', str(page_x * x_shift))
item.set('y', str(page_y * y_shift))
file_path = self.options.input_file
inkex.debug("File Path: " + str(file_path))
save_path = pdf_path + str(page_x) + str(page_y) + ".pdf"
inkex.debug("PDF Path: " + save_path)
if save_path:
subprocess.call(['inkscape', '-f', str(file_path), '--export-pdf', save_path])
if __name__ == "__main__":
MoveAndPrint().run()
# Make a temp folder to save changes to self.svg
import tempfile, os
temp_folder = tempfile.mkdtemp()
# Attach reference to temp folder to self.
MoveAndPrint.temp_folder = temp_folder
for page_x in range(pages_x):
for page_y in range(pages_y):
for item in selected_items:
inkex.debug("Page " + str(page_x) + " " + str(page_y))
item.set('x', str(page_x * x_shift))
item.set('y', str(page_y * y_shift))
file_path = self.options.input_file
inkex.debug("File Path: " + str(file_path))
save_path = pdf_path + str(page_x) + str(page_y) + ".pdf"
inkex.debug("PDF Path: " + save_path)
if save_path:
# Use uuid to generate a long unique string for temp filename
from uuid import uuid4
current_svg_temp_filepath = os.path.join(temp_folder, f'{str(uuid4())}.svg')
# Let us save the current state of the svg to the temp folder
with open(current_svg_temp_filepath, 'wb') as output_file:
self.save(output_file)
my_actions = '--actions='
export_pdf_actions = my_actions + f'export-filename:{save_path};export-do;'
inkex.command.inkscape(current_svg_temp_filepath, export_pdf_actions)
# Cleanup temp folder
import shutil
if hasattr(self, 'temp_folder'):
shutil.rmtree(self.temp_folder)
Import statements should be at the top - but I put them before the relevant code so you can see them.
self.options.input_file does not change while the extension is running so you do have to save the self.svg if you want to use the current state of the svg with the command line.
Thank you for the advice. I can see the temp folder and saving working, and it seems to properly loop, but sadly I still don't get any PDF output with this.
Do you have any idea left how I could debug this? If scaling is preserved, in the worst case I can also just convert the SVGs to PDF in batch afterwards, but I doubt this can be done without issues.
The export_pdf_actions = my_actions + f'export-filename:{save_path};export-do;'
that line can be edited to be any valid list of actions. However the only reason it will output to .pdf is because {save_path} string has a .pdf extension at the end.
Also if you do not give a complete path for the output_file, the files will will dumped by default into the root folder where your .py extension file is.
Have a look in there - you might see them :)
Really you should use a file chooser:
# Path param - for selecting making files / folders <param type="my_path" name="save_path" gui-text="File Save Path" mode="folder">None Selected</param> pars.add_argument("--my_path", type=str, dest="my_path")
Probably better to use the mode="folder" as above, and use the string entry for the user to choose the base file name. Add an increment to the user string, and .svg
then use os.path.join(my_path, base_filename_string) for the save filepath.
Usually you would use some kind of try / except loop in case the user has navigated to a folder which cannot be saved in etc and use inkex.errormsg('Cannot save file') in the except block
Sadly the files are also not present in the default location, but I suspect that the SVG would be good enough and to then convert them in batch with a different program.
However my new issue I've found is that groups don't have left or top properties that I can use to find the location, and I suspect I also can't use "set" to move the group like that. Any idea here? I can convert the group to a path, but a path also doesn't have the properties I have wanted to use. It seems like my first try only really worked with the rectangle...
Sorry for the late answer. What I was planning to do was basically a semi-automated version of this video: https://youtu.be/i2OFr1pVxuA
In the prompt I query for horizontal and vertical pages, as well as pixel height and width of pages (which I screwed up since I didn't realize that inkscape also works with fractions of pixels).
I have somewhat put this on the back burner now considering I found too many other issues in my code outside of saving. (But the pdf save really isn't necessary, since I can just convert the svgs in batch with PDF24 for example).
Hello, I have started today at making a small extension for myself to help with a repetitive task I have to do from time to time:
Moving a selected object by a certain amount of pixels and printing to pdf. This is used to get full pdf prints of objects that are larger than one page.
Generally the moving and cycling through seems to work fine, but I just can't get the export to PDF to work and I am seriously struggling with documentation I either can't find or solutions that don't seem to work anymore.
For the export to PDF I am trying to use this line (where file_path grabs the currently opened temporary file)
In case that the issue might be somewhere else I will add the rest of my code.
This is the first thing I've coded in years and the first thing in python ever, so please forgive the numerous inefficiencies and other issues.
and the corresponding inx file:
I hope someone can help me with this or point me in the right direction.
maybe something like this :
Import statements should be at the top - but I put them before the relevant code so you can see them.
self.options.input_file does not change while the extension is running so you do have to save the self.svg if you want to use the current state of the svg with the command line.
Thank you for the advice. I can see the temp folder and saving working, and it seems to properly loop, but sadly I still don't get any PDF output with this.
Do you have any idea left how I could debug this? If scaling is preserved, in the worst case I can also just convert the SVGs to PDF in batch afterwards, but I doubt this can be done without issues.
I should have mentioned a couple of things.
The
export_pdf_actions = my_actions + f'export-filename:{save_path};export-do;'
that line can be edited to be any valid list of actions. However the only reason it will output to .pdf is because
{save_path}
string has a .pdf extension at the end.Also if you do not give a complete path for the
output_file
, the files will will dumped by default into the root folder where your .py extension file is.Have a look in there - you might see them :)
Really you should use a file chooser:
# Path param - for selecting making files / folders
<param type="my_path" name="save_path" gui-text="File Save Path" mode="folder">None Selected</param>
pars.add_argument("--my_path", type=str, dest="my_path")
Probably better to use the mode="folder" as above, and use the string entry for the user to choose the base file name. Add an increment to the user string, and .svg
then use os.path.join(my_path, base_filename_string) for the save filepath.
Usually you would use some kind of try / except loop in case the user has navigated to a folder which cannot be saved in etc and use
inkex.errormsg('Cannot save file')
in the except blockSadly the files are also not present in the default location, but I suspect that the SVG would be good enough and to then convert them in batch with a different program.
However my new issue I've found is that groups don't have left or top properties that I can use to find the location, and I suspect I also can't use "set" to move the group like that. Any idea here? I can convert the group to a path, but a path also doesn't have the properties I have wanted to use. It seems like my first try only really worked with the rectangle...
Yes, It's something that I was able to get away with in Linux, not in Windows.
Do you just want to move an element around a page by pixels and save each time ? - or do you want to involve Inkscape Pages too ?
If you just specify exactly what you want to perform, I will see if I can make an example
Sorry for the late answer. What I was planning to do was basically a semi-automated version of this video: https://youtu.be/i2OFr1pVxuA
In the prompt I query for horizontal and vertical pages, as well as pixel height and width of pages (which I screwed up since I didn't realize that inkscape also works with fractions of pixels).
I have somewhat put this on the back burner now considering I found too many other issues in my code outside of saving. (But the pdf save really isn't necessary, since I can just convert the svgs in batch with PDF24 for example).