Merge pull request #4014 from sliptonic/feature/toolbitdock

[PATH] Feature/toolbitdock
This commit is contained in:
sliptonic
2020-11-23 10:12:58 -06:00
committed by GitHub
45 changed files with 1500 additions and 1201 deletions

View File

@@ -154,26 +154,28 @@ SET(PathScripts_post_SRCS
)
SET(Tools_Bit_SRCS
Tools/Bit/t1.fctb
Tools/Bit/t2.fctb
Tools/Bit/t3.fctb
Tools/Bit/t4.fctb
Tools/Bit/t5.fctb
Tools/Bit/t6.fctb
Tools/Bit/t7.fctb
Tools/Bit/t8.fctb
Tools/Bit/t9.fctb
Tools/Bit/45degree_chamfer.fctb
Tools/Bit/5mm_Drill.fctb
Tools/Bit/5mm_Endmill.fctb
Tools/Bit/60degree_Vbit.fctb
Tools/Bit/6mm_Ball_End.fctb
Tools/Bit/6mm_Bullnose.fctb
Tools/Bit/slittingsaw.fctb
Tools/Bit/probe.fctb
)
SET(Tools_Library_SRCS
Tools/Library/endmills.fctl
Tools/Library/Default.fctl
)
SET(Tools_Shape_SRCS
Tools/Shape/ballend.fcstd
Tools/Shape/bullnose.fcstd
Tools/Shape/drill.fcstd
Tools/Shape/chamfer.fcstd
Tools/Shape/endmill.fcstd
Tools/Shape/probe.fcstd
Tools/Shape/slittingsaw.fcstd
Tools/Shape/v-bit.fcstd
)

View File

@@ -1,21 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Form</class>
<widget class="QWidget" name="Form">
<class>ToolBitAttributes</class>
<widget class="QWidget" name="ToolBitAttributes">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>587</width>
<height>744</height>
<width>401</width>
<height>715</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
<string>Tool Bit Attributes</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QTabWidget" name="tabWidget">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="currentIndex">
<number>0</number>
</property>
@@ -114,7 +120,7 @@
<item row="0" column="1">
<widget class="Gui::InputField" name="toolCuttingEdgeAngle">
<property name="text">
<string>180°</string>
<string>0 °</string>
</property>
<property name="unit" stdset="0">
<string>°</string>
@@ -131,7 +137,7 @@
<item row="1" column="1">
<widget class="Gui::InputField" name="toolCuttingEdgeHeight">
<property name="text">
<string>0.00</string>
<string>0 mm</string>
</property>
<property name="unit" stdset="0">
<string>mm</string>

View File

@@ -11,297 +11,11 @@
</rect>
</property>
<property name="windowTitle">
<string>ToolBit Library</string>
<string>Library Manager</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="0">
<widget class="QWidget" name="toolTableGroup" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<property name="leftMargin">
<number>0</number>
</property>
<item>
<widget class="QWidget" name="verticalWidget" native="true">
<property name="maximumSize">
<size>
<width>226</width>
<height>16777215</height>
</size>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_5">
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="ToolTable">
<property name="text">
<string>Tool Libraries</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="ButtonRenameToolTable">
<property name="maximumSize">
<size>
<width>32</width>
<height>32</height>
</size>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Rename Tool Table&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../../../../Gui/Icons/resource.qrc">
<normaloff>:/icons/edit-edit.svg</normaloff>:/icons/edit-edit.svg</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="ButtonAddToolTable">
<property name="maximumSize">
<size>
<width>32</width>
<height>32</height>
</size>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Add New Tool Table&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../../../../Gui/Icons/resource.qrc">
<normaloff>:/icons/list-add.svg</normaloff>:/icons/list-add.svg</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="ButtonRemoveToolTable">
<property name="maximumSize">
<size>
<width>32</width>
<height>32</height>
</size>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Remove Tool Table from Disc&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../../../../Gui/Icons/resource.qrc">
<normaloff>:/icons/list-remove.svg</normaloff>:/icons/list-remove.svg</iconset>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QListWidget" name="TableList">
<property name="frameShape">
<enum>QFrame::Box</enum>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="leftMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QTableView" name="toolTable">
<property name="acceptDrops">
<bool>true</bool>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Table of Tool Bits of the library.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="frameShape">
<enum>QFrame::Box</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
<property name="lineWidth">
<number>1</number>
</property>
<property name="midLineWidth">
<number>0</number>
</property>
<property name="dragEnabled">
<bool>true</bool>
</property>
<property name="dragDropMode">
<enum>QAbstractItemView::InternalMove</enum>
</property>
<property name="defaultDropAction">
<enum>Qt::MoveAction</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
<property name="sortingEnabled">
<bool>true</bool>
</property>
<attribute name="verticalHeaderVisible">
<bool>false</bool>
</attribute>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QPushButton" name="addToolController">
<property name="text">
<string>Add Tool Controller(s) to Job</string>
</property>
<property name="icon">
<iconset resource="../../../../../Gui/Icons/resource.qrc">
<normaloff>:/icons/edit_OK.svg</normaloff>:/icons/edit_OK.svg</iconset>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>140</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="libraryCancel">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Close the Tool Bit Library Editor&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Cancel</string>
</property>
<property name="icon">
<iconset resource="../../../../../Gui/Icons/resource.qrc">
<normaloff>:/icons/button_invalid.svg</normaloff>:/icons/button_invalid.svg</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="librarySave">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Save the current Library&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Save Table</string>
</property>
<property name="icon">
<iconset resource="../../../../../Gui/Icons/resource.qrc">
<normaloff>:/icons/document-save.svg</normaloff>:/icons/document-save.svg</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="librarySaveAs">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Save the library to a new file&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Save Table As...</string>
</property>
<property name="icon">
<iconset resource="../../../../../Gui/Icons/resource.qrc">
<normaloff>:/icons/document-save-as.svg</normaloff>:/icons/document-save-as.svg</iconset>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item row="0" column="0" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLineEdit" name="lineLibPath">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>420</width>
<height>0</height>
</size>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="libraryOpen">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Select the folder with the tool libraries to load.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../../../../Gui/Icons/resource.qrc">
<normaloff>:/icons/document-open.svg</normaloff>:/icons/document-open.svg</iconset>
</property>
</widget>
</item>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
@@ -315,22 +29,45 @@
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="toolCreate">
<property name="text">
<string>Create Toolbit</string>
</property>
<property name="icon">
<iconset resource="../Path.qrc">
<normaloff>:/icons/Path-ToolBit.svg</normaloff>:/icons/Path-ToolBit.svg</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="toolAdd">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Add existing Tool Bit to this library.&lt;/p&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Add Toolbit</string>
<string>Add Existing</string>
</property>
<property name="icon">
<iconset resource="../../../../../Gui/Icons/resource.qrc">
<normaloff>:/icons/list-add.svg</normaloff>:/icons/list-add.svg</iconset>
<iconset resource="../Path.qrc">
<normaloff>:/icons/Path-ToolDuplicate.svg</normaloff>:/icons/Path-ToolDuplicate.svg</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="toolDelete">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Delete selected Tool Bit(s) from the library.&lt;/p&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
@@ -343,17 +80,194 @@
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QWidget" name="toolTableGroup" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QPushButton" name="libraryOpen">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Select a working path for the tool library editor.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../../../../Gui/Icons/resource.qrc">
<normaloff>:/icons/document-open.svg</normaloff>:/icons/document-open.svg</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="addToolTable">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Add New Tool Table&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../../../../Gui/Icons/resource.qrc">
<normaloff>:/icons/document-new.svg</normaloff>:/icons/document-new.svg</iconset>
</property>
<property name="iconSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="libraryExport">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Save the selected library with a new name or export to another format&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../../../../Gui/Icons/resource.qrc">
<normaloff>:/icons/document-save.svg</normaloff>:/icons/document-save.svg</iconset>
</property>
</widget>
</item>
<item>
<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>
</item>
<item>
<widget class="QTreeView" name="TableList">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="frameShape">
<enum>QFrame::Box</enum>
</property>
</widget>
</item>
<item>
<widget class="QTableView" name="toolTable">
<property name="acceptDrops">
<bool>true</bool>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Table of Tool Bits of the library.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="frameShape">
<enum>QFrame::Box</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
<property name="lineWidth">
<number>1</number>
</property>
<property name="midLineWidth">
<number>0</number>
</property>
<property name="dragEnabled">
<bool>false</bool>
</property>
<property name="dragDropOverwriteMode">
<bool>false</bool>
</property>
<property name="dragDropMode">
<enum>QAbstractItemView::DragOnly</enum>
</property>
<property name="defaultDropAction">
<enum>Qt::IgnoreAction</enum>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::SingleSelection</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
<property name="sortingEnabled">
<bool>true</bool>
</property>
<attribute name="verticalHeaderVisible">
<bool>false</bool>
</attribute>
<attribute name="verticalHeaderStretchLastSection">
<bool>true</bool>
</attribute>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_8">
<item>
<widget class="QPushButton" name="toolEnumerate">
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Preferred</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>65555555</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="librarySave">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Assign numbers to each Tool Bit according to its current position in the library. The first Tool Bit is assigned the ID 1.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Save the current Library&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Enumerate</string>
<string>Close</string>
</property>
<property name="icon">
<iconset resource="../../../../../Gui/Icons/resource.qrc">
<normaloff>:/icons/button_sort.svg</normaloff>:/icons/button_sort.svg</iconset>
<normaloff>:/icons/edit_OK.svg</normaloff>:/icons/edit_OK.svg</iconset>
</property>
</widget>
</item>
@@ -363,6 +277,7 @@
</widget>
<resources>
<include location="../../../../../Gui/Icons/resource.qrc"/>
<include location="../Path.qrc"/>
</resources>
<connections/>
</ui>

View File

@@ -1,119 +1,135 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Dialog</class>
<widget class="QDialog" name="Dialog">
<class>ToolSelector</class>
<widget class="QDockWidget" name="ToolSelector">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>588</width>
<height>396</height>
<width>350</width>
<height>542</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QWidget" name="widget_2" native="true">
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="windowTitle">
<string>Tool Selector</string>
</property>
<widget class="QWidget" name="dockWidgetContents">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QWidget" name="widget_2" native="true">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="lblLibrary">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="libraryEditorOpen">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../Path.qrc">
<normaloff>:/icons/Path-ToolTable.svg</normaloff>:/icons/Path-ToolTable.svg</iconset>
</property>
<property name="iconSize">
<size>
<width>16</width>
<height>16</height>
</size>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QListWidget" name="tools">
<widget class="QTreeView" name="tools">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Available Tool Bits to choose from.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
</widget>
</item>
<item>
<widget class="QWidget" name="widget" native="true">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QPushButton" name="toolLoad">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Load an existing Tool Bit from a file.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Load...</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="toolCreate">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Create a new Tool Bit based on an existing shape.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>New</string>
</property>
</widget>
</item>
<item>
<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>
<property name="selectionMode">
<enum>QAbstractItemView::ExtendedSelection</enum>
</property>
<property name="sortingEnabled">
<bool>false</bool>
</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>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QPushButton" name="addToolController">
<property name="enabled">
<bool>false</bool>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Create ToolControllers for the selected toolbits and add them to the Job&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Add To Job</string>
</property>
<property name="icon">
<iconset resource="../../../../../Gui/Icons/resource.qrc">
<normaloff>:/icons/edit_OK.svg</normaloff>:/icons/edit_OK.svg</iconset>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</widget>
</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>
<resources>
<include location="../../../../../Gui/Icons/resource.qrc"/>
<include location="../Path.qrc"/>
</resources>
<connections/>
</ui>

View File

