Initial commit of the nearly completed module.

This commit is contained in:
Jeremy Wright 2014-11-21 22:19:53 -05:00
parent a6869b39cf
commit 8dbd7d5877
21 changed files with 561 additions and 0 deletions

21
CadQuery/CadQuery_rc.py Normal file
View File

@ -0,0 +1,21 @@
# -*- coding: utf-8 -*-
# Resource object code
#
# Created: Mon Nov 17 14:44:25 2014
# by: The Resource Compiler for PySide (Qt v4.8.4)
#
# WARNING! All changes made in this file will be lost!
from PySide import QtCore
qt_resource_data = "\x00\x00\x07\x19<?xml version=\x221.0\x22 encoding=\x22UTF-8\x22 standalone=\x22no\x22?>\x0a<!-- Created with Inkscape (http://www.inkscape.org/) -->\x0a\x0a<svg\x0a xmlns:dc=\x22http://purl.org/dc/elements/1.1/\x22\x0a xmlns:cc=\x22http://creativecommons.org/ns#\x22\x0a xmlns:rdf=\x22http://www.w3.org/1999/02/22-rdf-syntax-ns#\x22\x0a xmlns:svg=\x22http://www.w3.org/2000/svg\x22\x0a xmlns=\x22http://www.w3.org/2000/svg\x22\x0a version=\x221.1\x22\x0a width=\x2250\x22\x0a height=\x2250\x22\x0a id=\x22svg2\x22>\x0a <defs\x0a id=\x22defs4\x22 />\x0a <metadata\x0a id=\x22metadata7\x22>\x0a <rdf:RDF>\x0a <cc:Work\x0a rdf:about=\x22\x22>\x0a <dc:format>image/svg+xml</dc:format>\x0a <dc:type\x0a rdf:resource=\x22http://purl.org/dc/dcmitype/StillImage\x22 />\x0a <dc:title></dc:title>\x0a </cc:Work>\x0a </rdf:RDF>\x0a </metadata>\x0a <g\x0a transform=\x22translate(0,-1002.3622)\x22\x0a id=\x22layer1\x22>\x0a <g\x0a transform=\x22matrix(1.1284014,0,0,1.1284014,-2.215934,-134.03857)\x22\x0a id=\x22g3946\x22>\x0a <text\x0a x=\x2217.912706\x22\x0a y=\x221039.6519\x22\x0a id=\x22text3906\x22\x0a xml:space=\x22preserve\x22\x0a style=\x22font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#ff6600;fill-opacity:1;stroke:none;font-family:Sans\x22><tspan\x0a x=\x2217.912706\x22\x0a y=\x221039.6519\x22\x0a id=\x22tspan3908\x22\x0a style=\x22font-size:36px;fill:#ff6600;fill-opacity:1\x22>Q</tspan></text>\x0a <text\x0a x=\x221.9388669\x22\x0a y=\x221039.6519\x22\x0a id=\x22text3134\x22\x0a xml:space=\x22preserve\x22\x0a style=\x22font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#345480;fill-opacity:1;stroke:none;font-family:Sans\x22><tspan\x0a x=\x221.9388669\x22\x0a y=\x221039.6519\x22\x0a id=\x22tspan3136\x22\x0a style=\x22font-size:36px;fill:#345480;fill-opacity:1\x22>C</tspan></text>\x0a </g>\x0a </g>\x0a</svg>\x0a"
qt_resource_name = "\x00\x05\x00o\xa6S\x00i\x00c\x00o\x00n\x00s\x00\x0b\x05r\xb2\xa7\x00C\x00Q\x00_\x00L\x00o\x00g\x00o\x00.\x00s\x00v\x00g"
qt_resource_struct = "\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x10\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00"
def qInitResources():
QtCore.qRegisterResourceData(0x01, qt_resource_struct, qt_resource_name, qt_resource_data)
def qCleanupResources():
QtCore.qUnregisterResourceData(0x01, qt_resource_struct, qt_resource_name, qt_resource_data)
qInitResources()

BIN
CadQuery/CadQuery_rc.pyc Normal file

Binary file not shown.

View File

@ -0,0 +1,3 @@
class CadQueryGui():
def __workbench__(self):
pass

Binary file not shown.

