Draft: improve handling of DWG-converters (#9444)

* Draft: improve handling of DWG-converters

* Lint import statement.
This commit is contained in:
Roy-043
2023-05-07 09:56:01 +02:00
committed by GitHub
parent 2d76f02484
commit 8ccdd8e80e

View File

@@ -12,10 +12,6 @@ This module is only a thin layer that uses the ODA (formerly Teigha) File
Converter application to convert to/from DXF. Then the real work is done by
importDXF
The converter may be called
/usr/bin/TeighaFileConverter
/usr/bin/ODAFileConverter
Test files
https://knowledge.autodesk.com/support/autocad/downloads/
caas/downloads/content/autocad-sample-files.html
@@ -125,7 +121,9 @@ def export(objectslist, filename):
str
The same `filename` input.
"""
import importDXF, os, tempfile
import importDXF
import os
import tempfile
outdir = tempfile.mkdtemp()
_basename = os.path.splitext(os.path.basename(filename))[0]
dxf = outdir + os.sep + _basename + ".dxf"
@@ -134,11 +132,54 @@ def export(objectslist, filename):
return filename
def getTeighaConverter():
"""Find the ODA (formerly Teigha) executable.
def get_libredwg_converter(typ):
"""Find the LibreDWG converter.
It searches the FreeCAD parameters database, then searches the OS search path
on Linux and Windows systems. There are no standard installation paths.
`typ` is required because LibreDWG uses two converters and we store only one.
Parameters
----------
typ : str
"dwg2dxf" or "dxf2dwg".
Returns
-------
str
The full path of the converter.
"""
import os
import platform
p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft")
path = p.GetString("TeighaFileConverter")
if "dwg2dxf" in path or "dxf2dwg" in path: # path set manually
if typ not in path:
path = os.path.dirname(path) + "/" + typ + os.path.splitext(path)[1]
if os.path.exists(path) and os.path.isfile(path):
return path
elif platform.system() == "Linux":
for sub in os.getenv("PATH").split(":"):
path = sub + "/" + typ
if os.path.exists(path) and os.path.isfile(path):
return path
elif platform.system() == "Windows":
for sub in os.getenv("PATH").split(";"):
path = sub.replace("\\", "/") + "/" + typ + ".exe"
if os.path.exists(path) and os.path.isfile(path):
return path
return None
def get_oda_converter():
"""Find the ODA converter.
It searches the FreeCAD parameters database, then searches for common
paths in Linux and Windows systems.
paths on Linux and Windows systems.
Parameters
----------
@@ -147,26 +188,67 @@ def getTeighaConverter():
Returns
-------
str
The full path of the converter executable
'/usr/bin/ODAFileConverter'
The full path of the converter.
"""
import FreeCAD, os, platform
import os
import platform
p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft")
path = p.GetString("TeighaFileConverter")
if path:
# path set manually
return path
if "ODAFileConverter" in path: # path set manually
if os.path.exists(path) and os.path.isfile(path):
return path
elif platform.system() == "Linux":
path = "/usr/bin/ODAFileConverter"
if os.path.exists(path):
if os.path.exists(path) and os.path.isfile(path):
return path
elif platform.system() == "Windows":
odadir = os.path.expandvars("%ProgramFiles%\ODA")
odadir = os.path.expandvars("%ProgramFiles%\\ODA").replace("\\", "/")
if os.path.exists(odadir):
for sub in os.listdir(odadir):
path = os.path.join(odadir, sub, "ODAFileConverter.exe")
if os.path.exists(path):
path = odadir + "/" + sub + "/" + "ODAFileConverter.exe"
if os.path.exists(path) and os.path.isfile(path):
return path
return None
def get_qcad_converter():
"""Find the QCAD converter.
It searches the FreeCAD parameters database, then searches for common
paths on Linux and Windows systems.
Parameters
----------
None
Returns
-------
str
The full path of the converter.
"""
import os
import platform
p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft")
path = p.GetString("TeighaFileConverter")
if "dwg2dwg" in path: # path set manually
pass
elif platform.system() == "Linux":
# /home/$USER/opt/qcad-3.28.1-trial-linux-qt5.14-x86_64/dwg2dwg
path = os.path.expandvars("/home/$USER/opt")
for sub in os.listdir(path):
if "qcad" in sub:
path = path + "/" + sub + "/" + "dwg2dwg"
break
elif platform.system() == "Windows":
path = os.path.expandvars("%ProgramFiles%\\QCAD\\dwg2dwg.bat").replace("\\", "/")
if os.path.exists(path) and os.path.isfile(path):
return path
return None
@@ -185,63 +267,76 @@ def convertToDxf(dwgfilename):
str
The new file produced.
"""
import os, tempfile, subprocess, sys
import os
import subprocess
import tempfile
dwgfilename = dwgfilename.replace("\\", "/")
p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft")
conv = p.GetInt("DWGConversion",0)
path = p.GetString("TeighaFileConverter","")
conv = p.GetInt("DWGConversion", 0)
error_msg = translate("draft", """Error during DWG conversion.
Try moving the DWG file to a directory path without spaces and non-english characters,
or try saving to a lower DWG version.""") + "\n"
if conv in [0,1]: # LibreDWG dxf2dwg/dwg2dxf
if not path:
path = "dwg2dxf"
if path.endswith("dxf2dwg"):
path = os.path.join(os.path.dirname,"dwg2dxf")
try:
outdir = tempfile.mkdtemp()
if conv in [0, 1]: # LibreDWG
libredwg = get_libredwg_converter("dwg2dxf")
if libredwg is not None:
outdir = tempfile.mkdtemp().replace("\\", "/")
basename = os.path.basename(dwgfilename)
result = outdir + os.sep + os.path.splitext(basename)[0] + ".dxf"
proc = subprocess.Popen((path, dwgfilename, "-o", result))
proc.communicate()
return result
except Exception:
if conv != 0:
FCC.PrintError(translate("draft", "LibreDWG error") + "\n")
if conv in [0,2]: # ODA
teigha = getTeighaConverter()
if teigha:
indir = os.path.dirname(dwgfilename)
outdir = tempfile.mkdtemp()
basename = os.path.basename(dwgfilename)
cmdline = [teigha, indir, outdir, "ACAD2000", "DXF", "0", "1", basename]
result = outdir + "/" + os.path.splitext(basename)[0] + ".dxf"
cmdline = [libredwg, dwgfilename, "-o", result]
FCC.PrintMessage(translate("draft", "Converting:") + " " + str(cmdline) + "\n")
proc = subprocess.Popen(cmdline)
proc.communicate()
result = outdir + os.sep + os.path.splitext(basename)[0] + ".dxf"
if os.path.exists(result):
FCC.PrintMessage(translate("draft", "Conversion successful") + "\n")
return result
else:
FCC.PrintError(translate("draft","""Error during DWG conversion.
Try moving the DWG file to a directory path without spaces and non-english characters,
or try saving to a lower DWG version.""") + "\n")
else:
if conv != 0:
FCC.PrintError(translate("draft", "ODA File Converter not found") + "\n")
FCC.PrintError(error_msg)
elif conv != 0:
FCC.PrintError(translate("draft", "LibreDWG converter not found") + "\n")
if conv in [0,3]: # QCAD
if not path:
path = "dwg2dwg"
try:
outdir = tempfile.mkdtemp()
if conv in [0, 2]: # ODA
oda = get_oda_converter()
if oda is not None:
indir = os.path.dirname(dwgfilename)
outdir = tempfile.mkdtemp().replace("\\", "/")
basename = os.path.basename(dwgfilename)
result = outdir + os.sep + os.path.splitext(basename)[0] + ".dxf"
proc = subprocess.Popen((path, "-f", "-o", result, dwgfilename))
cmdline = [oda, indir, outdir, "ACAD2000", "DXF", "0", "1", basename]
FCC.PrintMessage(translate("draft", "Converting:") + " " + str(cmdline) + "\n")
proc = subprocess.Popen(cmdline)
proc.communicate()
return result
except Exception:
FCC.PrintError(translate("draft", "QCAD error") + "\n")
result = outdir + "/" + os.path.splitext(basename)[0] + ".dxf"
if os.path.exists(result):
FCC.PrintMessage(translate("draft", "Conversion successful") + "\n")
return result
else:
FCC.PrintError(error_msg)
elif conv != 0:
FCC.PrintError(translate("draft", "ODA converter not found") + "\n")
if conv in [0, 3]: # QCAD
qcad = get_qcad_converter()
if qcad is not None:
outdir = tempfile.mkdtemp().replace("\\", "/")
basename = os.path.basename(dwgfilename)
result = outdir + "/" + os.path.splitext(basename)[0] + ".dxf"
cmdline = [qcad, "-f", "-o", result, dwgfilename]
FCC.PrintMessage(translate("draft", "Converting:") + " " + str(cmdline) + "\n")
proc = subprocess.Popen(cmdline, cwd=os.path.dirname(qcad)) # cwd required for Windows
proc.communicate()
if os.path.exists(result):
FCC.PrintMessage(translate("draft", "Conversion successful") + "\n")
return result
else:
FCC.PrintError(error_msg)
elif conv != 0:
FCC.PrintError(translate("draft", "QCAD converter not found") + "\n")
FCC.PrintError(translate("draft", """No suitable external DWG converter has been found.
Please set one manually under menu Edit -> Preferences -> Import/Export -> DWG
For more information see:
https://wiki.freecad.org/Import_Export_Preferences""") + "\n")
return None
@@ -262,51 +357,52 @@ def convertToDwg(dxffilename, dwgfilename):
str
The same `dwgfilename` file path.
"""
import os, subprocess, shutil
import os
import subprocess
dxffilename = dxffilename.replace("\\", "/")
dwgfilename = dwgfilename.replace("\\", "/")
p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft")
conv = p.GetInt("DWGConversion",0)
path = p.GetString("TeighaFileConverter","")
conv = p.GetInt("DWGConversion", 0)
if conv in [0,1]: # LibreDWG dxf2dwg/dwg2dxf
if not path:
path = "dxf2dwg"
if path.endswith("dwg2dxf"):
path = os.path.join(os.path.dirname,"dxf2dwg")
try:
proc = subprocess.Popen((path, dxffilename, "-y", "-o", dwgfilename))
proc.communicate()
return dwgfilename
except Exception:
if conv != 0:
FCC.PrintError(translate("draft", "LibreDWG error") + "\n")
if conv in [0,2]: # ODA
teigha = getTeighaConverter()
if teigha:
indir = os.path.dirname(dxffilename)
outdir = os.path.dirname(dwgfilename)
basename = os.path.basename(dxffilename)
cmdline = [teigha, indir, outdir, "ACAD2000", "DWG", "0", "1", basename]
if conv in [0, 1]: # LibreDWG
libredwg = get_libredwg_converter("dxf2dwg")
if libredwg is not None:
cmdline = [libredwg, dxffilename, "-y", "-o", dwgfilename]
FCC.PrintMessage(translate("draft", "Converting:") + " " + str(cmdline) + "\n")
proc = subprocess.Popen(cmdline)
proc.communicate()
return dwgfilename
else:
if conv != 0:
FCC.PrintError(translate("draft", "ODA File Converter not found") + "\n")
elif conv != 0:
FCC.PrintError(translate("draft", "LibreDWG converter not found") + "\n")
if conv in [0,3]: # QCAD
if not path:
path = "dwg2dwg"
try:
proc = subprocess.Popen((path, "-o", dwgfilename, dxffilename))
if conv in [0, 2]: # ODA
oda = get_oda_converter()
if oda is not None:
indir = os.path.dirname(dxffilename)
outdir = os.path.dirname(dwgfilename)
basename = os.path.basename(dxffilename)
cmdline = [oda, indir, outdir, "ACAD2000", "DWG", "0", "1", basename]
FCC.PrintMessage(translate("draft", "Converting:") + " " + str(cmdline) + "\n")
proc = subprocess.Popen(cmdline)
proc.communicate()
return dwgfilename
except Exception:
if conv != 0:
FCC.PrintError(translate("draft", "QCAD error") + "\n")
else:
FCC.PrintError(translate("draft", """No suitable DWG converter has been found.
Please set one manually under menu Edit -> Preferences -> Import/Export -> DWG""") + "\n")
elif conv != 0:
FCC.PrintError(translate("draft", "ODA converter not found") + "\n")
if conv in [0, 3]: # QCAD
qcad = get_qcad_converter()
if qcad is not None:
cmdline = [qcad, "-f", "-o", dwgfilename, dxffilename]
FCC.PrintMessage(translate("draft", "Converting:") + " " + str(cmdline) + "\n")
proc = subprocess.Popen(cmdline, cwd=os.path.dirname(qcad)) # cwd required for Windows
proc.communicate()
return dwgfilename
elif conv != 0:
FCC.PrintError(translate("draft", "QCAD converter not found") + "\n")
FCC.PrintError(translate("draft", """No suitable external DWG converter has been found.
Please set one manually under menu Edit -> Preferences -> Import/Export -> DWG
For more information see:
https://wiki.freecad.org/Import_Export_Preferences""") + "\n")
return None