@@ -76,20 +76,13 @@ class PathWorkbench (Workbench):
from PathScripts import PathToolBitCmd
from PathScripts import PathToolBitLibraryCmd
if PathPreferences.experimentalFeaturesEnabled():
toolbitcmdlist = PathToolBitCmd.CommandList + ["Separator"] + PathToolBitLibraryCmd.CommandList + ["Path_ToolController", "Separator"]
self.toolbitctxmenu = ["Path_ToolBitLibraryLoad", "Path_ToolController"]
else:
toolbitcmdlist = []
self.toolbitctxmenu = []
import PathCommands
PathGuiInit.Startup()
# build commands list
projcmdlist = ["Path_Job", "Path_Post"]
toolcmdlist = ["Path_Inspect", "Path_Simulator",
"Path_ToolLibraryEdit", "Path_SelectLoop",
toolcmdlist = ["Path_Inspect", "Path_Simulator", "Path_SelectLoop",
"Path_OpActiveToggle"]
prepcmdlist = ["Path_Fixture", "Path_Comment", "Path_Stop",
"Path_Custom", "Path_Probe"]
@@ -107,6 +100,16 @@ class PathWorkbench (Workbench):
# modcmdmore = ["Path_Hop",]
# remotecmdlist = ["Path_Remote"]
if PathPreferences.toolsReallyUseLegacyTools():
toolcmdlist.append("Path_ToolLibraryEdit")
toolbitcmdlist = []
else:
toolcmdlist.extend(PathToolBitLibraryCmd.BarList)
toolbitcmdlist = PathToolBitLibraryCmd.MenuList
engravecmdgroup = ['Path_EngraveTools']
FreeCADGui.addCommand('Path_EngraveTools', PathCommandGroup(engravecmdlist, QtCore.QT_TRANSLATE_NOOP("Path", 'Engraving Operations')))
@@ -134,7 +137,7 @@ class PathWorkbench (Workbench):
self.appendToolbar(QtCore.QT_TRANSLATE_NOOP("Path", "Helpful Tools"), extracmdlist)
self.appendMenu([QtCore.QT_TRANSLATE_NOOP("Path", "&Path")], projcmdlist + ["Path_ExportTemplate", "Separator"] +
toolbitcmdlist + toolcmdlist + ["Separator"] + twodopcmdlist + engravecmdlist + ["Separator"] +
toolcmdlist + toolbitcmdlist + ["Separator"] + twodopcmdlist + engravecmdlist + ["Separator"] +
threedopcmdlist + ["Separator"])
self.appendMenu([QtCore.QT_TRANSLATE_NOOP("Path", "&Path"), QtCore.QT_TRANSLATE_NOOP(
"Path", "Path Dressup")], dressupcmdlist)

View File

@@ -94,6 +94,13 @@ def createModelResourceClone(obj, orig):
return createResourceClone(obj, orig, 'Model', 'BaseGeometry')
class NotificationClass(QtCore.QObject):
updateTC = QtCore.Signal(object, object)
Notification = NotificationClass()
class ObjectJob:
def __init__(self, obj, models, templateFile=None):
@@ -261,6 +268,7 @@ class ObjectJob:
self.setupBaseModel(obj)
self.fixupOperations(obj)
self.setupSetupSheet(obj)
obj.setEditorMode('Operations', 2) # hide
obj.setEditorMode('Placement', 2)
@@ -413,6 +421,7 @@ class ObjectJob:
tc.setExpression('HorizRapid', "%s.%s" % (self.setupSheet.expressionReference(), PathSetupSheet.Template.HorizRapid))
group.append(tc)
self.obj.ToolController = group
Notification.updateTC.emit(self.obj, tc)
def allOperations(self):
ops = []

View File

@@ -25,7 +25,6 @@ from collections import Counter
from contextlib import contextmanager
import math
import traceback
from pivy import coin
from PySide import QtCore, QtGui
@@ -45,6 +44,7 @@ import PathScripts.PathToolControllerGui as PathToolControllerGui
import PathScripts.PathToolLibraryEditor as PathToolLibraryEditor
import PathScripts.PathUtil as PathUtil
import PathScripts.PathUtils as PathUtils
import PathScripts.PathToolBitGui as PathToolBitGui
# lazily loaded modules
from lazy_loader.lazy_loader import LazyLoader
@@ -866,7 +866,15 @@ class TaskPanel:
self.toolControllerSelect()
def toolControllerAdd(self):
PathToolLibraryEditor.CommandToolLibraryEdit().edit(self.obj, self.updateToolController)
if PathPreferences.toolsUseLegacyTools():
PathToolLibraryEditor.CommandToolLibraryEdit().edit(self.obj, self.updateToolController)
else:
tools = PathToolBitGui.LoadTools()
for tool in tools:
tc = PathToolControllerGui.Create(name=tool.Label, tool=tool)
self.obj.Proxy.addToolController(tc)
FreeCAD.ActiveDocument.recompute()
self.updateToolController()
def toolControllerDelete(self):
self.objectDelete(self.form.toolControllerList)

View File

@@ -25,6 +25,7 @@ import FreeCADGui
import PathScripts.PathGeom as PathGeom
import PathScripts.PathGetPoint as PathGetPoint
import PathScripts.PathGui as PathGui
import PathScripts.PathJob as PathJob
import PathScripts.PathLog as PathLog
import PathScripts.PathOp as PathOp
import PathScripts.PathPreferences as PathPreferences
@@ -211,6 +212,9 @@ class TaskPanelPage(object):
self.parent = None
self.panelTitle = 'Operation'
if hasattr(self.form, 'toolController'):
PathJob.Notification.updateTC.connect(self.resetToolController)
def setParent(self, parent):
'''setParent() ... used to transfer parent object link to child class.
Do not overwrite.'''
@@ -361,6 +365,12 @@ class TaskPanelPage(object):
combo.setCurrentIndex(index)
combo.blockSignals(False)
def resetToolController(self, job, tc):
if self.obj is not None:
self.obj.ToolController = tc
combo = self.form.toolController
self.setupToolController(self.obj, combo)
def setupToolController(self, obj, combo):
'''setupToolController(obj, combo) ...
helper function to setup obj's ToolController
@@ -535,7 +545,7 @@ class TaskPanelBaseGeometryPage(TaskPanelPage):
PathLog.error(translate("PathProject", "Faces are not supported"))
return False
else:
if not self.supportsPanels() or not 'Panel' in sel.Object.Name:
if not self.supportsPanels() or 'Panel' not in sel.Object.Name:
if not ignoreErrors:
PathLog.error(translate("PathProject", "Please select %s of a solid" % self.featureName()))
return False
@@ -626,6 +636,7 @@ class TaskPanelBaseGeometryPage(TaskPanelPage):
row = (qList.count() + qList.frameWidth()) * 15
qList.setFixedSize(col, row)
class TaskPanelBaseLocationPage(TaskPanelPage):
'''Page controller for base locations. Uses PathGetPoint.'''
@@ -926,6 +937,7 @@ class TaskPanelDepthsPage(TaskPanelPage):
self.form.startDepthSet.setEnabled(False)
self.form.finalDepthSet.setEnabled(False)
class TaskPanelDiametersPage(TaskPanelPage):
'''Page controller for diameters.'''
@@ -950,7 +962,7 @@ class TaskPanelDiametersPage(TaskPanelPage):
self.minDiameter.updateProperty()
self.maxDiameter.updateProperty()
def setFields(self, obj):
def setFields(self, obj):
self.minDiameter.updateSpinBox()
self.maxDiameter.updateSpinBox()
@@ -964,6 +976,7 @@ class TaskPanelDiametersPage(TaskPanelPage):
if prop in ['MinDiameter', 'MaxDiameter']:
self.setFields(obj)
class TaskPanel(object):
'''
Generic TaskPanel implementation handling the standard Path operation layout.

View File

@@ -1,5 +1,7 @@
# -*- coding: utf-8 -*-
# ***************************************************************************
# * *
# * Copyright (c) 2014 Yorik van Havre <yorik@uncreated.net> *
# * *
# * This program is free software; you can redistribute it and/or modify *
@@ -25,8 +27,8 @@ import glob
import os
import PathScripts.PathLog as PathLog
PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule())
#PathLog.trackModule()
# PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule())
# PathLog.trackModule()
DefaultFilePath = "DefaultFilePath"
DefaultJobTemplate = "DefaultJobTemplate"
@@ -42,15 +44,19 @@ PostProcessorOutputPolicy = "PostProcessorOutputPolicy"
LastPathToolBit = "LastPathToolBit"
LastPathToolLibrary = "LastPathToolLibrary"
LastPathToolShape = "LastPathToolShape"
LastPathToolTable ="LastPathToolTable"
LastPathToolTable = "LastPathToolTable"
LastFileToolBit = "LastFileToolBit"
LastFileToolLibrary = "LastFileToolLibrary"
LastFileToolShape = "LastFileToolShape"
UseLegacyTools = "UseLegacyTools"
UseAbsoluteToolPaths = "UseAbsoluteToolPaths"
OpenLastLibrary = "OpenLastLibrary"
# Linear tolerance to use when generating Paths, eg when tessellating geometry
GeometryTolerance = "GeometryTolerance"
LibAreaCurveAccuracy = "LibAreaCurveAccuarcy"
GeometryTolerance = "GeometryTolerance"
LibAreaCurveAccuracy = "LibAreaCurveAccuarcy"
EnableExperimentalFeatures = "EnableExperimentalFeatures"
@@ -58,58 +64,70 @@ EnableExperimentalFeatures = "EnableExperimentalFeatures"
def preferences():
return FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Path")
def pathScriptsSourcePath():
return os.path.join(FreeCAD.getHomePath(), "Mod/Path/PathScripts/")
def pathDefaultToolsPath(sub=None):
if sub:
return os.path.join(FreeCAD.getHomePath(), "Mod/Path/Tools/", sub)
return os.path.join(FreeCAD.getHomePath(), "Mod/Path/Tools/")
def allAvailablePostProcessors():
allposts = []
for path in searchPathsPost():
posts = [ str(os.path.split(os.path.splitext(p)[0])[1][:-5]) for p in glob.glob(path + '/*_post.py')]
posts = [str(os.path.split(os.path.splitext(p)[0])[1][:-5]) for p in glob.glob(path + '/*_post.py')]
allposts.extend(posts)
allposts.sort()
return allposts
def allEnabledPostProcessors(include = None):
def allEnabledPostProcessors(include=None):
blacklist = postProcessorBlacklist()
enabled = [processor for processor in allAvailablePostProcessors() if not processor in blacklist]
enabled = [processor for processor in allAvailablePostProcessors() if processor not in blacklist]
if include:
l = list(set(include + enabled))
l.sort()
return l
postlist = list(set(include + enabled))
postlist.sort()
return postlist
return enabled
def defaultPostProcessor():
pref = preferences()
return pref.GetString(PostProcessorDefault, "")
def defaultPostProcessorArgs():
pref = preferences()
return pref.GetString(PostProcessorDefaultArgs, "")
def defaultGeometryTolerance():
return preferences().GetFloat(GeometryTolerance, 0.01)
def defaultLibAreaCurveAccuracy():
return preferences().GetFloat(LibAreaCurveAccuracy, 0.01)
def defaultFilePath():
return preferences().GetString(DefaultFilePath)
def filePath():
path = defaultFilePath()
if not path:
path = macroFilePath()
return path
def macroFilePath():
grp = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Macro")
return grp.GetString("MacroPath", FreeCAD.getUserMacroDir())
def searchPaths():
paths = []
p = defaultFilePath()
@@ -118,6 +136,7 @@ def searchPaths():
paths.append(macroFilePath())
return paths
def searchPathsPost():
paths = []
p = defaultFilePath()
@@ -128,11 +147,14 @@ def searchPathsPost():
paths.append(pathScriptsSourcePath())
return paths
def searchPathsTool(sub='Bit'):
paths = []
if 'Bit' == sub:
paths.append("{}/Bit".format(os.path.dirname(lastPathToolLibrary())))
paths.append(lastPathToolBit())
if 'Library' == sub:
paths.append(lastPathToolLibrary())
if 'Shape' == sub:
@@ -148,30 +170,37 @@ def searchPathsTool(sub='Bit'):
appendPath(os.path.join(FreeCAD.getHomePath(), "Mod/Path/"), sub)
return paths
def toolsUseLegacyTools():
return preferences().GetBool(UseLegacyTools, True)
return preferences().GetBool(UseLegacyTools, False)
def toolsReallyUseLegacyTools():
return toolsUseLegacyTools() or not experimentalFeaturesEnabled()
return toolsUseLegacyTools()
def toolsStoreAbsolutePaths():
return preferences().GetBool(UseAbsoluteToolPaths, False)
def toolsOpenLastLibrary():
return preferences().GetBool(OpenLastLibrary, False)
def setToolsSettings(legacy, relative, lastlibrary):
pref = preferences()
pref.SetBool(UseLegacyTools, legacy)
pref.SetBool(UseAbsoluteToolPaths, relative)
pref.SetBool(OpenLastLibrary, lastlibrary)
def defaultJobTemplate():
template = preferences().GetString(DefaultJobTemplate)
if 'xml' not in template:
return template
return ''
def setJobDefaults(fileName, jobTemplate, geometryTolerance, curveAccuracy):
PathLog.track("(%s='%s', %s, %s, %s)" % (DefaultFilePath, fileName, jobTemplate, geometryTolerance, curveAccuracy))
pref = preferences()
@@ -180,12 +209,14 @@ def setJobDefaults(fileName, jobTemplate, geometryTolerance, curveAccuracy):
pref.SetFloat(GeometryTolerance, geometryTolerance)
pref.SetFloat(LibAreaCurveAccuracy, curveAccuracy)
def postProcessorBlacklist():
pref = preferences()
blacklist = pref.GetString(PostProcessorBlacklist, "")
if not blacklist:
return []
return eval(blacklist) # pylint: disable=eval-used
return eval(blacklist) # pylint: disable=eval-used
def setPostProcessorDefaults(processor, args, blacklist):
pref = preferences()
@@ -193,54 +224,99 @@ def setPostProcessorDefaults(processor, args, blacklist):
pref.SetString(PostProcessorDefaultArgs, args)
pref.SetString(PostProcessorBlacklist, "%s" % (blacklist))
def setOutputFileDefaults(fileName, policy):
pref = preferences()
pref.SetString(PostProcessorOutputFile, fileName)
pref.SetString(PostProcessorOutputPolicy, policy)
def defaultOutputFile():
pref = preferences()
return pref.GetString(PostProcessorOutputFile, "")
def defaultOutputPolicy():
pref = preferences()
return pref.GetString(PostProcessorOutputPolicy, "")
def defaultStockTemplate():
return preferences().GetString(DefaultStockTemplate, "")
def setDefaultStockTemplate(template):
preferences().SetString(DefaultStockTemplate, template)
def defaultTaskPanelLayout():
return preferences().GetInt(DefaultTaskPanelLayout, 0)
def setDefaultTaskPanelLayout(style):
preferences().SetInt(DefaultTaskPanelLayout, style)
def experimentalFeaturesEnabled():
return preferences().GetBool(EnableExperimentalFeatures, False)
def lastFileToolLibrary():
filename = preferences().GetString(LastFileToolLibrary)
if filename.endswith('.fctl') and os.path.isfile(filename):
return filename
libpath = preferences().GetString(LastPathToolLibrary, pathDefaultToolsPath('Library'))
libFiles = [f for f in glob.glob(libpath + '/*.fctl')]
libFiles.sort()
if len(libFiles) >= 1:
filename = libFiles[0]
setLastFileToolLibrary(filename)
PathLog.track(filename)
return filename
else:
return None
def setLastFileToolLibrary(path):
PathLog.track(path)
if os.path.isfile(path): # keep the path and file in sync
preferences().SetString(LastPathToolLibrary, os.path.split(path)[0])
return preferences().SetString(LastFileToolLibrary, path)
def lastPathToolBit():
return preferences().GetString(LastPathToolBit, pathDefaultToolsPath('Bit'))
def setLastPathToolBit(path):
return preferences().SetString(LastPathToolBit, path)
def lastPathToolLibrary():
PathLog.track()
return preferences().GetString(LastPathToolLibrary, pathDefaultToolsPath('Library'))
def setLastPathToolLibrary(path):
PathLog.track(path)
curLib = lastFileToolLibrary()
if os.path.split(curLib)[0] != path:
setLastFileToolLibrary('') # a path is known but not specific file
return preferences().SetString(LastPathToolLibrary, path)
def lastPathToolShape():
return preferences().GetString(LastPathToolShape, pathDefaultToolsPath('Shape'))
def setLastPathToolShape(path):
return preferences().SetString(LastPathToolShape, path)
def lastPathToolTable():
return preferences().GetString(LastPathToolTable, "")
def setLastPathToolTable(table):
return preferences().SetString(LastPathToolTable, table)

View File

@@ -38,6 +38,7 @@ __doc__ = "Profile operation page controller and command implementation."
FeatureSide = 0x01
FeatureProcessing = 0x02
def translate(context, text, disambig=None):
return QtCore.QCoreApplication.translate(context, text, disambig)
@@ -127,8 +128,6 @@ class TaskPanelOpPage(PathOpGui.TaskPanelPage):
def updateVisibility(self):
hasFace = False
hasGeom = False
fullModel = False
objBase = list()
if hasattr(self.obj, 'Base'):
@@ -140,8 +139,6 @@ class TaskPanelOpPage(PathOpGui.TaskPanelPage):
if sub[:4] == 'Face':
hasFace = True
break
else:
fullModel = True
if hasFace:
self.form.processCircles.show()

View File