188
CadQuery/Gui/Command.py Normal file
View File

@ -0,0 +1,188 @@
import tempfile
import FreeCAD, FreeCADGui
from PySide import QtGui
import ExportCQ, ImportCQ, CadQuery_rc
#Distinguish python built-in open function from the one declared here
if open.__module__ == '__builtin__':
pythonopen = open
def clearAll():
doc = FreeCAD.ActiveDocument
#Make sure we have an active document to work with
if doc is not None:
for obj in doc.Objects:
doc.removeObject(obj.Label)
class CadQueryCloseScript:
"""Allows the user to close a file without saving"""
def GetResources(self):
return {"MenuText": "Close Script",
"ToolTip": "Closes the CadQuery script"}
def IsActive(self):
return True
def Activated(self):
#Getting the main window will allow us to find the children we need to work with
mw = FreeCADGui.getMainWindow()
#We need this so we can load the file into it
cqCodePane = mw.findChild(QtGui.QPlainTextEdit, "cqCodePane")
reply = QtGui.QMessageBox.question(cqCodePane, "QMessageBox.question()", "Save script before closing?", QtGui.QMessageBox.Yes |
QtGui.QMessageBox.No | QtGui.QMessageBox.Cancel)
if reply == QtGui.QMessageBox.Cancel:
return
if reply == QtGui.QMessageBox.Yes:
#If we've got a file name already save it there, otherwise give a save-as dialog
if len(cqCodePane.file.path) == 0:
filename = QtGui.QFileDialog.getSaveFileName(mw, mw.tr("Save CadQuery Script As"), "/home/",
mw.tr("CadQuery Files (*.py)"))
else:
filename = cqCodePane.file.path
#Make sure we got a valid file name
if filename == None:
ExportCQ.save(filename)
#Clear our script and whatever was rendered by it out
cqCodePane.file.close()
clearAll()
class CadQueryExecuteScript:
"""CadQuery's command to execute a script file"""
def GetResources(self):
return {"MenuText": "Execute Script",
"Accel": "F2",
"ToolTip": "Executes the CadQuery script",
"Pixmap": ":/icons/macro-execute.svg"}
def IsActive(self):
return True
# if FreeCAD.ActiveDocument is None:
# return False
# else:
# return True
def Activated(self):
#Getting the main window will allow us to find the children we need to work with
mw = FreeCADGui.getMainWindow()
#We need this so we can load the file into it
cqCodePane = mw.findChild(QtGui.QPlainTextEdit, "cqCodePane")
clearAll()
#Save our code to a tempfile and render it
tempFile = tempfile.NamedTemporaryFile(delete=False)
tempFile.write(cqCodePane.toPlainText())
tempFile.close()
FreeCAD.Console.PrintMessage("\r\n")
execfile(tempFile.name)
msg = QtGui.QApplication.translate(
"cqCodeWidget",
"Executed ",
None,
QtGui.QApplication.UnicodeUTF8)
FreeCAD.Console.PrintMessage("\r\n" + msg + cqCodePane.file.path)
class CadQueryOpenScript():
"""CadQuery's command to open a script file."""
previousPath = None
def GetResources(self):
return {"MenuText": "Open Script",
"Accel": "Alt+O",
"ToolTip": "Opens a CadQuery script from disk",
"Pixmap": ":/icons/document-open.svg"}
def IsActive(self):
return True
# if FreeCAD.ActiveDocument is None:
# return False
# else:
# return True
def Activated(self):
mw = FreeCADGui.getMainWindow()
#Try to keep track of the previous path used to open as a convenience to the user
if self.previousPath is None:
self.previousPath = "/home/"
filename = QtGui.QFileDialog.getOpenFileName(mw, mw.tr("Open CadQuery Script"), self.previousPath,
mw.tr("CadQuery Files (*.py)"))
self.previousPath = filename[0]
#Make sure the user didn't click cancel
if filename[0]:
#We've created a library that FreeCAD can use as well to open CQ files
ImportCQ.open(filename[0])
class CadQuerySaveScript:
"""CadQuery's command to save a script file"""
def GetResources(self):
return {"MenuText": "Save Script",
"Accel": "Alt+S",
"ToolTip": "Saves the CadQuery script to disk",
"Pixmap": ":/icons/document-save.svg"}
def IsActive(self):
return True
# if FreeCAD.ActiveDocument is None:
# return False
# else:
# return True
def Activated(self):
#Rely on our export library to help us save the file
ExportCQ.save()
class CadQuerySaveAsScript:
"""CadQuery's command to save-as a script file"""
previousPath = None
def GetResources(self):
return {"MenuText": "Save Script As",
"Accel": "",
"ToolTip": "Saves the CadQuery script to disk in a location other than the original",
"Pixmap": ":/icons/document-save-as.svg"}
def IsActive(self):
return True
# if FreeCAD.ActiveDocument is None:
# return False
# else:
# return True
def Activated(self):
mw = FreeCADGui.getMainWindow()
#Try to keep track of the previous path used to open as a convenience to the user
if self.previousPath is None:
self.previousPath = "/home/"
filename = QtGui.QFileDialog.getSaveFileName(mw, mw.tr("Save CadQuery Script As"), self.previousPath,
mw.tr("CadQuery Files (*.py)"))
self.previousPath = filename[0]
#Make sure the user didn't click cancel
if filename[0]:
#Save the file before the re-render
ExportCQ.save(filename[0])
execfile(filename[0])

