121 lines
5.5 KiB
Python
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() |