@@ -47,21 +47,54 @@ def translate(context, text, disambig=None):
LOG_MODULE = 'PathSanity'
PathLog.setLevel(PathLog.Level.INFO, LOG_MODULE)
# PathLog.setLevel(PathLog.Level.INFO, LOG_MODULE)
# PathLog.trackModule('PathSanity')
class CommandPathSanity:
baseobj = None
outputpath = PathPreferences.defaultOutputFile()
if outputpath == "":
outputpath = PathPreferences.macroFilePath()
if outputpath[-1] != os.sep:
outputpath += os.sep
if not os.path.exists(outputpath):
os.makedirs(outputpath)
squawkData = {"items": []}
def resolveOutputPath(self, job):
if job.PostProcessorOutputFile != "":
filepath = job.PostProcessorOutputFile
elif PathPreferences.defaultOutputFile() != "":
filepath = PathPreferences.defaultOutputFile()
else:
filepath = PathPreferences.macroFilePath()
if '%D' in filepath:
D = FreeCAD.ActiveDocument.FileName
if D:
D = os.path.dirname(D)
# in case the document is in the current working directory
if not D:
D = '.'
else:
FreeCAD.Console.PrintError("Please save document in order to resolve output path!\n")
return None
filepath = filepath.replace('%D', D)
if '%d' in filepath:
d = FreeCAD.ActiveDocument.Label
filepath = filepath.replace('%d', d)
if '%j' in filepath:
j = job.Label
filepath = filepath.replace('%j', j)
if '%M' in filepath:
pref = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Macro")
M = pref.GetString("MacroPath", FreeCAD.getUserAppDataDir())
filepath = filepath.replace('%M', M)
PathLog.debug('filepath: {}'.format(filepath))
# starting at the derived filename, iterate up until we have a valid
# directory to write to
while not os.path.isdir(filepath):
filepath = os.path.dirname(filepath)
PathLog.debug('filepath: {}'.format(filepath))
return filepath + os.sep
def GetResources(self):
return {'Pixmap': 'Path-Sanity',
@@ -77,9 +110,10 @@ class CommandPathSanity:
def Activated(self):
# if everything is ok, execute
self.squawkData["items"] = []
self.squawkData = {"items": []}
obj = FreeCADGui.Selection.getSelectionEx()[0].Object
self.outputpath = self.resolveOutputPath(obj)
data = self.__summarize(obj)
html = self.__report(data)
if html is not None:
@@ -369,8 +403,8 @@ class CommandPathSanity:
# Save the report
reportraw = self.outputpath + '/setupreport.asciidoc'
reporthtml = self.outputpath + '/setupreport.html'
reportraw = self.outputpath + 'setupreport.asciidoc'
reporthtml = self.outputpath + 'setupreport.html'
with open(reportraw, 'w') as fd:
fd.write(report)
fd.close()
@@ -505,7 +539,7 @@ class CommandPathSanity:
tooldata['partNumber'] = ""
imagedata = TC.Tool.Proxy.getBitThumbnail(TC.Tool)
imagepath = '{}/T{}.png'.format(self.outputpath, TC.ToolNumber)
imagepath = '{}T{}.png'.format(self.outputpath, TC.ToolNumber)
tooldata['feedrate'] = str(TC.HorizFeed)
if TC.HorizFeed.Value == 0.0:
self.squawk("PathSanity",
@@ -646,7 +680,7 @@ class CommandPathSanity:
view.showNormal()
view.resize(320, 320)
imagepath = '{}/origin'.format(self.outputpath)
imagepath = '{}origin'.format(self.outputpath)
FreeCADGui.Selection.clearSelection()
FreeCADGui.SendMsgToActiveView("PerspectiveCamera")

View File

@@ -45,29 +45,32 @@ __doc__ = "Class to deal with and represent a tool bit."
# PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule())
# PathLog.trackModule()
def translate(context, text, disambig=None):
return PySide.QtCore.QCoreApplication.translate(context, text, disambig)
ParameterTypeConstraint = {
'Angle': 'App::PropertyAngle',
'Distance': 'App::PropertyLength',
'DistanceX': 'App::PropertyLength',
'DistanceY': 'App::PropertyLength',
'Radius': 'App::PropertyLength'
}
'Radius': 'App::PropertyLength'}
def _findTool(path, typ, dbg=False):
if os.path.exists(path):
if os.path.exists(path): # absolute reference
if dbg:
PathLog.debug("Found {} at {}".format(typ, path))
return path
def searchFor(pname, fname):
# PathLog.debug("pname: {} fname: {}".format(pname, fname))
if dbg:
PathLog.debug("Looking for {}".format(pname))
if fname:
for p in PathPreferences.searchPathsTool(typ):
PathLog.track(p)
f = os.path.join(p, fname)
if dbg:
PathLog.debug(" Checking {}".format(f))
@@ -76,6 +79,7 @@ def _findTool(path, typ, dbg=False):
PathLog.debug(" Found {} at {}".format(typ, f))
return f
if pname and os.path.sep != pname:
PathLog.track(pname)
ppname, pfname = os.path.split(pname)
ffname = os.path.join(pfname, fname) if fname else pfname
return searchFor(ppname, ffname)
@@ -83,20 +87,28 @@ def _findTool(path, typ, dbg=False):
return searchFor(path, '')
def findShape(path):
'''findShape(path) ... search for path, full and partially in all known shape directories.'''
'''
findShape(path) ... search for path, full and partially
in all known shape directories.
'''
return _findTool(path, 'Shape')
def findBit(path):
PathLog.track(path)
if path.endswith('.fctb'):
return _findTool(path, 'Bit')
return _findTool("{}.fctb".format(path), 'Bit')
def findLibrary(path, dbg=False):
if path.endswith('.fctl'):
return _findTool(path, 'Library', dbg)
return _findTool("{}.fctl".format(path), 'Library', dbg)
def _findRelativePath(path, typ):
relative = path
for p in PathPreferences.searchPathsTool(typ):
@@ -108,15 +120,19 @@ def _findRelativePath(path, typ):
relative = p
return relative
def findRelativePathShape(path):
return _findRelativePath(path, 'Shape')
def findRelativePathTool(path):
return _findRelativePath(path, 'Bit')
def findRelativePathLibrary(path):
return _findRelativePath(path, 'Library')
def updateConstraint(sketch, name, value):
for i, constraint in enumerate(sketch.Constraints):
if constraint.Name.split(';')[0] == name:
@@ -128,7 +144,9 @@ def updateConstraint(sketch, name, value):
if constr is not None:
if not PathGeom.isRoughly(constraint.Value, value.Value):
PathLog.track(name, constraint.Type, 'update', i, "(%.2f -> %.2f)" % (constraint.Value, value.Value))
PathLog.track(name, constraint.Type,
'update', i, "(%.2f -> %.2f)"
% (constraint.Value, value.Value))
sketch.delConstraint(i)
sketch.recompute()
n = sketch.addConstraint(constr)
@@ -141,15 +159,21 @@ def updateConstraint(sketch, name, value):
PropertyGroupBit = 'Bit'
PropertyGroupAttribute = 'Attribute'
class ToolBit(object):
def __init__(self, obj, shapeFile):
PathLog.track(obj.Label, shapeFile)
self.obj = obj
obj.addProperty('App::PropertyFile', 'BitShape', 'Base', translate('PathToolBit', 'Shape for bit shape'))
obj.addProperty('App::PropertyLink', 'BitBody', 'Base', translate('PathToolBit', 'The parametrized body representing the tool bit'))
obj.addProperty('App::PropertyFile', 'File', 'Base', translate('PathToolBit', 'The file of the tool'))
obj.addProperty('App::PropertyString', 'ShapeName', 'Base', translate('PathToolBit', 'The name of the shape file'))
obj.addProperty('App::PropertyFile', 'BitShape', 'Base',
translate('PathToolBit', 'Shape for bit shape'))
obj.addProperty('App::PropertyLink', 'BitBody', 'Base',
translate('PathToolBit',
'The parametrized body representing the tool bit'))
obj.addProperty('App::PropertyFile', 'File', 'Base',
translate('PathToolBit', 'The file of the tool'))
obj.addProperty('App::PropertyString', 'ShapeName', 'Base',
translate('PathToolBit', 'The name of the shape file'))
if shapeFile is None:
obj.BitShape = 'endmill.fcstd'
self._setupBitShape(obj)
@@ -184,14 +208,14 @@ class ToolBit(object):
for prop in self.propertyNamesBit(obj):
obj.setEditorMode(prop, 1)
# I currently don't see why these need to be read-only
#for prop in self.propertyNamesAttribute(obj):
# for prop in self.propertyNamesAttribute(obj):
# obj.setEditorMode(prop, 1)
def onChanged(self, obj, prop):
PathLog.track(obj.Label, prop)
if prop == 'BitShape' and not 'Restore' in obj.State:
if prop == 'BitShape' and 'Restore' not in obj.State:
self._setupBitShape(obj)
#elif obj.getGroupOfProperty(prop) == PropertyGroupBit:
# elif obj.getGroupOfProperty(prop) == PropertyGroupBit:
# self._updateBitShape(obj, [prop])
def onDelete(self, obj, arg2=None):
@@ -200,7 +224,7 @@ class ToolBit(object):
obj.Document.removeObject(obj.Name)
def _updateBitShape(self, obj, properties=None):
if not obj.BitBody is None:
if obj.BitBody is not None:
if not properties:
properties = self.propertyNamesBit(obj)
for prop in properties:
@@ -234,7 +258,6 @@ class ToolBit(object):
return (doc, docOpened)
def _removeBitBody(self, obj):
print('in _removebitbody')
if obj.BitBody:
obj.BitBody.removeObjectsFromDocument()
obj.Document.removeObject(obj.BitBody.Name)
@@ -286,7 +309,7 @@ class ToolBit(object):
prop = parts[0]
desc = ''
if len(parts) > 1:
desc = parts[1]
desc = parts[1]
obj.addProperty(typ, prop, PropertyGroupBit, desc)
obj.setEditorMode(prop, 1)
value = constraint.Value
@@ -307,7 +330,7 @@ class ToolBit(object):
return None
def saveToFile(self, obj, path, setFile=True):
print('were saving now')
PathLog.track(path)
try:
with open(path, 'w') as fp:
json.dump(self.templateAttrs(obj), fp, indent=' ')
@@ -315,12 +338,13 @@ class ToolBit(object):
obj.File = path
return True
except (OSError, IOError) as e:
PathLog.error("Could not save tool %s to %s (%s)" % (obj.Label, path, e))
PathLog.error("Could not save tool {} to {} ({})".format(
obj.Label, path, e))
raise
def templateAttrs(self, obj):
attrs = {}
attrs['version'] = 2 # Path.Tool is version 1
attrs['version'] = 2 # Path.Tool is version 1
attrs['name'] = obj.Label
if PathPreferences.toolsStoreAbsolutePaths():
attrs['shape'] = obj.BitShape
@@ -332,7 +356,6 @@ class ToolBit(object):
attrs['parameter'] = params
params = {}
for name in self.propertyNamesAttribute(obj):
#print(f"shapeattr {name}")
if name == "UserAttributes":
for key, value in obj.UserAttributes.items():
params[key] = value
@@ -341,26 +364,43 @@ class ToolBit(object):
attrs['attribute'] = params
return attrs
def Declaration(path):
PathLog.track(path)
with open(path, 'r') as fp:
return json.load(fp)
class AttributePrototype(PathSetupSheetOpPrototype.OpPrototype):
def __init__(self):
PathSetupSheetOpPrototype.OpPrototype.__init__(self, 'ToolBitAttribute')
self.addProperty('App::PropertyEnumeration', 'Material', PropertyGroupAttribute, translate('PathToolBit', 'Tool bit material'))
self.Material = ['Carbide', 'CastAlloy', 'Ceramics', 'Diamond', 'HighCarbonToolSteel', 'HighSpeedSteel', 'Sialon']
self.addProperty('App::PropertyDistance', 'LengthOffset', PropertyGroupAttribute, translate('PathToolBit', 'Length offset in Z direction'))
self.addProperty('App::PropertyInteger', 'Flutes', PropertyGroupAttribute, translate('PathToolBit', 'The number of flutes'))
self.addProperty('App::PropertyDistance', 'ChipLoad', PropertyGroupAttribute, translate('PathToolBit', 'Chipload as per manufacturer'))
self.addProperty('App::PropertyMap', 'UserAttributes', PropertyGroupAttribute, translate('PathTooolBit', 'User Defined Values'))
self.addProperty('App::PropertyEnumeration', 'Material',
PropertyGroupAttribute,
translate('PathToolBit', 'Tool bit material'))
self.Material = ['Carbide', 'CastAlloy', 'Ceramics', 'Diamond',
'HighCarbonToolSteel', 'HighSpeedSteel', 'Sialon']
self.addProperty('App::PropertyDistance', 'LengthOffset',
PropertyGroupAttribute, translate('PathToolBit',
'Length offset in Z direction'))
self.addProperty('App::PropertyInteger', 'Flutes',
PropertyGroupAttribute, translate('PathToolBit',
'The number of flutes'))
self.addProperty('App::PropertyDistance', 'ChipLoad',
PropertyGroupAttribute, translate('PathToolBit',
'Chipload as per manufacturer'))
self.addProperty('App::PropertyMap', 'UserAttributes',
PropertyGroupAttribute, translate('PathToolBit',
'User Defined Values'))
self.addProperty('App::PropertyBool', 'SpindlePower',
PropertyGroupAttribute, translate('PathToolBit',
'Whether Spindle Power should be allowed'))
class ToolBitFactory(object):
def CreateFromAttrs(self, attrs, name='ToolBit'):
# pylint: disable=protected-access
PathLog.debug(attrs)
obj = Factory.Create(name, attrs['shape'])
obj.Label = attrs['name']
params = attrs['parameter']
@@ -372,23 +412,17 @@ class ToolBitFactory(object):
proto = AttributePrototype()
uservals = {}
for pname in params:
#print(f"pname: {pname}")
try:
prop = proto.getProperty(pname)
val = prop.valueFromString(params[pname])
prop.setupProperty(obj, pname, PropertyGroupAttribute, prop.valueFromString(params[pname]))
except:
# prop = obj.addProperty('App::PropertyString', pname, "Attribute", translate('PathTooolBit', 'User Defined Value'))
# setattr(obj, pname, params[pname])
except Exception:
prop = proto.getProperty("UserAttributes")
uservals.update({pname: params[pname]})
#prop.setupProperty(obj, pname, "UserAttributes", prop.valueFromString(params[pname]))
if len(uservals.items()) > 0:
prop.setupProperty(obj, "UserAttributes", PropertyGroupAttribute, uservals)
prop.setupProperty(obj, "UserAttributes",
PropertyGroupAttribute, uservals)
# print("prop[%s] = %s (%s)" % (pname, params[pname], type(val)))
#prop.setupProperty(obj, pname, PropertyGroupAttribute, prop.valueFromString(params[pname]))
return obj
def CreateFrom(self, path, name='ToolBit'):
@@ -406,4 +440,5 @@ class ToolBitFactory(object):
obj.Proxy = ToolBit(obj, shapeFile)
return obj
Factory = ToolBitFactory()

View File

@@ -31,7 +31,7 @@ import re
from PySide import QtCore, QtGui
# PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule())
PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule())
# PathLog.trackModule(PathLog.thisModule())
@@ -42,10 +42,12 @@ def translate(context, text, disambig=None):
class ToolBitEditor(object):
'''UI and controller for editing a ToolBit.
The controller embeds the UI to the parentWidget which has to have a layout attached to it.
The controller embeds the UI to the parentWidget which has to have a
layout attached to it.
'''
def __init__(self, tool, parentWidget=None):
def __init__(self, tool, parentWidget=None, loadBitBody=True):
PathLog.track()
self.form = FreeCADGui.PySideUic.loadUi(":/panels/ToolBitEditor.ui")
if parentWidget:
@@ -53,13 +55,18 @@ class ToolBitEditor(object):
parentWidget.layout().addWidget(self.form)
self.tool = tool
self.loadbitbody = loadBitBody
if not tool.BitShape:
self.tool.BitShape = 'endmill.fcstd'
self.tool.Proxy.loadBitBody(self.tool)
if self.loadbitbody:
self.tool.Proxy.loadBitBody(self.tool)
self.setupTool(self.tool)
self.setupAttributes(self.tool)
def setupTool(self, tool):
PathLog.track()
layout = self.form.bitParams.layout()
for i in range(layout.rowCount() - 1, -1, -1):
layout.removeRow(i)
@@ -69,7 +76,8 @@ class ToolBitEditor(object):
if tool.getGroupOfProperty(name) == PathToolBit.PropertyGroupBit:
qsb = ui.createWidget('Gui::QuantitySpinBox')
editor[name] = PathGui.QuantitySpinBox(qsb, tool, name)
label = QtGui.QLabel(re.sub('([A-Z][a-z]+)', r' \1', re.sub('([A-Z]+)', r' \1', name)))
label = QtGui.QLabel(re.sub('([A-Z][a-z]+)', r' \1',
re.sub('([A-Z]+)', r' \1', name)))
layout.addRow(label, qsb)
self.bitEditor = editor
img = tool.Proxy.getBitThumbnail(tool)
@@ -79,6 +87,7 @@ class ToolBitEditor(object):
self.form.image.setPixmap(QtGui.QPixmap())
def setupAttributes(self, tool):
PathLog.track()
self.proto = PathToolBit.AttributePrototype()
self.props = sorted(self.proto.properties)
self.delegate = PathSetupSheetGui.Delegate(self.form)
@@ -86,7 +95,7 @@ class ToolBitEditor(object):
self.model.setHorizontalHeaderLabels(['Set', 'Property', 'Value'])
for i, name in enumerate(self.props):
print("propname: %s " % name)
PathLog.debug("propname: %s " % name)
prop = self.proto.getProperty(name)
isset = hasattr(tool, name)
@@ -99,10 +108,15 @@ class ToolBitEditor(object):
else:
self.model.setData(self.model.index(i, 0), isset, QtCore.Qt.EditRole)
self.model.setData(self.model.index(i, 1), name, QtCore.Qt.EditRole)
self.model.setData(self.model.index(i, 2), prop, PathSetupSheetGui.Delegate.PropertyRole)
self.model.setData(self.model.index(i, 2), prop.displayString(), QtCore.Qt.DisplayRole)
self.model.setData(self.model.index(i, 0), isset,
QtCore.Qt.EditRole)
self.model.setData(self.model.index(i, 1), name,
QtCore.Qt.EditRole)
self.model.setData(self.model.index(i, 2), prop,
PathSetupSheetGui.Delegate.PropertyRole)
self.model.setData(self.model.index(i, 2),
prop.displayString(),
QtCore.Qt.DisplayRole)
self.model.item(i, 0).setCheckable(True)
self.model.item(i, 0).setText('')
@@ -119,7 +133,7 @@ class ToolBitEditor(object):
if hasattr(tool, "UserAttributes"):
for key, value in tool.UserAttributes.items():
print(key, value)
PathLog.debug(key, value)
c1 = QtGui.QStandardItem()
c1.setCheckable(False)
c1.setEditable(False)
@@ -141,26 +155,33 @@ class ToolBitEditor(object):
self.model.dataChanged.connect(self.updateData)
def updateData(self, topLeft, bottomRight):
# pylint: disable=unused-argument
PathLog.track()
if 0 == topLeft.column():
isset = self.model.item(topLeft.row(), 0).checkState() == QtCore.Qt.Checked
isset = self.model.item(topLeft.row(),
0).checkState() == QtCore.Qt.Checked
self.model.item(topLeft.row(), 1).setEnabled(isset)
self.model.item(topLeft.row(), 2).setEnabled(isset)
def accept(self):
PathLog.track()
self.refresh()
self.tool.Proxy.unloadBitBody(self.tool)
# get the attributes
for i, name in enumerate(self.props):
PathLog.debug('in accept: {}'.format(name))
prop = self.proto.getProperty(name)
enabled = self.model.item(i, 0).checkState() == QtCore.Qt.Checked
if enabled and not prop.getValue() is None:
prop.setupProperty(self.tool, name, PathToolBit.PropertyGroupAttribute, prop.getValue())
elif hasattr(self.tool, name):
self.tool.removeProperty(name)
if self.model.item(i, 0) is not None:
enabled = self.model.item(i, 0).checkState() == QtCore.Qt.Checked
if enabled and not prop.getValue() is None:
prop.setupProperty(self.tool, name,
PathToolBit.PropertyGroupAttribute,
prop.getValue())
elif hasattr(self.tool, name):
self.tool.removeProperty(name)
def reject(self):
PathLog.track()
self.tool.Proxy.unloadBitBody(self.tool)
def updateUI(self):
@@ -172,6 +193,7 @@ class ToolBitEditor(object):
self.bitEditor[editor].updateSpinBox()
def updateShape(self):
PathLog.track()
self.tool.BitShape = str(self.form.shapePath.text())
self.setupTool(self.tool)
self.form.toolName.setText(self.tool.Label)
@@ -180,7 +202,6 @@ class ToolBitEditor(object):
self.bitEditor[editor].updateSpinBox()
def updateTool(self):
# pylint: disable=protected-access
PathLog.track()
self.tool.Label = str(self.form.toolName.text())
self.tool.BitShape = str(self.form.shapePath.text())
@@ -188,7 +209,7 @@ class ToolBitEditor(object):
for editor in self.bitEditor:
self.bitEditor[editor].updateProperty()
self.tool.Proxy._updateBitShape(self.tool)
# self.tool.Proxy._updateBitShape(self.tool)
def refresh(self):
PathLog.track()
@@ -198,13 +219,14 @@ class ToolBitEditor(object):
self.form.blockSignals(False)
def selectShape(self):
PathLog.track()
path = self.tool.BitShape
if not path:
path = PathPreferences.lastPathToolShape()
foo = QtGui.QFileDialog.getOpenFileName(self.form,
"Path - Tool Shape",
path,
"*.fcstd")
"Path - Tool Shape",
path,
"*.fcstd")
if foo and foo[0]:
PathPreferences.setLastPathToolShape(os.path.dirname(foo[0]))
self.form.shapePath.setText(foo[0])