BIN
CadQuery/Gui/Command.pyc Normal file

Binary file not shown.

30
CadQuery/Gui/ExportCQ.py Normal file
View File

@ -0,0 +1,30 @@
import FreeCAD, FreeCADGui
from PySide import QtGui
def export(self, filename):
save(filename)
def save(filename=None):
"""
Allows us to save the CQ script file to disk.
:param filename: The path and file name to save to. If not provided we try to pull it from the code pane itself
"""
#Getting the main window will allow us to find the children we need to work with
mw = FreeCADGui.getMainWindow()
#We need this so we can load the file into it
cqCodePane = mw.findChild(QtGui.QPlainTextEdit, "cqCodePane")
#If we weren't provided a file name, we need to find it from the text field
if filename is None:
cqCodePane.file.save()
else:
cqCodePane.file.save(filename)
msg = QtGui.QApplication.translate(
"cqCodeWidget",
"Saved ",
None,
QtGui.QApplication.UnicodeUTF8)
FreeCAD.Console.PrintMessage("\r\n" + msg + cqCodePane.file.path)

BIN
CadQuery/Gui/ExportCQ.pyc Normal file

Binary file not shown.

33
CadQuery/Gui/ImportCQ.py Normal file
View File

@ -0,0 +1,33 @@
import os, FreeCAD, FreeCADGui
from PySide import QtGui
#Distinguish python built-in open function from the one declared here
if open.__module__ == '__builtin__':
pythonopen = open
def open(filename):
docname = os.path.splitext(os.path.basename(filename))[0]
doc = FreeCAD.newDocument(docname)
#All of the Gui.* calls in the Python console break after opening if we don't do this
FreeCADGui.doCommand("import FreeCADGui as Gui")
#Getting the main window will allow us to find the children we need to work with
mw = FreeCADGui.getMainWindow()
#We need this so we can load the file into it
cqCodePane = mw.findChild(QtGui.QPlainTextEdit, "cqCodePane")
#Pull the text of the CQ script file into our code pane
cqCodePane.file.open(filename)
execfile(filename)
msg = QtGui.QApplication.translate(
"cqCodeWidget",
"Opened ",
None,
QtGui.QApplication.UnicodeUTF8)
FreeCAD.Console.PrintMessage("\r\n" + msg + filename)
return doc

BIN
CadQuery/Gui/ImportCQ.pyc Normal file

Binary file not shown.

View File

@ -0,0 +1,5 @@
<RCC>
<qresource>
<file>icons/CQ_Logo.svg</file>
</qresource>
</RCC>

View File

