Tool Library replaces ToolTable Job replaces Project

This commit is contained in:
sliptonic
2016-06-27 09:19:15 -05:00
committed by Yorik van Havre
parent 0bca05a5f2
commit cddccdf4c7
50 changed files with 4103 additions and 1532 deletions

View File

@@ -37,8 +37,7 @@ SET(PathScripts_SRCS
PathScripts/PathFixture.py
PathScripts/PathCopy.py
PathScripts/PathCompoundExtended.py
PathScripts/PathProject.py
PathScripts/PathToolTableEdit.py
PathScripts/PathJob.py
PathScripts/PathStock.py
PathScripts/PathPlane.py
PathScripts/PathPost.py
@@ -46,7 +45,6 @@ SET(PathScripts_SRCS
PathScripts/PathToolLenOffset.py
PathScripts/PathComment.py
PathScripts/PathStop.py
PathScripts/PathMachine.py
PathScripts/PathFromShape.py
PathScripts/DlgSettingsPath.ui
PathScripts/PathKurveUtils.py
@@ -62,7 +60,7 @@ SET(PathScripts_SRCS
PathScripts/PathSurface.py
PathScripts/PathRemote.py
PathScripts/PathSanity.py
PathScripts/PathToolLibraryManager.py
)
SET(PathScripts_NC_SRCS

View File

@@ -0,0 +1,70 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>DlgJobChooser</class>
<widget class="QDialog" name="DlgJobChooser">
<property name="windowModality">
<enum>Qt::WindowModal</enum>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>264</width>
<height>92</height>
</rect>
</property>
<property name="windowTitle">
<string>Choose a Path Job</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QComboBox" name="cboProject"/>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>DlgJobChooser</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>DlgJobChooser</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@@ -7,7 +7,7 @@
<file>icons/Path-Profile.svg</file>
<file>icons/Path-Pocket.svg</file>
<file>icons/Path-Drilling.svg</file>
<file>icons/Path-Project.svg</file>
<file>icons/Path-Job.svg</file>
<file>icons/Path-Dressup.svg</file>
<file>icons/Path-Hop.svg</file>
<file>icons/Path-Datums.svg</file>
@@ -74,5 +74,10 @@
<file>panels/SurfaceEdit.ui</file>
<file>panels/RemoteEdit.ui</file>
<file>panels/ToolControl.ui</file>
<file>panels/ToolLibraryEditor.ui</file>
<file>panels/JobEdit.ui</file>
<file>panels/DlgToolCopy.ui</file>
<file>panels/ToolEdit.ui</file>
<file>panels/DlgJobChooser.ui</file>
</qresource>
</RCC>

View File

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 40 KiB

View File

@@ -0,0 +1,70 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>DlgJobChooser</class>
<widget class="QDialog" name="DlgJobChooser">
<property name="windowModality">
<enum>Qt::WindowModal</enum>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>264</width>
<height>92</height>
</rect>
</property>
<property name="windowTitle">
<string>Choose a Path Job</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QComboBox" name="cboProject"/>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>DlgJobChooser</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>DlgJobChooser</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@@ -0,0 +1,93 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>DlgJobChooser</class>
<widget class="QDialog" name="DlgJobChooser">
<property name="windowModality">
<enum>Qt::WindowModal</enum>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>367</width>
<height>119</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string>Copy Selected Tools</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Destination</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="cboTarget"/>
</item>
<item>
<widget class="QCheckBox" name="chkMakeController">
<property name="text">
<string>Create Tool Controllers</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>DlgJobChooser</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>DlgJobChooser</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@@ -106,6 +106,30 @@
</item>
</layout>
</widget>
<widget class="QWidget" name="Tool">
<attribute name="icon">
<iconset resource="../Path.qrc">
<normaloff>:/icons/Path-LoadTool.svg</normaloff>:/icons/Path-LoadTool.svg</iconset>
</attribute>
<attribute name="label">
<string>Tool Settings</string>
</attribute>
<widget class="QWidget" name="widget" native="true">
<property name="geometry">
<rect>
<x>0</x>
<y>10</y>
<width>301</width>
<height>41</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<item row="0" column="0">
<widget class="QComboBox" name="cboToolController"/>
</item>
</layout>
</widget>
</widget>
<widget class="QWidget" name="Depths">
<property name="geometry">
<rect>

View File

@@ -0,0 +1,298 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>frmCNCJob</class>
<widget class="QWidget" name="frmCNCJob">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>398</width>
<height>534</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>533</height>
</size>
</property>
<property name="windowTitle">
<string>CNC Job</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="1">
<widget class="QToolBox" name="toolBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="General">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>380</width>
<height>426</height>
</rect>
</property>
<attribute name="icon">
<iconset resource="../Path.qrc">
<normaloff>:/icons/Path-OperationB.svg</normaloff>:/icons/Path-OperationB.svg</iconset>
</attribute>
<attribute name="label">
<string>General</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_4">
<item row="0" column="0">
<widget class="QWidget" name="widget_2" native="true">
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Job Type</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="label_6">
<property name="text">
<string>label</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QComboBox" name="cboJobType">
<item>
<property name="text">
<string>Milling</string>
</property>
</item>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="leLabel"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Base Object</string>
</property>
</widget>
</item>
<item row="4" column="0" colspan="2">
<widget class="QCheckBox" name="chkCreateClone">
<property name="text">
<string>Create Linked Clone</string>
</property>
</widget>
</item>
<item row="5" column="0" colspan="2">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Reorder operations by dragging them to their correct location</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="6" column="0" colspan="2">
<widget class="QListWidget" name="PathsList">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="dragEnabled">
<bool>true</bool>
</property>
<property name="dragDropMode">
<enum>QAbstractItemView::InternalMove</enum>
</property>
<property name="defaultDropAction">
<enum>Qt::MoveAction</enum>
</property>
</widget>
</item>
<item row="3" column="0" colspan="2">
<widget class="QComboBox" name="cboBaseObject"/>
</item>
</layout>
</widget>
</item>
<item row="1" column="0">
<widget class="QWidget" name="widget" native="true">
<layout class="QGridLayout" name="gridLayout_2"/>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="Stock">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>380</width>
<height>426</height>
</rect>
</property>
<attribute name="icon">
<iconset resource="../Path.qrc">
<normaloff>:/icons/Path-Stock.svg</normaloff>:/icons/Path-Stock.svg</iconset>
</attribute>
<attribute name="label">
<string>Stock</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_5">
<item row="0" column="0">
<widget class="QWidget" name="widget_3" native="true">
<layout class="QGridLayout" name="gridLayout_3">
<item row="0" column="0">
<widget class="QCheckBox" name="chkUseBoundingBox">
<property name="text">
<string>Use Part Bounding Box</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QComboBox" name="cboStockSource">
<property name="enabled">
<bool>false</bool>
</property>
<item>
<property name="text">
<string>Create from Part Bounding Box</string>
</property>
</item>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Material</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QComboBox" name="cboMaterial"/>
</item>
</layout>
</widget>
</item>
<item row="1" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<widget class="QWidget" name="PostProcessing">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>380</width>
<height>426</height>
</rect>
</property>
<attribute name="icon">
<iconset resource="../Path.qrc">
<normaloff>:/icons/Path-Post.svg</normaloff>:/icons/Path-Post.svg</iconset>
</attribute>
<attribute name="label">
<string>Post Processing</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QWidget" name="widget_4" native="true">
<layout class="QGridLayout" name="gridLayout_6">
<item row="0" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Output File</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLineEdit" name="leOutputFile">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QPushButton" name="btnSelectFile">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>...</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QLabel" name="label_7">
<property name="text">
<string>Post Processor</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="cboPostProcessor"/>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>13</width>
<height>290</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<resources>
<include location="../Path.qrc"/>
</resources>
<connections/>
</ui>

View File

@@ -15,7 +15,11 @@
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QLineEdit" name="tcoName"/>
<widget class="QLineEdit" name="tcoName">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QFrame" name="frame_2">
@@ -26,22 +30,8 @@
<enum>QFrame::Raised</enum>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="2" column="0">
<widget class="QLabel" name="txtToolType">
<property name="text">
<string>Unknown</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="txtToolName">
<property name="text">
<string>Unknown</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="txtToolMaterial">
<widget class="QLabel" name="txtToolDiameter">
<property name="text">
<string>Unknown</string>
</property>
@@ -50,8 +40,15 @@
<item row="0" column="0">
<widget class="QComboBox" name="cboToolSelect"/>
</item>
<item row="4" column="0">
<widget class="QLabel" name="txtToolDiameter">
<item row="1" column="0">
<widget class="QLabel" name="txtToolType">
<property name="text">
<string>Unknown</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="txtToolMaterial">
<property name="text">
<string>Unknown</string>
</property>
@@ -109,7 +106,11 @@
</widget>
</item>
<item row="1" column="0">
<widget class="QSpinBox" name="spindleSpeed"/>
<widget class="QSpinBox" name="spindleSpeed">
<property name="maximum">
<number>99999</number>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="cboSpindleDirection">

View File

@@ -0,0 +1,287 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Dialog</class>
<widget class="QDialog" name="Dialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>423</width>
<height>435</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>Tool Properties</string>
</property>
<layout class="QFormLayout" name="formLayout">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
</property>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Name</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="NameField"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Type</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="TypeField">
<item>
<property name="text">
<string>Drill</string>
</property>
</item>
<item>
<property name="text">
<string>CenterDrill</string>
</property>
</item>
<item>
<property name="text">
<string>CounterSink</string>
</property>
</item>
<item>
<property name="text">
<string>CounterBore</string>
</property>
</item>
<item>
<property name="text">
<string>Reamer</string>
</property>
</item>
<item>
<property name="text">
<string>Tap</string>
</property>
</item>
<item>
<property name="text">
<string>EndMill</string>
</property>
</item>
<item>
<property name="text">
<string>SlotCutter</string>
</property>
</item>
<item>
<property name="text">
<string>BallEndMill</string>
</property>
</item>
<item>
<property name="text">
<string>ChamferMill</string>
</property>
</item>
<item>
<property name="text">
<string>CornerRound</string>
</property>
</item>
<item>
<property name="text">
<string>Engraver</string>
</property>
</item>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Material</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QComboBox" name="MaterialField">
<item>
<property name="text">
<string>HighSpeedSteel</string>
</property>
</item>
<item>
<property name="text">
<string>HighCarbonSteel</string>
</property>
</item>
<item>
<property name="text">
<string>CastAlloy</string>
</property>
</item>
<item>
<property name="text">
<string>Carbide</string>
</property>
</item>
<item>
<property name="text">
<string>Ceramics</string>
</property>
</item>
<item>
<property name="text">
<string>Diamond</string>
</property>
</item>
<item>
<property name="text">
<string>Sialon</string>
</property>
</item>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Diameter</string>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QDoubleSpinBox" name="DiameterField">
<property name="suffix">
<string>mm</string>
</property>
</widget>
</item>
<item row="8" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Length Offset</string>
</property>
</widget>
</item>
<item row="8" column="1">
<widget class="QDoubleSpinBox" name="LengthOffsetField">
<property name="suffix">
<string>mm</string>
</property>
</widget>
</item>
<item row="12" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Flat Radius</string>
</property>
</widget>
</item>
<item row="12" column="1">
<widget class="QDoubleSpinBox" name="FlatRadiusField">
<property name="suffix">
<string>mm</string>
</property>
</widget>
</item>
<item row="14" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Corner Radius</string>
</property>
</widget>
</item>
<item row="14" column="1">
<widget class="QDoubleSpinBox" name="CornerRadiusField">
<property name="suffix">
<string>mm</string>
</property>
</widget>
</item>
<item row="16" column="0">
<widget class="QLabel" name="label_9">
<property name="text">
<string>Cutting Edge Angle</string>
</property>
</widget>
</item>
<item row="16" column="1">
<widget class="QDoubleSpinBox" name="CuttingEdgeAngleField">
<property name="suffix">
<string>°</string>
</property>
</widget>
</item>
<item row="18" column="0">
<widget class="QLabel" name="label_8">
<property name="text">
<string>Cutting Edge Height</string>
</property>
</widget>
</item>
<item row="18" column="1">
<widget class="QDoubleSpinBox" name="CuttingEdgeHeightField">
<property name="suffix">
<string>mm</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>Dialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>Dialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@@ -0,0 +1,207 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Dialog</class>
<widget class="QDialog" name="Dialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>946</width>
<height>614</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="1">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
<item row="0" column="0" colspan="2">
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Tool Library</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="5">
<widget class="QPushButton" name="ButtonImport">
<property name="text">
<string>Import...</string>
</property>
</widget>
</item>
<item row="4" column="6">
<widget class="QPushButton" name="ButtonDown">
<property name="text">
<string>Move down</string>
</property>
<property name="icon">
<iconset resource="../../../../../Gui/Icons/resource.qrc">
<normaloff>:/icons/button_down.svg</normaloff>:/icons/button_down.svg</iconset>
</property>
</widget>
</item>
<item row="4" column="5">
<widget class="QPushButton" name="ButtonUp">
<property name="text">
<string>Move up</string>
</property>
<property name="icon">
<iconset resource="../../../../../Gui/Icons/resource.qrc">
<normaloff>:/icons/button_up.svg</normaloff>:/icons/button_up.svg</iconset>
</property>
<property name="checkable">
<bool>false</bool>
</property>
<property name="default">
<bool>false</bool>
</property>
<property name="flat">
<bool>false</bool>
</property>
</widget>
</item>
<item row="3" column="3" colspan="4">
<widget class="QTableView" name="ToolsList">
<property name="dragEnabled">
<bool>true</bool>
</property>
<property name="dragDropMode">
<enum>QAbstractItemView::DragOnly</enum>
</property>
<property name="alternatingRowColors">
<bool>true</bool>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::SingleSelection</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
<property name="cornerButtonEnabled">
<bool>false</bool>
</property>
<attribute name="verticalHeaderVisible">
<bool>false</bool>
</attribute>
</widget>
</item>
<item row="0" column="6">
<widget class="QPushButton" name="ButtonExport">
<property name="text">
<string>Export...</string>
</property>
</widget>
</item>
<item row="4" column="4">
<widget class="QPushButton" name="ButtonDelete">
<property name="text">
<string>Delete</string>
</property>
<property name="icon">
<iconset resource="../../../../../Gui/Icons/resource.qrc">
<normaloff>:/icons/delete.svg</normaloff>:/icons/delete.svg</iconset>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QListView" name="listView">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="acceptDrops">
<bool>true</bool>
</property>
<property name="dragEnabled">
<bool>true</bool>
</property>
<property name="dragDropMode">
<enum>QAbstractItemView::DropOnly</enum>
</property>
</widget>
</item>
<item row="4" column="3">
<widget class="QPushButton" name="ButtonNewTool">
<property name="text">
<string>New Tool</string>
</property>
<property name="icon">
<iconset resource="../Path.qrc">
<normaloff>:/icons/Path-LoadTool.svg</normaloff>:/icons/Path-LoadTool.svg</iconset>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QPushButton" name="btnCopyTools">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Copy checked tools to another library</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../../../../Gui/Icons/resource.qrc">
<normaloff>:/icons/button_left.svg</normaloff>:/icons/button_left.svg</iconset>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<resources>
<include location="../../../../../Gui/Icons/resource.qrc"/>
<include location="../Path.qrc"/>
</resources>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>Dialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>Dialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>285</width>
<height>385</height>
<width>315</width>
<height>404</height>
</rect>
</property>
<property name="windowTitle">

View File

@@ -46,8 +46,8 @@ class PathWorkbench (Workbench):
from PathScripts import PathCopy
from PathScripts import PathFixture
from PathScripts import PathCompoundExtended
from PathScripts import PathProject
from PathScripts import PathToolTableEdit
from PathScripts import PathJob
from PathScripts import PathToolLibraryManager
from PathScripts import PathStock
from PathScripts import PathPlane
from PathScripts import PathPost
@@ -55,7 +55,6 @@ class PathWorkbench (Workbench):
from PathScripts import PathLoadTool
from PathScripts import PathComment
from PathScripts import PathStop
from PathScripts import PathMachine
from PathScripts import PathFromShape
from PathScripts import PathArray
from PathScripts import PathFaceProfile
@@ -70,15 +69,15 @@ class PathWorkbench (Workbench):
from PathScripts import DragknifeDressup
# build commands list
projcmdlist = ["Path_Project", "Path_Post", "Path_Inspect", "Path_Sanity"]
#toolcmdlist = ["Path_ToolTableEdit", "Path_ToolLibraryEdit", "Path_LoadTool"]
toolcmdlist = ["Path_ToolTableEdit", "Path_LoadTool"]
projcmdlist = ["Path_Job", "Path_Post", "Path_Inspect", "Path_Sanity"]
toolcmdlist = ["Path_ToolLibraryEdit", "Path_LoadTool"]
prepcmdlist = ["Path_Plane", "Path_Fixture", "Path_ToolLenOffset", "Path_Comment",
"Path_Stop", "Path_FaceProfile", "Path_FacePocket", "Path_Custom", "Path_FromShape"]
opcmdlist = ["Path_Profile", "Path_Pocket",
"Path_Drilling", "Path_Engrave", "Path_Surfacing"]
modcmdlist = ["Path_Copy", "Path_CompoundExtended",
"Path_Dressup", "Path_Hop", "Path_Array", "Path_SimpleCopy", "DragKnife_Dressup"]
modcmdlist = ["Path_Copy", "Path_CompoundExtended", "Path_Array",
"Path_SimpleCopy" ]
modcmdmore = ["Path_Dressup", "Path_Hop", "DragKnife_Dressup"]
remotecmdlist = ["Path_Remote"]
# Add commands to menu and toolbar
@@ -96,13 +95,15 @@ class PathWorkbench (Workbench):
self.appendMenu([translate("Path", "Path"), translate(
"Path", "Project Tools")], projcmdlist)
self.appendMenu([translate("Path", "Path"), translate(
"Path", "Tools")], projcmdlist)
"Path", "Tools")], toolcmdlist)
self.appendMenu([translate("Path", "Path"), translate(
"Path", "Partial Commands")], prepcmdlist)
self.appendMenu([translate("Path", "Path"), translate(
"Path", "New Operations")], opcmdlist)
self.appendMenu([translate("Path", "Path"), translate(
"Path", "Path Modification")], modcmdlist)
self.appendMenu([translate("Path", "Path"), translate(
"Path", "Path Modification")], modcmdmore)
self.appendMenu([translate("Path", "Path"), translate(
"Path", "Remote Operations")], remotecmdlist)

View File

@@ -0,0 +1,145 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Dialog</class>
<widget class="QDialog" name="Dialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>946</width>
<height>614</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="1">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCommandLinkButton" name="cmdAddTools">
<property name="text">
<string>Add Selected Tools to Project</string>
</property>
</widget>
</item>
<item row="0" column="0" colspan="2">
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Tool Library</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="4" column="2">
<widget class="QPushButton" name="ButtonDelete">
<property name="text">
<string>Delete</string>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QPushButton" name="ButtonImport">
<property name="text">
<string>Import...</string>
</property>
</widget>
</item>
<item row="4" column="3">
<widget class="QPushButton" name="ButtonUp">
<property name="text">
<string>Move up</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QPushButton" name="ButtonAdd">
<property name="text">
<string>Add new List</string>
</property>
</widget>
</item>
<item row="4" column="4">
<widget class="QPushButton" name="ButtonDown">
<property name="text">
<string>Move down</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QPushButton" name="ButtonNewTool">
<property name="text">
<string>New Tool</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QListWidget" name="listWidget">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="acceptDrops">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="4">
<widget class="QPushButton" name="ButtonExport">
<property name="text">
<string>Export...</string>
</property>
</widget>
</item>
<item row="3" column="1" colspan="4">
<widget class="QTableView" name="ToolsList"/>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>Dialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>Dialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@@ -0,0 +1,244 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Dialog</class>
<widget class="QDialog" name="Dialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>807</width>
<height>555</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="1" colspan="2">
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>Tool Properties</string>
</property>
<layout class="QFormLayout" name="formLayout">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
</property>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Name</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="NameField"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Type</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="TypeField"/>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Material</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QComboBox" name="MaterialField"/>
</item>
<item row="6" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Diameter</string>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QDoubleSpinBox" name="DiameterField">
<property name="suffix">
<string>mm</string>
</property>
</widget>
</item>
<item row="8" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Length Offset</string>
</property>
</widget>
</item>
<item row="8" column="1">
<widget class="QDoubleSpinBox" name="LengthOffsetField">
<property name="suffix">
<string>mm</string>
</property>
</widget>
</item>
<item row="12" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Flat Radius</string>
</property>
</widget>
</item>
<item row="12" column="1">
<widget class="QDoubleSpinBox" name="FlatRadiusField">
<property name="suffix">
<string>mm</string>
</property>
</widget>
</item>
<item row="14" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Corner Radius</string>
</property>
</widget>
</item>
<item row="14" column="1">
<widget class="QDoubleSpinBox" name="CornerRadiusField">
<property name="suffix">
<string>mm</string>
</property>
</widget>
</item>
<item row="16" column="0">
<widget class="QLabel" name="label_9">
<property name="text">
<string>Cutting Edge Angle</string>
</property>
</widget>
</item>
<item row="16" column="1">
<widget class="QDoubleSpinBox" name="CuttingEdgeAngleField">
<property name="suffix">
<string>°</string>
</property>
</widget>
</item>
<item row="18" column="0">
<widget class="QLabel" name="label_8">
<property name="text">
<string>Cutting Edge Height</string>
</property>
</widget>
</item>
<item row="18" column="1">
<widget class="QDoubleSpinBox" name="CuttingEdgeHeightField">
<property name="suffix">
<string>mm</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="1" column="2">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Tool List</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="2" column="1">
<widget class="QPushButton" name="ButtonDelete">
<property name="text">
<string>Delete</string>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QPushButton" name="ButtonUp">
<property name="text">
<string>Move up</string>
</property>
</widget>
</item>
<item row="0" column="0" colspan="2">
<widget class="QPushButton" name="ButtonImport">
<property name="text">
<string>Import...</string>
</property>
</widget>
</item>
<item row="0" column="2" colspan="2">
<widget class="QPushButton" name="ButtonExport">
<property name="text">
<string>Export...</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QPushButton" name="ButtonAdd">
<property name="text">
<string>Add new</string>
</property>
</widget>
</item>
<item row="1" column="0" colspan="4">
<widget class="QTableView" name="ToolsList"/>
</item>
<item row="2" column="3">
<widget class="QPushButton" name="ButtonDown">
<property name="text">
<string>Move down</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>Dialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>Dialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@@ -476,7 +476,11 @@ class CommandDragknifeDressup:
'ToolTip': QtCore.QT_TRANSLATE_NOOP("DragKnife_Dressup", "Modifies a path to add dragknife corner actions")}
def IsActive(self):
return FreeCAD.ActiveDocument is not None
if FreeCAD.ActiveDocument is not None:
for o in FreeCAD.ActiveDocument.Objects:
if o.Name[:3] == "Job":
return True
return False
def Activated(self):

View File