View File

@@ -36,12 +36,15 @@ __author__ = "sliptonic (Brad Collette)"
__url__ = "https://www.freecadweb.org"
__doc__ = "Task panel editor for a ToolBit"
# Qt translation handling
def translate(context, text, disambig=None):
return QtCore.QCoreApplication.translate(context, text, disambig)
#PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule())
#PathLog.trackModule(PathLog.thisModule())
PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule())
# PathLog.trackModule(PathLog.thisModule())
class ViewProvider(object):
'''ViewProvider for a ToolBit.
@@ -58,7 +61,7 @@ class ViewProvider(object):
def attach(self, vobj):
PathLog.track(vobj.Object)
self.vobj = vobj
self.obj = vobj.Object
self.obj = vobj.Object
def getIcon(self):
png = self.obj.Proxy.getBitThumbnail(self.obj)
@@ -111,7 +114,15 @@ class ViewProvider(object):
return []
def doubleClicked(self, vobj):
self.setEdit(vobj)
if os.path.exists(vobj.Object.BitShape):
self.setEdit(vobj)
else:
msg = translate('PathToolBit',
'Toolbit cannot be edited: Shapefile not found')
diag = QtGui.QMessageBox(QtGui.QMessageBox.Warning, 'Error', msg)
diag.setWindowModality(QtCore.Qt.ApplicationModal)
diag.exec_()
class TaskPanel:
'''TaskPanel for the SetupSheet - if it is being edited directly.'''
@@ -123,7 +134,8 @@ class TaskPanel:
self.editor = PathToolBitEdit.ToolBitEditor(self.obj)
self.form = self.editor.form
self.deleteOnReject = deleteOnReject
FreeCAD.ActiveDocument.openTransaction(translate('PathToolBit', 'Edit ToolBit'))
FreeCAD.ActiveDocument.openTransaction(translate('PathToolBit',
'Edit ToolBit'))
def reject(self):
FreeCAD.ActiveDocument.abortTransaction()
@@ -145,6 +157,7 @@ class TaskPanel:
FreeCAD.ActiveDocument.recompute()
def updateUI(self):
PathLog.track()
self.editor.updateUI()
def updateModel(self):
@@ -155,141 +168,91 @@ class TaskPanel:
self.editor.setupUI()
class ToolBitSelector(object):
ToolRole = QtCore.Qt.UserRole + 1
def __init__(self):
self.buttons = None
self.editor = None
self.dialog = None
self.form = FreeCADGui.PySideUic.loadUi(':/panels/ToolBitSelector.ui')
self.setupUI()
def updateTools(self, selected=None):
PathLog.track()
selItem = None
self.form.tools.setUpdatesEnabled(False)
if selected is None and self.form.tools.currentItem():
selected = self.form.tools.currentItem().text()
self.form.tools.clear()
for tool in sorted(self.loadedTools(), key=lambda t: t.Label):
icon = None
if tool.ViewObject and tool.ViewObject.Proxy:
icon = tool.ViewObject.Proxy.getIcon()
if icon and isinstance(icon, QtGui.QIcon):
item = QtGui.QListWidgetItem(icon, tool.Label)
else:
item = QtGui.QListWidgetItem(tool.Label)
item.setData(self.ToolRole, tool)
if selected == tool.Label:
selItem = item
self.form.tools.addItem(item)
if selItem:
self.form.tools.setCurrentItem(selItem)
self.updateSelection()
self.form.tools.setUpdatesEnabled(True)
def getTool(self):
PathLog.track()
self.updateTools()
res = self.form.exec_()
if 1 == res and self.form.tools.currentItem():
return self.form.tools.currentItem().data(self.ToolRole)
return None
def loadedTools(self):
PathLog.track()
if FreeCAD.ActiveDocument:
return [o for o in FreeCAD.ActiveDocument.Objects if hasattr(o, 'Proxy') and isinstance(o.Proxy, PathToolBit.ToolBit)]
return []
def loadTool(self):
PathLog.track()
tool = LoadTool(self.form)
if tool:
self.updateTools(tool.Label)
def createTool(self):
PathLog.track()
tool = PathToolBit.Factory.Create()
def accept():
self.editor.accept()
self.dialog.done(1)
self.updateTools(tool.Label)
def reject():
FreeCAD.ActiveDocument.openTransaction(translate('PathToolBit', 'Uncreate ToolBit'))
self.editor.reject()
self.dialog.done(0)
FreeCAD.ActiveDocument.removeObject(tool.Name)
FreeCAD.ActiveDocument.commitTransaction()
self.dialog = QtGui.QDialog(self.form)
layout = QtGui.QVBoxLayout(self.dialog)
self.editor = PathToolBitEdit.ToolBitEditor(tool, self.dialog)
self.editor.setupUI()
self.buttons = QtGui.QDialogButtonBox(
QtGui.QDialogButtonBox.Ok | QtGui.QDialogButtonBox.Cancel,
QtCore.Qt.Horizontal, self.dialog)
layout.addWidget(self.buttons)
self.buttons.accepted.connect(accept)
self.buttons.rejected.connect(reject)
print(self.dialog.exec_())
def updateSelection(self):
PathLog.track()
if self.form.tools.selectedItems():
self.form.buttonBox.button(QtGui.QDialogButtonBox.Ok).setEnabled(True)
else:
self.form.buttonBox.button(QtGui.QDialogButtonBox.Ok).setEnabled(False)
def setupUI(self):
PathLog.track()
self.form.toolCreate.clicked.connect(self.createTool)
self.form.toolLoad.clicked.connect(self.loadTool)
self.form.tools.itemSelectionChanged.connect(self.updateSelection)
self.form.tools.doubleClicked.connect(self.form.accept)
class ToolBitGuiFactory(PathToolBit.ToolBitFactory):
def Create(self, name='ToolBit', shapeFile=None):
'''Create(name = 'ToolBit') ... creates a new tool bit.
It is assumed the tool will be edited immediately so the internal bit body is still attached.'''
FreeCAD.ActiveDocument.openTransaction(translate('PathToolBit', 'Create ToolBit'))
FreeCAD.ActiveDocument.openTransaction(translate('PathToolBit',
'Create ToolBit'))
tool = PathToolBit.ToolBitFactory.Create(self, name, shapeFile)
PathIconViewProvider.Attach(tool.ViewObject, name)
FreeCAD.ActiveDocument.commitTransaction()
return tool
def GetToolFile(parent = None):
def GetNewToolFile(parent=None):
if parent is None:
parent = QtGui.QApplication.activeWindow()
foo = QtGui.QFileDialog.getOpenFileName(parent, 'Tool', PathPreferences.lastPathToolBit(), '*.fctb')
foo = QtGui.QFileDialog.getSaveFileName(parent, 'Tool',
PathPreferences.lastPathToolBit(),
'*.fctb')
if foo and foo[0]:
PathPreferences.setLastPathToolBit(os.path.dirname(foo[0]))
return foo[0]
return None
def GetToolFiles(parent = None):
def GetToolFile(parent=None):
if parent is None:
parent = QtGui.QApplication.activeWindow()
foo = QtGui.QFileDialog.getOpenFileNames(parent, 'Tool', PathPreferences.lastPathToolBit(), '*.fctb')
foo = QtGui.QFileDialog.getOpenFileName(parent, 'Tool',
PathPreferences.lastPathToolBit(),
'*.fctb')
if foo and foo[0]:
PathPreferences.setLastPathToolBit(os.path.dirname(foo[0]))
return foo[0]
return None
def GetToolFiles(parent=None):
if parent is None:
parent = QtGui.QApplication.activeWindow()
foo = QtGui.QFileDialog.getOpenFileNames(parent, 'Tool',
PathPreferences.lastPathToolBit(),
'*.fctb')
if foo and foo[0]:
PathPreferences.setLastPathToolBit(os.path.dirname(foo[0][0]))
return foo[0]
return []
def LoadTool(parent = None):
'''LoadTool(parent=None) ... Open a file dialog to load a tool from a file.'''
def GetToolShapeFile(parent=None):
if parent is None:
parent = QtGui.QApplication.activeWindow()
location = PathPreferences.lastPathToolShape()
if os.path.isfile(location):
location = os.path.split(location)[0]
elif not os.path.isdir(location):
location = PathPreferences.filePath()
fname = QtGui.QFileDialog.getOpenFileName(parent, 'Select Tool Shape',
location, '*.fcstd')
if fname and fname[0]:
if fname != location:
PathPreferences.setLastPathToolShape(location)
return fname[0]
else:
return None
def LoadTool(parent=None):
'''
LoadTool(parent=None) ... Open a file dialog to load a tool from a file.
'''
foo = GetToolFile(parent)
return PathToolBit.Factory.CreateFrom(foo) if foo else foo
def LoadTools(parent = None):
'''LoadTool(parent=None) ... Open a file dialog to load a tool from a file.'''
def LoadTools(parent=None):
'''
LoadTool(parent=None) ... Open a file dialog to load a tool from a file.
'''
return [PathToolBit.Factory.CreateFrom(foo) for foo in GetToolFiles(parent)]
# Set the factory so all tools are created with UI
PathToolBit.Factory = ToolBitGuiFactory()

View File

@@ -25,9 +25,10 @@ import FreeCADGui
import PySide.QtCore as QtCore
import PathScripts.PathPreferences as PathPreferences
class CommandToolBitLibraryOpen:
class CommandToolBitSelectorOpen:
'''
Command to ToolBitLibrary editor.
Command to toggle the ToolBitSelector Dock
'''
def __init__(self):
@@ -35,11 +36,42 @@ class CommandToolBitLibraryOpen:
def GetResources(self):
return {'Pixmap': 'Path-ToolTable',
'MenuText': QtCore.QT_TRANSLATE_NOOP("PathToolBitLibrary", "Open ToolBit Library editor"),
'ToolTip': QtCore.QT_TRANSLATE_NOOP("PathToolBitLibrary", "Open an editor to manage ToolBit libraries")}
'MenuText': QtCore.QT_TRANSLATE_NOOP("PathToolBitLibrary", "ToolBit Dock"),
'ToolTip': QtCore.QT_TRANSLATE_NOOP("PathToolBitLibrary", "Toggle the Toolbit Dock"),
'Accel': "P, T",
'CmdType': "ForEdit"}
def IsActive(self):
return True
return FreeCAD.ActiveDocument is not None
def Activated(self):
import PathScripts.PathToolBitLibraryGui as PathToolBitLibraryGui
dock = PathToolBitLibraryGui.ToolBitSelector()
lastlib = PathPreferences.lastPathToolLibrary()
if PathPreferences.toolsOpenLastLibrary():
dock.open(lastlib)
else:
dock.open()
class CommandToolBitLibraryOpen:
'''
Command to open ToolBitLibrary editor.
'''
def __init__(self):
pass
def GetResources(self):
return {'Pixmap': 'Path-ToolTable',
'MenuText': QtCore.QT_TRANSLATE_NOOP("PathToolBitLibrary", "ToolBit Library editor"),
'ToolTip': QtCore.QT_TRANSLATE_NOOP("PathToolBitLibrary", "Open an editor to manage ToolBit libraries"),
'CmdType': "ForEdit"}
def IsActive(self):
return FreeCAD.ActiveDocument is not None
def Activated(self):
import PathScripts.PathToolBitLibraryGui as PathToolBitLibraryGui
@@ -52,55 +84,57 @@ class CommandToolBitLibraryOpen:
else:
library.open()
class CommandToolBitLibraryLoad:
'''
Command used to load an entire ToolBitLibrary (or part of it) from a file into a job.
'''
# class CommandToolBitLibraryLoad:
# '''
# Command used to load an entire ToolBitLibrary (or part of it) from a file into a job.
# '''
def __init__(self):
pass
# def __init__(self):
# pass
def GetResources(self):
return {'Pixmap': 'Path-ToolTable',
'MenuText': QtCore.QT_TRANSLATE_NOOP("PathToolBitLibrary", "Load ToolBit Library"),
'ToolTip': QtCore.QT_TRANSLATE_NOOP("PathToolBitLibrary", "Load an entire ToolBit library or part of it into a job")}
# def GetResources(self):
# return {'Pixmap': 'Path-ToolTable',
# 'MenuText': QtCore.QT_TRANSLATE_NOOP("PathToolBitLibrary", "Load ToolBit Library"),
# 'ToolTip': QtCore.QT_TRANSLATE_NOOP("PathToolBitLibrary", "Load an entire ToolBit library or part of it into a job")}
def selectedJob(self):
if FreeCAD.ActiveDocument:
sel = FreeCADGui.Selection.getSelectionEx()
if sel and sel[0].Object.Name[:3] == 'Job':
return sel[0].Object
jobs = [o for o in FreeCAD.ActiveDocument.Objects if o.Name[:3] == 'Job']
if 1 == len(jobs):
return jobs[0]
return None
# def selectedJob(self):
# if FreeCAD.ActiveDocument:
# sel = FreeCADGui.Selection.getSelectionEx()
# if sel and sel[0].Object.Name[:3] == 'Job':
# return sel[0].Object
# jobs = [o for o in FreeCAD.ActiveDocument.Objects if o.Name[:3] == 'Job']
# if 1 == len(jobs):
# return jobs[0]
# return None
def IsActive(self):
return not self.selectedJob() is None
# def IsActive(self):
# return not self.selectedJob() is None
def Activated(self):
job = self.selectedJob()
self.Execute(job)
# def Activated(self):
# job = self.selectedJob()
# self.Execute(job)
@classmethod
def Execute(cls, job):
import PathScripts.PathToolBitLibraryGui as PathToolBitLibraryGui
import PathScripts.PathToolControllerGui as PathToolControllerGui
# @classmethod
# def Execute(cls, job):
# import PathScripts.PathToolBitLibraryGui as PathToolBitLibraryGui
# import PathScripts.PathToolControllerGui as PathToolControllerGui
library = PathToolBitLibraryGui.ToolBitLibrary()
# library = PathToolBitLibraryGui.ToolBitLibrary()
# if 1 == library.open() and job:
# for nr, tool in library.selectedOrAllTools():
# tc = PathToolControllerGui.Create("TC: {}".format(tool.Label), tool, nr)
# job.Proxy.addToolController(tc)
# FreeCAD.ActiveDocument.recompute()
# return True
# return False
if 1 == library.open() and job:
for nr, tool in library.selectedOrAllTools():
tc = PathToolControllerGui.Create("TC: {}".format(tool.Label), tool, nr)
job.Proxy.addToolController(tc)
FreeCAD.ActiveDocument.recompute()
return True
return False
if FreeCAD.GuiUp:
FreeCADGui.addCommand('Path_ToolBitLibraryOpen', CommandToolBitLibraryOpen())
FreeCADGui.addCommand('Path_ToolBitLibraryLoad', CommandToolBitLibraryLoad())
FreeCADGui.addCommand('Path_ToolBitDock', CommandToolBitSelectorOpen())
CommandList = ['Path_ToolBitLibraryOpen', 'Path_ToolBitLibraryLoad']
BarList = ['Path_ToolBitDock']
MenuList = ['Path_ToolBitLibraryOpen', 'Path_ToolBitDock']
FreeCAD.Console.PrintLog("Loading PathToolBitLibraryCmd... done\n")