@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
version="1.1"
width="50"
height="50"
id="svg2">
<defs
id="defs4" />
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
transform="translate(0,-1002.3622)"
id="layer1">
<g
transform="matrix(1.1284014,0,0,1.1284014,-2.215934,-134.03857)"
id="g3946">
<text
x="17.912706"
y="1039.6519"
id="text3906"
xml:space="preserve"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#ff6600;fill-opacity:1;stroke:none;font-family:Sans"><tspan
x="17.912706"
y="1039.6519"
id="tspan3908"
style="font-size:36px;fill:#ff6600;fill-opacity:1">Q</tspan></text>
<text
x="1.9388669"
y="1039.6519"
id="text3134"
xml:space="preserve"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#345480;fill-opacity:1;stroke:none;font-family:Sans"><tspan
x="1.9388669"
y="1039.6519"
id="tspan3136"
style="font-size:36px;fill:#345480;fill-opacity:1">C</tspan></text>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -0,0 +1,82 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="48"
height="48"
id="svg2"
version="1.1"
inkscape:version="0.48.4 r9939"
sodipodi:docname="CQ_Logo.svg">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="4.6418845"
inkscape:cx="26.73475"
inkscape:cy="17.442118"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="927"
inkscape:window-height="1028"
inkscape:window-x="992"
inkscape:window-y="24"
inkscape:window-maximized="0"
inkscape:showpageshadow="false" />
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1004.3622)">
<flowRoot
xml:space="preserve"
id="flowRoot2993"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
transform="matrix(0.26712119,0,0,0.26712119,-16.01485,841.24907)"><flowRegion
id="flowRegion2995"><rect
id="rect2997"
width="168.57144"
height="208.57147"
x="131.42857"
y="589.50507" /></flowRegion><flowPara
id="flowPara2999"
style="font-size:144px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#345480;fill-opacity:1;font-family:Ubuntu;-inkscape-font-specification:Ubuntu">Q</flowPara></flowRoot> <flowRoot
xml:space="preserve"
id="flowRoot2985"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#ff6600;fill-opacity:1;stroke:none;font-family:Sans"
transform="matrix(0.26712119,0,0,0.26712119,-43.871776,919.85783)"><flowRegion
id="flowRegion2987"><rect
id="rect2989"
width="134.28568"
height="185.71429"
x="160"
y="295.21933"
style="fill:#ff6600;fill-opacity:1" /></flowRegion><flowPara
id="flowPara2991"
style="font-size:144px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#ff6600;fill-opacity:1;font-family:Ubuntu;-inkscape-font-specification:Ubuntu">C</flowPara></flowRoot> </g>
</svg>

After

Width:  |  Height:  |  Size: 3.1 KiB

1
CadQuery/Gui/__init__.py Normal file
View File

@ -0,0 +1 @@
__author__ = 'jwright'

BIN
CadQuery/Gui/__init__.pyc Normal file

Binary file not shown.

2
CadQuery/Init.py Normal file
View File

@ -0,0 +1,2 @@
# FreeCAD init script of the CadQuery module
# (c) 2001 Juergen Riegel LGPL

BIN
CadQuery/Init.pyc Normal file

Binary file not shown.

139
CadQuery/InitGui.py Normal file
View File

