mightyscape-1.2/extensions/fablabchemnitz/qcad_svg_to_modern_dxf/qcad_svg_to_modern_dxf.py

121 lines
5.5 KiB
Python

#!/usr/bin/env python3
import inkex
import os
import shutil
import sys
import subprocess
from subprocess import Popen, PIPE
'''
Simple extension to utilize QCAD Pro for some neat DXF operations. Based on:
- https://ribbonsoft.com/rsforum/viewtopic.php?t=6801
- https://qcad.org/rsforum/viewtopic.php?t=8471
written 14.01.2024 by Mario Voigt / Stadtfabrikanten e.V.
ToDos
- black colored paths are getting blue or brown when using DXF Export of QCAD. Why? How to change this?
- keep canvas format
- keep original SVG Unit
'''
class QCAD_SVG(inkex.OutputExtension):
def __init__(self):
inkex.Effect.__init__(self)
def add_arguments(self, pars):
pars.add_argument("--tab")
pars.add_argument("--qcad_dxf_format", default="dxflib", help="DXF Export Type")
pars.add_argument("--qcad_join_polylines", type=inkex.Boolean, default=True, help="Join Polylines")
pars.add_argument("--qcad_tolerance", type=float, default=0.001, help="Polyline Tolerance")
pars.add_argument("--qcad_purge_duplicates", type=inkex.Boolean, default=False, help="Purge duplicate lines")
pars.add_argument("--qcad_pro_path", default="~/opt/qcad-3.28.2-pro-linux-x86_64/qcad", help="Location of qcad pro executable")
pars.add_argument("--debug", type=inkex.Boolean, default=False, help="Show debug info")
pars.add_argument("--open_in_qcad", type=inkex.Boolean, default=False, help="Open export file in QCAD")
def inplace_change(self, filename, old_string, new_string):
with open(filename) as f:
s = f.read()
with open(filename, 'w') as f:
s = s.replace(old_string, new_string)
f.write(s)
def effect(self):
so = self.options
if os.path.exists(so.input_file) is False:
inkex.utils.debug("WARNING: File was not saved yet! Try again after saving.")
exit(1)
qcad_pro_path = os.path.relpath(so.qcad_pro_path)
tmpdir_path = os.path.dirname(so.input_file)
export_path = self.document_path()
qcad_script = "qcad-dxf-script.js"
if so.qcad_join_polylines is True:
qcad_join_polylines = "true"
else:
qcad_join_polylines = "false"
qcad_tolerance = "{:6.6f}".format(so.qcad_tolerance)
if so.qcad_purge_duplicates is True:
qcad_purge_duplicates = "true"
else:
qcad_purge_duplicates = "false"
qcad_dxf_format = so.qcad_dxf_format
if so.debug is True:
inkex.utils.debug("Input file:{}".format(so.input_file))
inkex.utils.debug("/tmp dir Path:{}".format(tmpdir_path))
inkex.utils.debug("Export Path{}".format(export_path))
inkex.utils.debug("QCAD Pro Path: {}".format(qcad_pro_path))
inkex.utils.debug("QCAD Polyline Tolerance: {}".format(qcad_tolerance))
inkex.utils.debug("QCAD DXF Format: {}".format(qcad_dxf_format))
#we must copy the input file to a new file with ending *.svg. Otherwise QCAD does not recognise the file type
target_file = self.options.input_file + ".svg"
shutil.copy2(self.options.input_file, target_file)
#copy the qcad-dxf-script.js file to temporary location and modify its content
shutil.copy2(qcad_script, tmpdir_path)
qcad_script_tmp = os.path.join(tmpdir_path, qcad_script)
self.inplace_change(qcad_script_tmp, "$SVG_PATH$", target_file)
self.inplace_change(qcad_script_tmp, "$QCAD_JOIN_POLYLINES$", qcad_join_polylines)
self.inplace_change(qcad_script_tmp, "$QCAD_TOLERANCE$", qcad_tolerance)
self.inplace_change(qcad_script_tmp, "$EXPORT_PATH$", export_path)
self.inplace_change(qcad_script_tmp, "$QCAD_DXF_FORMAT$", qcad_dxf_format)
self.inplace_change(qcad_script_tmp, "$QCAD_PURGE_DUPLICATES$", qcad_purge_duplicates)
#build the command and execute the script
command = [qcad_pro_path + " -autostart \"" + qcad_script_tmp + "\""]
proc = subprocess.Popen(command, shell=True, stdout=PIPE, stderr=PIPE)
stdout, stderr = proc.communicate()
if proc.returncode != 0: #in this case we exit
inkex.utils.debug("QCAD Console Output: %d %s %s" % (proc.returncode, stdout, stderr))
if "Application already running" in stderr.decode('UTF-8'):
inkex.utils.debug("Warning. QCAD already running. Please close it and run this extension again!")
if so.debug is True:
inkex.utils.debug(stdout.decode('UTF-8'))
inkex.utils.debug(stderr.decode('UTF-8'))
proc.wait()
if so.open_in_qcad is True:
command = [qcad_pro_path + " " + export_path]
proc = subprocess.Popen(command, shell=True, stdout=PIPE, stderr=PIPE)
stdout, stderr = proc.communicate()
if proc.returncode != 0: #in this case we exit
inkex.utils.debug("QCAD Console Output: %d %s %s" % (proc.returncode, stdout, stderr))
if so.debug is True:
inkex.utils.debug(stdout.decode('UTF-8'))
inkex.utils.debug(stderr.decode('UTF-8'))
proc.wait()
#this is just implemented to avoid a warning. The file gets written twice, because its already generated by QCAD, then it gets written again by save() method
def save(self, stream):
with open(self.document_path(), 'rb') as finalfile:
stream.write(finalfile.read())
if __name__ == '__main__':
QCAD_SVG().run()