View File

@@ -35,7 +35,7 @@ from PySide import QtCore, QtGui
import PySide
import json
import os
import traceback
import glob
import uuid as UUID
from functools import partial
@@ -55,11 +55,11 @@ class _TableView(PySide.QtGui.QTableView):
def __init__(self, parent):
PySide.QtGui.QTableView.__init__(self, parent)
self.setDragEnabled(True)
self.setAcceptDrops(True)
self.setDropIndicatorShown(True)
self.setDragDropMode(PySide.QtGui.QAbstractItemView.InternalMove)
self.setDefaultDropAction(PySide.QtCore.Qt.MoveAction)
self.setDragEnabled(False)
self.setAcceptDrops(False)
self.setDropIndicatorShown(False)
self.setDragDropMode(PySide.QtGui.QAbstractItemView.DragOnly)
self.setDefaultDropAction(PySide.QtCore.Qt.IgnoreAction)
self.setSortingEnabled(True)
self.setSelectionBehavior(PySide.QtGui.QAbstractItemView.SelectRows)
self.verticalHeader().hide()
@@ -68,18 +68,18 @@ class _TableView(PySide.QtGui.QTableView):
return [PySide.QtCore.Qt.CopyAction, PySide.QtCore.Qt.MoveAction]
def _uuidOfRow(self, row):
model = self.model()
model = self.toolModel()
return model.data(model.index(row, 0), _UuidRole)
def _rowWithUuid(self, uuid):
model = self.model()
model = self.toolModel()
for row in range(model.rowCount()):
if self._uuidOfRow(row) == uuid:
return row
return None
def _copyTool(self, uuid_, dstRow):
model = self.model()
model = self.toolModel()
model.insertRow(dstRow)
srcRow = self._rowWithUuid(uuid_)
for col in range(model.columnCount()):
@@ -108,23 +108,9 @@ class _TableView(PySide.QtGui.QTableView):
# pylint: disable=unused-variable
row = stream.readInt32()
srcRows.append(row)
# col = stream.readInt32()
# PathLog.track(row, col)
# cnt = stream.readInt32()
# for i in range(cnt):
# key = stream.readInt32()
# val = stream.readQVariant()
# PathLog.track(' ', i, key, val, type(val))
# I have no idea what these three integers are,
# or if they even are three integers,
# but it seems to work out this way.
# i0 = stream.readInt32()
# i1 = stream.readInt32()
# i2 = stream.readInt32()
# PathLog.track(' ', i0, i1, i2)
# get the uuids of all srcRows
model = self.model()
model = self.toolModel()
srcUuids = [self._uuidOfRow(row) for row in set(srcRows)]
destRow = self.rowAt(event.pos().y())
@@ -134,264 +120,432 @@ class _TableView(PySide.QtGui.QTableView):
model.removeRow(self._rowWithUuid(uuid))
class ToolBitLibrary(object):
'''ToolBitLibrary is the controller for displaying/selecting/creating/editing a collection of ToolBits.'''
class ModelFactory(object):
''' Helper class to generate qtdata models for toolbit libraries
'''
def __init__(self, path=None):
self.path = path
PathLog.track()
self.path = ""
# self.currentLib = ""
def __libraryLoad(self, path, datamodel):
PathLog.track(path)
PathPreferences.setLastFileToolLibrary(path)
# self.currenLib = path
with open(path) as fp:
library = json.load(fp)
for toolBit in library['tools']:
try:
nr = toolBit['nr']
bit = PathToolBit.findBit(toolBit['path'])
if bit:
PathLog.track(bit)
tool = PathToolBit.Declaration(bit)
datamodel.appendRow(self._toolAdd(nr, tool, bit))
else:
PathLog.error("Could not find tool #{}: {}".format(nr, toolBit['path']))
except Exception as e:
msg = "Error loading tool: {} : {}".format(toolBit['path'], e)
FreeCAD.Console.PrintError(msg)
def _toolAdd(self, nr, tool, path):
strShape = os.path.splitext(os.path.basename(tool['shape']))[0]
# strDiam = tool['parameter']['Diameter']
tooltip = "{}".format(strShape)
toolNr = PySide.QtGui.QStandardItem()
toolNr.setData(nr, PySide.QtCore.Qt.EditRole)
toolNr.setToolTip(tool['shape'])
toolNr.setData(path, _PathRole)
toolNr.setData(UUID.uuid4(), _UuidRole)
toolNr.setToolTip(tooltip)
toolName = PySide.QtGui.QStandardItem()
toolName.setData(tool['name'], PySide.QtCore.Qt.EditRole)
toolName.setEditable(False)
toolName.setToolTip(tooltip)
toolShape = PySide.QtGui.QStandardItem()
toolShape.setData(strShape, PySide.QtCore.Qt.EditRole)
toolShape.setEditable(False)
return [toolNr, toolName, toolShape]
def newTool(self, datamodel, path):
'''
Adds a toolbit item to a model
'''
PathLog.track()
try:
nr = 0
for row in range(datamodel.rowCount()):
itemNr = int(datamodel.item(row, 0).data(PySide.QtCore.Qt.EditRole))
nr = max(nr, itemNr)
nr += 1
tool = PathToolBit.Declaration(path)
except Exception as e:
PathLog.error(e)
datamodel.appendRow(self._toolAdd(nr, tool, path))
def findLibraries(self, model):
'''
Finds all the fctl files in a location
Returns a QStandardItemModel
'''
PathLog.track()
path = PathPreferences.lastPathToolLibrary()
if os.path.isdir(path): # opening all tables in a directory
libFiles = [f for f in glob.glob(path + '/*.fctl')]
libFiles.sort()
for libFile in libFiles:
loc, fnlong = os.path.split(libFile)
fn, ext = os.path.splitext(fnlong)
libItem = QtGui.QStandardItem(fn)
libItem.setToolTip(loc)
libItem.setData(libFile, _PathRole)
libItem.setIcon(QtGui.QPixmap(':/icons/Path-ToolTable.svg'))
model.appendRow(libItem)
PathLog.debug('model rows: {}'.format(model.rowCount()))
return model
def libraryOpen(self, model, lib=""):
'''
opens the tools in library
Returns a QStandardItemModel
'''
PathLog.track(lib)
if lib == "":
lib = PathPreferences.lastFileToolLibrary()
if lib == "" or lib is None:
return model
if os.path.isfile(lib): # An individual library is wanted
self.__libraryLoad(lib, model)
PathLog.debug('model rows: {}'.format(model.rowCount()))
return model
class ToolBitSelector(object):
'''Controller for displaying a library and creating ToolControllers'''
def __init__(self):
self.form = FreeCADGui.PySideUic.loadUi(':/panels/ToolBitSelector.ui')
self.factory = ModelFactory()
self.toolModel = PySide.QtGui.QStandardItemModel(0, len(self.columnNames()))
self.setupUI()
self.title = self.form.windowTitle()
def columnNames(self):
return ['#', 'Tool']
def curLib(self):
libfile = PathPreferences.lastFileToolLibrary()
if libfile is None or libfile == "":
return ""
else:
libfile = os.path.split(PathPreferences.lastFileToolLibrary())[1]
libfile = os.path.splitext(libfile)[0]
return libfile
def loadData(self):
PathLog.track()
self.toolModel.clear()
self.toolModel.setHorizontalHeaderLabels(self.columnNames())
self.form.lblLibrary.setText(self.curLib())
self.factory.libraryOpen(self.toolModel)
self.toolModel.takeColumn(3)
self.toolModel.takeColumn(2)
def setupUI(self):
PathLog.track()
self.loadData()
self.form.tools.setModel(self.toolModel)
self.form.tools.selectionModel().selectionChanged.connect(self.enableButtons)
self.form.tools.doubleClicked.connect(partial(self.selectedOrAllToolControllers))
self.form.libraryEditorOpen.clicked.connect(self.libraryEditorOpen)
self.form.addToolController.clicked.connect(self.selectedOrAllToolControllers)
def enableButtons(self):
selected = (len(self.form.tools.selectedIndexes()) >= 1)
if selected:
jobs = len([1 for j in FreeCAD.ActiveDocument.Objects if j.Name[:3] == "Job"]) >= 1
self.form.addToolController.setEnabled(selected and jobs)
def libraryEditorOpen(self):
library = ToolBitLibrary()
library.open()
self.loadData()
def selectedOrAllTools(self):
'''
Iterate the selection and add individual tools
If a group is selected, iterate and add children
'''
itemsToProcess = []
for index in self.form.tools.selectedIndexes():
item = index.model().itemFromIndex(index)
if item.hasChildren():
for i in range(item.rowCount()-1):
if item.child(i).column() == 0:
itemsToProcess.append(item.child(i))
elif item.column() == 0:
itemsToProcess.append(item)
tools = []
for item in itemsToProcess:
toolNr = int(item.data(PySide.QtCore.Qt.EditRole))
toolPath = item.data(_PathRole)
tools.append((toolNr, PathToolBit.Factory.CreateFrom(toolPath)))
return tools
def selectedOrAllToolControllers(self, index=None):
'''
if no jobs, don't do anything, otherwise all TCs for all
selected toolbits
'''
jobs = PathUtilsGui.PathUtils.GetJobs()
if len(jobs) == 0:
return
elif len(jobs) == 1:
job = jobs[0]
else:
userinput = PathUtilsGui.PathUtilsUserInput()
job = userinput.chooseJob(jobs)
if job is None: # user may have canceled
return
tools = self.selectedOrAllTools()
for tool in tools:
tc = PathToolControllerGui.Create(tool[1].Label, tool[1], tool[0])
job.Proxy.addToolController(tc)
FreeCAD.ActiveDocument.recompute()
def open(self, path=None):
''' load library stored in path and bring up ui'''
docs = FreeCADGui.getMainWindow().findChildren(QtGui.QDockWidget)
for doc in docs:
if doc.objectName() == "ToolSelector":
if doc.isVisible():
doc.deleteLater()
return
else:
doc.setVisible(True)
return
mw = FreeCADGui.getMainWindow()
mw.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.form,
PySide.QtCore.Qt.Orientation.Vertical)
class ToolBitLibrary(object):
'''ToolBitLibrary is the controller for
displaying/selecting/creating/editing a collection of ToolBits.'''
def __init__(self):
PathLog.track()
self.factory = ModelFactory()
self.temptool = None
self.toolModel = PySide.QtGui.QStandardItemModel(0, len(self.columnNames()))
self.listModel = PySide.QtGui.QStandardItemModel()
self.form = FreeCADGui.PySideUic.loadUi(':/panels/ToolBitLibraryEdit.ui')
self.toolTableView = _TableView(self.form.toolTableGroup)
self.form.toolTableGroup.layout().replaceWidget(self.form.toolTable, self.toolTableView)
self.form.toolTable.hide()
self.setupUI()
self.title = self.form.windowTitle()
self.LibFiles = []
if path:
self.libraryLoad(path)
self.form.addToolController.setEnabled(False)
self.form.ButtonRemoveToolTable.setEnabled(False)
self.form.ButtonRenameToolTable.setEnabled(False)
def _toolAdd(self, nr, tool, path):
toolNr = PySide.QtGui.QStandardItem()
toolNr.setData(nr, PySide.QtCore.Qt.EditRole)
toolNr.setData(path, _PathRole)
toolNr.setData(UUID.uuid4(), _UuidRole)
toolName = PySide.QtGui.QStandardItem()
toolName.setData(tool['name'], PySide.QtCore.Qt.EditRole)
toolName.setEditable(False)
toolShape = PySide.QtGui.QStandardItem()
toolShape.setData(os.path.splitext(os.path.basename(tool['shape']))[0], PySide.QtCore.Qt.EditRole)
toolShape.setEditable(False)
toolDiameter = PySide.QtGui.QStandardItem()
toolDiameter.setData(tool['parameter']['Diameter'], PySide.QtCore.Qt.EditRole)
toolDiameter.setEditable(False)
self.model.appendRow([toolNr, toolName, toolShape, toolDiameter])
def toolAdd(self):
def toolBitNew(self):
PathLog.track()
# pylint: disable=broad-except
try:
nr = 0
for row in range(self.model.rowCount()):
itemNr = int(self.model.item(row, 0).data(PySide.QtCore.Qt.EditRole))
nr = max(nr, itemNr)
nr += 1
for i, foo in enumerate(PathToolBitGui.GetToolFiles(self.form)):
tool = PathToolBit.Declaration(foo)
self._toolAdd(nr + i, tool, foo)
self.toolTableView.resizeColumnsToContents()
except Exception:
PathLog.error('something happened')
PathLog.error(traceback.print_exc())
# select the shape file
shapefile = PathToolBitGui.GetToolShapeFile()
if shapefile is None: # user canceled
return
def selectedOrAllTools(self):
selectedRows = set([index.row() for index in self.toolTableView.selectedIndexes()])
if not selectedRows:
selectedRows = list(range(self.model.rowCount()))
tools = []
for row in selectedRows:
item = self.model.item(row, 0)
toolNr = int(item.data(PySide.QtCore.Qt.EditRole))
toolPath = item.data(_PathRole)
tools.append((toolNr, PathToolBit.Factory.CreateFrom(toolPath)))
return tools
filename = PathToolBitGui.GetNewToolFile()
if filename is None:
return
def selectedOrAllToolControllers(self):
tools = self.selectedOrAllTools()
# Parse out the name of the file and write the structure
loc, fil = os.path.split(filename)
fname = os.path.splitext(fil)[0]
fullpath = "{}/{}.fctb".format(loc, fname)
PathLog.debug(fullpath)
userinput = PathUtilsGui.PathUtilsUserInput()
job = userinput.chooseJob(PathUtilsGui.PathUtils.GetJobs())
for tool in tools:
print(tool)
tc = PathToolControllerGui.Create(tool[1].Label, tool[1], tool[0])
job.Proxy.addToolController(tc)
FreeCAD.ActiveDocument.recompute()
self.temptool = PathToolBit.ToolBitFactory().Create(name=fname)
self.temptool.BitShape = shapefile
self.temptool.Proxy.unloadBitBody(self.temptool)
self.temptool.Label = fname
self.temptool.Proxy.saveToFile(self.temptool, fullpath)
self.temptool.Document.removeObject(self.temptool.Name)
self.temptool = None
# add it to the model
self.factory.newTool(self.toolModel, fullpath)
def toolBitExisting(self):
filenames = PathToolBitGui.GetToolFiles()
if len(filenames) == 0:
return
for f in filenames:
loc, fil = os.path.split(f)
fname = os.path.splitext(fil)[0]
fullpath = "{}/{}.fctb".format(loc, fname)
self.factory.newTool(self.toolModel, fullpath)
def toolDelete(self):
PathLog.track()
selectedRows = set([index.row() for index in self.toolTableView.selectedIndexes()])
for row in sorted(list(selectedRows), key=lambda r: -r):
self.model.removeRows(row, 1)
def libraryDelete(self):
PathLog.track()
reply = QtGui.QMessageBox.question(self.form, 'Warning', "Delete " + os.path.basename(self.path) + "?", QtGui.QMessageBox.Yes | QtGui.QMessageBox.Cancel)
if reply == QtGui.QMessageBox.Yes and len(self.path) > 0:
os.remove(self.path)
PathPreferences.setLastPathToolTable("")
self.libraryOpen(filedialog=False)
def toolEnumerate(self):
PathLog.track()
for row in range(self.model.rowCount()):
self.model.setData(self.model.index(row, 0), row + 1, PySide.QtCore.Qt.EditRole)
self.toolModel.removeRows(row, 1)
def toolSelect(self, selected, deselected):
# pylint: disable=unused-argument
sel = len(self.toolTableView.selectedIndexes()) > 0
self.form.toolDelete.setEnabled(sel)
if sel:
self.form.addToolController.setEnabled(True)
else:
self.form.addToolController.setEnabled(False)
def tableSelected(self, index):
''' loads the tools for the selected tool table '''
name = self.form.TableList.itemWidget(self.form.TableList.itemFromIndex(index)).getTableName()
self.libraryLoad(PathPreferences.lastPathToolLibrary() + '/' + name)
self.form.ButtonRemoveToolTable.setEnabled(True)
self.form.ButtonRenameToolTable.setEnabled(True)
PathLog.track()
item = index.model().itemFromIndex(index)
libpath = item.data(_PathRole)
self.loadData(libpath)
self.path = libpath
def open(self, path=None, dialog=False):
'''open(path=None, dialog=False) ... load library stored in path and bring up ui.
Returns 1 if user pressed OK, 0 otherwise.'''
if path:
self.libraryOpen(path, filedialog=False)
elif dialog:
self.libraryOpen(None, True)
else:
self.libraryOpen(None, False)
def open(self):
PathLog.track()
return self.form.exec_()
def updateToolbar(self):
if self.path:
self.form.librarySave.setEnabled(True)
else:
self.form.librarySave.setEnabled(False)
def libraryOpen(self, path=None, filedialog=True):
import glob
def libraryPath(self):
PathLog.track()
path = PySide.QtGui.QFileDialog.getExistingDirectory(self.form, 'Tool Library Path', PathPreferences.lastPathToolLibrary())
if len(path) == 0:
return
# Load default search path
path = PathPreferences.lastPathToolLibrary()
PathPreferences.setLastPathToolLibrary(path)
self.loadData()
if filedialog or len(path) == 0:
path = PySide.QtGui.QFileDialog.getExistingDirectory(self.form, 'Tool Library Path', PathPreferences.lastPathToolLibrary())
if len(path) > 0:
PathPreferences.setLastPathToolLibrary(path)
else:
return
def cleanupDocument(self):
# This feels like a hack. Remove the toolbit object
# remove the editor from the dialog
# re-enable all the controls
self.temptool.Proxy.unloadBitBody(self.temptool)
self.temptool.Document.removeObject(self.temptool.Name)
self.temptool = None
widget = self.form.toolTableGroup.children()[-1]
widget.setParent(None)
self.editor = None
self.lockoff()
# Clear view
self.form.TableList.clear()
self.LibFiles.clear()
self.form.lineLibPath.clear()
self.form.lineLibPath.insert(path)
def accept(self):
self.editor.accept()
self.temptool.Proxy.saveToFile(self.temptool, self.temptool.File)
self.librarySave()
self.loadData()
self.cleanupDocument()
# Find all tool tables in directory
for file in glob.glob(path + '/*.fctl'):
self.LibFiles.append(file)
def reject(self):
self.cleanupDocument()
self.LibFiles.sort()
def lockon(self):
self.toolTableView.setEnabled(False)
self.form.toolCreate.setEnabled(False)
self.form.toolDelete.setEnabled(False)
self.form.toolAdd.setEnabled(False)
self.form.TableList.setEnabled(False)
self.form.libraryOpen.setEnabled(False)
self.form.libraryExport.setEnabled(False)
self.form.addToolTable.setEnabled(False)
self.form.librarySave.setEnabled(False)
# Add all tables to list
for table in self.LibFiles:
listWidgetItem = QtGui.QListWidgetItem()
listItem = ToolTableListWidgetItem()
listItem.setTableName(os.path.basename(table))
listItem.setIcon(QtGui.QPixmap(':/icons/Path-ToolTable.svg'))
listWidgetItem.setSizeHint(QtCore.QSize(0, 40))
self.form.TableList.addItem(listWidgetItem)
self.form.TableList.setItemWidget(listWidgetItem, listItem)
def lockoff(self):
self.toolTableView.setEnabled(True)
self.form.toolCreate.setEnabled(True)
self.form.toolDelete.setEnabled(True)
self.form.toolAdd.setEnabled(True)
self.form.toolTable.setEnabled(True)
self.form.TableList.setEnabled(True)
self.form.libraryOpen.setEnabled(True)
self.form.libraryExport.setEnabled(True)
self.form.addToolTable.setEnabled(True)
self.form.librarySave.setEnabled(True)
self.path = []
self.form.ButtonRemoveToolTable.setEnabled(False)
self.form.ButtonRenameToolTable.setEnabled(False)
def toolEdit(self, selected):
item = self.toolModel.item(selected.row(), 0)
self.toolTableView.setUpdatesEnabled(False)
self.model.clear()
self.model.setHorizontalHeaderLabels(self.columnNames())
self.toolTableView.resizeColumnsToContents()
self.toolTableView.setUpdatesEnabled(True)
if self.temptool is not None:
self.temptool.Document.removeObject(self.temptool.Name)
# Search last selected table
if len(self.LibFiles) > 0:
for idx in range(len(self.LibFiles)):
if PathPreferences.lastPathToolTable() == os.path.basename(self.LibFiles[idx]):
break
# Not found, select first entry
if idx >= len(self.LibFiles):
idx = 0
if selected.column() == 0: # editing Nr
pass
else:
tbpath = item.data(_PathRole)
self.temptool = PathToolBit.ToolBitFactory().CreateFrom(tbpath, 'temptool')
self.editor = PathToolBitEdit.ToolBitEditor(self.temptool, self.form.toolTableGroup, loadBitBody=False)
# Load selected table
self.libraryLoad(self.LibFiles[idx])
self.form.TableList.setCurrentRow(idx)
self.form.ButtonRemoveToolTable.setEnabled(True)
self.form.ButtonRenameToolTable.setEnabled(True)
QBtn = QtGui.QDialogButtonBox.Ok | QtGui.QDialogButtonBox.Cancel
buttonBox = QtGui.QDialogButtonBox(QBtn)
buttonBox.accepted.connect(self.accept)
buttonBox.rejected.connect(self.reject)
def libraryLoad(self, path):
self.toolTableView.setUpdatesEnabled(False)
self.model.clear()
self.model.setHorizontalHeaderLabels(self.columnNames())
layout = self.editor.form.layout()
layout.addWidget(buttonBox)
self.lockon()
self.editor.setupUI()
if path:
with open(path) as fp:
PathPreferences.setLastPathToolTable(os.path.basename(path))
library = json.load(fp)
for toolBit in library['tools']:
nr = toolBit['nr']
bit = PathToolBit.findBit(toolBit['path'])
if bit:
PathLog.track(bit)
tool = PathToolBit.Declaration(bit)
self._toolAdd(nr, tool, bit)
else:
PathLog.error("Could not find tool #{}: {}".format(nr, library['tools'][nr]))
self.toolTableView.resizeColumnsToContents()
self.toolTableView.setUpdatesEnabled(True)
self.form.setWindowTitle("{} - {}".format(self.title, os.path.basename(path) if path else ''))
self.path = path
self.updateToolbar()
def toolEditDone(self, success=True):
FreeCAD.ActiveDocument.removeObject("temptool")
print('all done')
def libraryNew(self):
self.libraryLoad(None)
self.librarySaveAs()
TooltableTypeJSON = translate("PathToolLibraryManager", "Tooltable JSON (*.fctl)")
def renameLibrary(self):
name = self.form.TableList.itemWidget(self.form.TableList.currentItem()).getTableName()
newName, ok = QtGui.QInputDialog.getText(None, translate(
"TooltableEditor", "Rename Tooltable"), translate(
"TooltableEditor", "Enter Name:"), QtGui.QLineEdit.Normal, name)
if ok and newName:
os.rename(PathPreferences.lastPathToolLibrary() + '/' + name, PathPreferences.lastPathToolLibrary() + '/' + newName)
self.libraryOpen(filedialog=False)
filename = PySide.QtGui.QFileDialog.getSaveFileName(self.form,
translate("TooltableEditor", "Save toolbit library", None),
PathPreferences.lastPathToolLibrary(), "{}".format(TooltableTypeJSON))
# def createToolBit(self):
# tool = PathToolBit.ToolBitFactory().Create()
if not (filename and filename[0]):
self.loadData()
# #self.dialog = PySide.QtGui.QDialog(self.form)
# #layout = PySide.QtGui.QVBoxLayout(self.dialog)
# self.editor = PathToolBitEdit.ToolBitEditor(tool, self.form.toolTableGroup)
# self.editor.setupUI()
# self.buttons = PySide.QtGui.QDialogButtonBox(
# PySide.QtGui.QDialogButtonBox.Ok | PySide.QtGui.QDialogButtonBox.Cancel,
# PySide.QtCore.Qt.Horizontal, self.dialog)
# layout.addWidget(self.buttons)
# #self.buttons.accepted.connect(accept)
# #self.buttons.rejected.connect(reject)
# print(self.dialog.exec_())
path = filename[0] if filename[0].endswith('.fctl') else "{}.fctl".format(filename[0])
library = {}
tools = []
library['version'] = 1
library['tools'] = tools
with open(path, 'w') as fp:
json.dump(library, fp, sort_keys=True, indent=2)
self.loadData()
def librarySave(self):
library = {}
tools = []
library['version'] = 1
library['tools'] = tools
for row in range(self.model.rowCount()):
toolNr = self.model.data(self.model.index(row, 0), PySide.QtCore.Qt.EditRole)
toolPath = self.model.data(self.model.index(row, 0), _PathRole)
for row in range(self.toolModel.rowCount()):
toolNr = self.toolModel.data(self.toolModel.index(row, 0), PySide.QtCore.Qt.EditRole)
toolPath = self.toolModel.data(self.toolModel.index(row, 0), _PathRole)
if PathPreferences.toolsStoreAbsolutePaths():
tools.append({'nr': toolNr, 'path': toolPath})
else:
@@ -400,13 +554,109 @@ class ToolBitLibrary(object):
with open(self.path, 'w') as fp:
json.dump(library, fp, sort_keys=True, indent=2)
def libraryOk(self):
self.librarySave()
self.form.close()
def libPaths(self):
lib = PathPreferences.lastFileToolLibrary()
loc = PathPreferences.lastPathToolLibrary()
PathLog.track("lib: {} loc: {}".format(lib, loc))
return lib, loc
def columnNames(self):
return ['Nr', 'Tool', 'Shape']
def loadData(self, path=None):
PathLog.track(path)
self.toolTableView.setUpdatesEnabled(False)
self.form.TableList.setUpdatesEnabled(False)
if path is None:
path, loc = self.libPaths()
self.toolModel.clear()
self.listModel.clear()
self.factory.libraryOpen(self.toolModel, lib=path)
self.factory.findLibraries(self.listModel)
else:
self.toolModel.clear()
self.factory.libraryOpen(self.toolModel, lib=path)
self.path = path
self.form.setWindowTitle("{}".format(PathPreferences.lastPathToolLibrary()))
self.toolModel.setHorizontalHeaderLabels(self.columnNames())
self.listModel.setHorizontalHeaderLabels(['Library'])
# Select the current library in the list of tables
curIndex = None
for i in range(self.listModel.rowCount()):
item = self.listModel.item(i)
if item.data(_PathRole) == path:
curIndex = self.listModel.indexFromItem(item)
if curIndex:
sm = self.form.TableList.selectionModel()
sm.select(curIndex, QtCore.QItemSelectionModel.Select)
self.toolTableView.setUpdatesEnabled(True)
self.form.TableList.setUpdatesEnabled(True)
def setupUI(self):
PathLog.track()
self.form.TableList.setModel(self.listModel)
self.toolTableView.setModel(self.toolModel)
self.loadData()
self.toolTableView.resizeColumnsToContents()
self.toolTableView.selectionModel().selectionChanged.connect(self.toolSelect)
self.toolTableView.doubleClicked.connect(self.toolEdit)
self.form.TableList.clicked.connect(self.tableSelected)
self.form.toolAdd.clicked.connect(self.toolBitExisting)
self.form.toolDelete.clicked.connect(self.toolDelete)
self.form.toolCreate.clicked.connect(self.toolBitNew)
self.form.addToolTable.clicked.connect(self.libraryNew)
self.form.libraryOpen.clicked.connect(self.libraryPath)
self.form.librarySave.clicked.connect(self.libraryOk)
self.form.libraryExport.clicked.connect(self.librarySaveAs)
self.toolSelect([], [])
def librarySaveAs(self, path):
TooltableTypeJSON = translate("PathToolLibraryManager", "Tooltable JSON (*.fctl)")
TooltableTypeLinuxCNC = translate("PathToolLibraryManager", "LinuxCNC tooltable (*.tbl)")
filename = PySide.QtGui.QFileDialog.getSaveFileName(self.form,
translate("TooltableEditor", "Save toolbit library", None),
PathPreferences.lastPathToolLibrary(), "{};;{}".format(TooltableTypeJSON,
TooltableTypeLinuxCNC))
if filename and filename[0]:
if filename[1] == TooltableTypeLinuxCNC:
path = filename[0] if filename[0].endswith('.tbl') else "{}.tbl".format(filename[0])
self.libararySaveLinuxCNC(path)
else:
path = filename[0] if filename[0].endswith('.fctl') else "{}.fctl".format(filename[0])
self.path = path
self.librarySave()
self.updateToolbar()
def libararySaveLinuxCNC(self, path):
# linuxcnc line template
LIN = "T{} P{} X{} Y{} Z{} A{} B{} C{} U{} V{} W{} D{} I{} J{} Q{}; {}"
with open(path, 'w') as fp:
fp.write(";\n")
for row in range(self.model.rowCount()):
toolNr = self.model.data(self.model.index(row, 0), PySide.QtCore.Qt.EditRole)
toolPath = self.model.data(self.model.index(row, 0), _PathRole)
for row in range(self.toolModel.rowCount()):
toolNr = self.toolModel.data(self.toolModel.index(row, 0), PySide.QtCore.Qt.EditRole)
toolPath = self.toolModel.data(self.toolModel.index(row, 0), _PathRole)
bit = PathToolBit.Factory.CreateFrom(toolPath)
if bit:
@@ -429,129 +679,12 @@ class ToolBitLibrary(object):
orientation = bit.Orientation if hasattr(bit, "Orientation") else "0"
remark = bit.Label
fp.write("T%s P%s X%s Y%s Z%s A%s B%s C%s U%s V%s W%s D%s I%s J%s Q%s ; %s\n" %
(toolNr,
pocket,
xoffset,
yoffset,
zoffset,
aoffset,
boffset,
coffset,
uoffset,
voffset,
woffset,
diameter,
frontangle,
backangle,
orientation,
remark))
fp.write(LIN.format(toolNr, pocket, xoffset, yoffset,
zoffset, aoffset, boffset, coffset, uoffset,
voffset, woffset, diameter, frontangle, backangle,
orientation, remark) + "\n")
FreeCAD.ActiveDocument.removeObject(bit.Name)
else:
PathLog.error("Could not find tool #{} ".format(toolNr))
def librarySaveAs(self):
TooltableTypeJSON = translate("PathToolLibraryManager", "Tooltable JSON (*.fctl)")
TooltableTypeLinuxCNC = translate("PathToolLibraryManager", "LinuxCNC tooltable (*.tbl)")
filename = PySide.QtGui.QFileDialog.getSaveFileName(self.form,
translate("TooltableEditor", "Save toolbit library", None),
PathPreferences.lastPathToolLibrary(), "{};;{}".format(TooltableTypeJSON,
TooltableTypeLinuxCNC))
# filename = PySide.QtGui.QFileDialog.getSaveFileName(self.form, \
# 'Tool Library', PathPreferences.lastPathToolLibrary(), '*.fctl')
if filename and filename[0]:
if filename[1] == TooltableTypeLinuxCNC:
path = filename[0] if filename[0].endswith('.tbl') else "{}.tbl".format(filename[0])
self.libararySaveLinuxCNC(path)
else:
path = filename[0] if filename[0].endswith('.fctl') else "{}.fctl".format(filename[0])
PathPreferences.setLastPathToolLibrary(os.path.dirname(path))
self.path = path
self.librarySave()
self.updateToolbar()
PathPreferences.setLastPathToolTable(os.path.basename(path))
self.libraryOpen(None, False)
def libraryCancel(self):
self.form.close()
def columnNames(self):
return ['Nr', 'Tool', 'Shape', 'Diameter']
def toolEdit(self, selected):
print('here')
print(selected)
if selected.column() == 0:
print('nope')
else:
print('yep')
def setupUI(self):
PathLog.track('+')
self.model = PySide.QtGui.QStandardItemModel(0, len(self.columnNames()), self.toolTableView)
self.model.setHorizontalHeaderLabels(self.columnNames())
self.toolTableView.setModel(self.model)
self.toolTableView.resizeColumnsToContents()
self.toolTableView.selectionModel().selectionChanged.connect(self.toolSelect)
self.toolTableView.doubleClicked.connect(self.toolEdit)
self.form.toolAdd.clicked.connect(self.toolAdd)
self.form.toolDelete.clicked.connect(self.toolDelete)
self.form.toolEnumerate.clicked.connect(self.toolEnumerate)
# self.form.createToolBit.clicked.connect(self.createToolBit)
self.form.ButtonAddToolTable.clicked.connect(self.libraryNew)
self.form.ButtonRemoveToolTable.clicked.connect(self.libraryDelete)
self.form.ButtonRenameToolTable.clicked.connect(self.renameLibrary)
# self.form.libraryNew.clicked.connect(self.libraryNew)
self.form.libraryOpen.clicked.connect(partial(self.libraryOpen, filedialog=True))
self.form.librarySave.clicked.connect(self.librarySave)
self.form.librarySaveAs.clicked.connect(self.librarySaveAs)
self.form.libraryCancel.clicked.connect(self.libraryCancel)
self.form.addToolController.clicked.connect(self.selectedOrAllToolControllers)
self.form.TableList.clicked.connect(self.tableSelected)
self.toolSelect([], [])
self.updateToolbar()
PathLog.track('-')
class ToolTableListWidgetItem(QtGui.QWidget):
toolMoved = QtCore.Signal()
def __init__(self):
super(ToolTableListWidgetItem, self).__init__()
self.setAcceptDrops(True)
self.mainLayout = QtGui.QHBoxLayout()
self.iconQLabel = QtGui.QLabel()
self.tableNameLabel = QtGui.QLabel()
self.mainLayout.addWidget(self.iconQLabel, 0)
self.mainLayout.addWidget(self.tableNameLabel, 1)
self.setLayout(self.mainLayout)
def setTableName(self, text):
self.tableNameLabel.setText(text)
def getTableName(self):
return self.tableNameLabel.text()
def setIcon(self, icon):
icon = icon.scaled(22, 22)
self.iconQLabel.setPixmap(icon)
# def dragEnterEvent(self, e):
# currentToolTable = self.tlm.getCurrentTableName()
# thisToolTable = self.getTableName()
def dropEvent(self, e):
selectedTools = e.source().selectedIndexes()
print("Drop: {}, {}".format(selectedTools, selectedTools[1].data()))