@ -0,0 +1,139 @@
# CadQuery gui init module
# (c) 2001 Juergen Riegel LGPL
import FreeCAD
import FreeCADGui
from Gui.Command import *
class CadQueryWorkbench (Workbench):
"""CadQuery workbench object"""
MenuText = "CadQuery"
ToolTip = "CadQuery workbench"
Icon = ":/icons/CQ_Logo.svg"
#Keeps track of which workbenches we have hidden so we can reshow them
closedWidgets = []
def Initialize(self):
import os
os.environ['QT_API'] = 'pyside'
#If we need a CQ menu, this would be the way to add it
commands = ['CadQueryOpenScript', 'CadQuerySaveScript', 'CadQuerySaveAsScript', 'CadQueryExecuteScript',
'CadQueryCloseScript']
self.appendMenu('CadQuery', commands)
def Activated(self):
import cadquery
from PySide import QtGui
import sys
msg = QtGui.QApplication.translate(
"cqCodeWidget",
"CadQuery " + cadquery.__version__ + "\r\n"
"CadQuery is a parametric scripting language "
"for creating and traversing CAD models\r\n"
"Author: David Cowden\r\n"
"License: LGPL\r\n"
"Website: https://github.com/dcowden/cadquery\r\n",
None,
QtGui.QApplication.UnicodeUTF8)
FreeCAD.Console.PrintMessage(msg)
from PySide import QtGui
from PySide import QtCore
FreeCAD.addImportType("CadQuery Script (*.py)", "Gui.ImportCQ")
FreeCAD.addExportType("CadQuery Script (*.py)", "Gui.ExportCQ")
try:
import cadquery
except ImportError:
msg = QtGui.QApplication.translate(
"cqCodeWidget",
"The cadquery library is not installed, please install it before using this workbench.\r\n"
"Linux and MacOS Users: 'pip install --upgrade cadquery'\r\n"
"Windows Users: 'Not sure yet.\r\n",
None,
QtGui.QApplication.UnicodeUTF8)
FreeCAD.Console.PrintError(msg)
try:
from pyqode.qt import QtWidgets
from pyqode.python.backend import server
from pyqode.python.widgets import PyCodeEdit
from pyqode.python.widgets import code_edit
except ImportError:
msg = QtGui.QApplication.translate(
"cqCodeWidget",
"The pyQode library is not installed, please install it before using this workbench.\r\n"
"Linux and MacOS Users: 'pip install --upgrade pyqode.core pyqode.qt pyqode.python'\r\n",
None,
QtGui.QApplication.UnicodeUTF8)
FreeCAD.Console.PrintError(msg)
#Make sure that we enforce a specific version (2.7) of the Python interpreter
ver = hex(sys.hexversion)
interpreter = "python%s.%s" % (ver[2], ver[4]) # => 'python2.7'
#If the user doesn't have Python 2.7, warn them
if interpreter != 'python2.7':
msg = QtGui.QApplication.translate(
"cqCodeWidget",
"Please install Python 2.7",
None,
QtGui.QApplication.UnicodeUTF8)
FreeCAD.Console.PrintError("\r\n" + msg)
#Getting the main window will allow us to start setting things up the way we want
mw = Gui.getMainWindow()
#Find all of the docks that are open so we can close them (except the Python console)
dockWidgets = mw.findChildren(QtGui.QDockWidget)
for widget in dockWidgets:
if widget.objectName() != "Report view":
#FreeCAD.Console.PrintMessage(str(widget.objectName()) + " is being hidden.\n")
#Only hide the widget if it isn't already hidden
if not widget.isHidden():
widget.setVisible(False)
FreeCAD.Console.PrintMessage(widget.objectName())
self.closedWidgets.append(widget)
else:
widget.setVisible(True)
#Add a new widget here that's a simple text area to begin with. It will become the CQ coding area
cqCodeWidget = QtGui.QDockWidget("CadQuery Code View")
cqCodeWidget.setObjectName("cqCodeView")
mw.addDockWidget(QtCore.Qt.LeftDockWidgetArea, cqCodeWidget)
#Set up the text area for our CQ code
codePane = PyCodeEdit(server_script=server.__file__, interpreter=interpreter)
codePane.setObjectName("cqCodePane")
#Add the text area to our dock widget
cqCodeWidget.setWidget(codePane)
def Deactivated(self):
from PySide import QtGui
from Gui import ExportCQ
#Put the UI back the way we found it
FreeCAD.Console.PrintMessage("\r\nCadQuery Workbench Deactivated\r\n")
#Rely on our export library to help us save the file
ExportCQ.save()
#TODO: This won't work for now because the views are destroyed when they are hidden
for widget in self.closedWidgets:
FreeCAD.Console.PrintMessage(widget.objectName())
#widget.setVisible(True)
FreeCADGui.addCommand('CadQueryOpenScript', CadQueryOpenScript())
FreeCADGui.addCommand('CadQuerySaveScript', CadQuerySaveScript())
FreeCADGui.addCommand('CadQuerySaveAsScript', CadQuerySaveAsScript())
FreeCADGui.addCommand('CadQueryExecuteScript', CadQueryExecuteScript())
FreeCADGui.addCommand('CadQueryCloseScript', CadQueryCloseScript())
FreeCADGui.addWorkbench(CadQueryWorkbench())

BIN
CadQuery/InitGui.pyc Normal file

Binary file not shown.

1
CadQuery/__init__.py Normal file
View File

@ -0,0 +1 @@
__author__ = 'jwright'

BIN
CadQuery/__init__.pyc Normal file

Binary file not shown.