@@ -1,29 +1,31 @@
# -*- coding: utf-8 -*-
#***************************************************************************
#* *
#* Copyright (c) 2015 Yorik van Havre <yorik@uncreated.net> *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
#* as published by the Free Software Foundation; either version 2 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENCE text file. *
#* *
#* 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 Library General Public License for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with this program; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#***************************************************************************
# ***************************************************************************
# * *
# * Copyright (c) 2015 Yorik van Havre <yorik@uncreated.net> *
# * *
# * This program is free software; you can redistribute it and/or modify *
# * it under the terms of the GNU Lesser General Public License (LGPL) *
# * as published by the Free Software Foundation; either version 2 of *
# * the License, or (at your option) any later version. *
# * for detail see the LICENCE text file. *
# * *
# * 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 Library General Public License for more details. *
# * *
# * You should have received a copy of the GNU Library General Public *
# * License along with this program; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
# * USA *
# * *
# ***************************************************************************
import FreeCAD,FreeCADGui,Path,PathGui
from PySide import QtCore,QtGui
import FreeCAD
import FreeCADGui
import Path
from PySide import QtCore, QtGui
"""Path Array object and FreeCAD command"""
@@ -38,27 +40,29 @@ except AttributeError:
class ObjectArray:
def __init__(self,obj):
obj.addProperty("App::PropertyLink","Base","Path",QtCore.QT_TRANSLATE_NOOP("App::Property","The path to array"))
obj.addProperty("App::PropertyVectorDistance","Offset","Path",QtCore.QT_TRANSLATE_NOOP("App::Property","The spacing between the array copies"))
obj.addProperty("App::PropertyInteger","Copies","Path",QtCore.QT_TRANSLATE_NOOP("App::Property","The number of copies"))
def __init__(self, obj):
obj.addProperty("App::PropertyLink", "Base",
"Path", "The path to array")
obj.addProperty("App::PropertyVectorDistance", "Offset",
"Path", "The spacing between the array copies")
obj.addProperty("App::PropertyInteger", "Copies",
"Path", "The number of copies")
obj.Proxy = self
def __getstate__(self):
return None
def __setstate__(self,state):
def __setstate__(self, state):
return None
def execute(self,obj):
def execute(self, obj):
if obj.Base:
if not obj.Base.isDerivedFrom("Path::Feature"):
return
if not obj.Base.Path:
return
# build copies
basepath = obj.Base.Path
output = basepath.toGCode()
@@ -66,33 +70,33 @@ class ObjectArray:
if obj.Offset != FreeCAD.Vector():
for i in range(obj.Copies):
pl.move(obj.Offset)
np = Path.Path([cm.transform(pl) for cm in basepath.Commands])
np = Path.Path([cm.transform(pl)
for cm in basepath.Commands])
output += np.toGCode()
#print output
# print output
path = Path.Path(output)
obj.Path = path
class ViewProviderArray:
def __init__(self,vobj):
def __init__(self, vobj):
vobj.Proxy = self
def attach(self,vobj):
def attach(self, vobj):
self.Object = vobj.Object
return
def __getstate__(self):
return None
def __setstate__(self,state):
def __setstate__(self, state):
return None
def claimChildren(self):
if hasattr(self,"Object"):
if hasattr(self.Object,"Base"):
if hasattr(self, "Object"):
if hasattr(self.Object, "Base"):
if self.Object.Base:
return self.Object.Base
return []
@@ -100,40 +104,48 @@ class ViewProviderArray:
class CommandPathArray:
def GetResources(self):
return {'Pixmap' : 'Path-Array',
'MenuText': QtCore.QT_TRANSLATE_NOOP("Path_Array","Array"),
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Path_Array","Creates an array from a selected path")}
return {'Pixmap': 'Path-Array',
'MenuText': QtCore.QT_TRANSLATE_NOOP("Path_Array", "Array"),
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Path_Array", "Creates an array from a selected path")}
def IsActive(self):
return not FreeCAD.ActiveDocument is None
if FreeCAD.ActiveDocument is not None:
for o in FreeCAD.ActiveDocument.Objects:
if o.Name[:3] == "Job":
return True
return False
def Activated(self):
# check that the selection contains exactly what we want
selection = FreeCADGui.Selection.getSelection()
if len(selection) != 1:
FreeCAD.Console.PrintError(translate("Path_Array","Please select exactly one path object\n"))
FreeCAD.Console.PrintError(
translate("Path_Array", "Please select exactly one path object\n"))
return
if not(selection[0].isDerivedFrom("Path::Feature")):
FreeCAD.Console.PrintError(translate("Path_Array","Please select exactly one path object\n"))
FreeCAD.Console.PrintError(
translate("Path_Array", "Please select exactly one path object\n"))
return
# if everything is ok, execute and register the transaction in the undo/redo stack
# if everything is ok, execute and register the transaction in the
# undo/redo stack
FreeCAD.ActiveDocument.openTransaction("Create Array")
FreeCADGui.addModule("PathScripts.PathArray")
FreeCADGui.addModule("PathScripts.PathUtils")
FreeCADGui.doCommand('obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython","Array")')
FreeCADGui.doCommand(
'obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython","Array")')
FreeCADGui.doCommand('PathScripts.PathArray.ObjectArray(obj)')
FreeCADGui.doCommand('obj.Base = (FreeCAD.ActiveDocument.' + selection[0].Name + ')')
#FreeCADGui.doCommand('PathScripts.PathArray.ViewProviderArray(obj.ViewObject)')
FreeCADGui.doCommand(
'obj.Base = (FreeCAD.ActiveDocument.' + selection[0].Name + ')')
# FreeCADGui.doCommand('PathScripts.PathArray.ViewProviderArray(obj.ViewObject)')
FreeCADGui.doCommand('obj.ViewObject.Proxy = 0')
FreeCADGui.doCommand('PathScripts.PathUtils.addToProject(obj)')
FreeCADGui.doCommand('PathScripts.PathUtils.addToJob(obj)')
FreeCAD.ActiveDocument.commitTransaction()
FreeCAD.ActiveDocument.recompute()
if FreeCAD.GuiUp:
if FreeCAD.GuiUp:
# register the FreeCAD command
FreeCADGui.addCommand('Path_Array',CommandPathArray())
FreeCADGui.addCommand('Path_Array', CommandPathArray())

View File

@@ -1,119 +1,126 @@
# -*- coding: utf-8 -*-
#***************************************************************************
#* *
#* Copyright (c) 2015 Dan Falck <ddfalck@gmail.com> *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
#* as published by the Free Software Foundation; either version 2 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENCE text file. *
#* *
#* 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 Library General Public License for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with this program; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#***************************************************************************
# ***************************************************************************
# * *
# * Copyright (c) 2015 Dan Falck <ddfalck@gmail.com> *
# * *
# * This program is free software; you can redistribute it and/or modify *
# * it under the terms of the GNU Lesser General Public License (LGPL) *
# * as published by the Free Software Foundation; either version 2 of *
# * the License, or (at your option) any later version. *
# * for detail see the LICENCE text file. *
# * *
# * 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 Library General Public License for more details. *
# * *
# * You should have received a copy of the GNU Library General Public *
# * License along with this program; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
# * USA *
# * *
# ***************************************************************************
''' Used for CNC machine comments for Path module. Create a comment and place it in the Document tree.'''
import FreeCAD,FreeCADGui,Path,PathGui
from PathScripts import PathProject
from PySide import QtCore,QtGui
import FreeCAD
import FreeCADGui
import Path
from PySide import QtCore, QtGui
# Qt tanslation handling
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def translate(context, text, disambig=None):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def translate(context, text, disambig=None):
return QtGui.QApplication.translate(context, text, disambig)
class Comment:
def __init__(self,obj):
obj.addProperty("App::PropertyString","Comment","Path",QtCore.QT_TRANSLATE_NOOP("App::Property","Comment or note for CNC program"))
def __init__(self, obj):
obj.addProperty("App::PropertyString", "Comment",
"Path", "Comment or note for CNC program")
obj.Proxy = self
mode = 2
obj.setEditorMode('Placement',mode)
obj.setEditorMode('Placement', mode)
def __getstate__(self):
return None
def __setstate__(self,state):
def __setstate__(self, state):
return None
def onChanged(self,obj,prop):
def onChanged(self, obj, prop):
pass
def execute(self,obj):
output =""
output += '('+ str(obj.Comment)+')\n'
path = Path.Path(output)
obj.Path = path
def execute(self, obj):
output = ""
output += '(' + str(obj.Comment) + ')\n'
path = Path.Path(output)
obj.Path = path
class _ViewProviderComment:
def __init__(self,vobj): #mandatory
# obj.addProperty("App::PropertyFloat","SomePropertyName","PropertyGroup","Description of this property")
def __init__(self, vobj): # mandatory
vobj.Proxy = self
mode = 2
vobj.setEditorMode('LineWidth',mode)
vobj.setEditorMode('MarkerColor',mode)
vobj.setEditorMode('NormalColor',mode)
vobj.setEditorMode('ShowFirstRapid',mode)
vobj.setEditorMode('DisplayMode',mode)
vobj.setEditorMode('BoundingBox',mode)
vobj.setEditorMode('Selectable',mode)
vobj.setEditorMode('ShapeColor',mode)
vobj.setEditorMode('Transparency',mode)
vobj.setEditorMode('Visibility',mode)
vobj.setEditorMode('LineWidth', mode)
vobj.setEditorMode('MarkerColor', mode)
vobj.setEditorMode('NormalColor', mode)
vobj.setEditorMode('ShowFirstRapid', mode)
vobj.setEditorMode('DisplayMode', mode)
vobj.setEditorMode('BoundingBox', mode)
vobj.setEditorMode('Selectable', mode)
vobj.setEditorMode('ShapeColor', mode)
vobj.setEditorMode('Transparency', mode)
vobj.setEditorMode('Visibility', mode)
def __getstate__(self): #mandatory
def __getstate__(self): # mandatory
return None
def __setstate__(self,state): #mandatory
def __setstate__(self, state): # mandatory
return None
def getIcon(self): #optional
def getIcon(self): # optional
return ":/icons/Path-Comment.svg"
def onChanged(self,vobj,prop): #optional
def onChanged(self, vobj, prop): # optional
mode = 2
vobj.setEditorMode('LineWidth',mode)
vobj.setEditorMode('MarkerColor',mode)
vobj.setEditorMode('NormalColor',mode)
vobj.setEditorMode('ShowFirstRapid',mode)
vobj.setEditorMode('DisplayMode',mode)
vobj.setEditorMode('BoundingBox',mode)
vobj.setEditorMode('Selectable',mode)
vobj.setEditorMode('ShapeColor',mode)
vobj.setEditorMode('Transparency',mode)
vobj.setEditorMode('Visibility',mode)
def getIcon(self):
return ":/icons/Path-Comment.svg"
vobj.setEditorMode('LineWidth', mode)
vobj.setEditorMode('MarkerColor', mode)
vobj.setEditorMode('NormalColor', mode)
vobj.setEditorMode('ShowFirstRapid', mode)
vobj.setEditorMode('DisplayMode', mode)
vobj.setEditorMode('BoundingBox', mode)
vobj.setEditorMode('Selectable', mode)
vobj.setEditorMode('ShapeColor', mode)
vobj.setEditorMode('Transparency', mode)
vobj.setEditorMode('Visibility', mode)
class CommandPathComment:
def GetResources(self):
return {'Pixmap' : 'Path-Comment',
'MenuText': QtCore.QT_TRANSLATE_NOOP("Path_Comment","Comment"),
return {'Pixmap': 'Path-Comment',
'MenuText': QtCore.QT_TRANSLATE_NOOP("Path_Comment", "Comment"),
'Accel': "P, C",
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Path_Comment","Add a Comment to your CNC program")}
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Path_Comment", "Add a Comment to your CNC program")}
def IsActive(self):
return not FreeCAD.ActiveDocument is None
if FreeCAD.ActiveDocument is not None:
for o in FreeCAD.ActiveDocument.Objects:
if o.Name[:3] == "Job":
return True
return False
def Activated(self):
FreeCAD.ActiveDocument.openTransaction(translate("Path_Comment","Create a Comment in your CNC program"))
FreeCAD.ActiveDocument.openTransaction(
translate("Path_Comment", "Create a Comment in your CNC program"))
FreeCADGui.addModule("PathScripts.PathComment")
snippet = '''
import Path
@@ -123,15 +130,15 @@ obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython","Comment")
PathScripts.PathComment.Comment(obj)
PathScripts.PathComment._ViewProviderComment(obj.ViewObject)
PathUtils.addToProject(obj)
PathUtils.addToJob(obj)
'''
FreeCADGui.doCommand(snippet)
FreeCAD.ActiveDocument.commitTransaction()
FreeCAD.ActiveDocument.recompute()
if FreeCAD.GuiUp:
if FreeCAD.GuiUp:
# register the FreeCAD command
FreeCADGui.addCommand('Path_Comment',CommandPathComment())
FreeCADGui.addCommand('Path_Comment', CommandPathComment())
FreeCAD.Console.PrintLog("Loading PathComment... done\n")

View File

@@ -1,35 +1,37 @@
# -*- coding: utf-8 -*-
# ***************************************************************************
# * *
# * Copyright (c) 2014 Yorik van Havre <yorik@uncreated.net> *
# * *
# * This program is free software; you can redistribute it and/or modify *
# * it under the terms of the GNU Lesser General Public License (LGPL) *
# * as published by the Free Software Foundation; either version 2 of *
# * the License, or (at your option) any later version. *
# * for detail see the LICENCE text file. *
# * *
# * 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 Library General Public License for more details. *
# * *
# * You should have received a copy of the GNU Library General Public *
# * License along with this program; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
# * USA *
# * *
# ***************************************************************************
#***************************************************************************
#* *
#* Copyright (c) 2014 Yorik van Havre <yorik@uncreated.net> *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
#* as published by the Free Software Foundation; either version 2 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENCE text file. *
#* *
#* 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 Library General Public License for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with this program; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#***************************************************************************
import FreeCAD,FreeCADGui,Path,PathGui, PathUtils
from PySide import QtCore,QtGui
import FreeCAD
import FreeCADGui
import Path
from PySide import QtCore, QtGui
"""Path Compound Extended object and FreeCAD command"""
# Qt tanslation handling
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def translate(context, text, disambig=None):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
@@ -38,7 +40,6 @@ except AttributeError:
class ObjectCompoundExtended:
def __init__(self,obj):
obj.addProperty("App::PropertyString","Description", "Path",QtCore.QT_TRANSLATE_NOOP("App::Property","An ptional description of this compounded operation"))
@@ -51,17 +52,17 @@ class ObjectCompoundExtended:
def __getstate__(self):
return None
def __setstate__(self,state):
def __setstate__(self, state):
return None
def onChanged(self,obj,prop):
def onChanged(self, obj, prop):
if prop == "Group":
print 'check order'
for child in obj.Group:
if child.isDerivedFrom("Path::Feature"):
child.touch()
child.touch()
def execute(self,obj):
def execute(self, obj):
cmds = []
for child in obj.Group:
if child.isDerivedFrom("Path::Feature"):
@@ -77,10 +78,10 @@ class ObjectCompoundExtended:
class ViewProviderCompoundExtended:
def __init__(self,vobj):
def __init__(self, vobj):
vobj.Proxy = self
def attach(self,vobj):
def attach(self, vobj):
self.Object = vobj.Object
return
@@ -90,25 +91,29 @@ class ViewProviderCompoundExtended:
def __getstate__(self):
return None
def __setstate__(self,state):
def __setstate__(self, state):
return None
class CommandCompoundExtended:
def GetResources(self):
return {'Pixmap' : 'Path-Compound',
'MenuText': QtCore.QT_TRANSLATE_NOOP("Path_CompoundExtended","Compound"),
return {'Pixmap': 'Path-Compound',
'MenuText': QtCore.QT_TRANSLATE_NOOP("Path_CompoundExtended", "Compound"),
'Accel': "P, C",
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Path_CompoundExtended","Creates a Path Compound object")}
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Path_CompoundExtended", "Creates a Path Compound object")}
def IsActive(self):
return not FreeCAD.ActiveDocument is None
if FreeCAD.ActiveDocument is not None:
for o in FreeCAD.ActiveDocument.Objects:
if o.Name[:3] == "Job":
return True
return False
def Activated(self):
FreeCAD.ActiveDocument.openTransaction(translate("Path_CompoundExtended","Create Compound"))
FreeCAD.ActiveDocument.openTransaction(
translate("Path_CompoundExtended", "Create Compound"))
FreeCADGui.addModule("PathScripts.PathCompoundExtended")
snippet = '''
import Path
@@ -124,12 +129,11 @@ for s in sel:
obj = FreeCAD.ActiveDocument.addObject("Path::FeatureCompoundPython","Compound")
PathScripts.PathCompoundExtended.ObjectCompoundExtended(obj)
PathScripts.PathCompoundExtended.ViewProviderCompoundExtended(obj.ViewObject)
project = PathUtils.addToProject(obj)
project = PathUtils.addToJob(obj)
if incl:
children = []
p = project.Group
g = obj.Group
for child in incl:
p.remove(child)
@@ -143,8 +147,8 @@ if incl:
FreeCAD.ActiveDocument.recompute()
if FreeCAD.GuiUp:
if FreeCAD.GuiUp:
# register the FreeCAD command
FreeCADGui.addCommand('Path_CompoundExtended',CommandCompoundExtended())
FreeCADGui.addCommand('Path_CompoundExtended', CommandCompoundExtended())
FreeCAD.Console.PrintLog("Loading PathCompoundExtended... done\n")

View File

@@ -1,35 +1,37 @@
# -*- coding: utf-8 -*-
#***************************************************************************
#* *
#* Copyright (c) 2014 Yorik van Havre <yorik@uncreated.net> *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
#* as published by the Free Software Foundation; either version 2 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENCE text file. *
#* *
#* 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 Library General Public License for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with this program; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#***************************************************************************
# ***************************************************************************
# * *
# * Copyright (c) 2014 Yorik van Havre <yorik@uncreated.net> *
# * *
# * This program is free software; you can redistribute it and/or modify *
# * it under the terms of the GNU Lesser General Public License (LGPL) *
# * as published by the Free Software Foundation; either version 2 of *
# * the License, or (at your option) any later version. *
# * for detail see the LICENCE text file. *
# * *
# * 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 Library General Public License for more details. *
# * *
# * You should have received a copy of the GNU Library General Public *
# * License along with this program; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
# * USA *
# * *
# ***************************************************************************
import FreeCAD,FreeCADGui,Path,PathGui
from PySide import QtCore,QtGui
import FreeCAD
import FreeCADGui
from PySide import QtCore, QtGui
"""Path Copy object and FreeCAD command"""
# Qt tanslation handling
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def translate(context, text, disambig=None):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
@@ -38,7 +40,6 @@ except AttributeError:
class ObjectPathCopy:
def __init__(self,obj):
obj.addProperty("App::PropertyLink","Base","Path",QtCore.QT_TRANSLATE_NOOP("App::Property","The path to be copied"))
@@ -47,10 +48,10 @@ class ObjectPathCopy:
def __getstate__(self):
return None
def __setstate__(self,state):
def __setstate__(self, state):
return None
def execute(self,obj):
def execute(self, obj):
if obj.Base:
if obj.Base.Path:
obj.Path = obj.Base.Path.copy()
@@ -58,10 +59,10 @@ class ObjectPathCopy:
class ViewProviderPathCopy:
def __init__(self,vobj):
def __init__(self, vobj):
vobj.Proxy = self
def attach(self,vobj):
def attach(self, vobj):
self.Object = vobj.Object
return
@@ -71,25 +72,29 @@ class ViewProviderPathCopy:
def __getstate__(self):
return None
def __setstate__(self,state):
def __setstate__(self, state):
return None
class CommandPathCopy:
def GetResources(self):
return {'Pixmap' : 'Path-Copy',
'MenuText': QtCore.QT_TRANSLATE_NOOP("Path_Copy","Copy"),
return {'Pixmap': 'Path-Copy',
'MenuText': QtCore.QT_TRANSLATE_NOOP("Path_Copy", "Copy"),
'Accel': "P, Y",
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Path_Copy","Creates a linked copy of another path")}
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Path_Copy", "Creates a linked copy of another path")}
def IsActive(self):
return not FreeCAD.ActiveDocument is None
if FreeCAD.ActiveDocument is not None:
for o in FreeCAD.ActiveDocument.Objects:
if o.Name[:3] == "Job":
return True
return False
def Activated(self):
FreeCAD.ActiveDocument.openTransaction(translate("Path_Copy","Create Copy"))
FreeCAD.ActiveDocument.openTransaction(
translate("Path_Copy", "Create Copy"))
FreeCADGui.addModule("PathScripts.PathCopy")
consolecode = '''
@@ -128,8 +133,8 @@ FreeCAD.ActiveDocument.recompute()
FreeCAD.ActiveDocument.recompute()
if FreeCAD.GuiUp:
if FreeCAD.GuiUp:
# register the FreeCAD command
FreeCADGui.addCommand('Path_Copy',CommandPathCopy())
FreeCADGui.addCommand('Path_Copy', CommandPathCopy())
FreeCAD.Console.PrintLog("Loading PathCopy... done\n")

View File

@@ -1,35 +1,37 @@
# -*- coding: utf-8 -*-
# ***************************************************************************
# * *
# * Copyright (c) 2014 Yorik van Havre <yorik@uncreated.net> *
# * *
# * This program is free software; you can redistribute it and/or modify *
# * it under the terms of the GNU Lesser General Public License (LGPL) *
# * as published by the Free Software Foundation; either version 2 of *
# * the License, or (at your option) any later version. *
# * for detail see the LICENCE text file. *
# * *
# * 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 Library General Public License for more details. *
# * *
# * You should have received a copy of the GNU Library General Public *
# * License along with this program; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
# * USA *
# * *
# ***************************************************************************
#***************************************************************************
#* *
#* Copyright (c) 2014 Yorik van Havre <yorik@uncreated.net> *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
#* as published by the Free Software Foundation; either version 2 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENCE text file. *
#* *
#* 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 Library General Public License for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with this program; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#***************************************************************************
import FreeCAD,FreeCADGui,Path,PathGui
from PySide import QtCore,QtGui
import FreeCAD
import FreeCADGui
import Path
from PySide import QtCore, QtGui
"""Path Custom object and FreeCAD command"""
# Qt tanslation handling
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def translate(context, text, disambig=None):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
@@ -47,11 +49,11 @@ class ObjectCustom:
def __getstate__(self):
return None
def __setstate__(self,state):
def __setstate__(self, state):
return None
def execute(self,obj):
if obj.Gcode:
def execute(self, obj):
if obj.Gcode:
s = ""
for l in obj.Gcode:
s += str(l)
@@ -62,27 +64,31 @@ class ObjectCustom:
class CommandPathCustom:
def GetResources(self):
return {'Pixmap' : 'Path-Custom',
'MenuText': QtCore.QT_TRANSLATE_NOOP("Path_Custom","Custom"),
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Path_Custom","Creates a path object based on custom G-code")}
return {'Pixmap': 'Path-Custom',
'MenuText': QtCore.QT_TRANSLATE_NOOP("Path_Custom", "Custom"),
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Path_Custom", "Creates a path object based on custom G-code")}
def IsActive(self):
return not FreeCAD.ActiveDocument is None
if FreeCAD.ActiveDocument is not None:
for o in FreeCAD.ActiveDocument.Objects:
if o.Name[:3] == "Job":
return True
return False
def Activated(self):
FreeCAD.ActiveDocument.openTransaction("Create Custom Path")
FreeCADGui.addModule("PathScripts.PathCustom")
FreeCADGui.addModule("PathScripts.PathUtils")
FreeCADGui.doCommand('obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython","Custom")')
FreeCADGui.doCommand(
'obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython","Custom")')
FreeCADGui.doCommand('PathScripts.PathCustom.ObjectCustom(obj)')
FreeCADGui.doCommand('obj.ViewObject.Proxy = 0')
FreeCADGui.doCommand('PathScripts.PathUtils.addToProject(obj)')
FreeCADGui.doCommand('PathScripts.PathUtils.addToJob(obj)')
FreeCAD.ActiveDocument.commitTransaction()
FreeCAD.ActiveDocument.recompute()
if FreeCAD.GuiUp:
if FreeCAD.GuiUp:
# register the FreeCAD command
FreeCADGui.addCommand('Path_Custom',CommandPathCustom())
FreeCADGui.addCommand('Path_Custom', CommandPathCustom())

View File

@@ -114,7 +114,11 @@ class CommandPathDressup:
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Path_Dressup", "Creates a Path Dress-up object from a selected path")}
def IsActive(self):
return FreeCAD.ActiveDocument is not None
if FreeCAD.ActiveDocument is not None:
for o in FreeCAD.ActiveDocument.Objects:
if o.Name[:3] == "Job":
return True
return False
def Activated(self):

View File

@@ -266,7 +266,11 @@ class CommandPathDrilling:
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Path_Drilling", "Creates a Path Drilling object")}
def IsActive(self):
return FreeCAD.ActiveDocument is not None
if FreeCAD.ActiveDocument is not None:
for o in FreeCAD.ActiveDocument.Objects:
if o.Name[:3] == "Job":
return True
return False
def Activated(self):
@@ -283,7 +287,7 @@ class CommandPathDrilling:
FreeCADGui.doCommand('obj.ClearanceHeight = ' + str(ztop))
FreeCADGui.doCommand('obj.RetractHeight= ' + str(ztop))
FreeCADGui.doCommand('obj.FinalDepth=' + str(zbottom))
FreeCADGui.doCommand('PathScripts.PathUtils.addToProject(obj)')
FreeCADGui.doCommand('PathScripts.PathUtils.addToJob(obj)')
FreeCAD.ActiveDocument.commitTransaction()
FreeCAD.ActiveDocument.recompute()

View File

@@ -56,6 +56,9 @@ class ObjectPathEngrave:
obj.Algorithm = ['OCC Native']
# Tool Properties
obj.addProperty("App::PropertyEnumeration", "ToolController", "Tool", QtCore.QT_TRANSLATE_NOOP("App::Property","The tool controller to use"))
obj.ToolController = ["None"]
obj.addProperty("App::PropertyIntegerConstraint", "ToolNumber", "Tool", QtCore.QT_TRANSLATE_NOOP("App::Property","The tool number in use"))
obj.ToolNumber = (0, 0, 1000, 1)
obj.setEditorMode('ToolNumber', 1) # make this read only
@@ -88,6 +91,17 @@ class ObjectPathEngrave:
if obj.Comment != "":
output += '(' + str(obj.Comment)+')\n'
myJob = PathUtils.findMyJob(obj)
if myJob is not None:
controllers = myJob.Proxy.getToolControllers(myJob)
if len(controllers) >= 1:
mlist = []
for c in controllers:
mlist.append(c.Name)
else:
mlist = ["None"]
obj.ToolController = mlist
toolLoad = PathUtils.getLastToolLoad(obj)
if toolLoad is None or toolLoad.ToolNumber == 0:
self.vertFeed = 100
@@ -238,6 +252,9 @@ class _ViewProviderEngrave:
def __setstate__(self, state):
return None
def onDelete(self):
return None
class CommandPathEngrave:
@@ -247,7 +264,11 @@ class CommandPathEngrave:
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Path_Engrave", "Creates an Engraving Path around a Draft ShapeString")}
def IsActive(self):
return FreeCAD.ActiveDocument is not None
if FreeCAD.ActiveDocument is not None:
for o in FreeCAD.ActiveDocument.Objects:
if o.Name[:3] == "Job":
return True
return False
def Activated(self):
@@ -263,7 +284,7 @@ class CommandPathEngrave:
FreeCADGui.doCommand('obj.SafeHeight= 5.0')
FreeCADGui.doCommand('obj.Active = True')
FreeCADGui.doCommand('PathScripts.PathUtils.addToProject(obj)')
FreeCADGui.doCommand('PathScripts.PathUtils.addToJob(obj)')
FreeCAD.ActiveDocument.commitTransaction()
FreeCAD.ActiveDocument.recompute()
FreeCADGui.doCommand('obj.ViewObject.startEditing()')

View File

@@ -1,35 +1,37 @@
# -*- coding: utf-8 -*-
# ***************************************************************************
# * *
# * Copyright (c) 2014 Yorik van Havre <yorik@uncreated.net> *
# * *
# * This program is free software; you can redistribute it and/or modify *
# * it under the terms of the GNU Lesser General Public License (LGPL) *
# * as published by the Free Software Foundation; either version 2 of *
# * the License, or (at your option) any later version. *
# * for detail see the LICENCE text file. *
# * *
# * 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 Library General Public License for more details. *
# * *
# * You should have received a copy of the GNU Library General Public *
# * License along with this program; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
# * USA *
# * *
# ***************************************************************************
#***************************************************************************
#* *
#* Copyright (c) 2014 Yorik van Havre <yorik@uncreated.net> *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
#* as published by the Free Software Foundation; either version 2 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENCE text file. *
#* *
#* 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 Library General Public License for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with this program; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#***************************************************************************
import FreeCAD,FreeCADGui,Path,PathGui
from PySide import QtCore,QtGui
import FreeCAD
import FreeCADGui
import Path
from PySide import QtCore, QtGui
"""Path Pocket object and FreeCAD command"""
# Qt tanslation handling
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def translate(context, text, disambig=None):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
@@ -38,7 +40,6 @@ except AttributeError:
class ObjectFacePocket:
def __init__(self,obj):
obj.addProperty("App::PropertyLinkSub","Base","Path",QtCore.QT_TRANSLATE_NOOP("App::Property","The base geometry of this object"))
@@ -53,44 +54,47 @@ class ObjectFacePocket:
def __getstate__(self):
return None
def __setstate__(self,state):
def __setstate__(self, state):
return None
def execute(self,obj):
def execute(self, obj):
if obj.Base and obj.Offset.Value:
import Part, DraftGeomUtils
import Part
import DraftGeomUtils
if "Face" in obj.Base[1][0]:
shape = getattr(obj.Base[0].Shape,obj.Base[1][0])
shape = getattr(obj.Base[0].Shape, obj.Base[1][0])
else:
edges = [getattr(obj.Base[0].Shape,sub) for sub in obj.Base[1]]
edges = [getattr(obj.Base[0].Shape, sub)
for sub in obj.Base[1]]
shape = Part.Wire(edges)
# absolute coords, millimeters, cancel offsets
output = "G90\nG21\nG40\n"
# build offsets
offsets = []
nextradius = obj.Offset.Value
result = DraftGeomUtils.pocket2d(shape,nextradius)
result = DraftGeomUtils.pocket2d(shape, nextradius)
while result:
offsets.extend(result)
if obj.Fill:
nextradius += obj.Offset.Value
result = DraftGeomUtils.pocket2d(shape,nextradius)
result = DraftGeomUtils.pocket2d(shape, nextradius)
else:
result = []
first = True
point = None
# revert the list so we start with the outer wires
offsets.reverse()
# loop over successive wires
while offsets:
currentWire = offsets.pop()
if first:
currentWire = DraftGeomUtils.rebaseWire(currentWire,obj.StartVertex)
currentWire = DraftGeomUtils.rebaseWire(
currentWire, obj.StartVertex)
last = None
for edge in currentWire.Edges:
if not last:
@@ -100,91 +104,107 @@ class ObjectFacePocket:
first = False
else:
if obj.RetractHeight.Value and point:
output += "G0 X" + str("%f" % point.x) + " Y" + str("%f" % point.y) + " Z" + str("%f" % obj.RetractHeight.Value) + "\n"
output += "G0 X" + str("%f" % point.x) + " Y" + str(
"%f" % point.y) + " Z" + str("%f" % obj.RetractHeight.Value) + "\n"
last = edge.Vertexes[0].Point
output += "G0 X" + str("%f" % last.x) + " Y" + str("%f" % last.y) + " Z" + str("%f" % obj.RetractHeight.Value) + "\n"
output += "G0 X" + str("%f" % last.x) + " Y" + str(
"%f" % last.y) + " Z" + str("%f" % obj.RetractHeight.Value) + "\n"
output += "G1"
last = edge.Vertexes[0].Point
output += " X" + str("%f" % last.x) + " Y" + str("%f" % last.y) + " Z" + str("%f" % last.z) + "\n"
if isinstance(edge.Curve,Part.Circle):
output += " X" + \
str("%f" % last.x) + " Y" + str("%f" %
last.y) + " Z" + str("%f" % last.z) + "\n"
if isinstance(edge.Curve, Part.Circle):
point = edge.Vertexes[-1].Point
if point == last: # edges can come flipped
if point == last: # edges can come flipped
point = edge.Vertexes[0].Point
center = edge.Curve.Center
relcenter = center.sub(last)
v1 = last.sub(center)
v2 = point.sub(center)
# v1 = last.sub(center)
# v2 = point.sub(center)
if edge.Curve.Axis.z < 0:
output += "G2"
else:
output += "G3"
output += " X" + str("%f" % point.x) + " Y" + str("%f" % point.y) + " Z" + str("%f" % point.z)
output += " I" + str("%f" % relcenter.x) + " J" + str("%f" % relcenter.y) + " K" + str("%f" % relcenter.z)
output += " X" + \
str("%f" % point.x) + " Y" + str("%f" %
point.y) + " Z" + str("%f" % point.z)
output += " I" + str("%f" % relcenter.x) + " J" + str(
"%f" % relcenter.y) + " K" + str("%f" % relcenter.z)
output += "\n"
last = point
else:
point = edge.Vertexes[-1].Point
if point == last: # edges can come flipped
if point == last: # edges can come flipped
point = edge.Vertexes[0].Point
output += "G1 X" + str("%f" % point.x) + " Y" + str("%f" % point.y) + " Z" + str("%f" % point.z) + "\n"
output += "G1 X" + \
str("%f" % point.x) + " Y" + str("%f" %
point.y) + " Z" + str("%f" % point.z) + "\n"
last = point
#print output
# print output
path = Path.Path(output)
obj.Path = path
class CommandPathFacePocket:
def GetResources(self):
return {'Pixmap' : 'Path-FacePocket',
'MenuText': QtCore.QT_TRANSLATE_NOOP("Path_FacePocket","Face Pocket"),
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Path_FacePocket","Creates a pocket inside a loop of edges or a face")}
return {'Pixmap': 'Path-FacePocket',
'MenuText': QtCore.QT_TRANSLATE_NOOP("Path_FacePocket", "Face Pocket"),
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Path_FacePocket", "Creates a pocket inside a loop of edges or a face")}
def IsActive(self):
return not FreeCAD.ActiveDocument is None
def Activated(self):
# check that the selection contains exactly what we want
selection = FreeCADGui.Selection.getSelectionEx()
if len(selection) != 1:
FreeCAD.Console.PrintError(translate("Path_FacePocket","Please select an edges loop from one object, or a single face\n"))
FreeCAD.Console.PrintError(translate(
"Path_FacePocket", "Please select an edges loop from one object, or a single face\n"))
return
if len(selection[0].SubObjects) == 0:
FreeCAD.Console.PrintError(translate("Path_FacePocket","Please select an edges loop from one object, or a single face\n"))
FreeCAD.Console.PrintError(translate(
"Path_FacePocket", "Please select an edges loop from one object, or a single face\n"))
return
for s in selection[0].SubObjects:
if s.ShapeType != "Edge":
if (s.ShapeType != "Face") or (len(selection[0].SubObjects) != 1):
FreeCAD.Console.PrintError(translate("Path_FacePocket","Please select only edges or a single face\n"))
FreeCAD.Console.PrintError(
translate("Path_FacePocket", "Please select only edges or a single face\n"))
return
if selection[0].SubObjects[0].ShapeType == "Edge":
try:
import Part
w = Part.Wire(selection[0].SubObjects)
# w = Part.Wire(selection[0].SubObjects)
except:
FreeCAD.Console.PrintError(translate("Path_FacePocket","The selected edges don't form a loop\n"))
FreeCAD.Console.PrintError(
translate("Path_FacePocket", "The selected edges don't form a loop\n"))
return
# if everything is ok, execute and register the transaction in the undo/redo stack
# if everything is ok, execute and register the transaction in the
# undo/redo stack
FreeCAD.ActiveDocument.openTransaction("Create Pocket")
FreeCADGui.addModule("PathScripts.PathFacePocket")
FreeCADGui.addModule("PathScripts.PathUtils")
FreeCADGui.doCommand('obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython","FacePocket")')
FreeCADGui.doCommand('PathScripts.PathFacePocket.ObjectFacePocket(obj)')
FreeCADGui.doCommand(
'obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython","FacePocket")')
FreeCADGui.doCommand(
'PathScripts.PathFacePocket.ObjectFacePocket(obj)')
subs = "["
for s in selection[0].SubElementNames:
subs += '"' + s + '",'
subs += "]"
FreeCADGui.doCommand('obj.Base = (FreeCAD.ActiveDocument.' + selection[0].ObjectName + ',' + subs + ')')
FreeCADGui.doCommand(
'obj.Base = (FreeCAD.ActiveDocument.' + selection[0].ObjectName + ',' + subs + ')')
FreeCADGui.doCommand('obj.ViewObject.Proxy = 0')
FreeCADGui.doCommand('PathScripts.PathUtils.addToProject(obj)')
FreeCADGui.doCommand('PathScripts.PathUtils.addToJob(obj)')
FreeCAD.ActiveDocument.commitTransaction()
FreeCAD.ActiveDocument.recompute()
if FreeCAD.GuiUp:
if FreeCAD.GuiUp:
# register the FreeCAD command
FreeCADGui.addCommand('Path_FacePocket',CommandPathFacePocket())
FreeCADGui.addCommand('Path_FacePocket', CommandPathFacePocket())

View File

@@ -1,35 +1,37 @@
# -*- coding: utf-8 -*-
# ***************************************************************************
# * *
# * Copyright (c) 2014 Yorik van Havre <yorik@uncreated.net> *
# * *
# * This program is free software; you can redistribute it and/or modify *
# * it under the terms of the GNU Lesser General Public License (LGPL) *
# * as published by the Free Software Foundation; either version 2 of *
# * the License, or (at your option) any later version. *
# * for detail see the LICENCE text file. *
# * *
# * 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 Library General Public License for more details. *
# * *
# * You should have received a copy of the GNU Library General Public *
# * License along with this program; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
# * USA *
# * *
# ***************************************************************************
#***************************************************************************
#* *
#* Copyright (c) 2014 Yorik van Havre <yorik@uncreated.net> *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
#* as published by the Free Software Foundation; either version 2 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENCE text file. *
#* *
#* 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 Library General Public License for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with this program; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#***************************************************************************
import FreeCAD,FreeCADGui,Path,PathGui
from PySide import QtCore,QtGui
import FreeCAD
import FreeCADGui
import Path
from PySide import QtCore, QtGui
"""Path Profile object and FreeCAD command"""
# Qt tanslation handling
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def translate(context, text, disambig=None):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
@@ -38,7 +40,6 @@ except AttributeError:
class ObjectFaceProfile:
def __init__(self,obj):
obj.addProperty("App::PropertyLinkSub","Base","Path",QtCore.QT_TRANSLATE_NOOP("App::Property","The base geometry of this object"))
@@ -51,14 +52,15 @@ class ObjectFaceProfile:
def __getstate__(self):
return None
def __setstate__(self,state):
def __setstate__(self, state):
return None
def execute(self,obj):
if obj.Base:
import Part,DraftGeomUtils
def execute(self, obj):
if obj.Base:
import Part
import DraftGeomUtils
# we only consider the outer wire if this is a Face
shape = getattr(obj.Base[0].Shape,obj.Base[1][0])
shape = getattr(obj.Base[0].Shape, obj.Base[1][0])
if shape.ShapeType == "Wire":
wire = shape
else:
@@ -71,17 +73,19 @@ class ObjectFaceProfile:
# absolute coords, millimeters, cancel offsets
output = "G90\nG21\nG40\n"
# reorder the wire
offset = DraftGeomUtils.rebaseWire(offset,obj.StartVertex)
offset = DraftGeomUtils.rebaseWire(offset, obj.StartVertex)
# we create the path from the offset shape
last = None
for edge in offset.Edges:
if not last:
# we set the first move to our first point
last = edge.Vertexes[0].Point
output += obj.FirstMove + " X" + str("%f" % last.x) + " Y" + str("%f" % last.y) + " Z" + str("%f" % last.z) + "\n"
if isinstance(edge.Curve,Part.Circle):
output += obj.FirstMove + " X" + \
str("%f" % last.x) + " Y" + str("%f" %
last.y) + " Z" + str("%f" % last.z) + "\n"
if isinstance(edge.Curve, Part.Circle):
point = edge.Vertexes[-1].Point
if point == last: # edges can come flipped
if point == last: # edges can come flipped
point = edge.Vertexes[0].Point
center = edge.Curve.Center
relcenter = center.sub(last)
@@ -91,59 +95,69 @@ class ObjectFaceProfile:
output += "G2"
else:
output += "G3"
output += " X" + str("%f" % point.x) + " Y" + str("%f" % point.y) + " Z" + str("%f" % point.z)
output += " I" + str("%f" % relcenter.x) + " J" + str("%f" % relcenter.y) + " K" + str("%f" % relcenter.z)
output += " X" + str("%f" % point.x) + " Y" + \
str("%f" % point.y) + " Z" + str("%f" % point.z)
output += " I" + str("%f" % relcenter.x) + " J" + str("%f" %
relcenter.y) + " K" + str("%f" % relcenter.z)
output += "\n"
last = point
else:
point = edge.Vertexes[-1].Point
if point == last: # edges can come flipped
if point == last: # edges can come flipped
point = edge.Vertexes[0].Point
output += "G1 X" + str("%f" % point.x) + " Y" + str("%f" % point.y) + " Z" + str("%f" % point.z) + "\n"
output += "G1 X" + \
str("%f" % point.x) + " Y" + str("%f" %
point.y) + " Z" + str("%f" % point.z) + "\n"
last = point
#print output
# print output
path = Path.Path(output)
obj.Path = path
class CommandPathFaceProfile:
def GetResources(self):
return {'Pixmap' : 'Path-FaceProfile',
'MenuText': QtCore.QT_TRANSLATE_NOOP("Path_FaceProfile","Face Profile"),
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Path_FaceProfile","Creates a profile object around a selected face")}
return {'Pixmap': 'Path-FaceProfile',
'MenuText': QtCore.QT_TRANSLATE_NOOP("Path_FaceProfile", "Face Profile"),
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Path_FaceProfile", "Creates a profile object around a selected face")}
def IsActive(self):
return not FreeCAD.ActiveDocument is None
return FreeCAD.ActiveDocument is not None
def Activated(self):
# check that the selection contains exactly what we want
selection = FreeCADGui.Selection.getSelectionEx()
if len(selection) != 1:
FreeCAD.Console.PrintError(translate("Path_FaceProfile","Please select one face or wire\n"))
FreeCAD.Console.PrintError(
translate("Path_FaceProfile", "Please select one face or wire\n"))
return
if len(selection[0].SubObjects) != 1:
FreeCAD.Console.PrintError(translate("Path_FaceProfile","Please select only one face or wire\n"))
FreeCAD.Console.PrintError(
translate("Path_FaceProfile", "Please select only one face or wire\n"))
return
if not selection[0].SubObjects[0].ShapeType in ["Face","Wire"]:
FreeCAD.Console.PrintError(translate("Path_FaceProfile","Please select only a face or a wire\n"))
if not selection[0].SubObjects[0].ShapeType in ["Face", "Wire"]:
FreeCAD.Console.PrintError(
translate("Path_FaceProfile", "Please select only a face or a wire\n"))
return
# if everything is ok, execute and register the transaction in the undo/redo stack
# if everything is ok, execute and register the transaction in the
# undo/redo stack
FreeCAD.ActiveDocument.openTransaction("Create Profile")
FreeCADGui.addModule("PathScripts.PathFaceProfile")
FreeCADGui.addModule("PathScripts.PathUtils")
FreeCADGui.doCommand('obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython","FaceProfile")')
FreeCADGui.doCommand('PathScripts.PathFaceProfile.ObjectFaceProfile(obj)')
FreeCADGui.doCommand('obj.Base = (FreeCAD.ActiveDocument.'+selection[0].ObjectName+',"'+selection[0].SubElementNames[0]+'")')
FreeCADGui.doCommand(
'obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython","FaceProfile")')
FreeCADGui.doCommand(
'PathScripts.PathFaceProfile.ObjectFaceProfile(obj)')
FreeCADGui.doCommand('obj.Base = (FreeCAD.ActiveDocument.' + selection[
0].ObjectName + ',"' + selection[0].SubElementNames[0] + '")')
FreeCADGui.doCommand('obj.ViewObject.Proxy = 0')
FreeCADGui.doCommand('PathScripts.PathUtils.addToProject(obj)')
FreeCADGui.doCommand('PathScripts.PathUtils.addToJob(obj)')
FreeCAD.ActiveDocument.commitTransaction()
FreeCAD.ActiveDocument.recompute()
if FreeCAD.GuiUp:
if FreeCAD.GuiUp:
# register the FreeCAD command
FreeCADGui.addCommand('Path_FaceProfile',CommandPathFaceProfile())
FreeCADGui.addCommand('Path_FaceProfile', CommandPathFaceProfile())

View File

@@ -1,41 +1,43 @@
# -*- coding: utf-8 -*-
#***************************************************************************
#* *
#* Copyright (c) 2015 Dan Falck <ddfalck@gmail.com> *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
#* as published by the Free Software Foundation; either version 2 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENCE text file. *
#* *
#* 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 Library General Public License for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with this program; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#***************************************************************************
# ***************************************************************************
# * *
# * Copyright (c) 2015 Dan Falck <ddfalck@gmail.com> *
# * *
# * This program is free software; you can redistribute it and/or modify *
# * it under the terms of the GNU Lesser General Public License (LGPL) *
# * as published by the Free Software Foundation; either version 2 of *
# * the License, or (at your option) any later version. *
# * for detail see the LICENCE text file. *
# * *
# * 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 Library General Public License for more details. *
# * *
# * You should have received a copy of the GNU Library General Public *
# * License along with this program; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
# * USA *
# * *
# ***************************************************************************
''' Used to create CNC machine fixture offsets such as G54,G55, etc...'''
import FreeCAD,FreeCADGui,Path,PathGui
from PathScripts import PathProject
from PySide import QtCore,QtGui
import FreeCAD
import FreeCADGui
import Path
from PySide import QtCore, QtGui
# Qt tanslation handling
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def translate(context, text, disambig=None):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def translate(context, text, disambig=None):
return QtGui.QApplication.translate(context, text, disambig)
class Fixture:
def __init__(self,obj):
obj.addProperty("App::PropertyEnumeration", "Fixture", "Path",QtCore.QT_TRANSLATE_NOOP("App::Property","Fixture Offset Number"))
@@ -44,11 +46,12 @@ class Fixture:
obj.Proxy = self
def execute(self,obj):
fixlist = ['G53','G54','G55','G56','G57','G58','G59','G59.1', 'G59.2', 'G59.3', 'G59.4', 'G59.5','G59.6','G59.7', 'G59.8', 'G59.9']
fixture=fixlist.index(obj.Fixture)
def execute(self, obj):
fixlist = ['G53', 'G54', 'G55', 'G56', 'G57', 'G58', 'G59', 'G59.1',
'G59.2', 'G59.3', 'G59.4', 'G59.5', 'G59.6', 'G59.7', 'G59.8', 'G59.9']
fixture = fixlist.index(obj.Fixture)
obj.Path = Path.Path(str(obj.Fixture))
obj.Label = "Fixture"+str(fixture)
obj.Label = "Fixture" + str(fixture)
if obj.Active:
obj.Path = Path.Path(str(obj.Fixture))
obj.ViewObject.Visibility = True
@@ -59,72 +62,78 @@ class Fixture:
class _ViewProviderFixture:
def __init__(self,vobj): #mandatory
# obj.addProperty("App::PropertyFloat","SomePropertyName","PropertyGroup","Description of this property")
def __init__(self, vobj): # mandatory
# obj.addProperty("App::PropertyFloat","SomePropertyName","PropertyGroup","Description of this property")
vobj.Proxy = self
mode = 2
vobj.setEditorMode('LineWidth',mode)
vobj.setEditorMode('MarkerColor',mode)
vobj.setEditorMode('NormalColor',mode)
vobj.setEditorMode('ShowFirstRapid',mode)
vobj.setEditorMode('DisplayMode',mode)
vobj.setEditorMode('BoundingBox',mode)
vobj.setEditorMode('Selectable',mode)
vobj.setEditorMode('ShapeColor',mode)
vobj.setEditorMode('Transparency',mode)
vobj.setEditorMode('Visibility',mode)
vobj.setEditorMode('LineWidth', mode)
vobj.setEditorMode('MarkerColor', mode)
vobj.setEditorMode('NormalColor', mode)
vobj.setEditorMode('ShowFirstRapid', mode)
vobj.setEditorMode('DisplayMode', mode)
vobj.setEditorMode('BoundingBox', mode)
vobj.setEditorMode('Selectable', mode)
vobj.setEditorMode('ShapeColor', mode)
vobj.setEditorMode('Transparency', mode)
vobj.setEditorMode('Visibility', mode)
def __getstate__(self): #mandatory
def __getstate__(self): # mandatory
return None
def __setstate__(self,state): #mandatory
def __setstate__(self, state): # mandatory
return None
def getIcon(self): #optional
def getIcon(self): # optional
return ":/icons/Path-Datums.svg"
# def attach(self): #optional
# # this is executed on object creation and object load from file
# pass
def onChanged(self,vobj,prop): #optional
def onChanged(self, vobj, prop): # optional
mode = 2
vobj.setEditorMode('LineWidth',mode)
vobj.setEditorMode('MarkerColor',mode)
vobj.setEditorMode('NormalColor',mode)
vobj.setEditorMode('ShowFirstRapid',mode)
vobj.setEditorMode('DisplayMode',mode)
vobj.setEditorMode('BoundingBox',mode)
vobj.setEditorMode('Selectable',mode)
vobj.setEditorMode('ShapeColor',mode)
vobj.setEditorMode('Transparency',mode)
vobj.setEditorMode('Visibility',mode)
vobj.setEditorMode('LineWidth', mode)
vobj.setEditorMode('MarkerColor', mode)
vobj.setEditorMode('NormalColor', mode)
vobj.setEditorMode('ShowFirstRapid', mode)
vobj.setEditorMode('DisplayMode', mode)
vobj.setEditorMode('BoundingBox', mode)
vobj.setEditorMode('Selectable', mode)
vobj.setEditorMode('ShapeColor', mode)
vobj.setEditorMode('Transparency', mode)
vobj.setEditorMode('Visibility', mode)
def updateData(self,vobj,prop): #optional
def updateData(self, vobj, prop): # optional
# this is executed when a property of the APP OBJECT changes
pass
def setEdit(self,vobj,mode): #optional
def setEdit(self, vobj, mode): # optional
# this is executed when the object is double-clicked in the tree
pass
def unsetEdit(self,vobj,mode): #optional
def unsetEdit(self, vobj, mode): # optional
# this is executed when the user cancels or terminates edit mode
pass
class CommandPathFixture:
def GetResources(self):
return {'Pixmap' : 'Path-Datums',
'MenuText': QtCore.QT_TRANSLATE_NOOP("Path_Fixture","Fixture"),
return {'Pixmap': 'Path-Datums',
'MenuText': QtCore.QT_TRANSLATE_NOOP("Path_Fixture", "Fixture"),
'Accel': "P, F",
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Path_Fixture","Creates a Fixture Offset object")}
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Path_Fixture", "Creates a Fixture Offset object")}
def IsActive(self):
return not FreeCAD.ActiveDocument is None
if FreeCAD.ActiveDocument is not None:
for o in FreeCAD.ActiveDocument.Objects:
if o.Name[:3] == "Job":
return True
return False
def Activated(self):
FreeCAD.ActiveDocument.openTransaction(translate("Path_Fixture","Create a Fixture Offset"))
FreeCAD.ActiveDocument.openTransaction(
translate("Path_Fixture", "Create a Fixture Offset"))
FreeCADGui.addModule("PathScripts.PathFixture")
snippet = '''
import Path
@@ -136,16 +145,16 @@ PathScripts.PathFixture.Fixture(obj)
obj.Active = True
PathScripts.PathFixture._ViewProviderFixture(obj.ViewObject)
PathUtils.addToProject(obj)
PathUtils.addToJob(obj)
'''
FreeCADGui.doCommand(snippet)
FreeCAD.ActiveDocument.commitTransaction()
FreeCAD.ActiveDocument.recompute()
if FreeCAD.GuiUp:
if FreeCAD.GuiUp:
# register the FreeCAD command
FreeCADGui.addCommand('Path_Fixture',CommandPathFixture())
FreeCADGui.addCommand('Path_Fixture', CommandPathFixture())
FreeCAD.Console.PrintLog("Loading PathFixture... done\n")

View File

@@ -1,42 +1,44 @@
# -*- coding: utf-8 -*-
#***************************************************************************
#* *
#* Copyright (c) 2015 Dan Falck <ddfalck@gmail.com> *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
#* as published by the Free Software Foundation; either version 2 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENCE text file. *
#* *
#* 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 Library General Public License for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with this program; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#***************************************************************************
# ***************************************************************************
# * *
# * Copyright (c) 2015 Dan Falck <ddfalck@gmail.com> *
# * *
# * This program is free software; you can redistribute it and/or modify *
# * it under the terms of the GNU Lesser General Public License (LGPL) *
# * as published by the Free Software Foundation; either version 2 of *
# * the License, or (at your option) any later version. *
# * for detail see the LICENCE text file. *
# * *
# * 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 Library General Public License for more details. *
# * *
# * You should have received a copy of the GNU Library General Public *
# * License along with this program; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
# * USA *
# * *
# ***************************************************************************
''' Used to make GCode from FreeCAD shapes - Wires and Edges/Curves '''
import FreeCAD,FreeCADGui,Path,PathGui
from PathScripts import PathProject
from PySide import QtCore,QtGui
import FreeCAD
import FreeCADGui
from PySide import QtCore, QtGui
# Qt tanslation handling
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def translate(context, text, disambig=None):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def translate(context, text, disambig=None):
return QtGui.QApplication.translate(context, text, disambig)
#TODO make the shape parametric
# TODO make the shape parametric
class FromShape:
@@ -47,61 +49,66 @@ class FromShape:
def __getstate__(self):
return None
def __setstate__(self,state):
def __setstate__(self, state):
return None
def execute(self,obj):
def execute(self, obj):
pass
class _ViewProviderFromShape:
def __init__(self,vobj): #mandatory
def __init__(self, vobj): # mandatory
vobj.Proxy = self
def attach(self, vobj):
self.Object = vobj.Object
def __getstate__(self): #mandatory
def __getstate__(self): # mandatory
return None
def __setstate__(self,state): #mandatory
def __setstate__(self, state): # mandatory
return None
def getIcon(self): #optional
def getIcon(self): # optional
return ":/icons/Path-Shape.svg"
class CommandFromShape:
def GetResources(self):
return {'Pixmap' : 'Path-Shape',
'MenuText': QtCore.QT_TRANSLATE_NOOP("Path_FromShape","Path from a Shape"),
return {'Pixmap': 'Path-Shape',
'MenuText': QtCore.QT_TRANSLATE_NOOP("Path_FromShape", "Path from a Shape"),
'Accel': "P, S",
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Path_FromShape","Creates a Path from a wire/curve")}
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Path_FromShape", "Creates a Path from a wire/curve")}
def IsActive(self):
return not FreeCAD.ActiveDocument is None
return FreeCAD.ActiveDocument is not None
def Activated(self):
# check that the selection contains exactly what we want
selection = FreeCADGui.Selection.getSelection()
if len(selection) != 1:
FreeCAD.Console.PrintError(translate("Path_FromShape","Please select exactly one Part-based object\n"))
FreeCAD.Console.PrintError(
translate("Path_FromShape", "Please select exactly one Part-based object\n"))
return
if not(selection[0].isDerivedFrom("Part::Feature")):
FreeCAD.Console.PrintError(translate("Path_FromShape","Please select exactly one Part-based object\n"))
FreeCAD.Console.PrintError(
translate("Path_FromShape", "Please select exactly one Part-based object\n"))
return
FreeCAD.ActiveDocument.openTransaction(translate("Path_FromShape","Create path from shape"))
FreeCAD.ActiveDocument.openTransaction(
translate("Path_FromShape", "Create path from shape"))
FreeCADGui.addModule("PathScripts.PathUtils")
FreeCADGui.doCommand("obj = FreeCAD.activeDocument().addObject('Path::FeatureShape','PathShape')")
FreeCADGui.doCommand("obj.Shape = FreeCAD.activeDocument()."+selection[0].Name+".Shape")
FreeCADGui.doCommand('PathScripts.PathUtils.addToProject(obj)')
FreeCADGui.doCommand(
"obj = FreeCAD.activeDocument().addObject('Path::FeatureShape','PathShape')")
FreeCADGui.doCommand(
"obj.Shape = FreeCAD.activeDocument()." + selection[0].Name + ".Shape")
FreeCADGui.doCommand('PathScripts.PathUtils.addToJob(obj)')
FreeCAD.ActiveDocument.commitTransaction()
FreeCAD.ActiveDocument.recompute()
if FreeCAD.GuiUp:
if FreeCAD.GuiUp:
# register the FreeCAD command
FreeCADGui.addCommand('Path_FromShape',CommandFromShape())
FreeCADGui.addCommand('Path_FromShape', CommandFromShape())

View File

@@ -105,7 +105,11 @@ class CommandPathHop:
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Path_Hop", "Creates a Path Hop object")}
def IsActive(self):
return FreeCAD.ActiveDocument is not None
if FreeCAD.ActiveDocument is not None:
for o in FreeCAD.ActiveDocument.Objects:
if o.Name[:3] == "Job":
return True
return False
def Activated(self):
@@ -131,7 +135,7 @@ class CommandPathHop:
'PathScripts.PathHop.ViewProviderPathHop(obj.ViewObject)')
FreeCADGui.doCommand(
'obj.NextObject = FreeCAD.ActiveDocument.' + selection[0].Name)
FreeCADGui.doCommand('PathScripts.PathUtils.addToProject(obj)')
FreeCADGui.doCommand('PathScripts.PathUtils.addToJob(obj)')
FreeCAD.ActiveDocument.commitTransaction()
FreeCAD.ActiveDocument.recompute()

View File

@@ -1,34 +1,35 @@
#***************************************************************************
#* (c) Yorik van Havre (yorik@uncreated.net) 2015 *
#* *
#* This file is part of the FreeCAD CAx development system. *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
#* as published by the Free Software Foundation; either version 2 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENCE text file. *
#* *
#* FreeCAD 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 Lesser General Public License for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with FreeCAD; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#***************************************************************************/
# ***************************************************************************
# * (c) Yorik van Havre (yorik@uncreated.net) 2015 *
# * *
# * This file is part of the FreeCAD CAx development system. *
# * *
# * This program is free software; you can redistribute it and/or modify *
# * it under the terms of the GNU Lesser General Public License (LGPL) *
# * as published by the Free Software Foundation; either version 2 of *
# * the License, or (at your option) any later version. *
# * for detail see the LICENCE text file. *
# * *
# * FreeCAD 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 Lesser General Public License for more details. *
# * *
# * You should have received a copy of the GNU Library General Public *
# * License along with FreeCAD; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
# * USA *
# * *
# ***************************************************************************/
from PySide import QtCore, QtGui
import FreeCAD,FreeCADGui
import FreeCAD
import FreeCADGui
# Qt tanslation handling
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def translate(context, text, disambig=None):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
@@ -38,7 +39,6 @@ except AttributeError:
class OldHighlighter(QtGui.QSyntaxHighlighter):
def highlightBlock(self, text):
myClassFormat = QtGui.QTextCharFormat()
@@ -56,11 +56,10 @@ class OldHighlighter(QtGui.QSyntaxHighlighter):
class GCodeHighlighter(QtGui.QSyntaxHighlighter):
def __init__(self, parent=None):
def convertcolor(c):
return QtGui.QColor(int((c>>24)&0xFF),int((c>>16)&0xFF),int((c>>8)&0xFF))
return QtGui.QColor(int((c >> 24) & 0xFF), int((c >> 16) & 0xFF), int((c >> 8) & 0xFF))
super(GCodeHighlighter, self).__init__(parent)
p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Editor")
@@ -74,26 +73,29 @@ class GCodeHighlighter(QtGui.QSyntaxHighlighter):
if c:
colors.append(convertcolor(c))
else:
colors.append(QtGui.QColor(0,170,0))
colors.append(QtGui.QColor(0, 170, 0))
c = p.GetUnsigned("Define name")
if c:
colors.append(convertcolor(c))
else:
colors.append(QtGui.QColor(160,160,164))
colors.append(QtGui.QColor(160, 160, 164))
self.highlightingRules = []
numberFormat = QtGui.QTextCharFormat()
numberFormat.setForeground(colors[0])
self.highlightingRules.append((QtCore.QRegExp("[\\-0-9\\.]"),numberFormat))
self.highlightingRules.append(
(QtCore.QRegExp("[\\-0-9\\.]"), numberFormat))
keywordFormat = QtGui.QTextCharFormat()
keywordFormat.setForeground(colors[1])
keywordFormat.setFontWeight(QtGui.QFont.Bold)
keywordPatterns = ["\\bG[0-9]+\\b", "\\bM[0-9]+\\b"]
self.highlightingRules.extend([(QtCore.QRegExp(pattern), keywordFormat) for pattern in keywordPatterns])
self.highlightingRules.extend(
[(QtCore.QRegExp(pattern), keywordFormat) for pattern in keywordPatterns])
speedFormat = QtGui.QTextCharFormat()
speedFormat.setFontWeight(QtGui.QFont.Bold)
speedFormat.setForeground(colors[2])
self.highlightingRules.append((QtCore.QRegExp("\\bF[0-9\\.]+\\b"),speedFormat))
self.highlightingRules.append(
(QtCore.QRegExp("\\bF[0-9\\.]+\\b"), speedFormat))
def highlightBlock(self, text):
@@ -108,30 +110,29 @@ class GCodeHighlighter(QtGui.QSyntaxHighlighter):
class GCodeEditorDialog(QtGui.QDialog):
def __init__(self, parent=FreeCADGui.getMainWindow()):
def __init__(self, parent = FreeCADGui.getMainWindow()):
QtGui.QDialog.__init__(self,parent)
QtGui.QDialog.__init__(self, parent)
layout = QtGui.QVBoxLayout(self)
# nice text editor widget for editing the gcode
self.editor = QtGui.QTextEdit()
font = QtGui.QFont()
p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Editor")
font.setFamily(p.GetString("Font","Courier"))
font.setFamily(p.GetString("Font", "Courier"))
font.setFixedPitch(True)
font.setPointSize(p.GetInt("FontSize",10))
font.setPointSize(p.GetInt("FontSize", 10))
self.editor.setFont(font)
self.editor.setText("G01 X55 Y4.5 F300.0")
self.highlighter = GCodeHighlighter(self.editor.document())
layout.addWidget(self.editor)
# Note
lab = QtGui.QLabel()
lab.setText(translate("PathInspect","<b>Note</b>: Pressing OK will commit any change you make above to the object, but if the object is parametric, these changes will be overridden on recompute."))
lab.setText(translate("PathInspect", "<b>Note</b>: Pressing OK will commit any change you make above to the object, but if the object is parametric, these changes will be overridden on recompute."))
lab.setWordWrap(True)
layout.addWidget(lab)
# OK and Cancel buttons
self.buttons = QtGui.QDialogButtonBox(
QtGui.QDialogButtonBox.Ok | QtGui.QDialogButtonBox.Cancel,
@@ -142,15 +143,15 @@ class GCodeEditorDialog(QtGui.QDialog):
def show(obj):
"show(obj): shows the G-code data of the given Path object in a dialog"
if hasattr(obj,"Path"):
if obj.Path:
if hasattr(obj, "Path"):
if obj.Path:
dia = GCodeEditorDialog()
dia.editor.setText(obj.Path.toGCode())
result = dia.exec_()
# exec_() returns 0 or 1 depending on the button pressed (Ok or Cancel)
# exec_() returns 0 or 1 depending on the button pressed (Ok or
# Cancel)
if result:
import Path
p = Path.Path(dia.editor.toPlainText())
@@ -162,31 +163,36 @@ def show(obj):
class CommandPathInspect:
def GetResources(self):
return {'Pixmap' : 'Path-Inspect',
'MenuText': QtCore.QT_TRANSLATE_NOOP("Path_Inspect","Inspect G-code"),
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Path_Inspect","Inspects the G-code contents of a path")}
return {'Pixmap': 'Path-Inspect',
'MenuText': QtCore.QT_TRANSLATE_NOOP("Path_Inspect", "Inspect G-code"),
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Path_Inspect", "Inspects the G-code contents of a path")}
def IsActive(self):
return not FreeCAD.ActiveDocument is None
if FreeCAD.ActiveDocument is not None:
for o in FreeCAD.ActiveDocument.Objects:
if o.Name[:3] == "Job":
return True
return False
def Activated(self):
# check that the selection contains exactly what we want
selection = FreeCADGui.Selection.getSelection()
if len(selection) != 1:
FreeCAD.Console.PrintError(translate("Path_Inspect","Please select exactly one path object\n"))
FreeCAD.Console.PrintError(
translate("Path_Inspect", "Please select exactly one path object\n"))
return
if not(selection[0].isDerivedFrom("Path::Feature")):
FreeCAD.Console.PrintError(translate("Path_Inspect","Please select exactly one path object\n"))
FreeCAD.Console.PrintError(
translate("Path_Inspect", "Please select exactly one path object\n"))
return
# if everything is ok, execute
FreeCADGui.addModule("PathScripts.PathInspect")
FreeCADGui.doCommand('PathScripts.PathInspect.show(FreeCAD.ActiveDocument.' + selection[0].Name + ')')
FreeCADGui.doCommand(
'PathScripts.PathInspect.show(FreeCAD.ActiveDocument.' + selection[0].Name + ')')
if FreeCAD.GuiUp:
if FreeCAD.GuiUp:
# register the FreeCAD command
FreeCADGui.addCommand('Path_Inspect',CommandPathInspect())
FreeCADGui.addCommand('Path_Inspect', CommandPathInspect())

View File

@@ -0,0 +1,314 @@
# -*- coding: utf-8 -*-
# ***************************************************************************
# * *
# * Copyright (c) 2014 Yorik van Havre <yorik@uncreated.net> *
# * *
# * This program is free software; you can redistribute it and/or modify *
# * it under the terms of the GNU Lesser General Public License (LGPL) *
# * as published by the Free Software Foundation; either version 2 of *
# * the License, or (at your option) any later version. *
# * for detail see the LICENCE text file. *
# * *
# * 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 Library General Public License for more details. *
# * *
# * You should have received a copy of the GNU Library General Public *
# * License along with this program; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
# * USA *
# * *
# ***************************************************************************
import FreeCAD
import Path
from PySide import QtCore, QtGui
import os
import sys
import glob
import PathLoadTool
FreeCADGui = None
if FreeCAD.GuiUp:
import FreeCADGui
"""Path Job object and FreeCAD command"""
# Qt tanslation handling
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def translate(context, text, disambig=None):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def translate(context, text, disambig=None):
return QtGui.QApplication.translate(context, text, disambig)
class ObjectPathJob:
def __init__(self, obj):
path = FreeCAD.getHomePath() + ("Mod/Path/PathScripts/")
posts = glob.glob(path + '/*_post.py')
allposts = [ str(os.path.split(os.path.splitext(p)[0])[1][:-5]) for p in posts]
grp = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Macro")
path = grp.GetString("MacroPath", FreeCAD.getUserAppDataDir())
posts = glob.glob(path + '/*_post.py')
allposts.extend([ str(os.path.split(os.path.splitext(p)[0])[1][:-5]) for p in posts])
# obj.addProperty("App::PropertyFile", "PostProcessor", "CodeOutput", "Select the Post Processor file for this project")
obj.addProperty("App::PropertyFile", "OutputFile", "CodeOutput", QtCore.QT_TRANSLATE_NOOP("App::Property","The NC output file for this project"))
obj.setEditorMode("OutputFile", 0) # set to default mode
obj.addProperty("App::PropertyString", "Description", "Path", QtCore.QT_TRANSLATE_NOOP("App::Property","An optional description for this job"))
obj.addProperty("App::PropertyEnumeration", "PostProcessor", "Output", QtCore.QT_TRANSLATE_NOOP("App::Property","Select the Post Processor"))
obj.PostProcessor = allposts
obj.addProperty("App::PropertyString", "MachineName", "Output", QtCore.QT_TRANSLATE_NOOP("App::Property","Name of the Machine that will use the CNC program"))
obj.addProperty("Path::PropertyTooltable", "Tooltable", "Base", QtCore.QT_TRANSLATE_NOOP("App::Property","The tooltable used for this CNC program"))
obj.addProperty("App::PropertyEnumeration", "MachineUnits", "Output", QtCore.QT_TRANSLATE_NOOP("App::Property","Units that the machine works in, ie Metric or Inch"))
obj.MachineUnits = ['Metric', 'Inch']
obj.addProperty("App::PropertyDistance", "X_Max", "Limits", QtCore.QT_TRANSLATE_NOOP("App::Property","The Maximum distance in X the machine can travel"))
obj.addProperty("App::PropertyDistance", "Y_Max", "Limits", QtCore.QT_TRANSLATE_NOOP("App::Property","The Maximum distance in X the machine can travel"))
obj.addProperty("App::PropertyDistance", "Z_Max", "Limits", QtCore.QT_TRANSLATE_NOOP("App::Property","The Maximum distance in X the machine can travel"))
obj.addProperty("App::PropertyDistance", "X_Min", "Limits", QtCore.QT_TRANSLATE_NOOP("App::Property","The Minimum distance in X the machine can travel"))
obj.addProperty("App::PropertyDistance", "Y_Min", "Limits", QtCore.QT_TRANSLATE_NOOP("App::Property","The Minimum distance in X the machine can travel"))
obj.addProperty("App::PropertyDistance", "Z_Min", "Limits", QtCore.QT_TRANSLATE_NOOP("App::Property","The Minimum distance in X the machine can travel"))
obj.Proxy = self
if FreeCAD.GuiUp:
ViewProviderJob(obj.ViewObject)
def __getstate__(self):
return None
def __setstate__(self, state):
return None
def onChanged(self, obj, prop):
mode = 2
obj.setEditorMode('Placement', mode)
if prop == "PostProcessor":
postname = obj.PostProcessor + "_post"
exec "import %s as current_post" % postname
if hasattr(current_post, "UNITS"):
if current_post.UNITS == "G21":
obj.MachineUnits = "Metric"
else:
obj.MachineUnits = "Inch"
if hasattr(current_post, "MACHINE_NAME"):
obj.MachineName = current_post.MACHINE_NAME
if hasattr(current_post, "CORNER_MAX"):
obj.X_Max = current_post.CORNER_MAX['x']
obj.Y_Max = current_post.CORNER_MAX['y']
obj.Z_Max = current_post.CORNER_MAX['z']
if hasattr(current_post, "CORNER_MIN"):
obj.X_Min = current_post.CORNER_MIN['x']
obj.Y_Min = current_post.CORNER_MIN['y']
obj.Z_Min = current_post.CORNER_MIN['z']
def getToolControllers(self, obj):
'''returns a list of ToolControllers for the current job'''
controllers = []
for o in obj.Group:
if "Proxy" in o.PropertiesList:
if isinstance(o.Proxy, PathLoadTool.LoadTool):
controllers.append (o.Name)
return controllers
def execute(self, obj):
cmds = []
for child in obj.Group:
if child.isDerivedFrom("Path::Feature"):
if obj.UsePlacements:
for c in child.Path.Commands:
cmds.append(c.transform(child.Placement))
else:
cmds.extend(child.Path.Commands)
if cmds:
path = Path.Path(cmds)
obj.Path = path
class ViewProviderJob:
def __init__(self, vobj):
vobj.Proxy = self
mode = 2
vobj.setEditorMode('BoundingBox', mode)
vobj.setEditorMode('DisplayMode', mode)
vobj.setEditorMode('Selectable', mode)
vobj.setEditorMode('ShapeColor', mode)
vobj.setEditorMode('Transparency', mode)
def __getstate__(self): # mandatory
return None
def __setstate__(self, state): # mandatory
return None
def setEdit(self, vobj, mode=0):
FreeCADGui.Control.closeDialog()
taskd = TaskPanel()
taskd.obj = vobj.Object
FreeCADGui.Control.showDialog(taskd)
taskd.setupUi()
return True
def getIcon(self):
return ":/icons/Path-Job.svg"
def onChanged(self, vobj, prop):
mode = 2
vobj.setEditorMode('BoundingBox', mode)
vobj.setEditorMode('DisplayMode', mode)
vobj.setEditorMode('Selectable', mode)
vobj.setEditorMode('ShapeColor', mode)
vobj.setEditorMode('Transparency', mode)
class CommandJob:
def GetResources(self):
return {'Pixmap': 'Path-Job',
'MenuText': QtCore.QT_TRANSLATE_NOOP("Path_Job", "Job"),
'Accel': "P, P",
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Path_Job", "Creates a Path Job object")}
def IsActive(self):
return FreeCAD.ActiveDocument is not None
def Activated(self):
CommandJob.Create()
FreeCAD.ActiveDocument.recompute()
@staticmethod
def Create():
FreeCAD.ActiveDocument.openTransaction(translate("Path_Job", "Create Job"))
FreeCADGui.addModule('PathScripts.PathUtils')
FreeCADGui.addModule('PathScripts.PathLoadTool')
FreeCADGui.doCommand('obj = FreeCAD.ActiveDocument.addObject("Path::FeatureCompoundPython", "Job")')
FreeCADGui.doCommand('PathScripts.PathJob.ObjectPathJob(obj)')
FreeCADGui.doCommand('PathScripts.PathLoadTool.CommandPathLoadTool.Create(obj.Name)')
FreeCADGui.doCommand('obj.ViewObject.startEditing()')
# FreeCADGui.doCommand('tool = Path.Tool()')
# FreeCADGui.doCommand('tool')
# FreeCADGui.doCommand('tool.Diameter = 5.0')
# FreeCADGui.doCommand('tool.Name = "Default Tool"')
# FreeCADGui.doCommand('tool.cuttingEdgeHeight = 15.0')
# FreeCADGui.doCommand('tool.ToolType = "EndMill"')
# FreeCADGui.doCommand('tool.Material = "HighSpeedSteel"')
# FreeCADGui.doCommand('obj.ToolTable.addTools(tool)')
FreeCAD.ActiveDocument.commitTransaction()
class TaskPanel:
def __init__(self):
#self.form = FreeCADGui.PySideUic.loadUi(":/panels/JobEdit.ui")
self.form = FreeCADGui.PySideUic.loadUi(FreeCAD.getHomePath() + "Mod/Path/JobEdit.ui")
path = FreeCAD.getHomePath() + ("Mod/Path/PathScripts/")
posts = glob.glob(path + '/*_post.py')
allposts = [ str(os.path.split(os.path.splitext(p)[0])[1][:-5]) for p in posts]
grp = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Macro")
path = grp.GetString("MacroPath", FreeCAD.getUserAppDataDir())
posts = glob.glob(path + '/*_post.py')
allposts.extend([ str(os.path.split(os.path.splitext(p)[0])[1][:-5]) for p in posts])
for post in allposts:
self.form.cboPostProcessor.addItem(post)
self.updating = False
def accept(self):
self.getFields()
FreeCADGui.ActiveDocument.resetEdit()
FreeCADGui.Control.closeDialog()
FreeCAD.ActiveDocument.recompute()
def reject(self):
FreeCADGui.Control.closeDialog()
FreeCAD.ActiveDocument.recompute()
def getFields(self):
if self.obj:
if hasattr(self.obj, "PostProcessor"):
self.obj.PostProcessor = str(self.form.cboPostProcessor.currentText())
if hasattr(self.obj, "Label"):
self.obj.Label = str(self.form.leLabel.text())
if hasattr(self.obj, "OutputFile"):
self.obj.OutputFile = str(self.form.leOutputFile.text())
oldlist = self.obj.Group
newlist = []
for index in xrange(self.form.PathsList.count()):
item = self.form.PathsList.item(index)
for olditem in oldlist:
if olditem.Name == item.text():
newlist.append(olditem)
self.obj.Group = newlist
self.obj.Proxy.execute(self.obj)
def setFields(self):
self.form.leLabel.setText(self.obj.Label)
self.form.leOutputFile.setText(self.obj.OutputFile)
index = self.form.cboPostProcessor.findText(
self.obj.PostProcessor, QtCore.Qt.MatchFixedString)
if index >= 0:
self.form.cboPostProcessor.setCurrentIndex(index)
for child in self.obj.Group:
self.form.PathsList.addItem(child.Name)
def open(self):
pass
def setFile(self):
filename = QtGui.QFileDialog.getSaveFileName(self.form, translate("PathJob", "Select Output File", None), None, translate("Path Job", "All Files (*.*)", None))
if filename:
self.obj.OutputFile = str(filename[0])
self.setFields()
def getStandardButtons(self):
return int(QtGui.QDialogButtonBox.Ok)
def setupUi(self):
# Connect Signals and Slots
self.form.cboPostProcessor.currentIndexChanged.connect(self.getFields)
self.form.leOutputFile.editingFinished.connect(self.getFields)
self.form.leLabel.editingFinished.connect(self.getFields)
self.form.btnSelectFile.clicked.connect(self.setFile)
self.form.PathsList.indexesMoved.connect(self.getFields)
self.setFields()
if FreeCAD.GuiUp:
# register the FreeCAD command
FreeCADGui.addCommand('Path_Job', CommandJob())
FreeCAD.Console.PrintLog("Loading PathJob... done\n")

View File

@@ -25,12 +25,9 @@
import FreeCAD
import FreeCADGui
import Path
# import PathGui
import PathScripts
import PathUtils
import Part
# from PathScripts import PathProject
import PathScripts
from PySide import QtCore, QtGui
# Qt tanslation handling
@@ -76,16 +73,15 @@ class LoadTool():
else:
commands += 'M4S' + str(obj.SpindleSpeed) + '\n'
obj.Path = Path.Path(commands)
def onChanged(self, obj, prop):
mode = 2
obj.setEditorMode('Placement', mode)
# if prop == "ToolNumber":
proj = PathUtils.findProj()
for g in proj.Group:
if not(isinstance(g.Proxy, PathScripts.PathLoadTool.LoadTool)):
g.touch()
job = PathUtils.findParentJob(obj)
if job is not None:
for g in job.Group:
if not(isinstance(g.Proxy, PathScripts.PathLoadTool.LoadTool)):
g.touch()
class _ViewProviderLoadTool:
@@ -147,12 +143,16 @@ class _ViewProviderLoadTool:
class CommandPathLoadTool:
def GetResources(self):
return {'Pixmap': 'Path-LoadTool',
'MenuText': QtCore.QT_TRANSLATE_NOOP("Path_LoadTool", "Add Tool Controller to the Project"),
'MenuText': QtCore.QT_TRANSLATE_NOOP("Path_LoadTool", "Add Tool Controller to the Job"),
'Accel': "P, T",
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Path_LoadTool", "Add Tool Controller")}
def IsActive(self):
return FreeCAD.ActiveDocument is not None
if FreeCAD.ActiveDocument is not None:
for o in FreeCAD.ActiveDocument.Objects:
if o.Name[:3] == "Job":
return True
return False
def Activated(self):
FreeCAD.ActiveDocument.openTransaction(translate("Path_LoadTool", "Create Tool Controller Object"))
@@ -164,16 +164,14 @@ obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython","TC")
PathScripts.PathLoadTool.LoadTool(obj)
PathScripts.PathLoadTool._ViewProviderLoadTool(obj.ViewObject)
PathUtils.addToProject(obj)
PathUtils.addToJob(obj)
'''
FreeCADGui.doCommand(snippet)
FreeCAD.ActiveDocument.commitTransaction()
FreeCAD.ActiveDocument.recompute()
@staticmethod
def Create():
# FreeCADGui.addModule("PathScripts.PathLoadTool")
# import Path
def Create(jobname = None):
import PathScripts
import PathUtils
@@ -181,7 +179,7 @@ PathUtils.addToProject(obj)
PathScripts.PathLoadTool.LoadTool(obj)
PathScripts.PathLoadTool._ViewProviderLoadTool(obj.ViewObject)
PathUtils.addToProject(obj)
PathUtils.addToJob(obj, jobname)
class TaskPanel:
@@ -205,6 +203,8 @@ class TaskPanel:
def reject(self):
FreeCADGui.Control.closeDialog()
if self.toolrep is not None:
FreeCAD.ActiveDocument.removeObject(self.toolrep.Name)
FreeCAD.ActiveDocument.recompute()
FreeCADGui.Selection.removeObserver(self.s)
@@ -221,11 +221,12 @@ class TaskPanel:
self.obj.SpindleSpeed = self.form.spindleSpeed.value()
if hasattr(self.obj, "SpindleDir"):
self.obj.SpindleDir = str(self.form.cboSpindleDirection.currentText())
#if hasattr(self.obj, "ToolNumber"):
# self.obj.ToolNumber = self.form.ToolNumber.value()
self.obj.Proxy.execute(self.obj)
def setFields(self):
self.form.cboToolSelect.blockSignals(True)
self.form.vertFeed.setText(str(self.obj.VertFeed.Value))
self.form.horizFeed.setText(str(self.obj.HorizFeed.Value))
self.form.spindleSpeed.setValue(self.obj.SpindleSpeed)
@@ -234,20 +235,45 @@ class TaskPanel:
index = self.form.cboSpindleDirection.findText(self.obj.SpindleDir, QtCore.Qt.MatchFixedString)
if index >= 0:
self.form.cboSpindleDirection.setCurrentIndex(index)
# Populate the tool list
mach = PathUtils.findMachine()
myJob = PathUtils.findParentJob(self.obj)
#populate the toolselector and select correct tool
self.form.cboToolSelect.clear()
tooltable = myJob.Tooltable
for number, tool in tooltable.Tools.iteritems():
self.form.cboToolSelect.addItem(tool.Name)
try:
tool = mach.Tooltable.Tools[self.obj.ToolNumber]
self.form.txtToolName.setText(tool.Name)
tool = myJob.Tooltable.Tools[self.obj.ToolNumber]
self.form.txtToolType.setText(tool.ToolType)
self.form.txtToolMaterial.setText(tool.Material)
self.form.txtToolDiameter.setText(str(tool.Diameter))
index = self.form.cboToolSelect.findText(tool.Name, QtCore.Qt.MatchFixedString)
if index >= 0:
self.form.cboToolSelect.setCurrentIndex(index)
except:
self.form.txtToolName.setText("UNDEFINED")
self.form.cboToolSelect.setCurrentIndex(-1)
self.form.txtToolType.setText("UNDEFINED")
self.form.txtToolMaterial.setText("UNDEFINED")
self.form.txtToolDiameter.setText("UNDEFINED")
self.form.cboToolSelect.blockSignals(False)
radius = tool.Diameter / 2
length = tool.CuttingEdgeHeight
t = Part.makeCylinder(radius, length)
self.toolrep.Shape = t
def changeTool(self):
myJob = PathUtils.findParentJob(self.obj)
newtool = self.form.cboToolSelect.currentText()
tooltable = myJob.Tooltable
for number, tool in tooltable.Tools.iteritems():
if tool.Name == newtool:
self.obj.ToolNumber = number
self.setFields()
def open(self):
self.s = SelObserver()
@@ -267,17 +293,19 @@ class TaskPanel:
FreeCAD.ActiveDocument.recompute()
def setupUi(self):
# setup the form fields
self.setFields()
self.form.cboToolSelect.currentIndexChanged.connect(self.changeTool)
self.form.tcoName.editingFinished.connect(self.getFields)
# build the tool representation
if self.form.txtToolDiameter.text() != "UNDEFINED":
radius = float(self.form.txtToolDiameter.text()) / 2
length = radius * 8
t = Part.makeCylinder(radius, length)
if self.obj.ToolNumber != 0:
t = Part.makeCylinder(1, 1)
self.toolrep = FreeCAD.ActiveDocument.addObject("Part::Feature", "tool")
self.toolrep.Shape = t
# setup the form fields
self.setFields()
class SelObserver:
def __init__(self):
pass

View File

@@ -1,254 +0,0 @@
# -*- coding: utf-8 -*-
# ***************************************************************************
# * *
# * Copyright (c) 2015 Dan Falck <ddfalck@gmail.com> *
# * *
# * This program is free software; you can redistribute it and/or modify *
# * it under the terms of the GNU Lesser General Public License (LGPL) *
# * as published by the Free Software Foundation; either version 2 of *
# * the License, or (at your option) any later version. *
# * for detail see the LICENCE text file. *
# * *
# * 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 Library General Public License for more details. *
# * *
# * You should have received a copy of the GNU Library General Public *
# * License along with this program; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
# * USA *
# * *
# ***************************************************************************
''' A CNC machine object to define how code is posted '''
import FreeCAD
import Path
import PathScripts
from PathScripts import PathUtils
from PySide import QtCore, QtGui
import os
import sys
# Qt tanslation handling
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def translate(context, text, disambig=None):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def translate(context, text, disambig=None):
return QtGui.QApplication.translate(context, text, disambig)
class Machine:
def __init__(self, obj):
obj.addProperty("App::PropertyString", "MachineName", "Base", QtCore.QT_TRANSLATE_NOOP("App::Property","Name of the Machine that will use the CNC program"))
obj.addProperty("App::PropertyFile", "PostProcessor", "CodeOutput", QtCore.QT_TRANSLATE_NOOP("App::Property","Select the Post Processor file for this machine"))
obj.addProperty("App::PropertyEnumeration", "MachineUnits", "CodeOutput", QtCore.QT_TRANSLATE_NOOP("App::Property","Units that the machine works in, ie Metric or Inch"))
obj.MachineUnits = ['Metric', 'Inch']
obj.addProperty("Path::PropertyTooltable", "Tooltable", "Base", QtCore.QT_TRANSLATE_NOOP("App::Property","The tooltable used for this CNC program"))
obj.addProperty("App::PropertyDistance", "X_Max", "Limits", QtCore.QT_TRANSLATE_NOOP("App::Property","The Maximum distance in X the machine can travel"))
obj.addProperty("App::PropertyDistance", "Y_Max", "Limits", QtCore.QT_TRANSLATE_NOOP("App::Property","The Maximum distance in Y the machine can travel"))
obj.addProperty("App::PropertyDistance", "Z_Max", "Limits", QtCore.QT_TRANSLATE_NOOP("App::Property","The Maximum distance in Z the machine can travel"))
obj.addProperty("App::PropertyDistance", "X_Min", "Limits", QtCore.QT_TRANSLATE_NOOP("App::Property","The Minimum distance in X the machine can travel"))
obj.addProperty("App::PropertyDistance", "Y_Min", "Limits", QtCore.QT_TRANSLATE_NOOP("App::Property","The Minimum distance in Y the machine can travel"))
obj.addProperty("App::PropertyDistance", "Z_Min", "Limits", QtCore.QT_TRANSLATE_NOOP("App::Property","The Minimum distance in Z the machine can travel"))
obj.addProperty("App::PropertyDistance", "X", "HomePosition", QtCore.QT_TRANSLATE_NOOP("App::Property","Home position of machine, in X (mainly for visualization)"))
obj.addProperty("App::PropertyDistance", "Y", "HomePosition", QtCore.QT_TRANSLATE_NOOP("App::Property","Home position of machine, in Y (mainly for visualization)"))
obj.addProperty("App::PropertyDistance", "Z", "HomePosition", QtCore.QT_TRANSLATE_NOOP("App::Property","Home position of machine, in Z (mainly for visualization)"))
obj.Proxy = self
mode = 2
obj.setEditorMode('Placement', mode)
def execute(self, obj):
obj.Label = "Machine_" + str(obj.MachineName)
# need to filter this path out in post- only for visualization
#gcode = 'G0 X' + str(obj.X.Value) + ' Y' + \
# str(obj.Y.Value) + ' Z' + str(obj.Z.Value)
gcode = ""
gcode += '(' + str(obj.Label) + ')'
obj.Path = Path.Path(gcode)
def onChanged(self, obj, prop):
mode = 2
obj.setEditorMode('Placement', mode)
if prop == "PostProcessor":
sys.path.append(os.path.split(obj.PostProcessor)[0])
lessextn = os.path.splitext(obj.PostProcessor)[0]
postname = os.path.split(lessextn)[1]
exec "import %s as current_post" % postname
if hasattr(current_post, "UNITS"):
if current_post.UNITS == "G21":
obj.MachineUnits = "Metric"
else:
obj.MachineUnits = "Inch"
if hasattr(current_post, "MACHINE_NAME"):
obj.MachineName = current_post.MACHINE_NAME
if hasattr(current_post, "CORNER_MAX"):
obj.X_Max = current_post.CORNER_MAX['x']
obj.Y_Max = current_post.CORNER_MAX['y']
obj.Z_Max = current_post.CORNER_MAX['z']
if hasattr(current_post, "CORNER_MIN"):
obj.X_Min = current_post.CORNER_MIN['x']
obj.Y_Min = current_post.CORNER_MIN['y']
obj.Z_Min = current_post.CORNER_MIN['z']
if prop == "Tooltable":
proj = PathUtils.findProj()
for g in proj.Group:
if not(isinstance(g.Proxy, PathScripts.PathMachine.Machine)):
g.touch()
class _ViewProviderMachine:
def __init__(self, vobj):
vobj.Proxy = self
vobj.addProperty("App::PropertyBool", "ShowLimits", "Path",
QtCore.QT_TRANSLATE_NOOP("App::Property", "Switch the machine max and minimum travel bounding box on/off"))
mode = 2
vobj.setEditorMode('LineWidth', mode)
vobj.setEditorMode('MarkerColor', mode)
vobj.setEditorMode('NormalColor', mode)
vobj.setEditorMode('ShowFirstRapid', 0)
vobj.setEditorMode('DisplayMode', mode)
vobj.setEditorMode('BoundingBox', mode)
vobj.setEditorMode('Selectable', mode)
def __getstate__(self): # mandatory
return None
def __setstate__(self, state): # mandatory
return None
def getIcon(self): # optional
return ":/icons/Path-Machine.svg"
def attach(self, vobj):
from pivy import coin
self.extentsBox = coin.SoSeparator()
vobj.RootNode.addChild(self.extentsBox)
def onChanged(self, vobj, prop):
if prop == "ShowLimits":
self.extentsBox.removeAllChildren()
if vobj.ShowLimits and hasattr(vobj, "Object"):
from pivy import coin
parent = coin.SoType.fromName(
"SoSkipBoundingGroup").createInstance()
self.extentsBox.addChild(parent)
# set pattern
pattern = FreeCAD.ParamGet(
"User parameter:BaseApp/Preferences/Mod/Part").GetInt("GridLinePattern", 0x0f0f)
defStyle = coin.SoDrawStyle()
defStyle.lineWidth = 1
defStyle.linePattern = pattern
parent.addChild(defStyle)
# set color
c = FreeCAD.ParamGet(
"User parameter:BaseApp/Preferences/Mod/Path").GetUnsigned("DefaultExtentsColor", 3418866943)
r = float((c >> 24) & 0xFF) / 255.0
g = float((c >> 16) & 0xFF) / 255.0
b = float((c >> 8) & 0xFF) / 255.0
color = coin.SoBaseColor()
parent.addChild(color)
# set boundbox
extents = coin.SoType.fromName(
"SoFCBoundingBox").createInstance()
extents.coordsOn.setValue(False)
extents.dimensionsOn.setValue(False)
XMax, YMax, ZMax = vobj.Object.X_Max.Value, vobj.Object.Y_Max.Value, vobj.Object.Z_Max.Value
XMin, YMin, ZMin = vobj.Object.X_Min.Value, vobj.Object.Y_Min.Value, vobj.Object.Z_Min.Value
# UnitParams = FreeCAD.ParamGet(
# "User parameter:BaseApp/Preferences/Units")
extents.minBounds.setValue(XMax, YMax, ZMax)
extents.maxBounds.setValue(XMin, YMin, ZMin)
parent.addChild(extents)
mode = 2
vobj.setEditorMode('LineWidth', mode)
vobj.setEditorMode('MarkerColor', mode)
vobj.setEditorMode('NormalColor', mode)
vobj.setEditorMode('ShowFirstRapid', 0)
vobj.setEditorMode('DisplayMode', mode)
vobj.setEditorMode('BoundingBox', mode)
vobj.setEditorMode('Selectable', mode)
def updateData(self, vobj, prop): # optional
# this is executed when a property of the APP OBJECT changes
pass
def setEdit(self, vobj, mode=0): # optional
return True
def unsetEdit(self, vobj, mode=0): # optional
# this is executed when the user cancels or terminates edit mode
pass
def doubleClicked(self, vobj):
from PathScripts import TooltableEditor
TooltableEditor.edit(vobj.Object.Name)
class CommandPathMachine:
def GetResources(self):
return {'Pixmap': 'Path-Machine',
'MenuText': QtCore.QT_TRANSLATE_NOOP("PathMachine", "Machine Object"),
'Accel': "P, M",
'ToolTip': QtCore.QT_TRANSLATE_NOOP("PathMachine", "Create a Machine object")}
def IsActive(self):
return FreeCAD.ActiveDocument is not None
def Activated(self):
FreeCAD.ActiveDocument.openTransaction(
translate("PathMachine", "Create a Machine object"))
CommandPathMachine.Create()
FreeCAD.ActiveDocument.commitTransaction()
FreeCAD.ActiveDocument.recompute()
@staticmethod
def Create():
obj = FreeCAD.ActiveDocument.addObject(
"Path::FeaturePython", "Machine")
Machine(obj)
_ViewProviderMachine(obj.ViewObject)
PathUtils.addToProject(obj)
UnitParams = FreeCAD.ParamGet(
"User parameter:BaseApp/Preferences/Units")
if UnitParams.GetInt('UserSchema') == 0:
obj.MachineUnits = 'Metric'
# metric mode
else:
obj.MachineUnits = 'Inch'
obj.ViewObject.ShowFirstRapid = False
return obj
if FreeCAD.GuiUp:
# register the FreeCAD command
import FreeCADGui
FreeCADGui.addCommand('Path_Machine', CommandPathMachine())
FreeCAD.Console.PrintLog("Loading PathMachine... done\n")

View File

@@ -1,41 +1,44 @@
# -*- coding: utf-8 -*-
#***************************************************************************
#* *
#* Copyright (c) 2015 Dan Falck <ddfalck@gmail.com> *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
#* as published by the Free Software Foundation; either version 2 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENCE text file. *
#* *
#* 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 Library General Public License for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with this program; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#***************************************************************************
# ***************************************************************************
# * *
# * Copyright (c) 2015 Dan Falck <ddfalck@gmail.com> *
# * *
# * This program is free software; you can redistribute it and/or modify *
# * it under the terms of the GNU Lesser General Public License (LGPL) *
# * as published by the Free Software Foundation; either version 2 of *
# * the License, or (at your option) any later version. *
# * for detail see the LICENCE text file. *
# * *
# * 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 Library General Public License for more details. *
# * *
# * You should have received a copy of the GNU Library General Public *
# * License along with this program; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
# * USA *
# * *
# ***************************************************************************
''' Used for CNC machine plane selection G17,G18,G19 '''
import FreeCAD,FreeCADGui,Path,PathGui
from PathScripts import PathProject
from PySide import QtCore,QtGui
import FreeCAD
import FreeCADGui
import Path
from PySide import QtCore, QtGui
# Qt tanslation handling
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def translate(context, text, disambig=None):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def translate(context, text, disambig=None):
return QtGui.QApplication.translate(context, text, disambig)
class Plane:
def __init__(self,obj):
obj.addProperty("App::PropertyEnumeration", "SelectionPlane","Path",QtCore.QT_TRANSLATE_NOOP("App::Property","Orientation plane of CNC path"))
@@ -43,13 +46,12 @@ class Plane:
obj.addProperty("App::PropertyBool","Active","Path",QtCore.QT_TRANSLATE_NOOP("App::Property","Make False, to prevent operation from generating code"))
obj.Proxy = self
def execute(self,obj):
def execute(self, obj):
clonelist = ['XY', 'XZ', 'YZ']
cindx = clonelist.index(str(obj.SelectionPlane))
pathlist = ['G17', 'G18', 'G19']
# obj.Path = Path.Path(pathlist[cindx])
labelindx = clonelist.index(obj.SelectionPlane)+1
obj.Label = "Plane"+str(labelindx)
labelindx = clonelist.index(obj.SelectionPlane) + 1
obj.Label = "Plane" + str(labelindx)
if obj.Active:
obj.Path = Path.Path(pathlist[cindx])
obj.ViewObject.Visibility = True
@@ -59,67 +61,74 @@ class Plane:
class _ViewProviderPlane:
def __init__(self,vobj): #mandatory
def __init__(self, vobj): # mandatory
vobj.Proxy = self
mode = 2
vobj.setEditorMode('LineWidth',mode)
vobj.setEditorMode('MarkerColor',mode)
vobj.setEditorMode('NormalColor',mode)
vobj.setEditorMode('ShowFirstRapid',mode)
vobj.setEditorMode('DisplayMode',mode)
vobj.setEditorMode('BoundingBox',mode)
vobj.setEditorMode('Selectable',mode)
vobj.setEditorMode('ShapeColor',mode)
vobj.setEditorMode('Transparency',mode)
vobj.setEditorMode('Visibility',mode)
vobj.setEditorMode('LineWidth', mode)
vobj.setEditorMode('MarkerColor', mode)
vobj.setEditorMode('NormalColor', mode)
vobj.setEditorMode('ShowFirstRapid', mode)
vobj.setEditorMode('DisplayMode', mode)
vobj.setEditorMode('BoundingBox', mode)
vobj.setEditorMode('Selectable', mode)
vobj.setEditorMode('ShapeColor', mode)
vobj.setEditorMode('Transparency', mode)
vobj.setEditorMode('Visibility', mode)
def __getstate__(self): #mandatory
def __getstate__(self): # mandatory
return None
def __setstate__(self,state): #mandatory
def __setstate__(self, state): # mandatory
return None
def getIcon(self): #optional
def getIcon(self): # optional
return ":/icons/Path-Plane.svg"
def onChanged(self,vobj,prop): #optional
def onChanged(self, vobj, prop): # optional
mode = 2
vobj.setEditorMode('LineWidth',mode)
vobj.setEditorMode('MarkerColor',mode)
vobj.setEditorMode('NormalColor',mode)
vobj.setEditorMode('ShowFirstRapid',mode)
vobj.setEditorMode('DisplayMode',mode)
vobj.setEditorMode('BoundingBox',mode)
vobj.setEditorMode('Selectable',mode)
vobj.setEditorMode('ShapeColor',mode)
vobj.setEditorMode('Transparency',mode)
vobj.setEditorMode('Visibility',mode)
vobj.setEditorMode('LineWidth', mode)
vobj.setEditorMode('MarkerColor', mode)
vobj.setEditorMode('NormalColor', mode)
vobj.setEditorMode('ShowFirstRapid', mode)
vobj.setEditorMode('DisplayMode', mode)
vobj.setEditorMode('BoundingBox', mode)
vobj.setEditorMode('Selectable', mode)
vobj.setEditorMode('ShapeColor', mode)
vobj.setEditorMode('Transparency', mode)
vobj.setEditorMode('Visibility', mode)
def updateData(self,vobj,prop): #optional
def updateData(self, vobj, prop): # optional
# this is executed when a property of the APP OBJECT changes
pass
def setEdit(self,vobj,mode): #optional
def setEdit(self, vobj, mode): # optional
# this is executed when the object is double-clicked in the tree
pass
def unsetEdit(self,vobj,mode): #optional
def unsetEdit(self, vobj, mode): # optional
# this is executed when the user cancels or terminates edit mode
pass
class CommandPathPlane:
def GetResources(self):
return {'Pixmap' : 'Path-Plane',
'MenuText': QtCore.QT_TRANSLATE_NOOP("Path_Plane","Selection Plane"),
return {'Pixmap': 'Path-Plane',
'MenuText': QtCore.QT_TRANSLATE_NOOP("Path_Plane", "Selection Plane"),
'Accel': "P, P",
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Path_Plane","Create a Selection Plane object")}
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Path_Plane", "Create a Selection Plane object")}
def IsActive(self):
return not FreeCAD.ActiveDocument is None
if FreeCAD.ActiveDocument is not None:
for o in FreeCAD.ActiveDocument.Objects:
if o.Name[:3] == "Job":
return True
return False
def Activated(self):
FreeCAD.ActiveDocument.openTransaction(translate("Path_Plane","Create a Selection Plane object"))
FreeCAD.ActiveDocument.openTransaction(
translate("Path_Plane", "Create a Selection Plane object"))
FreeCADGui.addModule("PathScripts.PathPlane")
snippet = '''
import Path
@@ -130,7 +139,7 @@ obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython","Plane")
PathScripts.PathPlane.Plane(obj)
obj.Active = True
PathScripts.PathPlane._ViewProviderPlane(obj.ViewObject)
PathUtils.addToProject(obj)
PathUtils.addToJob(obj)
'''
@@ -138,11 +147,9 @@ PathUtils.addToProject(obj)
FreeCAD.ActiveDocument.commitTransaction()
FreeCAD.ActiveDocument.recompute()
if FreeCAD.GuiUp:
if FreeCAD.GuiUp:
# register the FreeCAD command
FreeCADGui.addCommand('Path_Plane',CommandPathPlane())
FreeCADGui.addCommand('Path_Plane', CommandPathPlane())
FreeCAD.Console.PrintLog("Loading PathPlane... done\n")

View File

@@ -516,7 +516,7 @@ class CommandPathPocket:
FreeCADGui.doCommand('obj.RampAngle = 3.0')
FreeCADGui.doCommand('obj.RampSize = 0.75')
FreeCADGui.doCommand('obj.HelixSize = 0.75')
FreeCADGui.doCommand('PathScripts.PathUtils.addToProject(obj)')
FreeCADGui.doCommand('PathScripts.PathUtils.addToJob(obj)')
FreeCAD.ActiveDocument.commitTransaction()
FreeCAD.ActiveDocument.recompute()

View File

@@ -1,37 +1,38 @@
# -*- coding: utf-8 -*-
#***************************************************************************
#* *
#* Copyright (c) 2015 Dan Falck <ddfalck@gmail.com> *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
#* as published by the Free Software Foundation; either version 2 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENCE text file. *
#* *
#* 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 Library General Public License for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with this program; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#***************************************************************************
''' Post Process command that will make use of the Output File and Post Processor entries in PathProject '''
import FreeCAD, FreeCADGui
import Path, PathScripts,PathGui
from PathScripts import PostUtils
from PathScripts import PathProject
import os,sys
from PySide import QtCore,QtGui
# ***************************************************************************
# * *
# * Copyright (c) 2015 Dan Falck <ddfalck@gmail.com> *
# * *
# * This program is free software; you can redistribute it and/or modify *
# * it under the terms of the GNU Lesser General Public License (LGPL) *
# * as published by the Free Software Foundation; either version 2 of *
# * the License, or (at your option) any later version. *
# * for detail see the LICENCE text file. *
# * *
# * 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 Library General Public License for more details. *
# * *
# * You should have received a copy of the GNU Library General Public *
# * License along with this program; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
# * USA *
# * *
# ***************************************************************************
''' Post Process command that will make use of the Output File and Post Processor entries in PathJob '''
import FreeCAD
import FreeCADGui
import PathScripts
import os
import sys
from PySide import QtCore, QtGui
# Qt tanslation handling
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def translate(context, text, disambig=None):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
@@ -40,51 +41,66 @@ except AttributeError:
class CommandPathPost:
def GetResources(self):
return {'Pixmap' : 'Path-Post',
'MenuText': QtCore.QT_TRANSLATE_NOOP("Path_Post","Post Process"),
return {'Pixmap': 'Path-Post',
'MenuText': QtCore.QT_TRANSLATE_NOOP("Path_Post", "Post Process"),
'Accel': "P, P",
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Path_Post","Post Process the selected Project")}
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Path_Post", "Post Process the selected Job")}
def IsActive(self):
return not FreeCAD.ActiveDocument is None
if FreeCAD.ActiveDocument is not None:
for o in FreeCAD.ActiveDocument.Objects:
if o.Name[:3] == "Job":
return True
return False
def Activated(self):
FreeCAD.ActiveDocument.openTransaction(translate("Path_Post","Post Process the Selected path(s)"))
FreeCAD.ActiveDocument.openTransaction(
translate("Path_Post", "Post Process the Selected path(s)"))
FreeCADGui.addModule("PathScripts.PathPost")
#select the PathProject that you want to post output from
# select the Path Job that you want to post output from
obj = FreeCADGui.Selection.getSelection()
#default to the dumper post and default .tap file
postname = "dumper_post"
# default to the dumper post and default .tap file
postname = "dumper"
filename = "tmp.tap"
#check if the user has a project and has set the default post and output filename
if hasattr(obj[0],"Group") and hasattr(obj[0],"Path"):
#Check for a machine and use the post processor if it's set
print "in activated"
# check if the user has a project and has set the default post and
# output filename
if hasattr(obj[0], "Group") and hasattr(obj[0], "Path"):
# # Check for a selected post post processor if it's set
proj = obj[0]
postobj = None
for p in obj[0].Group:
if p.Name == "Machine":
postobj = p
#need to check for existance of these: obj.PostProcessor, obj.OutputFile
if postobj and postobj.PostProcessor:
sys.path.append(os.path.split(postobj.PostProcessor)[0])
lessextn = os.path.splitext(postobj.PostProcessor)[0]
postname = os.path.split(lessextn)[1]
if proj.OutputFile:
filename = proj.OutputFile
# postobj = None
# for p in obj[0].Group:
# if p.Name == "Machine":
# postobj = p
if hasattr(obj[0], "PostProcessor"):
postobj = obj[0]
# need to check for existance of these: obj.PostProcessor,
# obj.OutputFile
if postobj and postobj.PostProcessor:
sys.path.append(os.path.split(postobj.PostProcessor)[0])
lessextn = os.path.splitext(postobj.PostProcessor)[0]
postname = os.path.split(lessextn)[1]
if proj.OutputFile:
filename = proj.OutputFile
postname += "_post"
exec "import %s as current_post" % postname
current_post.export(obj,filename)
reload(current_post)
current_post.export(obj, filename)
FreeCAD.ActiveDocument.commitTransaction()
FreeCAD.ActiveDocument.recompute()
if FreeCAD.GuiUp:
if FreeCAD.GuiUp:
# register the FreeCAD command
FreeCADGui.addCommand('Path_Post',CommandPathPost())
FreeCADGui.addCommand('Path_Post', CommandPathPost())
FreeCAD.Console.PrintLog("Loading PathPost... done\n")

View File

@@ -32,7 +32,6 @@ from PathScripts.PathUtils import depth_params
if FreeCAD.GuiUp:
import FreeCADGui
from PySide import QtCore, QtGui
from DraftTools import translate
# Qt tanslation handling
try:
_encoding = QtGui.QApplication.UnicodeUTF8
@@ -452,7 +451,11 @@ class CommandPathProfile:
'ToolTip': QtCore.QT_TRANSLATE_NOOP("PathProfile", "Creates a Path Profile object from selected faces")}
def IsActive(self):
return FreeCAD.ActiveDocument is not None
if FreeCAD.ActiveDocument is not None:
for o in FreeCAD.ActiveDocument.Objects:
if o.Name[:3] == "Job":
return True
return False
def Activated(self):
ztop = 10.0
@@ -477,7 +480,7 @@ class CommandPathProfile:
FreeCADGui.doCommand('obj.Direction = "CW"')
FreeCADGui.doCommand('obj.UseComp = False')
FreeCADGui.doCommand('obj.PlungeAngle = 90.0')
FreeCADGui.doCommand('PathScripts.PathUtils.addToProject(obj)')
FreeCADGui.doCommand('PathScripts.PathUtils.addToJob(obj)')
FreeCAD.ActiveDocument.commitTransaction()
FreeCAD.ActiveDocument.recompute()

View File

@@ -1,161 +0,0 @@
# -*- coding: utf-8 -*-
# ***************************************************************************
# * *
# * Copyright (c) 2014 Yorik van Havre <yorik@uncreated.net> *
# * *
# * This program is free software; you can redistribute it and/or modify *
# * it under the terms of the GNU Lesser General Public License (LGPL) *
# * as published by the Free Software Foundation; either version 2 of *
# * the License, or (at your option) any later version. *
# * for detail see the LICENCE text file. *
# * *
# * 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 Library General Public License for more details. *
# * *
# * You should have received a copy of the GNU Library General Public *
# * License along with this program; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
# * USA *
# * *
# ***************************************************************************
import FreeCAD
import Path
from PySide import QtCore, QtGui
FreeCADGui = None
if FreeCAD.GuiUp:
import FreeCADGui
"""Path Project object and FreeCAD command"""
# Qt tanslation handling
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def translate(context, text, disambig=None):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def translate(context, text, disambig=None):
return QtGui.QApplication.translate(context, text, disambig)
class ObjectPathProject:
def __init__(self, obj):
# obj.addProperty("App::PropertyFile", "PostProcessor", "CodeOutput", "Select the Post Processor file for this project")
obj.addProperty("App::PropertyFile", "OutputFile", "CodeOutput", QtCore.QT_TRANSLATE_NOOP("App::Property","The NC output file for this project"))
obj.setEditorMode("OutputFile", 0) # set to default mode
obj.addProperty("App::PropertyString", "Description", "Path", QtCore.QT_TRANSLATE_NOOP("App::Property","An optional description for this project"))
obj.Proxy = self
def __getstate__(self):
return None
def __setstate__(self, state):
return None
def onChanged(self, obj, prop):
pass
def execute(self, obj):
cmds = []
for child in obj.Group:
if child.isDerivedFrom("Path::Feature"):
if obj.UsePlacements:
for c in child.Path.Commands:
cmds.append(c.transform(child.Placement))
else:
cmds.extend(child.Path.Commands)
if cmds:
path = Path.Path(cmds)
obj.Path = path
class ViewProviderProject:
def __init__(self, vobj):
vobj.Proxy = self
mode = 2
vobj.setEditorMode('BoundingBox', mode)
vobj.setEditorMode('DisplayMode', mode)
vobj.setEditorMode('Selectable', mode)
vobj.setEditorMode('ShapeColor', mode)
vobj.setEditorMode('Transparency', mode)
def __getstate__(self): # mandatory
return None
def __setstate__(self, state): # mandatory
return None
def getIcon(self):
return ":/icons/Path-Project.svg"
def onChanged(self, vobj, prop):
mode = 2
vobj.setEditorMode('BoundingBox', mode)
vobj.setEditorMode('DisplayMode', mode)
vobj.setEditorMode('Selectable', mode)
vobj.setEditorMode('ShapeColor', mode)
vobj.setEditorMode('Transparency', mode)
class CommandProject:
def GetResources(self):
return {'Pixmap': 'Path-Project',
'MenuText': QtCore.QT_TRANSLATE_NOOP("Path_Project", "Project"),
'Accel': "P, P",
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Path_Project", "Creates a Path Project object")}
def IsActive(self):
return FreeCAD.ActiveDocument is not None
def Activated(self):
incl = []
sel = FreeCADGui.Selection.getSelection()
for obj in sel:
if obj.isDerivedFrom("Path::Feature"):
incl.append(obj)
FreeCAD.ActiveDocument.openTransaction(
translate("Path_Project", "Create Project"))
CommandProject.Create(incl)
FreeCAD.ActiveDocument.commitTransaction()
FreeCAD.ActiveDocument.recompute()
@staticmethod
def Create(pathChildren=[]):
"""Code to create a project"""
# FreeCADGui.addModule("PathScripts.PathProject")
import PathScripts.PathUtils as PU
if not PU.findProj() is None:
FreeCAD.Console.PrintError(
"A Path project already exists in this document\n")
return
obj = FreeCAD.ActiveDocument.addObject(
"Path::FeatureCompoundPython", "Project")
ObjectPathProject(obj)
if pathChildren:
for child in pathChildren:
pathChildren.append(FreeCAD.ActiveDocument.getObject(obj.Name))
obj.Group = pathChildren
ViewProviderProject(obj.ViewObject)
# create a machine obj
import PathScripts
PathScripts.PathMachine.CommandPathMachine.Create()
PathScripts.PathLoadTool.CommandPathLoadTool.Create()
return obj
if FreeCAD.GuiUp:
# register the FreeCAD command
FreeCADGui.addCommand('Path_Project', CommandProject())
FreeCAD.Console.PrintLog("Loading PathProject... done\n")

View File

@@ -31,10 +31,6 @@ import json
if FreeCAD.GuiUp:
import FreeCADGui
from PySide import QtCore, QtGui
from DraftTools import translate
else:
def translate(ctxt, txt):
return txt
__title__ = "Path Remote Operation"
__author__ = "sliptonic (Brad Collette)"
@@ -303,7 +299,11 @@ class CommandPathRemote:
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Path_Remote", "Request a Path from a remote cloud service")}
def IsActive(self):
return FreeCAD.ActiveDocument is not None
if FreeCAD.ActiveDocument is not None:
for o in FreeCAD.ActiveDocument.Objects:
if o.Name[:3] == "Job":
return True
return False
def Activated(self):
ztop = 10.0
@@ -322,7 +322,7 @@ class CommandPathRemote:
FreeCADGui.doCommand('obj.StepDown = ' + str((ztop-zbottom)/8))
FreeCADGui.doCommand('obj.FinalDepth=' + str(zbottom))
FreeCADGui.doCommand('PathScripts.PathUtils.addToProject(obj)')
FreeCADGui.doCommand('PathScripts.PathUtils.addToJob(obj)')
FreeCAD.ActiveDocument.commitTransaction()
FreeCAD.ActiveDocument.recompute()

View File

@@ -41,7 +41,6 @@ except AttributeError:
def review(obj):
limits = False
"checks the selected project for common errors"
toolcontrolcount = 0
for item in obj.Group:
@@ -69,8 +68,6 @@ def review(obj):
if item.X_Max == item.X_Min or item.Y_Max == item.Y_Min:
FreeCAD.Console.PrintWarning(translate("Path_Sanity", "It appears the machine limits haven't been set. Not able to check path extents.\n"))
else:
limits = True
if toolcontrolcount == 0:
FreeCAD.Console.PrintWarning(translate("Path_Sanity", "A Tool Controller was not found. Default values are used which is dangerous. Please add a Tool Controller.\n"))
@@ -84,7 +81,11 @@ class CommandPathSanity:
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Path_Sanity","Check the Path Project for common errors")}
def IsActive(self):
return not FreeCAD.ActiveDocument is None
if FreeCAD.ActiveDocument is not None:
for o in FreeCAD.ActiveDocument.Objects:
if o.Name[:3] == "Job":
return True
return False
def Activated(self):
# check that the selection contains exactly what we want

View File

@@ -1,35 +1,36 @@
# -*- coding: utf-8 -*-
# ***************************************************************************
# * *
# * Copyright (c) 2015 Yorik van Havre <yorik@uncreated.net> *
# * *
# * This program is free software; you can redistribute it and/or modify *
# * it under the terms of the GNU Lesser General Public License (LGPL) *
# * as published by the Free Software Foundation; either version 2 of *
# * the License, or (at your option) any later version. *
# * for detail see the LICENCE text file. *
# * *
# * 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 Library General Public License for more details. *
# * *
# * You should have received a copy of the GNU Library General Public *
# * License along with this program; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
# * USA *
# * *
# ***************************************************************************
#***************************************************************************
#* *
#* Copyright (c) 2015 Yorik van Havre <yorik@uncreated.net> *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
#* as published by the Free Software Foundation; either version 2 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENCE text file. *
#* *
#* 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 Library General Public License for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with this program; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#***************************************************************************
import FreeCAD,FreeCADGui,Path,PathGui
from PySide import QtCore,QtGui
import FreeCAD
import FreeCADGui
from PySide import QtCore, QtGui
"""Path SimpleCopy command"""
# Qt tanslation handling
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def translate(context, text, disambig=None):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
@@ -39,35 +40,43 @@ except AttributeError:
class CommandPathSimpleCopy:
def GetResources(self):
return {'Pixmap' : 'Path-SimpleCopy',
'MenuText': QtCore.QT_TRANSLATE_NOOP("Path_SimpleCopy","Simple Copy"),
return {'Pixmap': 'Path-SimpleCopy',
'MenuText': QtCore.QT_TRANSLATE_NOOP("Path_SimpleCopy", "Simple Copy"),
'Accel': "P, Y",
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Path_SimpleCopy","Creates a non-parametric copy of another path")}
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Path_SimpleCopy", "Creates a non-parametric copy of another path")}
def IsActive(self):
return not FreeCAD.ActiveDocument is None
if FreeCAD.ActiveDocument is not None:
for o in FreeCAD.ActiveDocument.Objects:
if o.Name[:3] == "Job":
return True
return False
def Activated(self):
# check that the selection contains exactly what we want
selection = FreeCADGui.Selection.getSelection()
if len(selection) != 1:
FreeCAD.Console.PrintError(translate("Path_SimpleCopy","Please select exactly one path object\n"))
FreeCAD.Console.PrintError(
translate("Path_SimpleCopy", "Please select exactly one path object\n"))
return
if not(selection[0].isDerivedFrom("Path::Feature")):
FreeCAD.Console.PrintError(translate("Path_SimpleCopy","Please select exactly one path object\n"))
FreeCAD.Console.PrintError(
translate("Path_SimpleCopy", "Please select exactly one path object\n"))
return
FreeCAD.ActiveDocument.openTransaction(translate("Path_SimpleCopy","Simple Copy"))
FreeCAD.ActiveDocument.openTransaction(
translate("Path_SimpleCopy", "Simple Copy"))
FreeCADGui.addModule("PathScripts.PathUtils")
FreeCADGui.doCommand('obj = FreeCAD.ActiveDocument.addObject("Path::Feature","'+selection[0].Name+ '_copy")')
FreeCADGui.doCommand('obj.Path = FreeCAD.ActiveDocument.'+selection[0].Name+'.Path')
FreeCADGui.doCommand('PathScripts.PathUtils.addToProject(obj)')
FreeCADGui.doCommand(
'obj = FreeCAD.ActiveDocument.addObject("Path::Feature","' + selection[0].Name + '_copy")')
FreeCADGui.doCommand(
'obj.Path = FreeCAD.ActiveDocument.' + selection[0].Name + '.Path')
FreeCADGui.doCommand('PathScripts.PathUtils.addToJob(obj)')
FreeCAD.ActiveDocument.commitTransaction()
FreeCAD.ActiveDocument.recompute()
if FreeCAD.GuiUp:
if FreeCAD.GuiUp:
# register the FreeCAD command
FreeCADGui.addCommand('Path_SimpleCopy',CommandPathSimpleCopy())
FreeCADGui.addCommand('Path_SimpleCopy', CommandPathSimpleCopy())

View File

@@ -1,43 +1,45 @@
# -*- coding: utf-8 -*-
#***************************************************************************
#* *
#* Copyright (c) 2015 Dan Falck <ddfalck@gmail.com> *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
#* as published by the Free Software Foundation; either version 2 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENCE text file. *
#* *
#* 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 Library General Public License for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with this program; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#***************************************************************************
# ***************************************************************************
# * *
# * Copyright (c) 2015 Dan Falck <ddfalck@gmail.com> *
# * *
# * This program is free software; you can redistribute it and/or modify *
# * it under the terms of the GNU Lesser General Public License (LGPL) *
# * as published by the Free Software Foundation; either version 2 of *
# * the License, or (at your option) any later version. *
# * for detail see the LICENCE text file. *
# * *
# * 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 Library General Public License for more details. *
# * *
# * You should have received a copy of the GNU Library General Public *
# * License along with this program; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
# * USA *
# * *
# ***************************************************************************
'''used to create material stock around a machined part- for visualization '''
import Draft,Part
import FreeCAD, FreeCADGui
import FreeCAD
import FreeCADGui
from FreeCAD import Vector
from PySide import QtCore, QtGui
import Part
# Qt tanslation handling
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def translate(context, text, disambig=None):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def translate(context, text, disambig=None):
return QtGui.QApplication.translate(context, text, disambig)
class Stock:
def __init__(self, obj):
"Make stock"
obj.addProperty("App::PropertyFloat","Length_Allowance","Stock",QtCore.QT_TRANSLATE_NOOP("App::Property","extra allownace from part width")).Length_Allowance = 1.0
@@ -49,7 +51,7 @@ class Stock:
def __getstate__(self):
return None
def __setstate__(self,state):
def __setstate__(self, state):
return None
def execute(self, obj):
@@ -62,45 +64,49 @@ class Stock:
self.Zmin = obj.Base.Shape.BoundBox.ZMin
self.Zmax = obj.Base.Shape.BoundBox.ZMax
self.length = self.Xmax -self.Xmin+obj.Length_Allowance*2.0
self.width = self.Ymax - self.Ymin+obj.Width_Allowance*2.0
self.height = self.Zmax - self.Zmin+obj.Height_Allowance*2.0
self.pnt = Vector(self.Xmin-obj.Length_Allowance , self.Ymin-obj.Width_Allowance, self.Zmin-obj.Height_Allowance)
self.length = self.Xmax - self.Xmin + obj.Length_Allowance * 2.0
self.width = self.Ymax - self.Ymin + obj.Width_Allowance * 2.0
self.height = self.Zmax - self.Zmin + obj.Height_Allowance * 2.0
self.pnt = Vector(self.Xmin - obj.Length_Allowance, self.Ymin -
obj.Width_Allowance, self.Zmin - obj.Height_Allowance)
obj.Shape = Part.makeBox(
self.length, self.width, self.height, self.pnt)
obj.Shape = Part.makeBox(self.length,self.width,self.height,self.pnt)
class _ViewProviderStock:
def __init__(self,obj): #mandatory
# obj.addProperty("App::PropertyFloat","SomePropertyName","PropertyGroup","Description of this property")
def __init__(self, obj): # mandatory
# obj.addProperty("App::PropertyFloat","SomePropertyName","PropertyGroup","Description of this property")
obj.Proxy = self
def __getstate__(self): #mandatory
def __getstate__(self): # mandatory
return None
def __setstate__(self,state): #mandatory
def __setstate__(self, state): # mandatory
return None
def getIcon(self): #optional
def getIcon(self): # optional
return ":/icons/Path-Stock.svg"
def attach(self, vobj): #optional
def attach(self, vobj): # optional
self.Object = vobj.Object
class CommandPathStock:
def GetResources(self):
return {'Pixmap' : 'Path-Stock',
'MenuText': QtCore.QT_TRANSLATE_NOOP("PathStock","Stock"),
return {'Pixmap': 'Path-Stock',
'MenuText': QtCore.QT_TRANSLATE_NOOP("PathStock", "Stock"),
'Accel': "P, S",
'ToolTip': QtCore.QT_TRANSLATE_NOOP("PathStock","Creates a 3D object to represent raw stock to mill the part out of")}
'ToolTip': QtCore.QT_TRANSLATE_NOOP("PathStock", "Creates a 3D object to represent raw stock to mill the part out of")}
def IsActive(self):
return not FreeCAD.ActiveDocument is None
return FreeCAD.ActiveDocument is not None
def Activated(self):
FreeCAD.ActiveDocument.openTransaction(translate("PathStock","Creates a 3D object to represent raw stock to mill the part out of"))
FreeCAD.ActiveDocument.openTransaction(translate(
"PathStock", "Creates a 3D object to represent raw stock to mill the part out of"))
FreeCADGui.addModule("PathScripts.PathStock")
snippet = '''
import FreeCADGui
@@ -111,7 +117,7 @@ if len(FreeCADGui.Selection.getSelection())>0:
obj =FreeCAD.ActiveDocument.addObject('Part::FeaturePython',sel[0].Name+('_Stock'))
PathScripts.PathStock.Stock(obj)
PathScripts.PathStock._ViewProviderStock(obj.ViewObject)
PathScripts.PathUtils.addToProject(obj)
PathScripts.PathUtils.addToJob(obj)
baseobj = sel[0]
obj.Base = baseobj
FreeCADGui.ActiveDocument.getObject(sel[0].Name+("_Stock")).ShapeColor = (0.3333,0.6667,1.0000)
@@ -124,9 +130,8 @@ else:
'''
FreeCADGui.doCommand(snippet)
if FreeCAD.GuiUp:
if FreeCAD.GuiUp:
# register the FreeCAD command
FreeCADGui.addCommand('Path_Stock',CommandPathStock())
FreeCADGui.addCommand('Path_Stock', CommandPathStock())
FreeCAD.Console.PrintLog("Loading PathStock... done\n")

View File

@@ -1,124 +1,131 @@
# -*- coding: utf-8 -*-
#***************************************************************************
#* *
#* Copyright (c) 2015 Dan Falck <ddfalck@gmail.com> *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
#* as published by the Free Software Foundation; either version 2 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENCE text file. *
#* *
#* 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 Library General Public License for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with this program; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#***************************************************************************
# ***************************************************************************
# * *
# * Copyright (c) 2015 Dan Falck <ddfalck@gmail.com> *
# * *
# * This program is free software; you can redistribute it and/or modify *
# * it under the terms of the GNU Lesser General Public License (LGPL) *
# * as published by the Free Software Foundation; either version 2 of *
# * the License, or (at your option) any later version. *
# * for detail see the LICENCE text file. *
# * *
# * 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 Library General Public License for more details. *
# * *
# * You should have received a copy of the GNU Library General Public *
# * License along with this program; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
# * USA *
# * *
# ***************************************************************************
''' Used for CNC machine Stops for Path module. Create an Optional or Mandatory Stop.'''
import FreeCAD,FreeCADGui,Path,PathGui
from PathScripts import PathProject
from PySide import QtCore,QtGui
import FreeCAD
import FreeCADGui
import Path
from PySide import QtCore, QtGui
# Qt tanslation handling
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def translate(context, text, disambig=None):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def translate(context, text, disambig=None):
return QtGui.QApplication.translate(context, text, disambig)
class Stop:
def __init__(self,obj):
obj.addProperty("App::PropertyEnumeration", "Stop", "Path", QtCore.QT_TRANSLATE_NOOP("App::Property","Add Optional or Mandatory Stop to the program"))
obj.Stop=['Optional', 'Mandatory']
obj.Proxy = self
mode = 2
obj.setEditorMode('Placement',mode)
obj.setEditorMode('Placement', mode)
def __getstate__(self):
return None
def __setstate__(self,state):
def __setstate__(self, state):
return None
def onChanged(self,obj,prop):
def onChanged(self, obj, prop):
pass
# FreeCAD.ActiveDocument.recompute()
def execute(self,obj):
def execute(self, obj):
if obj.Stop == 'Optional':
word = 'M1'
else:
word = 'M0'
output =""
output = word+'\n'
output = ""
output = word + '\n'
path = Path.Path(output)
obj.Path = path
class _ViewProviderStop:
def __init__(self,vobj): #mandatory
# obj.addProperty("App::PropertyFloat","SomePropertyName","PropertyGroup","Description of this property")
def __init__(self, vobj): # mandatory
# obj.addProperty("App::PropertyFloat","SomePropertyName","PropertyGroup","Description of this property")
vobj.Proxy = self
mode = 2
vobj.setEditorMode('LineWidth',mode)
vobj.setEditorMode('MarkerColor',mode)
vobj.setEditorMode('NormalColor',mode)
vobj.setEditorMode('ShowFirstRapid',mode)
vobj.setEditorMode('DisplayMode',mode)
vobj.setEditorMode('BoundingBox',mode)
vobj.setEditorMode('Selectable',mode)
vobj.setEditorMode('ShapeColor',mode)
vobj.setEditorMode('Transparency',mode)
vobj.setEditorMode('Visibility',mode)
vobj.setEditorMode('LineWidth', mode)
vobj.setEditorMode('MarkerColor', mode)
vobj.setEditorMode('NormalColor', mode)
vobj.setEditorMode('ShowFirstRapid', mode)
vobj.setEditorMode('DisplayMode', mode)
vobj.setEditorMode('BoundingBox', mode)
vobj.setEditorMode('Selectable', mode)
vobj.setEditorMode('ShapeColor', mode)
vobj.setEditorMode('Transparency', mode)
vobj.setEditorMode('Visibility', mode)
def __getstate__(self): #mandatory
def __getstate__(self): # mandatory
return None
def __setstate__(self,state): #mandatory
def __setstate__(self, state): # mandatory
return None
def getIcon(self): #optional
def getIcon(self): # optional
return ":/icons/Path-Stop.svg"
def onChanged(self,vobj,prop): #optional
def onChanged(self, vobj, prop): # optional
mode = 2
vobj.setEditorMode('LineWidth',mode)
vobj.setEditorMode('MarkerColor',mode)
vobj.setEditorMode('NormalColor',mode)
vobj.setEditorMode('ShowFirstRapid',mode)
vobj.setEditorMode('DisplayMode',mode)
vobj.setEditorMode('BoundingBox',mode)
vobj.setEditorMode('Selectable',mode)
vobj.setEditorMode('ShapeColor',mode)
vobj.setEditorMode('Transparency',mode)
vobj.setEditorMode('Visibility',mode)
vobj.setEditorMode('LineWidth', mode)
vobj.setEditorMode('MarkerColor', mode)
vobj.setEditorMode('NormalColor', mode)
vobj.setEditorMode('ShowFirstRapid', mode)
vobj.setEditorMode('DisplayMode', mode)
vobj.setEditorMode('BoundingBox', mode)
vobj.setEditorMode('Selectable', mode)
vobj.setEditorMode('ShapeColor', mode)
vobj.setEditorMode('Transparency', mode)
vobj.setEditorMode('Visibility', mode)
class CommandPathStop:
def GetResources(self):
return {'Pixmap' : 'Path-Stop',
'MenuText': QtCore.QT_TRANSLATE_NOOP("Path_Stop","Stop"),
return {'Pixmap': 'Path-Stop',
'MenuText': QtCore.QT_TRANSLATE_NOOP("Path_Stop", "Stop"),
'Accel': "P, C",
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Path_Stop","Add Optional or Mandatory Stop to the program")}
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Path_Stop", "Add Optional or Mandatory Stop to the program")}
def IsActive(self):
return not FreeCAD.ActiveDocument is None
if FreeCAD.ActiveDocument is not None:
for o in FreeCAD.ActiveDocument.Objects:
if o.Name[:3] == "Job":
return True
return False
def Activated(self):
FreeCAD.ActiveDocument.openTransaction(translate("Path_Stop","Add Optional or Mandatory Stop to the program"))
FreeCAD.ActiveDocument.openTransaction(
translate("Path_Stop", "Add Optional or Mandatory Stop to the program"))
FreeCADGui.addModule("PathScripts.PathStop")
snippet = '''
import Path
@@ -129,15 +136,15 @@ obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython","Stop")
PathScripts.PathStop.Stop(obj)
PathScripts.PathStop._ViewProviderStop(obj.ViewObject)
PathUtils.addToProject(obj)
PathUtils.addToJob(obj)
'''
FreeCADGui.doCommand(snippet)
FreeCAD.ActiveDocument.commitTransaction()
FreeCAD.ActiveDocument.recompute()
if FreeCAD.GuiUp:
if FreeCAD.GuiUp:
# register the FreeCAD command
FreeCADGui.addCommand('Path_Stop',CommandPathStop())
FreeCADGui.addCommand('Path_Stop', CommandPathStop())
FreeCAD.Console.PrintLog("Loading PathStop... done\n")

View File

@@ -29,10 +29,6 @@ from PathScripts import PathUtils
if FreeCAD.GuiUp:
import FreeCADGui
from PySide import QtCore, QtGui
from DraftTools import translate
else:
def translate(ctxt, txt):
return txt
__title__ = "Path Surface Operation"
__author__ = "sliptonic (Brad Collette)"
@@ -372,7 +368,11 @@ class CommandPathSurfacing:
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Path_Surface", "Creates a Path Surfacing object")}
def IsActive(self):
return FreeCAD.ActiveDocument is not None
if FreeCAD.ActiveDocument is not None:
for o in FreeCAD.ActiveDocument.Objects:
if o.Name[:3] == "Job":
return True
return False
def Activated(self):
@@ -396,7 +396,7 @@ class CommandPathSurfacing:
FreeCADGui.doCommand('obj.SampleInterval = 0.4')
FreeCADGui.doCommand('obj.FinalDepth=' + str(zbottom))
FreeCADGui.doCommand('PathScripts.PathUtils.addToProject(obj)')
FreeCADGui.doCommand('PathScripts.PathUtils.addToJob(obj)')
FreeCAD.ActiveDocument.commitTransaction()
FreeCAD.ActiveDocument.recompute()

View File

@@ -1,41 +1,44 @@
# -*- coding: utf-8 -*-
#***************************************************************************
#* *
#* Copyright (c) 2015 Dan Falck <ddfalck@gmail.com> *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
#* as published by the Free Software Foundation; either version 2 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENCE text file. *
#* *
#* 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 Library General Public License for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with this program; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#***************************************************************************
# ***************************************************************************
# * *
# * Copyright (c) 2015 Dan Falck <ddfalck@gmail.com> *
# * *
# * This program is free software; you can redistribute it and/or modify *
# * it under the terms of the GNU Lesser General Public License (LGPL) *
# * as published by the Free Software Foundation; either version 2 of *
# * the License, or (at your option) any later version. *
# * for detail see the LICENCE text file. *
# * *
# * 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 Library General Public License for more details. *
# * *
# * You should have received a copy of the GNU Library General Public *
# * License along with this program; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
# * USA *
# * *
# ***************************************************************************
''' Used for CNC machine Tool Length Offsets ie G43H2'''
import FreeCAD,FreeCADGui,Path,PathGui
from PathScripts import PathProject,PathUtils
from PySide import QtCore,QtGui
import FreeCAD
import FreeCADGui
import Path
from PathScripts import PathUtils
from PySide import QtCore, QtGui
# Qt tanslation handling
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def translate(context, text, disambig=None):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def translate(context, text, disambig=None):
return QtGui.QApplication.translate(context, text, disambig)
class ToolLenOffset:
def __init__(self,obj):
obj.addProperty("App::PropertyIntegerConstraint", "HeightNumber","HeightOffset",QtCore.QT_TRANSLATE_NOOP("App::Property","The Height offset number of the active tool"))
@@ -44,13 +47,14 @@ class ToolLenOffset:
obj.addProperty("App::PropertyBool","Active","HeightOffset",QtCore.QT_TRANSLATE_NOOP("App::Property","Make False, to prevent operation from generating code"))
obj.Proxy = self
mode = 2
obj.setEditorMode('Placement',mode)
obj.setEditorMode('Placement', mode)
def execute(self,obj):
def execute(self, obj):
command = 'G43H'+str(obj.HeightNumber)+'G0Z'+str(obj.Height.Value)
command = 'G43H' + str(obj.HeightNumber) + \
'G0Z' + str(obj.Height.Value)
obj.Path = Path.Path(command)
obj.Label = "Height"+str(obj.HeightNumber)
obj.Label = "Height" + str(obj.HeightNumber)
if obj.Active:
obj.Path = Path.Path(command)
obj.ViewObject.Visibility = True
@@ -59,89 +63,95 @@ class ToolLenOffset:
obj.ViewObject.Visibility = False
# tie the HeightNumber to the PathLoadTool object ToolNumber
if len(obj.InList)>0: #check to see if obj is in the Project group yet
if len(obj.InList) > 0: # check to see if obj is in the Project group yet
project = obj.InList[0]
tl = int(PathUtils.changeTool(obj,project))
obj.HeightNumber= tl
tl = int(PathUtils.changeTool(obj, project))
obj.HeightNumber = tl
def onChanged(self,obj,prop):
def onChanged(self, obj, prop):
if prop == "HeightNumber":
obj.Label = "Height"+str(obj.HeightNumber)
obj.Label = "Height" + str(obj.HeightNumber)
class _ViewProviderTLO:
def __init__(self,vobj): #mandatory
def __init__(self, vobj): # mandatory
vobj.Proxy = self
mode = 2
vobj.setEditorMode('LineWidth',mode)
vobj.setEditorMode('MarkerColor',mode)
vobj.setEditorMode('NormalColor',mode)
vobj.setEditorMode('ShowFirstRapid',mode)
vobj.setEditorMode('DisplayMode',mode)
vobj.setEditorMode('BoundingBox',mode)
vobj.setEditorMode('Selectable',mode)
vobj.setEditorMode('ShapeColor',mode)
vobj.setEditorMode('Transparency',mode)
vobj.setEditorMode('Visibility',mode)
vobj.setEditorMode('LineWidth', mode)
vobj.setEditorMode('MarkerColor', mode)
vobj.setEditorMode('NormalColor', mode)
vobj.setEditorMode('ShowFirstRapid', mode)
vobj.setEditorMode('DisplayMode', mode)
vobj.setEditorMode('BoundingBox', mode)
vobj.setEditorMode('Selectable', mode)
vobj.setEditorMode('ShapeColor', mode)
vobj.setEditorMode('Transparency', mode)
vobj.setEditorMode('Visibility', mode)
def __getstate__(self): #mandatory
def __getstate__(self): # mandatory
return None
def __setstate__(self,state): #mandatory
def __setstate__(self, state): # mandatory
return None
def getIcon(self): #optional
def getIcon(self): # optional
return ":/icons/Path-LengthOffset.svg"
def onChanged(self,vobj,prop): #optional
def onChanged(self, vobj, prop): # optional
mode = 2
vobj.setEditorMode('LineWidth',mode)
vobj.setEditorMode('MarkerColor',mode)
vobj.setEditorMode('NormalColor',mode)
vobj.setEditorMode('ShowFirstRapid',mode)
vobj.setEditorMode('DisplayMode',mode)
vobj.setEditorMode('BoundingBox',mode)
vobj.setEditorMode('Selectable',mode)
vobj.setEditorMode('ShapeColor',mode)
vobj.setEditorMode('Transparency',mode)
vobj.setEditorMode('Visibility',mode)
vobj.setEditorMode('LineWidth', mode)
vobj.setEditorMode('MarkerColor', mode)
vobj.setEditorMode('NormalColor', mode)
vobj.setEditorMode('ShowFirstRapid', mode)
vobj.setEditorMode('DisplayMode', mode)
vobj.setEditorMode('BoundingBox', mode)
vobj.setEditorMode('Selectable', mode)
vobj.setEditorMode('ShapeColor', mode)
vobj.setEditorMode('Transparency', mode)
vobj.setEditorMode('Visibility', mode)
def updateData(self,vobj,prop): #optional
def updateData(self, vobj, prop): # optional
# this is executed when a property of the APP OBJECT changes
pass
def setEdit(self,vobj,mode): #optional
def setEdit(self, vobj, mode): # optional
# this is executed when the object is double-clicked in the tree
pass
def unsetEdit(self,vobj,mode): #optional
def unsetEdit(self, vobj, mode): # optional
# this is executed when the user cancels or terminates edit mode
pass
class CommandPathToolLenOffset:
def GetResources(self):
return {'Pixmap' : 'Path-LengthOffset',
'MenuText': QtCore.QT_TRANSLATE_NOOP("Path_ToolLenOffset","Tool Length Offset"),
return {'Pixmap': 'Path-LengthOffset',
'MenuText': QtCore.QT_TRANSLATE_NOOP("Path_ToolLenOffset", "Tool Length Offset"),
'Accel': "P, T",
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Path_ToolLenOffset","Create a Tool Length Offset object")}
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Path_ToolLenOffset", "Create a Tool Length Offset object")}
def IsActive(self):
return not FreeCAD.ActiveDocument is None
if FreeCAD.ActiveDocument is not None:
for o in FreeCAD.ActiveDocument.Objects:
if o.Name[:3] == "Job":
return True
return False
def Activated(self):
FreeCAD.ActiveDocument.openTransaction(translate("Path_ToolLenOffset","Create a Selection Plane object"))
FreeCAD.ActiveDocument.openTransaction(
translate("Path_ToolLenOffset", "Create a Selection Plane object"))
FreeCADGui.addModule("PathScripts.PathToolLenOffset")
snippet = '''
import Path
import PathScripts
from PathScripts import PathProject,PathUtils
from PathScripts import PathJob,PathUtils
obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython","HeightOffset")
PathScripts.PathToolLenOffset.ToolLenOffset(obj)
obj.Active = True
PathScripts.PathToolLenOffset._ViewProviderTLO(obj.ViewObject)
project = PathUtils.addToProject(obj)
project = PathUtils.addToJob(obj)
tl = PathUtils.changeTool(obj,project)
if tl:
@@ -153,12 +163,8 @@ FreeCAD.ActiveDocument.recompute()
FreeCAD.ActiveDocument.commitTransaction()
FreeCAD.ActiveDocument.recompute()
if FreeCAD.GuiUp:
if FreeCAD.GuiUp:
# register the FreeCAD command
FreeCADGui.addCommand('Path_ToolLenOffset', CommandPathToolLenOffset())
FreeCAD.Console.PrintLog("Loading PathToolLenOffset... done\n")

View File

@@ -0,0 +1,593 @@
# -*- coding: utf-8 -*-
# ***************************************************************************
# * *
# * Copyright (c) 2014 sliptonic <shopinthewoods@gmail.com> *
# * *
# * This program is free software; you can redistribute it and/or modify *
# * it under the terms of the GNU Lesser General Public License (LGPL) *
# * as published by the Free Software Foundation; either version 2 of *
# * the License, or (at your option) any later version. *
# * for detail see the LICENCE text file. *
# * *
# * 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 Library General Public License for more details. *
# * *
# * You should have received a copy of the GNU Library General Public *
# * License along with this program; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
# * USA *
# * *
# ***************************************************************************
import FreeCAD
import xml.sax
import FreeCADGui
import Path
import os
from PySide import QtCore, QtGui
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig)
# Tooltable XML readers
class FreeCADTooltableHandler(xml.sax.ContentHandler):
# http://www.tutorialspoint.com/python/python_xml_processing.htm
def __init__(self):
self.tooltable = None
self.tool = None
self.number = None
# Call when an element is found
def startElement(self, tag, attributes):
if tag == "Tooltable":
self.tooltable = Path.Tooltable()
elif tag == "Toolslot":
self.number = int(attributes["number"])
elif tag == "Tool":
self.tool = Path.Tool()
self.tool.Name = str(attributes["name"])
self.tool.ToolType = str(attributes["type"])
self.tool.Material = str(attributes["mat"])
# for some reason without the following line I get an error
#print attributes["diameter"]
self.tool.Diameter = float(attributes["diameter"])
self.tool.LengthOffset = float(attributes["length"])
self.tool.FlatRadius = float(attributes["flat"])
self.tool.CornerRadius = float(attributes["corner"])
self.tool.CuttingEdgeAngle = float(attributes["angle"])
self.tool.CuttingEdgeHeight = float(attributes["height"])
# Call when an elements ends
def endElement(self, tag):
if tag == "Toolslot":
if self.tooltable and self.tool and self.number:
self.tooltable.setTool(self.number, self.tool)
self.number = None
self.tool = None
class HeeksTooltableHandler(xml.sax.ContentHandler):
def __init__(self):
self.tooltable = Path.Tooltable()
self.tool = None
self.number = None
# Call when an element is found
def startElement(self, tag, attributes):
if tag == "Tool":
self.tool = Path.Tool()
self.number = int(attributes["tool_number"])
self.tool.Name = str(attributes["title"])
elif tag == "params":
t = str(attributes["type"])
if t == "drill":
self.tool.ToolType = "Drill"
elif t == "center_drill_bit":
self.tool.ToolType = "CenterDrill"
elif t == "end_mill":
self.tool.ToolType = "EndMill"
elif t == "slot_cutter":
self.tool.ToolType = "SlotCutter"
elif t == "ball_end_mill":
self.tool.ToolType = "BallEndMill"
elif t == "chamfer":
self.tool.ToolType = "Chamfer"
elif t == "engraving_bit":
self.tool.ToolType = "Engraver"
m = str(attributes["material"])
if m == "0":
self.tool.Material = "HighSpeedSteel"
elif m == "1":
self.tool.Material = "Carbide"
# for some reason without the following line I get an error
#print attributes["diameter"]
self.tool.Diameter = float(attributes["diameter"])
self.tool.LengthOffset = float(attributes["tool_length_offset"])
self.tool.FlatRadius = float(attributes["flat_radius"])
self.tool.CornerRadius = float(attributes["corner_radius"])
self.tool.CuttingEdgeAngle = float(
attributes["cutting_edge_angle"])
self.tool.CuttingEdgeHeight = float(
attributes["cutting_edge_height"])
# Call when an elements ends
def endElement(self, tag):
if tag == "Tool":
if self.tooltable and self.tool and self.number:
self.tooltable.setTool(self.number, self.tool)
self.number = None
self.tool = None
class ToolLibraryManager():
'''
The Tool Library is a list of individual tool tables. Each
Tool Table can contain n tools. The tool library will be persisted to user
preferences and all or part of the library can be exported to other formats
'''
def __init__(self):
self.ToolLibrary = []
self.prefs = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Path")
return
def saveMainLibrary(self, tooltable):
'''Persists the permanent library to FreeCAD user preferences'''
tmpstring = tooltable.Content
self.prefs.SetString("ToolLibrary", tmpstring)
return True
def getLists(self):
'''Builds the list of all Tool Table lists'''
tablelist = []
toollist = "<Main>"
tablelist.append(toollist)
# Get ToolTables from any open CNC jobs
for o in FreeCAD.ActiveDocument.Objects:
if "Proxy" in o.PropertiesList:
if hasattr(o, "Tooltable"):
toollist = o.Label
tablelist.append(toollist)
return tablelist
def _findList(self, listname):
tt = None
if listname == "<Main>":
tmpstring = self.prefs.GetString("ToolLibrary", "")
if tmpstring != "":
Handler = FreeCADTooltableHandler()
xml.sax.parseString(tmpstring, Handler)
tt = Handler.tooltable
else:
tt = Path.Tooltable()
else:
for o in FreeCAD.ActiveDocument.Objects:
if o.Label == listname:
tt = o.Tooltable
return tt
def getTool(self, listname, toolnum):
tt = self._findList(listname)
return tt.getTool(toolnum)
def getTools(self, tablename):
'''returns the tool data for a given table'''
tooldata = []
tt = self._findList(tablename)
headers = ["","Tool Num.","Name","Tool Type","Material","Diameter","Length Offset","Flat Radius","Corner Radius","Cutting Edge Angle","Cutting Edge Height"]
model = QtGui.QStandardItemModel()
model.setHorizontalHeaderLabels(headers)
if tt:
if len(tt.Tools) == 0:
tooldata.append([])
for number, t in tt.Tools.iteritems():
itemcheck = QtGui.QStandardItem()
itemcheck.setCheckable(True)
itemNumber = QtGui.QStandardItem(str(number))
itemName = QtGui.QStandardItem(t.Name)
itemToolType = QtGui.QStandardItem(t.ToolType)
itemMaterial = QtGui.QStandardItem(t.Material)
itemDiameter = QtGui.QStandardItem(str(t.Diameter))
itemLengthOffset = QtGui.QStandardItem(str(t.LengthOffset))
itemFlatRadius = QtGui.QStandardItem(str(t.FlatRadius))
itmCornerRadius = QtGui.QStandardItem(str(t.CornerRadius))
itemCuttingEdgeAngle = QtGui.QStandardItem(str(t.CuttingEdgeAngle))
itemCuttingEdgeHeight = QtGui.QStandardItem(str(t.CuttingEdgeHeight))
row = [itemcheck, itemNumber, itemName, itemToolType, itemMaterial, itemDiameter, itemLengthOffset, itemFlatRadius, itmCornerRadius, itemCuttingEdgeAngle, itemCuttingEdgeHeight]
model.appendRow(row)
return model
# methods for importing and exporting
def read(self, filename, listname):
"imports a tooltable from a file"
parser = xml.sax.make_parser()
parser.setFeature(xml.sax.handler.feature_namespaces, 0)
if os.path.splitext(filename[0])[1].lower() == ".tooltable":
Handler = HeeksTooltableHandler()
else:
Handler = FreeCADTooltableHandler()
parser.setContentHandler(Handler)
parser.parse(str(filename[0]))
if not Handler.tooltable:
return None
ht = Handler.tooltable
tt = self._findList(listname)
for t in ht.Tools:
newt = ht.getTool(t).copy()
tt.addTools(newt)
if listname == "<Main>":
self.saveMainLibrary(tt)
return True
def write(self, filename, listname):
"exports the tooltable to a file"
tt = self._findList(listname)
if tt:
fil = open(str(filename[0]), "wb")
fil.write('<?xml version="1.0" encoding="UTF-8"?>\n')
fil.write(tt.Content)
fil.close()
print "Written ", filename[0]
def addnew(self, listname, tool, position = None):
"adds a new tool at the end of the table"
tt = self._findList(listname)
if position is None:
tt.addTools(tool)
newID = tt.Tools.keys()[-1]
else:
tt.setTool(position, tool)
newID = position
if listname == "<Main>":
return self.saveMainLibrary(tt)
return newID
def updateTool(self, listname, toolnum, tool):
'''updates tool data'''
tt = self._findList(listname)
tt.deleteTool(toolnum)
tt.setTool(toolnum, tool)
if listname == "<Main>":
return self.saveMainLibrary(tt)
return True
def moveup(self, number, listname):
"moves a tool to a lower number, if possible"
if number < 2:
return False
target = number - 1
tt = self._findList(listname)
t1 = tt.getTool(number).copy()
tt.deleteTool(number)
if target in tt.Tools.keys():
t2 = tt.getTool(target).copy()
tt.deleteTool(target)
tt.setTool(number, t2)
tt.setTool(target, t1)
if listname == "<Main>":
self.saveMainLibrary(tt)
return True
def movedown(self, number, listname):
"moves a tool to a higher number, if possible"
tt = self._findList(listname)
target = number + 1
t1 = tt.getTool(number).copy()
tt.deleteTool(number)
if target in tt.Tools.keys():
t2 = tt.getTool(target).copy()
tt.deleteTool(target)
tt.setTool(number, t2)
tt.setTool(target, t1)
if listname == "<Main>":
self.saveMainLibrary(tt)
return True
def delete(self, number, listname):
'''deletes a tool from the current list'''
tt = self._findList(listname)
tt.deleteTool(number)
if listname == "<Main>":
self.saveMainLibrary(tt)
return True
def createToolController(self, job, tool):
pass
def exportListHeeks(self, tooltable):
'''exports one or more Lists as a HeeksCNC tooltable'''
pass
def exportListLinuxCNC(self, tooltable):
'''exports one or more Lists as a LinuxCNC tooltable'''
pass
def exportListXML(self, tooltable):
'''exports one or more Lists as an XML file'''
pass
class EditorPanel():
def __init__(self):
#self.form = FreeCADGui.PySideUic.loadUi(FreeCAD.getHomePath() + "Mod/Path/ToolLibraryEditor.ui")
self.form = FreeCADGui.PySideUic.loadUi(":/panels/ToolLibraryEditor.ui")
#self.editform = FreeCADGui.PySideUic.loadUi(FreeCAD.getHomePath() + "Mod/Path/ToolEdit.ui")
self.editform = FreeCADGui.PySideUic.loadUi(":/panels/ToolEdit.ui")
self.TLM = ToolLibraryManager()
data = self.TLM.getLists()
self.listmodel = QtGui.QStandardItemModel(self.form.listView)
# self.listmodel = QtGui.QStringListModel(data)
for i in data:
item = QtGui.QStandardItem(i)
self.listmodel.appendRow(item)
self.form.listView.setModel(self.listmodel)
#self.form.listView.setCurrentIndex(0)
self.form.ToolsList.resizeColumnsToContents()
def accept(self):
pass
def reject(self):
FreeCADGui.Control.closeDialog()
FreeCAD.ActiveDocument.recompute()
def getFields(self):
pass
def getType(self, tooltype):
"gets a combobox index number for a given type or viceversa"
toolslist = ["Drill", "CenterDrill", "CounterSink", "CounterBore",
"Reamer", "Tap", "EndMill", "SlotCutter", "BallEndMill",
"ChamferMill", "CornerRound", "Engraver"]
if isinstance(tooltype, str):
if tooltype in toolslist:
return toolslist.index(tooltype) + 1
else:
return 0
else:
if tooltype == 0:
return "Undefined"
else:
return toolslist[tooltype - 1]
def getMaterial(self, material):
"gets a combobox index number for a given material or viceversa"
matslist = ["HighSpeedSteel", "HighCarbonToolSteel", "CastAlloy",
"Carbide", "Ceramics", "Diamond", "Sialon"]
if isinstance(material, str):
if material in matslist:
return matslist.index(material) + 1
else:
return 0
else:
if material == 0:
return "Undefined"
else:
return matslist[material - 1]
def addTool(self):
t = Path.Tool()
print (t)
editform = FreeCADGui.PySideUic.loadUi(":/panels/ToolEdit.ui")
r = editform.exec_()
if r:
if editform.NameField.text():
t.Name = str(editform.NameField.text())
t.ToolType = self.getType(editform.TypeField.currentIndex())
t.Material = self.getMaterial(editform.MaterialField.currentIndex())
t.Diameter = editform.DiameterField.value()
t.LengthOffset = editform.LengthOffsetField.value()
t.FlatRadius = editform.FlatRadiusField.value()
t.CornerRadius = editform.CornerRadiusField.value()
t.CuttingEdgeAngle = editform.CuttingEdgeAngleField.value()
t.CuttingEdgeHeight = editform.CuttingEdgeHeightField.value()
listname = self.form.listView.selectedIndexes()[0].data()
if self.TLM.addnew(listname, t) is True:
self.loadTable(self.form.listView.selectedIndexes()[0])
def setFields(self):
index = self.listmodel.index(0, 0, QtCore.QModelIndex())
self.form.listView.setFocus()
sm = self.form.listView.selectionModel()
sm.select(index, sm.Select)
def open(self):
pass
def loadTable(self, curr):
tooldata = self.TLM.getTools(curr.data())
self.form.ToolsList.setModel(tooldata)
def moveUp(self):
"moves a tool to a lower number, if possible"
item = self.form.ToolsList.selectedIndexes()[1].data()
if item:
number = int(item)
listname = self.form.listView.selectedIndexes()[0].data()
if self.TLM.moveup(number, listname) is True:
self.loadTable(self.form.listView.selectedIndexes()[0])
def moveDown(self):
"moves a tool to a higher number, if possible"
item = self.form.ToolsList.selectedIndexes()[1].data()
if item:
number = int(item)
listname = self.form.listView.selectedIndexes()[0].data()
if self.TLM.movedown(number, listname) is True:
self.loadTable(self.form.listView.selectedIndexes()[0])
def delete(self):
'''deletes a tool'''
item = self.form.ToolsList.selectedIndexes()[1].data()
if item:
number = int(item)
listname = self.form.listView.selectedIndexes()[0].data()
if self.TLM.delete(number, listname) is True:
self.loadTable(self.form.listView.selectedIndexes()[0])
def editTool(self, currItem):
row = currItem.row()
value = currItem.sibling(row, 1).data()
listname = self.form.listView.selectedIndexes()[0].data()
toolnum = int(value)
tool = self.TLM.getTool(listname, toolnum)
editform = FreeCADGui.PySideUic.loadUi(":/panels/ToolEdit.ui")
editform.NameField.setText(tool.Name)
editform.TypeField.setCurrentIndex(self.getType(tool.ToolType))
editform.MaterialField.setCurrentIndex(self.getMaterial(tool.Material))
editform.DiameterField.setValue(tool.Diameter)
editform.LengthOffsetField.setValue(tool.LengthOffset)
editform.FlatRadiusField.setValue(tool.FlatRadius)
editform.CornerRadiusField.setValue(tool.CornerRadius)
editform.CuttingEdgeAngleField.setValue(tool.CuttingEdgeAngle)
editform.CuttingEdgeHeightField.setValue(tool.CuttingEdgeHeight)
r = editform.exec_()
if r:
if editform.NameField.text():
tool.Name = str(editform.NameField.text())
tool.ToolType = self.getType(editform.TypeField.currentIndex())
tool.Material = self.getMaterial(editform.MaterialField.currentIndex())
tool.Diameter = editform.DiameterField.value()
tool.LengthOffset = editform.LengthOffsetField.value()
tool.FlatRadius = editform.FlatRadiusField.value()
tool.CornerRadius = editform.CornerRadiusField.value()
tool.CuttingEdgeAngle = editform.CuttingEdgeAngleField.value()
tool.CuttingEdgeHeight = editform.CuttingEdgeHeightField.value()
if self.TLM.updateTool(listname, toolnum, tool) is True:
self.loadTable(self.form.listView.selectedIndexes()[0])
def importFile(self):
"imports a tooltable from a file"
filename = QtGui.QFileDialog.getOpenFileName(self.form, _translate(
"TooltableEditor", "Open tooltable", None), None, _translate("TooltableEditor", "Tooltable XML (*.xml);;HeeksCAD tooltable (*.tooltable)", None))
if filename:
listname = self.form.listView.selectedIndexes()[0].data()
if self.TLM.read(filename, listname):
self.loadTable(self.form.listView.selectedIndexes()[0])
def exportFile(self):
"imports a tooltable from a file"
filename = QtGui.QFileDialog.getSaveFileName(self.form, _translate("TooltableEditor", "Save tooltable", None), None, _translate("TooltableEditor", "Tooltable XML (*.xml)", None))
if filename:
listname = self.form.listView.selectedIndexes()[0].data()
self.TLM.write(filename, listname)
def copyTools(self):
tools = []
model = self.form.ToolsList.model()
for i in range(model.rowCount()):
item = model.item(i, 0)
if item.checkState():
item = model.index(i, 1)
tools.append(item.data())
if len(tools) == 0:
return
targets = self.TLM.getLists()
currList = self.form.listView.selectedIndexes()[0].data()
for target in targets:
if target == currList:
targets.remove(target)
if len(targets) == 0:
FreeCAD.Console.PrintWarning("no place to go")
return
else:
form = FreeCADGui.PySideUic.loadUi(":/panels/DlgToolCopy.ui")
form.cboTarget.addItems(targets)
r = form.exec_()
if r is False:
return None
else:
targetlist = form.cboTarget.currentText()
for toolnum in tools:
tool = self.TLM.getTool(currList, int(toolnum))
newtoolid = self.TLM.addnew(targetlist, tool.copy(), int(toolnum))
if form.chkMakeController.checkState() == QtCore.Qt.CheckState.Checked and targetlist != "<Main>":
snippet = '''
import Path, PathScripts
from PathScripts import PathUtils, PathLoadTool
obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython","TC")
PathScripts.PathLoadTool.LoadTool(obj)
PathScripts.PathLoadTool._ViewProviderLoadTool(obj.ViewObject)
obj.ToolNumber = %d
PathUtils.addToJob(obj, "%s")
App.activeDocument().recompute()
''' % (newtoolid, targetlist)
FreeCADGui.doCommand(snippet)
def getStandardButtons(self):
return int(QtGui.QDialogButtonBox.Ok)
def setupUi(self):
# Connect Signals and Slots
self.form.ButtonNewTool.clicked.connect(self.addTool)
#self.form.listWidget.currentItemChanged.connect(self.loadTable)
sm = self.form.listView.selectionModel()
sm.currentChanged.connect(self.loadTable)
self.form.ButtonImport.clicked.connect(self.importFile)
self.form.ButtonExport.clicked.connect(self.exportFile)
self.form.ButtonDown.clicked.connect(self.moveDown)
self.form.ButtonUp.clicked.connect(self.moveUp)
self.form.ButtonDelete.clicked.connect(self.delete)
self.form.ToolsList.doubleClicked.connect(self.editTool)
self.form.btnCopyTools.clicked.connect(self.copyTools)
self.setFields()
class CommandToolLibraryEdit():
def edit(self):
editor = EditorPanel()
editor.setupUi()
r = editor.form.exec_()
if r:
pass
def GetResources(self):
return {'Pixmap' : 'Path-ToolTable',
'MenuText': QtCore.QT_TRANSLATE_NOOP("Path_ToolTable","Edit the Tool Library"),
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Path_ToolTable","Edit the Tool Library")}
def IsActive(self):
return not FreeCAD.ActiveDocument is None
def Activated(self):
self.edit()
if FreeCAD.GuiUp:
# register the FreeCAD command
FreeCADGui.addCommand('Path_ToolLibraryEdit',CommandToolLibraryEdit())

View File

@@ -1,62 +1,79 @@
# -*- coding: utf-8 -*-
#***************************************************************************
#* *
#* Copyright (c) 2015 Dan Falck <ddfalck@gmail.com> *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
#* as published by the Free Software Foundation; either version 2 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENCE text file. *
#* *
#* 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 Library General Public License for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with this program; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#***************************************************************************
# ***************************************************************************
# * *
# * Copyright (c) 2015 Dan Falck <ddfalck@gmail.com> *
# * *
# * This program is free software; you can redistribute it and/or modify *
# * it under the terms of the GNU Lesser General Public License (LGPL) *
# * as published by the Free Software Foundation; either version 2 of *
# * the License, or (at your option) any later version. *
# * for detail see the LICENCE text file. *
# * *
# * 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 Library General Public License for more details. *
# * *
# * You should have received a copy of the GNU Library General Public *
# * License along with this program; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
# * USA *
# * *
# ***************************************************************************
import FreeCAD,FreeCADGui
from PySide import QtCore,QtGui
import FreeCAD
import FreeCADGui
from PySide import QtCore, QtGui
# Qt tanslation handling
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def translate(context, text, disambig=None):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def translate(context, text, disambig=None):
return QtGui.QApplication.translate(context, text, disambig)
class CommandPathToolTableEdit:
def GetResources(self):
return {'Pixmap' : 'Path-ToolTable',
'MenuText': QtCore.QT_TRANSLATE_NOOP("Path_ToolTableEdit","EditToolTable"),
return {'Pixmap': 'Path-ToolTable',
'MenuText': QtCore.QT_TRANSLATE_NOOP("Path_ToolTableEdit", "EditToolTable"),
'Accel': "P, T",
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Path_ToolTableEdit","Edits a Tool Table in a selected Project")}
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Path_ToolTableEdit", "Edits a Tool Table in a selected Project")}
def IsActive(self):
return not FreeCAD.ActiveDocument is None
return FreeCAD.ActiveDocument is not None
def Activated(self):
FreeCAD.ActiveDocument.openTransaction(translate("Path_ToolTableEdit","Edits a Tool Table in a selected Project"))
FreeCADGui.doCommand("from PathScripts import TooltableEditor")
FreeCADGui.doCommand("from PathScripts import PathUtils")
FreeCADGui.doCommand('machine = PathUtils.findMachine()')
FreeCADGui.doCommand('TooltableEditor.edit(machine.Name)')
FreeCAD.ActiveDocument.openTransaction(
translate("Path_ToolTableEdit", "Edits a Tool Table in a selected Project"))
snippet = '''
from PathScripts import TooltableEditor
from PathScripts import PathUtils
sel = Gui.Selection.getSelectionEx()[0]
obj=sel.Object
if "Tooltable" in obj.PropertiesList:
TooltableEditor.edit(obj.Name)
'''
FreeCADGui.doCommand(snippet)
# FreeCADGui.doCommand("from PathScripts import TooltableEditor")
# FreeCADGui.doCommand("from PathScripts import PathUtils")
# FreeCADGui.doCommand("sel = Gui.Selection.getSelectionEx()[0]")
# FreeCADGui.doCommand("obj=sel.Object")
# FreeCADGui.doCommand('job = PathUtils.findParentJob(obj)')
# FreeCADGui.doCommand('TooltableEditor.edit(job.Name)')
FreeCAD.ActiveDocument.commitTransaction()
FreeCAD.ActiveDocument.recompute()
if FreeCAD.GuiUp:
if FreeCAD.GuiUp:
# register the FreeCAD command
FreeCADGui.addCommand('Path_ToolTableEdit',CommandPathToolTableEdit())
FreeCADGui.addCommand('Path_ToolTableEdit', CommandPathToolTableEdit())
FreeCAD.Console.PrintLog("Loading PathToolTableEdit... done\n")

View File

@@ -23,6 +23,7 @@
# ***************************************************************************
'''PathUtils -common functions used in PathScripts for filterig, sorting, and generating gcode toolpath data '''
import FreeCAD
import FreeCADGui
import Part
import math
import Path
@@ -30,9 +31,9 @@ from DraftGeomUtils import geomType
from DraftGeomUtils import findWires
import DraftVecUtils
import PathScripts
from PathScripts import PathProject
from PathScripts import PathJob
import itertools
from PySide import QtGui
def cleanedges(splines, precision):
'''cleanedges([splines],precision). Convert BSpline curves, Beziers, to arcs that can be used for cnc paths.
@@ -240,16 +241,6 @@ def convert(toolpath, Z=0.0, PlungeAngle=90.0, Zprevious=None, StopLength=None,
endpt = arcstartpt
center = edge.Curve.Center
relcenter = center.sub(lastpt)
# start point and end point fall together in the given output precision?
if fmt(startpt.x) == fmt(endpt.x) and fmt(startpt.y) == fmt(endpt.y):
if edge.Length < 0.5 * 2 * math.pi * edge.Curve.Radius:
# because it is a very small circle -> omit, as that gcode would produce a full circle
return endpt, ""
else:
# it is an actual full circle, emit a line for this
pass
# FreeCAD.Console.PrintMessage("arc startpt= " + str(startpt)+ "\n")
# FreeCAD.Console.PrintMessage("arc midpt= " + str(midpt)+ "\n")
# FreeCAD.Console.PrintMessage("arc endpt= " + str(endpt)+ "\n")
@@ -387,12 +378,9 @@ def SortPath(wire, Side, radius, clockwise, firstedge=None, SegLen=0.5):
sortededges = Part.__sortEdges__(edgelist)
newwire = findWires(sortededges)[0]
print "newwire is clockwise: " + str(is_clockwise(newwire))
if is_clockwise(newwire) is not clockwise:
newwire.reverse()
print "newwire is clockwise: " + str(is_clockwise(newwire))
if Side == 'Left':
# we use the OCC offset feature
offset = newwire.makeOffset(radius) # tool is outside line
@@ -403,9 +391,7 @@ def SortPath(wire, Side, radius, clockwise, firstedge=None, SegLen=0.5):
offset = newwire.makeOffset(0.0)
else:
offset = newwire
print "offset wire is clockwise: " + str(is_clockwise(offset))
offset.reverse()
print "offset wire is clockwise: " + str(is_clockwise(offset))
return offset
@@ -455,9 +441,9 @@ def MakePath(wire, Side, radius, clockwise, ZClearance, StepDown, ZStart, ZFinal
# numbers/height offset numbers based on previously active toolnumbers
def changeTool(obj, proj):
def changeTool(obj, job):
tlnum = 0
for p in proj.Group:
for p in job.Group:
if not hasattr(p, "Group"):
if isinstance(p.Proxy, PathScripts.PathLoadTool.LoadTool) and p.ToolNumber > 0:
tlnum = p.ToolNumber
@@ -470,16 +456,14 @@ def changeTool(obj, proj):
if g == obj:
return tlnum
def getLastTool(obj):
toolNum = obj.ToolNumber
if obj.ToolNumber == 0:
# find tool from previous toolchange
proj = findProj()
toolNum = changeTool(obj, proj)
job = findJob()
toolNum = changeTool(obj, job)
return getTool(obj, toolNum)
def getLastToolLoad(obj):
# This walks up the hierarchy and tries to find the closest preceding
# toolchange.
@@ -523,51 +507,68 @@ def getLastToolLoad(obj):
continue
return tc
def getTool(obj, number=0):
"retrieves a tool from a hosting object with a tooltable, if any"
for o in obj.InList:
if o.TypeId == "Path::FeatureCompoundPython":
for m in o.Group:
if hasattr(m, "Tooltable"):
return m.Tooltable.getTool(number)
# not found? search one level up
for o in obj.InList:
return getTool(o, number)
if hasattr(o, "Tooltable"):
return o.Tooltable.getTool(number)
return None
def findProj():
for o in FreeCAD.ActiveDocument.Objects:
if "Proxy" in o.PropertiesList:
if isinstance(o.Proxy, PathProject.ObjectPathProject):
return o
def findMachine():
'''find machine object for the tooltable editor '''
for o in FreeCAD.ActiveDocument.Objects:
if "Proxy" in o.PropertiesList:
if isinstance(o.Proxy, PathScripts.PathMachine.Machine):
return o
def addToProject(obj):
"""Adds a path obj to this document, if no PathParoject exists it's created on the fly"""
p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Path")
if p.GetBool("pathAutoProject", True):
project = findProj()
if not project:
project = PathProject.CommandProject.Create()
g = project.Group
g.append(obj)
project.Group = g
return project
def findParentJob(obj):
'''retrieves a parent job object for an operation or other Path object'''
for i in obj.InList:
if isinstance(i.Proxy, PathScripts.PathJob.ObjectPathJob):
return i
return None
def GetJobs(jobname = None):
'''returns all jobs in the current document. If name is given, returns that job'''
jobs = []
for o in FreeCAD.ActiveDocument.Objects:
if "Proxy" in o.PropertiesList:
if isinstance(o.Proxy, PathJob.ObjectPathJob):
if jobname is not None:
if o.Name == jobname:
jobs.append(o)
else:
jobs.append(o)
return jobs
def addToJob(obj, jobname = None):
if jobname is not None:
jobs = GetJobs(jobname)
if len(jobs) == 1:
job = jobs[0]
else:
FreeCAD.Console.PrintError("Didn't find the job")
return None
else:
jobs = GetJobs()
if len(jobs) == 0:
job = PathJob.CommandJob.Create()
elif len(jobs) == 1:
job = jobs[0]
else:
form = FreeCADGui.PySideUic.loadUi(FreeCAD.getHomePath() + "Mod/Path/DlgJobChooser.ui")
mylist = [i.Name for i in jobs]
form.cboProject.addItems(mylist)
r = form.exec_()
if r is False:
return None
else:
print form.cboProject.currentText()
job = [i for i in jobs if i.Name == form.cboProject.currentText()][0]
g = job.Group
g.append(obj)
job.Group = g
return job
def getLastZ(obj):
''' find the last z value in the project '''
''' find the last z value in the job '''
lastZ = ""
for g in obj.Group:
for c in g.Path.Commands:
@@ -576,30 +577,6 @@ def getLastZ(obj):
lastZ = c.Parameters['Z']
return lastZ
def frange(start, stop, step, finish):
x = []
curdepth = start
if step == 0:
return x
# do the base cuts until finishing round
while curdepth >= stop + step + finish:
curdepth = curdepth - step
if curdepth <= stop + finish:
curdepth = stop + finish
x.append(curdepth)
# we might have to do a last pass or else finish round might be too far
# away
if curdepth - stop > finish:
x.append(stop + finish)
# do the the finishing round
if curdepth >= stop:
curdepth = stop
x.append(curdepth)
return x
def rapid(x=None, y=None, z=None):
""" Returns gcode string to perform a rapid move."""
retstr = "G00"
@@ -772,6 +749,7 @@ def rampPlunge(edge, rampangle, destZ, startZ):
class depth_params:
'''calculates the intermediate depth values for various operations given the starting, ending, and stepdown parameters'''
def __init__(self, clearance_height, rapid_safety_space, start_depth, step_down, z_finish_depth, final_depth, user_depths=None):
self.clearance_height = clearance_height

View File

@@ -0,0 +1,190 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Dialog</class>
<widget class="QDialog" name="Dialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>423</width>
<height>435</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>Tool Properties</string>
</property>
<layout class="QFormLayout" name="formLayout">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
</property>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Name</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="NameField"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Type</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="TypeField"/>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Material</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QComboBox" name="MaterialField"/>
</item>
<item row="6" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Diameter</string>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QDoubleSpinBox" name="DiameterField">
<property name="suffix">
<string>mm</string>
</property>
</widget>
</item>
<item row="8" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Length Offset</string>
</property>
</widget>
</item>
<item row="8" column="1">
<widget class="QDoubleSpinBox" name="LengthOffsetField">
<property name="suffix">
<string>mm</string>
</property>
</widget>
</item>
<item row="12" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Flat Radius</string>
</property>
</widget>
</item>
<item row="12" column="1">
<widget class="QDoubleSpinBox" name="FlatRadiusField">
<property name="suffix">
<string>mm</string>
</property>
</widget>
</item>
<item row="14" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Corner Radius</string>
</property>
</widget>
</item>
<item row="14" column="1">
<widget class="QDoubleSpinBox" name="CornerRadiusField">
<property name="suffix">
<string>mm</string>
</property>
</widget>
</item>
<item row="16" column="0">
<widget class="QLabel" name="label_9">
<property name="text">
<string>Cutting Edge Angle</string>
</property>
</widget>
</item>
<item row="16" column="1">
<widget class="QDoubleSpinBox" name="CuttingEdgeAngleField_2">
<property name="suffix">
<string>°</string>
</property>
</widget>
</item>
<item row="18" column="0">
<widget class="QLabel" name="label_8">
<property name="text">
<string>Cutting Edge Height</string>
</property>
</widget>
</item>
<item row="18" column="1">
<widget class="QDoubleSpinBox" name="CuttingEdgeHeightField">
<property name="suffix">
<string>mm</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>Dialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>Dialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@@ -0,0 +1,242 @@
# -*- coding: utf-8 -*-
# ***************************************************************************
# * *
# * Copyright (c) 2014 sliptonic <shopinthewoods@gmail.com> *
# * *
# * This program is free software; you can redistribute it and/or modify *
# * it under the terms of the GNU Lesser General Public License (LGPL) *
# * as published by the Free Software Foundation; either version 2 of *
# * the License, or (at your option) any later version. *
# * for detail see the LICENCE text file. *
# * *
# * 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 Library General Public License for more details. *
# * *
# * You should have received a copy of the GNU Library General Public *
# * License along with this program; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
# * USA *
# * *
# ***************************************************************************
import FreeCAD
import xml.sax
import FreeCADGui
import Path
import Draft
import Part
import os
from PySide import QtCore, QtGui
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig)
# Tooltable XML readers
class FreeCADTooltableHandler(xml.sax.ContentHandler):
# http://www.tutorialspoint.com/python/python_xml_processing.htm
def __init__(self):
self.tooltable = None
self.tool = None
self.number = None
# Call when an element is found
def startElement(self, tag, attributes):
if tag == "Tooltable":
self.tooltable = Path.Tooltable()
elif tag == "Toolslot":
self.number = int(attributes["number"])
elif tag == "Tool":
self.tool = Path.Tool()
self.tool.Name = str(attributes["name"])
self.tool.ToolType = str(attributes["type"])
self.tool.Material = str(attributes["mat"])
# for some reason without the following line I get an error
print attributes["diameter"]
self.tool.Diameter = float(attributes["diameter"])
self.tool.LengthOffset = float(attributes["length"])
self.tool.FlatRadius = float(attributes["flat"])
self.tool.CornerRadius = float(attributes["corner"])
self.tool.CuttingEdgeAngle = float(attributes["angle"])
self.tool.CuttingEdgeHeight = float(attributes["height"])
# Call when an elements ends
def endElement(self, tag):
if tag == "Toolslot":
if self.tooltable and self.tool and self.number:
self.tooltable.setTool(self.number, self.tool)
self.number = None
self.tool = None
class HeeksTooltableHandler(xml.sax.ContentHandler):
def __init__(self):
self.tooltable = Path.Tooltable()
self.tool = None
self.number = None
# Call when an element is found
def startElement(self, tag, attributes):
if tag == "Tool":
self.tool = Path.Tool()
self.number = int(attributes["tool_number"])
self.tool.Name = str(attributes["title"])
elif tag == "params":
t = str(attributes["type"])
if t == "drill":
self.tool.ToolType = "Drill"
elif t == "center_drill_bit":
self.tool.ToolType = "CenterDrill"
elif t == "end_mill":
self.tool.ToolType = "EndMill"
elif t == "slot_cutter":
self.tool.ToolType = "SlotCutter"
elif t == "ball_end_mill":
self.tool.ToolType = "BallEndMill"
elif t == "chamfer":
self.tool.ToolType = "Chamfer"
elif t == "engraving_bit":
self.tool.ToolType = "Engraver"
m = str(attributes["material"])
if m == "0":
self.tool.Material = "HighSpeedSteel"
elif m == "1":
self.tool.Material = "Carbide"
# for some reason without the following line I get an error
print attributes["diameter"]
self.tool.Diameter = float(attributes["diameter"])
self.tool.LengthOffset = float(attributes["tool_length_offset"])
self.tool.FlatRadius = float(attributes["flat_radius"])
self.tool.CornerRadius = float(attributes["corner_radius"])
self.tool.CuttingEdgeAngle = float(
attributes["cutting_edge_angle"])
self.tool.CuttingEdgeHeight = float(
attributes["cutting_edge_height"])
# Call when an elements ends
def endElement(self, tag):
if tag == "Tool":
if self.tooltable and self.tool and self.number:
self.tooltable.setTool(self.number, self.tool)
self.number = None
self.tool = None
class ToolLibraryManager():
'''
The Tool Library is a list of individual tool tables. Each
Tool Table can contain n tools. The tool library will be persisted to user
preferences and all or part of the library can be exported to other formats
'''
def __init__(self):
self.ToolLibrary = []
self.prefs = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Path/ToolLibrary")
return
def saveLibrary(self):
'''Persists the entire library to FreeCAD user preferences'''
tmpstring = ""
for table in self.ToolLibrary:
if table["listtype"] == 'User':
tmpstring += table["list"].Content
self.prefs.SetString("ToolLibrary", tmpstring)
# FreeCAD.ConfigSet("PathToolTable:" + table[0], table[2].Content)
def loadLibrary(self):
'''Loads the current library from FreeCAD user preferences'''
# Get persisted libraries from user prefs
tmpstring = self.prefs.GetString("ToolLibrary", "")
ToolLibrary = []
if tmpstring != "":
Handler = FreeCADTooltableHandler()
try:
xml.sax.parseString(tmpstring, Handler)
tt = Handler.tooltable
toollist = {'name': "main", 'listtype': "User", 'list': tt}
ToolLibrary.append(toollist)
except:
FreeCAD.Console.PrintError(
"Unable to import tools from user preferences")
# Get ToolTables from any open CNC jobs
for o in FreeCAD.ActiveDocument.Objects:
if "Proxy" in o.PropertiesList:
if hasattr(o, "Tooltable"):
toollist = {'name': o.Name,
'listtype': "Job", 'list': o.Tooltable}
ToolLibrary.append(toollist)
self.ToolLibrary = ToolLibrary
return self.ToolLibrary
# methods for lists
def addList(self, tablename, listtype="User", TL=None):
'''Add a new tooltable to the user library'''
if TL is None:
TL = Path.Tooltable()
toollist = {'name': tablename, 'listtype': listtype, 'list': TL}
self.ToolLibrary.append(toollist)
return TL
def deleteList(self, tablename):
'''Delete all lists from the user library with the given listname'''
for l in self.ToolLibrary:
if l['name'] == tablename:
# maybe check if tools exist in list
self.ToolLibrary.remove(l)
return
def findList(self, tablename):
'''Finds and returns list by name'''
returnlist = []
for l in self.ToolLibrary:
if l['name'] == tablename:
returnlist.append(l)
return returnlist
# methods for importing and exporting
def read(self):
"imports a tooltable from a file"
filename = QtGui.QFileDialog.getOpenFileName(None, _translate("ToolLibraryManager", "Import tooltable", None), None, _translate(
"ToolLibraryManager", "Tooltable XML (*.xml);;HeeksCAD tooltable (*.tooltable)", None))
if filename:
parser = xml.sax.make_parser()
parser.setFeature(xml.sax.handler.feature_namespaces, 0)
if os.path.splitext(filename[0])[1].lower() == ".tooltable":
Handler = HeeksTooltableHandler()
else:
Handler = FreeCADTooltableHandler()
parser.setContentHandler(Handler)
parser.parse(str(filename[0]))
if Handler.tooltable:
self.addList(filename[0], Handler.tooltable)
# self.reset()
def createToolController(self, job, tool):
pass
def exportListHeeks(self, tooltable):
'''exports one or more Lists as a HeeksCNC tooltable'''
pass
def exportListLinuxCNC(self, tooltable):
'''exports one or more Lists as a LinuxCNC tooltable'''
pass
def exportListXML(self, tooltable):
'''exports one or more Lists as an XML file'''
pass