View File

@@ -30,16 +30,17 @@ import PathScripts.PathToolBit as PathToolBit
from PySide import QtCore
#PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule())
#PathLog.trackModule(PathLog.thisModule())
# PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule())
# PathLog.trackModule(PathLog.thisModule())
# Qt translation handling
def translate(context, text, disambig=None):
return QtCore.QCoreApplication.translate(context, text, disambig)
class ToolControllerTemplate:
'''Attribute and sub element strings for template export/import.'''
# pylint: disable=no-init
Expressions = 'xengine'
ExprExpr = 'expr'
@@ -56,21 +57,36 @@ class ToolControllerTemplate:
VertFeed = 'vfeed'
VertRapid = 'vrapid'
class ToolController:
def __init__(self, obj, cTool=False):
PathLog.track('tool: {}'.format(cTool))
obj.addProperty("App::PropertyIntegerConstraint", "ToolNumber", "Tool", QtCore.QT_TRANSLATE_NOOP("PathToolController", "The active tool"))
obj.addProperty("App::PropertyIntegerConstraint", "ToolNumber",
"Tool", QtCore.QT_TRANSLATE_NOOP("PathToolController",
"The active tool"))
obj.ToolNumber = (0, 0, 10000, 1)
self.ensureUseLegacyTool(obj, cTool)
obj.addProperty("App::PropertyFloat", "SpindleSpeed", "Tool", QtCore.QT_TRANSLATE_NOOP("PathToolController", "The speed of the cutting spindle in RPM"))
obj.addProperty("App::PropertyEnumeration", "SpindleDir", "Tool", QtCore.QT_TRANSLATE_NOOP("PathToolController", "Direction of spindle rotation"))
obj.addProperty("App::PropertyFloat", "SpindleSpeed", "Tool",
QtCore.QT_TRANSLATE_NOOP("PathToolController",
"The speed of the cutting spindle in RPM"))
obj.addProperty("App::PropertyEnumeration", "SpindleDir", "Tool",
QtCore.QT_TRANSLATE_NOOP("PathToolController",
"Direction of spindle rotation"))
obj.SpindleDir = ['Forward', 'Reverse']
obj.addProperty("App::PropertySpeed", "VertFeed", "Feed", QtCore.QT_TRANSLATE_NOOP("PathToolController", "Feed rate for vertical moves in Z"))
obj.addProperty("App::PropertySpeed", "HorizFeed", "Feed", QtCore.QT_TRANSLATE_NOOP("PathToolController", "Feed rate for horizontal moves"))
obj.addProperty("App::PropertySpeed", "VertRapid", "Rapid", QtCore.QT_TRANSLATE_NOOP("PathToolController", "Rapid rate for vertical moves in Z"))
obj.addProperty("App::PropertySpeed", "HorizRapid", "Rapid", QtCore.QT_TRANSLATE_NOOP("PathToolController", "Rapid rate for horizontal moves"))
obj.addProperty("App::PropertySpeed", "VertFeed", "Feed",
QtCore.QT_TRANSLATE_NOOP("PathToolController",
"Feed rate for vertical moves in Z"))
obj.addProperty("App::PropertySpeed", "HorizFeed", "Feed",
QtCore.QT_TRANSLATE_NOOP("PathToolController",
"Feed rate for horizontal moves"))
obj.addProperty("App::PropertySpeed", "VertRapid", "Rapid",
QtCore.QT_TRANSLATE_NOOP("PathToolController",
"Rapid rate for vertical moves in Z"))
obj.addProperty("App::PropertySpeed", "HorizRapid", "Rapid",
QtCore.QT_TRANSLATE_NOOP("PathToolController",
"Rapid rate for horizontal moves"))
obj.setEditorMode('Placement', 2)
def onDocumentRestored(self, obj):
@@ -82,10 +98,12 @@ class ToolController:
if hasattr(obj.Tool, 'InList') and len(obj.Tool.InList) == 1:
if hasattr(obj.Tool.Proxy, 'onDelete'):
obj.Tool.Proxy.onDelete(obj.Tool)
obj.Document.removeObject(obj.Tool.Name)
def setFromTemplate(self, obj, template):
'''setFromTemplate(obj, xmlItem) ... extract properties from xmlItem and assign to receiver.'''
'''
setFromTemplate(obj, xmlItem) ... extract properties from xmlItem
and assign to receiver.
'''
PathLog.track(obj.Name, template)
version = 0
if template.get(ToolControllerTemplate.Version):
@@ -158,10 +176,21 @@ class ToolController:
commands += "(" + obj.Label + ")"+'\n'
commands += 'M6 T'+str(obj.ToolNumber)+'\n'
if obj.SpindleDir == 'Forward':
commands += 'M3 S' + str(obj.SpindleSpeed) + '\n'
else:
commands += 'M4 S' + str(obj.SpindleSpeed) + '\n'
# If a toolbit is used, check to see if spindlepower is allowed.
# This is to prevent accidentally spinning the spindle with an
# unpowered tool like probe or dragknife
allowSpindlePower = True
if (not isinstance(obj.Tool, Path.Tool) and
hasattr(obj.Tool, "SpindlePower")):
allowSpindlePower = obj.Tool.SpindlePower
if allowSpindlePower:
PathLog.debug('selected tool preventing spindle power')
if obj.SpindleDir == 'Forward':
commands += 'M3 S' + str(obj.SpindleSpeed) + '\n'
else:
commands += 'M4 S' + str(obj.SpindleSpeed) + '\n'
if commands == "":
commands += "(No commands processed)"
@@ -195,13 +224,14 @@ class ToolController:
else:
obj.addProperty("App::PropertyLink", "Tool", "Base", QtCore.QT_TRANSLATE_NOOP("PathToolController", "The tool used by this controller"))
def Create(name = 'Default Tool', tool=None, toolNumber=1, assignViewProvider=True):
def Create(name='Default Tool', tool=None, toolNumber=1, assignViewProvider=True):
legacyTool = PathPreferences.toolsReallyUseLegacyTools() if tool is None else isinstance(tool, Path.Tool)
PathLog.track(tool, toolNumber, legacyTool)
obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython", name)
obj.Label = name
obj.Label = "TC: {}".format(name)
obj.Proxy = ToolController(obj, legacyTool)
if FreeCAD.GuiUp and assignViewProvider:
@@ -224,6 +254,7 @@ def Create(name = 'Default Tool', tool=None, toolNumber=1, assignViewProvider=Tr
obj.ToolNumber = toolNumber
return obj
def FromTemplate(template, assignViewProvider=True):
# pylint: disable=unused-argument
PathLog.track()
@@ -234,6 +265,7 @@ def FromTemplate(template, assignViewProvider=True):
return obj
if FreeCAD.GuiUp:
# need ViewProvider class in this file to support loading of old files
from PathScripts.PathToolControllerGui import ViewProvider

View File

@@ -35,10 +35,12 @@ from PySide import QtCore, QtGui
from lazy_loader.lazy_loader import LazyLoader
Part = LazyLoader('Part', globals(), 'Part')
# Qt translation handling
def translate(context, text, disambig=None):
return QtCore.QCoreApplication.translate(context, text, disambig)
class ViewProvider:
def __init__(self, vobj):
@@ -122,7 +124,8 @@ class ViewProvider:
return [obj.Tool]
return []
def Create(name = 'Default Tool', tool=None, toolNumber=1):
def Create(name='Default Tool', tool=None, toolNumber=1):
PathLog.track(tool, toolNumber)
obj = PathScripts.PathToolController.Create(name, tool, toolNumber)
@@ -172,6 +175,7 @@ class CommandPathToolController(object):
job.Proxy.addToolController(tc)
FreeCAD.ActiveDocument.recompute()
class ToolControllerEditor(object):
def __init__(self, obj, asDialog):
@@ -180,13 +184,18 @@ class ToolControllerEditor(object):
self.form.buttonBox.hide()
self.obj = obj
self.vertFeed = PathGui.QuantitySpinBox(self.form.vertFeed, obj, 'VertFeed')
self.horizFeed = PathGui.QuantitySpinBox(self.form.horizFeed, obj, 'HorizFeed')
self.vertRapid = PathGui.QuantitySpinBox(self.form.vertRapid, obj, 'VertRapid')
self.horizRapid = PathGui.QuantitySpinBox(self.form.horizRapid, obj, 'HorizRapid')
self.vertFeed = PathGui.QuantitySpinBox(self.form.vertFeed, obj,
'VertFeed')
self.horizFeed = PathGui.QuantitySpinBox(self.form.horizFeed, obj,
'HorizFeed')
self.vertRapid = PathGui.QuantitySpinBox(self.form.vertRapid, obj,
'VertRapid')
self.horizRapid = PathGui.QuantitySpinBox(self.form.horizRapid, obj,
'HorizRapid')
if obj.Proxy.usesLegacyTool(obj):
self.editor = PathToolEdit.ToolEditor(obj.Tool, self.form.toolEditor)
self.editor = PathToolEdit.ToolEditor(obj.Tool,
self.form.toolEditor)
else:
self.editor = None
self.form.toolBox.widget(1).hide()
@@ -201,7 +210,8 @@ class ToolControllerEditor(object):
self.vertFeed.updateSpinBox()
self.vertRapid.updateSpinBox()
self.form.spindleSpeed.setValue(tc.SpindleSpeed)
index = self.form.spindleDirection.findText(tc.SpindleDir, QtCore.Qt.MatchFixedString)
index = self.form.spindleDirection.findText(tc.SpindleDir,
QtCore.Qt.MatchFixedString)
if index >= 0:
self.form.spindleDirection.setCurrentIndex(index)
@@ -224,9 +234,9 @@ class ToolControllerEditor(object):
self.editor.updateTool()
tc.Tool = self.editor.tool
except Exception as e: # pylint: disable=broad-except
PathLog.error(translate("PathToolController", "Error updating TC: %s") % e)
except Exception as e:
PathLog.error(translate("PathToolController",
"Error updating TC: %s") % e)
def refresh(self):
self.form.blockSignals(True)
@@ -296,7 +306,8 @@ class TaskPanel:
def setupUi(self):
if self.editor.editor:
t = Part.makeCylinder(1, 1)
self.toolrep = FreeCAD.ActiveDocument.addObject("Part::Feature", "tool")
self.toolrep = FreeCAD.ActiveDocument.addObject("Part::Feature",
"tool")
self.toolrep.Shape = t
self.setFields()
@@ -311,7 +322,7 @@ class DlgToolControllerEdit:
self.obj = obj
def exec_(self):
restoreTC = self.obj.Proxy.templateAttrs(self.obj)
restoreTC = self.obj.Proxy.templateAttrs(self.obj)
rc = False
if not self.editor.form.exec_():
@@ -320,6 +331,7 @@ class DlgToolControllerEdit:
rc = True
return rc
if FreeCAD.GuiUp:
# register the FreeCAD command
FreeCADGui.addCommand('Path_ToolController', CommandPathToolController())

View File

@@ -0,0 +1,14 @@
{
"version": 2,
"name": "45 Deg. Chamfer",
"shape": "chamfer.fcstd",
"parameter": {
"CuttingEdgeAngle": "45.0000 \u00b0",
"CuttingEdgeHeight": "6.3500 mm",
"Diameter": "12.3323 mm",
"FlatRadius": "5.0000 mm",
"Length": "30.0000 mm",
"ShankDiameter": "6.3500 mm"
},
"attribute": {}
}

View File

@@ -0,0 +1,11 @@
{
"version": 2,
"name": "5mm Drill",
"shape": "drill.fcstd",
"parameter": {
"Diameter": "5.0000 mm",
"Length": "50.0000 mm",
"TipAngle": "119.0000 \u00b0"
},
"attribute": {}
}

View File

@@ -0,0 +1,12 @@
{
"version": 2,
"name": "5mm Endmill",
"shape": "endmill.fcstd",
"parameter": {
"CuttingEdgeHeight": "30.0000 mm",
"Diameter": "5.0000 mm",
"Length": "50.0000 mm",
"ShankDiameter": "3.0000 mm"
},
"attribute": {}
}

View File

@@ -0,0 +1,14 @@
{
"version": 2,
"name": "60 Deg. V-Bit",
"shape": "v-bit.fcstd",
"parameter": {
"CuttingEdgeAngle": "60.0000 \u00b0",
"Diameter": "10.0000 mm",
"FlatHeight": "1.0000 mm",
"FlatRadius": "0.5000 mm",
"Length": "20.0000 mm",
"ShankDiameter": "5.0000 mm"
},
"attribute": {}
}

View File

@@ -0,0 +1,12 @@
{
"version": 2,
"name": "6mm Ball End",
"shape": "ballend.fcstd",
"parameter": {
"CuttingEdgeHeight": "40.0000 mm",
"Diameter": "6.0000 mm",
"Length": "50.0000 mm",
"ShankDiameter": "3.0000 mm"
},
"attribute": {}
}

View File

@@ -0,0 +1,13 @@
{
"version": 2,
"name": "6 mm Bull Nose",
"shape": "bullnose.fcstd",
"parameter": {
"CuttingEdgeHeight": "40.0000 mm",
"Diameter": "6.0000 mm",
"FlatRadius": "1.5000 mm",
"Length": "50.0000 mm",
"ShankDiameter": "3.0000 mm"
},
"attribute": {}
}

View File

@@ -0,0 +1,11 @@
{
"version": 2,
"name": "Probe004",
"shape": "probe.fcstd",
"parameter": {
"Diameter": "6.0000 mm",
"Length": "50.0000 mm",
"ShaftDiameter": "4.0000 mm"
},
"attribute": {}
}

View File

@@ -0,0 +1,14 @@
{
"version": 2,
"name": "Slitting Saw",
"shape": "slittingsaw.fcstd",
"parameter": {
"BladeThickness": "3.0000 mm",
"BoltHeight": "3.0000 mm",
"BoltWidth": "8.0000 mm",
"Diameter": "76.2000 mm",
"Length": "50.0000 mm",
"ShankDiameter": "19.0500 mm"
},
"attribute": {}
}

View File

@@ -1,12 +0,0 @@
{
"version": 2,
"name": "T1",
"shape": "endmill.fcstd",
"attribute": {},
"parameter": {
"CuttingEdgeHeight": "30.000 mm",
"Diameter": "1.000 mm",
"Length": "50.000 mm",
"ShankDiameter": "3.000 mm"
}
}

View File

@@ -1,12 +0,0 @@
{
"version": 1,
"name": "T2",
"shape": "endmill.fcstd",
"attribute": {},
"parameter": {
"CuttingEdgeHeight": "30.000 mm",
"Diameter": "2.000 mm",
"Length": "50.000 mm",
"ShankDiameter": "3.000 mm"
}
}

View File

@@ -1,12 +0,0 @@
{
"version": 2,
"name": "T3",
"shape": "endmill.fcstd",
"attribute": {},
"parameter": {
"CuttingEdgeHeight": "30.000 mm",
"Diameter": "3.000 mm",
"Length": "50.000 mm",
"ShankDiameter": "3.000 mm"
}
}

View File

@@ -1,12 +0,0 @@
{
"version": 1,
"name": "T4",
"shape": "endmill.fcstd",
"attribute": {},
"parameter": {
"CuttingEdgeHeight": "30.000 mm",
"Diameter": "4.000 mm",
"Length": "50.000 mm",
"ShankDiameter": "3.000 mm"
}
}

View File

@@ -1,12 +0,0 @@
{
"version": 1,
"name": "T5",
"shape": "endmill.fcstd",
"attribute": {},
"parameter": {
"CuttingEdgeHeight": "30.000 mm",
"Diameter": "5.000 mm",
"Length": "50.000 mm",
"ShankDiameter": "3.000 mm"
}
}

View File

@@ -1,12 +0,0 @@
{
"version": 1,
"name": "T6",
"shape": "endmill.fcstd",
"attribute": {},
"parameter": {
"CuttingEdgeHeight": "30.000 mm",
"Diameter": "6.000 mm",
"Length": "50.000 mm",
"ShankDiameter": "3.000 mm"
}
}

View File

@@ -1,12 +0,0 @@
{
"version": 1,
"name": "T7",
"shape": "endmill.fcstd",
"attribute": {},
"parameter": {
"CuttingEdgeHeight": "30.000 mm",
"Diameter": "7.000 mm",
"Length": "50.000 mm",
"ShankDiameter": "3.000 mm"
}
}

View File

@@ -1,12 +0,0 @@
{
"version": 1,
"name": "T8",
"shape": "endmill.fcstd",
"attribute": {},
"parameter": {
"CuttingEdgeHeight": "30.000 mm",
"Diameter": "8.000 mm",
"Length": "50.000 mm",
"ShankDiameter": "3.000 mm"
}
}

View File

@@ -1,12 +0,0 @@
{
"version": 1,
"name": "T9",
"shape": "endmill.fcstd",
"attribute": {},
"parameter": {
"CuttingEdgeHeight": "30.000 mm",
"Diameter": "9.000 mm",
"Length": "50.000 mm",
"ShankDiameter": "3.000 mm"
}
}

View File

@@ -0,0 +1,37 @@
{
"tools": [
{
"nr": 1,
"path": "5mm_Endmill.fctb"
},
{
"nr": 2,
"path": "5mm_Drill.fctb"
},
{
"nr": 3,
"path": "6mm_Ball_End.fctb"
},
{
"nr": 4,
"path": "6mm_Bullnose.fctb"
},
{
"nr": 5,
"path": "60degree_Vbit.fctb"
},
{
"nr": 6,
"path": "45degree_chamfer.fctb"
},
{
"nr": 7,
"path": "slittingsaw.fctb"
},
{
"nr": 8,
"path": "probe.fctb"
}
],
"version": 1
}

View File

@@ -1,41 +0,0 @@
{
"tools": [
{
"nr": 1,
"path": "t1.fctb"
},
{
"nr": 2,
"path": "t2.fctb"
},
{
"nr": 3,
"path": "t3.fctb"
},
{
"nr": 4,
"path": "t4.fctb"
},
{
"nr": 5,
"path": "t5.fctb"
},
{
"nr": 6,
"path": "t6.fctb"
},
{
"nr": 7,
"path": "t7.fctb"
},
{
"nr": 8,
"path": "t8.fctb"
},
{
"nr": 9,
"path": "t9.fctb"
}
],
"version": 1
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.