refactored file structures to match extension ids, file names and class names
This commit is contained in:
63
extensions/fablabchemnitz/nextgenerator/nextgenerator.inx
Normal file
63
extensions/fablabchemnitz/nextgenerator/nextgenerator.inx
Normal file
@ -0,0 +1,63 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
|
||||
<name>NextGenerator</name>
|
||||
<id>fablabchemnitz.de.nextgenerator</id>
|
||||
<param name="tab" type="notebook">
|
||||
<page name="config" gui-text="Options">
|
||||
<label appearance="header">Input options</label>
|
||||
<param gui-text="CSV file:" gui-description="A file with comma-separated values, one line per exported file. The first line contains the column names. Put quotation marks around your variables if they contain a comma." name="csv_file" type="path" mode="file" filetypes="csv">/path/to/file.csv</param>
|
||||
<spacer/>
|
||||
<label>Non-text values to replace (see Help tab):</label>
|
||||
<param name="extra-vars" type="string" gui-text=""/>
|
||||
<spacer/>
|
||||
<separator/>
|
||||
<spacer/>
|
||||
<label appearance="header">Output options</label>
|
||||
<param name="format" type="optiongroup" appearance="combo" gui-text="Export file format:">
|
||||
<option value="png">PNG</option>
|
||||
<option value="pdf">PDF</option>
|
||||
<option value="svg">SVG</option>
|
||||
<option value="ps">PS</option>
|
||||
<option value="eps">EPS</option>
|
||||
</param>
|
||||
<param gui-text="DPI (for PNG and filters):" gui-description="The resolution for your exported raster images" name="dpi" type="int" min="1" max="10000">300</param>
|
||||
<param gui-text="File name pattern:" gui-description="The pattern for the names of the generated files. It should contain at least one unique column variable (in the form of '%VAR_my_variablename%'), or a unique combination of column variables, so new files won't overwrite those that have already been generated. Do not include the file extension, it will be added automatically." name="file_pattern" type="string">%VAR_my_variablename%</param>
|
||||
<param gui-text="Save in:" gui-description="The name of the folder where the generated images should be saved" name="output_folder" type="path" mode="folders">/tmp</param>
|
||||
</page>
|
||||
<page name="help" gui-text="Help">
|
||||
<label appearance="header">Replacing text</label>
|
||||
<label xml:space="preserve">
|
||||
In your SVG file, create any texts that you want to replace by clicking (not clicking and dragging) on the canvas. If you want to limit the width of the text, use the diamond-shaped handle at the end of the first line to indicate a maximum width. The text will auto-flow into the next line if it is longer. Make sure there is enough space for your texts.
|
||||
|
||||
As (or into) the text, type '%VAR_my_variablename%' (without the quotes) as a placeholder, where 'my_variablename' is the title of the corresponding column in your CSV data file.
|
||||
</label>
|
||||
<label appearance="header">Replacing attributes</label>
|
||||
<label xml:space="preserve">If you want to replace attribute values in your SVG file (e.g. a color, or the name of a linked image file), you can assign them to columns in the field labeled "Non-text values to replace" in JSON format like this (no linebreaks allowed):
|
||||
|
||||
{"background_color":"#ff0000", "photo":"image.png"}
|
||||
|
||||
All objects that use the red color (#ff0000) will then be exported using the colors in the column 'background_color'. The linked image 'image.png' will be replaced by the image files listed in the column 'photo' (make sure to replace the complete image path).
|
||||
</label>
|
||||
</page>
|
||||
<page name="about" gui-text="About">
|
||||
<label appearance="header">NextGenerator</label>
|
||||
<label indent="1">Version 0.8</label>
|
||||
<spacer/>
|
||||
<label xml:space="preserve">An Inkscape extension to automatically replace values (text, attribute values) in an SVG file and to then export the result to various file formats. This is useful e.g. for generating images for name badges and other similar items.
|
||||
|
||||
This extension is a Python rewrite of the Generator bash script extension by Aurélio A. Heckert. It is compatible with Inkscape starting from version 1.0 and requires Python 3.</label>
|
||||
</page>
|
||||
</param>
|
||||
<effect needs-live-preview="false">
|
||||
<object-type>all</object-type>
|
||||
<effects-menu>
|
||||
<submenu name="FabLab Chemnitz">
|
||||
<submenu name="Import/Export/Transfer"/>
|
||||
</submenu>
|
||||
</effects-menu>
|
||||
<menu-tip>Automatically replace values and export the result.</menu-tip>
|
||||
</effect>
|
||||
<script>
|
||||
<command location="inx" interpreter="python">nextgenerator.py</command>
|
||||
</script>
|
||||
</inkscape-extension>
|
142
extensions/fablabchemnitz/nextgenerator/nextgenerator.py
Normal file
142
extensions/fablabchemnitz/nextgenerator/nextgenerator.py
Normal file
@ -0,0 +1,142 @@
|
||||
#!/usr/bin/env python
|
||||
# coding=utf-8
|
||||
#
|
||||
# NextGenerator - an Inkscape extension to export images with automatically replaced values
|
||||
# Copyright (C) 2008 Aurélio A. Heckert (original Generator extension in Bash)
|
||||
# 2019 Maren Hachmann (Python rewrite, update for Inkscape 1.0)
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
# Version 0.9
|
||||
"""
|
||||
An Inkscape extension to automatically replace values (text, attribute values)
|
||||
in an SVG file and to then export the result to various file formats.
|
||||
|
||||
This is useful e.g. for generating images for name badges and other similar items.
|
||||
"""
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import os
|
||||
import csv
|
||||
import json
|
||||
import time #for debugging purposes
|
||||
import inkex
|
||||
from inkex.command import inkscape
|
||||
|
||||
|
||||
class NextGenerator(inkex.base.TempDirMixin, inkex.base.InkscapeExtension):
|
||||
"""Generate image files by replacing variables in the current file"""
|
||||
|
||||
def add_arguments(self, pars):
|
||||
pars.add_argument("-c", "--csv_file", type=str, dest="csv_file", help="path to a CSV file")
|
||||
pars.add_argument("-e", "--extra-vars", help="additional variables to replace and the corresponding columns, in JSON format")
|
||||
pars.add_argument("-f", "--format", help="file format to export to: png, pdf, svg, ps, eps")
|
||||
pars.add_argument("-d", "--dpi", type=int, default="300", help="dpi value for exported raster images")
|
||||
pars.add_argument("-o", "--output_folder", help="path to output folder")
|
||||
pars.add_argument("-p", "--file_pattern", help="pattern for the output file")
|
||||
pars.add_argument("-t", "--tab", type=str, default="any", help="not needed at all")
|
||||
pars.add_argument("-i", "--id", type=str, default="", help="not needed at all")
|
||||
|
||||
def effect(self):
|
||||
|
||||
# load the attributes that should be replaced in addition to textual values
|
||||
if self.options.extra_vars == None:
|
||||
self.options.extra_vars = '{}'
|
||||
|
||||
extra_vars = json.loads(self.options.extra_vars)
|
||||
|
||||
|
||||
# load the CSV file
|
||||
# spaces around commas will be stripped
|
||||
csv.register_dialect('generator', 'excel', skipinitialspace=True)
|
||||
|
||||
with open(self.options.csv_file, newline='', encoding='utf-8-sig') as csvfile:
|
||||
|
||||
data = csv.DictReader(csvfile, dialect='generator')
|
||||
|
||||
for row in data:
|
||||
export_base_name = self.options.file_pattern
|
||||
self.new_doc = self.document
|
||||
for i, (key, value) in enumerate(row.items()):
|
||||
search_string = "%VAR_" + key + "%"
|
||||
# replace any occurrances of %VAR_my_variable_name% in the SVG file source code
|
||||
self.new_doc = self.new_doc.replace(search_string, value)
|
||||
# build the file name, still without file extension
|
||||
export_base_name = export_base_name.replace(search_string, value)
|
||||
for key, svg_cont in extra_vars.items():
|
||||
if key in row.keys():
|
||||
# replace any attributes and other SVG content by the values from the CSV file
|
||||
self.new_doc = self.new_doc.replace(svg_cont, row[key])
|
||||
else:
|
||||
inkex.errormsg("The replacements in the generated images may be incomplete. Please check your entry '{key}' in the field for the non-text values.").format(key=key)
|
||||
if self.export(export_base_name) != True:
|
||||
return
|
||||
|
||||
def export(self, export_base_name):
|
||||
|
||||
export_file_name = '{0}.{1}'.format(export_base_name, self.options.format)
|
||||
|
||||
if os.path.exists(self.options.output_folder):
|
||||
export_file_path = os.path.join(self.options.output_folder, export_file_name)
|
||||
else:
|
||||
inkex.errormsg("The selected output folder does not exist.")
|
||||
return False
|
||||
|
||||
|
||||
if self.options.format == 'svg':
|
||||
# would use this, but it cannot overwrite, nor handle strings for writing...:
|
||||
# write_svg(self.new_doc, export_file_path)
|
||||
with open(export_file_path, 'w') as f:
|
||||
f.write(self.new_doc)
|
||||
else:
|
||||
|
||||
actions = {
|
||||
'png' : 'export-dpi:{dpi};export-filename:{file_name};export-do;FileClose'.\
|
||||
format(dpi=self.options.dpi, file_name=export_file_path),
|
||||
'pdf' : 'export-dpi:{dpi};export-pdf-version:1.5;export-text-to-path;export-filename:{file_name};export-do;FileClose'.\
|
||||
format(dpi=self.options.dpi, file_name=export_file_path),
|
||||
'ps' : 'export-dpi:{dpi};export-text-to-path;export-filename:{file_name};export-do;FileClose'.\
|
||||
format(dpi=self.options.dpi, file_name=export_file_path),
|
||||
'eps' : 'export-dpi:{dpi};export-text-to-path;export-filename:{file_name};export-do;FileClose'.\
|
||||
format(dpi=self.options.dpi, file_name=export_file_path),
|
||||
}
|
||||
|
||||
# create a temporary svg file from our string
|
||||
temp_svg_name = '{0}.{1}'.format(export_base_name, 'svg')
|
||||
temp_svg_path = os.path.join(self.tempdir, temp_svg_name)
|
||||
#inkex.utils.debug("temp_svg_path=" + temp_svg_path)
|
||||
with open(temp_svg_path, 'w') as f:
|
||||
f.write(self.new_doc)
|
||||
#inkex.utils.debug("self.new_doc=" + self.new_doc)
|
||||
# let Inkscape do the exporting
|
||||
# self.debug(actions[self.options.format])
|
||||
cli_output = inkscape(temp_svg_path, actions=actions[self.options.format])
|
||||
|
||||
if len(cli_output) > 0:
|
||||
self.debug(_("Inkscape returned the following output when trying to run the file export; the file export may still have worked:"))
|
||||
self.debug(cli_output)
|
||||
return False
|
||||
return True
|
||||
|
||||
def load(self, stream):
|
||||
return str(stream.read(), 'utf-8')
|
||||
|
||||
def save(self, stream):
|
||||
# must be implemented, but isn't needed.
|
||||
pass
|
||||
|
||||
if __name__ == '__main__':
|
||||
NextGenerator().run()
|
Reference in New Issue
Block a user