From 3cb21f0e56c205b83f3a5879547a88d1ff20e47d Mon Sep 17 00:00:00 2001 From: Dubstar_04 Date: Tue, 20 Aug 2019 20:34:47 +0100 Subject: [PATCH 1/9] Seperate ToolTable and Tool implementations Seperate the tooltable and tool implementations. --- src/Mod/Path/App/AppPath.cpp | 1 + src/Mod/Path/App/CMakeLists.txt | 3 + src/Mod/Path/App/PropertyTool.h | 2 +- src/Mod/Path/App/Tool.cpp | 264 ++++++++++++++++++++++++ src/Mod/Path/App/Tool.h | 105 ++++++++++ src/Mod/Path/App/ToolPy.xml | 2 +- src/Mod/Path/App/ToolPyImp.cpp | 304 ++++++++++++++++++++++++++++ src/Mod/Path/App/Tooltable.cpp | 234 +-------------------- src/Mod/Path/App/Tooltable.h | 74 +------ src/Mod/Path/App/TooltablePyImp.cpp | 271 +------------------------ 10 files changed, 684 insertions(+), 576 deletions(-) create mode 100644 src/Mod/Path/App/Tool.cpp create mode 100644 src/Mod/Path/App/Tool.h create mode 100644 src/Mod/Path/App/ToolPyImp.cpp diff --git a/src/Mod/Path/App/AppPath.cpp b/src/Mod/Path/App/AppPath.cpp index 026968c50304..2e93cd169b2c 100644 --- a/src/Mod/Path/App/AppPath.cpp +++ b/src/Mod/Path/App/AppPath.cpp @@ -34,6 +34,7 @@ #include "CommandPy.h" #include "Path.h" #include "PathPy.h" +#include "Tool.h" #include "Tooltable.h" #include "ToolPy.h" #include "TooltablePy.h" diff --git a/src/Mod/Path/App/CMakeLists.txt b/src/Mod/Path/App/CMakeLists.txt index 2ef5835eac0a..32fc5b19aeab 100644 --- a/src/Mod/Path/App/CMakeLists.txt +++ b/src/Mod/Path/App/CMakeLists.txt @@ -43,6 +43,7 @@ SET(Python_SRCS PathPy.xml PathPyImp.cpp ToolPy.xml + ToolPyImp.cpp TooltablePy.xml TooltablePyImp.cpp FeaturePathCompoundPy.xml @@ -65,6 +66,8 @@ SET(Path_SRCS Command.h Path.cpp Path.h + Tool.cpp + Tool.h Tooltable.cpp Tooltable.h PropertyPath.cpp diff --git a/src/Mod/Path/App/PropertyTool.h b/src/Mod/Path/App/PropertyTool.h index 85e1756fe91e..706e4fae6bcc 100644 --- a/src/Mod/Path/App/PropertyTool.h +++ b/src/Mod/Path/App/PropertyTool.h @@ -24,7 +24,7 @@ #ifndef PROPERTYTOOL_H #define PROPERTYTOOL_H -#include "Tooltable.h" +#include "Tool.h" #include namespace Path diff --git a/src/Mod/Path/App/Tool.cpp b/src/Mod/Path/App/Tool.cpp new file mode 100644 index 000000000000..62a571d821fc --- /dev/null +++ b/src/Mod/Path/App/Tool.cpp @@ -0,0 +1,264 @@ +/*************************************************************************** + * Copyright (c) Yorik van Havre (yorik@uncreated.net) 2014 * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#include "PreCompiled.h" + +#ifndef _PreComp_ + +#endif +#include +#include +#include +#include "Tool.h" + +using namespace Base; +using namespace Path; + + +// TOOL + + +TYPESYSTEM_SOURCE(Path::Tool , Base::Persistence); + +// Constructors & destructors + +Tool::Tool(const char* name, + ToolType type, + ToolMaterial /*material*/, + double diameter, + double lengthoffset, + double flatradius, + double cornerradius, + double cuttingedgeangle, + double cuttingedgeheight) +:Name(name),Type(type),Material(MATUNDEFINED),Diameter(diameter),LengthOffset(lengthoffset), +FlatRadius(flatradius),CornerRadius(cornerradius),CuttingEdgeAngle(cuttingedgeangle), +CuttingEdgeHeight(cuttingedgeheight) +{ +} + +Tool::Tool() +{ + Type = UNDEFINED; + Material = MATUNDEFINED; + Diameter = 0; + LengthOffset = 0; + FlatRadius = 0; + CornerRadius = 0; + CuttingEdgeAngle = 180; + CuttingEdgeHeight = 0; +} + +Tool::~Tool() +{ +} + +// Reimplemented from base class + +unsigned int Tool::getMemSize (void) const +{ + return 0; +} + +void Tool::Save (Writer &writer) const +{ + writer.Stream() << writer.ind() << "" << std::endl; +} + +void Tool::Restore(XMLReader &reader) +{ + reader.readElement("Tool"); + Name = reader.getAttribute("name"); + Diameter = reader.hasAttribute("diameter") ? (double) reader.getAttributeAsFloat("diameter") : 0.0; + LengthOffset = reader.hasAttribute("length") ? (double) reader.getAttributeAsFloat("length") : 0.0; + FlatRadius = reader.hasAttribute("flat") ? (double) reader.getAttributeAsFloat("flat") : 0.0; + CornerRadius = reader.hasAttribute("corner") ? (double) reader.getAttributeAsFloat("corner") : 0.0; + CuttingEdgeAngle = reader.hasAttribute("angle") ? (double) reader.getAttributeAsFloat("angle") : 180.0; + CuttingEdgeHeight = reader.hasAttribute("height") ? (double) reader.getAttributeAsFloat("height") : 0.0; + std::string type = reader.hasAttribute("type") ? reader.getAttribute("type") : ""; + std::string mat = reader.hasAttribute("mat") ? reader.getAttribute("mat") : ""; + + Type = getToolType(type); + Material = getToolMaterial(mat); + + +} + +const std::vector Tool::ToolTypes(void) +{ + std::vector toolTypes(13); + toolTypes[0] ="EndMill"; + toolTypes[1] ="Drill"; + toolTypes[2] ="CenterDrill"; + toolTypes[3] ="CounterSink"; + toolTypes[4] ="CounterBore"; + toolTypes[5] ="FlyCutter"; + toolTypes[6] ="Reamer"; + toolTypes[7] ="Tap"; + toolTypes[8] ="SlotCutter"; + toolTypes[9] ="BallEndMill"; + toolTypes[10] ="ChamferMill"; + toolTypes[11] ="CornerRound"; + toolTypes[12] ="Engraver"; + return toolTypes; + +} + +const std::vector Tool::ToolMaterials(void) +{ + std::vector toolMat(7); + toolMat[0] ="Carbide"; + toolMat[1] ="HighSpeedSteel"; + toolMat[2] ="HighCarbonToolSteel"; + toolMat[3] ="CastAlloy"; + toolMat[4] ="Ceramics"; + toolMat[5] ="Diamond"; + toolMat[6] ="Sialon"; + return toolMat; + +} + +Tool::ToolType Tool::getToolType(std::string type) +{ + Tool::ToolType Type; + if(type=="EndMill") + Type = Tool::ENDMILL; + else if(type=="Drill") + Type = Tool::DRILL; + else if(type=="CenterDrill") + Type = Tool::CENTERDRILL; + else if(type=="CounterSink") + Type = Tool::COUNTERSINK; + else if(type=="CounterBore") + Type = Tool::COUNTERBORE; + else if(type=="FlyCutter") + Type = Tool::FLYCUTTER; + else if(type=="Reamer") + Type = Tool::REAMER; + else if(type=="Tap") + Type = Tool::TAP; + else if(type=="SlotCutter") + Type = Tool::SLOTCUTTER; + else if(type=="BallEndMill") + Type = Tool::BALLENDMILL; + else if(type=="ChamferMill") + Type = Tool::CHAMFERMILL; + else if(type=="CornerRound") + Type = Tool::CORNERROUND; + else if(type=="Engraver") + Type = Tool::ENGRAVER; + else + Type = Tool::UNDEFINED; + + return Type; +} + +Tool::ToolMaterial Tool::getToolMaterial(std::string mat) +{ + Tool::ToolMaterial Material; + if(mat=="Carbide") + Material = Tool::CARBIDE; + else if(mat=="HighSpeedSteel") + Material = Tool::HIGHSPEEDSTEEL; + else if(mat=="HighCarbonToolSteel") + Material = Tool::HIGHCARBONTOOLSTEEL; + else if(mat=="CastAlloy") + Material = Tool::CASTALLOY; + else if(mat=="Ceramics") + Material = Tool::CERAMICS; + else if(mat=="Diamond") + Material = Tool::DIAMOND; + else if(mat=="Sialon") + Material = Tool::SIALON; + else + Material = Tool::MATUNDEFINED; + + return Material; +} + +const char* Tool::TypeName(Tool::ToolType typ) { + switch (typ) { + case Tool::DRILL: + return "Drill"; + case Tool::CENTERDRILL: + return "CenterDrill"; + case Tool::COUNTERSINK: + return "CounterSink"; + case Tool::COUNTERBORE: + return "CounterBore"; + case Tool::FLYCUTTER: + return "FlyCutter"; + case Tool::REAMER: + return "Reamer"; + case Tool::TAP: + return "Tap"; + case Tool::ENDMILL: + return "EndMill"; + case Tool::SLOTCUTTER: + return "SlotCutter"; + case Tool::BALLENDMILL: + return "BallEndMill"; + case Tool::CHAMFERMILL: + return "ChamferMill"; + case Tool::CORNERROUND: + return "CornerRound"; + case Tool::ENGRAVER: + return "Engraver"; + case Tool::UNDEFINED: + return "Undefined"; + } + return "Undefined"; +} + +const char* Tool::MaterialName(Tool::ToolMaterial mat) +{ + switch (mat) { + case Tool::HIGHSPEEDSTEEL: + return "HighSpeedSteel"; + case Tool::CARBIDE: + return "Carbide"; + case Tool::HIGHCARBONTOOLSTEEL: + return "HighCarbonToolSteel"; + case Tool::CASTALLOY: + return "CastAlloy"; + case Tool::CERAMICS: + return "Ceramics"; + case Tool::DIAMOND: + return "Diamond"; + case Tool::SIALON: + return "Sialon"; + case Tool::MATUNDEFINED: + return "Undefined"; + } + return "Undefined"; +} \ No newline at end of file diff --git a/src/Mod/Path/App/Tool.h b/src/Mod/Path/App/Tool.h new file mode 100644 index 000000000000..f06ef2bb35c0 --- /dev/null +++ b/src/Mod/Path/App/Tool.h @@ -0,0 +1,105 @@ +/*************************************************************************** + * Copyright (c) Yorik van Havre (yorik@uncreated.net) 2014 * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#ifndef PATH_TOOL_H +#define PATH_TOOL_H + +#include +#include +#include +#include + +namespace Path +{ + + /** The representation of a single tool */ + class PathExport Tool : public Base::Persistence + { + TYPESYSTEM_HEADER(); + + public: + enum ToolType { + UNDEFINED, + DRILL, + CENTERDRILL, + COUNTERSINK, + COUNTERBORE, + FLYCUTTER, + REAMER, + TAP, + ENDMILL, + SLOTCUTTER, + BALLENDMILL, + CHAMFERMILL, + CORNERROUND, + ENGRAVER }; + + enum ToolMaterial { + MATUNDEFINED, + HIGHSPEEDSTEEL, + HIGHCARBONTOOLSTEEL, + CASTALLOY, + CARBIDE, + CERAMICS, + DIAMOND, + SIALON }; + + //constructors + Tool(); + Tool(const char* name, + ToolType type=Tool::UNDEFINED, + ToolMaterial material=Tool::MATUNDEFINED, + double diameter=10.0, + double lengthoffset=100, + double flatradius=0, + double cornerradius=0, + double cuttingedgeangle=0, + double cuttingedgeheight=0); + ~Tool(); + + // from base class + virtual unsigned int getMemSize (void) const; + virtual void Save (Base::Writer &/*writer*/) const; + virtual void Restore(Base::XMLReader &/*reader*/); + + // attributes + std::string Name; + ToolType Type; + ToolMaterial Material; + double Diameter; + double LengthOffset; + double FlatRadius; + double CornerRadius; + double CuttingEdgeAngle; + double CuttingEdgeHeight; + + static const std::vector ToolTypes(void); + static const std::vector ToolMaterials(void); + static const char* TypeName(ToolType typ); + static ToolType getToolType(std::string type); + static ToolMaterial getToolMaterial(std::string mat); + static const char* MaterialName(ToolMaterial mat); + }; +} //namespace Path + +#endif // PATH_TOOL_H diff --git a/src/Mod/Path/App/ToolPy.xml b/src/Mod/Path/App/ToolPy.xml index 0f515c8491ef..94e56525d330 100644 --- a/src/Mod/Path/App/ToolPy.xml +++ b/src/Mod/Path/App/ToolPy.xml @@ -5,7 +5,7 @@ Name="ToolPy" Twin="Tool" TwinPointer="Tool" - Include="Mod/Path/App/Tooltable.h" + Include="Mod/Path/App/Tool.h" Namespace="Path" FatherInclude="Base/PersistencePy.h" FatherNamespace="Base" diff --git a/src/Mod/Path/App/ToolPyImp.cpp b/src/Mod/Path/App/ToolPyImp.cpp new file mode 100644 index 000000000000..57d4e87d9597 --- /dev/null +++ b/src/Mod/Path/App/ToolPyImp.cpp @@ -0,0 +1,304 @@ +/*************************************************************************** + * Copyright (c) Yorik van Havre (yorik@uncreated.net) 2014 * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#include "PreCompiled.h" +#include "Base/Reader.h" +#include "Mod/Path/App/Tool.h" +#include "Mod/Path/App/Tooltable.h" + +// inclusion of the generated files (generated out of ToolPy.xml and TooltablePy.xml) +#include "ToolPy.h" +#include "ToolPy.cpp" +//#include "TooltablePy.h" +//#include "TooltablePy.cpp" + +using namespace Path; + +#if PY_MAJOR_VERSION >= 3 +# define PYSTRING_FROMSTRING(str) PyUnicode_FromString(str) +# define PYINT_TYPE PyLong_Type +# define PYINT_FROMLONG(l) PyLong_FromLong(l) +# define PYINT_ASLONG(o) PyLong_AsLong(o) +#else +# define PYSTRING_FROMSTRING(str) PyString_FromString(str) +# define PYINT_TYPE PyInt_Type +# define PYINT_FROMLONG(l) PyInt_FromLong(l) +# define PYINT_ASLONG(o) PyInt_AsLong(o) +#endif + + +// returns a string which represents the object e.g. when printed in python +std::string ToolPy::representation(void) const +{ + std::stringstream str; + str.precision(5); + str << "Tool "; + str << getToolPtr()->Name; + return str.str(); +} + +PyObject *ToolPy::PyMake(struct _typeobject *, PyObject *, PyObject *) // Python wrapper +{ + // create a new instance of ToolPy and the Twin object + return new ToolPy(new Tool); +} + +// constructor method +int ToolPy::PyInit(PyObject* args, PyObject* kwd) +{ + char *name="Default tool"; + char *type = "Undefined"; + char *mat = "Undefined"; + PyObject *dia = 0; + PyObject *len = 0; + PyObject *fla = 0; + PyObject *cor = 0; + PyObject *ang = 0; + PyObject *hei = 0; + int version = 1; + + static char *kwlist[] = {"name", "tooltype", "material", "diameter", "lengthOffset", "flatRadius", "cornerRadius", "cuttingEdgeAngle", "cuttingEdgeHeight" , "version", NULL}; + + PyObject *dict = 0; + if (!kwd && (PyObject_TypeCheck(args, &PyDict_Type) || PyArg_ParseTuple(args, "O!", &PyDict_Type, &dict))) { + static PyObject *arg = PyTuple_New(0); + if (PyObject_TypeCheck(args, &PyDict_Type)) { + dict = args; + } + if (!PyArg_ParseTupleAndKeywords(arg, dict, "|sssOOOOOOi", kwlist, &name, &type, &mat, &dia, &len, &fla, &cor, &ang, &hei, &version)) { + return -1; + } + } else { + PyErr_Clear(); + if (!PyArg_ParseTupleAndKeywords(args, kwd, "|sssOOOOOO", kwlist, &name, &type, &mat, &dia, &len, &fla, &cor, &ang, &hei)) { + return -1; + } + } + + if (1 != version) { + PyErr_SetString(PyExc_TypeError, "Unsupported Tool template version"); + return -1; + } + + getToolPtr()->Name = name; + + std::string typeStr(type); + getToolPtr()->Type = Tool::getToolType(typeStr); + + std::string matStr(mat); + getToolPtr()->Material = Tool::getToolMaterial(matStr); + + getToolPtr()->Diameter = dia ? PyFloat_AsDouble(dia) : 0.0; + getToolPtr()->LengthOffset = len ? PyFloat_AsDouble(len) : 0.0; + getToolPtr()->FlatRadius = fla ? PyFloat_AsDouble(fla) : 0.0; + getToolPtr()->CornerRadius = cor ? PyFloat_AsDouble(cor) : 0.0; + getToolPtr()->CuttingEdgeAngle = ang ? PyFloat_AsDouble(ang) : 180.0; + getToolPtr()->CuttingEdgeHeight = hei ? PyFloat_AsDouble(hei) : 0.0; + + return 0; +} + +// attributes get/setters + +Py::String ToolPy::getName(void) const +{ + return Py::String(getToolPtr()->Name.c_str()); +} + +void ToolPy::setName(Py::String arg) +{ + std::string name = arg.as_std_string(); + getToolPtr()->Name = name; +} + +Py::String ToolPy::getToolType(void) const +{ + return Py::String(Tool::TypeName(getToolPtr()->Type)); +} + +void ToolPy::setToolType(Py::String arg) +{ + std::string typeStr(arg.as_std_string()); + getToolPtr()->Type = Tool::getToolType(typeStr); + +} + +Py::String ToolPy::getMaterial(void) const +{ + return Py::String(Tool::MaterialName(getToolPtr()->Material)); +} + +void ToolPy::setMaterial(Py::String arg) +{ + std::string matStr(arg.as_std_string()); + getToolPtr()->Material = Tool::getToolMaterial(matStr); +} + +Py::Float ToolPy::getDiameter(void) const +{ + return Py::Float(getToolPtr()->Diameter); +} + +void ToolPy::setDiameter(Py::Float arg) +{ + getToolPtr()->Diameter = arg.operator double(); +} + +Py::Float ToolPy::getLengthOffset(void) const +{ + return Py::Float(getToolPtr()->LengthOffset); +} + +void ToolPy::setLengthOffset(Py::Float arg) +{ + getToolPtr()->LengthOffset = arg.operator double(); +} + +Py::Float ToolPy::getFlatRadius(void) const +{ + return Py::Float(getToolPtr()->FlatRadius); +} + +void ToolPy::setFlatRadius(Py::Float arg) +{ + getToolPtr()->FlatRadius = arg.operator double(); +} + +Py::Float ToolPy::getCornerRadius(void) const +{ + return Py::Float(getToolPtr()->CornerRadius); +} + +void ToolPy::setCornerRadius(Py::Float arg) +{ + getToolPtr()->CornerRadius = arg.operator double(); +} + +Py::Float ToolPy::getCuttingEdgeAngle(void) const +{ + return Py::Float(getToolPtr()->CuttingEdgeAngle); +} + +void ToolPy::setCuttingEdgeAngle(Py::Float arg) +{ + getToolPtr()->CuttingEdgeAngle = arg.operator double(); +} + +Py::Float ToolPy::getCuttingEdgeHeight(void) const +{ + return Py::Float(getToolPtr()->CuttingEdgeHeight); +} + +void ToolPy::setCuttingEdgeHeight(Py::Float arg) +{ + getToolPtr()->CuttingEdgeHeight = arg.operator double(); +} + +// custom attributes get/set + +PyObject *ToolPy::getCustomAttributes(const char* /*attr*/) const +{ + return 0; +} + +int ToolPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/) +{ + return 0; +} + +PyObject* ToolPy::copy(PyObject * args) +{ + if (PyArg_ParseTuple(args, "")) { + return new ToolPy(new Path::Tool(*getToolPtr())); + } + throw Py::TypeError("This method accepts no argument"); +} + +PyObject* ToolPy::setFromTemplate(PyObject * args) +{ + char *pstr = 0; + if (PyArg_ParseTuple(args, "s", &pstr)) { + // embed actual string in dummy tag so XMLReader can consume that on construction + std::ostringstream os; + os << "" << pstr << ""; + std::istringstream is(os.str()); + Base::XMLReader reader("", is); + getToolPtr()->Restore(reader); + Py_Return ; + } + + PyErr_Clear(); + if (!PyInit(args, 0)) { + Py_Return ; + } + + PyErr_SetString(PyExc_TypeError, "argument must be a string or dictionary"); + return 0; +} + +PyObject* ToolPy::templateAttrs(PyObject * args) +{ + if (!args || PyArg_ParseTuple(args, "")) { + PyObject *dict = PyDict_New(); + PyDict_SetItemString(dict, "version", PYINT_FROMLONG(1)); + PyDict_SetItemString(dict, "name", PYSTRING_FROMSTRING(getToolPtr()->Name.c_str())); + PyDict_SetItemString(dict, "tooltype",PYSTRING_FROMSTRING(Tool::TypeName(getToolPtr()->Type))); + PyDict_SetItemString(dict, "material", PYSTRING_FROMSTRING(Tool::MaterialName(getToolPtr()->Material))); + PyDict_SetItemString(dict, "diameter", PyFloat_FromDouble(getToolPtr()->Diameter)); + PyDict_SetItemString(dict, "lengthOffset", PyFloat_FromDouble(getToolPtr()->LengthOffset)); + PyDict_SetItemString(dict, "flatRadius", PyFloat_FromDouble(getToolPtr()->FlatRadius)); + PyDict_SetItemString(dict, "cornerRadius", PyFloat_FromDouble(getToolPtr()->CornerRadius)); + PyDict_SetItemString(dict, "cuttingEdgeAngle", PyFloat_FromDouble(getToolPtr()->CuttingEdgeAngle)); + PyDict_SetItemString(dict, "cuttingEdgeHeight", PyFloat_FromDouble(getToolPtr()->CuttingEdgeHeight)); + return dict; + } + throw Py::TypeError("This method accepts no argument"); +} + +PyObject* ToolPy::getToolTypes(PyObject * args) +{ + if (PyArg_ParseTuple(args, "")) { + std::vector toolTypes = Tool::ToolTypes(); + PyObject *list = PyList_New(0); + for(unsigned i = 0; i != toolTypes.size(); i++) { + + PyList_Append(list, PYSTRING_FROMSTRING(toolTypes[i].c_str())); + } + return list; + } + throw Py::TypeError("This method accepts no argument"); +} + +PyObject* ToolPy::getToolMaterials(PyObject * args) +{ + if (PyArg_ParseTuple(args, "")) { + std::vector toolMaterials = Tool::ToolMaterials(); + PyObject *list = PyList_New(0); + for(unsigned i = 0; i != toolMaterials.size(); i++) { + + PyList_Append(list, PYSTRING_FROMSTRING(toolMaterials[i].c_str())); + } + return list; + } + throw Py::TypeError("This method accepts no argument"); +} \ No newline at end of file diff --git a/src/Mod/Path/App/Tooltable.cpp b/src/Mod/Path/App/Tooltable.cpp index 85cfc89cd7b3..3fe036760a3a 100644 --- a/src/Mod/Path/App/Tooltable.cpp +++ b/src/Mod/Path/App/Tooltable.cpp @@ -31,242 +31,10 @@ #include #include "Tooltable.h" + using namespace Base; using namespace Path; - -// TOOL - - -TYPESYSTEM_SOURCE(Path::Tool , Base::Persistence); - -// Constructors & destructors - -Tool::Tool(const char* name, - ToolType type, - ToolMaterial /*material*/, - double diameter, - double lengthoffset, - double flatradius, - double cornerradius, - double cuttingedgeangle, - double cuttingedgeheight) -:Name(name),Type(type),Material(MATUNDEFINED),Diameter(diameter),LengthOffset(lengthoffset), -FlatRadius(flatradius),CornerRadius(cornerradius),CuttingEdgeAngle(cuttingedgeangle), -CuttingEdgeHeight(cuttingedgeheight) -{ -} - -Tool::Tool() -{ - Type = UNDEFINED; - Material = MATUNDEFINED; - Diameter = 0; - LengthOffset = 0; - FlatRadius = 0; - CornerRadius = 0; - CuttingEdgeAngle = 180; - CuttingEdgeHeight = 0; -} - -Tool::~Tool() -{ -} - -// Reimplemented from base class - -unsigned int Tool::getMemSize (void) const -{ - return 0; -} - -void Tool::Save (Writer &writer) const -{ - writer.Stream() << writer.ind() << "" << std::endl; -} - -void Tool::Restore(XMLReader &reader) -{ - reader.readElement("Tool"); - Name = reader.getAttribute("name"); - Diameter = reader.hasAttribute("diameter") ? (double) reader.getAttributeAsFloat("diameter") : 0.0; - LengthOffset = reader.hasAttribute("length") ? (double) reader.getAttributeAsFloat("length") : 0.0; - FlatRadius = reader.hasAttribute("flat") ? (double) reader.getAttributeAsFloat("flat") : 0.0; - CornerRadius = reader.hasAttribute("corner") ? (double) reader.getAttributeAsFloat("corner") : 0.0; - CuttingEdgeAngle = reader.hasAttribute("angle") ? (double) reader.getAttributeAsFloat("angle") : 180.0; - CuttingEdgeHeight = reader.hasAttribute("height") ? (double) reader.getAttributeAsFloat("height") : 0.0; - std::string type = reader.hasAttribute("type") ? reader.getAttribute("type") : ""; - std::string mat = reader.hasAttribute("mat") ? reader.getAttribute("mat") : ""; - - Type = getToolType(type); - Material = getToolMaterial(mat); - - -} - -const std::vector Tool::ToolTypes(void) -{ - std::vector toolTypes(13); - toolTypes[0] ="EndMill"; - toolTypes[1] ="Drill"; - toolTypes[2] ="CenterDrill"; - toolTypes[3] ="CounterSink"; - toolTypes[4] ="CounterBore"; - toolTypes[5] ="FlyCutter"; - toolTypes[6] ="Reamer"; - toolTypes[7] ="Tap"; - toolTypes[8] ="SlotCutter"; - toolTypes[9] ="BallEndMill"; - toolTypes[10] ="ChamferMill"; - toolTypes[11] ="CornerRound"; - toolTypes[12] ="Engraver"; - return toolTypes; - -} - -const std::vector Tool::ToolMaterials(void) -{ - std::vector toolMat(7); - toolMat[0] ="Carbide"; - toolMat[1] ="HighSpeedSteel"; - toolMat[2] ="HighCarbonToolSteel"; - toolMat[3] ="CastAlloy"; - toolMat[4] ="Ceramics"; - toolMat[5] ="Diamond"; - toolMat[6] ="Sialon"; - return toolMat; - -} - -Tool::ToolType Tool::getToolType(std::string type) -{ - Tool::ToolType Type; - if(type=="EndMill") - Type = Tool::ENDMILL; - else if(type=="Drill") - Type = Tool::DRILL; - else if(type=="CenterDrill") - Type = Tool::CENTERDRILL; - else if(type=="CounterSink") - Type = Tool::COUNTERSINK; - else if(type=="CounterBore") - Type = Tool::COUNTERBORE; - else if(type=="FlyCutter") - Type = Tool::FLYCUTTER; - else if(type=="Reamer") - Type = Tool::REAMER; - else if(type=="Tap") - Type = Tool::TAP; - else if(type=="SlotCutter") - Type = Tool::SLOTCUTTER; - else if(type=="BallEndMill") - Type = Tool::BALLENDMILL; - else if(type=="ChamferMill") - Type = Tool::CHAMFERMILL; - else if(type=="CornerRound") - Type = Tool::CORNERROUND; - else if(type=="Engraver") - Type = Tool::ENGRAVER; - else - Type = Tool::UNDEFINED; - - return Type; -} - -Tool::ToolMaterial Tool::getToolMaterial(std::string mat) -{ - Tool::ToolMaterial Material; - if(mat=="Carbide") - Material = Tool::CARBIDE; - else if(mat=="HighSpeedSteel") - Material = Tool::HIGHSPEEDSTEEL; - else if(mat=="HighCarbonToolSteel") - Material = Tool::HIGHCARBONTOOLSTEEL; - else if(mat=="CastAlloy") - Material = Tool::CASTALLOY; - else if(mat=="Ceramics") - Material = Tool::CERAMICS; - else if(mat=="Diamond") - Material = Tool::DIAMOND; - else if(mat=="Sialon") - Material = Tool::SIALON; - else - Material = Tool::MATUNDEFINED; - - return Material; -} - -const char* Tool::TypeName(Tool::ToolType typ) { - switch (typ) { - case Tool::DRILL: - return "Drill"; - case Tool::CENTERDRILL: - return "CenterDrill"; - case Tool::COUNTERSINK: - return "CounterSink"; - case Tool::COUNTERBORE: - return "CounterBore"; - case Tool::FLYCUTTER: - return "FlyCutter"; - case Tool::REAMER: - return "Reamer"; - case Tool::TAP: - return "Tap"; - case Tool::ENDMILL: - return "EndMill"; - case Tool::SLOTCUTTER: - return "SlotCutter"; - case Tool::BALLENDMILL: - return "BallEndMill"; - case Tool::CHAMFERMILL: - return "ChamferMill"; - case Tool::CORNERROUND: - return "CornerRound"; - case Tool::ENGRAVER: - return "Engraver"; - case Tool::UNDEFINED: - return "Undefined"; - } - return "Undefined"; -} - -const char* Tool::MaterialName(Tool::ToolMaterial mat) -{ - switch (mat) { - case Tool::HIGHSPEEDSTEEL: - return "HighSpeedSteel"; - case Tool::CARBIDE: - return "Carbide"; - case Tool::HIGHCARBONTOOLSTEEL: - return "HighCarbonToolSteel"; - case Tool::CASTALLOY: - return "CastAlloy"; - case Tool::CERAMICS: - return "Ceramics"; - case Tool::DIAMOND: - return "Diamond"; - case Tool::SIALON: - return "Sialon"; - case Tool::MATUNDEFINED: - return "Undefined"; - } - return "Undefined"; -} - -// TOOLTABLE - - - TYPESYSTEM_SOURCE(Path::Tooltable , Base::Persistence); Tooltable::Tooltable() diff --git a/src/Mod/Path/App/Tooltable.h b/src/Mod/Path/App/Tooltable.h index 450ea826b23b..13a051704e55 100644 --- a/src/Mod/Path/App/Tooltable.h +++ b/src/Mod/Path/App/Tooltable.h @@ -28,80 +28,10 @@ #include #include #include +#include "Tool.h" namespace Path -{ - - /** The representation of a single tool */ - class PathExport Tool : public Base::Persistence - { - TYPESYSTEM_HEADER(); - - public: - enum ToolType { - UNDEFINED, - DRILL, - CENTERDRILL, - COUNTERSINK, - COUNTERBORE, - FLYCUTTER, - REAMER, - TAP, - ENDMILL, - SLOTCUTTER, - BALLENDMILL, - CHAMFERMILL, - CORNERROUND, - ENGRAVER }; - - enum ToolMaterial { - MATUNDEFINED, - HIGHSPEEDSTEEL, - HIGHCARBONTOOLSTEEL, - CASTALLOY, - CARBIDE, - CERAMICS, - DIAMOND, - SIALON }; - - //constructors - Tool(); - Tool(const char* name, - ToolType type=Tool::UNDEFINED, - ToolMaterial material=Tool::MATUNDEFINED, - double diameter=10.0, - double lengthoffset=100, - double flatradius=0, - double cornerradius=0, - double cuttingedgeangle=0, - double cuttingedgeheight=0); - ~Tool(); - - // from base class - virtual unsigned int getMemSize (void) const; - virtual void Save (Base::Writer &/*writer*/) const; - virtual void Restore(Base::XMLReader &/*reader*/); - - // attributes - std::string Name; - ToolType Type; - ToolMaterial Material; - double Diameter; - double LengthOffset; - double FlatRadius; - double CornerRadius; - double CuttingEdgeAngle; - double CuttingEdgeHeight; - - static const std::vector ToolTypes(void); - static const std::vector ToolMaterials(void); - static const char* TypeName(ToolType typ); - static ToolType getToolType(std::string type); - static ToolMaterial getToolMaterial(std::string mat); - static const char* MaterialName(ToolMaterial mat); - }; - - /** The representation of a table of tools */ +{ /** The representation of a table of tools */ class PathExport Tooltable : public Base::Persistence { TYPESYSTEM_HEADER(); diff --git a/src/Mod/Path/App/TooltablePyImp.cpp b/src/Mod/Path/App/TooltablePyImp.cpp index 756ef0a23a79..05bcb0bf9118 100644 --- a/src/Mod/Path/App/TooltablePyImp.cpp +++ b/src/Mod/Path/App/TooltablePyImp.cpp @@ -23,231 +23,17 @@ #include "PreCompiled.h" #include "Base/Reader.h" +#include "Mod/Path/App/Tool.h" #include "Mod/Path/App/Tooltable.h" // inclusion of the generated files (generated out of ToolPy.xml and TooltablePy.xml) #include "ToolPy.h" -#include "ToolPy.cpp" +//#include "ToolPy.cpp" #include "TooltablePy.h" #include "TooltablePy.cpp" using namespace Path; - - -// ToolPy - - - -// returns a string which represents the object e.g. when printed in python -std::string ToolPy::representation(void) const -{ - std::stringstream str; - str.precision(5); - str << "Tool "; - str << getToolPtr()->Name; - return str.str(); -} - -PyObject *ToolPy::PyMake(struct _typeobject *, PyObject *, PyObject *) // Python wrapper -{ - // create a new instance of ToolPy and the Twin object - return new ToolPy(new Tool); -} - -// constructor method -int ToolPy::PyInit(PyObject* args, PyObject* kwd) -{ - char *name="Default tool"; - char *type = "Undefined"; - char *mat = "Undefined"; - PyObject *dia = 0; - PyObject *len = 0; - PyObject *fla = 0; - PyObject *cor = 0; - PyObject *ang = 0; - PyObject *hei = 0; - int version = 1; - - static char *kwlist[] = {"name", "tooltype", "material", "diameter", "lengthOffset", "flatRadius", "cornerRadius", "cuttingEdgeAngle", "cuttingEdgeHeight" , "version", NULL}; - - PyObject *dict = 0; - if (!kwd && (PyObject_TypeCheck(args, &PyDict_Type) || PyArg_ParseTuple(args, "O!", &PyDict_Type, &dict))) { - static PyObject *arg = PyTuple_New(0); - if (PyObject_TypeCheck(args, &PyDict_Type)) { - dict = args; - } - if (!PyArg_ParseTupleAndKeywords(arg, dict, "|sssOOOOOOi", kwlist, &name, &type, &mat, &dia, &len, &fla, &cor, &ang, &hei, &version)) { - return -1; - } - } else { - PyErr_Clear(); - if (!PyArg_ParseTupleAndKeywords(args, kwd, "|sssOOOOOO", kwlist, &name, &type, &mat, &dia, &len, &fla, &cor, &ang, &hei)) { - return -1; - } - } - - if (1 != version) { - PyErr_SetString(PyExc_TypeError, "Unsupported Tool template version"); - return -1; - } - - getToolPtr()->Name = name; - - std::string typeStr(type); - getToolPtr()->Type = Tool::getToolType(typeStr); - - std::string matStr(mat); - getToolPtr()->Material = Tool::getToolMaterial(matStr); - - getToolPtr()->Diameter = dia ? PyFloat_AsDouble(dia) : 0.0; - getToolPtr()->LengthOffset = len ? PyFloat_AsDouble(len) : 0.0; - getToolPtr()->FlatRadius = fla ? PyFloat_AsDouble(fla) : 0.0; - getToolPtr()->CornerRadius = cor ? PyFloat_AsDouble(cor) : 0.0; - getToolPtr()->CuttingEdgeAngle = ang ? PyFloat_AsDouble(ang) : 180.0; - getToolPtr()->CuttingEdgeHeight = hei ? PyFloat_AsDouble(hei) : 0.0; - - return 0; -} - -// attributes get/setters - -Py::String ToolPy::getName(void) const -{ - return Py::String(getToolPtr()->Name.c_str()); -} - -void ToolPy::setName(Py::String arg) -{ - std::string name = arg.as_std_string(); - getToolPtr()->Name = name; -} - -Py::String ToolPy::getToolType(void) const -{ - return Py::String(Tool::TypeName(getToolPtr()->Type)); -} - -void ToolPy::setToolType(Py::String arg) -{ - std::string typeStr(arg.as_std_string()); - getToolPtr()->Type = Tool::getToolType(typeStr); - -} - -Py::String ToolPy::getMaterial(void) const -{ - return Py::String(Tool::MaterialName(getToolPtr()->Material)); -} - -void ToolPy::setMaterial(Py::String arg) -{ - std::string matStr(arg.as_std_string()); - getToolPtr()->Material = Tool::getToolMaterial(matStr); -} - -Py::Float ToolPy::getDiameter(void) const -{ - return Py::Float(getToolPtr()->Diameter); -} - -void ToolPy::setDiameter(Py::Float arg) -{ - getToolPtr()->Diameter = arg.operator double(); -} - -Py::Float ToolPy::getLengthOffset(void) const -{ - return Py::Float(getToolPtr()->LengthOffset); -} - -void ToolPy::setLengthOffset(Py::Float arg) -{ - getToolPtr()->LengthOffset = arg.operator double(); -} - -Py::Float ToolPy::getFlatRadius(void) const -{ - return Py::Float(getToolPtr()->FlatRadius); -} - -void ToolPy::setFlatRadius(Py::Float arg) -{ - getToolPtr()->FlatRadius = arg.operator double(); -} - -Py::Float ToolPy::getCornerRadius(void) const -{ - return Py::Float(getToolPtr()->CornerRadius); -} - -void ToolPy::setCornerRadius(Py::Float arg) -{ - getToolPtr()->CornerRadius = arg.operator double(); -} - -Py::Float ToolPy::getCuttingEdgeAngle(void) const -{ - return Py::Float(getToolPtr()->CuttingEdgeAngle); -} - -void ToolPy::setCuttingEdgeAngle(Py::Float arg) -{ - getToolPtr()->CuttingEdgeAngle = arg.operator double(); -} - -Py::Float ToolPy::getCuttingEdgeHeight(void) const -{ - return Py::Float(getToolPtr()->CuttingEdgeHeight); -} - -void ToolPy::setCuttingEdgeHeight(Py::Float arg) -{ - getToolPtr()->CuttingEdgeHeight = arg.operator double(); -} - -// custom attributes get/set - -PyObject *ToolPy::getCustomAttributes(const char* /*attr*/) const -{ - return 0; -} - -int ToolPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/) -{ - return 0; -} - -PyObject* ToolPy::copy(PyObject * args) -{ - if (PyArg_ParseTuple(args, "")) { - return new ToolPy(new Path::Tool(*getToolPtr())); - } - throw Py::TypeError("This method accepts no argument"); -} - -PyObject* ToolPy::setFromTemplate(PyObject * args) -{ - char *pstr = 0; - if (PyArg_ParseTuple(args, "s", &pstr)) { - // embed actual string in dummy tag so XMLReader can consume that on construction - std::ostringstream os; - os << "" << pstr << ""; - std::istringstream is(os.str()); - Base::XMLReader reader("", is); - getToolPtr()->Restore(reader); - Py_Return ; - } - - PyErr_Clear(); - if (!PyInit(args, 0)) { - Py_Return ; - } - - PyErr_SetString(PyExc_TypeError, "argument must be a string or dictionary"); - return 0; -} - #if PY_MAJOR_VERSION >= 3 # define PYSTRING_FROMSTRING(str) PyUnicode_FromString(str) # define PYINT_TYPE PyLong_Type @@ -260,59 +46,6 @@ PyObject* ToolPy::setFromTemplate(PyObject * args) # define PYINT_ASLONG(o) PyInt_AsLong(o) #endif -PyObject* ToolPy::templateAttrs(PyObject * args) -{ - if (!args || PyArg_ParseTuple(args, "")) { - PyObject *dict = PyDict_New(); - PyDict_SetItemString(dict, "version", PYINT_FROMLONG(1)); - PyDict_SetItemString(dict, "name", PYSTRING_FROMSTRING(getToolPtr()->Name.c_str())); - PyDict_SetItemString(dict, "tooltype",PYSTRING_FROMSTRING(Tool::TypeName(getToolPtr()->Type))); - PyDict_SetItemString(dict, "material", PYSTRING_FROMSTRING(Tool::MaterialName(getToolPtr()->Material))); - PyDict_SetItemString(dict, "diameter", PyFloat_FromDouble(getToolPtr()->Diameter)); - PyDict_SetItemString(dict, "lengthOffset", PyFloat_FromDouble(getToolPtr()->LengthOffset)); - PyDict_SetItemString(dict, "flatRadius", PyFloat_FromDouble(getToolPtr()->FlatRadius)); - PyDict_SetItemString(dict, "cornerRadius", PyFloat_FromDouble(getToolPtr()->CornerRadius)); - PyDict_SetItemString(dict, "cuttingEdgeAngle", PyFloat_FromDouble(getToolPtr()->CuttingEdgeAngle)); - PyDict_SetItemString(dict, "cuttingEdgeHeight", PyFloat_FromDouble(getToolPtr()->CuttingEdgeHeight)); - return dict; - } - throw Py::TypeError("This method accepts no argument"); -} - -PyObject* ToolPy::getToolTypes(PyObject * args) -{ - if (PyArg_ParseTuple(args, "")) { - std::vector toolTypes = Tool::ToolTypes(); - PyObject *list = PyList_New(0); - for(unsigned i = 0; i != toolTypes.size(); i++) { - - PyList_Append(list, PYSTRING_FROMSTRING(toolTypes[i].c_str())); - } - return list; - } - throw Py::TypeError("This method accepts no argument"); -} - -PyObject* ToolPy::getToolMaterials(PyObject * args) -{ - if (PyArg_ParseTuple(args, "")) { - std::vector toolMaterials = Tool::ToolMaterials(); - PyObject *list = PyList_New(0); - for(unsigned i = 0; i != toolMaterials.size(); i++) { - - PyList_Append(list, PYSTRING_FROMSTRING(toolMaterials[i].c_str())); - } - return list; - } - throw Py::TypeError("This method accepts no argument"); -} - - -// TooltablePy - - - - // returns a string which represents the object e.g. when printed in python std::string TooltablePy::representation(void) const { From c2245be90743c95380d9d8fa51704884e14fc09e Mon Sep 17 00:00:00 2001 From: Dubstar_04 Date: Tue, 20 Aug 2019 20:41:53 +0100 Subject: [PATCH 2/9] Tidy up includes and whitespace --- src/Mod/Path/App/Tool.cpp | 6 ------ src/Mod/Path/App/Tool.h | 1 - src/Mod/Path/App/ToolPyImp.cpp | 2 -- src/Mod/Path/App/Tooltable.cpp | 1 - src/Mod/Path/App/TooltablePyImp.cpp | 1 - 5 files changed, 11 deletions(-) diff --git a/src/Mod/Path/App/Tool.cpp b/src/Mod/Path/App/Tool.cpp index 62a571d821fc..288626911e19 100644 --- a/src/Mod/Path/App/Tool.cpp +++ b/src/Mod/Path/App/Tool.cpp @@ -20,7 +20,6 @@ * * ***************************************************************************/ - #include "PreCompiled.h" #ifndef _PreComp_ @@ -34,10 +33,6 @@ using namespace Base; using namespace Path; - -// TOOL - - TYPESYSTEM_SOURCE(Path::Tool , Base::Persistence); // Constructors & destructors @@ -74,7 +69,6 @@ Tool::~Tool() } // Reimplemented from base class - unsigned int Tool::getMemSize (void) const { return 0; diff --git a/src/Mod/Path/App/Tool.h b/src/Mod/Path/App/Tool.h index f06ef2bb35c0..c8a5690fc3f8 100644 --- a/src/Mod/Path/App/Tool.h +++ b/src/Mod/Path/App/Tool.h @@ -20,7 +20,6 @@ * * ***************************************************************************/ - #ifndef PATH_TOOL_H #define PATH_TOOL_H diff --git a/src/Mod/Path/App/ToolPyImp.cpp b/src/Mod/Path/App/ToolPyImp.cpp index 57d4e87d9597..c075d2c786f0 100644 --- a/src/Mod/Path/App/ToolPyImp.cpp +++ b/src/Mod/Path/App/ToolPyImp.cpp @@ -29,8 +29,6 @@ // inclusion of the generated files (generated out of ToolPy.xml and TooltablePy.xml) #include "ToolPy.h" #include "ToolPy.cpp" -//#include "TooltablePy.h" -//#include "TooltablePy.cpp" using namespace Path; diff --git a/src/Mod/Path/App/Tooltable.cpp b/src/Mod/Path/App/Tooltable.cpp index 3fe036760a3a..a9351899e9fa 100644 --- a/src/Mod/Path/App/Tooltable.cpp +++ b/src/Mod/Path/App/Tooltable.cpp @@ -31,7 +31,6 @@ #include #include "Tooltable.h" - using namespace Base; using namespace Path; diff --git a/src/Mod/Path/App/TooltablePyImp.cpp b/src/Mod/Path/App/TooltablePyImp.cpp index 05bcb0bf9118..8c346ebc08d2 100644 --- a/src/Mod/Path/App/TooltablePyImp.cpp +++ b/src/Mod/Path/App/TooltablePyImp.cpp @@ -28,7 +28,6 @@ // inclusion of the generated files (generated out of ToolPy.xml and TooltablePy.xml) #include "ToolPy.h" -//#include "ToolPy.cpp" #include "TooltablePy.h" #include "TooltablePy.cpp" From 51f96a40fcd369105348d3986ae08948f8e08255 Mon Sep 17 00:00:00 2001 From: Dubstar_04 Date: Fri, 23 Aug 2019 22:13:04 +0100 Subject: [PATCH 3/9] Allow multiple Tool Tables Allow path to hold multiple tool tables --- src/Mod/Path/App/Tooltable.h | 3 + src/Mod/Path/App/TooltablePy.xml | 12 + src/Mod/Path/App/TooltablePyImp.cpp | 23 + .../Gui/Resources/panels/ToolLibraryEditor.ui | 208 +++++++- .../PathScripts/PathToolLibraryManager.py | 485 +++++++++++++----- 5 files changed, 578 insertions(+), 153 deletions(-) diff --git a/src/Mod/Path/App/Tooltable.h b/src/Mod/Path/App/Tooltable.h index 13a051704e55..77112398f520 100644 --- a/src/Mod/Path/App/Tooltable.h +++ b/src/Mod/Path/App/Tooltable.h @@ -50,6 +50,7 @@ namespace Path void addTool(const Tool &tool); // adds a tool at the end void setTool(const Tool &tool, int); // inserts a tool void deleteTool(int); // deletes a tool + //void setVersion(int); //set the table version // auto unsigned int getSize(void) const {return Tools.size();} @@ -59,6 +60,8 @@ namespace Path // attributes std::map Tools; + int Version; + std::string Name; }; } //namespace Path diff --git a/src/Mod/Path/App/TooltablePy.xml b/src/Mod/Path/App/TooltablePy.xml index 39230d35cbb6..0480a83b0383 100644 --- a/src/Mod/Path/App/TooltablePy.xml +++ b/src/Mod/Path/App/TooltablePy.xml @@ -15,6 +15,18 @@ The Tooltable object holds a table of CNC tools + + + the name of this tool table + + + + + + the version of this tooltable + + + the dictionary of tools of this table diff --git a/src/Mod/Path/App/TooltablePyImp.cpp b/src/Mod/Path/App/TooltablePyImp.cpp index 8c346ebc08d2..bb03bd8649bf 100644 --- a/src/Mod/Path/App/TooltablePyImp.cpp +++ b/src/Mod/Path/App/TooltablePyImp.cpp @@ -63,6 +63,9 @@ PyObject *TooltablePy::PyMake(struct _typeobject *, PyObject *, PyObject *) // // constructor method int TooltablePy::PyInit(PyObject* args, PyObject* /*kwd*/) { + char *name="Tooltable"; + int version = 1; + if (PyArg_ParseTuple(args, "")) { return 0; } @@ -234,6 +237,25 @@ int TooltablePy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/) return 0; } +Py::Int TooltablePy::getVersion(void) const +{ + return Py::Int(getTooltablePtr()->Version); +} + +void TooltablePy::setVersion(Py::Int version) { + getTooltablePtr()->Version = version; +} + +Py::String TooltablePy::getName(void) const +{ + return Py::String(getTooltablePtr()->Name.c_str()); +} + +void TooltablePy::setName(Py::String arg) +{ + std::string name = arg.as_std_string(); + getTooltablePtr()->Name = name; +} PyObject* TooltablePy::setFromTemplate(PyObject * args) { @@ -263,3 +285,4 @@ PyObject* TooltablePy::templateAttrs(PyObject * args) } return dict; } + diff --git a/src/Mod/Path/Gui/Resources/panels/ToolLibraryEditor.ui b/src/Mod/Path/Gui/Resources/panels/ToolLibraryEditor.ui index 01657469c426..ed3cdf6bd539 100644 --- a/src/Mod/Path/Gui/Resources/panels/ToolLibraryEditor.ui +++ b/src/Mod/Path/Gui/Resources/panels/ToolLibraryEditor.ui @@ -19,8 +19,8 @@ Tool Library - - + + @@ -38,32 +38,184 @@ - - - - true - - - QAbstractItemView::DragOnly - - - true - - - QAbstractItemView::SingleSelection - - - QAbstractItemView::SelectRows - - - false - - - false - - + + + + + + + 225 + 16777215 + + + + + 0 + + + 0 + + + 6 + + + 0 + + + + + + + Tool Tables + + + + + + + Qt::Horizontal + + + + 20 + 20 + + + + + + + + + + + 32 + 32 + + + + + + + + :/icons/FreeCAD-default/scalable/edit-edit.svg:/icons/FreeCAD-default/scalable/edit-edit.svg + + + + + + + + 32 + 32 + + + + + + + + :/icons/FreeCAD-default/scalable/list-remove.svg + + + + + + + + + 32 + 32 + + + + + + + + :/icons/FreeCAD-default/scalable/list-add.svg + + + + + + + + + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + + 0 + 0 + + + + true + + + + 20 + 20 + + + + + + + + + + + false + + + false + + + QAbstractItemView::NoDragDrop + + + Qt::IgnoreAction + + + true + + + QAbstractItemView::SingleSelection + + + QAbstractItemView::SelectRows + + + false + + + true + + + false + + + false + + + + - + @@ -140,7 +292,7 @@ - + Qt::Horizontal diff --git a/src/Mod/Path/PathScripts/PathToolLibraryManager.py b/src/Mod/Path/PathScripts/PathToolLibraryManager.py index 9580f60d2545..afeec843183b 100644 --- a/src/Mod/Path/PathScripts/PathToolLibraryManager.py +++ b/src/Mod/Path/PathScripts/PathToolLibraryManager.py @@ -145,6 +145,8 @@ class ToolLibraryManager(): preferences and all or part of the library can be exported to other formats ''' + #TODO: copy & Duplicate tools between lists + TooltableTypeJSON = translate("TooltableEditor", "Tooltable JSON (*.json)") TooltableTypeXML = translate("TooltableEditor", "Tooltable XML (*.xml)") TooltableTypeHeekscad = translate("TooltableEditor", "HeeksCAD tooltable (*.tooltable)") @@ -155,75 +157,194 @@ class ToolLibraryManager(): def __init__(self): self.prefs = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Path") + self.toolTables = [] + self.currentTableName = None + self.loadToolTables() + + if len(self.toolTables): + self.currentTableName = self.toolTables[0].Name + return - def templateAttrs(self, tooltable): - attrs = {} - attrs['Version'] = 1 - attrs['Tools'] = tooltable.templateAttrs() - return attrs + def getCurrentTableName(self): + ''' return the name of the currently loaded tool table ''' + return self.currentTableName + + def getCurrentTable(self): + ''' returns an object of the current tool table ''' + return self.getTableFromName(self.currentTableName) + + def getTableFromName(self, name): + ''' get the tool table object from the name ''' + for table in self.toolTables: + if table.Name == name: + return table + + def getNextToolTableName(self): + ''' get a unique name for a new tool table ''' + iter = 1 + tableNames = [] + + for table in self.toolTables: + tableNames.append(table.Name) + + while "ToolTable-" + str(iter) in tableNames: + iter += 1 + + return "ToolTable-" + str(iter) + + def addNewToolTable(self): + ''' creates a new tool table ''' + tt = Path.Tooltable() + tt.Version = 1 + name = self.getNextToolTableName() + tt.Name = name + self.toolTables.append(tt) + self.saveMainLibrary() + return name + + def deleteToolTable(self): + ''' deletes the selected tool table ''' + index = next((index for (index, d) in enumerate(self.toolTables) if d.Name == self.currentTableName), None) + self.toolTables.pop(index) + self.saveMainLibrary() + + def renameToolTable(self, newName, index): + ''' renames a tool table with the new name''' + currentTableName = self.toolTables[index].Name + if newName == currentTableName: + PathLog.error(translate('PathToolLibraryManager', "Tool Table Same Name")) + return False + if newName in self.toolTables: + PathLog.error(translate('PathToolLibraryManager', "Tool Table Name Exists")) + return False + tt = self.getTableFromName(currentTableName) + if tt: + tt.Name = newName + self.saveMainLibrary() + return True + + + def templateAttrs(self): + ''' gets the tool table arributes ''' + toolTables = [] + for tt in self.toolTables: + tableData = {} + tableData['Version'] = 1 + tableData['TableName'] = tt.Name + + toolData = {} + for tool in tt.Tools: + toolData[tool] = tt.Tools[tool].templateAttrs() + + tableData['Tools'] = toolData + toolTables.append(tableData) + + return toolTables def tooltableFromAttrs(self, stringattrs): if stringattrs.get('Version') and 1 == int(stringattrs['Version']): - attrs = {} - for key, val in PathUtil.keyValueIter(stringattrs['Tools']): - attrs[int(key)] = val - return Path.Tooltable(attrs) + + tt = Path.Tooltable() + tt.Version = 1 + + if stringattrs.get('Version'): + tt.Version = stringattrs.get('Version') + + if stringattrs.get('TableName'): + tt.Name = stringattrs.get('TableName') + + for key, attrs in PathUtil.keyValueIter(stringattrs['Tools']): + tool = Path.Tool() + tool.Name = str(attrs["name"]) + tool.ToolType = str(attrs["tooltype"]) + tool.Material = str(attrs["material"]) + tool.Diameter = float(attrs["diameter"]) + tool.LengthOffset = float(attrs["lengthOffset"]) + tool.FlatRadius = float(attrs["flatRadius"]) + tool.CornerRadius = float(attrs["cornerRadius"]) + tool.CuttingEdgeAngle = float(attrs["cuttingEdgeAngle"]) + tool.CuttingEdgeHeight = float(attrs["cuttingEdgeHeight"]) + tt.setTool(int(key), tool) + + return tt else: PathLog.error(translate('PathToolLibraryManager', "Unsupported Path tooltable template version %s") % stringattrs.get('Version')) return None - def saveMainLibrary(self, tooltable): + def loadToolTables(self): + ''' loads the tool tables from tehe stored data ''' + self.toolTables = [] + self.currentTableName = '' + + for table in json.loads(self.prefs.GetString(self.PreferenceMainLibraryJSON, "")): + + tt = self.tooltableFromAttrs(table) + if tt: + self.toolTables.append(tt) + else: + PathLog.error(translate('PathToolLibraryManager', "Unsupported Path tooltable")) + + def saveMainLibrary(self): '''Persists the permanent library to FreeCAD user preferences''' - tmpstring = json.dumps(self.templateAttrs(tooltable)) + tmpstring = json.dumps(self.templateAttrs()) self.prefs.SetString(self.PreferenceMainLibraryJSON, tmpstring) + self.loadToolTables() return True def getLists(self): '''Builds the list of all Tool Table lists''' - tablelist = [] - toollist = "
" - tablelist.append(toollist) - + tablelist = self.toolTables.copy() + #TODO load a tool table for current job? # Get ToolTables from any open CNC jobs - for o in FreeCAD.ActiveDocument.Objects: - if hasattr(o, "Proxy"): - if isinstance(o.Proxy, PathScripts.PathJob.ObjectJob): - tablelist.append(o.Label) + # for o in FreeCAD.ActiveDocument.Objects: + # if hasattr(o, "Proxy"): + # if isinstance(o.Proxy, PathScripts.PathJob.ObjectJob): + # tablelist.append(o.Label) return tablelist - def _findList(self, listname): - tt = None - if listname == "
": - tmpstring = self.prefs.GetString(self.PreferenceMainLibraryJSON, "") - if not tmpstring: - tmpstring = self.prefs.GetString(self.PreferenceMainLibraryXML, "") - if tmpstring: - if tmpstring[0] == '{': - tt = self.tooltableFromAttrs(json.loads(tmpstring)) - elif tmpstring[0] == '<': - # legacy XML table - Handler = FreeCADTooltableHandler() - xml.sax.parseString(tmpstring, Handler) - tt = Handler.tooltable - # store new format - self.saveMainLibrary(tt) - else: - tt = Path.Tooltable() - else: - for o in FreeCAD.ActiveDocument.Objects: - if o.Label == listname: - tt = o.Tooltable - return tt + # def _findList(self, listname): + # tt = None + # if listname == self.getCurrentTableName(): + # #print("Findlist - ListName:", listname) + # return self.getCurrentTable() + # else: + # tmpstring = self.prefs.GetString(self.PreferenceMainLibraryJSON, "") + # if not tmpstring: + # tmpstring = self.prefs.GetString(self.PreferenceMainLibraryXML, "") + # if tmpstring: + # if tmpstring[0] == '{': + # tt = self.tooltableFromAttrs(json.loads(tmpstring)) + # elif tmpstring[0] == '<': + # # legacy XML table + # Handler = FreeCADTooltableHandler() + # xml.sax.parseString(tmpstring, Handler) + # tt = Handler.tooltable + # # store new format + # self.saveMainLibrary() + # else: + # tt = Path.Tooltable() + # # else: + # # for o in FreeCAD.ActiveDocument.Objects: + # # if o.Label == listname: + # # tt = o.Tooltable + # return tt def getTool(self, listname, toolnum): - tt = self._findList(listname) + ''' gets the tool object ''' + tt = self.getTableFromName(listname) return tt.getTool(toolnum) def getTools(self, tablename): '''returns the tool data for a given table''' tooldata = [] - tt = self._findList(tablename) + tableExists = any(table.Name == tablename for table in self.toolTables) + if tableExists: + self.currentTableName = tablename + else: + return None + + tt = self.getTableFromName(tablename) headers = ["","Tool Num.","Name","Tool Type","Material","Diameter","Length Offset","Flat Radius","Corner Radius","Cutting Edge Angle","Cutting Edge Height"] model = QtGui.QStandardItemModel() model.setHorizontalHeaderLabels(headers) @@ -247,11 +368,11 @@ def unitconv(ivalue): itemDiameter = QtGui.QStandardItem(unitconv(t.Diameter)) itemLengthOffset = QtGui.QStandardItem(unitconv(t.LengthOffset)) itemFlatRadius = QtGui.QStandardItem(unitconv(t.FlatRadius)) - itmCornerRadius = QtGui.QStandardItem(unitconv(t.CornerRadius)) + itemCornerRadius = QtGui.QStandardItem(unitconv(t.CornerRadius)) itemCuttingEdgeAngle = QtGui.QStandardItem(str(t.CuttingEdgeAngle)) itemCuttingEdgeHeight = QtGui.QStandardItem(unitconv(t.CuttingEdgeHeight)) - row = [itemcheck, itemNumber, itemName, itemToolType, itemMaterial, itemDiameter, itemLengthOffset, itemFlatRadius, itmCornerRadius, itemCuttingEdgeAngle, itemCuttingEdgeHeight] + row = [itemcheck, itemNumber, itemName, itemToolType, itemMaterial, itemDiameter, itemLengthOffset, itemFlatRadius, itemCornerRadius, itemCuttingEdgeAngle, itemCuttingEdgeHeight] model.appendRow(row) return model @@ -281,12 +402,12 @@ def read(self, filename, listname): with open(PathUtil.toUnicode(filename[0]), "rb") as fp: ht = self.tooltableFromAttrs(json.load(fp)) - tt = self._findList(listname) + tt = self.getTableFromName(listname) for t in ht.Tools: newt = ht.getTool(t).copy() tt.addTools(newt) - if listname == "
": - self.saveMainLibrary(tt) + if listname == self.getCurrentTableName(): + self.saveMainLibrary() return True except Exception as e: # pylint: disable=broad-except print("could not parse file", e) @@ -294,7 +415,7 @@ def read(self, filename, listname): def write(self, filename, listname): "exports the tooltable to a file" - tt = self._findList(listname) + tt = self.getTableFromName(listname) if tt: try: def openFileWithExtension(name, ext): @@ -314,7 +435,7 @@ def openFileWithExtension(name, ext): fp.write("T{0} P{0} Y{1} Z{2} A{3} B{4} C{5} U{6} V{7} W{8} D{9} I{10} J{11} Q{12} ;{13}\n".format(key,0,t.LengthOffset,0,0,0,0,0,0,t.Diameter,0,0,0,t.Name)) else: fp,fname = openFileWithExtension(filename[0], '.json') - json.dump(self.templateAttrs(tt), fp, sort_keys=True, indent=2) + json.dump(self.templateAttrs(), fp, sort_keys=True, indent=2) fp.close() print("Written ", PathUtil.toUnicode(fname)) @@ -324,8 +445,7 @@ def openFileWithExtension(name, ext): def addnew(self, listname, tool, position = None): "adds a new tool at the end of the table" - print(listname, tool, position) - tt = self._findList(listname) + tt = self.getTableFromName(listname) if not tt: tt = Path.Tooltable() if position is None: @@ -335,26 +455,26 @@ def addnew(self, listname, tool, position = None): tt.setTool(position, tool) newID = position - if listname == "
": - return self.saveMainLibrary(tt) + if listname == self.getCurrentTableName(): + self.saveMainLibrary() return newID def updateTool(self, listname, toolnum, tool): '''updates tool data''' - tt = self._findList(listname) + tt = self.getTableFromName(listname) tt.deleteTool(toolnum) tt.setTool(toolnum, tool) - if listname == "
": - return self.saveMainLibrary(tt) + if listname == self.getCurrentTableName(): + return self.saveMainLibrary() return True def moveup(self, number, listname): "moves a tool to a lower number, if possible" + target = number - 1 if number < 2: - return False + return False, target target = number - 1 - tt = self._findList(listname) - + tt = self.getTableFromName(listname) t1 = tt.getTool(number).copy() tt.deleteTool(number) if target in tt.Tools.keys(): @@ -362,13 +482,13 @@ def moveup(self, number, listname): tt.deleteTool(target) tt.setTool(number, t2) tt.setTool(target, t1) - if listname == "
": - self.saveMainLibrary(tt) - return True + if listname == self.getCurrentTableName(): + self.saveMainLibrary() + return True, target def movedown(self, number, listname): "moves a tool to a higher number, if possible" - tt = self._findList(listname) + tt = self.getTableFromName(listname) target = number + 1 t1 = tt.getTool(number).copy() tt.deleteTool(number) @@ -377,16 +497,16 @@ def movedown(self, number, listname): tt.deleteTool(target) tt.setTool(number, t2) tt.setTool(target, t1) - if listname == "
": - self.saveMainLibrary(tt) - return True + if listname == self.getCurrentTableName(): + self.saveMainLibrary() + return True, target def delete(self, number, listname): '''deletes a tool from the current list''' - tt = self._findList(listname) + tt = self.getTableFromName(listname) tt.deleteTool(number) - if listname == "
": - self.saveMainLibrary(tt) + if listname == self.getCurrentTableName(): + self.saveMainLibrary() return True @@ -395,9 +515,12 @@ class EditorPanel(): def __init__(self, job, cb): self.form = FreeCADGui.PySideUic.loadUi(":/panels/ToolLibraryEditor.ui") self.TLM = ToolLibraryManager() + listname = self.TLM.getCurrentTableName() + + if listname: + self.loadToolTables() + #self.loadTable(listname) - self.loadTable() - self.form.ToolsList.resizeColumnsToContents() self.job = job self.cb = cb @@ -417,6 +540,12 @@ def reject(self): def getFields(self): pass + def setFields(self): + pass + + def open(self): + pass + def getType(self, tooltype): "gets a combobox index number for a given type or viceversa" toolslist = Path.Tool.getToolTypes(Path.Tool()) @@ -429,7 +558,7 @@ def getType(self, tooltype): return toolslist[tooltype] def getMaterial(self, material): - "gets a combobox index number for a given material or viceversa" + '''gets a combobox index number for a given material or viceversa''' matslist = Path.Tool.getToolMaterials(Path.Tool()) if isinstance(material, str): if material in matslist: @@ -440,65 +569,34 @@ def getMaterial(self, material): return matslist[material] def addTool(self): + '''adds new tool to the current tool table''' tool = Path.Tool() editor = self.toolEditor(tool) r = editor.Parent.exec_() if r: editor.accept() - listname = "
" - if self.TLM.addnew(listname, editor.Tool) is True: - self.loadTable() - - def setFields(self): - pass - - def open(self): - pass - - def loadTable(self): - #tooldata = self.TLM.getTools(curr.data()) - tooldata = self.TLM.getTools("
") - self.form.ToolsList.setModel(tooldata) - - def moveUp(self): - "moves a tool to a lower number, if possible" - item = self.form.ToolsList.selectedIndexes()[1].data() - if item: - number = int(item) - listname = "
" - #listname = self.form.listView.selectedIndexes()[0].data() - if self.TLM.moveup(number, listname) is True: - self.loadTable() - - def moveDown(self): - "moves a tool to a higher number, if possible" - item = self.form.ToolsList.selectedIndexes()[1].data() - if item: - number = int(item) - listname = "
" - #listname = self.form.listView.selectedIndexes()[0].data() - if self.TLM.movedown(number, listname) is True: - self.loadTable() + listname = self.TLM.getCurrentTableName() + self.TLM.addnew(listname, editor.Tool) # is True: + self.loadTable(listname) def delete(self): - '''deletes a tool''' + '''deletes the selected tool''' #listname = self.form.listView.selectedIndexes()[0].data() - listname = "
" + listname = self.TLM.getCurrentTableName() model = self.form.ToolsList.model() for i in range(model.rowCount()): item = model.item(i, 0) if item.checkState(): t = model.index(i, 1) self.TLM.delete(int(t.data()) ,listname) - self.loadTable() + self.loadTable(listname) def editTool(self, currItem): - + '''load the tool edit dialog''' row = currItem.row() value = currItem.sibling(row, 1).data() - #listname = self.form.listView.selectedIndexes()[0].data() - listname = "
" + listname = self.TLM.getCurrentTableName() toolnum = int(value) tool = self.TLM.getTool(listname, toolnum) editor = self.toolEditor(tool) @@ -507,38 +605,88 @@ def editTool(self, currItem): if r: editor.accept() if self.TLM.updateTool(listname, toolnum, editor.Tool) is True: - self.loadTable() + self.loadTable(listname) + + def moveUp(self): + '''moves a tool to a lower number, if possible''' + item = self.form.ToolsList.selectedIndexes()[1].data() + if item: + number = int(item) + listname = self.TLM.getCurrentTableName() + success, newNum = self.TLM.moveup(number, listname) + if success: + self.loadTable(listname) + self.updateSelection(newNum) + + def moveDown(self): + '''moves a tool to a higher number, if possible''' + item = self.form.ToolsList.selectedIndexes()[1].data() + if item: + number = int(item) + listname = self.TLM.getCurrentTableName() + success, newNum = self.TLM.movedown(number, listname) + if success: + self.loadTable(listname) + self.updateSelection(newNum) + + def updateSelection(self, number): + '''update the tool list selection to track moves''' + model = self.form.ToolsList.model() + for i in range(model.rowCount()): + if int(model.index(i, 1).data()) == number: + self.form.ToolsList.selectRow(i) + self.form.ToolsList.model().item(i, 0).setCheckState(QtCore.Qt.Checked) + return + def importFile(self): - "imports a tooltable from a file" + '''imports a tooltable from a file''' filename = QtGui.QFileDialog.getOpenFileName(self.form, translate( "TooltableEditor", "Open tooltable", None), None, "{};;{};;{}".format(ToolLibraryManager.TooltableTypeJSON, ToolLibraryManager.TooltableTypeXML, ToolLibraryManager.TooltableTypeHeekscad)) if filename[0]: - listname = '
' + listname = self.TLM.getNextToolTableName() if self.TLM.read(filename, listname): - self.loadTable() + self.loadTable(listname) def exportFile(self): - "export a tooltable to a file" + '''export a tooltable to a file''' filename = QtGui.QFileDialog.getSaveFileName(self.form, translate("TooltableEditor", "Save tooltable", None), None, "{};;{};;{}".format(ToolLibraryManager.TooltableTypeJSON, ToolLibraryManager.TooltableTypeXML, ToolLibraryManager.TooltableTypeLinuxCNC)) - if filename[0]: - #listname = self.form.listView.selectedIndexes()[0].data() - listname = '
' + listname = self.TLM.getCurrentTableName() self.TLM.write(filename, listname) - def checkCopy(self): + def toolSelected(self, index): + ''' updates the ui when tools are selected''' + self.form.ToolsList.selectRow(index.row()) + self.form.btnCopyTools.setEnabled(False) + self.form.ButtonDelete.setEnabled(False) + self.form.ButtonUp.setEnabled(False) + self.form.ButtonDown.setEnabled(False) + model = self.form.ToolsList.model() + checkCount = 0 + checkList = [] for i in range(model.rowCount()): item = model.item(i, 0) if item.checkState(): + checkCount += 1 + checkList.append(i) self.form.btnCopyTools.setEnabled(True) + # only allow moving or deleting a single tool at a time. + if checkCount == 1: + #make sure the row is highlighted when the check box gets ticked + self.form.ToolsList.selectRow(checkList[0]) + self.form.ButtonDelete.setEnabled(True) + self.form.ButtonUp.setEnabled(True) + self.form.ButtonDown.setEnabled(True) + if len(PathUtils.GetJobs()) == 0: self.form.btnCopyTools.setEnabled(False) def copyTools(self): + ''' copy selected tool ''' tools = [] model = self.form.ToolsList.model() for i in range(model.rowCount()): @@ -550,7 +698,7 @@ def copyTools(self): return targets = self.TLM.getLists() - currList = "
" + currList = self.TLM.getCurrentTableName() for target in targets: if target == currList: @@ -587,9 +735,78 @@ def copyTools(self): self.cb() FreeCAD.ActiveDocument.recompute() + def tableSelected(self, index): + ''' loads the tools for the selected tool table ''' + name = self.form.TableList.itemFromIndex(index).text() + self.loadTable(name) + + def loadTable(self, name): + ''' loads the tools for the selected tool table ''' + tooldata = self.TLM.getTools(name) + self.form.ToolsList.setModel(tooldata) + self.form.ToolsList.resizeColumnsToContents() + self.setCurrentToolTableByName(name) + + def addNewToolTable(self): + ''' adds new tool to selected tool table ''' + name = self.TLM.addNewToolTable() + self.loadToolTables() + self.loadTable(name) + + def loadToolTables(self): + ''' Load list of available tool tables ''' + self.form.TableList.clear() + for table in self.TLM.getLists(): + listItem = QtGui.QListWidgetItem(table.Name) + listItem.setIcon(QtGui.QIcon(':/icons/Path-ToolTable.svg')) + listItem.setFlags(listItem.flags() | QtCore.Qt.ItemIsEditable) + listItem.setSizeHint(QtCore.QSize(0,40)) + self.form.TableList.addItem(listItem) + self.loadTable(self.TLM.toolTables[0].Name) + + def setCurrentToolTableByName(self, name): + ''' get the current tool table ''' + item = self.form.TableList.findItems(name, QtCore.Qt.MatchExactly)[0] + self.form.TableList.setCurrentItem(item) + + def removeToolTable(self): + ''' delete the selected tool table ''' + self.TLM.deleteToolTable() + self.loadToolTables() + + def initTableRename(self): + ''' update the tool table list entry to allow renaming ''' + name = self.TLM.getCurrentTableName() + item = self.form.TableList.findItems(name, QtCore.Qt.MatchExactly)[0] + self.form.TableList.editItem(item) + + def renameTable(self, listItem): + ''' rename the selected too table ''' + newName = listItem.text() + index = self.form.TableList.indexFromItem(listItem).row() + reloadTables = self.TLM.renameToolTable(newName, index) + if reloadTables: + self.loadToolTables() + def getStandardButtons(self): return int(QtGui.QDialogButtonBox.Ok) + # def openMenu(self, position): + # menu = QtGui.QMenu() + # newAction = menu.addAction("New Tool Table") + # deleteAction = menu.addAction("Delete") + # renameAction = menu.addAction("Rename") + # action = menu.exec_(self.form.TableList.mapToGlobal(position)) + # if action == newAction: + # self.addNewToolTable() + # pass + # if action == deleteAction: + # self.removeToolTable() + # pass + # if action == renameAction: + # self.initTableRename() + # pass + def setupUi(self): # Connect Signals and Slots self.form.ButtonNewTool.clicked.connect(self.addTool) @@ -598,11 +815,29 @@ def setupUi(self): self.form.ButtonDown.clicked.connect(self.moveDown) self.form.ButtonUp.clicked.connect(self.moveUp) self.form.ButtonDelete.clicked.connect(self.delete) + self.form.ToolsList.doubleClicked.connect(self.editTool) - self.form.ToolsList.clicked.connect(self.checkCopy) + self.form.ToolsList.clicked.connect(self.toolSelected) + self.form.btnCopyTools.clicked.connect(self.copyTools) + self.form.TableList.clicked.connect(self.tableSelected) + self.form.TableList.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) + #self.form.TableList.customContextMenuRequested.connect(self.openMenu) + self.form.TableList.itemChanged.connect(self.renameTable) + + self.form.ButtonAddToolTable.clicked.connect(self.addNewToolTable) + self.form.ButtonAddToolTable.setToolTip(translate("TooltableEditor","Add New Tool Table")) + self.form.ButtonRemoveToolTable.clicked.connect(self.removeToolTable) + self.form.ButtonRemoveToolTable.setToolTip(translate("TooltableEditor","Delete Selected Tool Table")) + self.form.ButtonRenameToolTable.clicked.connect(self.initTableRename) + self.form.ButtonRenameToolTable.setToolTip(translate("TooltableEditor","Rename Selected Tool Table")) + + self.form.btnCopyTools.setEnabled(False) + self.form.ButtonDelete.setEnabled(False) + self.form.ButtonUp.setEnabled(False) + self.form.ButtonDown.setEnabled(False) self.setFields() From 3aec5ca8b829af5f0ccee7d89f1e55a583e18ed9 Mon Sep 17 00:00:00 2001 From: Dubstar_04 Date: Sat, 24 Aug 2019 19:16:31 +0100 Subject: [PATCH 4/9] Make sure the tool list get cleared Ensure the tool list gets clear when all tooltables are deleted. --- .../PathScripts/PathToolLibraryManager.py | 26 ++++++++++++------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/src/Mod/Path/PathScripts/PathToolLibraryManager.py b/src/Mod/Path/PathScripts/PathToolLibraryManager.py index afeec843183b..938450e8fdbb 100644 --- a/src/Mod/Path/PathScripts/PathToolLibraryManager.py +++ b/src/Mod/Path/PathScripts/PathToolLibraryManager.py @@ -743,9 +743,11 @@ def tableSelected(self, index): def loadTable(self, name): ''' loads the tools for the selected tool table ''' tooldata = self.TLM.getTools(name) - self.form.ToolsList.setModel(tooldata) - self.form.ToolsList.resizeColumnsToContents() - self.setCurrentToolTableByName(name) + if tooldata: + self.form.ToolsList.setModel(tooldata) + self.form.ToolsList.resizeColumnsToContents() + self.setCurrentToolTableByName(name) + def addNewToolTable(self): ''' adds new tool to selected tool table ''' @@ -756,13 +758,17 @@ def addNewToolTable(self): def loadToolTables(self): ''' Load list of available tool tables ''' self.form.TableList.clear() - for table in self.TLM.getLists(): - listItem = QtGui.QListWidgetItem(table.Name) - listItem.setIcon(QtGui.QIcon(':/icons/Path-ToolTable.svg')) - listItem.setFlags(listItem.flags() | QtCore.Qt.ItemIsEditable) - listItem.setSizeHint(QtCore.QSize(0,40)) - self.form.TableList.addItem(listItem) - self.loadTable(self.TLM.toolTables[0].Name) + model = self.form.ToolsList.model() + if model: + model.clear() + if len(self.TLM.toolTables) > 0: + for table in self.TLM.getLists(): + listItem = QtGui.QListWidgetItem(table.Name) + listItem.setIcon(QtGui.QIcon(':/icons/Path-ToolTable.svg')) + listItem.setFlags(listItem.flags() | QtCore.Qt.ItemIsEditable) + listItem.setSizeHint(QtCore.QSize(0,40)) + self.form.TableList.addItem(listItem) + self.loadTable(self.TLM.toolTables[0].Name) def setCurrentToolTableByName(self, name): ''' get the current tool table ''' From 9a5766e45106822d2920ccca3f7d9d353a41fbf4 Mon Sep 17 00:00:00 2001 From: Dubstar_04 Date: Sat, 24 Aug 2019 21:52:30 +0100 Subject: [PATCH 5/9] Check there is preference data before reading it --- .../Path/PathScripts/PathToolLibraryManager.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/Mod/Path/PathScripts/PathToolLibraryManager.py b/src/Mod/Path/PathScripts/PathToolLibraryManager.py index 938450e8fdbb..94e5b76d4832 100644 --- a/src/Mod/Path/PathScripts/PathToolLibraryManager.py +++ b/src/Mod/Path/PathScripts/PathToolLibraryManager.py @@ -146,6 +146,7 @@ class ToolLibraryManager(): ''' #TODO: copy & Duplicate tools between lists + #TODO: update version number and handle upgrading TooltableTypeJSON = translate("TooltableEditor", "Tooltable JSON (*.json)") TooltableTypeXML = translate("TooltableEditor", "Tooltable XML (*.xml)") @@ -273,17 +274,19 @@ def tooltableFromAttrs(self, stringattrs): return None def loadToolTables(self): - ''' loads the tool tables from tehe stored data ''' + ''' loads the tool tables from the stored data ''' self.toolTables = [] self.currentTableName = '' - for table in json.loads(self.prefs.GetString(self.PreferenceMainLibraryJSON, "")): + prefsData = self.prefs.GetString(self.PreferenceMainLibraryJSON, "") + if prefsData: + for table in json.loads(prefsData): - tt = self.tooltableFromAttrs(table) - if tt: - self.toolTables.append(tt) - else: - PathLog.error(translate('PathToolLibraryManager', "Unsupported Path tooltable")) + tt = self.tooltableFromAttrs(table) + if tt: + self.toolTables.append(tt) + else: + PathLog.error(translate('PathToolLibraryManager', "Unsupported Path tooltable")) def saveMainLibrary(self): '''Persists the permanent library to FreeCAD user preferences''' From 8faf893f9854515e3ac99410195a4633a4f4067e Mon Sep 17 00:00:00 2001 From: Daniel Wood Date: Mon, 26 Aug 2019 20:19:12 +0100 Subject: [PATCH 6/9] Import and opening current tool tables Handle opening and importing current (pre-0.19) tool tables. --- .../PathScripts/PathToolLibraryManager.py | 80 +++++++++++++------ 1 file changed, 56 insertions(+), 24 deletions(-) diff --git a/src/Mod/Path/PathScripts/PathToolLibraryManager.py b/src/Mod/Path/PathScripts/PathToolLibraryManager.py index 94e5b76d4832..cf3dbbc777d9 100644 --- a/src/Mod/Path/PathScripts/PathToolLibraryManager.py +++ b/src/Mod/Path/PathScripts/PathToolLibraryManager.py @@ -146,7 +146,6 @@ class ToolLibraryManager(): ''' #TODO: copy & Duplicate tools between lists - #TODO: update version number and handle upgrading TooltableTypeJSON = translate("TooltableEditor", "Tooltable JSON (*.json)") TooltableTypeXML = translate("TooltableEditor", "Tooltable XML (*.xml)") @@ -181,18 +180,18 @@ def getTableFromName(self, name): if table.Name == name: return table - def getNextToolTableName(self): + def getNextToolTableName(self, tableName='Tool Table'): ''' get a unique name for a new tool table ''' iter = 1 - tableNames = [] + tempName = tableName[-2:] - for table in self.toolTables: - tableNames.append(table.Name) - - while "ToolTable-" + str(iter) in tableNames: + if tempName[0] == '-' and tempName[-1].isdigit(): + tableName = tableName[:-2] + + while any(table.Name == tableName + '-' + str(iter) for table in self.toolTables): iter += 1 - return "ToolTable-" + str(iter) + return tableName + '-' + str(iter) def addNewToolTable(self): ''' creates a new tool table ''' @@ -248,13 +247,16 @@ def tooltableFromAttrs(self, stringattrs): tt = Path.Tooltable() tt.Version = 1 + tt.Name = self.getNextToolTableName() if stringattrs.get('Version'): tt.Version = stringattrs.get('Version') if stringattrs.get('TableName'): tt.Name = stringattrs.get('TableName') - + if any(table.Name == tt.Name for table in self.toolTables): + tt.Name = self.getNextToolTableName(tt.Name) + for key, attrs in PathUtil.keyValueIter(stringattrs['Tools']): tool = Path.Tool() tool.Name = str(attrs["name"]) @@ -278,15 +280,22 @@ def loadToolTables(self): self.toolTables = [] self.currentTableName = '' - prefsData = self.prefs.GetString(self.PreferenceMainLibraryJSON, "") - if prefsData: - for table in json.loads(prefsData): + def addTable(tt): + if tt: + self.toolTables.append(tt) + else: + PathLog.error(translate('PathToolLibraryManager', "Unsupported Path tooltable")) + + prefsData = json.loads(self.prefs.GetString(self.PreferenceMainLibraryJSON, "")) + + if isinstance(prefsData, dict): + tt = self.tooltableFromAttrs(prefsData) + addTable(tt) + if isinstance(prefsData, list): + for table in prefsData: tt = self.tooltableFromAttrs(table) - if tt: - self.toolTables.append(tt) - else: - PathLog.error(translate('PathToolLibraryManager', "Unsupported Path tooltable")) + addTable(tt) def saveMainLibrary(self): '''Persists the permanent library to FreeCAD user preferences''' @@ -384,6 +393,8 @@ def unitconv(ivalue): def read(self, filename, listname): "imports a tooltable from a file" + importedTables = [] + try: fileExtension = os.path.splitext(filename[0])[1].lower() xmlHandler = None @@ -403,15 +414,35 @@ def read(self, filename, listname): ht = xmlHandler.tooltable else: with open(PathUtil.toUnicode(filename[0]), "rb") as fp: - ht = self.tooltableFromAttrs(json.load(fp)) + tableData = json.load(fp) + + if isinstance(tableData, dict): + ht = self.tooltableFromAttrs(tableData) + if ht: + importedTables.append(ht) + + if isinstance(tableData, list): + for table in tableData: + ht = self.tooltableFromAttrs(table) + if ht: + importedTables.append(ht) - tt = self.getTableFromName(listname) - for t in ht.Tools: - newt = ht.getTool(t).copy() - tt.addTools(newt) - if listname == self.getCurrentTableName(): + if importedTables: + for tt in importedTables: + self.toolTables.append(tt) + self.saveMainLibrary() - return True + return True + else: + return False + + # tt = self.getTableFromName(listname) + # for t in ht.Tools: + # newt = ht.getTool(t).copy() + # tt.addTools(newt) + # if listname == self.getCurrentTableName(): + # self.saveMainLibrary() + # return True except Exception as e: # pylint: disable=broad-except print("could not parse file", e) @@ -648,7 +679,8 @@ def importFile(self): if filename[0]: listname = self.TLM.getNextToolTableName() if self.TLM.read(filename, listname): - self.loadTable(listname) + self.loadToolTables() + #self.loadTable(listname) def exportFile(self): From 990db1a3166a65af556351818aff13007e894d30 Mon Sep 17 00:00:00 2001 From: Daniel Wood Date: Mon, 26 Aug 2019 21:24:44 +0100 Subject: [PATCH 7/9] Return document jobs for copy commands Return the document jobs when creating tool controllers. --- .../PathScripts/PathToolLibraryManager.py | 58 ++++++------------- 1 file changed, 17 insertions(+), 41 deletions(-) diff --git a/src/Mod/Path/PathScripts/PathToolLibraryManager.py b/src/Mod/Path/PathScripts/PathToolLibraryManager.py index cf3dbbc777d9..817c0b515280 100644 --- a/src/Mod/Path/PathScripts/PathToolLibraryManager.py +++ b/src/Mod/Path/PathScripts/PathToolLibraryManager.py @@ -166,6 +166,9 @@ def __init__(self): return + def getToolTables(self): + return self.toolTables + def getCurrentTableName(self): ''' return the name of the currently loaded tool table ''' return self.currentTableName @@ -285,7 +288,7 @@ def addTable(tt): self.toolTables.append(tt) else: PathLog.error(translate('PathToolLibraryManager', "Unsupported Path tooltable")) - + prefsData = json.loads(self.prefs.GetString(self.PreferenceMainLibraryJSON, "")) if isinstance(prefsData, dict): @@ -304,43 +307,16 @@ def saveMainLibrary(self): self.loadToolTables() return True - def getLists(self): + def getJobList(self): '''Builds the list of all Tool Table lists''' - tablelist = self.toolTables.copy() - #TODO load a tool table for current job? - # Get ToolTables from any open CNC jobs - # for o in FreeCAD.ActiveDocument.Objects: - # if hasattr(o, "Proxy"): - # if isinstance(o.Proxy, PathScripts.PathJob.ObjectJob): - # tablelist.append(o.Label) - return tablelist + tablelist = [] - # def _findList(self, listname): - # tt = None - # if listname == self.getCurrentTableName(): - # #print("Findlist - ListName:", listname) - # return self.getCurrentTable() - # else: - # tmpstring = self.prefs.GetString(self.PreferenceMainLibraryJSON, "") - # if not tmpstring: - # tmpstring = self.prefs.GetString(self.PreferenceMainLibraryXML, "") - # if tmpstring: - # if tmpstring[0] == '{': - # tt = self.tooltableFromAttrs(json.loads(tmpstring)) - # elif tmpstring[0] == '<': - # # legacy XML table - # Handler = FreeCADTooltableHandler() - # xml.sax.parseString(tmpstring, Handler) - # tt = Handler.tooltable - # # store new format - # self.saveMainLibrary() - # else: - # tt = Path.Tooltable() - # # else: - # # for o in FreeCAD.ActiveDocument.Objects: - # # if o.Label == listname: - # # tt = o.Tooltable - # return tt + for o in FreeCAD.ActiveDocument.Objects: + if hasattr(o, "Proxy"): + if isinstance(o.Proxy, PathScripts.PathJob.ObjectJob): + tablelist.append(o.Label) + + return tablelist def getTool(self, listname, toolnum): ''' gets the tool object ''' @@ -732,7 +708,7 @@ def copyTools(self): if len(tools) == 0: return - targets = self.TLM.getLists() + targets = self.TLM.getJobList() currList = self.TLM.getCurrentTableName() for target in targets: @@ -740,7 +716,7 @@ def copyTools(self): targets.remove(target) if len(targets) == 0: - FreeCAD.Console.PrintWarning("no place to go") + FreeCAD.Console.PrintWarning("No Path Jobs in current document") return elif len(targets) == 1: targetlist = targets[0] @@ -796,14 +772,14 @@ def loadToolTables(self): model = self.form.ToolsList.model() if model: model.clear() - if len(self.TLM.toolTables) > 0: - for table in self.TLM.getLists(): + if len(self.TLM.getToolTables()) > 0: + for table in self.TLM.getToolTables(): listItem = QtGui.QListWidgetItem(table.Name) listItem.setIcon(QtGui.QIcon(':/icons/Path-ToolTable.svg')) listItem.setFlags(listItem.flags() | QtCore.Qt.ItemIsEditable) listItem.setSizeHint(QtCore.QSize(0,40)) self.form.TableList.addItem(listItem) - self.loadTable(self.TLM.toolTables[0].Name) + self.loadTable(self.TLM.getToolTables()[0].Name) def setCurrentToolTableByName(self, name): ''' get the current tool table ''' From 27d3b57b7b04db7d35e61183ad53f7f7815ac17e Mon Sep 17 00:00:00 2001 From: Daniel Wood Date: Mon, 26 Aug 2019 21:27:06 +0100 Subject: [PATCH 8/9] clean up unused code --- src/Mod/Path/PathScripts/PathToolLibraryManager.py | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/Mod/Path/PathScripts/PathToolLibraryManager.py b/src/Mod/Path/PathScripts/PathToolLibraryManager.py index 817c0b515280..a34f26724409 100644 --- a/src/Mod/Path/PathScripts/PathToolLibraryManager.py +++ b/src/Mod/Path/PathScripts/PathToolLibraryManager.py @@ -167,6 +167,7 @@ def __init__(self): return def getToolTables(self): + ''' Return tool table list ''' return self.toolTables def getCurrentTableName(self): @@ -412,13 +413,6 @@ def read(self, filename, listname): else: return False - # tt = self.getTableFromName(listname) - # for t in ht.Tools: - # newt = ht.getTool(t).copy() - # tt.addTools(newt) - # if listname == self.getCurrentTableName(): - # self.saveMainLibrary() - # return True except Exception as e: # pylint: disable=broad-except print("could not parse file", e) @@ -529,7 +523,6 @@ def __init__(self, job, cb): if listname: self.loadToolTables() - #self.loadTable(listname) self.job = job self.cb = cb From a6a7e045ab5d6831ab6989722f2eab094b709aa2 Mon Sep 17 00:00:00 2001 From: Daniel Wood Date: Tue, 27 Aug 2019 07:15:23 +0100 Subject: [PATCH 9/9] Remove unused function definition --- src/Mod/Path/App/Tooltable.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Mod/Path/App/Tooltable.h b/src/Mod/Path/App/Tooltable.h index 77112398f520..873b943afda1 100644 --- a/src/Mod/Path/App/Tooltable.h +++ b/src/Mod/Path/App/Tooltable.h @@ -50,7 +50,6 @@ namespace Path void addTool(const Tool &tool); // adds a tool at the end void setTool(const Tool &tool, int); // inserts a tool void deleteTool(int); // deletes a tool - //void setVersion(int); //set the table version // auto unsigned int getSize(void) const {return Tools.size();}