From 1764ac614dd8b3fb820dbf6159e8ba7f2e839885 Mon Sep 17 00:00:00 2001 From: David Carter Date: Mon, 23 Oct 2023 15:19:20 -0400 Subject: [PATCH 1/6] Material: Material editor enhancements Continues the work of the material subsystem improvements. This merge covers the continued development of the material editor. The primary improvements are in the handling of 2D and 3D array properties. These properties are now fully editable, and can be saved and restored. The cards now separate the author and license. These were previously saved as a single item. Future support will be provided for standard open source licenses. Saving operations validate the cards to ensure UUIDs of materials are considered. Warnings are given when a save could potentially impact the models, such as saving over a material instead of creating a new instance. The editor is still not complete. There are a number of functional elements, such as drag/drop operations, folder creation, and deletion operations that need to be added to the main tree. State needs to be saved and restored to improve the user experience. The appearance preview also needs significant work. This will be handled in a future PR. --- src/Mod/Fem/Gui/AppFemGui.cpp | 2 +- src/Mod/Fem/Gui/CMakeLists.txt | 6 + src/Mod/Material/App/AppMaterial.cpp | 2 + src/Mod/Material/App/Array2DPy.xml | 36 + src/Mod/Material/App/Array2DPyImpl.cpp | 85 ++ src/Mod/Material/App/CMakeLists.txt | 7 + src/Mod/Material/App/Exceptions.h | 106 +++ src/Mod/Material/App/FolderTree.h | 16 +- src/Mod/Material/App/MaterialConfigLoader.cpp | 62 +- src/Mod/Material/App/MaterialConfigLoader.h | 31 +- src/Mod/Material/App/MaterialLibrary.cpp | 286 ++++++- src/Mod/Material/App/MaterialLibrary.h | 67 +- src/Mod/Material/App/MaterialLoader.cpp | 313 ++++++-- src/Mod/Material/App/MaterialLoader.h | 62 +- src/Mod/Material/App/MaterialManager.cpp | 208 +++-- src/Mod/Material/App/MaterialManager.h | 73 +- .../Material/App/MaterialManagerPyImpl.cpp | 26 +- src/Mod/Material/App/MaterialPy.xml | 14 +- src/Mod/Material/App/MaterialPyImpl.cpp | 78 +- src/Mod/Material/App/MaterialValue.cpp | 564 ++++++++++++-- src/Mod/Material/App/MaterialValue.h | 177 +++-- src/Mod/Material/App/Materials.cpp | 729 +++++++++++++++--- src/Mod/Material/App/Materials.h | 183 +++-- src/Mod/Material/App/Model.cpp | 22 +- src/Mod/Material/App/Model.h | 81 +- src/Mod/Material/App/ModelLibrary.cpp | 83 +- src/Mod/Material/App/ModelLibrary.h | 43 +- src/Mod/Material/App/ModelLoader.cpp | 78 +- src/Mod/Material/App/ModelLoader.h | 45 +- src/Mod/Material/App/ModelManager.cpp | 107 ++- src/Mod/Material/App/ModelManager.h | 43 +- src/Mod/Material/App/ModelManagerPyImpl.cpp | 27 +- src/Mod/Material/App/ModelPropertyPyImpl.cpp | 4 - src/Mod/Material/App/ModelPyImpl.cpp | 26 +- src/Mod/Material/App/ModelUuids.cpp | 70 ++ src/Mod/Material/App/ModelUuids.h | 64 +- src/Mod/Material/App/PreCompiled.h | 4 - src/Mod/Material/App/UUIDsPy.xml | 116 +++ src/Mod/Material/App/UUIDsPyImpl.cpp | 139 ++++ src/Mod/Material/App/trim.h | 1 - src/Mod/Material/CMakeLists.txt | 23 +- src/Mod/Material/Gui/AppMatGui.cpp | 3 + src/Mod/Material/Gui/Array2D.cpp | 121 ++- src/Mod/Material/Gui/Array2D.h | 28 +- src/Mod/Material/Gui/Array3D.cpp | 259 ++++++- src/Mod/Material/Gui/Array3D.h | 32 +- src/Mod/Material/Gui/ArrayDelegate.cpp | 4 +- src/Mod/Material/Gui/ArrayDelegate.h | 11 +- src/Mod/Material/Gui/ArrayModel.cpp | 150 +++- src/Mod/Material/Gui/ArrayModel.h | 33 +- src/Mod/Material/Gui/DlgSettingsMaterial.h | 2 +- src/Mod/Material/Gui/MaterialDelegate.cpp | 16 +- src/Mod/Material/Gui/MaterialDelegate.h | 8 +- src/Mod/Material/Gui/MaterialSave.cpp | 394 +++++++++- src/Mod/Material/Gui/MaterialSave.h | 39 +- src/Mod/Material/Gui/MaterialSave.ui | 24 + src/Mod/Material/Gui/MaterialsEditor.cpp | 439 +++++++++-- src/Mod/Material/Gui/MaterialsEditor.h | 44 +- src/Mod/Material/Gui/MaterialsEditor.ui | 122 +-- src/Mod/Material/Gui/ModelSelect.cpp | 79 +- src/Mod/Material/Gui/ModelSelect.h | 24 +- src/Mod/Material/Gui/PreCompiled.h | 4 - src/Mod/Material/Gui/Workbench.cpp | 40 + src/Mod/Material/Gui/Workbench.h | 5 + .../Materials/Appearance/Aluminum.FCMat | 3 +- .../Materials/Appearance/Brass.FCMat | 3 +- .../Materials/Appearance/Bronze.FCMat | 3 +- .../Materials/Appearance/Chrome.FCMat | 3 +- .../Materials/Appearance/Copper.FCMat | 3 +- .../Appearance/DefaultAppearance.FCMat | 3 +- .../Materials/Appearance/Emerald.FCMat | 3 +- .../Resources/Materials/Appearance/Gold.FCMat | 3 +- .../Resources/Materials/Appearance/Jade.FCMat | 3 +- .../Materials/Appearance/Metalized.FCMat | 3 +- .../Materials/Appearance/NeonGNC.FCMat | 3 +- .../Materials/Appearance/NeonPHC.FCMat | 3 +- .../Materials/Appearance/Obsidian.FCMat | 3 +- .../Materials/Appearance/Pewter.FCMat | 3 +- .../Materials/Appearance/Plaster.FCMat | 3 +- .../Materials/Appearance/Plastic.FCMat | 3 +- .../Resources/Materials/Appearance/Ruby.FCMat | 3 +- .../Materials/Appearance/Satin.FCMat | 3 +- .../Materials/Appearance/ShinyPlastic.FCMat | 3 +- .../Materials/Appearance/Silver.FCMat | 3 +- .../Materials/Appearance/Steel.FCMat | 3 +- .../Materials/Appearance/Stone.FCMat | 3 +- .../Materials/FluidMaterial/Air.FCMat | 1 + .../Materials/FluidMaterial/Argon.FCMat | 1 + .../FluidMaterial/Carbon_dioxide.FCMat | 1 + .../Materials/FluidMaterial/Nitrogen.FCMat | 1 + .../Materials/FluidMaterial/None.FCMat | 1 + .../Materials/FluidMaterial/Water.FCMat | 1 + .../Aggregate/Concrete-EN-C35_45.FCMat | 3 +- .../Aggregate/Concrete-Generic.FCMat | 3 +- .../Aggregate/Reinforcement-FIB-B500.FCMat | 3 +- .../StandardMaterial/Carbon/Graphite.FCMat | 3 +- .../Glass/Glass-E-GlassFibre.FCMat | 3 +- .../Glass/Glass-Generic.FCMat | 3 +- .../Glass/Glass-S2-GlassFibre.FCMat | 3 +- .../Metal/Alloys/Invar-Generic.FCMat | 2 +- .../Metal/Aluminum/AlMg3F24.FCMat | 3 +- .../Metal/Aluminum/AlMgSi1F31.FCMat | 3 +- .../Metal/Aluminum/AlZn4-5Mg1F35.FCMat | 2 +- .../Metal/Aluminum/Aluminum-6061-T6.FCMat | 3 +- .../Metal/Aluminum/Aluminum-Generic.FCMat | 2 +- .../Metal/Copper/Copper-Generic.FCMat | 2 +- .../Metal/Iron/Iron-Generic.FCMat | 2 +- .../Metal/Steel/CalculiX-Steel.FCMat | 3 +- .../Metal/Steel/Steel-15CrNi6.FCMat | 3 +- .../Metal/Steel/Steel-17CrNiMo6.FCMat | 3 +- .../Metal/Steel/Steel-1C22.FCMat | 3 +- .../Metal/Steel/Steel-1C35.FCMat | 3 +- .../Metal/Steel/Steel-1C45.FCMat | 3 +- .../Metal/Steel/Steel-1C60.FCMat | 3 +- .../Metal/Steel/Steel-20NiCrMo2.FCMat | 3 +- .../Metal/Steel/Steel-28Mn6.FCMat | 3 +- .../Metal/Steel/Steel-2C10.FCMat | 3 +- .../Metal/Steel/Steel-30CrNiMo8.FCMat | 3 +- .../Metal/Steel/Steel-34CrNiMo6.FCMat | 3 +- .../Metal/Steel/Steel-36CrNiMo4.FCMat | 3 +- .../Metal/Steel/Steel-36NiCrMo16.FCMat | 3 +- .../Metal/Steel/Steel-3C15.FCMat | 3 +- .../Metal/Steel/Steel-3C22.FCMat | 3 +- .../Metal/Steel/Steel-3C35.FCMat | 3 +- .../Metal/Steel/Steel-3V45.FCMat | 3 +- .../Metal/Steel/Steel-C10.FCMat | 3 +- .../Metal/Steel/Steel-C15.FCMat | 3 +- .../Metal/Steel/Steel-C22E.FCMat | 3 +- .../Metal/Steel/Steel-C25E.FCMat | 3 +- .../Metal/Steel/Steel-C30E.FCMat | 3 +- .../Metal/Steel/Steel-C40E.FCMat | 3 +- .../Metal/Steel/Steel-C50E.FCMat | 3 +- .../Metal/Steel/Steel-C55E.FCMat | 3 +- .../Metal/Steel/Steel-C60E.FCMat | 3 +- .../Metal/Steel/Steel-E295-GC.FCMat | 3 +- .../Metal/Steel/Steel-E295.FCMat | 3 +- .../Metal/Steel/Steel-E335-GC.FCMat | 3 +- .../Metal/Steel/Steel-E335.FCMat | 3 +- .../Metal/Steel/Steel-E360-GC.FCMat | 3 +- .../Metal/Steel/Steel-E360.FCMat | 3 +- .../Metal/Steel/Steel-EN-GJL-100.FCMat | 3 +- .../Metal/Steel/Steel-EN-GJL-150.FCMat | 3 +- .../Metal/Steel/Steel-EN-GJL-200.FCMat | 3 +- .../Metal/Steel/Steel-EN-GJL-250.FCMat | 3 +- .../Metal/Steel/Steel-EN-GJL-300.FCMat | 3 +- .../Metal/Steel/Steel-EN-GJL-350.FCMat | 3 +- .../Metal/Steel/Steel-EN-GJMB-350-10.FCMat | 3 +- .../Metal/Steel/Steel-EN-GJMB-550-4.FCMat | 3 +- .../Metal/Steel/Steel-EN-GJMB-650-2.FCMat | 3 +- .../Metal/Steel/Steel-EN-GJMW-350-4.FCMat | 3 +- .../Metal/Steel/Steel-EN-GJMW-360-12.FCMat | 3 +- .../Metal/Steel/Steel-EN-GJMW-400-5.FCMat | 3 +- .../Metal/Steel/Steel-EN-GJMW-450-7.FCMat | 3 +- .../Metal/Steel/Steel-EN-GJS-400-15.FCMat | 3 +- .../Metal/Steel/Steel-EN-GJS-500-7.FCMat | 3 +- .../Metal/Steel/Steel-EN-GJS-600-3.FCMat | 3 +- .../Metal/Steel/Steel-EN-GJS-700-2.FCMat | 3 +- .../Metal/Steel/Steel-EN-GJS-800-1.FCMat | 3 +- .../Metal/Steel/Steel-G16Mn5.FCMat | 3 +- .../Metal/Steel/Steel-G200.FCMat | 3 +- .../Metal/Steel/Steel-G20Mn5.FCMat | 3 +- .../Metal/Steel/Steel-G230.FCMat | 3 +- .../Metal/Steel/Steel-G260.FCMat | 3 +- .../Metal/Steel/Steel-G300.FCMat | 3 +- .../Metal/Steel/Steel-G30Mn5.FCMat | 3 +- .../Metal/Steel/Steel-Generic.FCMat | 3 +- .../Metal/Steel/Steel-S185.FCMat | 3 +- .../Metal/Steel/Steel-S235JO.FCMat | 3 +- .../Metal/Steel/Steel-S235JR.FCMat | 3 +- .../Metal/Steel/Steel-S235JRG1.FCMat | 3 +- .../Metal/Steel/Steel-S260NC.FCMat | 3 +- .../Metal/Steel/Steel-S275JO.FCMat | 3 +- .../Metal/Steel/Steel-S275JR.FCMat | 3 +- .../Metal/Steel/Steel-S275N.FCMat | 3 +- .../Metal/Steel/Steel-S335JO.FCMat | 3 +- .../Metal/Steel/Steel-S335JR.FCMat | 3 +- .../Metal/Steel/Steel-S335N.FCMat | 3 +- .../Metal/Steel/Steel-S340MC.FCMat | 3 +- .../Metal/Steel/Steel-S355J2G3.FCMat | 3 +- .../Metal/Steel/Steel-S380MC.FCMat | 3 +- .../Metal/Steel/Steel-S420MC.FCMat | 3 +- .../Metal/Steel/Steel-S420N.FCMat | 3 +- .../Metal/Steel/Steel-S460MC.FCMat | 3 +- .../Metal/Steel/Steel-S460N.FCMat | 3 +- .../Metal/Steel/Steel-S500MC.FCMat | 3 +- .../Metal/Steel/Steel-S550MC.FCMat | 3 +- .../Metal/Steel/Steel-S690MC.FCMat | 3 +- .../Metal/Steel/Steel-St-37-2K.FCMat | 3 +- .../Metal/Steel/Steel-St-E-255.FCMat | 3 +- .../Metal/Steel/Steel-St-E-315.FCMat | 3 +- .../Metal/Steel/Steel-St-E-380.FCMat | 3 +- .../Metal/Steel/Steel-St-E-460.FCMat | 3 +- .../Metal/Steel/Steel-St-E-500.FCMat | 3 +- .../Metal/Steel/Steel-X2CrNiMoN17-13-3.FCMat | 3 +- .../Metal/Steel/Steel-X2CrNiN24-4.FCMat | 3 +- .../Metal/Steel/Steel-X39CrMo17-1.FCMat | 3 +- .../Metal/Steel/Steel-X3CrNiMo13-14.FCMat | 3 +- .../Metal/Steel/Steel-X5CrNi18-10.FCMat | 3 +- .../Metal/Steel/Steel-X5CrNiMo17-12-2.FCMat | 3 +- .../Metal/Steel/Steel-X6CrNiTi18-10.FCMat | 3 +- .../Metal/Titanium/Ti-6Al-4V.FCMat | 2 +- .../Thermoplast/ABS-Generic.FCMat | 3 +- .../Thermoplast/Acrylic-Glass-Generic.FCMat | 3 +- .../Thermoplast/PA6-Generic.FCMat | 3 +- .../Thermoplast/PET-Generic.FCMat | 3 +- .../Thermoplast/PLA-Generic.FCMat | 3 +- .../Thermoplast/PP-Generic.FCMat | 3 +- .../Thermoplast/PTFE-Generic.FCMat | 3 +- .../Thermoplast/PVC-Generic.FCMat | 3 +- .../StandardMaterial/Wood/Wood-Generic.FCMat | 3 +- src/Mod/Material/TestMaterialsApp.py | 219 +----- .../Material/materialtests/TestMaterials.py | 228 ++++++ src/Mod/Material/materialtests/TestModels.py | 79 ++ src/Mod/Material/materialtests/__init__.py | 0 src/Tools/updatecrowdin.py | 6 +- tests/CMakeLists.txt | 4 + tests/src/App/ComplexGeoData.cpp | 8 +- tests/src/App/Document.cpp | 8 +- tests/src/App/ElementMap.cpp | 8 +- tests/src/App/InitApplication.h | 21 + tests/src/Gui/QuantitySpinBox.cpp | 8 +- tests/src/Mod/Material/App/CMakeLists.txt | 6 +- tests/src/Mod/Material/App/Model.cpp | 8 +- .../Material/App/TestMaterialProperties.cpp | 226 ++++++ .../Mod/Material/App/TestMaterialValue.cpp | 310 ++++++++ tests/src/Mod/Material/App/TestMaterials.cpp | 339 ++++++++ tests/src/Mod/Material/App/TestModel.cpp | 140 ++++ .../Mod/Material/App/TestModelProperties.cpp | 144 ++++ tests/src/Mod/Sketcher/App/SketchObject.cpp | 8 +- 229 files changed, 6530 insertions(+), 1650 deletions(-) create mode 100644 src/Mod/Material/App/Array2DPy.xml create mode 100644 src/Mod/Material/App/Array2DPyImpl.cpp create mode 100644 src/Mod/Material/App/ModelUuids.cpp create mode 100644 src/Mod/Material/App/UUIDsPy.xml create mode 100644 src/Mod/Material/App/UUIDsPyImpl.cpp create mode 100644 src/Mod/Material/materialtests/TestMaterials.py create mode 100644 src/Mod/Material/materialtests/TestModels.py create mode 100644 src/Mod/Material/materialtests/__init__.py create mode 100644 tests/src/App/InitApplication.h create mode 100644 tests/src/Mod/Material/App/TestMaterialProperties.cpp create mode 100644 tests/src/Mod/Material/App/TestMaterialValue.cpp create mode 100644 tests/src/Mod/Material/App/TestMaterials.cpp create mode 100644 tests/src/Mod/Material/App/TestModel.cpp create mode 100644 tests/src/Mod/Material/App/TestModelProperties.cpp diff --git a/src/Mod/Fem/Gui/AppFemGui.cpp b/src/Mod/Fem/Gui/AppFemGui.cpp index c4f36d46a2..a6e8b665cd 100644 --- a/src/Mod/Fem/Gui/AppFemGui.cpp +++ b/src/Mod/Fem/Gui/AppFemGui.cpp @@ -187,4 +187,4 @@ PyMOD_INIT_FUNC(FemGui) // clang-format on PyMOD_Return(mod); -} +} \ No newline at end of file diff --git a/src/Mod/Fem/Gui/CMakeLists.txt b/src/Mod/Fem/Gui/CMakeLists.txt index 5635bef1fc..af0fb7fcd6 100755 --- a/src/Mod/Fem/Gui/CMakeLists.txt +++ b/src/Mod/Fem/Gui/CMakeLists.txt @@ -9,6 +9,12 @@ elseif(CMAKE_COMPILER_IS_GNUCXX) add_compile_options(-Wno-pedantic) # needed for vtk headers endif() +if(MSVC) + add_definitions(-DFCGuiFem -DHAVE_ACOSH -DHAVE_ASINH -DHAVE_ATANH) +else(MSVC) + add_definitions(-DHAVE_LIMITS_H -DHAVE_CONFIG_H) +endif(MSVC) + if(BUILD_FEM_NETGEN) add_definitions(-DFCWithNetgen) endif(BUILD_FEM_NETGEN) diff --git a/src/Mod/Material/App/AppMaterial.cpp b/src/Mod/Material/App/AppMaterial.cpp index ced297ec95..9d2471c657 100644 --- a/src/Mod/Material/App/AppMaterial.cpp +++ b/src/Mod/Material/App/AppMaterial.cpp @@ -33,6 +33,7 @@ #include "ModelManagerPy.h" #include "ModelPropertyPy.h" #include "ModelPy.h" +#include "UUIDsPy.h" namespace Materials { @@ -68,6 +69,7 @@ PyMOD_INIT_FUNC(Material) Base::Interpreter().addType(&Materials::ModelManagerPy ::Type, module, "ModelManager"); Base::Interpreter().addType(&Materials::ModelPropertyPy ::Type, module, "ModelProperty"); Base::Interpreter().addType(&Materials::ModelPy ::Type, module, "Model"); + Base::Interpreter().addType(&Materials::UUIDsPy ::Type, module, "UUIDs"); PyMOD_Return(module); } diff --git a/src/Mod/Material/App/Array2DPy.xml b/src/Mod/Material/App/Array2DPy.xml new file mode 100644 index 0000000000..ba6f5f965f --- /dev/null +++ b/src/Mod/Material/App/Array2DPy.xml @@ -0,0 +1,36 @@ + + + + + + 2D Array of material properties. + + + + The number of rows in the array. + + + + + + The number of columns in the array. + + + + + + Get the default value for the first column of the array + + + + diff --git a/src/Mod/Material/App/Array2DPyImpl.cpp b/src/Mod/Material/App/Array2DPyImpl.cpp new file mode 100644 index 0000000000..02ef6e5465 --- /dev/null +++ b/src/Mod/Material/App/Array2DPyImpl.cpp @@ -0,0 +1,85 @@ +/*************************************************************************** + * Copyright (c) 2023 David Carter * + * * + * This file is part of FreeCAD. * + * * + * FreeCAD is free software: you can redistribute it and/or modify it * + * under the terms of the GNU Lesser General Public License as * + * published by the Free Software Foundation, either version 2.1 of the * + * License, or (at your option) any later version. * + * * + * FreeCAD is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with FreeCAD. If not, see * + * . * + * * + **************************************************************************/ + +#include "PreCompiled.h" + +#include "Array2DPy.h" +#include "Model.h" +#include "ModelLibrary.h" +#include "ModelPropertyPy.h" +#include "ModelUuids.h" + +#include "Array2DPy.cpp" + +using namespace Materials; + +// returns a string which represents the object e.g. when printed in python +std::string Array2DPy::representation() const +{ + std::stringstream str; + str << ""; + + return str.str(); +} + +PyObject* Array2DPy::PyMake(struct _typeobject*, PyObject*, PyObject*) // Python wrapper +{ + // never create such objects with the constructor + return new Array2DPy(new Material2DArray()); +} + +// constructor method +int Array2DPy::PyInit(PyObject* /*args*/, PyObject* /*kwd*/) +{ + return 0; +} + +Py::Int Array2DPy::getRows() const +{ + return Py::Int(getMaterial2DArrayPtr()->rows()); +} + +Py::Int Array2DPy::getColumns() const +{ + return Py::Int(getMaterial2DArrayPtr()->columns()); +} + +PyObject* Array2DPy::getDefaultValue(PyObject* args) +{ + char* name; + if (!PyArg_ParseTuple(args, "s", &name)) { + return nullptr; + } + + // QVariant value = getMaterial2DArrayPtr()->getPhysicalValue(QString::fromStdString(name)); + // return _pyObjectFromVariant(value); + return nullptr; +} + +PyObject* Array2DPy::getCustomAttributes(const char* /*attr*/) const +{ + return nullptr; +} + +int Array2DPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/) +{ + return 0; +} diff --git a/src/Mod/Material/App/CMakeLists.txt b/src/Mod/Material/App/CMakeLists.txt index 21258ea53a..ab2bc85745 100644 --- a/src/Mod/Material/App/CMakeLists.txt +++ b/src/Mod/Material/App/CMakeLists.txt @@ -33,14 +33,18 @@ list(APPEND Material_LIBS ${YAML_CPP_LIBRARIES} ) +generate_from_xml(Array2DPy) generate_from_xml(MaterialManagerPy) generate_from_xml(MaterialPy) generate_from_xml(ModelManagerPy) generate_from_xml(ModelPropertyPy) generate_from_xml(ModelPy) +generate_from_xml(UUIDsPy) SET(Python_SRCS Exceptions.h + Array2DPy.xml + Array2DPyImpl.cpp MaterialManagerPy.xml MaterialManagerPyImpl.cpp MaterialPy.xml @@ -51,6 +55,8 @@ SET(Python_SRCS ModelPropertyPyImpl.cpp ModelPy.xml ModelPyImpl.cpp + UUIDsPy.xml + UUIDsPyImpl.cpp ) SOURCE_GROUP("Python" FILES ${Python_SRCS}) @@ -78,6 +84,7 @@ SET(Material_SRCS ModelLoader.h ModelManager.cpp ModelManager.h + ModelUuids.cpp ModelUuids.h PreCompiled.cpp PreCompiled.h diff --git a/src/Mod/Material/App/Exceptions.h b/src/Mod/Material/App/Exceptions.h index c67e9df4eb..49152cd263 100644 --- a/src/Mod/Material/App/Exceptions.h +++ b/src/Mod/Material/App/Exceptions.h @@ -22,6 +22,8 @@ #ifndef MATERIAL_EXCEPTIONS_H #define MATERIAL_EXCEPTIONS_H +#include + #include #include @@ -37,6 +39,10 @@ public: { this->setMessage(msg); } + explicit Uninitialized(const QString& msg) + { + this->setMessage(msg.toStdString().c_str()); + } ~Uninitialized() noexcept override = default; }; @@ -49,9 +55,29 @@ public: { this->setMessage(msg); } + explicit ModelNotFound(const QString& msg) + { + this->setMessage(msg.toStdString().c_str()); + } ~ModelNotFound() noexcept override = default; }; +class InvalidMaterialType: public Base::Exception +{ +public: + InvalidMaterialType() + {} + explicit InvalidMaterialType(const char* msg) + { + this->setMessage(msg); + } + explicit InvalidMaterialType(const QString& msg) + { + this->setMessage(msg.toStdString().c_str()); + } + ~InvalidMaterialType() noexcept override = default; +}; + class MaterialNotFound: public Base::Exception { public: @@ -61,9 +87,29 @@ public: { this->setMessage(msg); } + explicit MaterialNotFound(const QString& msg) + { + this->setMessage(msg.toStdString().c_str()); + } ~MaterialNotFound() noexcept override = default; }; +class MaterialExists: public Base::Exception +{ +public: + MaterialExists() + {} + explicit MaterialExists(const char* msg) + { + this->setMessage(msg); + } + explicit MaterialExists(const QString& msg) + { + this->setMessage(msg.toStdString().c_str()); + } + ~MaterialExists() noexcept override = default; +}; + class PropertyNotFound: public Base::Exception { public: @@ -73,6 +119,10 @@ public: { this->setMessage(msg); } + explicit PropertyNotFound(const QString& msg) + { + this->setMessage(msg.toStdString().c_str()); + } ~PropertyNotFound() noexcept override = default; }; @@ -85,6 +135,10 @@ public: { this->setMessage(msg); } + explicit LibraryNotFound(const QString& msg) + { + this->setMessage(msg.toStdString().c_str()); + } ~LibraryNotFound() noexcept override = default; }; @@ -97,6 +151,10 @@ public: { this->setMessage(msg); } + explicit InvalidModel(const QString& msg) + { + this->setMessage(msg.toStdString().c_str()); + } ~InvalidModel() noexcept override = default; }; @@ -109,6 +167,10 @@ public: { this->setMessage(msg); } + explicit InvalidRow(const QString& msg) + { + this->setMessage(msg.toStdString().c_str()); + } ~InvalidRow() noexcept override = default; }; @@ -121,9 +183,29 @@ public: { this->setMessage(msg); } + explicit InvalidColumn(const QString& msg) + { + this->setMessage(msg.toStdString().c_str()); + } ~InvalidColumn() noexcept override = default; }; +class InvalidDepth: public Base::Exception +{ +public: + InvalidDepth() + {} + explicit InvalidDepth(char* msg) + { + this->setMessage(msg); + } + explicit InvalidDepth(const QString& msg) + { + this->setMessage(msg.toStdString().c_str()); + } + ~InvalidDepth() noexcept override = default; +}; + class InvalidIndex: public Base::Exception { public: @@ -133,6 +215,10 @@ public: { this->setMessage(msg); } + explicit InvalidIndex(const QString& msg) + { + this->setMessage(msg.toStdString().c_str()); + } ~InvalidIndex() noexcept override = default; }; @@ -145,9 +231,29 @@ public: { this->setMessage(msg); } + explicit UnknownValueType(const QString& msg) + { + this->setMessage(msg.toStdString().c_str()); + } ~UnknownValueType() noexcept override = default; }; +class DeleteError: public Base::Exception +{ +public: + DeleteError() + {} + explicit DeleteError(char* msg) + { + this->setMessage(msg); + } + explicit DeleteError(const QString& msg) + { + this->setMessage(msg.toStdString().c_str()); + } + ~DeleteError() noexcept override = default; +}; + } // namespace Materials #endif // MATERIAL_EXCEPTIONS_H diff --git a/src/Mod/Material/App/FolderTree.h b/src/Mod/Material/App/FolderTree.h index 2cc3133fa6..e2c450753c 100644 --- a/src/Mod/Material/App/FolderTree.h +++ b/src/Mod/Material/App/FolderTree.h @@ -22,10 +22,10 @@ #ifndef MATERIAL_FOLDERTREE_H #define MATERIAL_FOLDERTREE_H -#include #include #include +#include namespace Materials { @@ -53,25 +53,25 @@ public: _type = type; } - const std::shared_ptr*>> getFolder() const + const std::shared_ptr>>> getFolder() const { return _folder; } - std::shared_ptr*>> getFolder() + std::shared_ptr>>> getFolder() { return _folder; } - const T* getData() const + std::shared_ptr getData() const { return _data; } - void setFolder(std::shared_ptr*>> folder) + void setFolder(std::shared_ptr>>> folder) { setType(FolderNode); _folder = folder; } - void setData(const T* data) + void setData(std::shared_ptr data) { setType(DataNode); _data = data; @@ -79,8 +79,8 @@ public: private: NodeType _type; - std::shared_ptr*>> _folder; - const T* _data; + std::shared_ptr>>> _folder; + std::shared_ptr _data; }; } // namespace Materials diff --git a/src/Mod/Material/App/MaterialConfigLoader.cpp b/src/Mod/Material/App/MaterialConfigLoader.cpp index 6e5e287600..492730f2ec 100644 --- a/src/Mod/Material/App/MaterialConfigLoader.cpp +++ b/src/Mod/Material/App/MaterialConfigLoader.cpp @@ -85,7 +85,8 @@ QString MaterialConfigLoader::getAuthorAndLicense(const QString& path) return noAuthor; } -void MaterialConfigLoader::addVectorRendering(const QSettings& fcmat, Material* finalModel) +void MaterialConfigLoader::addVectorRendering(const QSettings& fcmat, + std::shared_ptr finalModel) { QString sectionFillPattern = value(fcmat, "VectorRendering/SectionFillPattern", ""); QString sectionLinewidth = value(fcmat, "VectorRendering/SectionLinewidth", ""); @@ -97,7 +98,7 @@ void MaterialConfigLoader::addVectorRendering(const QSettings& fcmat, Material* if (sectionFillPattern.length() + sectionLinewidth.length() + sectionColor.length() + viewColor.length() + viewFillPattern.length() + viewLinewidth.length() > 0) { - finalModel->addAppearance(ModelUUID_Rendering_Vector); + finalModel->addAppearance(ModelUUIDs::ModelUUID_Rendering_Vector); } // Now add the data @@ -109,7 +110,8 @@ void MaterialConfigLoader::addVectorRendering(const QSettings& fcmat, Material* setAppearanceValue(finalModel, "ViewLinewidth", viewLinewidth); } -void MaterialConfigLoader::addRendering(const QSettings& fcmat, Material* finalModel) +void MaterialConfigLoader::addRendering(const QSettings& fcmat, + std::shared_ptr finalModel) { QString ambientColor = value(fcmat, "Rendering/AmbientColor", ""); QString diffuseColor = value(fcmat, "Rendering/DiffuseColor", ""); @@ -139,13 +141,13 @@ void MaterialConfigLoader::addRendering(const QSettings& fcmat, Material* finalM } if (useAdvanced) { - finalModel->addAppearance(ModelUUID_Rendering_Advanced); + finalModel->addAppearance(ModelUUIDs::ModelUUID_Rendering_Advanced); } else if (useTexture) { - finalModel->addAppearance(ModelUUID_Rendering_Texture); + finalModel->addAppearance(ModelUUIDs::ModelUUID_Rendering_Texture); } else if (useBasic) { - finalModel->addAppearance(ModelUUID_Rendering_Basic); + finalModel->addAppearance(ModelUUIDs::ModelUUID_Rendering_Basic); } // Now add the data @@ -161,14 +163,14 @@ void MaterialConfigLoader::addRendering(const QSettings& fcmat, Material* finalM setAppearanceValue(finalModel, "VertexShader", vertexShader); } -void MaterialConfigLoader::addCosts(const QSettings& fcmat, Material* finalModel) +void MaterialConfigLoader::addCosts(const QSettings& fcmat, std::shared_ptr finalModel) { QString productURL = value(fcmat, "Cost/ProductURL", ""); QString specificPrice = value(fcmat, "Cost/SpecificPrice", ""); QString vendor = value(fcmat, "Cost/Vendor", ""); if (productURL.length() + specificPrice.length() + vendor.length() > 0) { - finalModel->addPhysical(ModelUUID_Costs_Default); + finalModel->addPhysical(ModelUUIDs::ModelUUID_Costs_Default); } // Now add the data @@ -177,7 +179,8 @@ void MaterialConfigLoader::addCosts(const QSettings& fcmat, Material* finalModel setPhysicalValue(finalModel, "Vendor", vendor); } -void MaterialConfigLoader::addArchitectural(const QSettings& fcmat, Material* finalModel) +void MaterialConfigLoader::addArchitectural(const QSettings& fcmat, + std::shared_ptr finalModel) { QString color = value(fcmat, "Architectural/Color", ""); QString environmentalEfficiencyClass = @@ -193,7 +196,7 @@ void MaterialConfigLoader::addArchitectural(const QSettings& fcmat, Material* fi + finish.length() + fireResistanceClass.length() + model.length() + soundTransmissionClass.length() + unitsPerQuantity.length() > 0) { - finalModel->addPhysical(ModelUUID_Architectural_Default); + finalModel->addPhysical(ModelUUIDs::ModelUUID_Architectural_Default); } // Now add the data @@ -207,7 +210,8 @@ void MaterialConfigLoader::addArchitectural(const QSettings& fcmat, Material* fi setPhysicalValue(finalModel, "UnitsPerQuantity", unitsPerQuantity); } -void MaterialConfigLoader::addElectromagnetic(const QSettings& fcmat, Material* finalModel) +void MaterialConfigLoader::addElectromagnetic(const QSettings& fcmat, + std::shared_ptr finalModel) { QString relativePermittivity = value(fcmat, "Electromagnetic/RelativePermittivity", ""); QString electricalConductivity = value(fcmat, "Electromagnetic/ElectricalConductivity", ""); @@ -216,7 +220,7 @@ void MaterialConfigLoader::addElectromagnetic(const QSettings& fcmat, Material* if (relativePermittivity.length() + electricalConductivity.length() + relativePermeability.length() > 0) { - finalModel->addPhysical(ModelUUID_Electromagnetic_Default); + finalModel->addPhysical(ModelUUIDs::ModelUUID_Electromagnetic_Default); } // Now add the data @@ -225,7 +229,7 @@ void MaterialConfigLoader::addElectromagnetic(const QSettings& fcmat, Material* setPhysicalValue(finalModel, "RelativePermeability", relativePermeability); } -void MaterialConfigLoader::addThermal(const QSettings& fcmat, Material* finalModel) +void MaterialConfigLoader::addThermal(const QSettings& fcmat, std::shared_ptr finalModel) { QString specificHeat = value(fcmat, "Thermal/SpecificHeat", ""); QString thermalConductivity = value(fcmat, "Thermal/ThermalConductivity", ""); @@ -233,7 +237,7 @@ void MaterialConfigLoader::addThermal(const QSettings& fcmat, Material* finalMod if (specificHeat.length() + thermalConductivity.length() + thermalExpansionCoefficient.length() > 0) { - finalModel->addPhysical(ModelUUID_Thermal_Default); + finalModel->addPhysical(ModelUUIDs::ModelUUID_Thermal_Default); } // Now add the data @@ -242,7 +246,7 @@ void MaterialConfigLoader::addThermal(const QSettings& fcmat, Material* finalMod setPhysicalValue(finalModel, "ThermalExpansionCoefficient", thermalExpansionCoefficient); } -void MaterialConfigLoader::addFluid(const QSettings& fcmat, Material* finalModel) +void MaterialConfigLoader::addFluid(const QSettings& fcmat, std::shared_ptr finalModel) { QString density = value(fcmat, "Fluidic/Density", ""); QString dynamicViscosity = value(fcmat, "Fluidic/DynamicViscosity", ""); @@ -260,10 +264,10 @@ void MaterialConfigLoader::addFluid(const QSettings& fcmat, Material* finalModel } if (useFluid) { - finalModel->addPhysical(ModelUUID_Fluid_Default); + finalModel->addPhysical(ModelUUIDs::ModelUUID_Fluid_Default); } else if (useDensity) { - finalModel->addPhysical(ModelUUID_Mechanical_Density); + finalModel->addPhysical(ModelUUIDs::ModelUUID_Mechanical_Density); } // Now add the data @@ -273,7 +277,8 @@ void MaterialConfigLoader::addFluid(const QSettings& fcmat, Material* finalModel setPhysicalValue(finalModel, "PrandtlNumber", prandtlNumber); } -void MaterialConfigLoader::addMechanical(const QSettings& fcmat, Material* finalModel) +void MaterialConfigLoader::addMechanical(const QSettings& fcmat, + std::shared_ptr finalModel) { QString density = value(fcmat, "Mechanical/Density", ""); QString bulkModulus = value(fcmat, "Mechanical/BulkModulus", ""); @@ -308,14 +313,14 @@ void MaterialConfigLoader::addMechanical(const QSettings& fcmat, Material* final } if (useLinearElastic) { - finalModel->addPhysical(ModelUUID_Mechanical_LinearElastic); + finalModel->addPhysical(ModelUUIDs::ModelUUID_Mechanical_LinearElastic); } else { if (useIso) { - finalModel->addPhysical(ModelUUID_Mechanical_IsotropicLinearElastic); + finalModel->addPhysical(ModelUUIDs::ModelUUID_Mechanical_IsotropicLinearElastic); } if (useDensity) { - finalModel->addPhysical(ModelUUID_Mechanical_Density); + finalModel->addPhysical(ModelUUIDs::ModelUUID_Mechanical_Density); } } @@ -334,10 +339,11 @@ void MaterialConfigLoader::addMechanical(const QSettings& fcmat, Material* final setPhysicalValue(finalModel, "Stiffness", stiffness); } -Material* MaterialConfigLoader::getMaterialFromPath(const MaterialLibrary& library, - const QString& path) +std::shared_ptr +MaterialConfigLoader::getMaterialFromPath(std::shared_ptr library, + const QString& path) { - QString authorAndLicense = getAuthorAndLicense(path); + QString author = getAuthorAndLicense(path); // Place them both in the author field QSettings fcmat(path, QSettings::IniFormat); @@ -352,15 +358,15 @@ Material* MaterialConfigLoader::getMaterialFromPath(const MaterialLibrary& libra QString sourceReference = value(fcmat, "ReferenceSource", ""); QString sourceURL = value(fcmat, "SourceURL", ""); - Material* finalModel = new Material(library, path, uuid, name); - finalModel->setAuthorAndLicense(authorAndLicense); + std::shared_ptr finalModel = std::make_shared(library, path, uuid, name); + finalModel->setAuthor(author); finalModel->setDescription(description); finalModel->setReference(sourceReference); finalModel->setURL(sourceURL); QString father = value(fcmat, "Father", ""); if (father.length() > 0) { - finalModel->addPhysical(ModelUUID_Legacy_Father); + finalModel->addPhysical(ModelUUIDs::ModelUUID_Legacy_Father); // Now add the data setPhysicalValue(finalModel, "Father", father); @@ -372,7 +378,7 @@ Material* MaterialConfigLoader::getMaterialFromPath(const MaterialLibrary& libra QString standardCode = value(fcmat, "StandardCode", ""); if (kindOfMaterial.length() + materialNumber.length() + norm.length() + standardCode.length() > 0) { - finalModel->addPhysical(ModelUUID_Legacy_MaterialStandard); + finalModel->addPhysical(ModelUUIDs::ModelUUID_Legacy_MaterialStandard); // Now add the data setPhysicalValue(finalModel, "KindOfMaterial", kindOfMaterial); diff --git a/src/Mod/Material/App/MaterialConfigLoader.h b/src/Mod/Material/App/MaterialConfigLoader.h index f2337cd04f..5d847d944c 100644 --- a/src/Mod/Material/App/MaterialConfigLoader.h +++ b/src/Mod/Material/App/MaterialConfigLoader.h @@ -22,6 +22,8 @@ #ifndef MATERIAL_MATERIALCONFIGLOADER_H #define MATERIAL_MATERIALCONFIGLOADER_H +#include + #include #include #include @@ -39,7 +41,8 @@ public: static bool isConfigStyle(const QString& path); - static Material* getMaterialFromPath(const MaterialLibrary& library, const QString& path); + static std::shared_ptr getMaterialFromPath(std::shared_ptr library, + const QString& path); private: static QString @@ -49,15 +52,17 @@ private: .toString(); } - static void - setPhysicalValue(Material* finalModel, const std::string& name, const QString& value) + static void setPhysicalValue(std::shared_ptr finalModel, + const std::string& name, + const QString& value) { if (value.length() > 0) { finalModel->setPhysicalValue(QString::fromStdString(name), value); } } - static void - setAppearanceValue(Material* finalModel, const std::string& name, const QString& value) + static void setAppearanceValue(std::shared_ptr finalModel, + const std::string& name, + const QString& value) { if (value.length() > 0) { finalModel->setAppearanceValue(QString::fromStdString(name), value); @@ -65,14 +70,14 @@ private: } static QString getAuthorAndLicense(const QString& path); - static void addMechanical(const QSettings& fcmat, Material* finalModel); - static void addFluid(const QSettings& fcmat, Material* finalModel); - static void addThermal(const QSettings& fcmat, Material* finalModel); - static void addElectromagnetic(const QSettings& fcmat, Material* finalModel); - static void addArchitectural(const QSettings& fcmat, Material* finalModel); - static void addCosts(const QSettings& fcmat, Material* finalModel); - static void addRendering(const QSettings& fcmat, Material* finalModel); - static void addVectorRendering(const QSettings& fcmat, Material* finalModel); + static void addMechanical(const QSettings& fcmat, std::shared_ptr finalModel); + static void addFluid(const QSettings& fcmat, std::shared_ptr finalModel); + static void addThermal(const QSettings& fcmat, std::shared_ptr finalModel); + static void addElectromagnetic(const QSettings& fcmat, std::shared_ptr finalModel); + static void addArchitectural(const QSettings& fcmat, std::shared_ptr finalModel); + static void addCosts(const QSettings& fcmat, std::shared_ptr finalModel); + static void addRendering(const QSettings& fcmat, std::shared_ptr finalModel); + static void addVectorRendering(const QSettings& fcmat, std::shared_ptr finalModel); }; } // namespace Materials diff --git a/src/Mod/Material/App/MaterialLibrary.cpp b/src/Mod/Material/App/MaterialLibrary.cpp index 3d5ee05a59..944ae9408d 100644 --- a/src/Mod/Material/App/MaterialLibrary.cpp +++ b/src/Mod/Material/App/MaterialLibrary.cpp @@ -21,11 +21,17 @@ #include "PreCompiled.h" #ifndef _PreComp_ +#include #endif +#include +#include + #include #include "MaterialLibrary.h" +#include "MaterialLoader.h" +#include "MaterialManager.h" #include "Materials.h" #include "ModelManager.h" @@ -34,9 +40,6 @@ using namespace Materials; /* TRANSLATOR Material::Materials */ -std::unique_ptr> MaterialLibrary::_materialPathMap = - std::make_unique>(); - TYPESYSTEM_SOURCE(Materials::MaterialLibrary, LibraryBase) MaterialLibrary::MaterialLibrary() @@ -48,24 +51,165 @@ MaterialLibrary::MaterialLibrary(const QString& libraryName, bool readOnly) : LibraryBase(libraryName, dir, icon) , _readOnly(readOnly) + , _materialPathMap(std::make_unique>>()) {} -void MaterialLibrary::createPath(const QString& path) -{ - Q_UNUSED(path) -} - -Material* MaterialLibrary::saveMaterial(Material& material, const QString& path, bool saveAsCopy) +void MaterialLibrary::createFolder(const QString& path) { QString filePath = getLocalPath(path); - Base::Console().Log("\tfilePath = '%s'\n", filePath.toStdString().c_str()); + // Base::Console().Log("\tfilePath = '%s'\n", filePath.toStdString().c_str()); + + QDir fileDir(filePath); + if (!fileDir.exists()) { + if (!fileDir.mkpath(filePath)) { + Base::Console().Error("Unable to create directory path '%s'\n", + filePath.toStdString().c_str()); + } + } +} + +// This accepts the filesystem path as returned from getLocalPath +void MaterialLibrary::deleteDir(MaterialManager& manager, const QString& path) +{ + // Base::Console().Log("Removing directory '%s'\n", path.toStdString().c_str()); + + // Remove the children first + QDirIterator it(path, QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot); + + // Add paths to a list so there are no iterator errors + QVector dirList; + QVector fileList; + while (it.hasNext()) { + auto pathname = it.next(); + QFileInfo file(pathname); + if (file.isFile()) { + fileList.push_back(pathname); + } + else if (file.isDir()) { + dirList.push_back(pathname); + } + } + + // Remove the subdirs first + while (!dirList.isEmpty()) { + QString dirPath = dirList.takeFirst(); + deleteDir(manager, dirPath); + } + + // Remove the files + while (!fileList.isEmpty()) { + QString filePath = fileList.takeFirst(); + deleteFile(manager, filePath); + } + + // Finally, remove ourself + QDir dir; + if (!dir.rmdir(path)) { + throw DeleteError(path); + } +} + +// This accepts the filesystem path as returned from getLocalPath +void MaterialLibrary::deleteFile(MaterialManager& manager, const QString& path) +{ + // Base::Console().Log("Removing file '%s'\n", path.toStdString().c_str()); + + if (QFile::remove(path)) { + // Remove from the map + QString rPath = getRelativePath(path); + // Base::Console().Log("\trpath '%s'\n", rPath.toStdString().c_str()); + try { + auto material = getMaterialByPath(rPath); + manager.remove(material->getUUID()); + } + catch (const MaterialNotFound&) { + Base::Console().Log("Unable to remove file from materials list\n"); + } + _materialPathMap->erase(rPath); + } + else { + QString error = QString::fromStdString("DeleteError: Unable to delete ") + path; + throw DeleteError(error); + } +} + +void MaterialLibrary::deleteRecursive(const QString& path) +{ + std::string pstring = path.toStdString(); + Base::Console().Log("\tdeleteRecursive '%s'\n", pstring.c_str()); + + if (isRoot(path)) { + return; + } + + QString filePath = getLocalPath(path); + // Base::Console().Log("\tfilePath = '%s'\n", filePath.toStdString().c_str()); + MaterialManager manager; + + QFileInfo info(filePath); + if (info.isDir()) { + deleteDir(manager, filePath); + } + else { + deleteFile(manager, filePath); + } +} + +void MaterialLibrary::updatePaths(const QString& oldPath, const QString& newPath) +{ + // Update the path map + QString op = getRelativePath(oldPath); + QString np = getRelativePath(newPath); + std::unique_ptr>> pathMap = + std::make_unique>>(); + for (auto itp = _materialPathMap->begin(); itp != _materialPathMap->end(); itp++) { + QString path = itp->first; + if (path.startsWith(op)) { + path = np + path.remove(0, op.size()); + } + Base::Console().Error("Path '%s' -> '%s'\n", + itp->first.toStdString().c_str(), + path.toStdString().c_str()); + itp->second->setDirectory(path); + (*pathMap)[path] = itp->second; + } + + _materialPathMap = std::move(pathMap); +} + +void MaterialLibrary::renameFolder(const QString& oldPath, const QString& newPath) +{ + QString filePath = getLocalPath(oldPath); + // Base::Console().Log("\tfilePath = '%s'\n", filePath.toStdString().c_str()); + QString newFilePath = getLocalPath(newPath); + // Base::Console().Log("\tnew filePath = '%s'\n", newFilePath.toStdString().c_str()); + + QDir fileDir(filePath); + if (fileDir.exists()) { + if (!fileDir.rename(filePath, newFilePath)) { + Base::Console().Error("Unable to rename directory path '%s'\n", + filePath.toStdString().c_str()); + } + } + + updatePaths(oldPath, newPath); +} + +std::shared_ptr MaterialLibrary::saveMaterial(std::shared_ptr material, + const QString& path, + bool overwrite, + bool saveAsCopy, + bool saveInherited) +{ + QString filePath = getLocalPath(path); + // Base::Console().Log("\tfilePath = '%s'\n", filePath.toStdString().c_str()); QFile file(filePath); // Update UUID if required // if name changed true - if (material.getName() != file.fileName()) { - material.newUuid(); - } + // if (material->getName() != file.fileName()) { + // material->newUuid(); + // } // if overwrite false having warned the user // if old format true, but already set @@ -79,43 +223,49 @@ Material* MaterialLibrary::saveMaterial(Material& material, const QString& path, } } + if (info.exists()) { + if (!overwrite) { + Base::Console().Error("File already exists '%s'\n", info.path().toStdString().c_str()); + throw MaterialExists(); + } + } + if (file.open(QIODevice::WriteOnly | QIODevice::Text)) { QTextStream stream(&file); -#if QT_VERSION < QT_VERSION_CHECK(6,0,0) stream.setCodec("UTF-8"); -#endif stream.setGenerateByteOrderMark(true); // Write the contents - material.setLibrary(*this); - material.setDirectory(getRelativePath(path)); - material.save(stream, saveAsCopy); + material->setLibrary(getptr()); + material->setDirectory(getRelativePath(path)); + material->save(stream, saveAsCopy, saveInherited); } return addMaterial(material, path); } -Material* MaterialLibrary::addMaterial(const Material& material, const QString& path) +bool MaterialLibrary::fileExists(const QString& path) const +{ + QString filePath = getLocalPath(path); + QFileInfo info(filePath); + + return info.exists(); +} + +std::shared_ptr MaterialLibrary::addMaterial(std::shared_ptr material, + const QString& path) { QString filePath = getRelativePath(path); - Material* newMaterial = new Material(material); - newMaterial->setLibrary(*this); + std::shared_ptr newMaterial = std::make_shared(*material); + newMaterial->setLibrary(getptr()); newMaterial->setDirectory(filePath); - try { - // If there's already a material at that path we'll replace it - Material* old = _materialPathMap->at(filePath); - delete old; - } - catch (const std::out_of_range&) { - } - (*_materialPathMap)[filePath] = newMaterial; return newMaterial; } -const Material& MaterialLibrary::getMaterialByPath(const QString& path) const +std::shared_ptr MaterialLibrary::getMaterialByPath(const QString& path) const { // Base::Console().Log("MaterialLibrary::getMaterialByPath(%s)\n", path.toStdString().c_str()); // for (auto itp = _materialPathMap->begin(); itp != _materialPathMap->end(); itp++) { @@ -124,10 +274,10 @@ const Material& MaterialLibrary::getMaterialByPath(const QString& path) const QString filePath = getRelativePath(path); try { - Material* material = _materialPathMap->at(filePath); - return *material; + auto material = _materialPathMap->at(filePath); + return material; } - catch (std::out_of_range&) { + catch (std::out_of_range& e) { throw MaterialNotFound(); } } @@ -136,14 +286,80 @@ const QString MaterialLibrary::getUUIDFromPath(const QString& path) const { QString filePath = getRelativePath(path); try { - Material* material = _materialPathMap->at(filePath); + auto material = _materialPathMap->at(filePath); return material->getUUID(); } - catch (std::out_of_range&) { + catch (std::out_of_range& e) { throw MaterialNotFound(); } } +std::shared_ptr>> +MaterialLibrary::getMaterialTree() const +{ + std::shared_ptr>> materialTree = + std::make_shared>>(); + + for (auto it = _materialPathMap->begin(); it != _materialPathMap->end(); it++) { + auto filename = it->first; + auto material = it->second; + + // Base::Console().Log("Relative path '%s'\n\t", filename.toStdString().c_str()); + QStringList list = filename.split(QString::fromStdString("/")); + + // Start at the root + std::shared_ptr>> node = materialTree; + for (auto itp = list.begin(); itp != list.end(); itp++) { + // Base::Console().Log("\t%s", itp->toStdString().c_str()); + if (itp->endsWith(QString::fromStdString(".FCMat"))) { + std::shared_ptr child = std::make_shared(); + child->setData(material); + (*node)[*itp] = child; + } + else { + // Add the folder only if it's not already there + if (node->count(*itp) == 0) { + auto mapPtr = + std::make_shared>>(); + std::shared_ptr child = std::make_shared(); + child->setFolder(mapPtr); + (*node)[*itp] = child; + node = mapPtr; + } + else { + node = (*node)[*itp]->getFolder(); + } + } + } + } + + // Empty folders aren't included in _materialPathMap, so we add them by looking at the file + // system + auto folderList = MaterialLoader::getMaterialFolders(*this); + for (auto folder : *folderList) { + QStringList list = folder.split(QString::fromStdString("/")); + + // Start at the root + auto node = materialTree; + for (auto itp = list.begin(); itp != list.end(); itp++) { + // Add the folder only if it's not already there + if (node->count(*itp) == 0) { + std::shared_ptr>> mapPtr = + std::make_shared>>(); + std::shared_ptr child = std::make_shared(); + child->setFolder(mapPtr); + (*node)[*itp] = child; + node = mapPtr; + } + else { + node = (*node)[*itp]->getFolder(); + } + } + } + + return materialTree; +} + TYPESYSTEM_SOURCE(Materials::MaterialExternalLibrary, MaterialLibrary::MaterialLibrary) MaterialExternalLibrary::MaterialExternalLibrary() diff --git a/src/Mod/Material/App/MaterialLibrary.h b/src/Mod/Material/App/MaterialLibrary.h index 8bb16f34f8..ce6d32dfd3 100644 --- a/src/Mod/Material/App/MaterialLibrary.h +++ b/src/Mod/Material/App/MaterialLibrary.h @@ -22,14 +22,17 @@ #ifndef MATERIAL_MATERIALLIBRARY_H #define MATERIAL_MATERIALLIBRARY_H -#include - -#include #include + #include #include #include +#include + +#include + +#include "Materials.h" #include "Model.h" #include "ModelLibrary.h" @@ -37,17 +40,19 @@ namespace Materials { class Material; +class MaterialManager; -class MaterialsExport MaterialLibrary: public LibraryBase +class MaterialsExport MaterialLibrary: public LibraryBase, + public std::enable_shared_from_this { - TYPESYSTEM_HEADER_WITH_OVERRIDE(); + TYPESYSTEM_HEADER(); public: MaterialLibrary(); - explicit MaterialLibrary(const QString& libraryName, - const QString& dir, - const QString& icon, - bool readOnly = true); + MaterialLibrary(const QString& libraryName, + const QString& dir, + const QString& icon, + bool readOnly = true); ~MaterialLibrary() override = default; bool operator==(const MaterialLibrary& library) const @@ -58,40 +63,60 @@ public: { return !operator==(library); } - const Material& getMaterialByPath(const QString& path) const; + std::shared_ptr getMaterialByPath(const QString& path) const; - void createPath(const QString& path); - Material* saveMaterial(Material& material, const QString& path, bool saveAsCopy); - Material* addMaterial(const Material& material, const QString& path); + void createFolder(const QString& path); + void renameFolder(const QString& oldPath, const QString& newPath); + void deleteRecursive(const QString& path); + + std::shared_ptr saveMaterial(std::shared_ptr material, + const QString& path, + bool overwrite, + bool saveAsCopy, + bool saveInherited); + bool fileExists(const QString& path) const; + std::shared_ptr addMaterial(std::shared_ptr material, const QString& path); + std::shared_ptr>> getMaterialTree() const; bool isReadOnly() const { return _readOnly; } + // Use this to get a shared_ptr for *this + std::shared_ptr getptr() + { + return shared_from_this(); + } + protected: + MaterialLibrary(const MaterialLibrary&) = default; + + void deleteDir(MaterialManager& manager, const QString& path); + void deleteFile(MaterialManager& manager, const QString& path); + + void updatePaths(const QString& oldPath, const QString& newPath); const QString getUUIDFromPath(const QString& path) const; bool _readOnly; - static std::unique_ptr> _materialPathMap; + std::unique_ptr>> _materialPathMap; }; class MaterialsExport MaterialExternalLibrary: public MaterialLibrary { - TYPESYSTEM_HEADER_WITH_OVERRIDE(); + TYPESYSTEM_HEADER(); public: MaterialExternalLibrary(); - explicit MaterialExternalLibrary(const QString& libraryName, - const QString& dir, - const QString& icon, - bool readOnly = true); + MaterialExternalLibrary(const QString& libraryName, + const QString& dir, + const QString& icon, + bool readOnly = true); ~MaterialExternalLibrary() override; }; } // namespace Materials -Q_DECLARE_METATYPE(Materials::MaterialLibrary) -Q_DECLARE_METATYPE(Materials::MaterialExternalLibrary) +Q_DECLARE_METATYPE(std::shared_ptr) #endif // MATERIAL_MATERIALLIBRARY_H diff --git a/src/Mod/Material/App/MaterialLoader.cpp b/src/Mod/Material/App/MaterialLoader.cpp index 8742d7df6b..34004bc0a6 100644 --- a/src/Mod/Material/App/MaterialLoader.cpp +++ b/src/Mod/Material/App/MaterialLoader.cpp @@ -24,13 +24,18 @@ #include #endif -#include -#include - #include #include +#include + +#include +#include +#include + +#include "Materials.h" #include "MaterialConfigLoader.h" +#include "MaterialLibrary.h" #include "MaterialLoader.h" #include "Model.h" #include "ModelManager.h" @@ -41,7 +46,7 @@ using namespace Materials; MaterialEntry::MaterialEntry() {} -MaterialEntry::MaterialEntry(const MaterialLibrary& library, +MaterialEntry::MaterialEntry(std::shared_ptr library, const QString& modelName, const QString& dir, const QString& modelUuid) @@ -51,7 +56,7 @@ MaterialEntry::MaterialEntry(const MaterialLibrary& library, , _uuid(modelUuid) {} -MaterialYamlEntry::MaterialYamlEntry(const MaterialLibrary& library, +MaterialYamlEntry::MaterialYamlEntry(std::shared_ptr library, const QString& modelName, const QString& dir, const QString& modelUuid, @@ -73,7 +78,82 @@ QString MaterialYamlEntry::yamlValue(const YAML::Node& node, return QString::fromStdString(defaultValue); } -void MaterialYamlEntry::addToTree(std::shared_ptr> materialMap) +std::shared_ptr MaterialYamlEntry::read2DArray(const YAML::Node& node) +{ + // Base::Console().Log("Read 2D Array\n"); + + auto array2d = std::make_shared(); + + if (node.size() == 2) { + // Get the default + Base::Quantity defaultValue = + Base::Quantity::parse(QString::fromStdString(node[0].as())); + array2d->setDefault(QVariant::fromValue(defaultValue)); + + auto yamlArray = node[1]; + for (std::size_t i = 0; i < yamlArray.size(); i++) { + auto yamlRow = yamlArray[i]; + + auto row = std::make_shared>(); + for (std::size_t j = 0; j < yamlRow.size(); j++) { + Base::Quantity q = + Base::Quantity::parse(QString::fromStdString(yamlRow[j].as())); + row->push_back(QVariant::fromValue(q)); + } + array2d->addRow(row); + } + } + + return array2d; +} + +std::shared_ptr MaterialYamlEntry::read3DArray(const YAML::Node& node) +{ + Base::Console().Log("Read 3D Array\n"); + + auto array3d = std::make_shared(); + + if (node.size() == 2) { + // Get the default + Base::Quantity defaultValue = + Base::Quantity::parse(QString::fromStdString(node[0].as())); + array3d->setDefault(QVariant::fromValue(defaultValue)); + + auto yamlArray = node[1]; + + for (std::size_t depth = 0; depth < yamlArray.size(); depth++) { + auto yamlDepth = yamlArray[depth]; + MaterialLoader::showYaml(yamlDepth); + for (auto it = yamlDepth.begin(); it != yamlDepth.end(); it++) { + MaterialLoader::showYaml(it->first); + MaterialLoader::showYaml(it->second); + + Base::Console().Log("Depth %d '%s'\n", depth, it->first.as().c_str()); + auto depthValue = + Base::Quantity::parse(QString::fromStdString(it->first.as())); + + array3d->addDepth(depth, depthValue); + + auto yamlTable = it->second; + for (std::size_t i = 0; i < yamlTable.size(); i++) { + auto yamlRow = yamlTable[i]; + + auto row = std::make_shared>(); + for (std::size_t j = 0; j < yamlRow.size(); j++) { + row->push_back(Base::Quantity::parse( + QString::fromStdString(yamlRow[j].as()))); + } + array3d->addRow(depth, row); + } + } + } + } + + return array3d; +} + +void MaterialYamlEntry::addToTree( + std::shared_ptr>> materialMap) { std::set exclude; exclude.insert(QString::fromStdString("General")); @@ -85,11 +165,14 @@ void MaterialYamlEntry::addToTree(std::shared_ptr> auto directory = getDirectory(); QString uuid = getUUID(); - QString authorAndLicense = yamlValue(yamlModel["General"], "AuthorAndLicense", ""); + QString author = yamlValue(yamlModel["General"], "Author", ""); + QString license = yamlValue(yamlModel["General"], "License", ""); QString description = yamlValue(yamlModel["General"], "Description", ""); - Material* finalModel = new Material(library, directory, uuid, name); - finalModel->setAuthorAndLicense(authorAndLicense); + std::shared_ptr finalModel = + std::make_shared(library, directory, uuid, name); + finalModel->setAuthor(author); + finalModel->setLicense(license); finalModel->setDescription(description); // Add inheritance list @@ -118,11 +201,34 @@ void MaterialYamlEntry::addToTree(std::shared_ptr> auto properties = yamlModel["Models"][modelName]; for (auto itp = properties.begin(); itp != properties.end(); itp++) { std::string propertyName = (itp->first).as(); - std::string propertyValue = (itp->second).as(); - if (finalModel->hasPhysicalProperty(QString::fromStdString(propertyName))) { - finalModel->setPhysicalValue(QString::fromStdString(propertyName), - QString::fromStdString(propertyValue)); + auto prop = + finalModel->getPhysicalProperty(QString::fromStdString(propertyName)); + auto type = prop->getType(); + + try { + if (type == MaterialValue::Array2D) { + auto array2d = read2DArray(itp->second); + finalModel->setPhysicalValue(QString::fromStdString(propertyName), + array2d); + } + else if (type == MaterialValue::Array3D) { + auto array3d = read3DArray(itp->second); + finalModel->setPhysicalValue(QString::fromStdString(propertyName), + array3d); + } + else { + std::string propertyValue = (itp->second).as(); + finalModel->setPhysicalValue(QString::fromStdString(propertyName), + QString::fromStdString(propertyValue)); + } + } + catch (const YAML::BadConversion& e) { + Base::Console().Log("Exception %s <%s:%s> - ignored\n", + e.what(), + name.toStdString().c_str(), + propertyName.c_str()); + } } else if (propertyName != "UUID") { Base::Console().Log("\tProperty '%s' is not described by any model. Ignored\n", @@ -147,11 +253,32 @@ void MaterialYamlEntry::addToTree(std::shared_ptr> auto properties = yamlModel["AppearanceModels"][modelName]; for (auto itp = properties.begin(); itp != properties.end(); itp++) { std::string propertyName = (itp->first).as(); - std::string propertyValue = (itp->second).as(); - if (finalModel->hasAppearanceProperty(QString::fromStdString(propertyName))) { - finalModel->setAppearanceValue(QString::fromStdString(propertyName), - QString::fromStdString(propertyValue)); + auto prop = + finalModel->getAppearanceProperty(QString::fromStdString(propertyName)); + auto type = prop->getType(); + + try { + if (type == MaterialValue::Array2D) { + auto array2d = read2DArray(itp->second); + finalModel->setAppearanceValue(QString::fromStdString(propertyName), + array2d); + } + else if (type == MaterialValue::Array3D) { + Base::Console().Log("Read 3D Array\n"); + } + else { + std::string propertyValue = (itp->second).as(); + finalModel->setAppearanceValue(QString::fromStdString(propertyName), + QString::fromStdString(propertyValue)); + } + } + catch (const YAML::BadConversion& e) { + Base::Console().Log("Exception %s <%s:%s> - ignored\n", + e.what(), + name.toStdString().c_str(), + propertyName.c_str()); + } } else if (propertyName != "UUID") { Base::Console().Log("\tProperty '%s' is not described by any model. Ignored\n", @@ -163,13 +290,15 @@ void MaterialYamlEntry::addToTree(std::shared_ptr> QString path = QDir(directory).absolutePath(); // Base::Console().Log("\tPath '%s'\n", path.toStdString().c_str()); - (*materialMap)[uuid] = library.addMaterial(*finalModel, path); + (*materialMap)[uuid] = library->addMaterial(finalModel, path); } -std::unique_ptr> MaterialLoader::_materialEntryMap = nullptr; +std::unique_ptr>> + MaterialLoader::_materialEntryMap = nullptr; -MaterialLoader::MaterialLoader(std::shared_ptr> materialMap, - std::shared_ptr> libraryList) +MaterialLoader::MaterialLoader( + std::shared_ptr>> materialMap, + std::shared_ptr>> libraryList) : _materialMap(materialMap) , _libraryList(libraryList) { @@ -182,25 +311,58 @@ MaterialLoader::MaterialLoader(std::shared_ptr> mat MaterialLoader::~MaterialLoader() {} -void MaterialLoader::addLibrary(MaterialLibrary* model) +void MaterialLoader::addLibrary(std::shared_ptr model) { _libraryList->push_back(model); } -MaterialEntry* MaterialLoader::getMaterialFromPath(MaterialLibrary& library, - const QString& path) const +std::shared_ptr +MaterialLoader::getMaterialFromYAML(std::shared_ptr library, + YAML::Node& yamlroot, + const QString& path) const { - MaterialEntry* model = nullptr; + std::shared_ptr model = nullptr; + + try { + const std::string uuid = yamlroot["General"]["UUID"].as(); + + // Always get the name from the filename + // QString name = QString::fromStdString(yamlroot["General"]["Name"].as()); + QFileInfo filepath(path); + QString name = + filepath.fileName().remove(QString::fromStdString(".FCMat"), Qt::CaseInsensitive); + + model = std::make_shared(library, + name, + path, + QString::fromStdString(uuid), + yamlroot); + // showYaml(yamlroot); + } + catch (YAML::Exception const& e) { + Base::Console().Error("YAML parsing error: '%s'\n", path.toStdString().c_str()); + Base::Console().Error("\t'%s'\n", e.what()); + showYaml(yamlroot); + } + + + return model; +} + +std::shared_ptr +MaterialLoader::getMaterialFromPath(std::shared_ptr library, + const QString& path) const +{ + std::shared_ptr model = nullptr; // Used for debugging - std::string uuid; std::string pathName = path.toStdString(); if (MaterialConfigLoader::isConfigStyle(path)) { - Base::Console().Log("Old format .FCMat file: '%s'\n", pathName.c_str()); - Material* material = MaterialConfigLoader::getMaterialFromPath(library, path); + // Base::Console().Log("Old format .FCMat file: '%s'\n", pathName.c_str()); + auto material = MaterialConfigLoader::getMaterialFromPath(library, path); if (material) { - (*_materialMap)[material->getUUID()] = library.addMaterial(*material, path); + (*_materialMap)[material->getUUID()] = library->addMaterial(material, path); } // Return the nullptr as there are no intermediate steps to take, such @@ -212,15 +374,7 @@ MaterialEntry* MaterialLoader::getMaterialFromPath(MaterialLibrary& library, try { yamlroot = YAML::LoadFile(pathName); - const std::string uuid = yamlroot["General"]["UUID"].as(); - // Always get the name from the filename - // QString name = QString::fromStdString(yamlroot["General"]["Name"].as()); - QFileInfo filepath(path); - QString name = - filepath.fileName().remove(QString::fromStdString(".FCMat"), Qt::CaseInsensitive); - - model = new MaterialYamlEntry(library, name, path, QString::fromStdString(uuid), yamlroot); - // showYaml(yamlroot); + model = getMaterialFromYAML(library, yamlroot, path); } catch (YAML::Exception const& e) { Base::Console().Error("YAML parsing error: '%s'\n", pathName.c_str()); @@ -242,7 +396,9 @@ void MaterialLoader::showYaml(const YAML::Node& yaml) } -void MaterialLoader::dereference(Material* material) +void MaterialLoader::dereference( + std::shared_ptr>> materialMap, + std::shared_ptr material) { // Avoid recursion if (material->getDereferenced()) { @@ -254,19 +410,20 @@ void MaterialLoader::dereference(Material* material) auto parentUUID = material->getParentUUID(); if (parentUUID.size() > 0) { - Material* parent; + std::shared_ptr parent; try { - parent = (*_materialMap)[parentUUID]; + parent = materialMap->at(parentUUID); } - catch (std::out_of_range&) { + catch (std::out_of_range& e) { Base::Console().Log( "Unable to apply inheritance for material '%s', parent '%s' not found.\n", material->getName().toStdString().c_str(), parentUUID.toStdString().c_str()); + return; } // Ensure the parent has been dereferenced - dereference(parent); + dereference(materialMap, parent); // Add physical models auto modelVector = parent->getPhysicalModels(); @@ -288,20 +445,20 @@ void MaterialLoader::dereference(Material* material) auto properties = parent->getPhysicalProperties(); for (auto itp = properties.begin(); itp != properties.end(); itp++) { auto name = itp->first; - auto property = static_cast(itp->second); + auto property = itp->second; - if (material->getPhysicalProperty(name).isNull()) { - material->getPhysicalProperty(name).setValue(property.getValue()); + if (material->getPhysicalProperty(name)->isNull()) { + material->getPhysicalProperty(name)->setValue(property->getValue()); } } properties = parent->getAppearanceProperties(); for (auto itp = properties.begin(); itp != properties.end(); itp++) { auto name = itp->first; - auto property = static_cast(itp->second); + auto property = itp->second; - if (material->getAppearanceProperty(name).isNull()) { - material->getAppearanceProperty(name).setValue(property.getValue()); + if (material->getAppearanceProperty(name)->isNull()) { + material->getAppearanceProperty(name)->setValue(property->getValue()); } } } @@ -309,13 +466,18 @@ void MaterialLoader::dereference(Material* material) material->markDereferenced(); } -void MaterialLoader::loadLibrary(MaterialLibrary& library) +void MaterialLoader::dereference(std::shared_ptr material) +{ + dereference(_materialMap, material); +} + +void MaterialLoader::loadLibrary(std::shared_ptr library) { if (_materialEntryMap == nullptr) { - _materialEntryMap = std::make_unique>(); + _materialEntryMap = std::make_unique>>(); } - QDirIterator it(library.getDirectory(), QDirIterator::Subdirectories); + QDirIterator it(library->getDirectory(), QDirIterator::Subdirectories); while (it.hasNext()) { auto pathname = it.next(); QFileInfo file(pathname); @@ -341,7 +503,7 @@ void MaterialLoader::loadLibraries() auto _libraryList = getMaterialLibraries(); if (_libraryList) { for (auto it = _libraryList->begin(); it != _libraryList->end(); it++) { - loadLibrary(**it); + loadLibrary(*it); } } @@ -350,7 +512,7 @@ void MaterialLoader::loadLibraries() } } -std::shared_ptr> MaterialLoader::getMaterialLibraries() +std::shared_ptr>> MaterialLoader::getMaterialLibraries() { auto param = App::GetApplication().GetParameterGroupByPath( "User parameter:BaseApp/Preferences/Mod/Material/Resources"); @@ -362,10 +524,11 @@ std::shared_ptr> MaterialLoader::getMaterialLibrarie if (useBuiltInMaterials) { QString resourceDir = QString::fromStdString(App::Application::getResourceDir() + "/Mod/Material/Resources/Materials"); - auto libData = new MaterialLibrary(QString::fromStdString("System"), - resourceDir, - QString::fromStdString(":/icons/freecad.svg"), - true); + auto libData = + std::make_shared(QString::fromStdString("System"), + resourceDir, + QString::fromStdString(":/icons/freecad.svg"), + true); _libraryList->push_back(libData); } @@ -382,10 +545,10 @@ std::shared_ptr> MaterialLoader::getMaterialLibrarie if (materialDir.length() > 0) { QDir dir(materialDir); if (dir.exists()) { - auto libData = new MaterialLibrary(moduleName, - materialDir, - materialIcon, - materialReadOnly); + auto libData = std::make_shared(moduleName, + materialDir, + materialIcon, + materialReadOnly); _libraryList->push_back(libData); } } @@ -397,12 +560,19 @@ std::shared_ptr> MaterialLoader::getMaterialLibrarie QString::fromStdString(App::Application::getUserAppDataDir() + "/Material"); if (!resourceDir.isEmpty()) { QDir materialDir(resourceDir); + if (!materialDir.exists()) { + // Try creating the user dir if it doesn't exist + if (!materialDir.mkpath(resourceDir)) { + Base::Console().Log("Unable to create user library '%s'\n", + resourceDir.toStdString().c_str()); + } + } if (materialDir.exists()) { - auto libData = - new MaterialLibrary(QString::fromStdString("User"), - resourceDir, - QString::fromStdString(":/icons/preferences-general.svg"), - false); + auto libData = std::make_shared( + QString::fromStdString("User"), + resourceDir, + QString::fromStdString(":/icons/preferences-general.svg"), + false); _libraryList->push_back(libData); } } @@ -413,10 +583,11 @@ std::shared_ptr> MaterialLoader::getMaterialLibrarie if (!resourceDir.isEmpty()) { QDir materialDir(resourceDir); if (materialDir.exists()) { - auto libData = new MaterialLibrary(QString::fromStdString("Custom"), - resourceDir, - QString::fromStdString(":/icons/user.svg"), - false); + auto libData = + std::make_shared(QString::fromStdString("Custom"), + resourceDir, + QString::fromStdString(":/icons/user.svg"), + false); _libraryList->push_back(libData); } } diff --git a/src/Mod/Material/App/MaterialLoader.h b/src/Mod/Material/App/MaterialLoader.h index f4bac08939..427d348630 100644 --- a/src/Mod/Material/App/MaterialLoader.h +++ b/src/Mod/Material/App/MaterialLoader.h @@ -22,6 +22,8 @@ #ifndef MATERIAL_MATERIALLOADER_H #define MATERIAL_MATERIALLOADER_H +#include + #include #include #include @@ -36,15 +38,16 @@ class MaterialEntry { public: MaterialEntry(); - explicit MaterialEntry(const MaterialLibrary& library, - const QString& modelName, - const QString& dir, - const QString& modelUuid); + MaterialEntry(std::shared_ptr library, + const QString& modelName, + const QString& dir, + const QString& modelUuid); virtual ~MaterialEntry() = default; - virtual void addToTree(std::shared_ptr> materialMap) = 0; + virtual void + addToTree(std::shared_ptr>> materialMap) = 0; - const MaterialLibrary& getLibrary() const + std::shared_ptr getLibrary() const { return _library; } @@ -62,7 +65,7 @@ public: } protected: - MaterialLibrary _library; + std::shared_ptr _library; QString _name; QString _directory; QString _uuid; @@ -71,14 +74,15 @@ protected: class MaterialYamlEntry: public MaterialEntry { public: - explicit MaterialYamlEntry(const MaterialLibrary& library, - const QString& modelName, - const QString& dir, - const QString& modelUuid, - const YAML::Node& modelData); + MaterialYamlEntry(std::shared_ptr library, + const QString& modelName, + const QString& dir, + const QString& modelUuid, + const YAML::Node& modelData); ~MaterialYamlEntry() override = default; - void addToTree(std::shared_ptr> materialMap) override; + void + addToTree(std::shared_ptr>> materialMap) override; const YAML::Node& getModel() const { @@ -94,6 +98,8 @@ private: QString yamlValue(const YAML::Node& node, const std::string& key, const std::string& defaultValue); + std::shared_ptr read2DArray(const YAML::Node& node); + std::shared_ptr read3DArray(const YAML::Node& node); YAML::Node _model; }; @@ -101,26 +107,34 @@ private: class MaterialLoader { public: - explicit MaterialLoader(std::shared_ptr> materialMap, - std::shared_ptr> libraryList); + MaterialLoader(std::shared_ptr>> materialMap, + std::shared_ptr>> libraryList); virtual ~MaterialLoader(); - std::shared_ptr> getMaterialLibraries(); + std::shared_ptr>> getMaterialLibraries(); static std::shared_ptr> getMaterialFolders(const MaterialLibrary& library); static void showYaml(const YAML::Node& yaml); + static void + dereference(std::shared_ptr>> materialMap, + std::shared_ptr material); + std::shared_ptr getMaterialFromYAML(std::shared_ptr library, + YAML::Node& yamlroot, + const QString& path) const; private: MaterialLoader(); - void addToTree(MaterialEntry* model); - void dereference(Material* material); - MaterialEntry* getMaterialFromPath(MaterialLibrary& library, const QString& path) const; - void addLibrary(MaterialLibrary* model); - void loadLibrary(MaterialLibrary& library); + void addToTree(std::shared_ptr model); + void dereference(std::shared_ptr material); + std::shared_ptr getMaterialFromPath(std::shared_ptr library, + const QString& path) const; + void addLibrary(std::shared_ptr model); + void loadLibrary(std::shared_ptr library); void loadLibraries(); - static std::unique_ptr> _materialEntryMap; - std::shared_ptr> _materialMap; - std::shared_ptr> _libraryList; + + static std::unique_ptr>> _materialEntryMap; + std::shared_ptr>> _materialMap; + std::shared_ptr>> _libraryList; }; } // namespace Materials diff --git a/src/Mod/Material/App/MaterialManager.cpp b/src/Mod/Material/App/MaterialManager.cpp index efbf45b0b9..f073b7a087 100644 --- a/src/Mod/Material/App/MaterialManager.cpp +++ b/src/Mod/Material/App/MaterialManager.cpp @@ -23,6 +23,7 @@ #ifndef _PreComp_ #endif +#include #include #include @@ -37,8 +38,10 @@ using namespace Materials; /* TRANSLATOR Material::Materials */ -std::shared_ptr> MaterialManager::_libraryList = nullptr; -std::shared_ptr> MaterialManager::_materialMap = nullptr; +std::shared_ptr>> MaterialManager::_libraryList = + nullptr; +std::shared_ptr>> MaterialManager::_materialMap = + nullptr; QMutex MaterialManager::_mutex; TYPESYSTEM_SOURCE(Materials::MaterialManager, Base::BaseClass) @@ -60,10 +63,10 @@ void MaterialManager::initLibraries() delete manager; - _materialMap = std::make_shared>(); + _materialMap = std::make_shared>>(); if (_libraryList == nullptr) { - _libraryList = std::make_shared>(); + _libraryList = std::make_shared>>(); } // Load the libraries @@ -71,23 +74,15 @@ void MaterialManager::initLibraries() } } -void MaterialManager::saveMaterial(MaterialLibrary* library, - Material& material, +void MaterialManager::saveMaterial(std::shared_ptr library, + std::shared_ptr material, const QString& path, - bool saveAsCopy) + bool overwrite, + bool saveAsCopy, + bool saveInherited) { - Material* newMaterial = library->saveMaterial(material, path, saveAsCopy); - - try { - Material* old = _materialMap->at(newMaterial->getUUID()); - if (old) { - delete old; - } - } - catch (const std::out_of_range&) { - } - - (*_materialMap)[material.getUUID()] = newMaterial; + auto newMaterial = library->saveMaterial(material, path, overwrite, saveAsCopy, saveInherited); + (*_materialMap)[newMaterial->getUUID()] = newMaterial; } bool MaterialManager::isMaterial(const fs::path& p) @@ -102,31 +97,43 @@ bool MaterialManager::isMaterial(const fs::path& p) return false; } -const Material& MaterialManager::getMaterial(const QString& uuid) const +bool MaterialManager::isMaterial(const QFileInfo& file) +{ + if (!file.isFile()) { + return false; + } + // check file extension + if (file.suffix() == QString::fromStdString("FCMat")) { + return true; + } + return false; +} + +std::shared_ptr MaterialManager::getMaterial(const QString& uuid) const { try { - return *(_materialMap->at(uuid)); + return _materialMap->at(uuid); } - catch (std::out_of_range&) { + catch (std::out_of_range& e) { throw MaterialNotFound(); } } -const Material& MaterialManager::getMaterialByPath(const QString& path) const +std::shared_ptr MaterialManager::getMaterialByPath(const QString& path) const { QString cleanPath = QDir::cleanPath(path); for (auto library : *_libraryList) { - Base::Console().Log("MaterialManager::getMaterialByPath() Checking library '%s'->'%s'\n", - library->getName().toStdString().c_str(), - library->getDirectory().toStdString().c_str()); + // Base::Console().Log("MaterialManager::getMaterialByPath() Checking library '%s'->'%s'\n", + // library->getName().toStdString().c_str(), + // library->getDirectory().toStdString().c_str()); if (cleanPath.startsWith(library->getDirectory())) { - Base::Console().Log("MaterialManager::getMaterialByPath() Library '%s'\n", - library->getDirectory().toStdString().c_str()); - Base::Console().Log("MaterialManager::getMaterialByPath() Path '%s'\n", - cleanPath.toStdString().c_str()); + // Base::Console().Log("MaterialManager::getMaterialByPath() Library '%s'\n", + // library->getDirectory().toStdString().c_str()); + // Base::Console().Log("MaterialManager::getMaterialByPath() Path '%s'\n", + // cleanPath.toStdString().c_str()); return library->getMaterialByPath(cleanPath); } } @@ -136,13 +143,51 @@ const Material& MaterialManager::getMaterialByPath(const QString& path) const throw MaterialNotFound(); } -const Material& MaterialManager::getMaterialByPath(const QString& path, const QString& lib) const +std::shared_ptr MaterialManager::getMaterialByPath(const QString& path, + const QString& lib) const { auto library = getLibrary(lib); // May throw LibraryNotFound return library->getMaterialByPath(path); // May throw MaterialNotFound } -MaterialLibrary* MaterialManager::getLibrary(const QString& name) const +bool MaterialManager::exists(const QString& uuid) const +{ + try { + auto material = getMaterial(uuid); + if (material.get() != nullptr) { + return true; + } + } + catch (const MaterialNotFound&) { + } + + return false; +} + +std::shared_ptr MaterialManager::getParent(std::shared_ptr material) +{ + if (material->getParentUUID().isEmpty()) { + throw MaterialNotFound(); + } + + return getMaterial(material->getParentUUID()); +} + +bool MaterialManager::exists(std::shared_ptr library, const QString& uuid) const +{ + try { + auto material = getMaterial(uuid); + if (material.get() != nullptr) { + return (*material->getLibrary() == *library); + } + } + catch (const MaterialNotFound&) { + } + + return false; +} + +std::shared_ptr MaterialManager::getLibrary(const QString& name) const { for (auto library : *_libraryList) { if (library->getName() == name) { @@ -153,13 +198,13 @@ MaterialLibrary* MaterialManager::getLibrary(const QString& name) const throw LibraryNotFound(); } -std::shared_ptr> MaterialManager::getMaterialLibraries() +std::shared_ptr>> MaterialManager::getMaterialLibraries() { if (_libraryList == nullptr) { if (_materialMap == nullptr) { - _materialMap = std::make_shared>(); + _materialMap = std::make_shared>>(); } - _libraryList = std::make_shared>(); + _libraryList = std::make_shared>>(); // Load the libraries MaterialLoader loader(_materialMap, _libraryList); @@ -167,87 +212,21 @@ std::shared_ptr> MaterialManager::getMaterialLibrari return _libraryList; } -std::shared_ptr> -MaterialManager::getMaterialTree(const MaterialLibrary& library) const -{ - std::shared_ptr> materialTree = - std::make_shared>(); - - for (auto it = _materialMap->begin(); it != _materialMap->end(); it++) { - auto filename = it->first; - auto material = it->second; - - if (material->getLibrary() == library) { - fs::path path = material->getDirectory().toStdString(); - - // Start at the root - auto node = materialTree; - for (auto itp = path.begin(); itp != path.end(); itp++) { - if (QString::fromStdString(itp->string()) - .endsWith(QString::fromStdString(".FCMat"))) { - MaterialTreeNode* child = new MaterialTreeNode(); - child->setData(material); - (*node)[QString::fromStdString(itp->string())] = child; - } - else { - // Add the folder only if it's not already there - QString folderName = QString::fromStdString(itp->string()); - std::shared_ptr> mapPtr; - if (node->count(folderName) == 0) { - mapPtr = std::make_shared>(); - MaterialTreeNode* child = new MaterialTreeNode(); - child->setFolder(mapPtr); - (*node)[folderName] = child; - node = mapPtr; - } - else { - node = (*node)[folderName]->getFolder(); - } - } - } - } - } - - auto folderList = getMaterialFolders(library); - for (auto folder : *folderList) { - fs::path path = folder.toStdString(); - - // Start at the root - auto node = materialTree; - for (auto itp = path.begin(); itp != path.end(); itp++) { - // Add the folder only if it's not already there - QString folderName = QString::fromStdString(itp->string()); - if (node->count(folderName) == 0) { - std::shared_ptr> mapPtr = - std::make_shared>(); - MaterialTreeNode* child = new MaterialTreeNode(); - child->setFolder(mapPtr); - (*node)[folderName] = child; - node = mapPtr; - } - else { - node = (*node)[folderName]->getFolder(); - } - } - } - - return materialTree; -} - std::shared_ptr> -MaterialManager::getMaterialFolders(const MaterialLibrary& library) const +MaterialManager::getMaterialFolders(std::shared_ptr library) const { - return MaterialLoader::getMaterialFolders(library); + return MaterialLoader::getMaterialFolders(*library); } -std::shared_ptr> MaterialManager::materialsWithModel(QString uuid) +std::shared_ptr>> +MaterialManager::materialsWithModel(QString uuid) { - std::shared_ptr> dict = - std::make_shared>(); + std::shared_ptr>> dict = + std::make_shared>>(); for (auto it = _materialMap->begin(); it != _materialMap->end(); it++) { QString key = it->first; - Material* material = it->second; + auto material = it->second; if (material->hasModel(uuid)) { (*dict)[key] = material; @@ -257,15 +236,15 @@ std::shared_ptr> MaterialManager::materialsWithMode return dict; } -std::shared_ptr> +std::shared_ptr>> MaterialManager::materialsWithModelComplete(QString uuid) { - std::shared_ptr> dict = - std::make_shared>(); + std::shared_ptr>> dict = + std::make_shared>>(); for (auto it = _materialMap->begin(); it != _materialMap->end(); it++) { QString key = it->first; - Material* material = it->second; + auto material = it->second; if (material->isModelComplete(uuid)) { (*dict)[key] = material; @@ -274,3 +253,8 @@ MaterialManager::materialsWithModelComplete(QString uuid) return dict; } + +void MaterialManager::dereference(std::shared_ptr material) +{ + MaterialLoader::dereference(_materialMap, material); +} diff --git a/src/Mod/Material/App/MaterialManager.h b/src/Mod/Material/App/MaterialManager.h index 03c423326d..af4261cd9f 100644 --- a/src/Mod/Material/App/MaterialManager.h +++ b/src/Mod/Material/App/MaterialManager.h @@ -22,61 +22,90 @@ #ifndef MATERIAL_MATERIALMANAGER_H #define MATERIAL_MATERIALMANAGER_H -#include +#include #include #include +#include + #include "FolderTree.h" #include "Materials.h" +#include "MaterialLibrary.h" + namespace fs = boost::filesystem; namespace Materials { -typedef FolderTreeNode MaterialTreeNode; - class MaterialsExport MaterialManager: public Base::BaseClass { - TYPESYSTEM_HEADER_WITH_OVERRIDE(); + TYPESYSTEM_HEADER(); public: MaterialManager(); ~MaterialManager() override = default; - std::shared_ptr> getMaterials() + std::shared_ptr>> getMaterials() { return _materialMap; } - const Material& getMaterial(const QString& uuid) const; - const Material& getMaterialByPath(const QString& path) const; - const Material& getMaterialByPath(const QString& path, const QString& library) const; - MaterialLibrary* getLibrary(const QString& name) const; + std::shared_ptr getMaterial(const QString& uuid) const; + std::shared_ptr getMaterialByPath(const QString& path) const; + std::shared_ptr getMaterialByPath(const QString& path, const QString& library) const; + std::shared_ptr getParent(std::shared_ptr material); + std::shared_ptr getLibrary(const QString& name) const; + bool exists(const QString& uuid) const; + bool exists(std::shared_ptr library, const QString& uuid) const; // Library management - static std::shared_ptr> getMaterialLibraries(); - std::shared_ptr> - getMaterialTree(const MaterialLibrary& library) const; - std::shared_ptr> getMaterialFolders(const MaterialLibrary& library) const; - void createPath(MaterialLibrary* library, const QString& path) + static std::shared_ptr>> getMaterialLibraries(); + std::shared_ptr>> + getMaterialTree(std::shared_ptr library) const { - library->createPath(path); + return library->getMaterialTree(); } - void saveMaterial(MaterialLibrary* library, - Material& material, + std::shared_ptr> + getMaterialFolders(std::shared_ptr library) const; + void createFolder(std::shared_ptr library, const QString& path) + { + library->createFolder(path); + } + void renameFolder(std::shared_ptr library, + const QString& oldPath, + const QString& newPath) + { + library->renameFolder(oldPath, newPath); + } + void deleteRecursive(std::shared_ptr library, const QString& path) + { + library->deleteRecursive(path); + } + void remove(const QString& uuid) + { + _materialMap->erase(uuid); + } + + void saveMaterial(std::shared_ptr library, + std::shared_ptr material, const QString& path, - bool saveAsCopy = true); + bool overwrite, + bool saveAsCopy, + bool saveInherited); static bool isMaterial(const fs::path& p); + static bool isMaterial(const QFileInfo& file); - std::shared_ptr> materialsWithModel(QString uuid); - std::shared_ptr> materialsWithModelComplete(QString uuid); + std::shared_ptr>> materialsWithModel(QString uuid); + std::shared_ptr>> + materialsWithModelComplete(QString uuid); + void dereference(std::shared_ptr material); private: - static std::shared_ptr> _libraryList; - static std::shared_ptr> _materialMap; + static std::shared_ptr>> _libraryList; + static std::shared_ptr>> _materialMap; static QMutex _mutex; static void initLibraries(); diff --git a/src/Mod/Material/App/MaterialManagerPyImpl.cpp b/src/Mod/Material/App/MaterialManagerPyImpl.cpp index 733b2cba2c..560e22c9e3 100644 --- a/src/Mod/Material/App/MaterialManagerPyImpl.cpp +++ b/src/Mod/Material/App/MaterialManagerPyImpl.cpp @@ -21,10 +21,6 @@ #include "PreCompiled.h" -#ifndef _PreComp_ -#include -#endif - #include "Exceptions.h" #include "MaterialManager.h" #include "MaterialManagerPy.h" @@ -64,9 +60,8 @@ PyObject* MaterialManagerPy::getMaterial(PyObject* args) } try { - const Material& material = - getMaterialManagerPtr()->getMaterial(QString::fromStdString(uuid)); - return new MaterialPy(new Material(material)); + auto material = getMaterialManagerPtr()->getMaterial(QString::fromStdString(uuid)); + return new MaterialPy(new Material(*material)); } catch (const MaterialNotFound&) { PyErr_SetString(PyExc_LookupError, "Material not found"); @@ -85,9 +80,9 @@ PyObject* MaterialManagerPy::getMaterialByPath(PyObject* args) QString libPath(QString::fromStdString(lib)); if (!libPath.isEmpty()) { try { - const Material& material = + auto material = getMaterialManagerPtr()->getMaterialByPath(QString::fromStdString(path), libPath); - return new MaterialPy(new Material(material)); + return new MaterialPy(new Material(*material)); } catch (const MaterialNotFound&) { PyErr_SetString(PyExc_LookupError, "Material not found"); @@ -100,9 +95,8 @@ PyObject* MaterialManagerPy::getMaterialByPath(PyObject* args) } try { - const Material& material = - getMaterialManagerPtr()->getMaterialByPath(QString::fromStdString(path)); - return new MaterialPy(new Material(material)); + auto material = getMaterialManagerPtr()->getMaterialByPath(QString::fromStdString(path)); + return new MaterialPy(new Material(*material)); } catch (const MaterialNotFound&) { PyErr_SetString(PyExc_LookupError, "Material not found"); @@ -116,7 +110,7 @@ Py::List MaterialManagerPy::getMaterialLibraries() const Py::List list; for (auto it = libraries->begin(); it != libraries->end(); it++) { - MaterialLibrary* lib = *it; + auto lib = *it; Py::Tuple libTuple(3); libTuple.setItem(0, Py::String(lib->getName().toStdString())); libTuple.setItem(1, Py::String(lib->getDirectoryPath().toStdString())); @@ -136,7 +130,7 @@ Py::Dict MaterialManagerPy::getMaterials() const for (auto it = materials->begin(); it != materials->end(); it++) { QString key = it->first; - Material* material = it->second; + auto material = it->second; PyObject* materialPy = new MaterialPy(new Material(*material)); dict.setItem(Py::String(key.toStdString()), Py::Object(materialPy, true)); @@ -168,7 +162,7 @@ PyObject* MaterialManagerPy::materialsWithModel(PyObject* args) for (auto it = materials->begin(); it != materials->end(); it++) { QString key = it->first; - Material* material = it->second; + auto material = it->second; PyObject* materialPy = new MaterialPy(new Material(*material)); PyDict_SetItem(dict, PyUnicode_FromString(key.toStdString().c_str()), materialPy); @@ -190,7 +184,7 @@ PyObject* MaterialManagerPy::materialsWithModelComplete(PyObject* args) for (auto it = materials->begin(); it != materials->end(); it++) { QString key = it->first; - Material* material = it->second; + auto material = it->second; PyObject* materialPy = new MaterialPy(new Material(*material)); PyDict_SetItem(dict, PyUnicode_FromString(key.toStdString().c_str()), materialPy); diff --git a/src/Mod/Material/App/MaterialPy.xml b/src/Mod/Material/App/MaterialPy.xml index d2ffb43da2..e16a95f804 100644 --- a/src/Mod/Material/App/MaterialPy.xml +++ b/src/Mod/Material/App/MaterialPy.xml @@ -77,10 +77,22 @@ - Author and license information. + deprecated -- Author and license information. + + + Author information. + + + + + + License information. + + + List of implemented models. diff --git a/src/Mod/Material/App/MaterialPyImpl.cpp b/src/Mod/Material/App/MaterialPyImpl.cpp index 8248f2951f..49d3668e99 100644 --- a/src/Mod/Material/App/MaterialPyImpl.cpp +++ b/src/Mod/Material/App/MaterialPyImpl.cpp @@ -21,20 +21,18 @@ #include "PreCompiled.h" -#ifndef _PreComp_ -#include -#endif - #include #include #include #include -#include "Exceptions.h" -#include "MaterialPy.h" #include "Materials.h" +#include "Exceptions.h" +#include "MaterialLibrary.h" +#include "MaterialPy.h" + #include "MaterialPy.cpp" using namespace Materials; @@ -49,11 +47,11 @@ std::string MaterialPy::representation() const str << "), UUID=("; str << ptr->getUUID().toStdString(); str << "), Library Name=("; - str << ptr->getLibrary().getName().toStdString(); + str << ptr->getLibrary()->getName().toStdString(); str << "), Library Root=("; - str << ptr->getLibrary().getDirectoryPath().toStdString(); + str << ptr->getLibrary()->getDirectoryPath().toStdString(); str << "), Library Icon=("; - str << ptr->getLibrary().getIconPath().toStdString(); + str << ptr->getLibrary()->getIconPath().toStdString(); str << "), Directory=("; str << ptr->getDirectory().toStdString(); // str << "), URL=("; @@ -93,17 +91,17 @@ int MaterialPy::PyInit(PyObject* /*args*/, PyObject* /*kwd*/) Py::String MaterialPy::getLibraryName() const { - return Py::String(getMaterialPtr()->getLibrary().getName().toStdString()); + return Py::String(getMaterialPtr()->getLibrary()->getName().toStdString()); } Py::String MaterialPy::getLibraryRoot() const { - return Py::String(getMaterialPtr()->getLibrary().getDirectoryPath().toStdString()); + return Py::String(getMaterialPtr()->getLibrary()->getDirectoryPath().toStdString()); } Py::String MaterialPy::getLibraryIcon() const { - return Py::String(getMaterialPtr()->getLibrary().getIconPath().toStdString()); + return Py::String(getMaterialPtr()->getLibrary()->getIconPath().toStdString()); } Py::String MaterialPy::getName() const @@ -146,15 +144,23 @@ Py::String MaterialPy::getAuthorAndLicense() const return Py::String(getMaterialPtr()->getAuthorAndLicense().toStdString()); } +Py::String MaterialPy::getAuthor() const +{ + return Py::String(getMaterialPtr()->getAuthor().toStdString()); +} + +Py::String MaterialPy::getLicense() const +{ + return Py::String(getMaterialPtr()->getLicense().toStdString()); +} + Py::List MaterialPy::getPhysicalModels() const { - const std::vector* models = getMaterialPtr()->getPhysicalModels(); + auto models = getMaterialPtr()->getPhysicalModels(); Py::List list; for (auto it = models->begin(); it != models->end(); it++) { - QString uuid = *it; - - list.append(Py::String(uuid.toStdString())); + list.append(Py::String(it->toStdString())); } return list; @@ -162,13 +168,11 @@ Py::List MaterialPy::getPhysicalModels() const Py::List MaterialPy::getAppearanceModels() const { - const std::vector* models = getMaterialPtr()->getAppearanceModels(); + auto models = getMaterialPtr()->getAppearanceModels(); Py::List list; for (auto it = models->begin(); it != models->end(); it++) { - QString uuid = *it; - - list.append(Py::String(uuid.toStdString())); + list.append(Py::String(it->toStdString())); } return list; @@ -176,13 +180,11 @@ Py::List MaterialPy::getAppearanceModels() const Py::List MaterialPy::getTags() const { - const std::list& tags = getMaterialPtr()->getTags(); + auto& tags = getMaterialPtr()->getTags(); Py::List list; for (auto it = tags.begin(); it != tags.end(); it++) { - QString uuid = *it; - - list.append(Py::String(uuid.toStdString())); + list.append(Py::String(it->toStdString())); } return list; @@ -272,6 +274,8 @@ Py::Dict MaterialPy::getProperties() const dict.setItem(Py::String("CardName"), Py::String(getMaterialPtr()->getName().toStdString())); dict.setItem(Py::String("AuthorAndLicense"), Py::String(getMaterialPtr()->getAuthorAndLicense().toStdString())); + dict.setItem(Py::String("Author"), Py::String(getMaterialPtr()->getAuthor().toStdString())); + dict.setItem(Py::String("License"), Py::String(getMaterialPtr()->getLicense().toStdString())); dict.setItem(Py::String("Name"), Py::String(getMaterialPtr()->getName().toStdString())); dict.setItem(Py::String("Description"), Py::String(getMaterialPtr()->getDescription().toStdString())); @@ -282,10 +286,10 @@ Py::Dict MaterialPy::getProperties() const auto properties = getMaterialPtr()->getPhysicalProperties(); for (auto it = properties.begin(); it != properties.end(); it++) { QString key = it->first; - MaterialProperty& materialProperty = it->second; + auto materialProperty = it->second; - if (!materialProperty.isNull()) { - auto value = materialProperty.getString(); + if (!materialProperty->isNull()) { + auto value = materialProperty->getString(); dict.setItem(Py::String(key.toStdString()), Py::String(value.toStdString())); } } @@ -293,10 +297,10 @@ Py::Dict MaterialPy::getProperties() const properties = getMaterialPtr()->getAppearanceProperties(); for (auto it = properties.begin(); it != properties.end(); it++) { QString key = it->first; - MaterialProperty& materialProperty = it->second; + auto materialProperty = it->second; - if (!materialProperty.isNull()) { - auto value = materialProperty.getString(); + if (!materialProperty->isNull()) { + auto value = materialProperty->getString(); dict.setItem(Py::String(key.toStdString()), Py::String(value.toStdString())); } } @@ -311,10 +315,10 @@ Py::Dict MaterialPy::getPhysicalProperties() const auto properties = getMaterialPtr()->getPhysicalProperties(); for (auto it = properties.begin(); it != properties.end(); it++) { QString key = it->first; - MaterialProperty& materialProperty = it->second; + auto materialProperty = it->second; - if (!materialProperty.isNull()) { - auto value = materialProperty.getString(); + if (!materialProperty->isNull()) { + auto value = materialProperty->getString(); dict.setItem(Py::String(key.toStdString()), Py::String(value.toStdString())); } } @@ -329,10 +333,10 @@ Py::Dict MaterialPy::getAppearanceProperties() const auto properties = getMaterialPtr()->getAppearanceProperties(); for (auto it = properties.begin(); it != properties.end(); it++) { QString key = it->first; - MaterialProperty& materialProperty = it->second; + auto materialProperty = it->second; - if (!materialProperty.isNull()) { - auto value = materialProperty.getString(); + if (!materialProperty->isNull()) { + auto value = materialProperty->getString(); dict.setItem(Py::String(key.toStdString()), Py::String(value.toStdString())); } } @@ -346,7 +350,7 @@ static PyObject* _pyObjectFromVariant(const QVariant& value) return new PyObject(); } - if (value.userType() == qMetaTypeId()) { + if (value.userType() == QMetaType::type("Base::Quantity")) { return new Base::QuantityPy(new Base::Quantity(value.value())); } else if (value.userType() == QMetaType::Double) { diff --git a/src/Mod/Material/App/MaterialValue.cpp b/src/Mod/Material/App/MaterialValue.cpp index 76805d369b..3229424696 100644 --- a/src/Mod/Material/App/MaterialValue.cpp +++ b/src/Mod/Material/App/MaterialValue.cpp @@ -23,7 +23,11 @@ #ifndef _PreComp_ #endif +#include + #include +#include +#include #include "Exceptions.h" #include "MaterialValue.h" @@ -33,29 +37,203 @@ using namespace Materials; /* TRANSLATOR Material::MaterialValue */ +TYPESYSTEM_SOURCE(Materials::MaterialValue, Base::BaseClass) + MaterialValue::MaterialValue() : _valueType(None) +{ + this->setInitialValue(None); +} + +MaterialValue::MaterialValue(const MaterialValue& other) + : _valueType(other._valueType) + , _value(other._value) {} MaterialValue::MaterialValue(ValueType type) : _valueType(type) -{} +{ + this->setInitialValue(None); +} + +MaterialValue::MaterialValue(ValueType type, ValueType inherited) + : _valueType(type) +{ + this->setInitialValue(inherited); +} + +MaterialValue& MaterialValue::operator=(const MaterialValue& other) +{ + if (this == &other) { + return *this; + } + + _valueType = other._valueType; + _value = other._value; + + return *this; +} + +bool MaterialValue::operator==(const MaterialValue& other) const +{ + if (this == &other) { + return true; + } + + return (_valueType == other._valueType) && (_value == other._value); +} + +void MaterialValue::setInitialValue(ValueType inherited) +{ + if (_valueType == String) { + _value = QVariant(static_cast(QMetaType::QString)); + } + else if (_valueType == Boolean) { + _value = QVariant(static_cast(QMetaType::Bool)); + } + else if (_valueType == Integer) { + _value = QVariant(static_cast(QMetaType::Int)); + } + else if (_valueType == Float) { + _value = QVariant(static_cast(QMetaType::Float)); + } + else if (_valueType == URL) { + _value = QVariant(static_cast(QMetaType::QString)); + } + else if (_valueType == Quantity) { + Base::Quantity q; + q.setInvalid(); + _value = QVariant::fromValue(q); + } + else if (_valueType == Color) { + _value = QVariant(static_cast(QMetaType::QString)); + } + else if (_valueType == File) { + _value = QVariant(static_cast(QMetaType::QString)); + } + else if (_valueType == Image) { + _value = QVariant(static_cast(QMetaType::QString)); + } + else if (_valueType == List) { + _value = QVariant(static_cast(QMetaType::QString)); + } + else if (_valueType == Array2D) { + if (_valueType != inherited) { + throw InvalidMaterialType("Initializing a regular material value as a 2D Array"); + } + + _value = QVariant(); // Uninitialized default value + } + else if (_valueType == Array3D) { + if (_valueType != inherited) { + throw InvalidMaterialType("Initializing a regular material value as a 3D Array"); + } + + _value = QVariant(); // Uninitialized default value + } + else { + // Default is to set the type to None and leave the variant uninitialized + _valueType = None; + _value = QVariant(); + } +} + +bool MaterialValue::isNull() const +{ + if (_value.isNull()) { + return true; + } + + if (_valueType == Quantity) { + return !_value.value().isValid(); + } + + return false; +} + +const QString MaterialValue::getYAMLString() const +{ + QString yaml = QString::fromStdString("\""); + if (!isNull()) { + if (getType() == MaterialValue::Quantity) { + Base::Quantity quantity = getValue().value(); + yaml += quantity.getUserString(); + } + else if (getType() == MaterialValue::Float) { + auto value = getValue(); + if (!value.isNull()) { + yaml += QString(QString::fromStdString("%1")).arg(value.toFloat(), 0, 'g', 6); + } + } + else { + yaml += getValue().toString(); + } + } + yaml += QString::fromStdString("\""); + return yaml; +} //=== +TYPESYSTEM_SOURCE(Materials::Material2DArray, Materials::MaterialValue) + Material2DArray::Material2DArray() - : MaterialValue(Array2D) + : MaterialValue(Array2D, Array2D) , _defaultSet(false) -{} - -MaterialValue Material2DArray::getDefault() const { - MaterialValue ret(_valueType); - ret.setValue(_value); - return ret; + // Initialize separatelt to prevent recursion + // setType(Array2D); } -const std::vector* Material2DArray::getRow(int row) const +Material2DArray::Material2DArray(const Material2DArray& other) + : MaterialValue(other) + , _defaultSet(other._defaultSet) +{ + deepCopy(other); +} + +Material2DArray& Material2DArray::operator=(const Material2DArray& other) +{ + if (this == &other) { + return *this; + } + + MaterialValue::operator=(other); + _defaultSet = other._defaultSet; + + deepCopy(other); + + return *this; +} + +void Material2DArray::deepCopy(const Material2DArray& other) +{ + // Deep copy + for (auto row : other._rows) { + std::vector v; + for (auto col : *row) { + QVariant newVariant(col); + v.push_back(newVariant); + } + addRow(std::make_shared>(v)); + } +} + +bool Material2DArray::isNull() const +{ + return rows() <= 0; +} + +const QVariant Material2DArray::getDefault() const +{ + if (_defaultSet) { + return _value; + } + + return QVariant(); +} + +std::shared_ptr> Material2DArray::getRow(int row) const { try { return _rows.at(row); @@ -65,7 +243,7 @@ const std::vector* Material2DArray::getRow(int row) const } } -std::vector* Material2DArray::getRow(int row) +std::shared_ptr> Material2DArray::getRow(int row) { try { return _rows.at(row); @@ -75,12 +253,12 @@ std::vector* Material2DArray::getRow(int row) } } -void Material2DArray::addRow(std::vector* row) +void Material2DArray::addRow(std::shared_ptr> row) { _rows.push_back(row); } -void Material2DArray::insertRow(int index, std::vector* row) +void Material2DArray::insertRow(int index, std::shared_ptr> row) { _rows.insert(_rows.begin() + index, row); } @@ -99,7 +277,7 @@ void Material2DArray::setValue(int row, int column, const QVariant& value) throw InvalidIndex(); } - std::vector* val = getRow(row); + auto val = getRow(row); try { val->at(column) = value; } @@ -124,10 +302,10 @@ const QVariant Material2DArray::getValue(int row, int column) const } } -void Material2DArray::dumpRow(const std::vector& row) const +void Material2DArray::dumpRow(std::shared_ptr> row) const { Base::Console().Log("row: "); - for (auto column : row) { + for (auto column : *row) { Base::Console().Log("'%s' ", column.toString().toStdString().c_str()); } Base::Console().Log("\n"); @@ -136,107 +314,389 @@ void Material2DArray::dumpRow(const std::vector& row) const void Material2DArray::dump() const { for (auto row : _rows) { - dumpRow(*row); + dumpRow(row); } } +const QString Material2DArray::getYAMLString() const +{ + if (isNull()) { + return QString(); + } + + // Set the correct indentation. 9 chars in this case + QString pad; + pad.fill(QChar::fromLatin1(' '), 9); + + // Save the default value + QString yaml = QString::fromStdString("\n - \""); + Base::Quantity quantity = getDefault().value(); + yaml += quantity.getUserString(); + yaml += QString::fromStdString("\"\n"); + + // Next the array contents + yaml += QString::fromStdString(" - ["); + bool firstRow = true; + for (auto row : _rows) { + if (!firstRow) { + // Each row is on its own line, padded for correct indentation + yaml += QString::fromStdString(",\n") + pad; + } + else { + firstRow = false; + } + yaml += QString::fromStdString("["); + + bool first = true; + for (auto column : *row) { + if (!first) { + // TODO: Fix for arrays with too many columns to fit on a single line + yaml += QString::fromStdString(", "); + } + else { + first = false; + } + yaml += QString::fromStdString("\""); + Base::Quantity quantity = column.value(); + yaml += quantity.getUserString(); + yaml += QString::fromStdString("\""); + } + + yaml += QString::fromStdString("]"); + } + yaml += QString::fromStdString("]"); + return yaml; +} + //=== +TYPESYSTEM_SOURCE(Materials::Material3DArray, Materials::MaterialValue) + Material3DArray::Material3DArray() - : MaterialValue(Array3D) + : MaterialValue(Array3D, Array3D) , _defaultSet(false) -{} - -MaterialValue Material3DArray::getDefault() const + , _currentDepth(0) { - MaterialValue ret(_valueType); - ret.setValue(_value); - return ret; + // Initialize separatelt to prevent recursion + // setType(Array3D); } -const std::vector*>& Material3DArray::getTable(const QVariant& depth) const +bool Material3DArray::isNull() const +{ + return depth() <= 0; +} + +const QVariant Material3DArray::getDefault() const +{ + return _value; +} + +const std::shared_ptr>>>& +Material3DArray::getTable(const Base::Quantity& depth) const +{ + for (auto it = _rowMap.begin(); it != _rowMap.end(); it++) { + if (std::get<0>(*it) == depth) { + return std::get<1>(*it); + } + } + + throw InvalidDepth(); +} + +const std::shared_ptr>>>& +Material3DArray::getTable(int depthIndex) const { try { - return _rowMap.at(depth); + return std::get<1>(_rowMap.at(depthIndex)); + } + catch (std::out_of_range const&) { + throw InvalidDepth(); + } +} + +const std::shared_ptr> Material3DArray::getRow(int depth, int row) const +{ + try { + return getTable(depth)->at(row); } catch (std::out_of_range const&) { throw InvalidRow(); } } -const std::vector& Material3DArray::getRow(const QVariant& depth, int row) const +std::shared_ptr> Material3DArray::getRow(int row) const +{ + // Check if we can convert otherwise throw error + return getRow(_currentDepth, row); +} + +std::shared_ptr> Material3DArray::getRow(int depth, int row) { try { - return *(_rowMap.at(depth).at(row)); + return getTable(depth)->at(row); } catch (std::out_of_range const&) { throw InvalidRow(); } } -const std::vector& Material3DArray::getRow(int row) const +std::shared_ptr> Material3DArray::getRow(int row) { - return getRow(getDefault().getValue().toString(), row); + return getRow(_currentDepth, row); } -std::vector& Material3DArray::getRow(const QVariant& depth, int row) +void Material3DArray::addRow(int depth, std::shared_ptr> row) { try { - return *(_rowMap.at(depth).at(row)); + getTable(depth)->push_back(row); } catch (std::out_of_range const&) { throw InvalidRow(); } } -std::vector& Material3DArray::getRow(int row) +void Material3DArray::addRow(std::shared_ptr> row) { - return getRow(getDefault().getValue().toString(), row); + addRow(_currentDepth, row); } -void Material3DArray::addRow(const QVariant& depth, std::vector* row) +int Material3DArray::addDepth(int depth, Base::Quantity value) { - _rowMap[depth].push_back(row); + if (depth == this->depth()) { + // Append to the end + return addDepth(value); + } + else if (depth > this->depth()) { + throw InvalidDepth(); + } + auto rowVector = std::make_shared>>>(); + auto entry = std::make_pair(value, rowVector); + _rowMap.insert(_rowMap.begin() + depth, entry); + + return depth; } -void Material3DArray::deleteRow(const QVariant& depth, int row) +int Material3DArray::addDepth(Base::Quantity value) { - Q_UNUSED(depth) - Q_UNUSED(row) + auto rowVector = std::make_shared>>>(); + auto entry = std::make_pair(value, rowVector); + _rowMap.push_back(entry); + + return depth() - 1; +} + +void Material3DArray::deleteDepth(int depth) +{ + deleteRows(depth); // This may throw an InvalidDepth + _rowMap.erase(_rowMap.begin() + depth); +} + +void Material3DArray::insertRow(int depth, + int row, + std::shared_ptr> rowData) +{ + try { + auto table = getTable(depth); + // auto it = table->begin(); + // std::advance(it, row); + table->insert(table->begin() + row, rowData); + } + catch (std::out_of_range const&) { + throw InvalidRow(); + } +} + +void Material3DArray::insertRow(int row, std::shared_ptr> rowData) +{ + insertRow(_currentDepth, row, rowData); +} + +void Material3DArray::deleteRow(int depth, int row) +{ + auto table = getTable(depth); + if (static_cast(row) >= table->size() || row < 0) { + throw InvalidRow(); + } + table->erase(table->begin() + row); +} + +void Material3DArray::deleteRow(int row) +{ + deleteRow(_currentDepth, row); } void Material3DArray::deleteRows(int depth) { - Q_UNUSED(depth) + auto table = getTable(depth); + table->clear(); } -void Material3DArray::setValue(const QVariant& depth, int row, int column, const QVariant& value) +void Material3DArray::deleteRows() { - Q_UNUSED(depth) - Q_UNUSED(row) - Q_UNUSED(column) - Q_UNUSED(value) + deleteRows(_currentDepth); } -void Material3DArray::setValue(int row, int column, const QVariant& value) +int Material3DArray::rows(int depth) const { - Q_UNUSED(row) - Q_UNUSED(column) - Q_UNUSED(value) + if (depth < 0 || (depth == 0 && this->depth() == 0)) { + return 0; + } + + return getTable(depth)->size(); } -const QVariant Material3DArray::getValue(const QVariant& depth, int row, int column) +int Material3DArray::columns(int depth) const +{ + if (depth < 0 || (depth == 0 && this->depth() == 0)) { + return 0; + } + if (rows() == 0) { + return 0; + } + + return getTable(depth)->at(0)->size(); +} + +void Material3DArray::setValue(int depth, int row, int column, const Base::Quantity& value) { auto val = getRow(depth, row); try { - return val.at(column); + val->at(column) = value; } catch (std::out_of_range const&) { throw InvalidColumn(); } } -const QVariant Material3DArray::getValue(int row, int column) +void Material3DArray::setValue(int row, int column, const Base::Quantity& value) { - return getValue(getDefault().getValue().toString(), row, column); + setValue(_currentDepth, row, column, value); +} + +void Material3DArray::setDepthValue(int depth, const Base::Quantity& value) +{ + try { + auto oldRows = getTable(depth); + _rowMap.at(depth) = std::pair(value, oldRows); + } + catch (std::out_of_range const&) { + throw InvalidRow(); + } +} + +void Material3DArray::setDepthValue(const Base::Quantity& value) +{ + setDepthValue(_currentDepth, value); +} + + +const Base::Quantity Material3DArray::getValue(int depth, int row, int column) const +{ + auto val = getRow(depth, row); + try { + return val->at(column); + } + catch (std::out_of_range const&) { + throw InvalidColumn(); + } +} + +const Base::Quantity Material3DArray::getValue(int row, int column) const +{ + return getValue(_currentDepth, row, column); +} + +const Base::Quantity Material3DArray::getDepthValue(int depth) const +{ + try { + return std::get<0>(_rowMap.at(depth)); + } + catch (std::out_of_range const&) { + throw InvalidRow(); + } +} + +int Material3DArray::currentDepth() const +{ + return _currentDepth; +} + +void Material3DArray::setCurrentDepth(int depth) +{ + if (depth < 0 || _rowMap.size() == 0) { + _currentDepth = 0; + } + else if (static_cast(depth) >= _rowMap.size()) { + _currentDepth = _rowMap.size() - 1; + } + else { + _currentDepth = depth; + } +} + +const QString Material3DArray::getYAMLString() const +{ + if (isNull()) { + return QString(); + } + + // Set the correct indentation. 7 chars + name length + QString pad; + pad.fill(QChar::fromLatin1(' '), 9); + + // Save the default value + QString yaml = QString::fromStdString("\n - \""); + Base::Quantity quantity = getDefault().value(); + yaml += quantity.getUserString(); + yaml += QString::fromStdString("\"\n"); + + // Next the array contents + yaml += QString::fromStdString(" - ["); + for (int depth = 0; depth < this->depth(); depth++) { + if (depth > 0) { + // Each row is on its own line, padded for correct indentation + yaml += QString::fromStdString(",\n") + pad; + } + + yaml += QString::fromStdString("\""); + auto value = getDepthValue(depth).getUserString(); + yaml += value; + yaml += QString::fromStdString("\": ["); + + QString pad2; + pad2.fill(QChar::fromLatin1(' '), 14 + value.length()); + + bool firstRow = true; + auto rows = getTable(depth); + for (auto row : *rows) { + if (!firstRow) { + // Each row is on its own line, padded for correct indentation + yaml += QString::fromStdString(",\n") + pad2; + } + else { + firstRow = false; + } + yaml += QString::fromStdString("["); + + bool first = true; + for (auto column : *row) { + if (!first) { + // TODO: Fix for arrays with too many columns to fit on a single line + yaml += QString::fromStdString(", "); + } + else { + first = false; + } + yaml += QString::fromStdString("\""); + // Base::Quantity quantity = column.value(); + yaml += column.getUserString(); + yaml += QString::fromStdString("\""); + } + + yaml += QString::fromStdString("]"); + } + yaml += QString::fromStdString("]"); + } + yaml += QString::fromStdString("]"); + return yaml; } diff --git a/src/Mod/Material/App/MaterialValue.h b/src/Mod/Material/App/MaterialValue.h index 409c137d30..8f1559ed31 100644 --- a/src/Mod/Material/App/MaterialValue.h +++ b/src/Mod/Material/App/MaterialValue.h @@ -22,15 +22,22 @@ #ifndef MATERIAL_MATERIALVALUE_H #define MATERIAL_MATERIALVALUE_H -#include +#include +#include #include +#include + +#include + namespace Materials { -class MaterialsExport MaterialValue +class MaterialsExport MaterialValue: public Base::BaseClass { + TYPESYSTEM_HEADER(); + public: enum ValueType { @@ -50,9 +57,17 @@ public: URL = 13 }; MaterialValue(); - explicit MaterialValue(ValueType type); + MaterialValue(const MaterialValue& other); + MaterialValue(ValueType type); virtual ~MaterialValue() = default; + MaterialValue& operator=(const MaterialValue& other); + virtual bool operator==(const MaterialValue& other) const; + bool operator!=(const MaterialValue& other) const + { + return !operator==(other); + } + ValueType getType() const { return _valueType; @@ -62,10 +77,8 @@ public: { return _value; } - bool isNull() const - { - return _value.isNull(); - } + virtual bool isNull() const; + virtual const QVariant getValueAt(const QVariant& value) const { Q_UNUSED(value); @@ -76,126 +89,182 @@ public: _value = value; } + virtual const QString getYAMLString() const; + protected: - ValueType _valueType; - QVariant _value; + MaterialValue(ValueType type, ValueType inherited); void setType(ValueType type) { _valueType = type; } + void setInitialValue(ValueType inherited); + + ValueType _valueType; + QVariant _value; }; class MaterialsExport Material2DArray: public MaterialValue { + TYPESYSTEM_HEADER_WITH_OVERRIDE(); + public: Material2DArray(); + Material2DArray(const Material2DArray& other); ~Material2DArray() override = default; - void setDefault(MaterialValue value) + Material2DArray& operator=(const Material2DArray& other); + + bool isNull() const override; + + void setDefault(MaterialValue value, bool markSet = true) { _value = value.getValue(); - _defaultSet = true; + _defaultSet = markSet; } - void setDefault(const QVariant& value) + void setDefault(const QVariant& value, bool markSet = true) { _value = value; - _defaultSet = true; + _defaultSet = markSet; } - MaterialValue getDefault() const; + void setDefault(const Base::Quantity& value, bool markSet = true) + { + _value = QVariant::fromValue(value); + _defaultSet = markSet; + } + const QVariant getDefault() const; bool defaultSet() const { return _defaultSet; } - const std::vector* getRow(int row) const; - std::vector* getRow(int row); + std::shared_ptr> getRow(int row) const; + std::shared_ptr> getRow(int row); int rows() const { return _rows.size(); } - void addRow(std::vector* row); - void insertRow(int index, std::vector* row); + int columns() const + { + if (rows() == 0) { + return 0; + } + + return _rows.at(0)->size(); + } + void addRow(std::shared_ptr> row); + void insertRow(int index, std::shared_ptr> row); void deleteRow(int row); void setValue(int row, int column, const QVariant& value); const QVariant getValue(int row, int column) const; + const QString getYAMLString() const override; + protected: - std::vector*> _rows; + void deepCopy(const Material2DArray& other); + + std::vector>> _rows; bool _defaultSet; private: - void dumpRow(const std::vector& row) const; + void dumpRow(std::shared_ptr> row) const; void dump() const; }; class MaterialsExport Material3DArray: public MaterialValue { + TYPESYSTEM_HEADER_WITH_OVERRIDE(); + public: Material3DArray(); ~Material3DArray() override = default; - void setDefault(MaterialValue value) + bool isNull() const override; + + void setDefault(MaterialValue value, bool markSet = true) { _value = value.getValue(); - _defaultSet = true; + _defaultSet = markSet; } - void setDefault(const QVariant& value) + void setDefault(const QVariant& value, bool markSet = true) { _value = value; - _defaultSet = true; + _defaultSet = markSet; } - MaterialValue getDefault() const; + void setDefault(const Base::Quantity& value, bool markSet = true) + { + _value = QVariant::fromValue(value); + _defaultSet = markSet; + } + const QVariant getDefault() const; bool defaultSet() const { return _defaultSet; } - const std::vector*>& getTable(const QVariant& depth) const; - const std::vector& getRow(const QVariant& depth, int row) const; - const std::vector& getRow(int row) const; - std::vector& getRow(const QVariant& depth, int row); - std::vector& getRow(int row); - void addRow(const QVariant& depth, std::vector* row); - void deleteRow(const QVariant& depth, int row); + const std::shared_ptr>>>& + getTable(const Base::Quantity& depth) const; + const std::shared_ptr>>>& + getTable(int depthIndex) const; + const std::shared_ptr> getRow(int depth, int row) const; + std::shared_ptr> getRow(int row) const; + std::shared_ptr> getRow(int depth, int row); + std::shared_ptr> getRow(int row); + void addRow(int depth, std::shared_ptr> row); + void addRow(std::shared_ptr> row); + int addDepth(int depth, Base::Quantity value); + int addDepth(Base::Quantity value); + void deleteDepth(int depth); + void insertRow(int depth, int row, std::shared_ptr> rowData); + void insertRow(int row, std::shared_ptr> rowData); + void deleteRow(int depth, int row); + void deleteRow(int row); void deleteRows(int depth); + void deleteRows(); int depth() const { return _rowMap.size(); } - int rows(const QVariant& depth) const + int rows(int depth) const; + int rows() const { - return getTable(depth).size(); + return rows(_currentDepth); + } + int columns(int depth) const; + int columns() const + { + return columns(_currentDepth); } - void setValue(const QVariant& depth, int row, int column, const QVariant& value); - void setValue(int row, int column, const QVariant& value); - const QVariant getValue(const QVariant& depth, int row, int column); - const QVariant getValue(int row, int column); + void setValue(int depth, int row, int column, const Base::Quantity& value); + void setValue(int row, int column, const Base::Quantity& value); + void setDepthValue(int depth, const Base::Quantity& value); + void setDepthValue(const Base::Quantity& value); + const Base::Quantity getValue(int depth, int row, int column) const; + const Base::Quantity getValue(int row, int column) const; + const Base::Quantity getDepthValue(int depth) const; + + int currentDepth() const; + void setCurrentDepth(int depth); + + const QString getYAMLString() const override; protected: -#if QT_VERSION < QT_VERSION_CHECK(6,0,0) - std::map*>> _rowMap; -#else - struct variant_comp - { - bool operator()(const QVariant& var1, - const QVariant& var2) const - { - return QVariant::compare(var1, var2) == QPartialOrdering::Less; - } - }; - std::map*>, variant_comp> _rowMap; -#endif - + std::vector< + std::pair>>>>> + _rowMap; bool _defaultSet; + int _currentDepth; }; } // namespace Materials Q_DECLARE_METATYPE(Materials::MaterialValue) -Q_DECLARE_METATYPE(Materials::Material2DArray) -Q_DECLARE_METATYPE(Materials::Material3DArray) +// Q_DECLARE_METATYPE(Materials::Material2DArray) +Q_DECLARE_METATYPE(std::shared_ptr) +// Q_DECLARE_METATYPE(Materials::Material3DArray) +Q_DECLARE_METATYPE(std::shared_ptr) #endif // MATERIAL_MATERIALVALUE_H diff --git a/src/Mod/Material/App/Materials.cpp b/src/Mod/Material/App/Materials.cpp index a2c3b23add..2ea280d8c4 100644 --- a/src/Mod/Material/App/Materials.cpp +++ b/src/Mod/Material/App/Materials.cpp @@ -29,8 +29,10 @@ #include #include -#include "MaterialManager.h" #include "Materials.h" + +#include "MaterialLibrary.h" +#include "MaterialManager.h" #include "ModelManager.h" @@ -58,10 +60,25 @@ MaterialProperty::MaterialProperty(const ModelProperty& property) } if (_valuePtr->getType() == MaterialValue::Array2D) { - std::static_pointer_cast(_valuePtr)->setDefault(getColumnNull(0)); + std::static_pointer_cast(_valuePtr)->setDefault(getColumnNull(0), false); } else if (_valuePtr->getType() == MaterialValue::Array3D) { - std::static_pointer_cast(_valuePtr)->setDefault(getColumnNull(0)); + std::static_pointer_cast(_valuePtr)->setDefault(getColumnNull(0), false); + } +} + +void MaterialProperty::copyValuePtr(std::shared_ptr value) +{ + if (value->getType() == MaterialValue::Array2D) { + _valuePtr = + std::make_shared(*(std::static_pointer_cast(value))); + } + else if (value->getType() == MaterialValue::Array3D) { + _valuePtr = + std::make_shared(*(std::static_pointer_cast(value))); + } + else { + _valuePtr = std::make_shared(*value); } } @@ -69,20 +86,16 @@ MaterialProperty::MaterialProperty(const MaterialProperty& other) : ModelProperty(other) { _modelUUID = other._modelUUID; - if (other._valuePtr != nullptr) { - _valuePtr = std::make_shared(*(other._valuePtr)); - } - else { - _valuePtr = nullptr; - } + copyValuePtr(other._valuePtr); for (auto it = other._columns.begin(); it != other._columns.end(); it++) { _columns.push_back(*it); } } -// MaterialProperty::~MaterialProperty() -// {} +MaterialProperty::MaterialProperty(std::shared_ptr other) + : MaterialProperty(*other) +{} void MaterialProperty::setModelUUID(const QString& uuid) { @@ -106,13 +119,28 @@ const std::shared_ptr MaterialProperty::getMaterialValue() const const QString MaterialProperty::getString() const { + if (isNull()) { + return QString(); + } if (getType() == MaterialValue::Quantity) { Base::Quantity quantity = getValue().value(); return quantity.getUserString(); } + else if (getType() == MaterialValue::Float) { + auto value = getValue(); + if (value.isNull()) { + return QString(); + } + return QString(QString::fromStdString("%1")).arg(value.toFloat(), 0, 'g', 6); + } return getValue().toString(); } +const QString MaterialProperty::getYAMLString() const +{ + return _valuePtr->getYAMLString(); +} + void MaterialProperty::setPropertyType(const QString& type) { ModelProperty::setPropertyType(type); @@ -229,7 +257,6 @@ QVariant MaterialProperty::getColumnNull(int column) const void MaterialProperty::setValue(const QVariant& value) { - // _valueType = MaterialValue::String; _valuePtr->setValue(value); } @@ -247,13 +274,21 @@ void MaterialProperty::setValue(const QString& value) else if (_valuePtr->getType() == MaterialValue::URL) { setURL(value); } + else if (_valuePtr->getType() == MaterialValue::Array2D) { + //_valuePtr->setValue(QVariant(std::make_shared())); + } + else if (_valuePtr->getType() == MaterialValue::Array3D) { + //_valuePtr = std::make_shared(); + } else if (_valuePtr->getType() == MaterialValue::Quantity) { // Base::Console().Log("\tParse quantity '%s'\n", value.toStdString().c_str()); try { setQuantity(Base::Quantity::parse(value)); } catch (const Base::ParserError& e) { - Base::Console().Log("Error '%s'\n", e.what()); + Base::Console().Log("MaterialProperty::setValue Error '%s' - '%s'\n", + e.what(), + value.toStdString().c_str()); // Save as a string setString(value); } @@ -263,6 +298,11 @@ void MaterialProperty::setValue(const QString& value) } } +void MaterialProperty::setValue(std::shared_ptr value) +{ + _valuePtr = value; +} + void MaterialProperty::setString(const QString& value) { // _valueType = MaterialValue::String; @@ -346,14 +386,9 @@ MaterialProperty& MaterialProperty::operator=(const MaterialProperty& other) } ModelProperty::operator=(other); - _modelUUID = other._modelUUID; - if (other._valuePtr != nullptr) { - _valuePtr = std::make_shared(*(other._valuePtr)); - } - else { - _valuePtr = nullptr; - } + _modelUUID = other._modelUUID; + copyValuePtr(other._valuePtr); _columns.clear(); for (auto it = other._columns.begin(); it != other._columns.end(); it++) { @@ -363,13 +398,26 @@ MaterialProperty& MaterialProperty::operator=(const MaterialProperty& other) return *this; } +bool MaterialProperty::operator==(const MaterialProperty& other) const +{ + if (this == &other) { + return true; + } + + if (ModelProperty::operator==(other)) { + return (*_valuePtr == *other._valuePtr); + } + return false; +} + TYPESYSTEM_SOURCE(Materials::Material, Base::BaseClass) Material::Material() : _dereferenced(false) + , _editState(ModelEdit_None) {} -Material::Material(const MaterialLibrary& library, +Material::Material(std::shared_ptr library, const QString& directory, const QString& uuid, const QString& name) @@ -387,7 +435,8 @@ Material::Material(const Material& other) , _directory(other._directory) , _uuid(other._uuid) , _name(other._name) - , _authorAndLicense(other._authorAndLicense) + , _author(other._author) + , _license(other._license) , _parentUuid(other._parentUuid) , _description(other._description) , _url(other._url) @@ -408,19 +457,31 @@ Material::Material(const Material& other) _allUuids.push_back(*it); } for (auto it = other._physical.begin(); it != other._physical.end(); it++) { - _physical[it->first] = MaterialProperty(it->second); + MaterialProperty prop = it->second; + _physical[it->first] = std::make_shared(prop); } for (auto it = other._appearance.begin(); it != other._appearance.end(); it++) { - _appearance[it->first] = MaterialProperty(it->second); + MaterialProperty prop = it->second; + _appearance[it->first] = std::make_shared(prop); } } -/* - * Destroys the object and frees any allocated resources - */ -Material::~Material() +const QString Material::getAuthorAndLicense() const { - // no need to delete child widgets, Qt does it all for us + QString authorAndLicense; + + // Combine the author and license field for backwards compatibility + if (!_author.isNull()) { + authorAndLicense = _author; + if (!_license.isNull()) { + authorAndLicense += QString::fromStdString(" ") + _license; + } + } + else if (!_license.isNull()) { + authorAndLicense = _license; + } + + return _license; } void Material::addModel(const QString& uuid) @@ -431,13 +492,13 @@ void Material::addModel(const QString& uuid) } } - _allUuids.push_back(uuid); + _allUuids << uuid; ModelManager manager; try { - const Model& model = manager.getModel(uuid); - auto inheritance = model.getInheritance(); + auto model = manager.getModel(uuid); + auto inheritance = model->getInheritance(); for (auto inherits = inheritance.begin(); inherits != inheritance.end(); inherits++) { addModel(*inherits); } @@ -446,6 +507,62 @@ void Material::addModel(const QString& uuid) } } +void Material::removeModel(const QString& uuid) +{ + Q_UNUSED(uuid); +} + +void Material::clearModels() +{ + _physicalUuids.clear(); + _appearanceUuids.clear(); + _allUuids.clear(); + _physical.clear(); + _appearance.clear(); +} + +void Material::setName(const QString& name) +{ + _name = name; + setEditStateExtend(); +} + +void Material::setAuthor(const QString& author) +{ + _author = author; + setEditStateExtend(); +} + +void Material::setLicense(const QString& license) +{ + _license = license; + setEditStateExtend(); +} + +void Material::setParentUUID(const QString& uuid) +{ + _parentUuid = uuid; + setEditStateExtend(); +} + +void Material::setDescription(const QString& description) +{ + _description = description; + setEditStateExtend(); +} + +void Material::setURL(const QString& url) +{ + _url = url; + setEditStateExtend(); +} + +void Material::setReference(const QString& reference) +{ + _reference = reference; + setEditStateExtend(); +} + void Material::setEditState(ModelEdit newState) { if (newState == ModelEdit_Extend) { @@ -458,6 +575,11 @@ void Material::setEditState(ModelEdit newState) } } +void Material::removeUUID(QStringList& uuidList, const QString& uuid) +{ + uuidList.removeAll(uuid); +} + void Material::addPhysical(const QString& uuid) { if (hasPhysicalModel(uuid)) { @@ -467,23 +589,32 @@ void Material::addPhysical(const QString& uuid) ModelManager manager; try { - const Model& model = manager.getModel(uuid); + auto model = manager.getModel(uuid); + + auto& inheritance = model->getInheritance(); + for (auto it = inheritance.begin(); it != inheritance.end(); it++) { + // Inherited models may already have the properties, so just + // remove the uuid + removeUUID(_physicalUuids, *it); + } _physicalUuids.push_back(uuid); addModel(uuid); setEditStateExtend(); - for (auto it = model.begin(); it != model.end(); it++) { + for (auto it = model->begin(); it != model->end(); it++) { QString propertyName = it->first; - ModelProperty property = static_cast(it->second); + if (!hasPhysicalProperty(propertyName)) { + ModelProperty property = static_cast(it->second); - try { - _physical[propertyName] = MaterialProperty(property); - } - catch (const UnknownValueType&) { - Base::Console().Error("Property '%s' has unknown type '%s'. Ignoring\n", - property.getName().toStdString().c_str(), - property.getPropertyType().toStdString().c_str()); + try { + _physical[propertyName] = std::make_shared(property); + } + catch (const UnknownValueType&) { + Base::Console().Error("Property '%s' has unknown type '%s'. Ignoring\n", + property.getName().toStdString().c_str(), + property.getPropertyType().toStdString().c_str()); + } } } } @@ -491,6 +622,47 @@ void Material::addPhysical(const QString& uuid) } } +void Material::removePhysical(const QString& uuid) +{ + if (!hasPhysicalModel(uuid)) { + return; + } + + // If it's an inherited model, do nothing + bool inherited = true; + for (auto it = _physicalUuids.begin(); it != _physicalUuids.end(); it++) { + if (*it == uuid) { + inherited = false; + break; + } + } + if (inherited) { + return; + } + + ModelManager manager; + + try { + auto model = manager.getModel(uuid); + + auto& inheritance = model->getInheritance(); + for (auto it = inheritance.begin(); it != inheritance.end(); it++) { + removeUUID(_physicalUuids, *it); + removeUUID(_allUuids, *it); + } + removeUUID(_physicalUuids, uuid); + removeUUID(_allUuids, uuid); + + for (auto it = model->begin(); it != model->end(); it++) { + _physical.erase(it->first); + } + + setEditStateAlter(); + } + catch (ModelNotFound const&) { + } +} + void Material::addAppearance(const QString& uuid) { if (hasAppearanceModel(uuid)) { @@ -500,26 +672,86 @@ void Material::addAppearance(const QString& uuid) ModelManager manager; try { - const Model& model = manager.getModel(uuid); + auto model = manager.getModel(uuid); + + auto& inheritance = model->getInheritance(); + for (auto it = inheritance.begin(); it != inheritance.end(); it++) { + // Inherited models may already have the properties, so just + // remove the uuid + removeUUID(_appearanceUuids, *it); + } _appearanceUuids.push_back(uuid); addModel(uuid); setEditStateExtend(); - for (auto it = model.begin(); it != model.end(); it++) { + for (auto it = model->begin(); it != model->end(); it++) { QString propertyName = it->first; - ModelProperty property = static_cast(it->second); + if (!hasAppearanceProperty(propertyName)) { + ModelProperty property = static_cast(it->second); - _appearance[propertyName] = MaterialProperty(property); + _appearance[propertyName] = std::make_shared(property); + } } } catch (ModelNotFound const&) { } } +void Material::removeAppearance(const QString& uuid) +{ + if (!hasAppearanceModel(uuid)) { + return; + } + + // If it's an inherited model, do nothing + bool inherited = true; + for (auto it = _appearanceUuids.begin(); it != _appearanceUuids.end(); it++) { + if (*it == uuid) { + inherited = false; + break; + } + } + if (inherited) { + return; + } + + ModelManager manager; + + try { + auto model = manager.getModel(uuid); + + auto& inheritance = model->getInheritance(); + for (auto it = inheritance.begin(); it != inheritance.end(); it++) { + removeUUID(_appearanceUuids, *it); + removeUUID(_allUuids, *it); + } + removeUUID(_appearanceUuids, uuid); + removeUUID(_allUuids, uuid); + + for (auto it = model->begin(); it != model->end(); it++) { + _appearance.erase(it->first); + } + + setEditStateAlter(); + } + catch (ModelNotFound const&) { + } +} + +void Material::setPropertyEditState(const QString& name) +{ + if (hasPhysicalProperty(name)) { + setPhysicalEditState(name); + } + else if (hasAppearanceProperty(name)) { + setAppearanceEditState(name); + } +} + void Material::setPhysicalEditState(const QString& name) { - if (getPhysicalProperty(name).isNull()) { + if (getPhysicalProperty(name)->isNull()) { setEditStateExtend(); } else { @@ -529,7 +761,7 @@ void Material::setPhysicalEditState(const QString& name) void Material::setAppearanceEditState(const QString& name) { - if (getAppearanceProperty(name).isNull()) { + if (getAppearanceProperty(name)->isNull()) { setEditStateExtend(); } else { @@ -541,38 +773,52 @@ void Material::setPhysicalValue(const QString& name, const QString& value) { setPhysicalEditState(name); - _physical[name].setValue(value); // may not be a string type + _physical[name]->setValue(value); // may not be a string type, conversion may be required } void Material::setPhysicalValue(const QString& name, int value) { setPhysicalEditState(name); - _physical[name].setInt(value); + _physical[name]->setInt(value); } void Material::setPhysicalValue(const QString& name, double value) { setPhysicalEditState(name); - _physical[name].setFloat(value); + _physical[name]->setFloat(value); } void Material::setPhysicalValue(const QString& name, const Base::Quantity value) { setPhysicalEditState(name); - _physical[name].setQuantity(value); + _physical[name]->setQuantity(value); +} + +void Material::setPhysicalValue(const QString& name, std::shared_ptr value) +{ + setPhysicalEditState(name); + + _physical[name]->setValue(value); } void Material::setAppearanceValue(const QString& name, const QString& value) { setAppearanceEditState(name); - _appearance[name].setValue(value); // may not be a string type + _appearance[name]->setValue(value); // may not be a string type, conversion may be required } -MaterialProperty& Material::getPhysicalProperty(const QString& name) +void Material::setAppearanceValue(const QString& name, std::shared_ptr value) +{ + setAppearanceEditState(name); + + _appearance[name]->setValue(value); +} + +std::shared_ptr Material::getPhysicalProperty(const QString& name) { try { return _physical.at(name); @@ -582,7 +828,7 @@ MaterialProperty& Material::getPhysicalProperty(const QString& name) } } -const MaterialProperty& Material::getPhysicalProperty(const QString& name) const +const std::shared_ptr Material::getPhysicalProperty(const QString& name) const { try { return _physical.at(name); @@ -592,7 +838,7 @@ const MaterialProperty& Material::getPhysicalProperty(const QString& name) const } } -MaterialProperty& Material::getAppearanceProperty(const QString& name) +std::shared_ptr Material::getAppearanceProperty(const QString& name) { try { return _appearance.at(name); @@ -602,7 +848,7 @@ MaterialProperty& Material::getAppearanceProperty(const QString& name) } } -const MaterialProperty& Material::getAppearanceProperty(const QString& name) const +const std::shared_ptr Material::getAppearanceProperty(const QString& name) const { try { return _appearance.at(name); @@ -612,29 +858,42 @@ const MaterialProperty& Material::getAppearanceProperty(const QString& name) con } } -const QVariant Material::getValue(const std::map& propertyList, - const QString& name) const +const QVariant +Material::getValue(const std::map>& propertyList, + const QString& name) const { try { - return propertyList.at(name).getValue(); + return propertyList.at(name)->getValue(); } catch (std::out_of_range const&) { throw PropertyNotFound(); } } -const QString Material::getValueString(const std::map& propertyList, - const QString& name) const +const QString +Material::getValueString(const std::map>& propertyList, + const QString& name) const { try { - if (propertyList.at(name).getType() == MaterialValue::Quantity) { - auto value = propertyList.at(name).getValue(); + auto property = propertyList.at(name); + if (property->isNull()) { + return QString(); + } + if (property->getType() == MaterialValue::Quantity) { + auto value = property->getValue(); if (value.isNull()) { return QString(); } return value.value().getUserString(); } - return propertyList.at(name).getValue().toString(); + else if (property->getType() == MaterialValue::Float) { + auto value = property->getValue(); + if (value.isNull()) { + return QString(); + } + return QString(QString::fromStdString("%1")).arg(value.toFloat(), 0, 'g', 6); + } + return property->getValue().toString(); } catch (std::out_of_range const&) { throw PropertyNotFound(); @@ -646,6 +905,11 @@ const QVariant Material::getPhysicalValue(const QString& name) const return getValue(_physical, name); } +const Base::Quantity Material::getPhysicalQuantity(const QString& name) const +{ + return getValue(_physical, name).value(); +} + const QString Material::getPhysicalValueString(const QString& name) const { return getValueString(_physical, name); @@ -656,6 +920,11 @@ const QVariant Material::getAppearanceValue(const QString& name) const return getValue(_appearance, name); } +const Base::Quantity Material::getAppearanceQuantity(const QString& name) const +{ + return getValue(_appearance, name).value(); +} + const QString Material::getAppearanceValueString(const QString& name) const { return getValueString(_appearance, name); @@ -685,13 +954,7 @@ bool Material::hasAppearanceProperty(const QString& name) const bool Material::hasModel(const QString& uuid) const { - for (QString modelUUID : _allUuids) { - if (modelUUID == uuid) { - return true; - } - } - - return false; + return _allUuids.contains(uuid); } bool Material::hasPhysicalModel(const QString& uuid) const @@ -703,8 +966,8 @@ bool Material::hasPhysicalModel(const QString& uuid) const ModelManager manager; try { - const Model& model = manager.getModel(uuid); - if (model.getType() == Model::ModelType_Physical) { + auto model = manager.getModel(uuid); + if (model->getType() == Model::ModelType_Physical) { return true; } } @@ -723,8 +986,8 @@ bool Material::hasAppearanceModel(const QString& uuid) const ModelManager manager; try { - const Model& model = manager.getModel(uuid); - if (model.getType() == Model::ModelType_Appearance) { + auto model = manager.getModel(uuid); + if (model->getType() == Model::ModelType_Appearance) { return true; } } @@ -743,12 +1006,12 @@ bool Material::isPhysicalModelComplete(const QString& uuid) const ModelManager manager; try { - const Model& model = manager.getModel(uuid); - for (auto it = model.begin(); it != model.end(); it++) { + auto model = manager.getModel(uuid); + for (auto it = model->begin(); it != model->end(); it++) { QString propertyName = it->first; - const MaterialProperty& property = getPhysicalProperty(propertyName); + auto property = getPhysicalProperty(propertyName); - if (property.isNull()) { + if (property->isNull()) { return false; } } @@ -769,12 +1032,12 @@ bool Material::isAppearanceModelComplete(const QString& uuid) const ModelManager manager; try { - const Model& model = manager.getModel(uuid); - for (auto it = model.begin(); it != model.end(); it++) { + auto model = manager.getModel(uuid); + for (auto it = model->begin(); it != model->end(); it++) { QString propertyName = it->first; - const MaterialProperty& property = getAppearanceProperty(propertyName); + auto property = getAppearanceProperty(propertyName); - if (property.isNull()) { + if (property->isNull()) { return false; } } @@ -791,8 +1054,11 @@ void Material::saveGeneral(QTextStream& stream) const stream << "General:\n"; stream << " UUID: \"" << _uuid << "\"\n"; stream << " Name: \"" << _name << "\"\n"; - if (!_authorAndLicense.isEmpty()) { - stream << " AuthorAndLicense: \"" << _authorAndLicense << "\"\n"; + if (!_author.isEmpty()) { + stream << " Author: \"" << _author << "\"\n"; + } + if (!_license.isEmpty()) { + stream << " License: \"" << _license << "\"\n"; } if (!_description.isEmpty()) { stream << " Description: \"" << _description << "\"\n"; @@ -810,52 +1076,157 @@ void Material::saveInherits(QTextStream& stream) const if (!_parentUuid.isEmpty()) { MaterialManager manager; - stream << "Inherits:\n"; - stream << " " << manager.getMaterial(_parentUuid).getName() << ":\n"; - stream << " UUID: \"" << _parentUuid << "\"\n"; + try { + auto material = manager.getMaterial(_parentUuid); + + stream << "Inherits:\n"; + stream << " " << material->getName() << ":\n"; + stream << " UUID: \"" << _parentUuid << "\"\n"; + } + catch (const MaterialNotFound&) { + } } } -void Material::saveModels(QTextStream& stream) const +bool Material::modelChanged(const std::shared_ptr parent, + const std::shared_ptr model) const +{ + for (auto itp = model->begin(); itp != model->end(); itp++) { + QString propertyName = itp->first; + auto property = getPhysicalProperty(propertyName); + try { + auto parentProperty = parent->getPhysicalProperty(propertyName); + + if (*property != *parentProperty) { + return true; + } + } + catch (const PropertyNotFound&) { + return true; + } + } + + return false; +} + +bool Material::modelAppearanceChanged(const std::shared_ptr parent, + const std::shared_ptr model) const +{ + for (auto itp = model->begin(); itp != model->end(); itp++) { + QString propertyName = itp->first; + auto property = getAppearanceProperty(propertyName); + try { + auto parentProperty = parent->getAppearanceProperty(propertyName); + + if (*property != *parentProperty) { + return true; + } + } + catch (const PropertyNotFound&) { + return true; + } + } + + return false; +} + +void Material::saveModels(QTextStream& stream, bool saveInherited) const { if (!_physical.empty()) { ModelManager modelManager; + MaterialManager materialManager; - stream << "Models:\n"; + bool inherited = saveInherited && (_parentUuid.size() > 0); + std::shared_ptr parent; + if (inherited) { + try { + parent = materialManager.getMaterial(_parentUuid); + } + catch (const MaterialNotFound&) { + inherited = false; + } + } + + bool headerPrinted = false; for (auto itm = _physicalUuids.begin(); itm != _physicalUuids.end(); itm++) { auto model = modelManager.getModel(*itm); - stream << " " << model.getName() << ":\n"; - stream << " UUID: \"" << model.getUUID() << "\"\n"; - for (auto itp = model.begin(); itp != model.end(); itp++) { - QString propertyName = itp->first; - const MaterialProperty& property = getPhysicalProperty(propertyName); + if (!inherited || modelChanged(parent, model)) { + if (!headerPrinted) { + stream << "Models:\n"; + headerPrinted = true; + } + stream << " " << model->getName() << ":\n"; + stream << " UUID: \"" << model->getUUID() << "\"\n"; + for (auto itp = model->begin(); itp != model->end(); itp++) { + QString propertyName = itp->first; + std::shared_ptr property = getPhysicalProperty(propertyName); + std::shared_ptr parentProperty; + try { + if (inherited) { + parentProperty = parent->getPhysicalProperty(propertyName); + } + } + catch (const PropertyNotFound&) { + Base::Console().Log("Material::saveModels Property not found '%s'\n", + propertyName.toStdString().c_str()); + } - if (!property.isNull()) { - stream << " " << propertyName << ": \"" - << getPhysicalValueString(propertyName) << "\"\n"; + if (!inherited || (*property != *parentProperty)) { + if (!property->isNull()) { + stream << " " << *property << "\n"; + } + } } } } } } -void Material::saveAppearanceModels(QTextStream& stream) const +void Material::saveAppearanceModels(QTextStream& stream, bool saveInherited) const { if (!_appearance.empty()) { ModelManager modelManager; + MaterialManager materialManager; - stream << "AppearanceModels:\n"; + bool inherited = saveInherited && (_parentUuid.size() > 0); + std::shared_ptr parent; + if (inherited) { + try { + parent = materialManager.getMaterial(_parentUuid); + } + catch (const MaterialNotFound&) { + inherited = false; + } + } + + bool headerPrinted = false; for (auto itm = _appearanceUuids.begin(); itm != _appearanceUuids.end(); itm++) { auto model = modelManager.getModel(*itm); - stream << " " << model.getName() << ":\n"; - stream << " UUID: \"" << model.getUUID() << "\"\n"; - for (auto itp = model.begin(); itp != model.end(); itp++) { - QString propertyName = itp->first; - const MaterialProperty& property = getAppearanceProperty(propertyName); + if (!inherited || modelAppearanceChanged(parent, model)) { + if (!headerPrinted) { + stream << "AppearanceModels:\n"; + headerPrinted = true; + } + stream << " " << model->getName() << ":\n"; + stream << " UUID: \"" << model->getUUID() << "\"\n"; + for (auto itp = model->begin(); itp != model->end(); itp++) { + QString propertyName = itp->first; + std::shared_ptr property = + getAppearanceProperty(propertyName); + std::shared_ptr parentProperty; + try { + if (inherited) { + parentProperty = parent->getAppearanceProperty(propertyName); + } + } + catch (const PropertyNotFound&) { + } - if (!property.isNull()) { - stream << " " << propertyName << ": \"" - << getAppearanceValueString(propertyName) << "\"\n"; + if (!inherited || (*property != *parentProperty)) { + if (!property->isNull()) { + stream << " " << *property << "\n"; + } + } } } } @@ -867,15 +1238,57 @@ void Material::newUuid() _uuid = QUuid::createUuid().toString(QUuid::WithoutBraces); } -void Material::save(QTextStream& stream, bool saveAsCopy) +QString Material::getModelByName(const QString& name) const { - Q_UNUSED(saveAsCopy) + ModelManager manager; - stream << "# File created by FreeCAD\n"; + for (auto it = _allUuids.begin(); it != _allUuids.end(); it++) { + try { + auto model = manager.getModel(*it); + if (model->getName() == name) { + return *it; + } + } + catch (ModelNotFound const&) { + } + } + + return QString(); +} + +void Material::save(QTextStream& stream, bool saveAsCopy, bool saveInherited) +{ + if (saveInherited && !saveAsCopy) { + // Check to see if we're an original or if we're already in the list of models + MaterialManager materialManager; + if (materialManager.exists(_uuid)) { + // Make a new version based on the current + setParentUUID(_uuid); + newUuid(); + } + } + + if (saveAsCopy) { + // Save it in the same format as the parent + if (_parentUuid.isEmpty()) { + saveInherited = false; + } + else { + saveInherited = true; + } + } + + stream << "---\n"; + stream << "# File created by " << QString::fromStdString(App::Application::Config()["ExeName"]) + << " " << QString::fromStdString(App::Application::Config()["ExeVersion"]) + << " Revision: " << QString::fromStdString(App::Application::Config()["BuildRevision"]) + << "\n"; saveGeneral(stream); - saveInherits(stream); - saveModels(stream); - saveAppearanceModels(stream); + if (saveInherited) { + saveInherits(stream); + } + saveModels(stream, saveInherited); + saveAppearanceModels(stream, saveInherited); } Material& Material::operator=(const Material& other) @@ -888,12 +1301,14 @@ Material& Material::operator=(const Material& other) _directory = other._directory; _uuid = other._uuid; _name = other._name; - _authorAndLicense = other._authorAndLicense; + _author = other._author; + _license = other._license; _parentUuid = other._parentUuid; _description = other._description; _url = other._url; _reference = other._reference; _dereferenced = other._dereferenced; + _editState = other._editState; _tags.clear(); for (auto it = other._tags.begin(); it != other._tags.end(); it++) { @@ -911,14 +1326,92 @@ Material& Material::operator=(const Material& other) for (auto it = other._allUuids.begin(); it != other._allUuids.end(); it++) { _allUuids.push_back(*it); } + + // Create copies of the properties rather than modify the originals _physical.clear(); for (auto it = other._physical.begin(); it != other._physical.end(); it++) { - _physical[it->first] = MaterialProperty(it->second); + MaterialProperty prop = it->second; + _physical[it->first] = std::make_shared(prop); } _appearance.clear(); for (auto it = other._appearance.begin(); it != other._appearance.end(); it++) { - _appearance[it->first] = MaterialProperty(it->second); + MaterialProperty prop = it->second; + _appearance[it->first] = std::make_shared(prop); } return *this; } + +/* + * Normalize models by removing any inherited models + */ +QStringList Material::normalizeModels(const QStringList& models) +{ + QStringList normalized; + + ModelManager manager; + + for (auto uuid : models) { + auto model = manager.getModel(uuid); + + bool found = false; + for (auto childUuid : models) { + if (uuid != childUuid) { + auto childModel = manager.getModel(childUuid); + if (childModel->inherits(childUuid)) { + // We're an inherited model + found = true; + break; + } + } + } + if (!found) { + normalized << uuid; + } + } + + return normalized; +} + +/* + * Set or change the base material for the current material, updating the properties as + * required. + */ +void Material::updateInheritance(const QString& parent) +{} + +/* + * Return a list of models that are defined in the parent material but not in this one + */ +QStringList Material::inheritedMissingModels(const Material& parent) +{ + QStringList missing; + for (auto uuid : parent._allUuids) { + if (!hasModel(uuid)) { + missing << uuid; + } + } + + return normalizeModels(missing); +} + +/* + * Return a list of models that are defined in this model but not the parent + */ +QStringList Material::inheritedAddedModels(const Material& parent) +{ + QStringList added; + for (auto uuid : _allUuids) { + if (!parent.hasModel(uuid)) { + added << uuid; + } + } + + return normalizeModels(added); +} + +/* + * Return a list of properties that have different values from the parent material + */ +void Material::inheritedPropertyDiff(const QString& parent) +{} diff --git a/src/Mod/Material/App/Materials.h b/src/Mod/Material/App/Materials.h index a4ff89cd44..c0b8cf7769 100644 --- a/src/Mod/Material/App/Materials.h +++ b/src/Mod/Material/App/Materials.h @@ -22,31 +22,34 @@ #ifndef MATERIAL_MATERIALS_H #define MATERIAL_MATERIALS_H -#include +#include -#include #include #include +#include #include #include +#include + +#include -#include "MaterialLibrary.h" #include "Model.h" -namespace fs = boost::filesystem; - namespace Materials { +class MaterialLibrary; + class MaterialsExport MaterialProperty: public ModelProperty { TYPESYSTEM_HEADER_WITH_OVERRIDE(); public: MaterialProperty(); - explicit MaterialProperty(const ModelProperty& property); - explicit MaterialProperty(const MaterialProperty& property); + MaterialProperty(const ModelProperty& property); + MaterialProperty(const MaterialProperty& property); + MaterialProperty(std::shared_ptr property); ~MaterialProperty() override = default; MaterialValue::ValueType getType() const @@ -63,6 +66,7 @@ public: std::shared_ptr getMaterialValue(); const std::shared_ptr getMaterialValue() const; const QString getString() const; + const QString getYAMLString() const; bool getBoolean() const; int getInt() const; double getFloat() const; @@ -79,6 +83,7 @@ public: void setPropertyType(const QString& type) override; void setValue(const QVariant& value); void setValue(const QString& value); + void setValue(std::shared_ptr value); void setString(const QString& value); void setBoolean(bool value); void setBoolean(int value); @@ -93,10 +98,23 @@ public: void setURL(const QString& value); MaterialProperty& operator=(const MaterialProperty& other); + friend QTextStream& operator<<(QTextStream& output, const MaterialProperty& property) + { + output << property.getName() << ": " << property.getYAMLString(); + return output; + } + bool operator==(const MaterialProperty& other) const; + bool operator!=(const MaterialProperty& other) const + { + return !operator==(other); + } + + // void save(QTextStream& stream); protected: void setType(const QString& type); // void setType(MaterialValue::ValueType type) { _valueType = type; } + void copyValuePtr(std::shared_ptr value); void addColumn(MaterialProperty& column) { @@ -122,14 +140,14 @@ public: }; Material(); - explicit Material(const MaterialLibrary& library, - const QString& directory, - const QString& uuid, - const QString& name); - explicit Material(const Material& other); - virtual ~Material(); + Material(std::shared_ptr library, + const QString& directory, + const QString& uuid, + const QString& name); + Material(const Material& other); + ~Material() override = default; - const MaterialLibrary& getLibrary() const + std::shared_ptr getLibrary() const { return _library; } @@ -145,9 +163,14 @@ public: { return _name; } - const QString getAuthorAndLicense() const + const QString getAuthorAndLicense() const; + const QString getAuthor() const { - return _authorAndLicense; + return _author; + } + const QString getLicense() const + { + return _license; } const QString getParentUUID() const { @@ -169,56 +192,39 @@ public: { return _editState; } - const std::list& getTags() const + const QStringList& getTags() const { return _tags; } - const std::vector* getPhysicalModels() const + const QStringList* getPhysicalModels() const { return &_physicalUuids; } - const std::vector* getAppearanceModels() const + const QStringList* getAppearanceModels() const { return &_appearanceUuids; } - void setLibrary(const MaterialLibrary& library) + void setLibrary(std::shared_ptr library) { _library = library; } void setDirectory(const QString& directory) { - Base::Console().Log("Materials::setDirectory(%s)\n", directory.toStdString().c_str()); _directory = directory; } void setUUID(const QString& uuid) { _uuid = uuid; } - void setName(const QString& name) - { - _name = name; - } - void setAuthorAndLicense(const QString& authorAndLicense) - { - _authorAndLicense = authorAndLicense; - } - void setParentUUID(const QString& uuid) - { - _parentUuid = uuid; - } - void setDescription(const QString& description) - { - _description = description; - } - void setURL(const QString& url) - { - _url = url; - } - void setReference(const QString& reference) - { - _reference = reference; - } + void setName(const QString& name); + void setAuthor(const QString& author); + void setLicense(const QString& license); + void setParentUUID(const QString& uuid); + void setDescription(const QString& description); + void setURL(const QString& url); + void setReference(const QString& reference); + void setEditState(ModelEdit newState); void setEditStateAlter() { @@ -228,6 +234,7 @@ public: { setEditState(ModelEdit_Extend); } + void setPropertyEditState(const QString& name); void setPhysicalEditState(const QString& name); void setAppearanceEditState(const QString& name); void resetEditState() @@ -243,23 +250,30 @@ public: Q_UNUSED(tag); } void addPhysical(const QString& uuid); + void removePhysical(const QString& uuid); void addAppearance(const QString& uuid); + void removeAppearance(const QString& uuid); + void clearModels(); void newUuid(); void setPhysicalValue(const QString& name, const QString& value); void setPhysicalValue(const QString& name, int value); void setPhysicalValue(const QString& name, double value); void setPhysicalValue(const QString& name, const Base::Quantity value); + void setPhysicalValue(const QString& name, std::shared_ptr value); void setAppearanceValue(const QString& name, const QString& value); + void setAppearanceValue(const QString& name, std::shared_ptr value); - MaterialProperty& getPhysicalProperty(const QString& name); - const MaterialProperty& getPhysicalProperty(const QString& name) const; - MaterialProperty& getAppearanceProperty(const QString& name); - const MaterialProperty& getAppearanceProperty(const QString& name) const; + std::shared_ptr getPhysicalProperty(const QString& name); + const std::shared_ptr getPhysicalProperty(const QString& name) const; + std::shared_ptr getAppearanceProperty(const QString& name); + const std::shared_ptr getAppearanceProperty(const QString& name) const; const QVariant getPhysicalValue(const QString& name) const; + const Base::Quantity getPhysicalQuantity(const QString& name) const; const QString getPhysicalValueString(const QString& name) const; const QVariant getAppearanceValue(const QString& name) const; + const Base::Quantity getAppearanceQuantity(const QString& name) const; const QString getAppearanceValueString(const QString& name) const; bool hasPhysicalProperty(const QString& name) const; bool hasAppearanceProperty(const QString& name) const; @@ -275,15 +289,17 @@ public: bool isPhysicalModelComplete(const QString& uuid) const; bool isAppearanceModelComplete(const QString& uuid) const; - const std::map& getPhysicalProperties() const + std::map>& getPhysicalProperties() { return _physical; } - const std::map& getAppearanceProperties() const + std::map>& getAppearanceProperties() { return _appearance; } + QString getModelByName(const QString& name) const; + bool getDereferenced() const { return _dereferenced; @@ -293,45 +309,80 @@ public: _dereferenced = true; } - void save(QTextStream& stream, bool saveAsCopy); + /* + * Normalize models by removing any inherited models + */ + QStringList normalizeModels(const QStringList& models); + + /* + * Set or change the base material for the current material, updating the properties as + * required. + */ + void updateInheritance(const QString& parent); + /* + * Return a list of models that are defined in the parent material but not in this one + */ + QStringList inheritedMissingModels(const Material& parent); + /* + * Return a list of models that are defined in this model but not the parent + */ + QStringList inheritedAddedModels(const Material& parent); + /* + * Return a list of properties that have different values from the parent material + */ + void inheritedPropertyDiff(const QString& parent); + + void save(QTextStream& stream, bool saveAsCopy, bool saveInherited); Material& operator=(const Material& other); protected: void addModel(const QString& uuid); + void removeModel(const QString& uuid); + void removeUUID(QStringList& uuidList, const QString& uuid); - const QVariant getValue(const std::map& propertyList, - const QString& name) const; - const QString getValueString(const std::map& propertyList, - const QString& name) const; + const QVariant + getValue(const std::map>& propertyList, + const QString& name) const; + const QString + getValueString(const std::map>& propertyList, + const QString& name) const; + bool modelChanged(const std::shared_ptr parent, + const std::shared_ptr model) const; + bool modelAppearanceChanged(const std::shared_ptr parent, + const std::shared_ptr model) const; void saveGeneral(QTextStream& stream) const; void saveInherits(QTextStream& stream) const; - void saveModels(QTextStream& stream) const; - void saveAppearanceModels(QTextStream& stream) const; + void saveModels(QTextStream& stream, bool saveInherited) const; + void saveAppearanceModels(QTextStream& stream, bool saveInherited) const; private: - MaterialLibrary _library; + std::shared_ptr _library; QString _directory; QString _uuid; QString _name; - QString _authorAndLicense; + QString _author; + QString _license; QString _parentUuid; QString _description; QString _url; QString _reference; - std::list _tags; - std::vector _physicalUuids; - std::vector _appearanceUuids; - std::vector _allUuids; // Includes inherited models - std::map _physical; - std::map _appearance; + QStringList _tags; + QStringList _physicalUuids; + QStringList _appearanceUuids; + QStringList _allUuids; // Includes inherited models + std::map> _physical; + std::map> _appearance; bool _dereferenced; ModelEdit _editState; }; +typedef FolderTreeNode MaterialTreeNode; + } // namespace Materials Q_DECLARE_METATYPE(Materials::Material*) +Q_DECLARE_METATYPE(std::shared_ptr) #endif // MATERIAL_MATERIALS_H diff --git a/src/Mod/Material/App/Model.cpp b/src/Mod/Material/App/Model.cpp index 87020a96fa..c9b95e85f8 100644 --- a/src/Mod/Material/App/Model.cpp +++ b/src/Mod/Material/App/Model.cpp @@ -23,10 +23,13 @@ #ifndef _PreComp_ #endif +#include + +#include + #include "Exceptions.h" #include "Model.h" #include "ModelLibrary.h" -#include using namespace Materials; @@ -81,12 +84,27 @@ ModelProperty& ModelProperty::operator=(const ModelProperty& other) return *this; } +bool ModelProperty::operator==(const ModelProperty& other) const +{ + if (this == &other) { + return true; + } + + if (&other == nullptr) { + return false; + } + + return (_name == other._name) && (_propertyType == other._propertyType) + && (_units == other._units) && (_url == other._url) && (_description == other._description) + && (_inheritance == other._inheritance); +} + TYPESYSTEM_SOURCE(Materials::Model, Base::BaseClass) Model::Model() {} -Model::Model(const ModelLibrary& library, +Model::Model(std::shared_ptr library, ModelType type, const QString& name, const QString& directory, diff --git a/src/Mod/Material/App/Model.h b/src/Mod/Material/App/Model.h index c286ffeb0c..fcf83efd47 100644 --- a/src/Mod/Material/App/Model.h +++ b/src/Mod/Material/App/Model.h @@ -22,31 +22,45 @@ #ifndef MATERIAL_MODEL_H #define MATERIAL_MODEL_H -#include +#include + +#include +#include +#include #include #include -#include -#include +#include + +#include "FolderTree.h" #include "MaterialValue.h" -#include "ModelLibrary.h" +// #include "ModelLibrary.h" namespace Materials { +class ModelLibrary; + +enum ModelFilter +{ + ModelFilter_None, + ModelFilter_Physical, + ModelFilter_Appearance +}; + class MaterialsExport ModelProperty: public Base::BaseClass { TYPESYSTEM_HEADER_WITH_OVERRIDE(); public: ModelProperty(); - explicit ModelProperty(const QString& name, - const QString& type, - const QString& units, - const QString& url, - const QString& description); - explicit ModelProperty(const ModelProperty& other); + ModelProperty(const QString& name, + const QString& type, + const QString& units, + const QString& url, + const QString& description); + ModelProperty(const ModelProperty& other); ~ModelProperty() override = default; const QString getName() const @@ -117,6 +131,11 @@ public: } ModelProperty& operator=(const ModelProperty& other); + bool operator==(const ModelProperty& other) const; + bool operator!=(const ModelProperty& other) const + { + return !operator==(other); + } private: QString _name; @@ -140,17 +159,17 @@ public: }; Model(); - explicit Model(const ModelLibrary& library, - ModelType type, - const QString& name, - const QString& directory, - const QString& uuid, - const QString& description, - const QString& url, - const QString& doi); + Model(std::shared_ptr library, + ModelType type, + const QString& name, + const QString& directory, + const QString& uuid, + const QString& description, + const QString& url, + const QString& doi); ~Model() override = default; - const ModelLibrary& getLibrary() const + std::shared_ptr getLibrary() const { return _library; } @@ -175,10 +194,10 @@ public: { return QDir(_directory).absolutePath(); } - const QString getRelativePath() const - { - return QDir(_directory).relativeFilePath(QDir(_directory).absolutePath()); - } + // const QString getRelativePath() const + // { + // return QDir(_directory).relativeFilePath(QDir(_directory).absolutePath()); + // } const QString getUUID() const { return _uuid; @@ -196,7 +215,7 @@ public: return _doi; } - void setLibrary(const ModelLibrary& library) + void setLibrary(std::shared_ptr library) { _library = library; } @@ -231,12 +250,16 @@ public: void addInheritance(const QString& uuid) { - _inheritedUuids.push_back(uuid); + _inheritedUuids << uuid; } - const std::vector& getInheritance() const + const QStringList& getInheritance() const { return _inheritedUuids; } + bool inherits(const QString& uuid) const + { + return _inheritedUuids.contains(uuid); + } bool operator==(const Model& m) const { @@ -281,7 +304,7 @@ public: } private: - ModelLibrary _library; + std::shared_ptr _library; ModelType _type; QString _name; QString _directory; @@ -289,10 +312,12 @@ private: QString _description; QString _url; QString _doi; - std::vector _inheritedUuids; + QStringList _inheritedUuids; std::map _properties; }; +typedef FolderTreeNode ModelTreeNode; + } // namespace Materials #endif // MATERIAL_MODEL_H diff --git a/src/Mod/Material/App/ModelLibrary.cpp b/src/Mod/Material/App/ModelLibrary.cpp index 901795bd30..7f866db939 100644 --- a/src/Mod/Material/App/ModelLibrary.cpp +++ b/src/Mod/Material/App/ModelLibrary.cpp @@ -30,6 +30,7 @@ #include "Exceptions.h" #include "Model.h" #include "ModelLibrary.h" +#include "ModelManager.h" using namespace Materials; @@ -66,6 +67,15 @@ QString LibraryBase::getLocalPath(const QString& path) const return filePath; } +bool LibraryBase::isRoot(const QString& path) const +{ + QString localPath = getLocalPath(path); + QString cleanPath = getLocalPath(QString::fromStdString("")); + std::string pLocal = localPath.toStdString(); + std::string pclean = cleanPath.toStdString(); + return (cleanPath == localPath); +} + QString LibraryBase::getRelativePath(const QString& path) const { QString filePath; @@ -97,17 +107,80 @@ TYPESYSTEM_SOURCE(Materials::ModelLibrary, LibraryBase) ModelLibrary::ModelLibrary(const QString& libraryName, const QString& dir, const QString& icon) : LibraryBase(libraryName, dir, icon) -{} +{ + _modelPathMap = std::make_unique>>(); +} ModelLibrary::ModelLibrary() -{} +{ + _modelPathMap = std::make_unique>>(); +} -Model* ModelLibrary::addModel(const Model& model, const QString& path) +std::shared_ptr ModelLibrary::getModelByPath(const QString& path) const { QString filePath = getRelativePath(path); - Model* newModel = new Model(model); - newModel->setLibrary(*this); + try { + std::shared_ptr model = _modelPathMap->at(filePath); + return model; + } + catch (std::out_of_range& e) { + throw ModelNotFound(); + } +} + +std::shared_ptr ModelLibrary::addModel(const Model& model, const QString& path) +{ + QString filePath = getRelativePath(path); + std::shared_ptr newModel = std::make_shared(model); + newModel->setLibrary(getptr()); newModel->setDirectory(filePath); + (*_modelPathMap)[filePath] = newModel; + return newModel; } + +std::shared_ptr>> +ModelLibrary::getModelTree(ModelFilter filter) const +{ + std::shared_ptr>> modelTree = + std::make_shared>>(); + + for (auto it = _modelPathMap->begin(); it != _modelPathMap->end(); it++) { + auto filename = it->first; + auto model = it->second; + + if (ModelManager::passFilter(filter, model->getType())) { + // Base::Console().Log("Relative path '%s'\n\t", filename.toStdString().c_str()); + QStringList list = filename.split(QString::fromStdString("/")); + + // Start at the root + std::shared_ptr>> node = modelTree; + for (auto itp = list.begin(); itp != list.end(); itp++) { + // Base::Console().Log("\t%s", itp->toStdString().c_str()); + if (ModelManager::isModel(*itp)) { + std::shared_ptr child = std::make_shared(); + child->setData(model); + (*node)[*itp] = child; + } + else { + // Add the folder only if it's not already there + if (node->count(*itp) == 0) { + auto mapPtr = + std::make_shared>>(); + std::shared_ptr child = std::make_shared(); + child->setFolder(mapPtr); + (*node)[*itp] = child; + node = mapPtr; + } + else { + node = (*node)[*itp]->getFolder(); + } + } + } + // Base::Console().Log("\n"); + } + } + + return modelTree; +} diff --git a/src/Mod/Material/App/ModelLibrary.h b/src/Mod/Material/App/ModelLibrary.h index ea42aa6d9a..8b9fa8b004 100644 --- a/src/Mod/Material/App/ModelLibrary.h +++ b/src/Mod/Material/App/ModelLibrary.h @@ -22,27 +22,30 @@ #ifndef MATERIAL_MODELLIBRARY_H #define MATERIAL_MODELLIBRARY_H -#include +#include -#include -#include #include #include -#include "MaterialValue.h" +#include +#include +#include + +#include "MaterialValue.h" +#include "Model.h" namespace Materials { -class Model; +// class Model; class MaterialsExport LibraryBase: public Base::BaseClass { - TYPESYSTEM_HEADER_WITH_OVERRIDE(); + TYPESYSTEM_HEADER(); public: LibraryBase(); - explicit LibraryBase(const QString& libraryName, const QString& dir, const QString& icon); + LibraryBase(const QString& libraryName, const QString& dir, const QString& icon); ~LibraryBase() override = default; const QString getName() const @@ -68,20 +71,24 @@ public: } QString getLocalPath(const QString& path) const; QString getRelativePath(const QString& path) const; + bool isRoot(const QString& path) const; private: + LibraryBase(const LibraryBase&); + QString _name; QString _directory; QString _iconPath; }; -class MaterialsExport ModelLibrary: public LibraryBase +class MaterialsExport ModelLibrary: public LibraryBase, + public std::enable_shared_from_this { - TYPESYSTEM_HEADER_WITH_OVERRIDE(); + TYPESYSTEM_HEADER(); public: ModelLibrary(); - explicit ModelLibrary(const QString& libraryName, const QString& dir, const QString& icon); + ModelLibrary(const QString& libraryName, const QString& dir, const QString& icon); ~ModelLibrary() override = default; bool operator==(const ModelLibrary& library) const @@ -92,8 +99,22 @@ public: { return !operator==(library); } + std::shared_ptr getModelByPath(const QString& path) const; - Model* addModel(const Model& model, const QString& path); + std::shared_ptr addModel(const Model& model, const QString& path); + + // Use this to get a shared_ptr for *this + std::shared_ptr getptr() + { + return shared_from_this(); + } + std::shared_ptr>> + getModelTree(ModelFilter filter) const; + +private: + ModelLibrary(const ModelLibrary&); + + std::unique_ptr>> _modelPathMap; }; } // namespace Materials diff --git a/src/Mod/Material/App/ModelLoader.cpp b/src/Mod/Material/App/ModelLoader.cpp index 0357b2b27e..b8e9ad582f 100644 --- a/src/Mod/Material/App/ModelLoader.cpp +++ b/src/Mod/Material/App/ModelLoader.cpp @@ -37,7 +37,7 @@ using namespace Materials; -ModelEntry::ModelEntry(const ModelLibrary& library, +ModelEntry::ModelEntry(std::shared_ptr library, const QString& baseName, const QString& modelName, const QString& dir, @@ -52,17 +52,18 @@ ModelEntry::ModelEntry(const ModelLibrary& library, , _dereferenced(false) {} -std::unique_ptr> ModelLoader::_modelEntryMap = nullptr; +std::unique_ptr>> ModelLoader::_modelEntryMap = + nullptr; -ModelLoader::ModelLoader(std::shared_ptr> modelMap, - std::shared_ptr> libraryList) +ModelLoader::ModelLoader(std::shared_ptr>> modelMap, + std::shared_ptr>> libraryList) : _modelMap(modelMap) , _libraryList(libraryList) { loadLibraries(); } -void ModelLoader::addLibrary(ModelLibrary* model) +void ModelLoader::addLibrary(std::shared_ptr model) { _libraryList->push_back(model); } @@ -84,12 +85,13 @@ const QString ModelLoader::getUUIDFromPath(const QString& path) const QString uuid = QString::fromStdString(yamlroot[base]["UUID"].as()); return uuid; } - catch (YAML::Exception&) { + catch (YAML::Exception& ex) { throw ModelNotFound(); } } -ModelEntry* ModelLoader::getModelFromPath(const ModelLibrary& library, const QString& path) const +std::shared_ptr ModelLoader::getModelFromPath(std::shared_ptr library, + const QString& path) const { QFile file(path); if (!file.exists()) { @@ -113,12 +115,12 @@ ModelEntry* ModelLoader::getModelFromPath(const ModelLibrary& library, const QSt throw InvalidModel(); } - ModelEntry* model = new ModelEntry(library, - QString::fromStdString(base), - QString::fromStdString(name), - path, - QString::fromStdString(uuid), - yamlroot); + std::shared_ptr model = std::make_shared(library, + QString::fromStdString(base), + QString::fromStdString(name), + path, + QString::fromStdString(uuid), + yamlroot); return model; } @@ -133,8 +135,8 @@ void ModelLoader::showYaml(const YAML::Node& yaml) const } void ModelLoader::dereference(const QString& uuid, - ModelEntry* parent, - const ModelEntry* child, + std::shared_ptr parent, + std::shared_ptr child, std::map, QString>* inheritances) { auto parentPtr = parent->getModelPtr(); @@ -168,7 +170,7 @@ void ModelLoader::dereference(const QString& uuid, } -void ModelLoader::dereference(ModelEntry* model, +void ModelLoader::dereference(std::shared_ptr model, std::map, QString>* inheritances) { // Avoid recursion @@ -185,10 +187,10 @@ void ModelLoader::dereference(ModelEntry* model, // This requires that all models have already been loaded undereferenced try { - const ModelEntry* child = (*_modelEntryMap)[nodeName]; + std::shared_ptr child = (*_modelEntryMap)[nodeName]; dereference(model->getUUID(), model, child, inheritances); } - catch (const std::out_of_range&) { + catch (const std::out_of_range& oor) { Base::Console().Log("Unable to find '%s' in model map\n", nodeName.toStdString().c_str()); } @@ -208,7 +210,7 @@ QString ModelLoader::yamlValue(const YAML::Node& node, return QString::fromStdString(defaultValue); } -void ModelLoader::addToTree(ModelEntry* model, +void ModelLoader::addToTree(std::shared_ptr model, std::map, QString>* inheritances) { std::set exclude; @@ -268,12 +270,12 @@ void ModelLoader::addToTree(ModelEntry* model, if (propType == QString::fromStdString("2DArray") || propType == QString::fromStdString("3DArray")) { - Base::Console().Log("Reading columns\n"); + // Base::Console().Log("Reading columns\n"); // Read the columns auto cols = yamlProp["Columns"]; for (auto col : cols) { std::string colName = col.first.as(); - Base::Console().Log("\tColumns '%s'\n", colName.c_str()); + // Base::Console().Log("\tColumns '%s'\n", colName.c_str()); auto colProp = cols[colName]; auto colPropType = yamlValue(colProp, "Type", ""); @@ -299,16 +301,16 @@ void ModelLoader::addToTree(ModelEntry* model, } } - (*_modelMap)[uuid] = library.addModel(*finalModel, directory); + (*_modelMap)[uuid] = library->addModel(*finalModel, directory); } -void ModelLoader::loadLibrary(const ModelLibrary& library) +void ModelLoader::loadLibrary(std::shared_ptr library) { if (_modelEntryMap == nullptr) { - _modelEntryMap = std::make_unique>(); + _modelEntryMap = std::make_unique>>(); } - QDirIterator it(library.getDirectory(), QDirIterator::Subdirectories); + QDirIterator it(library->getDirectory(), QDirIterator::Subdirectories); while (it.hasNext()) { auto pathname = it.next(); QFileInfo file(pathname); @@ -345,7 +347,7 @@ void ModelLoader::loadLibraries() getModelLibraries(); if (_libraryList) { for (auto it = _libraryList->begin(); it != _libraryList->end(); it++) { - loadLibrary(**it); + loadLibrary(*it); } } } @@ -362,9 +364,10 @@ void ModelLoader::getModelLibraries() if (useBuiltInMaterials) { QString resourceDir = QString::fromStdString(App::Application::getResourceDir() + "/Mod/Material/Resources/Models"); - auto libData = new ModelLibrary(QString::fromStdString("System"), - resourceDir, - QString::fromStdString(":/icons/freecad.svg")); + auto libData = + std::make_shared(QString::fromStdString("System"), + resourceDir, + QString::fromStdString(":/icons/freecad.svg")); _libraryList->push_back(libData); } @@ -380,7 +383,7 @@ void ModelLoader::getModelLibraries() if (modelDir.length() > 0) { QDir dir(modelDir); if (dir.exists()) { - auto libData = new ModelLibrary(moduleName, modelDir, modelIcon); + auto libData = std::make_shared(moduleName, modelDir, modelIcon); _libraryList->push_back(libData); } } @@ -393,10 +396,10 @@ void ModelLoader::getModelLibraries() if (!resourceDir.isEmpty()) { QDir materialDir(resourceDir); if (materialDir.exists()) { - auto libData = - new ModelLibrary(QString::fromStdString("User"), - resourceDir, - QString::fromStdString(":/icons/preferences-general.svg")); + auto libData = std::make_shared( + QString::fromStdString("User"), + resourceDir, + QString::fromStdString(":/icons/preferences-general.svg")); _libraryList->push_back(libData); } } @@ -407,9 +410,10 @@ void ModelLoader::getModelLibraries() if (!resourceDir.isEmpty()) { QDir materialDir(resourceDir); if (materialDir.exists()) { - auto libData = new ModelLibrary(QString::fromStdString("Custom"), - resourceDir, - QString::fromStdString(":/icons/user.svg")); + auto libData = + std::make_shared(QString::fromStdString("Custom"), + resourceDir, + QString::fromStdString(":/icons/user.svg")); _libraryList->push_back(libData); } } diff --git a/src/Mod/Material/App/ModelLoader.h b/src/Mod/Material/App/ModelLoader.h index b843b9e1fb..9db76092b3 100644 --- a/src/Mod/Material/App/ModelLoader.h +++ b/src/Mod/Material/App/ModelLoader.h @@ -22,6 +22,8 @@ #ifndef MATERIAL_MODELLOADER_H #define MATERIAL_MODELLOADER_H +#include + #include #include #include @@ -34,15 +36,15 @@ namespace Materials class ModelEntry { public: - explicit ModelEntry(const ModelLibrary& library, - const QString& baseName, - const QString& modelName, - const QString& dir, - const QString& modelUuid, - const YAML::Node& modelData); + ModelEntry(std::shared_ptr library, + const QString& baseName, + const QString& modelName, + const QString& dir, + const QString& modelUuid, + const YAML::Node& modelData); virtual ~ModelEntry() = default; - const ModelLibrary& getLibrary() const + std::shared_ptr getLibrary() const { return _library; } @@ -83,7 +85,7 @@ public: private: ModelEntry(); - ModelLibrary _library; + std::shared_ptr _library; QString _base; QString _name; QString _directory; @@ -95,8 +97,8 @@ private: class ModelLoader { public: - explicit ModelLoader(std::shared_ptr> modelMap, - std::shared_ptr> libraryList); + ModelLoader(std::shared_ptr>> modelMap, + std::shared_ptr>> libraryList); virtual ~ModelLoader() = default; static const QString getUUIDFromPath(const QString& path); @@ -107,21 +109,24 @@ private: void getModelLibraries(); QString yamlValue(const YAML::Node& node, const std::string& key, const std::string& defaultValue); - void addToTree(ModelEntry* model, std::map, QString>* inheritances); + void addToTree(std::shared_ptr model, + std::map, QString>* inheritances); void showYaml(const YAML::Node& yaml) const; void dereference(const QString& uuid, - ModelEntry* parent, - const ModelEntry* child, + std::shared_ptr parent, + std::shared_ptr child, std::map, QString>* inheritances); - void dereference(ModelEntry* model, + void dereference(std::shared_ptr model, std::map, QString>* inheritances); - ModelEntry* getModelFromPath(const ModelLibrary& library, const QString& path) const; - void addLibrary(ModelLibrary* model); - void loadLibrary(const ModelLibrary& library); + std::shared_ptr getModelFromPath(std::shared_ptr library, + const QString& path) const; + void addLibrary(std::shared_ptr model); + void loadLibrary(std::shared_ptr library); void loadLibraries(); - static std::unique_ptr> _modelEntryMap; - std::shared_ptr> _modelMap; - std::shared_ptr> _libraryList; + + static std::unique_ptr>> _modelEntryMap; + std::shared_ptr>> _modelMap; + std::shared_ptr>> _libraryList; }; } // namespace Materials diff --git a/src/Mod/Material/App/ModelManager.cpp b/src/Mod/Material/App/ModelManager.cpp index 2900fdde55..88d4e85012 100644 --- a/src/Mod/Material/App/ModelManager.cpp +++ b/src/Mod/Material/App/ModelManager.cpp @@ -23,6 +23,7 @@ #ifndef _PreComp_ #endif +#include #include #include @@ -34,8 +35,8 @@ using namespace Materials; -std::shared_ptr> ModelManager::_libraryList = nullptr; -std::shared_ptr> ModelManager::_modelMap = nullptr; +std::shared_ptr>> ModelManager::_libraryList = nullptr; +std::shared_ptr>> ModelManager::_modelMap = nullptr; QMutex ModelManager::_mutex; TYPESYSTEM_SOURCE(Materials::ModelManager, Base::BaseClass) @@ -50,9 +51,9 @@ void ModelManager::initLibraries() QMutexLocker locker(&_mutex); if (_modelMap == nullptr) { - _modelMap = std::make_shared>(); + _modelMap = std::make_shared>>(); if (_libraryList == nullptr) { - _libraryList = std::make_shared>(); + _libraryList = std::make_shared>>(); } // Load the libraries @@ -60,12 +61,12 @@ void ModelManager::initLibraries() } } -bool ModelManager::isModel(const fs::path& p) +bool ModelManager::isModel(const QString& file) { // if (!fs::is_regular_file(p)) // return false; // check file extension - if (p.extension() == ".yml") { + if (file.endsWith(QString::fromStdString(".yml"))) { return true; } return false; @@ -80,36 +81,62 @@ void ModelManager::refresh() ModelLoader loader(_modelMap, _libraryList); } -const Model& ModelManager::getModel(const QString& uuid) const +std::shared_ptr ModelManager::getModel(const QString& uuid) const { try { if (_modelMap == nullptr) { throw Uninitialized(); } - return *(_modelMap->at(uuid)); + return _modelMap->at(uuid); } catch (std::out_of_range const&) { throw ModelNotFound(); } } -const Model& ModelManager::getModelByPath(const QString& path) const +std::shared_ptr ModelManager::getModelByPath(const QString& path) const { - const QString& uuid = ModelLoader::getUUIDFromPath(path); - const Model& model = getModel(uuid); + QString cleanPath = QDir::cleanPath(path); - return model; + for (auto library : *_libraryList) { + // Base::Console().Log("ModelManager::getModelByPath() Checking library '%s'->'%s'\n", + // library->getName().toStdString().c_str(), + // library->getDirectory().toStdString().c_str()); + + + if (cleanPath.startsWith(library->getDirectory())) { + // Base::Console().Log("ModelManager::getModelByPath() Library '%s'\n", + // library->getDirectory().toStdString().c_str()); + // Base::Console().Log("ModelManager::getModelByPath() Path '%s'\n", + // cleanPath.toStdString().c_str()); + return library->getModelByPath(cleanPath); + } + } + Base::Console().Log("ModelManager::getModelByPath() Library not found for path '%s'\n", + cleanPath.toStdString().c_str()); + + throw MaterialNotFound(); } -const Model& ModelManager::getModelByPath(const QString& path, const QString& libraryPath) const +std::shared_ptr ModelManager::getModelByPath(const QString& path, const QString& lib) const { - QDir modelDir(QDir::cleanPath(libraryPath + QString::fromStdString("/") + path)); - QString absPath = modelDir.absolutePath(); - return getModelByPath(absPath); + auto library = getLibrary(lib); // May throw LibraryNotFound + return library->getModelByPath(path); // May throw ModelNotFound } -bool ModelManager::passFilter(ModelFilter filter, Model::ModelType modelType) const +std::shared_ptr ModelManager::getLibrary(const QString& name) const +{ + for (auto library : *_libraryList) { + if (library->getName() == name) { + return library; + } + } + + throw LibraryNotFound(); +} + +bool ModelManager::passFilter(ModelFilter filter, Model::ModelType modelType) { switch (filter) { case ModelFilter_None: @@ -124,49 +151,3 @@ bool ModelManager::passFilter(ModelFilter filter, Model::ModelType modelType) co return false; } - -std::shared_ptr> -ModelManager::getModelTree(const ModelLibrary& library, ModelFilter filter) const -{ - std::shared_ptr> modelTree = - std::make_shared>(); - - for (auto it = _modelMap->begin(); it != _modelMap->end(); it++) { - auto filename = it->first; - auto model = it->second; - - if (model->getLibrary() == library && passFilter(filter, model->getType())) { - fs::path path = model->getDirectory().toStdString(); - Base::Console().Log("Relative path '%s'\n\t", path.string().c_str()); - - // Start at the root - std::shared_ptr> node = modelTree; - for (auto itp = path.begin(); itp != path.end(); itp++) { - if (isModel(itp->string())) { - ModelTreeNode* child = new ModelTreeNode(); - child->setData(model); - (*node)[QString::fromStdString(itp->string())] = child; - } - else { - // Add the folder only if it's not already there - QString folderName = QString::fromStdString(itp->string()); - std::shared_ptr> mapPtr; - if (node->count(QString::fromStdString(itp->string())) == 0) { - mapPtr = std::make_shared>(); - ModelTreeNode* child = new ModelTreeNode(); - child->setFolder(mapPtr); - (*node)[QString::fromStdString(itp->string())] = child; - node = mapPtr; - } - else { - node = (*node)[QString::fromStdString(itp->string())]->getFolder(); - } - } - Base::Console().Log("'%s' ", itp->string().c_str()); - } - Base::Console().Log("\n"); - } - } - - return modelTree; -} diff --git a/src/Mod/Material/App/ModelManager.h b/src/Mod/Material/App/ModelManager.h index 5a5eed39ba..a1954d3419 100644 --- a/src/Mod/Material/App/ModelManager.h +++ b/src/Mod/Material/App/ModelManager.h @@ -22,62 +22,57 @@ #ifndef MATERIAL_MODELMANAGER_H #define MATERIAL_MODELMANAGER_H +#include + #include #include -#include - #include "Exceptions.h" #include "FolderTree.h" #include "Model.h" +#include "ModelLibrary.h" -namespace fs = boost::filesystem; namespace Materials { -typedef FolderTreeNode ModelTreeNode; - class MaterialsExport ModelManager: public Base::BaseClass { - TYPESYSTEM_HEADER_WITH_OVERRIDE(); + TYPESYSTEM_HEADER(); public: - enum ModelFilter - { - ModelFilter_None, - ModelFilter_Physical, - ModelFilter_Appearance - }; - ModelManager(); ~ModelManager() override = default; void refresh(); - std::shared_ptr> getModelLibraries() + std::shared_ptr>> getModelLibraries() { return _libraryList; } - std::shared_ptr> getModels() + std::shared_ptr>> getModels() { return _modelMap; } - std::shared_ptr> - getModelTree(const ModelLibrary& library, ModelFilter filter = ModelFilter_None) const; - const Model& getModel(const QString& uuid) const; - const Model& getModelByPath(const QString& path) const; - const Model& getModelByPath(const QString& path, const QString& libraryPath) const; + std::shared_ptr>> + getModelTree(std::shared_ptr library, ModelFilter filter = ModelFilter_None) const + { + return library->getModelTree(filter); + } + std::shared_ptr getModel(const QString& uuid) const; + std::shared_ptr getModelByPath(const QString& path) const; + std::shared_ptr getModelByPath(const QString& path, const QString& lib) const; + std::shared_ptr getLibrary(const QString& name) const; - static bool isModel(const fs::path& p); - bool passFilter(ModelFilter filter, Model::ModelType modelType) const; + static bool isModel(const QString& file); + static bool passFilter(ModelFilter filter, Model::ModelType modelType); private: static void initLibraries(); - static std::shared_ptr> _libraryList; - static std::shared_ptr> _modelMap; + static std::shared_ptr>> _libraryList; + static std::shared_ptr>> _modelMap; static QMutex _mutex; }; diff --git a/src/Mod/Material/App/ModelManagerPyImpl.cpp b/src/Mod/Material/App/ModelManagerPyImpl.cpp index 793a80a63b..b7b2608a26 100644 --- a/src/Mod/Material/App/ModelManagerPyImpl.cpp +++ b/src/Mod/Material/App/ModelManagerPyImpl.cpp @@ -21,10 +21,8 @@ #include "PreCompiled.h" -#ifndef _PreComp_ -#include -#endif - +#include "Model.h" +#include "ModelLibrary.h" #include "ModelManager.h" #include "ModelManagerPy.h" #include "ModelPy.h" @@ -62,8 +60,8 @@ PyObject* ModelManagerPy::getModel(PyObject* args) } try { - const Model model = getModelManagerPtr()->getModel(QString::fromStdString(uuid)); - return new ModelPy(new Model(model)); + auto model = getModelManagerPtr()->getModel(QString::fromStdString(uuid)); + return new ModelPy(new Model(*model)); } catch (ModelNotFound const&) { QString error = QString::fromStdString("Model not found:\n"); @@ -96,10 +94,9 @@ PyObject* ModelManagerPy::getModelByPath(PyObject* args) std::string libPath(lib); if (libPath.length() > 0) { try { - const Model& model = - getModelManagerPtr()->getModelByPath(QString::fromStdString(path), - QString::fromStdString(libPath)); - return new ModelPy(new Model(model)); + auto model = getModelManagerPtr()->getModelByPath(QString::fromStdString(path), + QString::fromStdString(libPath)); + return new ModelPy(new Model(*model)); } catch (ModelNotFound const&) { PyErr_SetString(PyExc_LookupError, "Model not found"); @@ -108,8 +105,8 @@ PyObject* ModelManagerPy::getModelByPath(PyObject* args) } try { - const Model& model = getModelManagerPtr()->getModelByPath(QString::fromStdString(path)); - return new ModelPy(new Model(model)); + auto model = getModelManagerPtr()->getModelByPath(QString::fromStdString(path)); + return new ModelPy(new Model(*model)); } catch (ModelNotFound const&) { PyErr_SetString(PyExc_LookupError, "Model not found"); @@ -119,11 +116,11 @@ PyObject* ModelManagerPy::getModelByPath(PyObject* args) Py::List ModelManagerPy::getModelLibraries() const { - std::shared_ptr> libraries = getModelManagerPtr()->getModelLibraries(); + auto libraries = getModelManagerPtr()->getModelLibraries(); Py::List list; for (auto it = libraries->begin(); it != libraries->end(); it++) { - ModelLibrary* lib = *it; + auto lib = *it; Py::Tuple libTuple(3); libTuple.setItem(0, Py::String(lib->getName().toStdString())); libTuple.setItem(1, Py::String(lib->getDirectoryPath().toStdString())); @@ -142,7 +139,7 @@ Py::Dict ModelManagerPy::getModels() const for (auto it = models->begin(); it != models->end(); it++) { QString key = it->first; - Model* model = it->second; + auto model = it->second; PyObject* modelPy = new ModelPy(new Model(*model)); dict.setItem(Py::String(key.toStdString()), Py::Object(modelPy, true)); diff --git a/src/Mod/Material/App/ModelPropertyPyImpl.cpp b/src/Mod/Material/App/ModelPropertyPyImpl.cpp index e87cb6f15f..d701df9da6 100644 --- a/src/Mod/Material/App/ModelPropertyPyImpl.cpp +++ b/src/Mod/Material/App/ModelPropertyPyImpl.cpp @@ -21,10 +21,6 @@ #include "PreCompiled.h" -#ifndef _PreComp_ -#include -#endif - #include "Model.h" #include "ModelPropertyPy.h" diff --git a/src/Mod/Material/App/ModelPyImpl.cpp b/src/Mod/Material/App/ModelPyImpl.cpp index 1d83d99e65..f450ee1f0b 100644 --- a/src/Mod/Material/App/ModelPyImpl.cpp +++ b/src/Mod/Material/App/ModelPyImpl.cpp @@ -21,13 +21,11 @@ #include "PreCompiled.h" -#ifndef _PreComp_ -#include -#endif - #include "Model.h" +#include "ModelLibrary.h" #include "ModelPropertyPy.h" #include "ModelPy.h" +#include "ModelUuids.h" #include "ModelPy.cpp" @@ -43,11 +41,11 @@ std::string ModelPy::representation() const str << "), UUID=("; str << ptr->getUUID().toStdString(); str << "), Library Name=("; - str << ptr->getLibrary().getName().toStdString(); + str << ptr->getLibrary()->getName().toStdString(); str << "), Library Root=("; - str << ptr->getLibrary().getDirectoryPath().toStdString(); + str << ptr->getLibrary()->getDirectoryPath().toStdString(); str << "), Library Icon=("; - str << ptr->getLibrary().getIconPath().toStdString(); + str << ptr->getLibrary()->getIconPath().toStdString(); str << "), Directory=("; str << ptr->getDirectory().toStdString(); str << "), URL=("; @@ -57,7 +55,7 @@ std::string ModelPy::representation() const str << "), Description=("; str << ptr->getDescription().toStdString(); str << "), Inherits=["; - const std::vector& inherited = getModelPtr()->getInheritance(); + auto& inherited = getModelPtr()->getInheritance(); for (auto it = inherited.begin(); it != inherited.end(); it++) { QString uuid = *it; if (it != inherited.begin()) { @@ -87,17 +85,17 @@ int ModelPy::PyInit(PyObject* /*args*/, PyObject* /*kwd*/) Py::String ModelPy::getLibraryName() const { - return Py::String(getModelPtr()->getLibrary().getName().toStdString()); + return Py::String(getModelPtr()->getLibrary()->getName().toStdString()); } Py::String ModelPy::getLibraryRoot() const { - return Py::String(getModelPtr()->getLibrary().getDirectoryPath().toStdString()); + return Py::String(getModelPtr()->getLibrary()->getDirectoryPath().toStdString()); } Py::String ModelPy::getLibraryIcon() const { - return Py::String(getModelPtr()->getLibrary().getIconPath().toStdString()); + return Py::String(getModelPtr()->getLibrary()->getIconPath().toStdString()); } Py::String ModelPy::getName() const @@ -132,13 +130,11 @@ Py::String ModelPy::getDOI() const Py::List ModelPy::getInherited() const { - const std::vector& inherited = getModelPtr()->getInheritance(); + auto& inherited = getModelPtr()->getInheritance(); Py::List list; for (auto it = inherited.begin(); it != inherited.end(); it++) { - QString uuid = *it; - - list.append(Py::String(uuid.toStdString())); + list.append(Py::String(it->toStdString())); } return list; diff --git a/src/Mod/Material/App/ModelUuids.cpp b/src/Mod/Material/App/ModelUuids.cpp new file mode 100644 index 0000000000..78c02ace68 --- /dev/null +++ b/src/Mod/Material/App/ModelUuids.cpp @@ -0,0 +1,70 @@ +/*************************************************************************** + * Copyright (c) 2023 David Carter * + * * + * This file is part of FreeCAD. * + * * + * FreeCAD is free software: you can redistribute it and/or modify it * + * under the terms of the GNU Lesser General Public License as * + * published by the Free Software Foundation, either version 2.1 of the * + * License, or (at your option) any later version. * + * * + * FreeCAD is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with FreeCAD. If not, see * + * . * + * * + **************************************************************************/ + +#include "PreCompiled.h" +#ifndef _PreComp_ +#endif + +#include "ModelUuids.h" + +using namespace Materials; + +TYPESYSTEM_SOURCE(Materials::ModelUUIDs, Base::BaseClass) + +const QString ModelUUIDs::ModelUUID_Legacy_Father = + QString::fromStdString("9cdda8b6-b606-4778-8f13-3934d8668e67"); +const QString ModelUUIDs::ModelUUID_Legacy_MaterialStandard = + QString::fromStdString("1e2c0088-904a-4537-925f-64064c07d700"); + +const QString ModelUUIDs::ModelUUID_Mechanical_Density = + QString::fromStdString("454661e5-265b-4320-8e6f-fcf6223ac3af"); +const QString ModelUUIDs::ModelUUID_Mechanical_IsotropicLinearElastic = + QString::fromStdString("f6f9e48c-b116-4e82-ad7f-3659a9219c50"); +const QString ModelUUIDs::ModelUUID_Mechanical_LinearElastic = + QString::fromStdString("7b561d1d-fb9b-44f6-9da9-56a4f74d7536"); +const QString ModelUUIDs::ModelUUID_Mechanical_OgdenYld2004p18 = + QString::fromStdString("3ef9e427-cc25-43f7-817f-79ff0d49625f"); +const QString ModelUUIDs::ModelUUID_Mechanical_OrthotropicLinearElastic = + QString::fromStdString("b19ccc6b-a431-418e-91c2-0ac8c649d146"); + +const QString ModelUUIDs::ModelUUID_Fluid_Default = + QString::fromStdString("1ae66d8c-1ba1-4211-ad12-b9917573b202"); + +const QString ModelUUIDs::ModelUUID_Thermal_Default = + QString::fromStdString("9959d007-a970-4ea7-bae4-3eb1b8b883c7"); + +const QString ModelUUIDs::ModelUUID_Electromagnetic_Default = + QString::fromStdString("b2eb5f48-74b3-4193-9fbb-948674f427f3"); + +const QString ModelUUIDs::ModelUUID_Architectural_Default = + QString::fromStdString("32439c3b-262f-4b7b-99a8-f7f44e5894c8"); + +const QString ModelUUIDs::ModelUUID_Costs_Default = + QString::fromStdString("881df808-8726-4c2e-be38-688bb6cce466"); + +const QString ModelUUIDs::ModelUUID_Rendering_Basic = + QString::fromStdString("f006c7e4-35b7-43d5-bbf9-c5d572309e6e"); +const QString ModelUUIDs::ModelUUID_Rendering_Texture = + QString::fromStdString("bbdcc65b-67ca-489c-bd5c-a36e33d1c160"); +const QString ModelUUIDs::ModelUUID_Rendering_Advanced = + QString::fromStdString("c880f092-cdae-43d6-a24b-55e884aacbbf"); +const QString ModelUUIDs::ModelUUID_Rendering_Vector = + QString::fromStdString("fdf5a80e-de50-4157-b2e5-b6e5f88b680e"); diff --git a/src/Mod/Material/App/ModelUuids.h b/src/Mod/Material/App/ModelUuids.h index d160f13ac4..db667940db 100644 --- a/src/Mod/Material/App/ModelUuids.h +++ b/src/Mod/Material/App/ModelUuids.h @@ -24,50 +24,48 @@ #include +#include + +#include + namespace Materials { -// UUIDs for predefined material models +class MaterialsExport ModelUUIDs: public Base::BaseClass +{ + TYPESYSTEM_HEADER_WITH_OVERRIDE(); -static const QString ModelUUID_Legacy_Father = - QString::fromStdString("9cdda8b6-b606-4778-8f13-3934d8668e67"); -static const QString ModelUUID_Legacy_MaterialStandard = - QString::fromStdString("1e2c0088-904a-4537-925f-64064c07d700"); +public: + ModelUUIDs() + {} + ~ModelUUIDs() override = default; -static const QString ModelUUID_Mechanical_Density = - QString::fromStdString("454661e5-265b-4320-8e6f-fcf6223ac3af"); -static const QString ModelUUID_Mechanical_IsotropicLinearElastic = - QString::fromStdString("f6f9e48c-b116-4e82-ad7f-3659a9219c50"); -static const QString ModelUUID_Mechanical_LinearElastic = - QString::fromStdString("7b561d1d-fb9b-44f6-9da9-56a4f74d7536"); -static const QString ModelUUID_Mechanical_OgdenYld2004p18 = - QString::fromStdString("3ef9e427-cc25-43f7-817f-79ff0d49625f"); -static const QString ModelUUID_Mechanical_OrthotropicLinearElastic = - QString::fromStdString("b19ccc6b-a431-418e-91c2-0ac8c649d146"); + // UUIDs for predefined material models -static const QString ModelUUID_Fluid_Default = - QString::fromStdString("1ae66d8c-1ba1-4211-ad12-b9917573b202"); + static const QString ModelUUID_Legacy_Father; + static const QString ModelUUID_Legacy_MaterialStandard; -static const QString ModelUUID_Thermal_Default = - QString::fromStdString("9959d007-a970-4ea7-bae4-3eb1b8b883c7"); + static const QString ModelUUID_Mechanical_Density; + static const QString ModelUUID_Mechanical_IsotropicLinearElastic; + static const QString ModelUUID_Mechanical_LinearElastic; + static const QString ModelUUID_Mechanical_OgdenYld2004p18; + static const QString ModelUUID_Mechanical_OrthotropicLinearElastic; -static const QString ModelUUID_Electromagnetic_Default = - QString::fromStdString("b2eb5f48-74b3-4193-9fbb-948674f427f3"); + static const QString ModelUUID_Fluid_Default; -static const QString ModelUUID_Architectural_Default = - QString::fromStdString("32439c3b-262f-4b7b-99a8-f7f44e5894c8"); + static const QString ModelUUID_Thermal_Default; -static const QString ModelUUID_Costs_Default = - QString::fromStdString("881df808-8726-4c2e-be38-688bb6cce466"); + static const QString ModelUUID_Electromagnetic_Default; -static const QString ModelUUID_Rendering_Basic = - QString::fromStdString("f006c7e4-35b7-43d5-bbf9-c5d572309e6e"); -static const QString ModelUUID_Rendering_Texture = - QString::fromStdString("bbdcc65b-67ca-489c-bd5c-a36e33d1c160"); -static const QString ModelUUID_Rendering_Advanced = - QString::fromStdString("c880f092-cdae-43d6-a24b-55e884aacbbf"); -static const QString ModelUUID_Rendering_Vector = - QString::fromStdString("fdf5a80e-de50-4157-b2e5-b6e5f88b680e"); + static const QString ModelUUID_Architectural_Default; + + static const QString ModelUUID_Costs_Default; + + static const QString ModelUUID_Rendering_Basic; + static const QString ModelUUID_Rendering_Texture; + static const QString ModelUUID_Rendering_Advanced; + static const QString ModelUUID_Rendering_Vector; +}; } // namespace Materials diff --git a/src/Mod/Material/App/PreCompiled.h b/src/Mod/Material/App/PreCompiled.h index c643eb4f42..f602f3773c 100644 --- a/src/Mod/Material/App/PreCompiled.h +++ b/src/Mod/Material/App/PreCompiled.h @@ -55,10 +55,6 @@ // Qt #include -// Boost -#include -#include - #endif //_PreComp_ #endif // MATERIAL_PRECOMPILED_H diff --git a/src/Mod/Material/App/UUIDsPy.xml b/src/Mod/Material/App/UUIDsPy.xml new file mode 100644 index 0000000000..29138e05c3 --- /dev/null +++ b/src/Mod/Material/App/UUIDsPy.xml @@ -0,0 +1,116 @@ + + + + + + Material model UUID identifiers. + + + + UUID for model System:Legacy/Father + + + + + + UUID for model System:Legacy/MaterialStandard + + + + + + UUID for model System:Mechanical/Density + + + + + + UUID for model System:Mechanical/IsotropicLinearElastic + + + + + + UUID for model System:Mechanical/LinearElastic + + + + + + UUID for model System:Mechanical/OgdenYld2004p18 + + + + + + UUID for model System:Mechanical/OrthotropicLinearElastic + + + + + + UUID for model System:Fluid/Fluid + + + + + + UUID for model System:Thermal/Thermal + + + + + + UUID for model System:Electromagnetic/Electromagnetic + + + + + + UUID for model System:Architectural/Architectural + + + + + + UUID for model System:Costs/Costs + + + + + + UUID for model System:Rendering/BasicRendering + + + + + + UUID for model System:Rendering/TextureRendering + + + + + + UUID for model System:Rendering/AdvancedRendering + + + + + + UUID for model System:Rendering/VectorRendering + + + + + diff --git a/src/Mod/Material/App/UUIDsPyImpl.cpp b/src/Mod/Material/App/UUIDsPyImpl.cpp new file mode 100644 index 0000000000..94d3fb9071 --- /dev/null +++ b/src/Mod/Material/App/UUIDsPyImpl.cpp @@ -0,0 +1,139 @@ +/*************************************************************************** + * Copyright (c) 2023 David Carter * + * * + * This file is part of FreeCAD. * + * * + * FreeCAD is free software: you can redistribute it and/or modify it * + * under the terms of the GNU Lesser General Public License as * + * published by the Free Software Foundation, either version 2.1 of the * + * License, or (at your option) any later version. * + * * + * FreeCAD is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with FreeCAD. If not, see * + * . * + * * + **************************************************************************/ + +#include "PreCompiled.h" + +#include "ModelUuids.h" + +#include "UUIDsPy.h" + +#include "UUIDsPy.cpp" + +using namespace Materials; + +// returns a string which represents the object e.g. when printed in python +std::string UUIDsPy::representation() const +{ + return {""}; +} + +PyObject* UUIDsPy::PyMake(struct _typeobject*, PyObject*, PyObject*) // Python wrapper +{ + // create a new instance of UUIDsPy and the Twin object + return new UUIDsPy(new ModelUUIDs); +} + +// constructor method +int UUIDsPy::PyInit(PyObject* /*args*/, PyObject* /*kwd*/) +{ + return 0; +} + +Py::String UUIDsPy::getFather() const +{ + return Py::String(ModelUUIDs::ModelUUID_Legacy_Father.toStdString()); +} + +Py::String UUIDsPy::getMaterialStandard() const +{ + return Py::String(ModelUUIDs::ModelUUID_Legacy_MaterialStandard.toStdString()); +} + +Py::String UUIDsPy::getDensity() const +{ + return Py::String(ModelUUIDs::ModelUUID_Mechanical_Density.toStdString()); +} + +Py::String UUIDsPy::getIsotropicLinearElastic() const +{ + return Py::String(ModelUUIDs::ModelUUID_Mechanical_IsotropicLinearElastic.toStdString()); +} + +Py::String UUIDsPy::getLinearElastic() const +{ + return Py::String(ModelUUIDs::ModelUUID_Mechanical_LinearElastic.toStdString()); +} + +Py::String UUIDsPy::getOgdenYld2004p18() const +{ + return Py::String(ModelUUIDs::ModelUUID_Mechanical_OgdenYld2004p18.toStdString()); +} + +Py::String UUIDsPy::getOrthotropicLinearElastic() const +{ + return Py::String(ModelUUIDs::ModelUUID_Mechanical_OrthotropicLinearElastic.toStdString()); +} + +Py::String UUIDsPy::getFluid() const +{ + return Py::String(ModelUUIDs::ModelUUID_Fluid_Default.toStdString()); +} + +Py::String UUIDsPy::getThermal() const +{ + return Py::String(ModelUUIDs::ModelUUID_Thermal_Default.toStdString()); +} + +Py::String UUIDsPy::getElectromagnetic() const +{ + return Py::String(ModelUUIDs::ModelUUID_Electromagnetic_Default.toStdString()); +} + +Py::String UUIDsPy::getArchitectural() const +{ + return Py::String(ModelUUIDs::ModelUUID_Architectural_Default.toStdString()); +} + +Py::String UUIDsPy::getCosts() const +{ + return Py::String(ModelUUIDs::ModelUUID_Costs_Default.toStdString()); +} + +Py::String UUIDsPy::getBasicRendering() const +{ + return Py::String(ModelUUIDs::ModelUUID_Rendering_Basic.toStdString()); +} + +Py::String UUIDsPy::getTextureRendering() const +{ + return Py::String(ModelUUIDs::ModelUUID_Rendering_Texture.toStdString()); +} + +Py::String UUIDsPy::getAdvancedRendering() const +{ + Base::Console().Log(getModelUUIDsPtr()->ModelUUID_Rendering_Advanced.toStdString().c_str()); + return Py::String(getModelUUIDsPtr()->ModelUUID_Rendering_Advanced.toStdString()); +} + +Py::String UUIDsPy::getVectorRendering() const +{ + return Py::String(ModelUUIDs::ModelUUID_Rendering_Vector.toStdString()); +} + +PyObject* UUIDsPy::getCustomAttributes(const char* /*attr*/) const +{ + return nullptr; +} + +int UUIDsPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/) +{ + return 0; +} diff --git a/src/Mod/Material/App/trim.h b/src/Mod/Material/App/trim.h index a8b4a94d84..c4b038567a 100644 --- a/src/Mod/Material/App/trim.h +++ b/src/Mod/Material/App/trim.h @@ -22,7 +22,6 @@ #ifndef MATERIAL_TRIM_H #define MATERIAL_TRIM_H -#include #include namespace Materials diff --git a/src/Mod/Material/CMakeLists.txt b/src/Mod/Material/CMakeLists.txt index b9ae72647d..6263b1ea80 100644 --- a/src/Mod/Material/CMakeLists.txt +++ b/src/Mod/Material/CMakeLists.txt @@ -194,7 +194,6 @@ SET(MaterialModel_Files Resources/Models/Legacy/Father.yml Resources/Models/Legacy/MaterialStandard.yml Resources/Models/Mechanical/Density.yml - Resources/Models/Mechanical/HypotheticalExample.yml Resources/Models/Mechanical/IsotropicLinearElastic.yml Resources/Models/Mechanical/LinearElastic.yml Resources/Models/Mechanical/OgdenYld2004p18.yml @@ -206,6 +205,21 @@ SET(MaterialModel_Files Resources/Models/Thermal/Thermal.yml ) +set(MaterialTest_Files + materialtests/__init__.py + materialtests/TestModels.py + materialtests/TestMaterials.py +) + +ADD_CUSTOM_TARGET(MateriaTestLib ALL + SOURCES ${MaterialTest_Files} +) + +fc_target_copy_resource(MateriaTestLib + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_BINARY_DIR}/Mod/Material + ${MaterialTest_Files}) + ADD_CUSTOM_TARGET(MaterialScripts ALL SOURCES ${MaterialScripts_Files} ${Material_QRC_SRCS} ) @@ -275,8 +289,13 @@ INSTALL( DESTINATION Mod/Material ) +INSTALL( + FILES ${MaterialTest_Files} + DESTINATION Mod/Material/materialtests +) + foreach(file ${MaterialLib_Files} ${FluidMaterial_Files} ${AppearanceLib_Files} ${MaterialModel_Files}) - get_filename_component(filepath ${file} DIRECTORY) + cmake_path(REMOVE_FILENAME file OUTPUT_VARIABLE filepath) INSTALL( FILES ${file} DESTINATION ${CMAKE_INSTALL_DATADIR}/Mod/Material/${filepath} diff --git a/src/Mod/Material/Gui/AppMatGui.cpp b/src/Mod/Material/Gui/AppMatGui.cpp index f20967589b..b424067ca3 100644 --- a/src/Mod/Material/Gui/AppMatGui.cpp +++ b/src/Mod/Material/Gui/AppMatGui.cpp @@ -96,6 +96,9 @@ PyMOD_INIT_FUNC(MatGui) // register preferences pages on Material, the order here will be the order of the tabs in pref // widget + Gui::Dialog::DlgPreferencesImp::setGroupData("Material", + "Material", + QObject::tr("Material workbench")); new Gui::PrefPageProducer( QT_TRANSLATE_NOOP("QObject", "Material")); diff --git a/src/Mod/Material/Gui/Array2D.cpp b/src/Mod/Material/Gui/Array2D.cpp index 5e39884d82..799dec92f2 100644 --- a/src/Mod/Material/Gui/Array2D.cpp +++ b/src/Mod/Material/Gui/Array2D.cpp @@ -24,6 +24,8 @@ #include #endif +#include + #include #include @@ -39,32 +41,52 @@ using namespace MatGui; /* TRANSLATOR MatGui::Array2D */ -Array2D::Array2D(const QString& propertyName, Materials::Material* material, QWidget* parent) +Array2D::Array2D(const QString& propertyName, + std::shared_ptr material, + QWidget* parent) : QDialog(parent) , ui(new Ui_Array2D) + , _material(material) { ui->setupUi(this); if (material->hasPhysicalProperty(propertyName)) { - _property = &(material->getPhysicalProperty(propertyName)); + _property = material->getPhysicalProperty(propertyName); } else if (material->hasAppearanceProperty(propertyName)) { - _property = &(material->getAppearanceProperty(propertyName)); + _property = material->getAppearanceProperty(propertyName); } else { + Base::Console().Log("Property '%s' not found\n", propertyName.toStdString().c_str()); _property = nullptr; } if (_property) { + Base::Console().Log("Value type %d\n", + static_cast(_property->getMaterialValue()->getType())); _value = std::static_pointer_cast(_property->getMaterialValue()); } else { + Base::Console().Log("No value loaded\n"); _value = nullptr; } + if (_value) { + Base::Console().Log("Value type %d\n", static_cast(_value->getType())); + // auto value = _property->getMaterialValue()->getValue(); + // Base::Console().Log("\tQVariant type %d\n", value.userType()); + } setupDefault(); setupArray(); + ui->tableView->setContextMenuPolicy(Qt::CustomContextMenu); + connect(ui->tableView, &QWidget::customContextMenuRequested, this, &Array2D::onContextMenu); + + _deleteAction.setText(tr("Delete row")); + _deleteAction.setShortcut(Qt::Key_Delete); + connect(&_deleteAction, &QAction::triggered, this, &Array2D::onDelete); + ui->tableView->addAction(&_deleteAction); + connect(ui->standardButtons, &QDialogButtonBox::accepted, this, &Array2D::accept); connect(ui->standardButtons, &QDialogButtonBox::rejected, this, &Array2D::reject); } @@ -77,13 +99,16 @@ void Array2D::setupDefault() try { const Materials::MaterialProperty& column1 = _property->getColumn(0); - QString label = QString::fromStdString("Default ") + column1.getName(); + QString label = tr("Default ") + column1.getName(); ui->labelDefault->setText(label); if (column1.getPropertyType() == QString::fromStdString("Quantity")) { ui->editDefault->setMinimum(std::numeric_limits::min()); ui->editDefault->setMaximum(std::numeric_limits::max()); ui->editDefault->setUnitText(_property->getColumnUnits(0)); - ui->editDefault->setValue(_value->getDefault().getValue().value()); + if (!_value->defaultSet()) { + _value->setDefault(_property->getColumnNull(0).value()); + } + ui->editDefault->setValue(_value->getDefault().value()); connect(ui->editDefault, qOverload(&Gui::QuantitySpinBox::valueChanged), @@ -134,15 +159,99 @@ void Array2D::setupArray() auto table = ui->tableView; auto model = new Array2DModel(_property, _value, this); table->setModel(model); - table->setEditTriggers(QAbstractItemView::AllEditTriggers); + // table->setEditTriggers(QAbstractItemView::AllEditTriggers); + table->setSelectionMode(QAbstractItemView::SingleSelection); setColumnWidths(table); setColumnDelegates(table); + connect(model, &QAbstractItemModel::dataChanged, this, &Array2D::onDataChanged); +} + +void Array2D::onDataChanged(const QModelIndex& topLeft, + const QModelIndex& bottomRight, + const QVector& roles) +{ + Q_UNUSED(topLeft) + Q_UNUSED(bottomRight) + Q_UNUSED(roles) + + _material->setEditStateAlter(); } void Array2D::defaultValueChanged(const Base::Quantity& value) { _value->setDefault(QVariant::fromValue(value)); + _material->setEditStateAlter(); +} + +void Array2D::onContextMenu(const QPoint& pos) +{ + Base::Console().Log("Array2D::onContextMenu(%d,%d)\n", pos.x(), pos.y()); + QModelIndex index = ui->tableView->indexAt(pos); + Base::Console().Log("\tindex at (%d,%d)\n", index.row(), index.column()); + + + QMenu contextMenu(tr("Context menu"), this); + + contextMenu.addAction(&_deleteAction); + + contextMenu.exec(ui->tableView->mapToGlobal(pos)); +} + +bool Array2D::newRow(const QModelIndex& index) +{ + Array2DModel* model = static_cast(ui->tableView->model()); + return model->newRow(index); +} + +void Array2D::onDelete(bool checked) +{ + Q_UNUSED(checked) + + Base::Console().Log("Array2D::onDelete()\n"); + QItemSelectionModel* selectionModel = ui->tableView->selectionModel(); + if (!selectionModel->hasSelection() || newRow(selectionModel->currentIndex())) { + Base::Console().Log("\tNothing selected\n"); + return; + } + + int res = confirmDelete(); + if (res == QMessageBox::Cancel) { + return; + } +} + +int Array2D::confirmDelete() +{ + QMessageBox box(this); + box.setIcon(QMessageBox::Question); + box.setWindowTitle(QObject::tr("Confirm Delete")); + + QString prompt = QObject::tr("Are you sure you want to delete the row?"); + box.setText(prompt); + + box.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel); + box.setDefaultButton(QMessageBox::Cancel); + box.setEscapeButton(QMessageBox::Cancel); + + int res = QMessageBox::Cancel; + box.adjustSize(); // Silence warnings from Qt on Windows + switch (box.exec()) { + case QMessageBox::Ok: + deleteSelected(); + res = QMessageBox::Ok; + break; + } + + return res; +} + +void Array2D::deleteSelected() +{ + Array2DModel* model = static_cast(ui->tableView->model()); + QItemSelectionModel* selectionModel = ui->tableView->selectionModel(); + auto index = selectionModel->currentIndex(); + model->deleteRow(index); } void Array2D::accept() diff --git a/src/Mod/Material/Gui/Array2D.h b/src/Mod/Material/Gui/Array2D.h index f32f97e93e..11af3e5366 100644 --- a/src/Mod/Material/Gui/Array2D.h +++ b/src/Mod/Material/Gui/Array2D.h @@ -22,14 +22,20 @@ #ifndef MATGUI_ARRAY2D_H #define MATGUI_ARRAY2D_H +#include + #include +#include #include +#include #include +#include #include -#include "ArrayModel.h" #include +#include "ArrayModel.h" + namespace MatGui { @@ -40,26 +46,38 @@ class Array2D: public QDialog Q_OBJECT public: - explicit Array2D(const QString& propertyName, - Materials::Material* material, - QWidget* parent = nullptr); + Array2D(const QString& propertyName, + std::shared_ptr material, + QWidget* parent = nullptr); ~Array2D() override = default; + void onDataChanged(const QModelIndex& topLeft, + const QModelIndex& bottomRight, + const QVector& roles = QVector()); void defaultValueChanged(const Base::Quantity& value); + void onDelete(bool checked); + void onContextMenu(const QPoint& pos); void accept() override; void reject() override; private: std::unique_ptr ui; - const Materials::MaterialProperty* _property; + std::shared_ptr _material; + std::shared_ptr _property; std::shared_ptr _value; + QAction _deleteAction; + void setupDefault(); void setHeaders(QStandardItemModel* model); void setColumnWidths(QTableView* table); void setColumnDelegates(QTableView* table); void setupArray(); + + bool newRow(const QModelIndex& index); + int confirmDelete(); + void deleteSelected(); }; } // namespace MatGui diff --git a/src/Mod/Material/Gui/Array3D.cpp b/src/Mod/Material/Gui/Array3D.cpp index 956a033204..58f6299d7e 100644 --- a/src/Mod/Material/Gui/Array3D.cpp +++ b/src/Mod/Material/Gui/Array3D.cpp @@ -25,9 +25,12 @@ #include #endif +#include + #include #include +#include #include "Array3D.h" #include "ArrayDelegate.h" @@ -37,19 +40,23 @@ using namespace MatGui; -Array3D::Array3D(const QString& propertyName, Materials::Material* material, QWidget* parent) +Array3D::Array3D(const QString& propertyName, + std::shared_ptr material, + QWidget* parent) : QDialog(parent) , ui(new Ui_Array3D) + , _material(material) { ui->setupUi(this); if (material->hasPhysicalProperty(propertyName)) { - _property = &(material->getPhysicalProperty(propertyName)); + _property = material->getPhysicalProperty(propertyName); } else if (material->hasAppearanceProperty(propertyName)) { - _property = &(material->getAppearanceProperty(propertyName)); + _property = material->getAppearanceProperty(propertyName); } else { + Base::Console().Log("Property '%s' not found\n", propertyName.toStdString().c_str()); _property = nullptr; } if (_property) { @@ -57,6 +64,7 @@ Array3D::Array3D(const QString& propertyName, Materials::Material* material, QWi std::static_pointer_cast(_property->getMaterialValue()); } else { + Base::Console().Log("No value loaded\n"); _value = nullptr; } @@ -64,6 +72,22 @@ Array3D::Array3D(const QString& propertyName, Materials::Material* material, QWi setupDepthArray(); setupArray(); + ui->table3D->setContextMenuPolicy(Qt::CustomContextMenu); + connect(ui->table3D, &QWidget::customContextMenuRequested, this, &Array3D::onDepthContextMenu); + + ui->table2D->setContextMenuPolicy(Qt::CustomContextMenu); + connect(ui->table2D, &QWidget::customContextMenuRequested, this, &Array3D::on2DContextMenu); + + _deleteDepthAction.setText(tr("Delete row")); + // _deleteDepthAction.setShortcut(Qt::Key_Delete); + connect(&_deleteDepthAction, &QAction::triggered, this, &Array3D::onDepthDelete); + ui->table3D->addAction(&_deleteDepthAction); + + _delete2DAction.setText(tr("Delete row")); + // _delete2DAction.setShortcut(Qt::Key_Delete); + connect(&_delete2DAction, &QAction::triggered, this, &Array3D::on2DDelete); + ui->table2D->addAction(&_delete2DAction); + Base::Console().Log("Material '%s'\n", material->getName().toStdString().c_str()); Base::Console().Log("\tproperty '%s'\n", propertyName.toStdString().c_str()); @@ -78,6 +102,10 @@ Array3D::Array3D(const QString& propertyName, Materials::Material* material, QWi &QPushButton::clicked, this, &Array3D::onCancel); + + + QItemSelectionModel* selectionModel = ui->table3D->selectionModel(); + connect(selectionModel, &QItemSelectionModel::selectionChanged, this, &Array3D::onSelectDepth); } bool Array3D::onSplitter(QEvent* e) @@ -95,13 +123,16 @@ void Array3D::setupDefault() try { auto& column1 = _property->getColumn(0); - QString label = QString::fromStdString("Default ") + column1.getName(); + QString label = tr("Default ") + column1.getName(); ui->labelDefault->setText(label); if (column1.getPropertyType() == QString::fromStdString("Quantity")) { ui->editDefault->setMinimum(std::numeric_limits::min()); ui->editDefault->setMaximum(std::numeric_limits::max()); ui->editDefault->setUnitText(_property->getColumnUnits(0)); - ui->editDefault->setValue(_value->getDefault().getValue().value()); + if (!_value->defaultSet()) { + _value->setDefault(_property->getColumnNull(0).value()); + } + ui->editDefault->setValue(_value->getDefault().value()); connect(ui->editDefault, qOverload(&Gui::QuantitySpinBox::valueChanged), @@ -117,6 +148,7 @@ void Array3D::setupDefault() void Array3D::defaultValueChanged(const Base::Quantity& value) { _value->setDefault(QVariant::fromValue(value)); + _material->setEditStateAlter(); } void Array3D::setDepthColumnDelegate(QTableView* table) @@ -140,10 +172,43 @@ void Array3D::setupDepthArray() auto table = ui->table3D; auto model = new Array3DDepthModel(_property, _value, this); table->setModel(model); - table->setEditTriggers(QAbstractItemView::AllEditTriggers); + // table->setEditTriggers(QAbstractItemView::AllEditTriggers); + table->setSelectionMode(QAbstractItemView::SingleSelection); setDepthColumnWidth(table); setDepthColumnDelegate(table); + connect(model, &QAbstractItemModel::rowsInserted, this, &Array3D::onRowsInserted); + connect(model, &QAbstractItemModel::rowsRemoved, this, &Array3D::onRowsRemoved); + connect(model, &QAbstractItemModel::dataChanged, this, &Array3D::onDataChanged); +} + +void Array3D::onRowsInserted(const QModelIndex& parent, int first, int last) +{ + Q_UNUSED(parent) + Q_UNUSED(first) + Q_UNUSED(last) + + update2DArray(); +} + +void Array3D::onRowsRemoved(const QModelIndex& parent, int first, int last) +{ + Q_UNUSED(parent) + Q_UNUSED(first) + Q_UNUSED(last) + + update2DArray(); +} + +void Array3D::onDataChanged(const QModelIndex& topLeft, + const QModelIndex& bottomRight, + const QVector& roles) +{ + Q_UNUSED(topLeft) + Q_UNUSED(bottomRight) + Q_UNUSED(roles) + + _material->setEditStateAlter(); } void Array3D::setColumnWidths(QTableView* table) @@ -174,10 +239,190 @@ void Array3D::setupArray() auto table = ui->table2D; auto model = new Array3DModel(_property, _value, this); table->setModel(model); - table->setEditTriggers(QAbstractItemView::AllEditTriggers); + // table->setEditTriggers(QAbstractItemView::AllEditTriggers); + table->setSelectionMode(QAbstractItemView::SingleSelection); setColumnWidths(table); setColumnDelegates(table); + + if (_value->depth() == 0) { + table->setEnabled(false); + } + connect(model, &QAbstractItemModel::dataChanged, this, &Array3D::onDataChanged); +} + +void Array3D::onSelectDepth(const QItemSelection& selected, const QItemSelection& deselected) +{ + Q_UNUSED(deselected); + + QModelIndexList indexes = selected.indexes(); + + // This should be a list of length 1 + for (auto it = indexes.begin(); it != indexes.end(); it++) { + _value->setCurrentDepth(it->row()); + break; + } + + update2DArray(); +} + +void Array3D::update2DArray() +{ + auto table = ui->table2D; + auto model = static_cast(table->model()); + model->updateData(); + table->setEnabled(_value->depth() > 0); +} + +void Array3D::onDepthContextMenu(const QPoint& pos) +{ + Base::Console().Log("Array3D::onDepthContextMenu(%d,%d)\n", pos.x(), pos.y()); + QModelIndex index = ui->table3D->indexAt(pos); + Base::Console().Log("\tindex at (%d,%d)\n", index.row(), index.column()); + + + QMenu contextMenu(tr("Context menu"), this); + + contextMenu.addAction(&_deleteDepthAction); + + contextMenu.exec(ui->table3D->mapToGlobal(pos)); +} + +bool Array3D::newDepthRow(const QModelIndex& index) +{ + Array3DDepthModel* model = static_cast(ui->table3D->model()); + return model->newRow(index); +} + +void Array3D::onDepthDelete(bool checked) +{ + Q_UNUSED(checked) + + Base::Console().Log("Array3D::onDepthDelete()\n"); + QItemSelectionModel* selectionModel = ui->table3D->selectionModel(); + if (!selectionModel->hasSelection() || newDepthRow(selectionModel->currentIndex())) { + Base::Console().Log("\tNothing selected\n"); + return; + } + + int res = confirmDepthDelete(); + if (res == QMessageBox::Cancel) { + return; + } +} + +int Array3D::confirmDepthDelete() +{ + QMessageBox box(this); + box.setIcon(QMessageBox::Question); + box.setWindowTitle(tr("Confirm Delete")); + + QString prompt = tr("Are you sure you want to delete the row?"); + box.setText(prompt); + box.setInformativeText(tr("Removing this will also remove all 2D contents.")); + + box.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel); + box.setDefaultButton(QMessageBox::Cancel); + box.setEscapeButton(QMessageBox::Cancel); + + int res = QMessageBox::Cancel; + box.adjustSize(); // Silence warnings from Qt on Windows + switch (box.exec()) { + case QMessageBox::Ok: + deleteDepthSelected(); + res = QMessageBox::Ok; + break; + } + + return res; +} + +void Array3D::deleteDepthSelected() +{ + Array3DDepthModel* model = static_cast(ui->table3D->model()); + QItemSelectionModel* selectionModel = ui->table3D->selectionModel(); + auto index = selectionModel->currentIndex(); + model->deleteRow(index); + + auto depth = _value->currentDepth(); + if (depth >= _value->depth()) { + depth = depth - 1; + } + _value->setCurrentDepth(depth); + update2DArray(); +} + +void Array3D::on2DContextMenu(const QPoint& pos) +{ + Base::Console().Log("Array3D::onDepthContextMenu(%d,%d)\n", pos.x(), pos.y()); + QModelIndex index = ui->table2D->indexAt(pos); + Base::Console().Log("\tindex at (%d,%d)\n", index.row(), index.column()); + + + QMenu contextMenu(tr("Context menu"), this); + + contextMenu.addAction(&_delete2DAction); + + // contextMenu.exec(mapToGlobal(pos)); + contextMenu.exec(ui->table2D->mapToGlobal(pos)); +} + +bool Array3D::new2DRow(const QModelIndex& index) +{ + Array3DModel* model = static_cast(ui->table2D->model()); + return model->newRow(index); +} + +void Array3D::on2DDelete(bool checked) +{ + Q_UNUSED(checked) + + Base::Console().Log("Array3D::on2DDelete()\n"); + QItemSelectionModel* selectionModel = ui->table2D->selectionModel(); + if (!selectionModel->hasSelection() || new2DRow(selectionModel->currentIndex())) { + Base::Console().Log("\tNothing selected\n"); + return; + } + + int res = confirm2dDelete(); + if (res == QMessageBox::Cancel) { + return; + } +} + +int Array3D::confirm2dDelete() +{ + QMessageBox box(this); + box.setIcon(QMessageBox::Question); + box.setWindowTitle(tr("Confirm Delete")); + + QString prompt = tr("Are you sure you want to delete the row?"); + box.setText(prompt); + + box.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel); + box.setDefaultButton(QMessageBox::Cancel); + box.setEscapeButton(QMessageBox::Cancel); + + int res = QMessageBox::Cancel; + box.adjustSize(); // Silence warnings from Qt on Windows + switch (box.exec()) { + case QMessageBox::Ok: + delete2DSelected(); + res = QMessageBox::Ok; + break; + } + + return res; +} + +void Array3D::delete2DSelected() +{ + Array3DModel* model = static_cast(ui->table2D->model()); + QItemSelectionModel* selectionModel = ui->table2D->selectionModel(); + auto index = selectionModel->currentIndex(); + model->deleteRow(index); + + update2DArray(); } void Array3D::onOk(bool checked) diff --git a/src/Mod/Material/Gui/Array3D.h b/src/Mod/Material/Gui/Array3D.h index 63cdb4cf46..e0c376e654 100644 --- a/src/Mod/Material/Gui/Array3D.h +++ b/src/Mod/Material/Gui/Array3D.h @@ -22,11 +22,10 @@ #ifndef MATGUI_ARRAY3D_H #define MATGUI_ARRAY3D_H +#include #include #include #include -#include - namespace MatGui { @@ -37,22 +36,42 @@ class Array3D: public QDialog Q_OBJECT public: - explicit Array3D(const QString& propertyName, - Materials::Material* material, - QWidget* parent = nullptr); + Array3D(const QString& propertyName, + std::shared_ptr material, + QWidget* parent = nullptr); ~Array3D() override = default; void defaultValueChanged(const Base::Quantity& value); + void onRowsInserted(const QModelIndex& parent, int first, int last); + void onRowsRemoved(const QModelIndex& parent, int first, int last); + void onDataChanged(const QModelIndex& topLeft, + const QModelIndex& bottomRight, + const QVector& roles = QVector()); + void onSelectDepth(const QItemSelection& selected, const QItemSelection& deselected); bool onSplitter(QEvent* e); + void onDepthDelete(bool checked); + int confirmDepthDelete(); + void deleteDepthSelected(); + void on2DDelete(bool checked); + int confirm2dDelete(); + void delete2DSelected(); + void onDepthContextMenu(const QPoint& pos); + void on2DContextMenu(const QPoint& pos); void onOk(bool checked); void onCancel(bool checked); private: std::unique_ptr ui; - const Materials::MaterialProperty* _property; + std::shared_ptr _material; + std::shared_ptr _property; std::shared_ptr _value; + QAction _deleteDepthAction; + QAction _delete2DAction; + + bool newDepthRow(const QModelIndex& index); + bool new2DRow(const QModelIndex& index); void setupDefault(); void setDepthColumnWidth(QTableView* table); void setDepthColumnDelegate(QTableView* table); @@ -60,6 +79,7 @@ private: void setColumnWidths(QTableView* table); void setColumnDelegates(QTableView* table); void setupArray(); + void update2DArray(); }; } // namespace MatGui diff --git a/src/Mod/Material/Gui/ArrayDelegate.cpp b/src/Mod/Material/Gui/ArrayDelegate.cpp index 95c030a159..255cac8168 100644 --- a/src/Mod/Material/Gui/ArrayDelegate.cpp +++ b/src/Mod/Material/Gui/ArrayDelegate.cpp @@ -156,8 +156,8 @@ QWidget* ArrayDelegate::createWidget(QWidget* parent, const QVariant& item) cons else if (_type == Materials::MaterialValue::Boolean) { Gui::PrefComboBox* combo = new Gui::PrefComboBox(parent); combo->insertItem(0, QString::fromStdString("")); - combo->insertItem(1, QString::fromStdString("False")); - combo->insertItem(2, QString::fromStdString("True")); + combo->insertItem(1, tr("False")); + combo->insertItem(2, tr("True")); combo->setCurrentText(item.toString()); widget = combo; } diff --git a/src/Mod/Material/Gui/ArrayDelegate.h b/src/Mod/Material/Gui/ArrayDelegate.h index 74e9c76c36..2f07398a79 100644 --- a/src/Mod/Material/Gui/ArrayDelegate.h +++ b/src/Mod/Material/Gui/ArrayDelegate.h @@ -22,8 +22,6 @@ #ifndef MATGUI_ArrayDelegate_H #define MATGUI_ArrayDelegate_H -#include - #include #include #include @@ -35,8 +33,6 @@ #include #include -namespace fs = boost::filesystem; - namespace MatGui { @@ -44,10 +40,9 @@ class ArrayDelegate: public QStyledItemDelegate { Q_OBJECT public: - explicit ArrayDelegate( - Materials::MaterialValue::ValueType type = Materials::MaterialValue::None, - QString units = QString(), - QObject* parent = nullptr); + ArrayDelegate(Materials::MaterialValue::ValueType type = Materials::MaterialValue::None, + QString units = QString(), + QObject* parent = nullptr); virtual ~ArrayDelegate() = default; void paint(QPainter* painter, diff --git a/src/Mod/Material/Gui/ArrayModel.cpp b/src/Mod/Material/Gui/ArrayModel.cpp index 24c0ba8b42..8c1156faeb 100644 --- a/src/Mod/Material/Gui/ArrayModel.cpp +++ b/src/Mod/Material/Gui/ArrayModel.cpp @@ -26,6 +26,7 @@ #include +#include #include #include @@ -46,7 +47,7 @@ AbstractArrayModel::AbstractArrayModel(QObject* parent) //=== -Array2DModel::Array2DModel(const Materials::MaterialProperty* property, +Array2DModel::Array2DModel(std::shared_ptr property, std::shared_ptr value, QObject* parent) : AbstractArrayModel(parent) @@ -68,6 +69,12 @@ bool Array2DModel::newRow(const QModelIndex& index) const return (index.row() == _value->rows()); } +void Array2DModel::deleteRow(const QModelIndex& index) +{ + removeRows(index.row(), 1); + Q_EMIT dataChanged(index, index); +} + int Array2DModel::columnCount(const QModelIndex& parent) const { Q_UNUSED(parent); @@ -145,7 +152,7 @@ bool Array2DModel::insertRows(int row, int count, const QModelIndex& parent) int columns = columnCount(); for (int i = 0; i < count; i++) { - std::vector* rowPtr = new std::vector(); + auto rowPtr = std::make_shared>(); for (int j = 0; j < columns; j++) { rowPtr->push_back(_property->getColumnNull(j)); } @@ -162,6 +169,10 @@ bool Array2DModel::removeRows(int row, int count, const QModelIndex& parent) { beginRemoveRows(parent, row, row + count - 1); + for (int i = 0; i < count; i++) { + _value->deleteRow(row); + } + endRemoveRows(); return false; @@ -187,7 +198,7 @@ bool Array2DModel::removeColumns(int column, int count, const QModelIndex& paren //=== -Array3DDepthModel::Array3DDepthModel(const Materials::MaterialProperty* property, +Array3DDepthModel::Array3DDepthModel(std::shared_ptr property, std::shared_ptr value, QObject* parent) : AbstractArrayModel(parent) @@ -209,26 +220,34 @@ bool Array3DDepthModel::newRow(const QModelIndex& index) const return (index.row() == _value->depth()); } +void Array3DDepthModel::deleteRow(const QModelIndex& index) +{ + removeRows(index.row(), 1); + Q_EMIT dataChanged(index, index); +} + QVariant Array3DDepthModel::data(const QModelIndex& index, int role) const { if (role == Qt::DisplayRole) { try { - return _value->getValue(index.row(), index.column()); + Base::Quantity q = _value->getDepthValue(index.row()); + return QVariant::fromValue(q); + } + catch (const Materials::InvalidDepth&) { + } + catch (const Materials::InvalidRow&) { + } + catch (const Materials::InvalidColumn&) { } catch (const Materials::InvalidIndex&) { } try { - auto column = _property->getColumnType(index.column()); - if (column == Materials::MaterialValue::Quantity) { - Base::Quantity q = Base::Quantity(0, _property->getColumnUnits(index.column())); - return QVariant::fromValue(q); - } + Base::Quantity q = Base::Quantity(0, _property->getColumnUnits(0)); + return QVariant::fromValue(q); } catch (const Materials::InvalidColumn&) { } - - return QString(); } return QVariant(); @@ -259,8 +278,9 @@ bool Array3DDepthModel::setData(const QModelIndex& index, const QVariant& value, if (index.row() == _value->depth()) { insertRows(index.row(), 1); + _value->setCurrentDepth(index.row()); } - _value->setValue(index.row(), index.column(), value); + _value->setDepthValue(index.row(), value.value()); Q_EMIT dataChanged(index, index); return true; @@ -277,14 +297,8 @@ bool Array3DDepthModel::insertRows(int row, int count, const QModelIndex& parent { beginInsertRows(parent, row, row + count - 1); - int columns = columnCount(); for (int i = 0; i < count; i++) { - std::vector* rowPtr = new std::vector(); - for (int j = 0; j < columns; j++) { - rowPtr->push_back(_property->getColumnNull(j)); - } - - // _value->insertRow(row, rowPtr); + _value->addDepth(row, Base::Quantity(0, _property->getColumnUnits(0))); } endInsertRows(); @@ -296,6 +310,10 @@ bool Array3DDepthModel::removeRows(int row, int count, const QModelIndex& parent { beginRemoveRows(parent, row, row + count - 1); + for (int i = 0; i < count; i++) { + _value->deleteDepth(row); + } + endRemoveRows(); return false; @@ -321,7 +339,7 @@ bool Array3DDepthModel::removeColumns(int column, int count, const QModelIndex& //=== -Array3DModel::Array3DModel(const Materials::MaterialProperty* property, +Array3DModel::Array3DModel(std::shared_ptr property, std::shared_ptr value, QObject* parent) : AbstractArrayModel(parent) @@ -335,7 +353,15 @@ int Array3DModel::rowCount(const QModelIndex& parent) const return 0; // No children } - return _value->depth() + 1; // Will always have 1 empty row + try { + return _value->rows() + 1; // Will always have 1 empty row + } + catch (const Materials::InvalidDepth&) { + return 1; + } + catch (const Materials::InvalidRow&) { + return 1; + } } int Array3DModel::columnCount(const QModelIndex& parent) const @@ -347,15 +373,36 @@ int Array3DModel::columnCount(const QModelIndex& parent) const bool Array3DModel::newRow(const QModelIndex& index) const { - return (index.row() == _value->depth()); + try { + return (index.row() == _value->rows()); + } + catch (const Materials::InvalidDepth&) { + return true; + } + catch (const Materials::InvalidRow&) { + return true; + } +} + +void Array3DModel::deleteRow(const QModelIndex& index) +{ + removeRows(index.row(), 1); + Q_EMIT dataChanged(index, index); } QVariant Array3DModel::data(const QModelIndex& index, int role) const { if (role == Qt::DisplayRole) { - Base::Console().Error("Row %d, column %d\n", index.row(), index.column()); + // Base::Console().Log("Row %d, column %d\n", index.row(), index.column()); try { - return _value->getValue(index.row(), index.column() + 1); + Base::Quantity q = _value->getValue(index.row(), index.column()); + return QVariant::fromValue(q); + } + catch (const Materials::InvalidDepth&) { + } + catch (const Materials::InvalidRow&) { + } + catch (const Materials::InvalidColumn&) { } catch (const Materials::InvalidIndex&) { } @@ -364,16 +411,11 @@ QVariant Array3DModel::data(const QModelIndex& index, int role) const } try { - auto column = _property->getColumnType(index.column() + 1); - if (column == Materials::MaterialValue::Quantity) { - Base::Quantity q = Base::Quantity(0, _property->getColumnUnits(index.column() - 1)); - return QVariant::fromValue(q); - } + Base::Quantity q = Base::Quantity(0, _property->getColumnUnits(index.column() + 1)); + return QVariant::fromValue(q); } catch (const Materials::InvalidColumn&) { } - - return QString(); } return QVariant(); @@ -402,10 +444,32 @@ bool Array3DModel::setData(const QModelIndex& index, const QVariant& value, int { Q_UNUSED(role); - if (index.row() == _value->depth()) { + Base::Console().Log("Array3DModel::setData at (%d, %d, %d)\n", + _value->currentDepth(), + index.row(), + index.column()); + + if (_value->depth() == 0) { + // Create the first row + // _value->addDepth(Base::Quantity(0, _property->getColumnUnits(0))); + return false; + } + + if (index.row() == _value->rows()) { insertRows(index.row(), 1); } - _value->setValue(index.row(), index.column(), value); + try { + _value->setValue(index.row(), index.column(), value.value()); + } + catch (const Materials::InvalidDepth&) { + Base::Console().Error("Array3DModel::setData - InvalidDepth"); + } + catch (const Materials::InvalidRow&) { + Base::Console().Error("Array3DModel::setData - invalidRow"); + } + catch (const Materials::InvalidColumn&) { + Base::Console().Error("Array3DModel::setData - InvalidColumn"); + } Q_EMIT dataChanged(index, index); return true; @@ -424,12 +488,12 @@ bool Array3DModel::insertRows(int row, int count, const QModelIndex& parent) int columns = columnCount(); for (int i = 0; i < count; i++) { - std::vector* rowPtr = new std::vector(); + auto rowPtr = std::make_shared>(); for (int j = 0; j < columns; j++) { - rowPtr->push_back(_property->getColumnNull(j)); + rowPtr->push_back(_property->getColumnNull(j).value()); } - // _value->insertRow(row, rowPtr); + _value->insertRow(row, rowPtr); } endInsertRows(); @@ -441,6 +505,10 @@ bool Array3DModel::removeRows(int row, int count, const QModelIndex& parent) { beginRemoveRows(parent, row, row + count - 1); + for (int i = 0; i < count; i++) { + _value->deleteRow(row); + } + endRemoveRows(); return false; @@ -463,3 +531,13 @@ bool Array3DModel::removeColumns(int column, int count, const QModelIndex& paren return false; } + +void Array3DModel::updateData() +{ + beginResetModel(); + + // The table has changed at this point, typically by setting the current depth. + // The existing structure needs to be cleared and the table redrawn. + + endResetModel(); +} diff --git a/src/Mod/Material/Gui/ArrayModel.h b/src/Mod/Material/Gui/ArrayModel.h index 7bb4f6816d..739bd6524d 100644 --- a/src/Mod/Material/Gui/ArrayModel.h +++ b/src/Mod/Material/Gui/ArrayModel.h @@ -22,6 +22,8 @@ #ifndef MATGUI_ARRAYMODEL_H #define MATGUI_ARRAYMODEL_H +#include + #include #include #include @@ -36,7 +38,7 @@ namespace MatGui class AbstractArrayModel: public QAbstractTableModel { public: - explicit AbstractArrayModel(QObject* parent = nullptr); + AbstractArrayModel(QObject* parent = nullptr); ~AbstractArrayModel() override = default; virtual bool newRow(const QModelIndex& index) const = 0; @@ -45,14 +47,15 @@ public: class Array2DModel: public AbstractArrayModel { public: - explicit Array2DModel(const Materials::MaterialProperty* property = nullptr, - std::shared_ptr value = nullptr, - QObject* parent = nullptr); + Array2DModel(std::shared_ptr property = nullptr, + std::shared_ptr value = nullptr, + QObject* parent = nullptr); ~Array2DModel() override = default; // Overridden virtual functions int rowCount(const QModelIndex& parent = QModelIndex()) const override; bool newRow(const QModelIndex& index) const override; + void deleteRow(const QModelIndex& index); int columnCount(const QModelIndex& parent = QModelIndex()) const override; QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; QVariant @@ -67,21 +70,22 @@ public: bool removeColumns(int column, int count, const QModelIndex& parent = QModelIndex()) override; private: - const Materials::MaterialProperty* _property; + std::shared_ptr _property; std::shared_ptr _value; }; class Array3DDepthModel: public AbstractArrayModel { public: - explicit Array3DDepthModel(const Materials::MaterialProperty* property = nullptr, - std::shared_ptr value = nullptr, - QObject* parent = nullptr); + Array3DDepthModel(std::shared_ptr property = nullptr, + std::shared_ptr value = nullptr, + QObject* parent = nullptr); ~Array3DDepthModel() override = default; // Overridden virtual functions int rowCount(const QModelIndex& parent = QModelIndex()) const override; bool newRow(const QModelIndex& index) const override; + void deleteRow(const QModelIndex& index); int columnCount(const QModelIndex& parent = QModelIndex()) const override { Q_UNUSED(parent) @@ -100,21 +104,22 @@ public: bool removeColumns(int column, int count, const QModelIndex& parent = QModelIndex()) override; private: - const Materials::MaterialProperty* _property; + std::shared_ptr _property; std::shared_ptr _value; }; class Array3DModel: public AbstractArrayModel { public: - explicit Array3DModel(const Materials::MaterialProperty* property = nullptr, - std::shared_ptr value = nullptr, - QObject* parent = nullptr); + Array3DModel(std::shared_ptr property = nullptr, + std::shared_ptr value = nullptr, + QObject* parent = nullptr); ~Array3DModel() override = default; // Overridden virtual functions int rowCount(const QModelIndex& parent = QModelIndex()) const override; bool newRow(const QModelIndex& index) const override; + void deleteRow(const QModelIndex& index); int columnCount(const QModelIndex& parent = QModelIndex()) const override; QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; QVariant @@ -128,8 +133,10 @@ public: bool insertColumns(int column, int count, const QModelIndex& parent = QModelIndex()) override; bool removeColumns(int column, int count, const QModelIndex& parent = QModelIndex()) override; + void updateData(); + private: - const Materials::MaterialProperty* _property; + std::shared_ptr _property; std::shared_ptr _value; }; diff --git a/src/Mod/Material/Gui/DlgSettingsMaterial.h b/src/Mod/Material/Gui/DlgSettingsMaterial.h index 4f62921794..183bfd555f 100644 --- a/src/Mod/Material/Gui/DlgSettingsMaterial.h +++ b/src/Mod/Material/Gui/DlgSettingsMaterial.h @@ -35,7 +35,7 @@ class DlgSettingsMaterial: public Gui::Dialog::PreferencePage Q_OBJECT public: - explicit DlgSettingsMaterial(QWidget* parent = nullptr); + DlgSettingsMaterial(QWidget* parent = nullptr); ~DlgSettingsMaterial() override = default; protected: diff --git a/src/Mod/Material/Gui/MaterialDelegate.cpp b/src/Mod/Material/Gui/MaterialDelegate.cpp index 92f96ab7dd..ee9d4b7144 100644 --- a/src/Mod/Material/Gui/MaterialDelegate.cpp +++ b/src/Mod/Material/Gui/MaterialDelegate.cpp @@ -88,7 +88,7 @@ bool MaterialDelegate::editorEvent(QEvent* event, std::string type = propertyType.toStdString(); if (type == "Color") { Base::Console().Log("Edit color\n"); - showColorModal(item); + showColorModal(item, propertyName); // Mark as handled return true; } @@ -109,7 +109,7 @@ bool MaterialDelegate::editorEvent(QEvent* event, return QStyledItemDelegate::editorEvent(event, model, option, index); } -void MaterialDelegate::showColorModal(QStandardItem* item) +void MaterialDelegate::showColorModal(QStandardItem* item, QString propertyName) { QColor currentColor; // = d->col; currentColor.setRgba(parseColor(item->text())); @@ -126,14 +126,18 @@ void MaterialDelegate::showColorModal(QStandardItem* item) connect(dlg, &QColorDialog::finished, this, [&](int result) { if (result == QDialog::Accepted) { + Base::Console().Log("Accepted\n"); QColor color = dlg->selectedColor(); if (color.isValid()) { + Base::Console().Log("isValid\n"); QString colorText = QString(QString::fromStdString("(%1,%2,%3,%4)")) .arg(color.red() / 255.0) .arg(color.green() / 255.0) .arg(color.blue() / 255.0) .arg(color.alpha() / 255.0); item->setText(colorText); + Q_EMIT const_cast(this)->propertyChange(propertyName, + item->text()); } } }); @@ -143,7 +147,7 @@ void MaterialDelegate::showColorModal(QStandardItem* item) void MaterialDelegate::showArray2DModal(const QString& propertyName, QStandardItem* item) { - Materials::Material* material = item->data().value(); + auto material = item->data().value>(); Array2D* dlg = new Array2D(propertyName, material); dlg->setAttribute(Qt::WA_DeleteOnClose); @@ -161,7 +165,7 @@ void MaterialDelegate::showArray2DModal(const QString& propertyName, QStandardIt void MaterialDelegate::showArray3DModal(const QString& propertyName, QStandardItem* item) { - Materials::Material* material = item->data().value(); + auto material = item->data().value>(); Array3D* dlg = new Array3D(propertyName, material); dlg->setAttribute(Qt::WA_DeleteOnClose); @@ -411,8 +415,8 @@ QWidget* MaterialDelegate::createWidget(QWidget* parent, else if (type == "Boolean") { Gui::PrefComboBox* combo = new Gui::PrefComboBox(parent); combo->insertItem(0, QString::fromStdString("")); - combo->insertItem(1, QString::fromStdString("False")); - combo->insertItem(2, QString::fromStdString("True")); + combo->insertItem(1, tr("False")); + combo->insertItem(2, tr("True")); combo->setCurrentText(propertyValue); widget = combo; } diff --git a/src/Mod/Material/Gui/MaterialDelegate.h b/src/Mod/Material/Gui/MaterialDelegate.h index 1febeb11cf..a395fa8d9f 100644 --- a/src/Mod/Material/Gui/MaterialDelegate.h +++ b/src/Mod/Material/Gui/MaterialDelegate.h @@ -22,8 +22,6 @@ #ifndef MATGUI_MATERIALDELEGATE_H #define MATGUI_MATERIALDELEGATE_H -#include - #include #include #include @@ -35,8 +33,6 @@ #include #include -namespace fs = boost::filesystem; - namespace MatGui { @@ -44,7 +40,7 @@ class MaterialDelegate: public QStyledItemDelegate { Q_OBJECT public: - explicit MaterialDelegate(QObject* parent = nullptr); + MaterialDelegate(QObject* parent = nullptr); ~MaterialDelegate() override = default; QWidget* createEditor(QWidget* parent, @@ -76,7 +72,7 @@ private: const QString& propertyValue, const QString& propertyUnits) const; QRgb parseColor(const QString& color) const; - void showColorModal(QStandardItem* item); + void showColorModal(QStandardItem* item, QString propertyName); void showArray2DModal(const QString& propertyName, QStandardItem* item); void showArray3DModal(const QString& propertyName, QStandardItem* item); }; diff --git a/src/Mod/Material/Gui/MaterialSave.cpp b/src/Mod/Material/Gui/MaterialSave.cpp index 58d610e4e8..853c973ea2 100644 --- a/src/Mod/Material/Gui/MaterialSave.cpp +++ b/src/Mod/Material/Gui/MaterialSave.cpp @@ -21,6 +21,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ +#include #include #include #endif @@ -36,12 +37,15 @@ using namespace MatGui; /* TRANSLATOR MatGui::MaterialsEditor */ -MaterialSave::MaterialSave(Materials::Material* material, QWidget* parent) +MaterialSave::MaterialSave(std::shared_ptr material, QWidget* parent) : QDialog(parent) , ui(new Ui_MaterialSave) , _material(material) + , _saveInherited(true) , _selectedPath(QString::fromStdString("/")) + , _selectedFull(QString::fromStdString("/")) , _selectedUUID(QString()) + , _deleteAction(this) { ui->setupUi(this); @@ -57,6 +61,9 @@ MaterialSave::MaterialSave(Materials::Material* material, QWidget* parent) } _filename = QString(ui->editFilename->text()); // No filename by default + ui->checkDerived->setChecked(_saveInherited); + connect(ui->checkDerived, &QCheckBox::stateChanged, this, &MaterialSave::onInherited); + connect(ui->standardButtons->button(QDialogButtonBox::Ok), &QPushButton::clicked, this, @@ -73,11 +80,25 @@ MaterialSave::MaterialSave(Materials::Material* material, QWidget* parent) connect(ui->buttonNewFolder, &QPushButton::clicked, this, &MaterialSave::onNewFolder); connect(ui->editFilename, &QLineEdit::textEdited, this, &MaterialSave::onFilename); + ui->treeMaterials->setContextMenuPolicy(Qt::CustomContextMenu); + connect(ui->treeMaterials, + &QWidget::customContextMenuRequested, + this, + &MaterialSave::onContextMenu); + + _deleteAction.setText(tr("Delete")); + _deleteAction.setShortcut(Qt::Key_Delete); + connect(&_deleteAction, &QAction::triggered, this, &MaterialSave::onDelete); + ui->treeMaterials->addAction(&_deleteAction); + QItemSelectionModel* selectionModel = ui->treeMaterials->selectionModel(); connect(selectionModel, &QItemSelectionModel::selectionChanged, this, &MaterialSave::onSelectModel); + + auto model = static_cast(ui->treeMaterials->model()); + connect(model, &QStandardItemModel::itemChanged, this, &MaterialSave::onItemChanged); } /* @@ -88,6 +109,13 @@ MaterialSave::~MaterialSave() // no need to delete child widgets, Qt does it all for us } +void MaterialSave::onInherited(int state) +{ + Q_UNUSED(state) + + _saveInherited = ui->checkDerived->isChecked(); +} + void MaterialSave::onOk(bool checked) { Q_UNUSED(checked) @@ -100,18 +128,145 @@ void MaterialSave::onOk(bool checked) } auto variant = ui->comboLibrary->currentData(); - auto library = variant.value(); + auto library = variant.value>(); QFileInfo filepath(_selectedPath + QString::fromStdString("/") + name + QString::fromStdString(".FCMat")); Base::Console().Log("saveMaterial(library(%s), material(%s), path(%s))\n", - library.getName().toStdString().c_str(), + library->getName().toStdString().c_str(), _material->getName().toStdString().c_str(), filepath.filePath().toStdString().c_str()); - _manager.saveMaterial(&library, *_material, filepath.filePath()); + + if (library->fileExists(filepath.filePath())) { + // confirm overwrite + auto res = confirmOverwrite(_filename); + if (res == QMessageBox::Cancel) { + return; + } + + _manager.saveMaterial(library, _material, filepath.filePath(), true, false, _saveInherited); + accept(); + return; + } + + bool saveAsCopy = false; + if (_manager.exists(_material->getUUID())) { + // Does it already exist in this library? + if (_manager.exists(library, _material->getUUID())) { + // Confirm saving a new material + auto res = confirmNewMaterial(); + if (res == QMessageBox::Cancel) { + return; + } + // saveAsCopy = false = already done + } + else { + // Copy or new + auto res = confirmCopy(); + if (res == QMessageBox::Cancel) { + return; + } + else if (res == QMessageBox::Save) { + // QMessageBox::Save saves as normal, a duplicate + saveAsCopy = true; + } + // QMessageBox::Ok saves a new material + } + } + + _manager + .saveMaterial(library, _material, filepath.filePath(), false, saveAsCopy, _saveInherited); accept(); } +int MaterialSave::confirmOverwrite(const QString& filename) +{ + QMessageBox box(this); + box.setIcon(QMessageBox::Question); + box.setWindowTitle(QObject::tr("Confirm Overwrite")); + + QFileInfo info(_selectedFull); + QString prompt = tr("Are you sure you want to save over '%1'?").arg(filename); + box.setText(prompt); + + box.setInformativeText(tr("Saving over the original file may cause other documents to break. " + "This is not recommended.")); + + box.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel); + box.setDefaultButton(QMessageBox::Cancel); + box.setEscapeButton(QMessageBox::Cancel); + + int res = QMessageBox::Cancel; + box.adjustSize(); // Silence warnings from Qt on Windows + switch (box.exec()) { + case QMessageBox::Ok: + res = QMessageBox::Ok; + break; + } + + return res; +} + +int MaterialSave::confirmNewMaterial() +{ + QMessageBox box(this); + box.setIcon(QMessageBox::Question); + box.setWindowTitle(tr("Confirm Save As New Material")); + + QString prompt = tr("Save as new material"); + box.setText(prompt); + + box.setInformativeText(tr( + "This material already exists in this library. Would you like to save as a new material?")); + + box.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel); + box.setDefaultButton(QMessageBox::Cancel); + box.setEscapeButton(QMessageBox::Cancel); + + int res = QMessageBox::Cancel; + box.adjustSize(); // Silence warnings from Qt on Windows + switch (box.exec()) { + case QMessageBox::Ok: + res = QMessageBox::Ok; + break; + } + + return res; +} + +int MaterialSave::confirmCopy() +{ + QMessageBox box(this); + box.setIcon(QMessageBox::Question); + box.setWindowTitle(tr("Confirm Save As Copy")); + + QString prompt = tr("Save as Copy"); + box.setText(prompt); + + box.setInformativeText(tr("Saving a copy is not recommended as it can break other documents. " + "We recommend you save as a new material.")); + + QPushButton* duplicateButton = box.addButton(tr("Save Copy"), QMessageBox::AcceptRole); + QPushButton* newButton = box.addButton(tr("Save As New"), QMessageBox::ActionRole); + QPushButton* cancelButton = box.addButton(QMessageBox::Cancel); + + box.setDefaultButton(cancelButton); + box.setEscapeButton(cancelButton); + + box.adjustSize(); // Silence warnings from Qt on Windows + box.exec(); + + int res = QMessageBox::Cancel; + if (box.clickedButton() == duplicateButton) { + res = QMessageBox::Save; + } + else if (box.clickedButton() == newButton) { + res = QMessageBox::Ok; + } + + return res; +} + void MaterialSave::onCancel(bool checked) { Q_UNUSED(checked) @@ -135,7 +290,7 @@ void MaterialSave::setLibraries() for (auto library : *libraries) { if (!library->isReadOnly()) { QVariant libraryVariant; - libraryVariant.setValue(*library); + libraryVariant.setValue(library); ui->comboLibrary->addItem(library->getName(), libraryVariant); } } @@ -163,31 +318,34 @@ void MaterialSave::addExpanded(QTreeView* tree, QStandardItemModel* parent, QSta void MaterialSave::addMaterials( QStandardItem& parent, - const std::shared_ptr> modelTree, + const std::shared_ptr>> + modelTree, const QIcon& folderIcon, const QIcon& icon) { auto tree = ui->treeMaterials; for (auto& mat : *modelTree) { - Materials::MaterialTreeNode* nodePtr = mat.second; + std::shared_ptr nodePtr = mat.second; if (nodePtr->getType() == Materials::MaterialTreeNode::DataNode) { - const Materials::Material* material = nodePtr->getData(); + std::shared_ptr material = nodePtr->getData(); QString uuid = material->getUUID(); Base::Console().Log("Material path '%s'\n", material->getDirectory().toStdString().c_str()); - // auto card = new QStandardItem(icon, material->getName()); auto card = new QStandardItem(icon, mat.first); - // card->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled - // | Qt::ItemIsDropEnabled); + card->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled + | Qt::ItemIsDropEnabled); card->setData(QVariant(uuid), Qt::UserRole); addExpanded(tree, &parent, card); } else { + Base::Console().Log("Material folder path '%s'\n", mat.first.toStdString().c_str()); auto node = new QStandardItem(folderIcon, mat.first); + node->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled + | Qt::ItemIsDropEnabled | Qt::ItemIsEditable); addExpanded(tree, &parent, node); - // node->setFlags(Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled); + auto treeMap = nodePtr->getFolder(); addMaterials(*node, treeMap, folderIcon, icon); } @@ -202,13 +360,14 @@ void MaterialSave::showSelectedTree() if (ui->comboLibrary->count() > 0) { auto variant = ui->comboLibrary->currentData(); - auto library = variant.value(); - QIcon icon(library.getIconPath()); + auto library = variant.value>(); + QIcon icon(library->getIconPath()); QIcon folderIcon(QString::fromStdString(":/icons/folder.svg")); - _libraryName = library.getName(); + _libraryName = library->getName(); _selectedPath = QString::fromStdString("/") + _libraryName; + _selectedFull = _selectedPath; - auto lib = new QStandardItem(library.getName()); + auto lib = new QStandardItem(library->getName()); lib->setFlags(Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled); addExpanded(tree, model, lib); @@ -246,6 +405,7 @@ void MaterialSave::onSelectModel(const QItemSelection& selected, const QItemSele if (indexes.count() == 0) { Base::Console().Log("Nothing selected\n"); _selectedPath = QString::fromStdString("/") + _libraryName; + _selectedFull = _selectedPath; _selectedUUID = QString(); Base::Console().Log("\tSelected path '%s'\n", _selectedPath.toStdString().c_str()); return; @@ -258,11 +418,13 @@ void MaterialSave::onSelectModel(const QItemSelection& selected, const QItemSele if (_selected.isValid()) { Base::Console().Log("\tuuid %s\n", _selected.toString().toStdString().c_str()); _selectedPath = getPath(item->parent()); + _selectedFull = getPath(item); _selectedUUID = _selected.toString(); _filename = item->text(); } else { _selectedPath = getPath(item); + _selectedFull = _selectedPath; _selectedUUID = QString(); } } @@ -282,6 +444,34 @@ void MaterialSave::currentTextChanged(const QString& value) showSelectedTree(); } +std::shared_ptr MaterialSave::currentLibrary() +{ + auto variant = ui->comboLibrary->currentData(); + return variant.value>(); +} + +void MaterialSave::createFolder(const QString& path) +{ + auto library = currentLibrary(); + + _manager.createFolder(library, path); +} + +void MaterialSave::renameFolder(const QString& oldPath, const QString& newPath) +{ + auto library = currentLibrary(); + + _manager.renameFolder(library, oldPath, newPath); +} + +void MaterialSave::deleteRecursive(const QString& path) +{ + // This will delete files, folders, and any children + auto library = currentLibrary(); + + _manager.deleteRecursive(library, path); +} + void MaterialSave::onNewFolder(bool checked) { Q_UNUSED(checked) @@ -293,16 +483,53 @@ void MaterialSave::onNewFolder(bool checked) current = model->index(0, 0); } auto item = model->itemFromIndex(current); + + // Check for existing folders starting "New Folder" to prevent duplicates + int newCount = 0; if (item->hasChildren()) { + for (auto i = 0; i < item->rowCount(); i++) { + auto child = item->child(i); + if (child->text().startsWith(tr("New Folder"))) { + newCount++; + } + } + } + + // Folders have no associated data + if (item->data(Qt::UserRole).isNull()) { Base::Console().Log("Add new folder to '%s'\n", item->text().toStdString().c_str()); QIcon folderIcon(QString::fromStdString(":/icons/folder.svg")); - auto node = new QStandardItem(folderIcon, QString::fromStdString("New Folder")); + QString folderName = tr("New Folder"); + if (newCount > 0) { + folderName += QString::number(newCount); + } + auto node = new QStandardItem(folderIcon, folderName); + node->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled + | Qt::ItemIsDropEnabled | Qt::ItemIsEditable); addExpanded(tree, item, node); - // node->setFlags(Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled); + + Base::Console().Log("New folder index valid: %s\n", + node->index().isValid() ? "true" : "false"); + + QItemSelectionModel* selectionModel = ui->treeMaterials->selectionModel(); + selectionModel->select(node->index(), + QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Current); + + createFolder(getPath(node)); } } +void MaterialSave::onItemChanged(QStandardItem* item) +{ + Base::Console().Log("MaterialSave::onItemChanged('%s')\n", item->text().toStdString().c_str()); + QString oldPath = _selectedPath; + _selectedPath = getPath(item); + _selectedFull = _selectedPath; + Base::Console().Log("\tSelected path '%s'\n", _selectedPath.toStdString().c_str()); + renameFolder(oldPath, _selectedPath); +} + void MaterialSave::onFilename(const QString& text) { Base::Console().Log("MaterialSave::onFilename('%s')\n", text.toStdString().c_str()); @@ -310,4 +537,135 @@ void MaterialSave::onFilename(const QString& text) _filename = text; } +QString MaterialSave::pathFromIndex(const QModelIndex& index) const +{ + auto model = static_cast(index.model()); + auto item = model->itemFromIndex(index); + return getPath(item); +} + +void MaterialSave::onContextMenu(const QPoint& pos) +{ + Base::Console().Log("MaterialSave::onContextMenu(%d,%d)\n", pos.x(), pos.y()); + QModelIndex index = ui->treeMaterials->indexAt(pos); + QString path = pathFromIndex(index); + Base::Console().Log("\tindex at (%d,%d)->'%s'\n", + index.row(), + index.column(), + path.toStdString().c_str()); + + + QMenu contextMenu(tr("Context menu"), this); + + // QAction action1(tr("Delete"), this); + // action1.setShortcut(Qt::Key_Delete); + // connect(&action1, &QAction::triggered, this, &MaterialSave::onDelete); + contextMenu.addAction(&_deleteAction); + + contextMenu.exec(ui->treeMaterials->mapToGlobal(pos)); +} + +void MaterialSave::onDelete(bool checked) +{ + Q_UNUSED(checked) + + Base::Console().Log("MaterialSave::onDelete()\n"); + QItemSelectionModel* selectionModel = ui->treeMaterials->selectionModel(); + if (!selectionModel->hasSelection()) { + Base::Console().Log("\tNothing selected\n"); + return; + } + + Base::Console().Log("\tSelected path '%s'\n", _selectedFull.toStdString().c_str()); + int res = confirmDelete(this); + if (res == QMessageBox::Cancel) { + return; + } +} + +int MaterialSave::confirmDelete(QWidget* parent) +{ + auto library = currentLibrary(); + + if (library->isRoot(_selectedFull)) { + return QMessageBox::Cancel; + } + + QMessageBox box(parent ? parent : this); + box.setIcon(QMessageBox::Question); + box.setWindowTitle(QObject::tr("Confirm Delete")); + + QFileInfo info(_selectedFull); + QString prompt = QObject::tr("Are you sure you want to delete '%1'?").arg(info.fileName()); + box.setText(prompt); + + if (selectedHasChildren()) { + box.setInformativeText(QObject::tr("Removing this will also remove all contents.")); + } + box.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel); + box.setDefaultButton(QMessageBox::Cancel); + box.setEscapeButton(QMessageBox::Cancel); + + int res = QMessageBox::Cancel; + box.adjustSize(); // Silence warnings from Qt on Windows + switch (box.exec()) { + case QMessageBox::Ok: + deleteSelected(); + res = QMessageBox::Ok; + break; + } + + return res; +} + +bool MaterialSave::selectedHasChildren() +{ + auto tree = ui->treeMaterials; + auto model = static_cast(tree->model()); + auto current = tree->currentIndex(); + if (!current.isValid()) { + current = model->index(0, 0); + } + auto item = model->itemFromIndex(current); + + return item->hasChildren(); +} + +void MaterialSave::deleteSelected() +{ + Base::Console().Log("\tDelete selected path '%s'\n", _selectedFull.toStdString().c_str()); + auto library = currentLibrary(); + + if (!library->isRoot(_selectedFull)) { + _manager.deleteRecursive(library, _selectedFull); + removeSelectedFromTree(); + } +} + +void MaterialSave::removeChildren(QStandardItem* item) +{ + while (item->rowCount() > 0) { + auto child = item->child(0); + removeChildren(child); + item->removeRow(0); + } +} + +void MaterialSave::removeSelectedFromTree() +{ + auto tree = ui->treeMaterials; + auto model = static_cast(tree->model()); + auto current = tree->currentIndex(); + if (current.row() >= 0) { + auto item = model->itemFromIndex(current); + + // Remove the children + removeChildren(item); + item->parent()->removeRow(item->row()); + } + + QItemSelectionModel* selectionModel = ui->treeMaterials->selectionModel(); + selectionModel->clear(); +} + #include "moc_MaterialSave.cpp" diff --git a/src/Mod/Material/Gui/MaterialSave.h b/src/Mod/Material/Gui/MaterialSave.h index 56dc196cd1..620c21ba70 100644 --- a/src/Mod/Material/Gui/MaterialSave.h +++ b/src/Mod/Material/Gui/MaterialSave.h @@ -22,8 +22,9 @@ #ifndef MATGUI_MATERIALSAVE_H #define MATGUI_MATERIALSAVE_H -// #include +#include +#include #include #include #include @@ -41,39 +42,61 @@ class MaterialSave: public QDialog Q_OBJECT public: - explicit MaterialSave(Materials::Material* material, QWidget* parent = nullptr); + MaterialSave(std::shared_ptr material, QWidget* parent = nullptr); ~MaterialSave() override; void setLibraries(); void createModelTree(); void addExpanded(QTreeView* tree, QStandardItem* parent, QStandardItem* child); void addExpanded(QTreeView* tree, QStandardItemModel* parent, QStandardItem* child); - void - addMaterials(QStandardItem& parent, - const std::shared_ptr> modelTree, - const QIcon& folderIcon, - const QIcon& icon); + void addMaterials( + QStandardItem& parent, + const std::shared_ptr>> + modelTree, + const QIcon& folderIcon, + const QIcon& icon); void showSelectedTree(); void onSelectModel(const QItemSelection& selected, const QItemSelection& deselected); void currentTextChanged(const QString& value); void onNewFolder(bool checked); + void onItemChanged(QStandardItem* item); void onFilename(const QString& text); + void onContextMenu(const QPoint& pos); + void onDelete(bool checked); + void onInherited(int state); void onOk(bool checked); void onCancel(bool checked); + int confirmOverwrite(const QString& filename); + int confirmNewMaterial(); + int confirmCopy(); void accept() override; void reject() override; private: std::unique_ptr ui; Materials::MaterialManager _manager; - Materials::Material* _material; + std::shared_ptr _material; + bool _saveInherited; QString _selectedPath; + QString _selectedFull; QString _selectedUUID; QString _libraryName; QString _filename; + QAction _deleteAction; + QString getPath(const QStandardItem* item) const; + std::shared_ptr currentLibrary(); + void createFolder(const QString& path); + void renameFolder(const QString& oldPath, const QString& newPath); + void deleteRecursive(const QString& path); + QString pathFromIndex(const QModelIndex& index) const; + int confirmDelete(QWidget* parent); + bool selectedHasChildren(); + void deleteSelected(); + void removeChildren(QStandardItem* item); + void removeSelectedFromTree(); }; } // namespace MatGui diff --git a/src/Mod/Material/Gui/MaterialSave.ui b/src/Mod/Material/Gui/MaterialSave.ui index a6a719e5a6..7298e6a23a 100644 --- a/src/Mod/Material/Gui/MaterialSave.ui +++ b/src/Mod/Material/Gui/MaterialSave.ui @@ -83,6 +83,30 @@ + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Save as Inherited + + + + + diff --git a/src/Mod/Material/Gui/MaterialsEditor.cpp b/src/Mod/Material/Gui/MaterialsEditor.cpp index 7916805b0c..c3c15c6b2a 100644 --- a/src/Mod/Material/Gui/MaterialsEditor.cpp +++ b/src/Mod/Material/Gui/MaterialsEditor.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -35,6 +36,7 @@ #include #include +#include #include #include #include @@ -61,6 +63,7 @@ using namespace MatGui; MaterialsEditor::MaterialsEditor(QWidget* parent) : QDialog(parent) , ui(new Ui_MaterialsEditor) + , _material(std::make_shared()) , _edited(false) { ui->setupUi(this); @@ -72,6 +75,7 @@ MaterialsEditor::MaterialsEditor(QWidget* parent) createPhysicalTree(); createAppearanceTree(); createPreviews(); + setMaterialDefaults(); ui->buttonURL->setIcon(QIcon(QString::fromStdString(":/icons/internet-web-browser.svg"))); @@ -88,12 +92,35 @@ MaterialsEditor::MaterialsEditor(QWidget* parent) this, &MaterialsEditor::onSave); + connect(ui->editName, &QLineEdit::textEdited, this, &MaterialsEditor::onName); + connect(ui->editAuthor, &QLineEdit::textEdited, this, &MaterialsEditor::onAuthor); + connect(ui->editLicense, &QLineEdit::textEdited, this, &MaterialsEditor::onLicense); + connect(ui->editSourceURL, &QLineEdit::textEdited, this, &MaterialsEditor::onSourceURL); + connect(ui->editSourceReference, + &QLineEdit::textEdited, + this, + &MaterialsEditor::onSourceReference); + connect(ui->editDescription, &QTextEdit::textChanged, this, &MaterialsEditor::onDescription); + connect(ui->buttonURL, &QPushButton::clicked, this, &MaterialsEditor::onURL); connect(ui->buttonPhysicalAdd, &QPushButton::clicked, this, &MaterialsEditor::onPhysicalAdd); + connect(ui->buttonPhysicalRemove, + &QPushButton::clicked, + this, + &MaterialsEditor::onPhysicalRemove); connect(ui->buttonAppearanceAdd, &QPushButton::clicked, this, &MaterialsEditor::onAppearanceAdd); + connect(ui->buttonAppearanceRemove, + &QPushButton::clicked, + this, + &MaterialsEditor::onAppearanceRemove); + connect(ui->buttonInheritNew, + &QPushButton::clicked, + this, + &MaterialsEditor::onInheritNewMaterial); + connect(ui->buttonNew, &QPushButton::clicked, this, &MaterialsEditor::onNewMaterial); connect(ui->buttonFavorite, &QPushButton::clicked, this, &MaterialsEditor::onFavourite); QItemSelectionModel* selectionModel = ui->treeMaterials->selectionModel(); @@ -101,6 +128,13 @@ MaterialsEditor::MaterialsEditor(QWidget* parent) &QItemSelectionModel::selectionChanged, this, &MaterialsEditor::onSelectMaterial); + connect(ui->treeMaterials, &QTreeView::doubleClicked, this, &MaterialsEditor::onDoubleClick); + + ui->treeMaterials->setContextMenuPolicy(Qt::CustomContextMenu); + connect(ui->treeMaterials, + &QWidget::customContextMenuRequested, + this, + &MaterialsEditor::onContextMenu); } void MaterialsEditor::getFavorites() @@ -144,7 +178,7 @@ void MaterialsEditor::addFavorite(const QString& uuid) { // Ensure it is a material. New, unsaved materials will not be try { - const Materials::Material& material = _materialManager.getMaterial(uuid); + auto material = _materialManager.getMaterial(uuid); Q_UNUSED(material) } catch (const Materials::MaterialNotFound&) { @@ -227,7 +261,7 @@ void MaterialsEditor::addRecent(const QString& uuid) { // Ensure it is a material. New, unsaved materials will not be try { - const Materials::Material& material = _materialManager.getMaterial(uuid); + auto material = _materialManager.getMaterial(uuid); Q_UNUSED(material) } catch (const Materials::MaterialNotFound&) { @@ -257,16 +291,46 @@ bool MaterialsEditor::isRecent(const QString& uuid) const return false; } +void MaterialsEditor::onName(const QString& text) +{ + _material->setName(text); +} + +void MaterialsEditor::onAuthor(const QString& text) +{ + _material->setAuthor(text); +} + +void MaterialsEditor::onLicense(const QString& text) +{ + _material->setLicense(text); +} + +void MaterialsEditor::onSourceURL(const QString& text) +{ + _material->setURL(text); +} + +void MaterialsEditor::onSourceReference(const QString& text) +{ + _material->setReference(text); +} + +void MaterialsEditor::onDescription() +{ + _material->setDescription(ui->editDescription->toPlainText()); +} + void MaterialsEditor::propertyChange(const QString& property, const QString value) { Base::Console().Log("MaterialsEditor::propertyChange(%s) = '%s'\n", property.toStdString().c_str(), value.toStdString().c_str()); - if (_material.hasPhysicalProperty(property)) { - _material.setPhysicalValue(property, value); + if (_material->hasPhysicalProperty(property)) { + _material->setPhysicalValue(property, value); } - else if (_material.hasAppearanceProperty(property)) { - _material.setAppearanceValue(property, value); + else if (_material->hasAppearanceProperty(property)) { + _material->setAppearanceValue(property, value); updatePreview(); } _edited = true; @@ -287,12 +351,12 @@ void MaterialsEditor::onPhysicalAdd(bool checked) { Q_UNUSED(checked) - ModelSelect dialog(this, Materials::ModelManager::ModelFilter_Physical); + ModelSelect dialog(this, Materials::ModelFilter_Physical); dialog.setModal(true); if (dialog.exec() == QDialog::Accepted) { QString selected = dialog.selectedModel(); Base::Console().Log("Selected model '%s'\n", selected.toStdString().c_str()); - _material.addPhysical(selected); + _material->addPhysical(selected); updateMaterial(); } else { @@ -300,16 +364,39 @@ void MaterialsEditor::onPhysicalAdd(bool checked) } } +void MaterialsEditor::onPhysicalRemove(bool checked) +{ + Q_UNUSED(checked) + + QItemSelectionModel* selectionModel = ui->treePhysicalProperties->selectionModel(); + if (selectionModel->hasSelection()) { + const QModelIndex index = selectionModel->currentIndex().siblingAtColumn(0); + + const QStandardItemModel* treeModel = static_cast(index.model()); + + // Check we're the material model root. + auto item = treeModel->itemFromIndex(index); + auto group = item->parent(); + if (!group) { + QString propertyName = index.data().toString(); + + QString uuid = _material->getModelByName(propertyName); + _material->removePhysical(uuid); + updateMaterial(); + } + } +} + void MaterialsEditor::onAppearanceAdd(bool checked) { Q_UNUSED(checked) - ModelSelect dialog(this, Materials::ModelManager::ModelFilter_Appearance); + ModelSelect dialog(this, Materials::ModelFilter_Appearance); dialog.setModal(true); if (dialog.exec() == QDialog::Accepted) { QString selected = dialog.selectedModel(); Base::Console().Log("Selected model '%s'\n", selected.toStdString().c_str()); - _material.addAppearance(selected); + _material->addAppearance(selected); updateMaterial(); } else { @@ -317,12 +404,35 @@ void MaterialsEditor::onAppearanceAdd(bool checked) } } +void MaterialsEditor::onAppearanceRemove(bool checked) +{ + Q_UNUSED(checked) + + QItemSelectionModel* selectionModel = ui->treeAppearance->selectionModel(); + if (selectionModel->hasSelection()) { + const QModelIndex index = selectionModel->currentIndex().siblingAtColumn(0); + + const QStandardItemModel* treeModel = static_cast(index.model()); + + // Check we're the material model root. + auto item = treeModel->itemFromIndex(index); + auto group = item->parent(); + if (!group) { + QString propertyName = index.data().toString(); + + QString uuid = _material->getModelByName(propertyName); + _material->removeAppearance(uuid); + updateMaterial(); + } + } +} + void MaterialsEditor::onFavourite(bool checked) { Q_UNUSED(checked) Base::Console().Log("Favorite\n"); - auto selected = _material.getUUID(); + auto selected = _material->getUUID(); if (isFavorite(selected)) { removeFavorite(selected); } @@ -331,6 +441,76 @@ void MaterialsEditor::onFavourite(bool checked) } } +void MaterialsEditor::setMaterialDefaults() +{ + _material->setName(tr("Unnamed")); + std::string Author = App::GetApplication() + .GetParameterGroupByPath("User parameter:BaseApp/Preferences/Document") + ->GetASCII("prefAuthor", ""); + _material->setAuthor(QString::fromStdString(Author)); + + // license stuff + auto paramGrp {App::GetApplication().GetParameterGroupByPath( + "User parameter:BaseApp/Preferences/Document")}; + auto index = static_cast(paramGrp->GetInt("prefLicenseType", 0)); + const char* name = App::licenseItems.at(index).at(App::posnOfFullName); + // const char* url = App::licenseItems.at(index).at(App::posnOfUrl); + // std::string licenseUrl = (paramGrp->GetASCII("prefLicenseUrl", url)); + _material->setLicense(QString::fromStdString(name)); + + // Empty materials will have no parent + _materialManager.dereference(_material); + + updateMaterial(); + _material->resetEditState(); +} + +void MaterialsEditor::onNewMaterial(bool checked) +{ + Q_UNUSED(checked) + + Base::Console().Log("New Material\n"); + + // Ensure data is saved (or discarded) before changing materials + if (_material->getEditState() != Materials::Material::ModelEdit_None) { + // Prompt the user to save or discard changes + Base::Console().Log("*** Material edited!!!\n"); + int res = confirmSave(this); + if (res == QMessageBox::Cancel) { + return; + } + } + + // Create a new material + _material = std::make_shared(); + setMaterialDefaults(); +} + +void MaterialsEditor::onInheritNewMaterial(bool checked) +{ + Q_UNUSED(checked) + + Base::Console().Log("Inherit New Material\n"); + + // Save the current UUID to use as out parent + auto parent = _material->getUUID(); + + // Ensure data is saved (or discarded) before changing materials + if (_material->getEditState() != Materials::Material::ModelEdit_None) { + // Prompt the user to save or discard changes + Base::Console().Log("*** Material edited!!!\n"); + int res = confirmSave(this); + if (res == QMessageBox::Cancel) { + return; + } + } + + // Create a new material + _material = std::make_shared(); + _material->setParentUUID(parent); + setMaterialDefaults(); +} + void MaterialsEditor::onOk(bool checked) { Q_UNUSED(checked) @@ -354,17 +534,18 @@ void MaterialsEditor::onSave(bool checked) void MaterialsEditor::saveMaterial() { - MaterialSave dialog(&_material, this); + MaterialSave dialog(_material, this); dialog.setModal(true); if (dialog.exec() == QDialog::Accepted) { - _material.resetEditState(); + updateMaterialGeneral(); + _material->resetEditState(); refreshMaterialTree(); } } void MaterialsEditor::accept() { - addRecent(_material.getUUID()); + addRecent(_material->getUUID()); QDialog::accept(); } @@ -379,15 +560,16 @@ void MaterialsEditor::reject() void MaterialsEditor::addMaterials( QStandardItem& parent, - const std::shared_ptr> modelTree, + const std::shared_ptr>> + modelTree, const QIcon& folderIcon, const QIcon& icon) { auto tree = ui->treeMaterials; for (auto& mat : *modelTree) { - Materials::MaterialTreeNode* nodePtr = mat.second; + std::shared_ptr nodePtr = mat.second; if (nodePtr->getType() == Materials::MaterialTreeNode::DataNode) { - const Materials::Material* material = nodePtr->getData(); + auto material = nodePtr->getData(); QString uuid = material->getUUID(); // Base::Console().Log("Material path '%s'\n", // material->getDirectory().toStdString().c_str()); @@ -429,9 +611,9 @@ void MaterialsEditor::createPhysicalTree() tree->setModel(model); QStringList headers; - headers.append(QString::fromStdString("Property")); - headers.append(QString::fromStdString("Value")); - headers.append(QString::fromStdString("Type")); + headers.append(tr("Property")); + headers.append(tr("Value")); + headers.append(tr("Type")); model->setHorizontalHeaderLabels(headers); tree->setColumnWidth(0, 250); @@ -444,6 +626,12 @@ void MaterialsEditor::createPhysicalTree() tree->setItemDelegateForColumn(1, delegate); connect(delegate, &MaterialDelegate::propertyChange, this, &MaterialsEditor::propertyChange); + + // QItemSelectionModel* selectionModel = ui->treePhysicalProperties->selectionModel(); + // connect(selectionModel, + // &QItemSelectionModel::selectionChanged, + // this, + // &MaterialsEditor::onSelectPhysicalProperty); } void MaterialsEditor::createPreviews() @@ -468,9 +656,9 @@ void MaterialsEditor::createAppearanceTree() tree->setModel(model); QStringList headers; - headers.append(QString::fromStdString("Property")); - headers.append(QString::fromStdString("Value")); - headers.append(QString::fromStdString("Type")); + headers.append(tr("Property")); + headers.append(tr("Value")); + headers.append(tr("Type")); model->setHorizontalHeaderLabels(headers); tree->setColumnWidth(0, 250); @@ -490,10 +678,10 @@ void MaterialsEditor::addRecents(QStandardItem* parent) auto tree = ui->treeMaterials; for (auto& uuid : _recents) { try { - const Materials::Material& material = getMaterialManager().getMaterial(uuid); + auto material = getMaterialManager().getMaterial(uuid); - QIcon icon = QIcon(material.getLibrary().getIconPath()); - auto card = new QStandardItem(icon, material.getName()); + QIcon icon = QIcon(material->getLibrary()->getIconPath()); + auto card = new QStandardItem(icon, libraryPath(material)); card->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled); card->setData(QVariant(uuid), Qt::UserRole); @@ -510,10 +698,10 @@ void MaterialsEditor::addFavorites(QStandardItem* parent) auto tree = ui->treeMaterials; for (auto& uuid : _favorites) { try { - const Materials::Material& material = getMaterialManager().getMaterial(uuid); + auto material = getMaterialManager().getMaterial(uuid); - QIcon icon = QIcon(material.getLibrary().getIconPath()); - auto card = new QStandardItem(icon, material.getName()); + QIcon icon = QIcon(material->getLibrary()->getIconPath()); + auto card = new QStandardItem(icon, libraryPath(material)); card->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled); card->setData(QVariant(uuid), Qt::UserRole); @@ -530,12 +718,12 @@ void MaterialsEditor::fillMaterialTree() auto tree = ui->treeMaterials; auto model = static_cast(tree->model()); - auto lib = new QStandardItem(QString::fromStdString("Favorites")); + auto lib = new QStandardItem(tr("Favorites")); lib->setFlags(Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled); addExpanded(tree, model, lib); addFavorites(lib); - lib = new QStandardItem(QString::fromStdString("Recent")); + lib = new QStandardItem(tr("Recent")); lib->setFlags(Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled); addExpanded(tree, model, lib); addRecents(lib); @@ -549,7 +737,7 @@ void MaterialsEditor::fillMaterialTree() QIcon icon(library->getIconPath()); QIcon folderIcon(QString::fromStdString(":/icons/folder.svg")); - auto modelTree = _materialManager.getMaterialTree(*library); + auto modelTree = _materialManager.getMaterialTree(library); addMaterials(*lib, modelTree, folderIcon, icon); } } @@ -582,23 +770,23 @@ void MaterialsEditor::updatePreview() const QString highlightColor; QString sectionColor; - if (_material.hasAppearanceProperty(QString::fromStdString("DiffuseColor"))) { - diffuseColor = _material.getAppearanceValueString(QString::fromStdString("DiffuseColor")); + if (_material->hasAppearanceProperty(QString::fromStdString("DiffuseColor"))) { + diffuseColor = _material->getAppearanceValueString(QString::fromStdString("DiffuseColor")); } - else if (_material.hasAppearanceProperty(QString::fromStdString("ViewColor"))) { - diffuseColor = _material.getAppearanceValueString(QString::fromStdString("ViewColor")); + else if (_material->hasAppearanceProperty(QString::fromStdString("ViewColor"))) { + diffuseColor = _material->getAppearanceValueString(QString::fromStdString("ViewColor")); } - else if (_material.hasAppearanceProperty(QString::fromStdString("Color"))) { - diffuseColor = _material.getAppearanceValueString(QString::fromStdString("Color")); + else if (_material->hasAppearanceProperty(QString::fromStdString("Color"))) { + diffuseColor = _material->getAppearanceValueString(QString::fromStdString("Color")); } - if (_material.hasAppearanceProperty(QString::fromStdString("SpecularColor"))) { + if (_material->hasAppearanceProperty(QString::fromStdString("SpecularColor"))) { highlightColor = - _material.getAppearanceValueString(QString::fromStdString("SpecularColor")); + _material->getAppearanceValueString(QString::fromStdString("SpecularColor")); } - if (_material.hasAppearanceProperty(QString::fromStdString("SectionColor"))) { - sectionColor = _material.getAppearanceValueString(QString::fromStdString("SectionColor")); + if (_material->hasAppearanceProperty(QString::fromStdString("SectionColor"))) { + sectionColor = _material->getAppearanceValueString(QString::fromStdString("SectionColor")); } if ((diffuseColor.length() + highlightColor.length()) > 0) { @@ -678,28 +866,28 @@ void MaterialsEditor::updateMaterialAppearance() treeModel->clear(); QStringList headers; - headers.append(QString::fromStdString("Property")); - headers.append(QString::fromStdString("Value")); - headers.append(QString::fromStdString("Type")); + headers.append(tr("Property")); + headers.append(tr("Value")); + headers.append(tr("Type")); treeModel->setHorizontalHeaderLabels(headers); tree->setColumnWidth(0, 250); tree->setColumnWidth(1, 250); tree->setColumnHidden(2, true); - const std::vector* models = _material.getAppearanceModels(); + auto models = _material->getAppearanceModels(); if (models) { for (auto it = models->begin(); it != models->end(); it++) { QString uuid = *it; try { - const Materials::Model& model = getModelManager().getModel(uuid); - QString name = model.getName(); + auto model = getModelManager().getModel(uuid); + QString name = model->getName(); auto modelRoot = new QStandardItem(name); modelRoot->setFlags(Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled); addExpanded(tree, treeModel, modelRoot); - for (auto itp = model.begin(); itp != model.end(); itp++) { + for (auto itp = model->begin(); itp != model->end(); itp++) { QList items; QString key = itp->first; @@ -707,10 +895,10 @@ void MaterialsEditor::updateMaterialAppearance() propertyItem->setToolTip(itp->second.getDescription()); items.append(propertyItem); - auto valueItem = new QStandardItem(_material.getAppearanceValueString(key)); + auto valueItem = new QStandardItem(_material->getAppearanceValueString(key)); valueItem->setToolTip(itp->second.getDescription()); QVariant variant; - variant.setValue(&_material); + variant.setValue(_material); valueItem->setData(variant); items.append(valueItem); @@ -737,10 +925,10 @@ void MaterialsEditor::updateMaterialProperties() treeModel->clear(); QStringList headers; - headers.append(QString::fromStdString("Property")); - headers.append(QString::fromStdString("Value")); - headers.append(QString::fromStdString("Type")); - headers.append(QString::fromStdString("Units")); + headers.append(tr("Property")); + headers.append(tr("Value")); + headers.append(tr("Type")); + headers.append(tr("Units")); treeModel->setHorizontalHeaderLabels(headers); tree->setColumnWidth(0, 250); @@ -748,19 +936,19 @@ void MaterialsEditor::updateMaterialProperties() tree->setColumnHidden(2, true); tree->setColumnHidden(3, true); - const std::vector* models = _material.getPhysicalModels(); + auto models = _material->getPhysicalModels(); if (models) { for (auto it = models->begin(); it != models->end(); it++) { QString uuid = *it; try { - const Materials::Model& model = getModelManager().getModel(uuid); - QString name = model.getName(); + auto model = getModelManager().getModel(uuid); + QString name = model->getName(); auto modelRoot = new QStandardItem(name); modelRoot->setFlags(Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled); addExpanded(tree, treeModel, modelRoot); - for (auto itp = model.begin(); itp != model.end(); itp++) { + for (auto itp = model->begin(); itp != model->end(); itp++) { QList items; QString key = itp->first; @@ -770,10 +958,10 @@ void MaterialsEditor::updateMaterialProperties() propertyItem->setToolTip(modelProperty.getDescription()); items.append(propertyItem); - auto valueItem = new QStandardItem(_material.getPhysicalValueString(key)); + auto valueItem = new QStandardItem(_material->getPhysicalValueString(key)); valueItem->setToolTip(modelProperty.getDescription()); QVariant variant; - variant.setValue(&_material); + variant.setValue(_material); valueItem->setData(variant); items.append(valueItem); @@ -794,17 +982,47 @@ void MaterialsEditor::updateMaterialProperties() } } +QString MaterialsEditor::libraryPath(std::shared_ptr material) const +{ + QString path; + auto library = material->getLibrary(); + if (library) { + path = QString::fromStdString("/%1/%2") + .arg(material->getLibrary()->getName()) + .arg(material->getDirectory()); + } + else { + path = QString::fromStdString("%1").arg(material->getDirectory()); + } + + return path; +} + +void MaterialsEditor::updateMaterialGeneral() +{ + QString parentString; + try { + auto parent = _materialManager.getParent(_material); + parentString = libraryPath(parent); + } + catch (const Materials::MaterialNotFound&) { + } + + // Update the general information + ui->editName->setText(_material->getName()); + ui->editAuthor->setText(_material->getAuthor()); + ui->editLicense->setText(_material->getLicense()); + ui->editParent->setText(parentString); + ui->editParent->setReadOnly(true); + ui->editSourceURL->setText(_material->getURL()); + ui->editSourceReference->setText(_material->getReference()); + // ui->editTags->setText(_material->getName()); + ui->editDescription->setText(_material->getDescription()); +} + void MaterialsEditor::updateMaterial() { - // Update the general information - ui->editName->setText(_material.getName()); - ui->editAuthorLicense->setText(_material.getAuthorAndLicense()); - // ui->editParent->setText(_material.getName()); - ui->editSourceURL->setText(_material.getURL()); - ui->editSourceReference->setText(_material.getReference()); - // ui->editTags->setText(_material.getName()); - ui->editDescription->setText(_material.getDescription()); - + updateMaterialGeneral(); updateMaterialProperties(); updateMaterialAppearance(); @@ -830,13 +1048,13 @@ void MaterialsEditor::onSelectMaterial(const QItemSelection& selected, } } - if (uuid.isEmpty() || uuid == _material.getUUID()) { + if (uuid.isEmpty() || uuid == _material->getUUID()) { Base::Console().Log("*** Unchanged material '%s'\n", uuid.toStdString().c_str()); return; } // Ensure data is saved (or discarded) before changing materials - if (_material.getEditState() != Materials::Material::ModelEdit_None) { + if (_material->getEditState() != Materials::Material::ModelEdit_None) { // Prompt the user to save or discard changes Base::Console().Log("*** Material edited!!!\n"); int res = confirmSave(this); @@ -847,16 +1065,85 @@ void MaterialsEditor::onSelectMaterial(const QItemSelection& selected, // Get the selected material try { - _material = getMaterialManager().getMaterial(uuid); + _material = std::make_shared(*getMaterialManager().getMaterial(uuid)); } catch (Materials::ModelNotFound const&) { Base::Console().Log("*** Unable to load material '%s'\n", uuid.toStdString().c_str()); - Materials::Material empty; - _material = empty; + _material = std::make_shared(); } updateMaterial(); - _material.resetEditState(); + _material->resetEditState(); +} + +void MaterialsEditor::onDoubleClick(const QModelIndex& index) +{ + Q_UNUSED(index) + + Base::Console().Log("MaterialsEditor::onDoubleClick()\n"); + accept(); +} + +void MaterialsEditor::onContextMenu(const QPoint& pos) +{ + Base::Console().Log("MaterialsEditor::onContextMenu(%d,%d)\n", pos.x(), pos.y()); + // QModelIndex index = ui->treeMaterials->indexAt(pos); + // QString path = pathFromIndex(index); + // Base::Console().Log("\tindex at (%d,%d)->'%s'\n", + // index.row(), + // index.column(), + // path.toStdString().c_str()); + + + QMenu contextMenu(tr("Context menu"), this); + + QAction action1(tr("Inherit from"), this); + // action1.setShortcut(Qt::Key_Delete); + connect(&action1, &QAction::triggered, this, &MaterialsEditor::onInherit); + contextMenu.addAction(&action1); + + QAction action2(tr("Inherit new material"), this); + // action1.setShortcut(Qt::Key_Delete); + connect(&action2, &QAction::triggered, this, &MaterialsEditor::onInheritNew); + contextMenu.addAction(&action2); + + contextMenu.exec(ui->treeMaterials->mapToGlobal(pos)); +} + +void MaterialsEditor::onInherit(bool checked) +{ + Q_UNUSED(checked) + + Base::Console().Log("MaterialsEditor::onInherit()\n"); + // QItemSelectionModel* selectionModel = ui->treeMaterials->selectionModel(); + // if (!selectionModel->hasSelection()) { + // Base::Console().Log("\tNothing selected\n"); + // return; + // } + + // Base::Console().Log("\tSelected path '%s'\n", _selectedFull.toStdString().c_str()); + // int res = confirmDelete(this); + // if (res == QMessageBox::Cancel) { + // return; + // } +} + +void MaterialsEditor::onInheritNew(bool checked) +{ + Q_UNUSED(checked) + + Base::Console().Log("MaterialsEditor::onInherit()\n"); + // QItemSelectionModel* selectionModel = ui->treeMaterials->selectionModel(); + // if (!selectionModel->hasSelection()) { + // Base::Console().Log("\tNothing selected\n"); + // return; + // } + + // Base::Console().Log("\tSelected path '%s'\n", _selectedFull.toStdString().c_str()); + // int res = confirmDelete(this); + // if (res == QMessageBox::Cancel) { + // return; + // } } int MaterialsEditor::confirmSave(QWidget* parent) diff --git a/src/Mod/Material/Gui/MaterialsEditor.h b/src/Mod/Material/Gui/MaterialsEditor.h index 6a1169724b..33f03b221d 100644 --- a/src/Mod/Material/Gui/MaterialsEditor.h +++ b/src/Mod/Material/Gui/MaterialsEditor.h @@ -22,10 +22,11 @@ #ifndef MATGUI_MATERIALSEDITOR_H #define MATGUI_MATERIALSEDITOR_H -#include +#include #include #include +#include #include #include #include @@ -35,8 +36,6 @@ #include #include -namespace fs = boost::filesystem; - namespace MatGui { @@ -47,14 +46,25 @@ class MaterialsEditor: public QDialog Q_OBJECT public: - explicit MaterialsEditor(QWidget* parent = nullptr); + MaterialsEditor(QWidget* parent = nullptr); ~MaterialsEditor() override = default; + void onName(const QString& text); + void onAuthor(const QString& text); + void onLicense(const QString& text); + void onSourceURL(const QString& text); + void onSourceReference(const QString& text); + void onDescription(); + void propertyChange(const QString& property, const QString value); + void onInheritNewMaterial(bool checked); + void onNewMaterial(bool checked); void onFavourite(bool checked); void onURL(bool checked); void onPhysicalAdd(bool checked); + void onPhysicalRemove(bool checked); void onAppearanceAdd(bool checked); + void onAppearanceRemove(bool checked); void onOk(bool checked); void onCancel(bool checked); void onSave(bool checked); @@ -70,10 +80,15 @@ public: return _modelManager; } + QString libraryPath(std::shared_ptr material) const; + void updateMaterialAppearance(); void updateMaterialProperties(); + void updateMaterialGeneral(); void updateMaterial(); void onSelectMaterial(const QItemSelection& selected, const QItemSelection& deselected); + void onDoubleClick(const QModelIndex& index); + void onContextMenu(const QPoint& pos); protected: int confirmSave(QWidget* parent); @@ -83,7 +98,7 @@ private: std::unique_ptr ui; Materials::MaterialManager _materialManager; Materials::ModelManager _modelManager; - Materials::Material _material; + std::shared_ptr _material; QSvgWidget* _rendered; QSvgWidget* _vectored; bool _edited; @@ -102,6 +117,10 @@ private: void addRecent(const QString& uuid); bool isRecent(const QString& uuid) const; + void onInherit(bool checked); + void onInheritNew(bool checked); + + void setMaterialDefaults(); void updatePreview() const; QString getColorHash(const QString& colorString, int colorRange = 255) const; @@ -115,15 +134,12 @@ private: void createMaterialTree(); void fillMaterialTree(); void refreshMaterialTree(); - void - addMaterials(QStandardItem& parent, - const std::shared_ptr> modelTree, - const QIcon& folderIcon, - const QIcon& icon); - bool isMaterial(const fs::path& p) const - { - return Materials::MaterialManager::isMaterial(p); - } + void addMaterials( + QStandardItem& parent, + const std::shared_ptr>> + modelTree, + const QIcon& folderIcon, + const QIcon& icon); }; } // namespace MatGui diff --git a/src/Mod/Material/Gui/MaterialsEditor.ui b/src/Mod/Material/Gui/MaterialsEditor.ui index 8533439e88..5825062271 100644 --- a/src/Mod/Material/Gui/MaterialsEditor.ui +++ b/src/Mod/Material/Gui/MaterialsEditor.ui @@ -68,19 +68,40 @@ 7 + + + + Parent + + + + + + + + + + Tags + + + + + + + Source URL + + + - + Description - - - @@ -88,54 +109,10 @@ - - - - Source Reference - - - - - - - Parent - - - - - - - - - - Author and License - - - - - - - - - - Tags - - - - - - - Source URL - - - - + - - - @@ -155,6 +132,39 @@ + + + + + + + Author + + + + + + + + + + Source Reference + + + + + + + + + + + + + License + + + @@ -172,6 +182,20 @@ + + + + &New + + + + + + + Inherit New + + + diff --git a/src/Mod/Material/Gui/ModelSelect.cpp b/src/Mod/Material/Gui/ModelSelect.cpp index 9b2d19ab38..55fc1a95e2 100644 --- a/src/Mod/Material/Gui/ModelSelect.cpp +++ b/src/Mod/Material/Gui/ModelSelect.cpp @@ -33,6 +33,8 @@ #include #include +#include + #include "ModelSelect.h" #include "ui_ModelSelect.h" @@ -41,7 +43,7 @@ using namespace MatGui; /* TRANSLATOR MatGui::ModelSelect */ -ModelSelect::ModelSelect(QWidget* parent, Materials::ModelManager::ModelFilter filter) +ModelSelect::ModelSelect(QWidget* parent, Materials::ModelFilter filter) : QDialog(parent) , _filter(filter) , ui(new Ui_ModelSelect) @@ -69,6 +71,7 @@ ModelSelect::ModelSelect(QWidget* parent, Materials::ModelManager::ModelFilter f connect(ui->buttonURL, &QPushButton::clicked, this, &ModelSelect::onURL); connect(ui->buttonDOI, &QPushButton::clicked, this, &ModelSelect::onDOI); connect(ui->buttonFavorite, &QPushButton::clicked, this, &ModelSelect::onFavourite); + connect(ui->treeModels, &QTreeView::doubleClicked, this, &ModelSelect::onDoubleClick); ui->standardButtons->button(QDialogButtonBox::Ok)->setEnabled(false); ui->buttonFavorite->setEnabled(false); @@ -232,14 +235,14 @@ void ModelSelect::addExpanded(QTreeView* tree, QStandardItemModel* parent, QStan void ModelSelect::addModels( QStandardItem& parent, - const std::shared_ptr> modelTree, + const std::shared_ptr>> modelTree, const QIcon& icon) { auto tree = ui->treeModels; for (auto& mod : *modelTree) { - Materials::ModelTreeNode* nodePtr = mod.second; + std::shared_ptr nodePtr = mod.second; if (nodePtr->getType() == Materials::ModelTreeNode::DataNode) { - const Materials::Model* model = nodePtr->getData(); + auto model = nodePtr->getData(); QString uuid = model->getUUID(); auto card = new QStandardItem(icon, model->getName()); @@ -264,11 +267,11 @@ void ModelSelect::addRecents(QStandardItem* parent) auto tree = ui->treeModels; for (auto& uuid : _recents) { try { - const Materials::Model& model = getModelManager().getModel(uuid); + auto model = getModelManager().getModel(uuid); - if (getModelManager().passFilter(_filter, model.getType())) { - QIcon icon = QIcon(model.getLibrary().getIconPath()); - auto card = new QStandardItem(icon, model.getName()); + if (getModelManager().passFilter(_filter, model->getType())) { + QIcon icon = QIcon(model->getLibrary()->getIconPath()); + auto card = new QStandardItem(icon, model->getName()); card->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled); card->setData(QVariant(uuid), Qt::UserRole); @@ -286,11 +289,11 @@ void ModelSelect::addFavorites(QStandardItem* parent) auto tree = ui->treeModels; for (auto& uuid : _favorites) { try { - const Materials::Model& model = getModelManager().getModel(uuid); + auto model = getModelManager().getModel(uuid); - if (getModelManager().passFilter(_filter, model.getType())) { - QIcon icon = QIcon(model.getLibrary().getIconPath()); - auto card = new QStandardItem(icon, model.getName()); + if (getModelManager().passFilter(_filter, model->getType())) { + QIcon icon = QIcon(model->getLibrary()->getIconPath()); + auto card = new QStandardItem(icon, model->getName()); card->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled); card->setData(QVariant(uuid), Qt::UserRole); @@ -305,8 +308,6 @@ void ModelSelect::addFavorites(QStandardItem* parent) void ModelSelect::createModelTree() { - // Materials::ModelManager modelManager; - auto tree = ui->treeModels; auto model = new QStandardItemModel(); tree->setModel(model); @@ -326,17 +327,16 @@ void ModelSelect::refreshModelTree() void ModelSelect::fillTree() { - // Materials::ModelManager modelManager; - auto tree = ui->treeModels; auto model = static_cast(tree->model()); + model->clear(); - auto lib = new QStandardItem(QString::fromStdString("Favorites")); + auto lib = new QStandardItem(tr("Favorites")); lib->setFlags(Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled); addExpanded(tree, model, lib); addFavorites(lib); - lib = new QStandardItem(QString::fromStdString("Recent")); + lib = new QStandardItem(tr("Recent")); lib->setFlags(Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled); addExpanded(tree, model, lib); addRecents(lib); @@ -347,7 +347,7 @@ void ModelSelect::fillTree() lib->setFlags(Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled); addExpanded(tree, model, lib); - auto modelTree = getModelManager().getModelTree(*library, _filter); + auto modelTree = getModelManager().getModelTree(library, _filter); addModels(*lib, modelTree, QIcon(library->getIconPath())); } } @@ -355,11 +355,11 @@ void ModelSelect::fillTree() void ModelSelect::setHeaders(QStandardItemModel* model) { QStringList headers; - headers.append(QString::fromStdString("Inherited")); - headers.append(QString::fromStdString("Property")); - headers.append(QString::fromStdString("Units")); - headers.append(QString::fromStdString("Description")); - headers.append(QString::fromStdString("URL")); + headers.append(tr("Inherited")); + headers.append(tr("Property")); + headers.append(tr("Units")); + headers.append(tr("Description")); + headers.append(tr("URL")); model->setHorizontalHeaderLabels(headers); } @@ -388,7 +388,7 @@ void ModelSelect::createModelProperties() // table->setItemDelegate(new MaterialDelegate(this)); } -void ModelSelect::updateModelProperties(const Materials::Model& model) +void ModelSelect::updateModelProperties(std::shared_ptr model) { QTableView* table = ui->tableProperties; QStandardItemModel* tableModel = static_cast(table->model()); @@ -397,7 +397,7 @@ void ModelSelect::updateModelProperties(const Materials::Model& model) setHeaders(tableModel); setColumnWidths(table); - for (auto itp = model.begin(); itp != model.end(); itp++) { + for (auto itp = model->begin(); itp != model->end(); itp++) { QList items; QString key = itp->first; @@ -428,19 +428,19 @@ void ModelSelect::updateModelProperties(const Materials::Model& model) void ModelSelect::updateMaterialModel(const QString& uuid) { - Materials::Model model = getModelManager().getModel(uuid); + auto model = getModelManager().getModel(uuid); // Update the general information - ui->editName->setText(model.getName()); - ui->editURL->setText(model.getURL()); - ui->editDOI->setText(model.getDOI()); - ui->editDescription->setText(model.getDescription()); + ui->editName->setText(model->getName()); + ui->editURL->setText(model->getURL()); + ui->editDOI->setText(model->getDOI()); + ui->editDescription->setText(model->getDescription()); - if (model.getType() == Materials::Model::ModelType_Physical) { - ui->tabWidget->setTabText(1, QString::fromStdString("Properties")); + if (model->getType() == Materials::Model::ModelType_Physical) { + ui->tabWidget->setTabText(1, tr("Properties")); } else { - ui->tabWidget->setTabText(1, QString::fromStdString("Appearance")); + ui->tabWidget->setTabText(1, tr("Appearance")); } updateModelProperties(model); } @@ -453,7 +453,7 @@ void ModelSelect::clearMaterialModel() ui->editDOI->setText(QString::fromStdString("")); ui->editDescription->setText(QString::fromStdString("")); - ui->tabWidget->setTabText(1, QString::fromStdString("Properties")); + ui->tabWidget->setTabText(1, tr("Properties")); QTableView* table = ui->tableProperties; QStandardItemModel* tableModel = static_cast(table->model()); @@ -467,6 +467,7 @@ void ModelSelect::onSelectModel(const QItemSelection& selected, const QItemSelec { Q_UNUSED(deselected); + Base::Console().Log("ModelSelect::onSelectModel()\n"); QStandardItemModel* model = static_cast(ui->treeModels->model()); QModelIndexList indexes = selected.indexes(); for (auto it = indexes.begin(); it != indexes.end(); it++) { @@ -491,6 +492,14 @@ void ModelSelect::onSelectModel(const QItemSelection& selected, const QItemSelec } } +void ModelSelect::onDoubleClick(const QModelIndex& index) +{ + Q_UNUSED(index) + + Base::Console().Log("ModelSelect::onDoubleClick()\n"); + accept(); +} + void ModelSelect::onURL(bool checked) { Q_UNUSED(checked) diff --git a/src/Mod/Material/Gui/ModelSelect.h b/src/Mod/Material/Gui/ModelSelect.h index a80e98fe65..57c3737411 100644 --- a/src/Mod/Material/Gui/ModelSelect.h +++ b/src/Mod/Material/Gui/ModelSelect.h @@ -22,7 +22,7 @@ #ifndef MATGUI_MODELSELECT_H #define MATGUI_MODELSELECT_H -#include +#include #include #include @@ -31,9 +31,7 @@ #include #include -#include - -namespace fs = boost::filesystem; +#include namespace MatGui { @@ -45,15 +43,15 @@ class ModelSelect: public QDialog Q_OBJECT public: - explicit ModelSelect( - QWidget* parent = nullptr, - Materials::ModelManager::ModelFilter filter = Materials::ModelManager::ModelFilter_None); + ModelSelect(QWidget* parent = nullptr, + Materials::ModelFilter filter = Materials::ModelFilter_None); ~ModelSelect() override; void onURL(bool checked); void onDOI(bool checked); void onFavourite(bool checked); void onSelectModel(const QItemSelection& selected, const QItemSelection& deselected); + void onDoubleClick(const QModelIndex& index); const QString& selectedModel() const { return _selected; @@ -77,9 +75,11 @@ private: void addExpanded(QTreeView* tree, QStandardItemModel* parent, QStandardItem* child); void addRecents(QStandardItem* parent); void addFavorites(QStandardItem* parent); - void addModels(QStandardItem& parent, - const std::shared_ptr> modelTree, - const QIcon& icon); + void + addModels(QStandardItem& parent, + const std::shared_ptr>> + modelTree, + const QIcon& icon); void updateMaterialModel(const QString& uuid); void clearMaterialModel(); void createModelTree(); @@ -88,14 +88,14 @@ private: void setHeaders(QStandardItemModel* model); void setColumnWidths(QTableView* table); - void updateModelProperties(const Materials::Model& model); + void updateModelProperties(std::shared_ptr model); void createModelProperties(); Materials::ModelManager& getModelManager() { return _modelManager; } - Materials::ModelManager::ModelFilter _filter; + Materials::ModelFilter _filter; std::unique_ptr ui; Materials::ModelManager _modelManager; QString _selected; diff --git a/src/Mod/Material/Gui/PreCompiled.h b/src/Mod/Material/Gui/PreCompiled.h index 6c9e2163ab..36cb312a6f 100644 --- a/src/Mod/Material/Gui/PreCompiled.h +++ b/src/Mod/Material/Gui/PreCompiled.h @@ -55,10 +55,6 @@ // OpenCasCade // #include -// Boost -#include -#include - // Qt Toolkit #ifndef __QtAll__ #include diff --git a/src/Mod/Material/Gui/Workbench.cpp b/src/Mod/Material/Gui/Workbench.cpp index 21c244052f..65ee6aa6b8 100644 --- a/src/Mod/Material/Gui/Workbench.cpp +++ b/src/Mod/Material/Gui/Workbench.cpp @@ -22,13 +22,53 @@ #include "PreCompiled.h" +#include +#include + #include "Workbench.h" using namespace MatGui; + +#if 0 // needed for Qt's lupdate utility + qApp->translate("Workbench", "&Materials"); + qApp->translate("Workbench", "Materials"); +#endif + /// @namespace MatGui @class Workbench TYPESYSTEM_SOURCE(MatGui::Workbench, Gui::StdWorkbench) Workbench::Workbench() = default; Workbench::~Workbench() = default; + +Gui::MenuItem* Workbench::setupMenuBar() const +{ + Gui::MenuItem* root = StdWorkbench::setupMenuBar(); + Gui::MenuItem* item = root->findItem("&Windows"); + + Gui::MenuItem* part = new Gui::MenuItem; + root->insertItem(item, part); + part->setCommand("&Materials"); + *part << "Materials_Edit"; + + return root; +} + +Gui::ToolBarItem* Workbench::setupToolBars() const +{ + Gui::ToolBarItem* root = StdWorkbench::setupToolBars(); + + Gui::ToolBarItem* solids = new Gui::ToolBarItem(root); + solids->setCommand("Materials"); + *solids << "Materials_Edit"; + + return root; +} + +Gui::ToolBarItem* Workbench::setupCommandBars() const +{ + // Part tools + Gui::ToolBarItem* root = new Gui::ToolBarItem; + return root; +} diff --git a/src/Mod/Material/Gui/Workbench.h b/src/Mod/Material/Gui/Workbench.h index d0de5238c6..fe3800fca7 100644 --- a/src/Mod/Material/Gui/Workbench.h +++ b/src/Mod/Material/Gui/Workbench.h @@ -39,6 +39,11 @@ class MatGuiExport Workbench: public Gui::StdWorkbench public: Workbench(); ~Workbench() override; + +protected: + Gui::MenuItem* setupMenuBar() const override; + Gui::ToolBarItem* setupToolBars() const override; + Gui::ToolBarItem* setupCommandBars() const override; }; } // namespace MatGui diff --git a/src/Mod/Material/Resources/Materials/Appearance/Aluminum.FCMat b/src/Mod/Material/Resources/Materials/Appearance/Aluminum.FCMat index d33f1d0ef4..df4bfa6d55 100644 --- a/src/Mod/Material/Resources/Materials/Appearance/Aluminum.FCMat +++ b/src/Mod/Material/Resources/Materials/Appearance/Aluminum.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "d1f317f0-5ffa-4798-8ab3-af2ff0b5182c" - AuthorAndLicense: "(c) 2023 David Carter" + Author: "David Carter" + License: "GPL-2.0-or-later" Name: "Aluminum" Description: "Defines the Aluminum appearance properties" AppearanceModels: diff --git a/src/Mod/Material/Resources/Materials/Appearance/Brass.FCMat b/src/Mod/Material/Resources/Materials/Appearance/Brass.FCMat index f17c932862..7c84d933f4 100644 --- a/src/Mod/Material/Resources/Materials/Appearance/Brass.FCMat +++ b/src/Mod/Material/Resources/Materials/Appearance/Brass.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "4151e19c-fd6a-4ca4-83d4-d5e17d76cb9c" - AuthorAndLicense: "(c) 2023 David Carter" + Author: "David Carter" + License: "GPL-2.0-or-later" Name: "Brass" Description: "Defines the Brass appearance properties" AppearanceModels: diff --git a/src/Mod/Material/Resources/Materials/Appearance/Bronze.FCMat b/src/Mod/Material/Resources/Materials/Appearance/Bronze.FCMat index bc6c294526..18f0b94a57 100644 --- a/src/Mod/Material/Resources/Materials/Appearance/Bronze.FCMat +++ b/src/Mod/Material/Resources/Materials/Appearance/Bronze.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "ae194589-02d4-4e9b-98a7-f523f660d510" - AuthorAndLicense: "(c) 2023 David Carter" + Author: "David Carter" + License: "GPL-2.0-or-later" Name: "Bronze" Description: "Defines the Bronze appearance properties" AppearanceModels: diff --git a/src/Mod/Material/Resources/Materials/Appearance/Chrome.FCMat b/src/Mod/Material/Resources/Materials/Appearance/Chrome.FCMat index dccbfaec0e..646c2d8891 100644 --- a/src/Mod/Material/Resources/Materials/Appearance/Chrome.FCMat +++ b/src/Mod/Material/Resources/Materials/Appearance/Chrome.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "a9544b88-dde7-4d05-9bdb-c008a4e88dc1" - AuthorAndLicense: "(c) 2023 David Carter" + Author: "David Carter" + License: "GPL-2.0-or-later" Name: "Chrome" Description: "Defines the Chrome appearance properties" AppearanceModels: diff --git a/src/Mod/Material/Resources/Materials/Appearance/Copper.FCMat b/src/Mod/Material/Resources/Materials/Appearance/Copper.FCMat index 643ca6ed06..2e04a10667 100644 --- a/src/Mod/Material/Resources/Materials/Appearance/Copper.FCMat +++ b/src/Mod/Material/Resources/Materials/Appearance/Copper.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "524cad9b-b841-4037-9851-badeca7dcee2" - AuthorAndLicense: "(c) 2023 David Carter" + Author: "David Carter" + License: "GPL-2.0-or-later" Name: "Copper" Description: "Defines the Copper appearance properties" AppearanceModels: diff --git a/src/Mod/Material/Resources/Materials/Appearance/DefaultAppearance.FCMat b/src/Mod/Material/Resources/Materials/Appearance/DefaultAppearance.FCMat index 9795ceae40..9c6eb2f497 100644 --- a/src/Mod/Material/Resources/Materials/Appearance/DefaultAppearance.FCMat +++ b/src/Mod/Material/Resources/Materials/Appearance/DefaultAppearance.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "5dbb7be6-8b63-479b-ab4c-87be02ead973" - AuthorAndLicense: "(c) 2023 David Carter" + Author: "David Carter" + License: "GPL-2.0-or-later" Name: "Default Appearance" Description: "Defines the default appearance properties" AppearanceModels: diff --git a/src/Mod/Material/Resources/Materials/Appearance/Emerald.FCMat b/src/Mod/Material/Resources/Materials/Appearance/Emerald.FCMat index d98a8f1153..519b79bdd6 100644 --- a/src/Mod/Material/Resources/Materials/Appearance/Emerald.FCMat +++ b/src/Mod/Material/Resources/Materials/Appearance/Emerald.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "54def35f-a6bf-472e-8410-dc9fb4b143cf" - AuthorAndLicense: "(c) 2023 David Carter" + Author: "David Carter" + License: "GPL-2.0-or-later" Name: "Emerald" Description: "Defines the Emerald appearance properties" AppearanceModels: diff --git a/src/Mod/Material/Resources/Materials/Appearance/Gold.FCMat b/src/Mod/Material/Resources/Materials/Appearance/Gold.FCMat index 170b7d1302..4805837cf3 100644 --- a/src/Mod/Material/Resources/Materials/Appearance/Gold.FCMat +++ b/src/Mod/Material/Resources/Materials/Appearance/Gold.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "85257e2c-be3f-40a1-b03f-0bd4ba58ca08" - AuthorAndLicense: "(c) 2023 David Carter" + Author: "David Carter" + License: "GPL-2.0-or-later" Name: "Gold" Description: "Defines the Gold appearance properties" AppearanceModels: diff --git a/src/Mod/Material/Resources/Materials/Appearance/Jade.FCMat b/src/Mod/Material/Resources/Materials/Appearance/Jade.FCMat index 3a956ebff2..af9b12ceeb 100644 --- a/src/Mod/Material/Resources/Materials/Appearance/Jade.FCMat +++ b/src/Mod/Material/Resources/Materials/Appearance/Jade.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "cddfa21f-0715-49dd-b35b-951c076fa52c" - AuthorAndLicense: "(c) 2023 David Carter" + Author: "David Carter" + License: "GPL-2.0-or-later" Name: "Jade" Description: "Defines the Jade appearance properties" AppearanceModels: diff --git a/src/Mod/Material/Resources/Materials/Appearance/Metalized.FCMat b/src/Mod/Material/Resources/Materials/Appearance/Metalized.FCMat index 11892dc311..9c9d2feb2d 100644 --- a/src/Mod/Material/Resources/Materials/Appearance/Metalized.FCMat +++ b/src/Mod/Material/Resources/Materials/Appearance/Metalized.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "d149a177-07f1-4e53-9bad-0b5bf0663600" - AuthorAndLicense: "(c) 2023 David Carter" + Author: "David Carter" + License: "GPL-2.0-or-later" Name: "Metalized" Description: "Defines the Metalized appearance properties" AppearanceModels: diff --git a/src/Mod/Material/Resources/Materials/Appearance/NeonGNC.FCMat b/src/Mod/Material/Resources/Materials/Appearance/NeonGNC.FCMat index ddf2092e1c..00a226c0ca 100644 --- a/src/Mod/Material/Resources/Materials/Appearance/NeonGNC.FCMat +++ b/src/Mod/Material/Resources/Materials/Appearance/NeonGNC.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "c0341eef-0897-4fcf-a7f7-eddf1a2600a5" - AuthorAndLicense: "(c) 2023 David Carter" + Author: "David Carter" + License: "GPL-2.0-or-later" Name: "Neon GNC" Description: "Defines the Neon GNC appearance properties" AppearanceModels: diff --git a/src/Mod/Material/Resources/Materials/Appearance/NeonPHC.FCMat b/src/Mod/Material/Resources/Materials/Appearance/NeonPHC.FCMat index ed315a25b6..ea1473d575 100644 --- a/src/Mod/Material/Resources/Materials/Appearance/NeonPHC.FCMat +++ b/src/Mod/Material/Resources/Materials/Appearance/NeonPHC.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "add2d6b2-c8fb-4777-a80a-52bae97300ae" - AuthorAndLicense: "(c) 2023 David Carter" + Author: "David Carter" + License: "GPL-2.0-or-later" Name: "Neon PHC" Description: "Defines the Neon PHC appearance properties" AppearanceModels: diff --git a/src/Mod/Material/Resources/Materials/Appearance/Obsidian.FCMat b/src/Mod/Material/Resources/Materials/Appearance/Obsidian.FCMat index e4f366cff9..3496efb8ea 100644 --- a/src/Mod/Material/Resources/Materials/Appearance/Obsidian.FCMat +++ b/src/Mod/Material/Resources/Materials/Appearance/Obsidian.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "a004c270-7d2c-4898-bec6-b1120edacea9" - AuthorAndLicense: "(c) 2023 David Carter" + Author: "David Carter" + License: "GPL-2.0-or-later" Name: "Obsidian" Description: "Defines the Obsidian appearance properties" AppearanceModels: diff --git a/src/Mod/Material/Resources/Materials/Appearance/Pewter.FCMat b/src/Mod/Material/Resources/Materials/Appearance/Pewter.FCMat index b7592ea3df..b263611987 100644 --- a/src/Mod/Material/Resources/Materials/Appearance/Pewter.FCMat +++ b/src/Mod/Material/Resources/Materials/Appearance/Pewter.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "a61853b9-ec9f-403e-9726-0a938731aecd" - AuthorAndLicense: "(c) 2023 David Carter" + Author: "David Carter" + License: "GPL-2.0-or-later" Name: "Pewter" Description: "Defines the Pewter appearance properties" AppearanceModels: diff --git a/src/Mod/Material/Resources/Materials/Appearance/Plaster.FCMat b/src/Mod/Material/Resources/Materials/Appearance/Plaster.FCMat index 70f6c8932a..d969f84f02 100644 --- a/src/Mod/Material/Resources/Materials/Appearance/Plaster.FCMat +++ b/src/Mod/Material/Resources/Materials/Appearance/Plaster.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "569dccb6-c64b-4dd0-9d3c-1b78f40ad1a5" - AuthorAndLicense: "(c) 2023 David Carter" + Author: "David Carter" + License: "GPL-2.0-or-later" Name: "Plaster" Description: "Defines the Plaster appearance properties" AppearanceModels: diff --git a/src/Mod/Material/Resources/Materials/Appearance/Plastic.FCMat b/src/Mod/Material/Resources/Materials/Appearance/Plastic.FCMat index 2484521dca..efcc9df554 100644 --- a/src/Mod/Material/Resources/Materials/Appearance/Plastic.FCMat +++ b/src/Mod/Material/Resources/Materials/Appearance/Plastic.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "a74622cd-0e2d-4a96-b8c4-fefcc82ac694" - AuthorAndLicense: "(c) 2023 David Carter" + Author: "David Carter" + License: "GPL-2.0-or-later" Name: "Plastic" Description: "Defines the Plastic appearance properties" AppearanceModels: diff --git a/src/Mod/Material/Resources/Materials/Appearance/Ruby.FCMat b/src/Mod/Material/Resources/Materials/Appearance/Ruby.FCMat index 5a8138ba39..eac38bb236 100644 --- a/src/Mod/Material/Resources/Materials/Appearance/Ruby.FCMat +++ b/src/Mod/Material/Resources/Materials/Appearance/Ruby.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "953261a0-cc48-41f8-a3f9-7b20ae3f9b56" - AuthorAndLicense: "(c) 2023 David Carter" + Author: "David Carter" + License: "GPL-2.0-or-later" Name: "Ruby" Description: "Defines the Ruby appearance properties" AppearanceModels: diff --git a/src/Mod/Material/Resources/Materials/Appearance/Satin.FCMat b/src/Mod/Material/Resources/Materials/Appearance/Satin.FCMat index 97a198c206..211f1441df 100644 --- a/src/Mod/Material/Resources/Materials/Appearance/Satin.FCMat +++ b/src/Mod/Material/Resources/Materials/Appearance/Satin.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "951b54ae-86b6-46d2-b452-60bd6a3ba1bb" - AuthorAndLicense: "(c) 2023 David Carter" + Author: "David Carter" + License: "GPL-2.0-or-later" Name: "Satin" Description: "Defines the Satin appearance properties" AppearanceModels: diff --git a/src/Mod/Material/Resources/Materials/Appearance/ShinyPlastic.FCMat b/src/Mod/Material/Resources/Materials/Appearance/ShinyPlastic.FCMat index 75853c01bc..221be76449 100644 --- a/src/Mod/Material/Resources/Materials/Appearance/ShinyPlastic.FCMat +++ b/src/Mod/Material/Resources/Materials/Appearance/ShinyPlastic.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "591c4c4a-22ba-4a9a-869d-e5610107d69a" - AuthorAndLicense: "(c) 2023 David Carter" + Author: "David Carter" + License: "GPL-2.0-or-later" Name: "Shiny Plastic" Description: "Defines the Shiny Plastic appearance properties" AppearanceModels: diff --git a/src/Mod/Material/Resources/Materials/Appearance/Silver.FCMat b/src/Mod/Material/Resources/Materials/Appearance/Silver.FCMat index b3354a150a..dbdedc9a27 100644 --- a/src/Mod/Material/Resources/Materials/Appearance/Silver.FCMat +++ b/src/Mod/Material/Resources/Materials/Appearance/Silver.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "62839fb0-d854-4b44-92df-b7249213de49" - AuthorAndLicense: "(c) 2023 David Carter" + Author: "David Carter" + License: "GPL-2.0-or-later" Name: "Silver" Description: "Defines the Silver appearance properties" AppearanceModels: diff --git a/src/Mod/Material/Resources/Materials/Appearance/Steel.FCMat b/src/Mod/Material/Resources/Materials/Appearance/Steel.FCMat index 7bebcd8a90..bc9e1acc99 100644 --- a/src/Mod/Material/Resources/Materials/Appearance/Steel.FCMat +++ b/src/Mod/Material/Resources/Materials/Appearance/Steel.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "4b849c55-6b3a-4f75-a055-40c0d0324596" - AuthorAndLicense: "(c) 2023 David Carter" + Author: "David Carter" + License: "GPL-2.0-or-later" Name: "Steel" Description: "Defines the Steel appearance properties" AppearanceModels: diff --git a/src/Mod/Material/Resources/Materials/Appearance/Stone.FCMat b/src/Mod/Material/Resources/Materials/Appearance/Stone.FCMat index 8c3910ee5d..74436298ba 100644 --- a/src/Mod/Material/Resources/Materials/Appearance/Stone.FCMat +++ b/src/Mod/Material/Resources/Materials/Appearance/Stone.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "a9f54d61-cc98-46df-8734-b0543ceb4e45" - AuthorAndLicense: "(c) 2023 David Carter" + Author: "David Carter" + License: "GPL-2.0-or-later" Name: "Stone" Description: "Defines the Stone appearance properties" AppearanceModels: diff --git a/src/Mod/Material/Resources/Materials/FluidMaterial/Air.FCMat b/src/Mod/Material/Resources/Materials/FluidMaterial/Air.FCMat index 6a5be9c27c..025c280566 100644 --- a/src/Mod/Material/Resources/Materials/FluidMaterial/Air.FCMat +++ b/src/Mod/Material/Resources/Materials/FluidMaterial/Air.FCMat @@ -1,6 +1,7 @@ # File created by ConvertFCMat.py General: UUID: "94370b96-c97e-4a3f-83b2-11d7461f7da7" + License: "GPL-2.0-or-later" Name: "Air" Description: "Dry air properties at 20 Degrees Celsius and 1 atm" Models: diff --git a/src/Mod/Material/Resources/Materials/FluidMaterial/Argon.FCMat b/src/Mod/Material/Resources/Materials/FluidMaterial/Argon.FCMat index 1607bd59da..235f07091c 100644 --- a/src/Mod/Material/Resources/Materials/FluidMaterial/Argon.FCMat +++ b/src/Mod/Material/Resources/Materials/FluidMaterial/Argon.FCMat @@ -1,6 +1,7 @@ # File created by ConvertFCMat.py General: UUID: "e359c5b5-eae2-42b1-9ef6-edde21d706ee" + License: "GPL-2.0-or-later" Name: "Argon" Description: "Argon properties at 20 Degrees Celsius and 1 atm" Models: diff --git a/src/Mod/Material/Resources/Materials/FluidMaterial/Carbon_dioxide.FCMat b/src/Mod/Material/Resources/Materials/FluidMaterial/Carbon_dioxide.FCMat index 7ffe282fed..fdfc5a94c9 100644 --- a/src/Mod/Material/Resources/Materials/FluidMaterial/Carbon_dioxide.FCMat +++ b/src/Mod/Material/Resources/Materials/FluidMaterial/Carbon_dioxide.FCMat @@ -1,6 +1,7 @@ # File created by ConvertFCMat.py General: UUID: "ef0e4040-a498-48c3-a87b-e996bfd89195" + License: "GPL-2.0-or-later" Name: "Carbon dioxide" Description: "Carbon dioxide properties at 20 Degrees Celsius and 1 atm" Models: diff --git a/src/Mod/Material/Resources/Materials/FluidMaterial/Nitrogen.FCMat b/src/Mod/Material/Resources/Materials/FluidMaterial/Nitrogen.FCMat index bd5fd3ea07..d7c81bea31 100644 --- a/src/Mod/Material/Resources/Materials/FluidMaterial/Nitrogen.FCMat +++ b/src/Mod/Material/Resources/Materials/FluidMaterial/Nitrogen.FCMat @@ -1,6 +1,7 @@ # File created by ConvertFCMat.py General: UUID: "8d02a797-5e0a-4e40-803a-75fc66de8de6" + License: "GPL-2.0-or-later" Name: "Nitrogen" Description: "Nitrogen properties at 20 Degrees Celsius and 1 atm" Models: diff --git a/src/Mod/Material/Resources/Materials/FluidMaterial/None.FCMat b/src/Mod/Material/Resources/Materials/FluidMaterial/None.FCMat index 40094e2d06..8497cd58bb 100644 --- a/src/Mod/Material/Resources/Materials/FluidMaterial/None.FCMat +++ b/src/Mod/Material/Resources/Materials/FluidMaterial/None.FCMat @@ -1,6 +1,7 @@ # File created by ConvertFCMat.py General: UUID: "944a8018-09bf-48f6-a7b3-aa8f6a00a310" + License: "GPL-2.0-or-later" Name: "None" Description: "None" Models: diff --git a/src/Mod/Material/Resources/Materials/FluidMaterial/Water.FCMat b/src/Mod/Material/Resources/Materials/FluidMaterial/Water.FCMat index aa4c8d35cc..6f0fe7c6dc 100644 --- a/src/Mod/Material/Resources/Materials/FluidMaterial/Water.FCMat +++ b/src/Mod/Material/Resources/Materials/FluidMaterial/Water.FCMat @@ -1,6 +1,7 @@ # File created by ConvertFCMat.py General: UUID: "7e5559d5-be15-4571-a72f-20c39edd41cf" + License: "GPL-2.0-or-later" Name: "Water" Description: "Standard distilled water properties at 20 Degrees Celsius and 1 atm" ReferenceSource: "''" diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Aggregate/Concrete-EN-C35_45.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Aggregate/Concrete-EN-C35_45.FCMat index fa6eabb71f..281b959ca6 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Aggregate/Concrete-EN-C35_45.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Aggregate/Concrete-EN-C35_45.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "dba76940-a910-4a3b-ab73-a9f412ac69d9" - AuthorAndLicense: "(c) 2019 Bernd Hahnebach (CC-BY 3.0)" + Author: "Bernd Hahnebach" + License: "CC-BY-3.0" Name: "Concrete-EN-C35/45" Description: "Concrete matrix for reinforcement material examples, 0.6 x 0.75 x 35 MPa = 15.75 MPa (https://forum.freecad.org/viewtopic.php?f=18&t=33106&start=200#p311075)" Inherits: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Aggregate/Concrete-Generic.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Aggregate/Concrete-Generic.FCMat index 994874548d..72e4c9af4a 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Aggregate/Concrete-Generic.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Aggregate/Concrete-Generic.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "26042aa5-56e6-4d99-8b63-dd8b9ea5a37a" - AuthorAndLicense: "(c) 2013 Yorik van Havre (CC-BY 3.0)" + Author: "Yorik van Havre" + License: "CC-BY-3.0" Name: "Concrete" Description: "A standard C-25 construction concrete" Inherits: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Aggregate/Reinforcement-FIB-B500.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Aggregate/Reinforcement-FIB-B500.FCMat index 13ac6afc77..70e70e1916 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Aggregate/Reinforcement-FIB-B500.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Aggregate/Reinforcement-FIB-B500.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "57507cd4-d22f-4d86-9794-fdb1ec8cd098" - AuthorAndLicense: "(c) 2019 Bernd Hahnebach (CC-BY 3.0)" + Author: "Bernd Hahnebach" + License: "CC-BY-3.0" Name: "Reinforcement-Harry" Description: "Reinforcement inside concrete for reinforcement material examples, from fib examples, 0.84 x 0.75 x 500 MPa = 315 MPa (https://forum.freecad.org/viewtopic.php?f=18&t=33106&start=200#p311705)" Inherits: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Carbon/Graphite.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Carbon/Graphite.FCMat index e66b987f2e..5983299e4a 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Carbon/Graphite.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Carbon/Graphite.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "5c67b675-69a2-4782-902a-bb90c3952f07" - AuthorAndLicense: "Uwe Stöhr, LGPL" + Author: "Uwe Stöhr" + License: "LGPL-2.0-or-later" Name: "Graphite" Description: "Typical material properties for pure graphite" ReferenceSource: "Properties and characteristics of graphite" diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Glass/Glass-E-GlassFibre.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Glass/Glass-E-GlassFibre.FCMat index 034f5271f0..862f02108f 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Glass/Glass-E-GlassFibre.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Glass/Glass-E-GlassFibre.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "a02bf9d7-6e3e-4e36-881b-10779ee9f706" - AuthorAndLicense: "(c) 2015 DaviKaur (CC-BY 3.0)" + Author: "DaviKaur" + License: "CC-BY-3.0" Name: "Glass-E" Description: "Glass Fibre" Models: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Glass/Glass-Generic.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Glass/Glass-Generic.FCMat index 1502a1e85b..9074cfe621 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Glass/Glass-Generic.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Glass/Glass-Generic.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "3e3a3e13-04a4-410e-8e36-bbd83ca66847" - AuthorAndLicense: "(c) 2015 Przemo Firszt (CC-BY 3.0)" + Author: "Przemo Firszt" + License: "CC-BY-3.0" Name: "Glass" Description: "Generic soda-lime glass" Models: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Glass/Glass-S2-GlassFibre.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Glass/Glass-S2-GlassFibre.FCMat index 79d993d62d..70daa6df5b 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Glass/Glass-S2-GlassFibre.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Glass/Glass-S2-GlassFibre.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "0c4943e0-248b-4df9-88d9-3b4dd84dfc68" - AuthorAndLicense: "(c) 2015 DaviKaur (CC-BY 3.0)" + Author: "DaviKaur" + License: "CC-BY-3.0" Name: "Glass-S2" Description: "Glass Fibre" Models: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Alloys/Invar-Generic.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Alloys/Invar-Generic.FCMat index 1653bde1ae..80fce39425 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Alloys/Invar-Generic.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Alloys/Invar-Generic.FCMat @@ -1,7 +1,7 @@ # File created by ConvertFCMat.py General: UUID: "27745e16-2a10-4c8e-bd22-59971806909c" - AuthorAndLicense: "Uwe Stöhr" + Author: "Uwe Stöhr" Name: "Invar Generic" Models: Father: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Aluminum/AlMg3F24.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Aluminum/AlMg3F24.FCMat index d3ea2edf4c..b7a7da8f77 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Aluminum/AlMg3F24.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Aluminum/AlMg3F24.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "0051bddf-6f62-4406-b8c9-569322880564" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "AlMg3F24" Inherits: Aluminum: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Aluminum/AlMgSi1F31.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Aluminum/AlMgSi1F31.FCMat index ce7ad3a053..7d27af3936 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Aluminum/AlMgSi1F31.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Aluminum/AlMgSi1F31.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "460e02a3-b6cd-4662-b2f6-8c9d44146c66" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "AlMgSi1F31" Inherits: Aluminum: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Aluminum/AlZn4-5Mg1F35.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Aluminum/AlZn4-5Mg1F35.FCMat index 9ff117b0ed..cae2453d1e 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Aluminum/AlZn4-5Mg1F35.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Aluminum/AlZn4-5Mg1F35.FCMat @@ -1,7 +1,7 @@ # File created by ConvertFCMat.py General: UUID: "05f8f1b2-b92b-4e41-8de9-1e064e78a165" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + License: "LGPL-2.0-or-later" Name: "AlZn4,5Mg1F35" Inherits: Aluminum: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Aluminum/Aluminum-6061-T6.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Aluminum/Aluminum-6061-T6.FCMat index 648350b109..3fe4777c23 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Aluminum/Aluminum-6061-T6.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Aluminum/Aluminum-6061-T6.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "68b152b2-fd5e-4f10-8db0-1a2df3fe0fda" - AuthorAndLicense: "(c) 2016 Mandeep Singh (CC-BY 3.0)" + Author: "Mandeep Singh" + License: "CC-BY-3.0" Name: "Aluminum 6061-T6" Description: "Precipitation-hardened, Nonferrous Aluminum alloy" Inherits: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Aluminum/Aluminum-Generic.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Aluminum/Aluminum-Generic.FCMat index c518eaf674..d96cd80218 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Aluminum/Aluminum-Generic.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Aluminum/Aluminum-Generic.FCMat @@ -1,7 +1,7 @@ # File created by ConvertFCMat.py General: UUID: "9bf060e9-1663-44a2-88e2-2ff6ee858efe" - AuthorAndLicense: "Uwe Stöhr" + Author: "Uwe Stöhr" Name: "Aluminum Generic" Inherits: Aluminum: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Copper/Copper-Generic.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Copper/Copper-Generic.FCMat index 8188c3a553..8379ecba69 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Copper/Copper-Generic.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Copper/Copper-Generic.FCMat @@ -1,7 +1,7 @@ # File created by ConvertFCMat.py General: UUID: "6c03899d-496e-4c60-a41b-3d66f2337fb9" - AuthorAndLicense: "Uwe Stöhr" + Author: "Uwe Stöhr" Name: "Copper Generic" Inherits: Copper: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Iron/Iron-Generic.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Iron/Iron-Generic.FCMat index f99d52a37f..f33cdf155f 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Iron/Iron-Generic.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Iron/Iron-Generic.FCMat @@ -1,7 +1,7 @@ # File created by ConvertFCMat.py General: UUID: "1826c364-d26a-43fb-8f61-288281236836" - AuthorAndLicense: "Uwe Stöhr" + Author: "Uwe Stöhr" Name: "Iron Generic" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/CalculiX-Steel.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/CalculiX-Steel.FCMat index 7763a27728..5105e234d2 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/CalculiX-Steel.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/CalculiX-Steel.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "92589471-a6cb-4bbc-b748-d425a17dea7d" - AuthorAndLicense: "(c) 2013 Juergen Riegel (CC-BY 3.0)" + Author: "Juergen Riegel" + License: "CC-BY-3.0" Name: "CalculiX-Steel" Description: "Standard steel material for CalculiX sample calculations" Inherits: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-15CrNi6.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-15CrNi6.FCMat index c1be13ce98..e719b9b5e6 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-15CrNi6.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-15CrNi6.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "6822df30-db32-4a68-a8d7-aaddcb9649d1" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "15CrNi6" Description: "High-strength carbon steel" Inherits: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-17CrNiMo6.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-17CrNiMo6.FCMat index 462e784536..247c10e733 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-17CrNiMo6.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-17CrNiMo6.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "e4c76f15-00af-4498-ac57-beaf49c150e9" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "17CrNiMo6" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-1C22.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-1C22.FCMat index f36307b08d..4f0271aff2 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-1C22.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-1C22.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "c424fe3d-5f49-4c39-9467-8a2a800076aa" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "1C22" Description: "Case hardened alloy steel" Inherits: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-1C35.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-1C35.FCMat index 8cc577729a..0c5702696b 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-1C35.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-1C35.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "cd932bad-4085-459f-aea6-1da737ae38ae" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "1C35" Description: "Non-alloy quality steel" Inherits: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-1C45.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-1C45.FCMat index 9433799bcb..4fabe2bb90 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-1C45.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-1C45.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "958b7a5c-4764-4a2f-a450-2153a41fb5ec" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "1C45" Description: "Non-alloy quality steel" Inherits: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-1C60.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-1C60.FCMat index dac83e2809..45ae6f0566 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-1C60.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-1C60.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "9717f953-1cfc-41a6-8974-3ad45188ad48" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "1C60" Description: "Non-alloy quality steel" Inherits: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-20NiCrMo2.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-20NiCrMo2.FCMat index f63fc2cd6b..af5e731492 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-20NiCrMo2.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-20NiCrMo2.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "1c759697-7aef-4a14-92c5-5bf84b99a4f0" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "20NiCrMo2" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-28Mn6.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-28Mn6.FCMat index 5166ff1d58..c310e12ec6 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-28Mn6.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-28Mn6.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "6894c597-5771-4b56-825f-ce7d5e4689f4" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "28Mn6" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-2C10.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-2C10.FCMat index bb25674809..55e4894152 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-2C10.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-2C10.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "a7be39a1-1686-4fee-a1d5-81ef73b82d16" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "2C10" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-30CrNiMo8.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-30CrNiMo8.FCMat index b8edc93d8e..276e40f244 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-30CrNiMo8.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-30CrNiMo8.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "a6d96264-affc-4406-9816-75099c1fa0d9" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "30CrNiMo8" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-34CrNiMo6.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-34CrNiMo6.FCMat index 4c02195cf8..67ce48abdb 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-34CrNiMo6.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-34CrNiMo6.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "e69448d5-2517-4c00-9e70-ebeb11ca017f" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "34CrNiMo6" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-36CrNiMo4.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-36CrNiMo4.FCMat index f1635de298..e41bf67f6b 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-36CrNiMo4.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-36CrNiMo4.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "3e78b767-5530-4d69-a541-cf33a5a2ad19" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "36CrNiMo4" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-36NiCrMo16.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-36NiCrMo16.FCMat index 1a9e29753a..be7b82a8fe 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-36NiCrMo16.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-36NiCrMo16.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "3fdf729c-bec4-4bfa-ba94-b0c9e51a2040" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "36NiCrMo16" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-3C15.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-3C15.FCMat index 6ad2a41287..5384f6afb0 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-3C15.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-3C15.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "605fd7b6-caa3-400d-b6d7-ed52c0f5da21" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "3C15" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-3C22.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-3C22.FCMat index 19c035f0a4..bb8f193f81 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-3C22.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-3C22.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "7313f076-faf4-41dd-8dae-1b9a586990dc" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "3C22" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-3C35.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-3C35.FCMat index 583523ea88..91c2f6478f 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-3C35.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-3C35.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "251cc54e-4a5a-4cd3-9c9e-006c416d7ce9" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "3C35" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-3V45.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-3V45.FCMat index 193f19e1b9..189f0f3b04 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-3V45.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-3V45.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "d2e12a80-fd17-42db-99d8-62971f65ee84" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "3V45" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C10.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C10.FCMat index b72f563c88..016b585afa 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C10.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C10.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "9086ae2f-3b2e-4654-9665-0fe31effb8a2" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "C10" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C15.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C15.FCMat index 6a11819478..47d53206b6 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C15.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C15.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "06ae5c92-de7b-46c9-984d-4dd87964bc5c" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "C15" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C22E.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C22E.FCMat index 932930426e..09bbdc3424 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C22E.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C22E.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "befa2489-dba0-41c5-aa83-7cca2ac8947b" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "C22E" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C25E.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C25E.FCMat index 12f65b3acc..fecc163322 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C25E.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C25E.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "b95d3de5-36af-41cd-a6dd-3f647b1d4eee" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "C25E" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C30E.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C30E.FCMat index d6cfe2d8c3..8dc09c6ca6 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C30E.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C30E.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "e88e1e86-fad2-4c70-b185-4b2975e7fba5" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "C30E" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C40E.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C40E.FCMat index c777dc3028..1ccb48ea77 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C40E.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C40E.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "5b33f177-b0da-4ffa-acb5-a3b23ab6e630" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "C40E" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C50E.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C50E.FCMat index 3a73bb97f7..10122e36fa 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C50E.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C50E.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "6821be5f-5471-4939-bb1d-866f83018090" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "C50E" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C55E.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C55E.FCMat index be4341ad95..27da081e4e 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C55E.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C55E.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "d60a21c9-9c4b-4463-b133-bb0e84ce46b2" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "C55E" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C60E.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C60E.FCMat index 7c0c04301b..7ae48bda84 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C60E.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C60E.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "56027b3e-876e-4c0e-9f39-242feaa67e13" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "C60E" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-E295-GC.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-E295-GC.FCMat index 9b314d4c01..1cae3d8294 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-E295-GC.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-E295-GC.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "fc010ef8-91de-4099-9a73-605c01dd117c" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "E295 GC" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-E295.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-E295.FCMat index e74c218799..d919a2b3f1 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-E295.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-E295.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "f1567a1c-995f-4feb-8baf-09ade3e830c5" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "E295" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-E335-GC.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-E335-GC.FCMat index 9612056c9b..b4a6f21b2b 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-E335-GC.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-E335-GC.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "ab901ecc-d880-4cb4-b400-dbe4fd9b0f0a" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "E335 GC" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-E335.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-E335.FCMat index 7ca7e2a764..44e9e013db 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-E335.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-E335.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "da418876-f80e-4793-8fc8-a6040a694389" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "E335" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-E360-GC.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-E360-GC.FCMat index aa14d78d49..69ee63fa8d 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-E360-GC.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-E360-GC.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "4c311592-659b-4ef0-bac9-5cffe9e70612" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "E360 GC" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-E360.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-E360.FCMat index 6ed1535ce0..086b7b9ddb 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-E360.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-E360.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "dfba065e-2bfb-4fe3-8eec-dfb1cb6274fe" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "E360" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJL-100.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJL-100.FCMat index 282a042e41..8bac4460a4 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJL-100.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJL-100.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "5a1d56e3-8180-4f81-a0d7-887fb08e3752" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "EN-GJL-100" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJL-150.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJL-150.FCMat index f4c9e2ca3c..e68bdbd697 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJL-150.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJL-150.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "7a2aa3c4-10fa-44b0-9420-37ae74207fa3" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "EN-GJL-150" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJL-200.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJL-200.FCMat index aca3e5b83a..ed3218a3ff 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJL-200.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJL-200.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "8ae26e72-65b6-4f93-9fbe-9e3f17a2e1b5" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "EN-GJL-200" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJL-250.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJL-250.FCMat index 13d4da1f70..5272f9b931 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJL-250.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJL-250.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "71f32e31-656e-4f94-a5f0-5b656b9367c6" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "EN-GJL-250" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJL-300.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJL-300.FCMat index 489a2e3c24..2dd95eb99d 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJL-300.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJL-300.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "6db01463-7772-4d0e-ab81-fae6d45ce669" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "EN-GJL-300" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJL-350.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJL-350.FCMat index 9922275365..f463241b6d 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJL-350.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJL-350.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "c4ff4bef-4885-41d5-904f-9c71a8018c98" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "EN-GJL-350" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMB-350-10.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMB-350-10.FCMat index 05dc53a302..e3068a9035 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMB-350-10.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMB-350-10.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "eec1833a-424a-4c4f-bdf2-6f8377845d54" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "EN-GJMB-350-10" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMB-550-4.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMB-550-4.FCMat index 7e8b518d5c..d4e4f44237 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMB-550-4.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMB-550-4.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "095140bb-df01-4bb9-8ff3-062aa91ec48c" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "EN-GJMB-550-4" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMB-650-2.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMB-650-2.FCMat index d22fcd93ad..d11ba1c726 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMB-650-2.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMB-650-2.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "490a348c-f508-4599-a5e0-2f6b211126d5" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "EN-GJMB-650-2" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMW-350-4.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMW-350-4.FCMat index 148e26a9b3..ebb8694572 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMW-350-4.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMW-350-4.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "a97c3eab-a1e8-472b-ba40-519a0d660019" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "EN-GJMW-350-4" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMW-360-12.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMW-360-12.FCMat index 604538d200..e1c40edde3 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMW-360-12.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMW-360-12.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "81a865af-79b6-4e0b-98ad-5cde134ad99e" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "EN-GJMW-360-12" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMW-400-5.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMW-400-5.FCMat index db74ef871c..9220b27f79 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMW-400-5.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMW-400-5.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "9d71fc9c-960a-47e8-afa8-a86a24b3ff89" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "EN-GJMW-400-5" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMW-450-7.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMW-450-7.FCMat index 0e6de5ac4e..1e9d4e28d1 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMW-450-7.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMW-450-7.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "c0eedc49-d63b-429d-be63-ef0ea442f45c" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "EN-GJMW-450-7" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJS-400-15.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJS-400-15.FCMat index ab7c0b2163..051c98f0ec 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJS-400-15.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJS-400-15.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "f6300691-ecf0-4846-acb1-8c2bad3359a8" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "EN-GJS-400-15" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJS-500-7.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJS-500-7.FCMat index 5a28f4356f..1c28126097 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJS-500-7.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJS-500-7.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "51aabe6f-642b-4f47-9006-1c8c3613a422" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "EN-GJS-500-7" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJS-600-3.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJS-600-3.FCMat index 0f3f5d7ed9..1de6ec6cf9 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJS-600-3.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJS-600-3.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "eb573f18-5a7b-493b-bfda-d711f03f7f71" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "EN-GJS-600-3" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJS-700-2.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJS-700-2.FCMat index 28c327f104..3e1f7625de 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJS-700-2.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJS-700-2.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "9a194e62-d2e4-466d-92ba-2707107c4e3c" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "EN-GJS-700-2" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJS-800-1.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJS-800-1.FCMat index 071d813334..9ad715e980 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJS-800-1.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJS-800-1.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "97c444f9-83ae-48d8-98e5-603349d06f7e" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "EN-GJS-800-1" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G16Mn5.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G16Mn5.FCMat index 97d45db1ae..bdede7e22a 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G16Mn5.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G16Mn5.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "fc5c14ba-4885-4c75-aaf6-0ec4f2365f40" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "G16Mn5" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G200.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G200.FCMat index 51965ab4d2..2c61fce091 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G200.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G200.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "8d799def-e941-4cb6-b48d-72b9a292fafe" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "G200" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G20Mn5.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G20Mn5.FCMat index 7e1e9c8e6d..b7bbf43d10 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G20Mn5.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G20Mn5.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "d384d1e5-e2fe-4e09-9a0f-78e5670425ee" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "G20Mn5" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G230.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G230.FCMat index 2c11dcd9f6..114fd54038 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G230.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G230.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "53931707-6fe7-4ac0-ac7a-e9ddfec70fa5" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "G230" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G260.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G260.FCMat index 4c4b62744e..71e5f54ef6 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G260.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G260.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "22971112-d137-4db1-9349-edf5e281e333" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "G260" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G300.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G300.FCMat index 8c0acbd1cd..488a762db6 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G300.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G300.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "33f1c891-7488-4324-9af9-cbdde6726b49" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "G300" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G30Mn5.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G30Mn5.FCMat index bb11cbee52..91675dc395 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G30Mn5.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G30Mn5.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "e03df70c-ceb8-4317-825d-1195c8c178d0" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "G30Mn5" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-Generic.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-Generic.FCMat index c2fead712a..e291486c4a 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-Generic.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-Generic.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "90bbd8ef-8623-4d78-b3bf-e0bdb9b74dd3" - AuthorAndLicense: "(c) 2013 Juergen Riegel (CC-BY 3.0)" + Author: "Juergen Riegel" + License: "CC-BY-3.0" Name: "Steel-Generic" Description: "This is a blend Steel material card. The values are at the low end of the spectrum. If you need a more precise material definition use the more specialised steel cards." Inherits: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S185.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S185.FCMat index ebba16c9d5..c8f0ada537 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S185.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S185.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "6f32981a-7bbf-49a1-842c-7567a195fa7e" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "S185" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S235JO.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S235JO.FCMat index 3f26e56e56..c484567ffd 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S235JO.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S235JO.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "5b13e02a-b173-4e2d-95fd-a30d9e0f7cf5" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "S235JO" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S235JR.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S235JR.FCMat index 5c4cf2a2ca..657975b9c7 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S235JR.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S235JR.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "4a96627d-6518-458c-8ccf-846f69fd8a50" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "S235JR" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S235JRG1.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S235JRG1.FCMat index a4949171a9..fe1182e815 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S235JRG1.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S235JRG1.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "d8cc450d-7d6d-4377-8a8d-ffe3cf30fcb2" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "S235JRG1" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S260NC.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S260NC.FCMat index 09cf375caa..b9e5794e79 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S260NC.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S260NC.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "4994efd8-fc7b-41b3-ad61-9d98d1bdbe6e" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "S260NC" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S275JO.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S275JO.FCMat index 95a8ec460a..56fb705e76 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S275JO.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S275JO.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "f9deac5f-91a4-41aa-b49c-ef09ec4613e2" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "S275JO" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S275JR.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S275JR.FCMat index 9d57c21c9d..c3da4512c9 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S275JR.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S275JR.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "30e4da7d-1fe3-41de-911a-a42e3405bb7b" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "S275JR" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S275N.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S275N.FCMat index 18c0439561..59a1888016 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S275N.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S275N.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "07592e35-3e1a-470f-8eda-f4bee7d9cb4a" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "S275N" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S335JO.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S335JO.FCMat index c8ae2510e0..c7fbcc90db 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S335JO.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S335JO.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "c50ad549-b4f4-47ab-9bc6-4eb5191da111" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "S335JO" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S335JR.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S335JR.FCMat index 931e9d418f..83ac7fe653 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S335JR.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S335JR.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "dbd04cee-3b92-4b79-a208-58547ebe3807" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "S335JR" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S335N.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S335N.FCMat index 231271d7cd..e7d8fc174b 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S335N.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S335N.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "16d7f1d5-449f-4b9e-b57a-7ea114fda115" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "S335N" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S340MC.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S340MC.FCMat index a3e0a90eb4..baccd4ca36 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S340MC.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S340MC.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "5785ea5e-3376-47dd-8dc2-f1267c47e9bc" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "S340MC" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S355J2G3.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S355J2G3.FCMat index 71b783d323..72e7ca9845 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S355J2G3.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S355J2G3.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "b9e861ee-93fb-4eca-a2de-03579bc503c1" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "S355J2G3" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S380MC.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S380MC.FCMat index aa8d2c2c94..b28262ff49 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S380MC.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S380MC.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "da2a429b-8763-4586-be3d-620e7dd30271" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "S380MC" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S420MC.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S420MC.FCMat index 41b6518bed..407d553894 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S420MC.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S420MC.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "c3452eff-f68e-4cfd-a24e-27e2abcd01ac" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "S420MC" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S420N.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S420N.FCMat index a8a2d0b6cd..74f00df70f 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S420N.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S420N.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "902f2d4a-5bd0-44bf-9c14-54462ba6778b" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "S420N" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S460MC.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S460MC.FCMat index 2b972e87ef..7834dca011 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S460MC.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S460MC.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "c254dac5-3ee3-49b9-b8d4-16d20d21c94f" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "S460MC" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S460N.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S460N.FCMat index d3c96c9639..536b5df413 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S460N.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S460N.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "f0ae245a-1041-4674-ac4f-bf212dda6009" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "S460N" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S500MC.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S500MC.FCMat index 7703c36586..679dfaf447 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S500MC.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S500MC.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "ad8e2007-ee73-4b71-8830-6d40a8407284" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "S500MC" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S550MC.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S550MC.FCMat index 9ac063cd0d..b7c5bc08b2 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S550MC.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S550MC.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "b7308026-9278-4346-b157-2b3da280b61b" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "S550MC" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S690MC.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S690MC.FCMat index 1d979fd02c..223f410073 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S690MC.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S690MC.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "41360af5-98ed-4125-a89c-ff711e4dd2bf" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "S690MC" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-St-37-2K.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-St-37-2K.FCMat index 0478534039..9f6476151e 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-St-37-2K.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-St-37-2K.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "e97be20f-246a-48b5-9718-3d39486e7af2" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "St 37-2K" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-St-E-255.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-St-E-255.FCMat index 230b39f30a..2b5057f72a 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-St-E-255.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-St-E-255.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "1078eb9f-ac3e-4b24-b40e-b9ead77828e0" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "St E 255" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-St-E-315.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-St-E-315.FCMat index efcc99b6f9..3d15c2d2df 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-St-E-315.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-St-E-315.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "74ca3b08-d561-4440-a4c2-d9b839b66670" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "St E 315" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-St-E-380.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-St-E-380.FCMat index f2d7b9df43..33b2d3c85a 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-St-E-380.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-St-E-380.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "a1b62461-7abc-45da-9a3c-3068367d2990" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "St E 380" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-St-E-460.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-St-E-460.FCMat index 9ec5596e74..5bc873d0d9 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-St-E-460.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-St-E-460.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "b312ad7b-95d4-4ca5-9736-360dbed918ee" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "St E 460" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-St-E-500.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-St-E-500.FCMat index 7c08645652..c5bc2706f3 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-St-E-500.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-St-E-500.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "90fb6bd4-05db-4d44-ba89-280b5a060921" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "St E 500" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X2CrNiMoN17-13-3.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X2CrNiMoN17-13-3.FCMat index 104b026672..083668673d 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X2CrNiMoN17-13-3.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X2CrNiMoN17-13-3.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "a05b5f9b-27b9-4554-8feb-553f9d6027ef" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "X2CrNiMoN17-13-3" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X2CrNiN24-4.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X2CrNiN24-4.FCMat index f59cd81717..d048a4677c 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X2CrNiN24-4.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X2CrNiN24-4.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "be74ada5-2775-41fc-a44b-36df6fb5e0b8" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "X2CrNiN24-4" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X39CrMo17-1.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X39CrMo17-1.FCMat index ec90558bbe..485f5099a7 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X39CrMo17-1.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X39CrMo17-1.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "9e7069ef-296d-401d-9331-d3e11267c2e0" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "X39CrMo17-1" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X3CrNiMo13-14.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X3CrNiMo13-14.FCMat index b4fc5986dd..87ec296574 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X3CrNiMo13-14.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X3CrNiMo13-14.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "88632101-8868-407a-a95f-01773b5f2245" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "X3CrNiMo13-14" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X5CrNi18-10.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X5CrNi18-10.FCMat index e8c5f023bf..0e0a81db1e 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X5CrNi18-10.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X5CrNi18-10.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "e5329208-0c38-47ec-8c59-e7bf6a35801d" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "X5CrNi18-10" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X5CrNiMo17-12-2.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X5CrNiMo17-12-2.FCMat index 5bf2b0b38b..f115a63bff 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X5CrNiMo17-12-2.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X5CrNiMo17-12-2.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "7625a484-96de-438d-b251-2b71044cfa88" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "X5CrNiMo17-12-2" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X6CrNiTi18-10.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X6CrNiTi18-10.FCMat index 8e04da41e5..76366b8f64 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X6CrNiTi18-10.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X6CrNiTi18-10.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "2c577c45-ebae-46b2-9e36-e41fbcce9286" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "X6CrNiTi18-10" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Titanium/Ti-6Al-4V.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Titanium/Ti-6Al-4V.FCMat index b68cc7b6d0..ee1b06c1b0 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Titanium/Ti-6Al-4V.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Titanium/Ti-6Al-4V.FCMat @@ -1,7 +1,7 @@ # File created by ConvertFCMat.py General: UUID: "f8013463-8008-4063-818c-ab6884cfa015" - AuthorAndLicense: "vlk" + Author: "vlk" Name: "Ti-6Al-4V (Grade 5)" Models: Father: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/ABS-Generic.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/ABS-Generic.FCMat index d85813be24..b5fba41f91 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/ABS-Generic.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/ABS-Generic.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "73371529-2983-47dd-b988-6739a2e20029" - AuthorAndLicense: "(c) 2013 Juergen Riegel (CC-BY 3.0)" + Author: "Juergen Riegel" + License: "CC-BY-3.0" Name: "ABS" Description: "This is a blend AcrylnitrilButadienStyrol (ABS) material card. The values are at the low end of the spectrum. If you need a more precise material definition use the more specialised ABS-blend cards." SourceURL: "http://www.matweb.com/search/DataSheet.aspx?MatGUID=eb7a78f5948d481c9493a67f0d089646" diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/Acrylic-Glass-Generic.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/Acrylic-Glass-Generic.FCMat index 086f0b1ad5..8daa44d95b 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/Acrylic-Glass-Generic.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/Acrylic-Glass-Generic.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "f255cd82-91d5-4e97-9032-1843128a2eaa" - AuthorAndLicense: "(c) 2016 Przemo Firszt (CC-BY 3.0)" + Author: "Przemo Firszt" + License: "CC-BY-3.0" Name: "Acrylic Glass" Description: "Poly(methyl methacrylate) (PMMA, acrylic, acrylic glass, trade names Plexiglas, Acrylite, Lucite, Perspex) a transparent thermoplastic often used in sheet form as a lightweight or shatter-resistant alternative to glass." SourceURL: "http://www.matweb.com/search/DataSheet.aspx?MatGUID=632572aeef2a4224b5ac8fbd4f1b6f77" diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/PA6-Generic.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/PA6-Generic.FCMat index 1a16486a01..2460f65648 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/PA6-Generic.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/PA6-Generic.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "9d59dc3b-ce66-4bec-82c9-b962082e7c9e" - AuthorAndLicense: "(c) 2019 Uwe Stöhr (CC-BY 3.0)" + Author: "Uwe Stöhr" + License: "CC-BY-3.0" Name: "Polyamide 6" SourceURL: "http://www.matweb.com/search/datasheet.aspx?MatGUID=8d78f3cfcb6f49d595896ce6ce6a2ef1" Models: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/PET-Generic.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/PET-Generic.FCMat index 6822285250..c80562e2b1 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/PET-Generic.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/PET-Generic.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "f73004e3-6fb4-4591-8be7-89d1370be312" - AuthorAndLicense: "(c) 2019 Uwe Stöhr (CC-BY 3.0)" + Author: "Uwe Stöhr" + License: "CC-BY-3.0" Name: "PET" SourceURL: "http://www.matweb.com/search/DataSheet.aspx?MatGUID=a696bdcdff6f41dd98f8eec3599eaa20" Models: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/PLA-Generic.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/PLA-Generic.FCMat index f1f23fd796..1eab389a6d 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/PLA-Generic.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/PLA-Generic.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "93861244-fbbe-41a9-a7e0-aeed53abd782" - AuthorAndLicense: "(c) 2019 Uwe Stöhr (CC-BY 3.0)" + Author: "Uwe Stöhr" + License: "CC-BY-3.0" Name: "PLA" Description: "Polylactic acid or polylactide (PLA, Poly) is a biodegradable thermoplastic aliphatic polyester derived from renewable resources, such as corn starch, tapioca roots, chips, starch or sugarcane." SourceURL: "https://www.sd3d.com/wp-content/uploads/2017/06/MaterialTDS-PLA_01.pdf" diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/PP-Generic.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/PP-Generic.FCMat index 19a8d81b6b..39c439f422 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/PP-Generic.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/PP-Generic.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "0e669f57-de27-4915-9a02-124f36047972" - AuthorAndLicense: "(c) 2019 Uwe Stöhr (CC-BY 3.0)" + Author: "Uwe Stöhr" + License: "CC-BY-3.0" Name: "Polypropylene" SourceURL: "http://www.matweb.com/search/DataSheet.aspx?MatGUID=a882a1c603374e278d062f106dfda95b" Models: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/PTFE-Generic.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/PTFE-Generic.FCMat index b7091e9e05..8cdd2fcb2b 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/PTFE-Generic.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/PTFE-Generic.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "8ce226db-43ef-4471-93f1-07e7276aa276" - AuthorAndLicense: "(c) 2019 Uwe Stöhr (CC-BY 3.0)" + Author: "Uwe Stöhr" + License: "CC-BY-3.0" Name: "PTFE" SourceURL: "http://www.matweb.com/search/datasheet.aspx?MatGUID=4d14eac958e5401a8fd152e1261b6843" Models: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/PVC-Generic.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/PVC-Generic.FCMat index dfde218e7f..f94f4e5b11 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/PVC-Generic.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/PVC-Generic.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "758cfc44-f4ad-4605-8645-75e9e6b053ab" - AuthorAndLicense: "(c) 2019 Uwe Stöhr (CC-BY 3.0)" + Author: "Uwe Stöhr" + License: "CC-BY-3.0" Name: "PVC" SourceURL: "http://www.matweb.com/search/DataSheet.aspx?MatGUID=1f650966ec834bb8833dd4c6e3116079" Models: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Wood/Wood-Generic.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Wood/Wood-Generic.FCMat index 9c64883f91..4f87fd1b6d 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Wood/Wood-Generic.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Wood/Wood-Generic.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "b588224e-e8d6-47ad-ba1f-a058333fd1c6" - AuthorAndLicense: "(c) 2015 Bernd Hahnebach (CC-BY 3.0)" + Author: "Bernd Hahnebach" + License: "CC-BY-3.0" Name: "Wood" Description: "A standard construction wood" Models: diff --git a/src/Mod/Material/TestMaterialsApp.py b/src/Mod/Material/TestMaterialsApp.py index 4679987368..30d562dc6f 100644 --- a/src/Mod/Material/TestMaterialsApp.py +++ b/src/Mod/Material/TestMaterialsApp.py @@ -26,220 +26,5 @@ import unittest import FreeCAD import Material -parseQuantity = FreeCAD.Units.parseQuantity -# import locale -# locale.setpreferredencoding("UTF8") - -class MaterialTestCases(unittest.TestCase): - def setUp(self): - self.ModelManager = Material.ModelManager() - self.MaterialManager = Material.MaterialManager() - - def testModelManager(self): - self.assertIn("ModelLibraries", dir(self.ModelManager)) - self.assertIn("Models", dir(self.ModelManager)) - - def testMaterialManager(self): - self.assertIn("MaterialLibraries", dir(self.MaterialManager)) - self.assertIn("Materials", dir(self.MaterialManager)) - - def testModelLoad(self): - density = self.ModelManager.getModel("454661e5-265b-4320-8e6f-fcf6223ac3af") - self.assertIsNotNone(density) - self.assertEqual(density.Name, "Density") - self.assertEqual(density.UUID, "454661e5-265b-4320-8e6f-fcf6223ac3af") - self.assertIn("Density", density.Properties) - prop = density.Properties["Density"] - self.assertIn("Description", dir(prop)) - self.assertIn("Name", dir(prop)) - self.assertIn("Type", dir(prop)) - self.assertIn("URL", dir(prop)) - self.assertIn("Units", dir(prop)) - self.assertEqual(prop.Name, "Density") - - def testCalculiXSteel(self): - steel = self.MaterialManager.getMaterial("92589471-a6cb-4bbc-b748-d425a17dea7d") - self.assertIsNotNone(steel) - self.assertEqual(steel.Name, "CalculiX-Steel") - self.assertEqual(steel.UUID, "92589471-a6cb-4bbc-b748-d425a17dea7d") - - self.assertTrue(steel.hasPhysicalModel('454661e5-265b-4320-8e6f-fcf6223ac3af')) # Density - self.assertTrue(steel.hasPhysicalModel('f6f9e48c-b116-4e82-ad7f-3659a9219c50')) # IsotropicLinearElastic - self.assertTrue(steel.hasPhysicalModel('9959d007-a970-4ea7-bae4-3eb1b8b883c7')) # Thermal - self.assertFalse(steel.hasPhysicalModel('7b561d1d-fb9b-44f6-9da9-56a4f74d7536')) # Legacy linear elastic - Not in the model - self.assertTrue(steel.hasAppearanceModel('f006c7e4-35b7-43d5-bbf9-c5d572309e6e')) # BasicRendering - inherited from Steel.FCMat - - self.assertTrue(steel.isPhysicalModelComplete('454661e5-265b-4320-8e6f-fcf6223ac3af')) # Density - self.assertFalse(steel.isPhysicalModelComplete('f6f9e48c-b116-4e82-ad7f-3659a9219c50')) # IsotropicLinearElastic - incomplete - self.assertTrue(steel.isPhysicalModelComplete('9959d007-a970-4ea7-bae4-3eb1b8b883c7')) # Thermal - self.assertFalse(steel.isPhysicalModelComplete('7b561d1d-fb9b-44f6-9da9-56a4f74d7536')) # Legacy linear elastic - Not in the model - self.assertTrue(steel.isAppearanceModelComplete('f006c7e4-35b7-43d5-bbf9-c5d572309e6e')) # BasicRendering - inherited from Steel.FCMat - - self.assertTrue(steel.hasPhysicalProperty("Density")) - self.assertTrue(steel.hasPhysicalProperty("BulkModulus")) - self.assertTrue(steel.hasPhysicalProperty("PoissonRatio")) - self.assertTrue(steel.hasPhysicalProperty("YoungsModulus")) - self.assertTrue(steel.hasPhysicalProperty("ShearModulus")) - self.assertTrue(steel.hasPhysicalProperty("SpecificHeat")) - self.assertTrue(steel.hasPhysicalProperty("ThermalConductivity")) - self.assertTrue(steel.hasPhysicalProperty("ThermalExpansionCoefficient")) - self.assertTrue(steel.hasAppearanceProperty("AmbientColor")) - self.assertTrue(steel.hasAppearanceProperty("DiffuseColor")) - self.assertTrue(steel.hasAppearanceProperty("EmissiveColor")) - self.assertTrue(steel.hasAppearanceProperty("Shininess")) - self.assertTrue(steel.hasAppearanceProperty("SpecularColor")) - self.assertTrue(steel.hasAppearanceProperty("Transparency")) - - properties = steel.PhysicalProperties - self.assertIn("Density", properties) - self.assertNotIn("BulkModulus", properties) - self.assertIn("PoissonRatio", properties) - self.assertIn("YoungsModulus", properties) - self.assertNotIn("ShearModulus", properties) - self.assertIn("SpecificHeat", properties) - self.assertIn("ThermalConductivity", properties) - self.assertIn("ThermalExpansionCoefficient", properties) - self.assertNotIn("AmbientColor", properties) - self.assertNotIn("DiffuseColor", properties) - self.assertNotIn("EmissiveColor", properties) - self.assertNotIn("Shininess", properties) - self.assertNotIn("SpecularColor", properties) - self.assertNotIn("Transparency", properties) - - properties = steel.AppearanceProperties - self.assertNotIn("Density", properties) - self.assertNotIn("BulkModulus", properties) - self.assertNotIn("PoissonRatio", properties) - self.assertNotIn("YoungsModulus", properties) - self.assertNotIn("ShearModulus", properties) - self.assertNotIn("SpecificHeat", properties) - self.assertNotIn("ThermalConductivity", properties) - self.assertNotIn("ThermalExpansionCoefficient", properties) - self.assertIn("AmbientColor", properties) - self.assertIn("DiffuseColor", properties) - self.assertIn("EmissiveColor", properties) - self.assertIn("Shininess", properties) - self.assertIn("SpecularColor", properties) - self.assertIn("Transparency", properties) - - properties = steel.Properties - self.assertIn("Density", properties) - self.assertNotIn("BulkModulus", properties) - self.assertIn("PoissonRatio", properties) - self.assertIn("YoungsModulus", properties) - self.assertNotIn("ShearModulus", properties) - self.assertIn("SpecificHeat", properties) - self.assertIn("ThermalConductivity", properties) - self.assertIn("ThermalExpansionCoefficient", properties) - self.assertIn("AmbientColor", properties) - self.assertIn("DiffuseColor", properties) - self.assertIn("EmissiveColor", properties) - self.assertIn("Shininess", properties) - self.assertIn("SpecularColor", properties) - self.assertIn("Transparency", properties) - - # - # The test for ThermalExpansionCoefficient causes problems with some localizations - # due to the Unicode mu character in the units. I don't have a solution to this - # yet so it's commented out for now - print("Density " + properties["Density"]) - # print("BulkModulus " + properties["BulkModulus"]) - print("PoissonRatio " + properties["PoissonRatio"]) - print("YoungsModulus " + properties["YoungsModulus"]) - # print("ShearModulus " + properties["ShearModulus"]) - print("SpecificHeat " + properties["SpecificHeat"]) - print("ThermalConductivity " + properties["ThermalConductivity"]) - # print("ThermalExpansionCoefficient " + properties["ThermalExpansionCoefficient"]) - print("AmbientColor " + properties["AmbientColor"]) - print("DiffuseColor " + properties["DiffuseColor"]) - print("EmissiveColor " + properties["EmissiveColor"]) - print("Shininess " + properties["Shininess"]) - print("SpecularColor " + properties["SpecularColor"]) - print("Transparency " + properties["Transparency"]) - - self.assertTrue(len(properties["Density"]) > 0) - # self.assertTrue(len(properties["BulkModulus"]) == 0) - self.assertTrue(len(properties["PoissonRatio"]) > 0) - self.assertTrue(len(properties["YoungsModulus"]) > 0) - # self.assertTrue(len(properties["ShearModulus"]) == 0) - self.assertTrue(len(properties["SpecificHeat"]) > 0) - self.assertTrue(len(properties["ThermalConductivity"]) > 0) - self.assertTrue(len(properties["ThermalExpansionCoefficient"]) > 0) - self.assertTrue(len(properties["AmbientColor"]) > 0) - self.assertTrue(len(properties["DiffuseColor"]) > 0) - self.assertTrue(len(properties["EmissiveColor"]) > 0) - self.assertTrue(len(properties["Shininess"]) > 0) - self.assertTrue(len(properties["SpecularColor"]) > 0) - self.assertTrue(len(properties["Transparency"]) > 0) - - self.assertEqual(properties["Density"], parseQuantity("7900.00 kg/m^3").UserString) - # self.assertEqual(properties["BulkModulus"], "") - self.assertAlmostEqual(parseQuantity(properties["PoissonRatio"]).Value, parseQuantity("0.30000001192092896").Value) - self.assertEqual(properties["YoungsModulus"], parseQuantity("210.00 GPa").UserString) - # self.assertEqual(properties["ShearModulus"], "") - self.assertEqual(properties["SpecificHeat"], parseQuantity("590.00 J/kg/K").UserString) - self.assertEqual(properties["ThermalConductivity"], parseQuantity("43.00 W/m/K").UserString) - self.assertEqual(properties["ThermalExpansionCoefficient"], parseQuantity("12.00 µm/m/K").UserString) - self.assertEqual(properties["AmbientColor"], "(0.0020, 0.0020, 0.0020, 1.0)") - self.assertEqual(properties["DiffuseColor"], "(0.0000, 0.0000, 0.0000, 1.0)") - self.assertEqual(properties["EmissiveColor"], "(0.0000, 0.0000, 0.0000, 1.0)") - self.assertAlmostEqual(parseQuantity(properties["Shininess"]).Value, parseQuantity("0.05999999865889549").Value) - self.assertEqual(properties["SpecularColor"], "(0.9800, 0.9800, 0.9800, 1.0)") - self.assertAlmostEqual(parseQuantity(properties["Transparency"]).Value, parseQuantity("0").Value) - - print("Density " + steel.getPhysicalValue("Density").UserString) - # print("BulkModulus " + properties["BulkModulus"]) - print("PoissonRatio %f" % steel.getPhysicalValue("PoissonRatio")) - print("YoungsModulus " + steel.getPhysicalValue("YoungsModulus").UserString) - # print("ShearModulus " + properties["ShearModulus"]) - print("SpecificHeat " + steel.getPhysicalValue("SpecificHeat").UserString) - print("ThermalConductivity " + steel.getPhysicalValue("ThermalConductivity").UserString) - # print("ThermalExpansionCoefficient " + steel.getPhysicalValue("ThermalExpansionCoefficient").UserString) - print("AmbientColor " + steel.getAppearanceValue("AmbientColor")) - print("DiffuseColor " + steel.getAppearanceValue("DiffuseColor")) - print("EmissiveColor " + steel.getAppearanceValue("EmissiveColor")) - print("Shininess %f" % steel.getAppearanceValue("Shininess")) - print("SpecularColor " + steel.getAppearanceValue("SpecularColor")) - print("Transparency %f" % steel.getAppearanceValue("Transparency")) - - self.assertAlmostEqual(steel.getPhysicalValue("Density").Value, 7.9e-06) - self.assertAlmostEqual(steel.getPhysicalValue("PoissonRatio"), 0.3) - self.assertAlmostEqual(steel.getPhysicalValue("YoungsModulus").Value, 210000000.0) - self.assertAlmostEqual(steel.getPhysicalValue("SpecificHeat").Value, 590000000.0) - self.assertAlmostEqual(steel.getPhysicalValue("ThermalConductivity").Value, 43000.0) - self.assertAlmostEqual(steel.getPhysicalValue("ThermalExpansionCoefficient").Value, 1.2e-05) - self.assertEqual(steel.getAppearanceValue("AmbientColor"), "(0.0020, 0.0020, 0.0020, 1.0)") - self.assertEqual(steel.getAppearanceValue("DiffuseColor"), "(0.0000, 0.0000, 0.0000, 1.0)") - self.assertEqual(steel.getAppearanceValue("EmissiveColor"), "(0.0000, 0.0000, 0.0000, 1.0)") - self.assertAlmostEqual(steel.getAppearanceValue("Shininess"), 0.06) - self.assertEqual(steel.getAppearanceValue("SpecularColor"), "(0.9800, 0.9800, 0.9800, 1.0)") - self.assertAlmostEqual(steel.getAppearanceValue("Transparency"), 0.0) - - def testMaterialsWithModel(self): - materials = self.MaterialManager.materialsWithModel('f6f9e48c-b116-4e82-ad7f-3659a9219c50') # IsotropicLinearElastic - materialsComplete = self.MaterialManager.materialsWithModelComplete('f6f9e48c-b116-4e82-ad7f-3659a9219c50') # IsotropicLinearElastic - - self.assertTrue(len(materialsComplete) <= len(materials)) # Not all will be complete - - materialsLinearElastic = self.MaterialManager.materialsWithModel('7b561d1d-fb9b-44f6-9da9-56a4f74d7536') # LinearElastic - - # All LinearElastic models should be in IsotropicLinearElastic since it is inherited - self.assertTrue(len(materialsLinearElastic) <= len(materials)) - for mat in materialsLinearElastic: - self.assertIn(mat, materials) - - def testMaterialByPath(self): - steel = self.MaterialManager.getMaterialByPath('StandardMaterial/Metal/Steel/CalculiX-Steel.FCMat', 'System') - self.assertIsNotNone(steel) - self.assertEqual(steel.Name, "CalculiX-Steel") - self.assertEqual(steel.UUID, "92589471-a6cb-4bbc-b748-d425a17dea7d") - - steel2 = self.MaterialManager.getMaterialByPath('/StandardMaterial/Metal/Steel/CalculiX-Steel.FCMat', 'System') - self.assertIsNotNone(steel2) - self.assertEqual(steel2.Name, "CalculiX-Steel") - self.assertEqual(steel2.UUID, "92589471-a6cb-4bbc-b748-d425a17dea7d") - - steel3 = self.MaterialManager.getMaterialByPath('/System/StandardMaterial/Metal/Steel/CalculiX-Steel.FCMat', 'System') - self.assertIsNotNone(steel3) - self.assertEqual(steel3.Name, "CalculiX-Steel") - self.assertEqual(steel3.UUID, "92589471-a6cb-4bbc-b748-d425a17dea7d") +from materialtests.TestModels import ModelTestCases +from materialtests.TestMaterials import MaterialTestCases diff --git a/src/Mod/Material/materialtests/TestMaterials.py b/src/Mod/Material/materialtests/TestMaterials.py new file mode 100644 index 0000000000..7e8cb030df --- /dev/null +++ b/src/Mod/Material/materialtests/TestMaterials.py @@ -0,0 +1,228 @@ +#************************************************************************** +# Copyright (c) 2023 David Carter * +# * +# This file is part of the FreeCAD CAx development system. * +# * +# This program is free software; you can redistribute it and/or modify * +# it under the terms of the GNU Lesser General Public License (LGPL) * +# as published by the Free Software Foundation; either version 2 of * +# the License, or (at your option) any later version. * +# for detail see the LICENCE text file. * +# * +# FreeCAD is distributed in the hope that it will be useful, * +# but WITHOUT ANY WARRANTY; without even the implied warranty of * +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +# GNU Library General Public License for more details. * +# * +# You should have received a copy of the GNU Library General Public * +# License along with FreeCAD; if not, write to the Free Software * +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * +# USA * +#************************************************************************** + +# import FreeCAD +from os import walk +import unittest +import FreeCAD +import Material + +parseQuantity = FreeCAD.Units.parseQuantity + +class MaterialTestCases(unittest.TestCase): + def setUp(self): + self.ModelManager = Material.ModelManager() + self.MaterialManager = Material.MaterialManager() + self.uuids = Material.UUIDs() + + def testMaterialManager(self): + self.assertIn("MaterialLibraries", dir(self.MaterialManager)) + self.assertIn("Materials", dir(self.MaterialManager)) + + def testCalculiXSteel(self): + steel = self.MaterialManager.getMaterial("92589471-a6cb-4bbc-b748-d425a17dea7d") + self.assertIsNotNone(steel) + self.assertEqual(steel.Name, "CalculiX-Steel") + self.assertEqual(steel.UUID, "92589471-a6cb-4bbc-b748-d425a17dea7d") + + self.assertTrue(steel.hasPhysicalModel(self.uuids.Density)) + self.assertTrue(steel.hasPhysicalModel(self.uuids.IsotropicLinearElastic)) + self.assertTrue(steel.hasPhysicalModel(self.uuids.Thermal)) + self.assertFalse(steel.hasPhysicalModel(self.uuids.LinearElastic)) # Not in the model + self.assertTrue(steel.hasAppearanceModel(self.uuids.BasicRendering)) # inherited from Steel.FCMat + + self.assertTrue(steel.isPhysicalModelComplete(self.uuids.Density)) + self.assertFalse(steel.isPhysicalModelComplete(self.uuids.IsotropicLinearElastic)) + self.assertTrue(steel.isPhysicalModelComplete(self.uuids.Thermal)) + self.assertFalse(steel.isPhysicalModelComplete(self.uuids.LinearElastic)) # Not in the model + self.assertTrue(steel.isAppearanceModelComplete(self.uuids.BasicRendering)) # inherited from Steel.FCMat + + self.assertTrue(steel.hasPhysicalProperty("Density")) + self.assertTrue(steel.hasPhysicalProperty("BulkModulus")) + self.assertTrue(steel.hasPhysicalProperty("PoissonRatio")) + self.assertTrue(steel.hasPhysicalProperty("YoungsModulus")) + self.assertTrue(steel.hasPhysicalProperty("ShearModulus")) + self.assertTrue(steel.hasPhysicalProperty("SpecificHeat")) + self.assertTrue(steel.hasPhysicalProperty("ThermalConductivity")) + self.assertTrue(steel.hasPhysicalProperty("ThermalExpansionCoefficient")) + self.assertTrue(steel.hasAppearanceProperty("AmbientColor")) + self.assertTrue(steel.hasAppearanceProperty("DiffuseColor")) + self.assertTrue(steel.hasAppearanceProperty("EmissiveColor")) + self.assertTrue(steel.hasAppearanceProperty("Shininess")) + self.assertTrue(steel.hasAppearanceProperty("SpecularColor")) + self.assertTrue(steel.hasAppearanceProperty("Transparency")) + + properties = steel.PhysicalProperties + self.assertIn("Density", properties) + self.assertNotIn("BulkModulus", properties) + self.assertIn("PoissonRatio", properties) + self.assertIn("YoungsModulus", properties) + self.assertNotIn("ShearModulus", properties) + self.assertIn("SpecificHeat", properties) + self.assertIn("ThermalConductivity", properties) + self.assertIn("ThermalExpansionCoefficient", properties) + self.assertNotIn("AmbientColor", properties) + self.assertNotIn("DiffuseColor", properties) + self.assertNotIn("EmissiveColor", properties) + self.assertNotIn("Shininess", properties) + self.assertNotIn("SpecularColor", properties) + self.assertNotIn("Transparency", properties) + + properties = steel.AppearanceProperties + self.assertNotIn("Density", properties) + self.assertNotIn("BulkModulus", properties) + self.assertNotIn("PoissonRatio", properties) + self.assertNotIn("YoungsModulus", properties) + self.assertNotIn("ShearModulus", properties) + self.assertNotIn("SpecificHeat", properties) + self.assertNotIn("ThermalConductivity", properties) + self.assertNotIn("ThermalExpansionCoefficient", properties) + self.assertIn("AmbientColor", properties) + self.assertIn("DiffuseColor", properties) + self.assertIn("EmissiveColor", properties) + self.assertIn("Shininess", properties) + self.assertIn("SpecularColor", properties) + self.assertIn("Transparency", properties) + + properties = steel.Properties + self.assertIn("Density", properties) + self.assertNotIn("BulkModulus", properties) + self.assertIn("PoissonRatio", properties) + self.assertIn("YoungsModulus", properties) + self.assertNotIn("ShearModulus", properties) + self.assertIn("SpecificHeat", properties) + self.assertIn("ThermalConductivity", properties) + self.assertIn("ThermalExpansionCoefficient", properties) + self.assertIn("AmbientColor", properties) + self.assertIn("DiffuseColor", properties) + self.assertIn("EmissiveColor", properties) + self.assertIn("Shininess", properties) + self.assertIn("SpecularColor", properties) + self.assertIn("Transparency", properties) + + # + # The test for ThermalExpansionCoefficient causes problems with some localizations + # due to the Unicode mu character in the units. This will happen with + # locales that don't support UTF8 such as zh_CN (It does support UTF-8) + # + # When this is a problem simply comment the lines printing ThermalExpansionCoefficient + print("Density " + properties["Density"]) + # print("BulkModulus " + properties["BulkModulus"]) + print("PoissonRatio " + properties["PoissonRatio"]) + print("YoungsModulus " + properties["YoungsModulus"]) + # print("ShearModulus " + properties["ShearModulus"]) + print("SpecificHeat " + properties["SpecificHeat"]) + print("ThermalConductivity " + properties["ThermalConductivity"]) + print("ThermalExpansionCoefficient " + properties["ThermalExpansionCoefficient"]) + print("AmbientColor " + properties["AmbientColor"]) + print("DiffuseColor " + properties["DiffuseColor"]) + print("EmissiveColor " + properties["EmissiveColor"]) + print("Shininess " + properties["Shininess"]) + print("SpecularColor " + properties["SpecularColor"]) + print("Transparency " + properties["Transparency"]) + + self.assertTrue(len(properties["Density"]) > 0) + # self.assertTrue(len(properties["BulkModulus"]) == 0) + self.assertTrue(len(properties["PoissonRatio"]) > 0) + self.assertTrue(len(properties["YoungsModulus"]) > 0) + # self.assertTrue(len(properties["ShearModulus"]) == 0) + self.assertTrue(len(properties["SpecificHeat"]) > 0) + self.assertTrue(len(properties["ThermalConductivity"]) > 0) + self.assertTrue(len(properties["ThermalExpansionCoefficient"]) > 0) + self.assertTrue(len(properties["AmbientColor"]) > 0) + self.assertTrue(len(properties["DiffuseColor"]) > 0) + self.assertTrue(len(properties["EmissiveColor"]) > 0) + self.assertTrue(len(properties["Shininess"]) > 0) + self.assertTrue(len(properties["SpecularColor"]) > 0) + self.assertTrue(len(properties["Transparency"]) > 0) + + self.assertEqual(properties["Density"], parseQuantity("7900.00 kg/m^3").UserString) + # self.assertEqual(properties["BulkModulus"], "") + self.assertAlmostEqual(parseQuantity(properties["PoissonRatio"]).Value, parseQuantity("0.3").Value) + self.assertEqual(properties["YoungsModulus"], parseQuantity("210.00 GPa").UserString) + # self.assertEqual(properties["ShearModulus"], "") + self.assertEqual(properties["SpecificHeat"], parseQuantity("590.00 J/kg/K").UserString) + self.assertEqual(properties["ThermalConductivity"], parseQuantity("43.00 W/m/K").UserString) + self.assertEqual(properties["ThermalExpansionCoefficient"], parseQuantity("12.00 µm/m/K").UserString) + self.assertEqual(properties["AmbientColor"], "(0.0020, 0.0020, 0.0020, 1.0)") + self.assertEqual(properties["DiffuseColor"], "(0.0000, 0.0000, 0.0000, 1.0)") + self.assertEqual(properties["EmissiveColor"], "(0.0000, 0.0000, 0.0000, 1.0)") + self.assertAlmostEqual(parseQuantity(properties["Shininess"]).Value, parseQuantity("0.06").Value) + self.assertEqual(properties["SpecularColor"], "(0.9800, 0.9800, 0.9800, 1.0)") + self.assertAlmostEqual(parseQuantity(properties["Transparency"]).Value, parseQuantity("0").Value) + + print("Density " + steel.getPhysicalValue("Density").UserString) + # print("BulkModulus " + properties["BulkModulus"]) + print("PoissonRatio %f" % steel.getPhysicalValue("PoissonRatio")) + print("YoungsModulus " + steel.getPhysicalValue("YoungsModulus").UserString) + # print("ShearModulus " + properties["ShearModulus"]) + print("SpecificHeat " + steel.getPhysicalValue("SpecificHeat").UserString) + print("ThermalConductivity " + steel.getPhysicalValue("ThermalConductivity").UserString) + print("ThermalExpansionCoefficient " + steel.getPhysicalValue("ThermalExpansionCoefficient").UserString) + print("AmbientColor " + steel.getAppearanceValue("AmbientColor")) + print("DiffuseColor " + steel.getAppearanceValue("DiffuseColor")) + print("EmissiveColor " + steel.getAppearanceValue("EmissiveColor")) + print("Shininess %f" % steel.getAppearanceValue("Shininess")) + print("SpecularColor " + steel.getAppearanceValue("SpecularColor")) + print("Transparency %f" % steel.getAppearanceValue("Transparency")) + + self.assertAlmostEqual(steel.getPhysicalValue("Density").Value, 7.9e-06) + self.assertAlmostEqual(steel.getPhysicalValue("PoissonRatio"), 0.3) + self.assertAlmostEqual(steel.getPhysicalValue("YoungsModulus").Value, 210000000.0) + self.assertAlmostEqual(steel.getPhysicalValue("SpecificHeat").Value, 590000000.0) + self.assertAlmostEqual(steel.getPhysicalValue("ThermalConductivity").Value, 43000.0) + self.assertAlmostEqual(steel.getPhysicalValue("ThermalExpansionCoefficient").Value, 1.2e-05) + self.assertEqual(steel.getAppearanceValue("AmbientColor"), "(0.0020, 0.0020, 0.0020, 1.0)") + self.assertEqual(steel.getAppearanceValue("DiffuseColor"), "(0.0000, 0.0000, 0.0000, 1.0)") + self.assertEqual(steel.getAppearanceValue("EmissiveColor"), "(0.0000, 0.0000, 0.0000, 1.0)") + self.assertAlmostEqual(steel.getAppearanceValue("Shininess"), 0.06) + self.assertEqual(steel.getAppearanceValue("SpecularColor"), "(0.9800, 0.9800, 0.9800, 1.0)") + self.assertAlmostEqual(steel.getAppearanceValue("Transparency"), 0.0) + + def testMaterialsWithModel(self): + materials = self.MaterialManager.materialsWithModel('f6f9e48c-b116-4e82-ad7f-3659a9219c50') # IsotropicLinearElastic + materialsComplete = self.MaterialManager.materialsWithModelComplete('f6f9e48c-b116-4e82-ad7f-3659a9219c50') # IsotropicLinearElastic + + self.assertTrue(len(materialsComplete) <= len(materials)) # Not all will be complete + + materialsLinearElastic = self.MaterialManager.materialsWithModel('7b561d1d-fb9b-44f6-9da9-56a4f74d7536') # LinearElastic + + # All LinearElastic models should be in IsotropicLinearElastic since it is inherited + self.assertTrue(len(materialsLinearElastic) <= len(materials)) + for mat in materialsLinearElastic: + self.assertIn(mat, materials) + + def testMaterialByPath(self): + steel = self.MaterialManager.getMaterialByPath('StandardMaterial/Metal/Steel/CalculiX-Steel.FCMat', 'System') + self.assertIsNotNone(steel) + self.assertEqual(steel.Name, "CalculiX-Steel") + self.assertEqual(steel.UUID, "92589471-a6cb-4bbc-b748-d425a17dea7d") + + steel2 = self.MaterialManager.getMaterialByPath('/StandardMaterial/Metal/Steel/CalculiX-Steel.FCMat', 'System') + self.assertIsNotNone(steel2) + self.assertEqual(steel2.Name, "CalculiX-Steel") + self.assertEqual(steel2.UUID, "92589471-a6cb-4bbc-b748-d425a17dea7d") + + steel3 = self.MaterialManager.getMaterialByPath('/System/StandardMaterial/Metal/Steel/CalculiX-Steel.FCMat', 'System') + self.assertIsNotNone(steel3) + self.assertEqual(steel3.Name, "CalculiX-Steel") + self.assertEqual(steel3.UUID, "92589471-a6cb-4bbc-b748-d425a17dea7d") diff --git a/src/Mod/Material/materialtests/TestModels.py b/src/Mod/Material/materialtests/TestModels.py new file mode 100644 index 0000000000..d4fd143442 --- /dev/null +++ b/src/Mod/Material/materialtests/TestModels.py @@ -0,0 +1,79 @@ +#************************************************************************** +# Copyright (c) 2023 David Carter * +# * +# This file is part of the FreeCAD CAx development system. * +# * +# This program is free software; you can redistribute it and/or modify * +# it under the terms of the GNU Lesser General Public License (LGPL) * +# as published by the Free Software Foundation; either version 2 of * +# the License, or (at your option) any later version. * +# for detail see the LICENCE text file. * +# * +# FreeCAD is distributed in the hope that it will be useful, * +# but WITHOUT ANY WARRANTY; without even the implied warranty of * +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +# GNU Library General Public License for more details. * +# * +# You should have received a copy of the GNU Library General Public * +# License along with FreeCAD; if not, write to the Free Software * +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * +# USA * +#************************************************************************** + +# import FreeCAD +from os import walk +import unittest +import FreeCAD +import Material + +parseQuantity = FreeCAD.Units.parseQuantity +# import locale +# locale.setpreferredencoding("UTF8") + +class ModelTestCases(unittest.TestCase): + def setUp(self): + self.ModelManager = Material.ModelManager() + self.uuids = Material.UUIDs() + + def testModelManager(self): + self.assertIn("ModelLibraries", dir(self.ModelManager)) + self.assertIn("Models", dir(self.ModelManager)) + + def testUUIDs(self): + self.assertTrue(self.uuids.Father, "9cdda8b6-b606-4778-8f13-3934d8668e67") + self.assertTrue(self.uuids.MaterialStandard, "1e2c0088-904a-4537-925f-64064c07d700") + + self.assertTrue(self.uuids.Density, "454661e5-265b-4320-8e6f-fcf6223ac3af") + self.assertTrue(self.uuids.IsotropicLinearElastic, "f6f9e48c-b116-4e82-ad7f-3659a9219c50") + self.assertTrue(self.uuids.LinearElastic,"7b561d1d-fb9b-44f6-9da9-56a4f74d7536") + self.assertTrue(self.uuids.OgdenYld2004p18, "3ef9e427-cc25-43f7-817f-79ff0d49625f") + self.assertTrue(self.uuids.OrthotropicLinearElastic, "b19ccc6b-a431-418e-91c2-0ac8c649d146") + + self.assertTrue(self.uuids.Fluid, "1ae66d8c-1ba1-4211-ad12-b9917573b202") + + self.assertTrue(self.uuids.Thermal, "9959d007-a970-4ea7-bae4-3eb1b8b883c7") + + self.assertTrue(self.uuids.Electromagnetic, "b2eb5f48-74b3-4193-9fbb-948674f427f3") + + self.assertTrue(self.uuids.Architectural, "32439c3b-262f-4b7b-99a8-f7f44e5894c8") + + self.assertTrue(self.uuids.Costs, "881df808-8726-4c2e-be38-688bb6cce466") + + self.assertTrue(self.uuids.BasicRendering, "f006c7e4-35b7-43d5-bbf9-c5d572309e6e") + self.assertTrue(self.uuids.TextureRendering, "bbdcc65b-67ca-489c-bd5c-a36e33d1c160") + self.assertTrue(self.uuids.AdvancedRendering, "c880f092-cdae-43d6-a24b-55e884aacbbf") + self.assertTrue(self.uuids.VectorRendering, "fdf5a80e-de50-4157-b2e5-b6e5f88b680e") + + def testModelLoad(self): + density = self.ModelManager.getModel(self.uuids.Density) + self.assertIsNotNone(density) + self.assertEqual(density.Name, "Density") + self.assertEqual(density.UUID, "454661e5-265b-4320-8e6f-fcf6223ac3af") + self.assertIn("Density", density.Properties) + prop = density.Properties["Density"] + self.assertIn("Description", dir(prop)) + self.assertIn("Name", dir(prop)) + self.assertIn("Type", dir(prop)) + self.assertIn("URL", dir(prop)) + self.assertIn("Units", dir(prop)) + self.assertEqual(prop.Name, "Density") diff --git a/src/Mod/Material/materialtests/__init__.py b/src/Mod/Material/materialtests/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/Tools/updatecrowdin.py b/src/Tools/updatecrowdin.py index 57c17d890f..15f197b48c 100755 --- a/src/Tools/updatecrowdin.py +++ b/src/Tools/updatecrowdin.py @@ -96,7 +96,6 @@ GENERATE_QM = { "Cloud", "Draft", "Inspection", - "Material", "OpenSCAD", "Tux", "Help", @@ -135,6 +134,11 @@ locations = [ "../Mod/Inspection/Gui/Resources/translations", "../Mod/Inspection/Gui/Resources/Inspection.qrc", ], + [ + "Material", + "../Mod/Material/Gui/Resources/translations", + "../Mod/Material/Gui/Resources/Material.qrc", + ], [ "Mesh", "../Mod/Mesh/Gui/Resources/translations", diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 7cb488ecd4..f3b605fe99 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -37,6 +37,10 @@ if(NOT BUILD_DYNAMIC_LINK_PYTHON) ) endif() +include_directories( + ${CMAKE_CURRENT_SOURCE_DIR} +) + set(CMAKE_AUTOMOC ON) function(setup_qt_test) diff --git a/tests/src/App/ComplexGeoData.cpp b/tests/src/App/ComplexGeoData.cpp index 23c6cddf4a..0f962c4d14 100644 --- a/tests/src/App/ComplexGeoData.cpp +++ b/tests/src/App/ComplexGeoData.cpp @@ -8,6 +8,7 @@ #include #include #include +#include class ConcreteComplexGeoDataForTesting: public Data::ComplexGeoData @@ -72,12 +73,7 @@ class ComplexGeoDataTest: public ::testing::Test protected: static void SetUpTestSuite() { - if (App::Application::GetARGC() == 0) { - constexpr int argc = 1; - std::array argv {"FreeCAD"}; - App::Application::Config()["ExeName"] = "FreeCAD"; - App::Application::init(argc, argv.data()); - } + tests::initApplication(); } void SetUp() override diff --git a/tests/src/App/Document.cpp b/tests/src/App/Document.cpp index 027c60c583..5ac999765d 100644 --- a/tests/src/App/Document.cpp +++ b/tests/src/App/Document.cpp @@ -7,6 +7,7 @@ #include "App/Document.h" #include "App/StringHasher.h" #include "Base/Writer.h" +#include using ::testing::Eq; using ::testing::Ne; @@ -28,12 +29,7 @@ class DocumentTest: public ::testing::Test protected: static void SetUpTestSuite() { - if (App::Application::GetARGC() == 0) { - constexpr int argc = 1; - std::array argv {"FreeCAD"}; - App::Application::Config()["ExeName"] = "FreeCAD"; - App::Application::init(argc, const_cast(argv.data())); // NOLINT - } + tests::initApplication(); } void SetUp() override diff --git a/tests/src/App/ElementMap.cpp b/tests/src/App/ElementMap.cpp index 05fba5cbea..3e63bb1a7e 100644 --- a/tests/src/App/ElementMap.cpp +++ b/tests/src/App/ElementMap.cpp @@ -4,6 +4,7 @@ #include #include +#include // NOLINTBEGIN(readability-magic-numbers) @@ -45,12 +46,7 @@ class ElementMapTest: public ::testing::Test protected: static void SetUpTestSuite() { - if (App::Application::GetARGC() == 0) { - int argc = 1; - char* argv[] = {"FreeCAD"}; - App::Application::Config()["ExeName"] = "FreeCAD"; - App::Application::init(argc, argv); - } + tests::initApplication(); } void SetUp() override diff --git a/tests/src/App/InitApplication.h b/tests/src/App/InitApplication.h new file mode 100644 index 0000000000..53cc4f5b13 --- /dev/null +++ b/tests/src/App/InitApplication.h @@ -0,0 +1,21 @@ +#ifndef TEST_APPLICATION_H +#define TEST_APPLICATION_H + +#include + +namespace tests +{ + +static void initApplication() +{ + if (App::Application::GetARGC() == 0) { + constexpr int argc = 1; + std::array argv {"FreeCAD"}; + App::Application::Config()["ExeName"] = "FreeCAD"; + App::Application::init(argc, const_cast(argv.data())); // NOLINT + } +} + +} // namespace tests + +#endif // TEST_APPLICATION_H diff --git a/tests/src/Gui/QuantitySpinBox.cpp b/tests/src/Gui/QuantitySpinBox.cpp index 05f571dac4..ebfc454c70 100644 --- a/tests/src/Gui/QuantitySpinBox.cpp +++ b/tests/src/Gui/QuantitySpinBox.cpp @@ -6,6 +6,7 @@ #include #include "Gui/QuantitySpinBox.h" +#include // NOLINTBEGIN(readability-magic-numbers) @@ -16,12 +17,7 @@ class testQuantitySpinBox: public QObject public: testQuantitySpinBox() { - if (App::Application::GetARGC() == 0) { - constexpr int argc = 1; - std::array argv {"FreeCAD"}; - App::Application::Config()["ExeName"] = "FreeCAD"; - App::Application::init(argc, argv.data()); - } + tests::initApplication(); qsb = std::make_unique(); } diff --git a/tests/src/Mod/Material/App/CMakeLists.txt b/tests/src/Mod/Material/App/CMakeLists.txt index 879f74ef06..1e1fe038b7 100644 --- a/tests/src/Mod/Material/App/CMakeLists.txt +++ b/tests/src/Mod/Material/App/CMakeLists.txt @@ -2,5 +2,9 @@ target_sources( Material_tests_run PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR}/Model.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/TestMaterialProperties.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/TestMaterials.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/TestMaterialValue.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/TestModel.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/TestModelProperties.cpp ) diff --git a/tests/src/Mod/Material/App/Model.cpp b/tests/src/Mod/Material/App/Model.cpp index 19300f1231..6a0f84b354 100644 --- a/tests/src/Mod/Material/App/Model.cpp +++ b/tests/src/Mod/Material/App/Model.cpp @@ -33,18 +33,14 @@ #include #include #include +#include // clang-format off class MaterialTest : public ::testing::Test { protected: static void SetUpTestSuite() { - if (App::Application::GetARGC() == 0) { - constexpr int argc = 1; - std::array argv {"FreeCAD"}; - App::Application::Config()["ExeName"] = "FreeCAD"; - App::Application::init(argc, argv.data()); - } + tests::initApplication(); } void SetUp() override { diff --git a/tests/src/Mod/Material/App/TestMaterialProperties.cpp b/tests/src/Mod/Material/App/TestMaterialProperties.cpp new file mode 100644 index 0000000000..bac0b1adee --- /dev/null +++ b/tests/src/Mod/Material/App/TestMaterialProperties.cpp @@ -0,0 +1,226 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later +/*************************************************************************** + * Copyright (c) 2023 David Carter * + * * + * This file is part of FreeCAD. * + * * + * FreeCAD is free software: you can redistribute it and/or modify it * + * under the terms of the GNU Lesser General Public License as * + * published by the Free Software Foundation, either version 2.1 of the * + * License, or (at your option) any later version. * + * * + * FreeCAD is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with FreeCAD. If not, see * + * . * + * * + **************************************************************************/ + +#include "gtest/gtest.h" + +#include +#ifndef _PreComp_ +#endif + +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include + +class TestMaterialProperties: public ::testing::Test +{ +protected: + static void SetUpTestSuite() + {} + + void SetUp() override + { + // 2D Properties + modelProp = Materials::ModelProperty(QString::fromStdString("Density"), // Name + QString::fromStdString("2DArray"), // Type + QString::fromStdString(""), // Units + QString::fromStdString(""), // URL + QString::fromStdString("desc")); // Description + modelProp1 = Materials::ModelProperty(QString::fromStdString("Temperature"), + QString::fromStdString("Quantity"), + QString::fromStdString("C"), + QString::fromStdString(""), + QString::fromStdString("desc1")); + modelProp2 = Materials::ModelProperty( + QString::fromStdString("Density"), + QString::fromStdString("Quantity"), + QString::fromStdString("kg/m^3"), + QString::fromStdString("https://en.wikipedia.org/wiki/Density"), + QString::fromStdString("desc2")); + + modelProp.addColumn(modelProp1); + modelProp.addColumn(modelProp2); + + // 3D properties + model3DProp = Materials::ModelProperty( + QString::fromStdString("StressStrain"), // Name + QString::fromStdString("3DArray"), // Type + QString::fromStdString(""), // Units + QString::fromStdString(""), // URL + QString::fromStdString("3 Dimensional array showing stress and strain as a function of " + "temperature")); // Description + model3DProp1 = Materials::ModelProperty(QString::fromStdString("Temperature"), + QString::fromStdString("Quantity"), + QString::fromStdString("C"), + QString::fromStdString(""), + QString::fromStdString("desc1")); + model3DProp2 = Materials::ModelProperty(QString::fromStdString("Stress"), + QString::fromStdString("Quantity"), + QString::fromStdString("MPa"), + QString::fromStdString(""), + QString::fromStdString("desc2")); + model3DProp3 = Materials::ModelProperty(QString::fromStdString("Strain"), + QString::fromStdString("Quantity"), + QString::fromStdString("MPa"), + QString::fromStdString(""), + QString::fromStdString("desc3")); + + model3DProp.addColumn(model3DProp1); + model3DProp.addColumn(model3DProp2); + model3DProp.addColumn(model3DProp3); + } + + // void TearDown() override {} + + Materials::ModelProperty modelProp; + Materials::ModelProperty modelProp1; + Materials::ModelProperty modelProp2; + Materials::ModelProperty model3DProp; + Materials::ModelProperty model3DProp1; + Materials::ModelProperty model3DProp2; + Materials::ModelProperty model3DProp3; +}; + +TEST_F(TestMaterialProperties, TestEmpty) +{ + Materials::MaterialProperty prop; + EXPECT_EQ(prop.getType(), Materials::MaterialValue::None); + EXPECT_TRUE(prop.isNull()); + auto variant = prop.getValue(); + EXPECT_TRUE(variant.isNull()); + EXPECT_FALSE(variant.canConvert()); + EXPECT_TRUE(variant.toString().isNull()); + EXPECT_TRUE(variant.toString().isEmpty()); + EXPECT_EQ(variant.toString().size(), 0); +} + +TEST_F(TestMaterialProperties, TestSingle) +{ + Materials::MaterialProperty prop(modelProp1); + EXPECT_EQ(prop.getType(), Materials::MaterialValue::Quantity); + EXPECT_TRUE(prop.isNull()); + auto variant = prop.getValue(); + EXPECT_TRUE(variant.canConvert()); + EXPECT_FALSE(variant.value().isValid()); + EXPECT_FALSE(variant.canConvert()); + EXPECT_TRUE(variant.toString().isNull()); + EXPECT_TRUE(variant.toString().isEmpty()); + EXPECT_EQ(variant.toString().size(), 0); +} + +void check2DArray(Materials::MaterialProperty& prop) +{ + EXPECT_EQ(prop.getType(), Materials::MaterialValue::Array2D); + EXPECT_TRUE(prop.isNull()); + auto array = std::static_pointer_cast(prop.getMaterialValue()); + EXPECT_FALSE(array->defaultSet()); + EXPECT_EQ(array->rows(), 0); + auto variant = prop.getValue(); // Throw an error? + // Getting a default value is not yet defined or implemented + // EXPECT_TRUE(variant.canConvert()); + // EXPECT_TRUE(variant.isNull()); + // EXPECT_FALSE(variant.value().isValid()); -- the variant is null + EXPECT_FALSE(variant.canConvert()); + EXPECT_TRUE(variant.toString().isNull()); + EXPECT_TRUE(variant.toString().isEmpty()); + EXPECT_EQ(variant.toString().size(), 0); + + // Check the columns + EXPECT_EQ(prop.columns(), 2); +} + +TEST_F(TestMaterialProperties, Test2DArray) +{ + Materials::MaterialProperty prop(modelProp); + check2DArray(prop); +} + +TEST_F(TestMaterialProperties, Test2DArrayCopy) +{ + Materials::MaterialProperty propBase(modelProp); + Materials::MaterialProperty prop(propBase); + check2DArray(prop); +} + +TEST_F(TestMaterialProperties, Test2DArrayAssignment) +{ + Materials::MaterialProperty propBase(modelProp); + Materials::MaterialProperty prop; + + prop = propBase; + check2DArray(prop); +} + +void check3DArray(Materials::MaterialProperty& prop) +{ + EXPECT_EQ(prop.getType(), Materials::MaterialValue::Array3D); + EXPECT_TRUE(prop.isNull()); + auto array = std::static_pointer_cast(prop.getMaterialValue()); + EXPECT_FALSE(array->defaultSet()); + EXPECT_EQ(array->depth(), 0); + auto variant = prop.getValue(); // Throw an error? + // Getting a default value is not yet defined or implemented + // EXPECT_TRUE(variant.canConvert()); + // EXPECT_TRUE(variant.isNull()); + // EXPECT_FALSE(variant.value().isValid()); -- the variant is null + EXPECT_FALSE(variant.canConvert()); + EXPECT_TRUE(variant.toString().isNull()); + EXPECT_TRUE(variant.toString().isEmpty()); + EXPECT_EQ(variant.toString().size(), 0); + + // Check the columns + EXPECT_EQ(prop.columns(), 3); +} + +TEST_F(TestMaterialProperties, Test3DArray) +{ + Materials::MaterialProperty prop(model3DProp); + check3DArray(prop); +} + +TEST_F(TestMaterialProperties, Test3DArrayCopy) +{ + Materials::MaterialProperty propBase(model3DProp); + Materials::MaterialProperty prop(propBase); + check3DArray(prop); +} + +TEST_F(TestMaterialProperties, Test3DArrayAssignment) +{ + Materials::MaterialProperty propBase(model3DProp); + Materials::MaterialProperty prop; + + prop = propBase; + check3DArray(prop); +} + +// clang-format off + +// clang-format on diff --git a/tests/src/Mod/Material/App/TestMaterialValue.cpp b/tests/src/Mod/Material/App/TestMaterialValue.cpp new file mode 100644 index 0000000000..d39023f939 --- /dev/null +++ b/tests/src/Mod/Material/App/TestMaterialValue.cpp @@ -0,0 +1,310 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later +/*************************************************************************** + * Copyright (c) 2023 David Carter * + * * + * This file is part of FreeCAD. * + * * + * FreeCAD is free software: you can redistribute it and/or modify it * + * under the terms of the GNU Lesser General Public License as * + * published by the Free Software Foundation, either version 2.1 of the * + * License, or (at your option) any later version. * + * * + * FreeCAD is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with FreeCAD. If not, see * + * . * + * * + **************************************************************************/ + +#include "gtest/gtest.h" + +#include +#ifndef _PreComp_ +#endif + +#include +#include + +#include +#include + +#include +#include +#include +#include + +// clang-format off + +class TestMaterialValue : public ::testing::Test { + protected: + static void SetUpTestSuite() { + // if (App::Application::GetARGC() == 0) { + // constexpr int argc = 1; + // std::array argv {"FreeCAD"}; + // App::Application::Config()["ExeName"] = "FreeCAD"; + // App::Application::init(argc, argv.data()); + // } + } + +// void SetUp() override { +// _modelManager = new Materials::ModelManager(); +// _materialManager = new Materials::MaterialManager(); +// } + + // void TearDown() override {} +// Materials::ModelManager* _modelManager; +// Materials::MaterialManager* _materialManager; +}; + +TEST_F(TestMaterialValue, TestNoneType) +{ + auto mat1 = Materials::MaterialValue(); + EXPECT_EQ(mat1.getType(), Materials::MaterialValue::None); + EXPECT_TRUE(mat1.isNull()); + auto variant = mat1.getValue(); + EXPECT_TRUE(variant.isNull()); + EXPECT_FALSE(variant.canConvert()); + EXPECT_TRUE(variant.toString().isNull()); + EXPECT_TRUE(variant.toString().isEmpty()); + EXPECT_EQ(variant.toString().size(), 0); +} + +TEST_F(TestMaterialValue, TestStringType) +{ + auto mat1 = Materials::MaterialValue(Materials::MaterialValue::String); + EXPECT_EQ(mat1.getType(), Materials::MaterialValue::String); + EXPECT_TRUE(mat1.isNull()); + auto variant = mat1.getValue(); + EXPECT_TRUE(variant.isNull()); + EXPECT_TRUE(variant.canConvert()); + EXPECT_TRUE(variant.toString().isNull()); + EXPECT_TRUE(variant.toString().isEmpty()); + EXPECT_EQ(variant.toString().size(), 0); +} + +TEST_F(TestMaterialValue, TestBooleanType) +{ + auto mat1 = Materials::MaterialValue(Materials::MaterialValue::Boolean); + EXPECT_EQ(mat1.getType(), Materials::MaterialValue::Boolean); + EXPECT_TRUE(mat1.isNull()); + auto variant = mat1.getValue(); + EXPECT_TRUE(variant.isNull()); + EXPECT_TRUE(variant.canConvert()); + EXPECT_FALSE(variant.toString().isNull()); + EXPECT_FALSE(variant.toString().isEmpty()); + EXPECT_EQ(variant.toString().size(), 5); + EXPECT_EQ(variant.toString(), QString::fromStdString("false")); + EXPECT_EQ(variant.toBool(), false); +} + +TEST_F(TestMaterialValue, TestIntegerType) +{ + auto mat1 = Materials::MaterialValue(Materials::MaterialValue::Integer); + EXPECT_EQ(mat1.getType(), Materials::MaterialValue::Integer); + EXPECT_TRUE(mat1.isNull()); + auto variant = mat1.getValue(); + EXPECT_TRUE(variant.isNull()); + EXPECT_TRUE(variant.canConvert()); + EXPECT_FALSE(variant.toString().isNull()); + EXPECT_FALSE(variant.toString().isEmpty()); + EXPECT_EQ(variant.toString().size(), 1); + EXPECT_EQ(variant.toString(), QString::fromStdString("0")); + EXPECT_EQ(variant.toInt(), 0); +} + +TEST_F(TestMaterialValue, TestFloatType) +{ + auto mat1 = Materials::MaterialValue(Materials::MaterialValue::Float); + EXPECT_EQ(mat1.getType(), Materials::MaterialValue::Float); + EXPECT_TRUE(mat1.isNull()); + auto variant = mat1.getValue(); + EXPECT_TRUE(variant.isNull()); + EXPECT_TRUE(variant.canConvert()); + EXPECT_FALSE(variant.toString().isNull()); + EXPECT_FALSE(variant.toString().isEmpty()); + EXPECT_EQ(variant.toString().size(), 1); + EXPECT_EQ(variant.toString(), QString::fromStdString("0")); + EXPECT_EQ(variant.toFloat(), 0); +} + +TEST_F(TestMaterialValue, TestQuantityType) +{ + auto mat1 = Materials::MaterialValue(Materials::MaterialValue::Quantity); + EXPECT_EQ(mat1.getType(), Materials::MaterialValue::Quantity); + EXPECT_TRUE(mat1.isNull()); + + auto variant = mat1.getValue(); + EXPECT_FALSE(variant.isNull()); + EXPECT_TRUE(variant.canConvert()); + EXPECT_TRUE(variant.toString().isNull()); + EXPECT_TRUE(variant.toString().isEmpty()); + EXPECT_EQ(variant.toString().size(), 0); + + auto quantity = variant.value(); + EXPECT_FALSE(quantity.isValid()); + EXPECT_EQ(quantity.getUserString(), QString::fromStdString("nan ")); + EXPECT_TRUE(std::isnan(quantity.getValue())); + + // Test a copy + auto mat2 = Materials::MaterialValue(mat1); + EXPECT_EQ(mat2.getType(), Materials::MaterialValue::Quantity); + EXPECT_TRUE(mat2.isNull()); + + variant = mat2.getValue(); + EXPECT_FALSE(variant.isNull()); + EXPECT_TRUE(variant.canConvert()); + EXPECT_TRUE(variant.toString().isNull()); + EXPECT_TRUE(variant.toString().isEmpty()); + EXPECT_EQ(variant.toString().size(), 0); + + quantity = variant.value(); + EXPECT_FALSE(quantity.isValid()); + EXPECT_EQ(quantity.getUserString(), QString::fromStdString("nan ")); + EXPECT_TRUE(std::isnan(quantity.getValue())); +} + +TEST_F(TestMaterialValue, TestListType) +{ + auto mat1 = Materials::MaterialValue(Materials::MaterialValue::List); + EXPECT_EQ(mat1.getType(), Materials::MaterialValue::List); + EXPECT_TRUE(mat1.isNull()); + auto variant = mat1.getValue(); + EXPECT_TRUE(variant.isNull()); + EXPECT_TRUE(variant.canConvert()); + EXPECT_TRUE(variant.toString().isNull()); + EXPECT_TRUE(variant.toString().isEmpty()); + EXPECT_EQ(variant.toString().size(), 0); +} + +TEST_F(TestMaterialValue, TestArray2DType) +{ + EXPECT_THROW(auto mat1 = Materials::MaterialValue(Materials::MaterialValue::Array2D), Materials::InvalidMaterialType); + + auto mat2 = Materials::Material2DArray(); + EXPECT_EQ(mat2.getType(), Materials::MaterialValue::Array2D); + EXPECT_TRUE(mat2.isNull()); + auto variant = mat2.getDefault(); + EXPECT_TRUE(variant.isNull()); + EXPECT_FALSE(variant.canConvert()); + EXPECT_TRUE(variant.toString().isNull()); + EXPECT_TRUE(variant.toString().isEmpty()); + EXPECT_EQ(variant.toString().size(), 0); + + EXPECT_EQ(mat2.rows(), 0); +} + +TEST_F(TestMaterialValue, TestArray3DType) +{ + EXPECT_THROW(auto mat1 = Materials::MaterialValue(Materials::MaterialValue::Array3D), Materials::InvalidMaterialType); + + auto mat2 = Materials::Material3DArray(); + EXPECT_EQ(mat2.getType(), Materials::MaterialValue::Array3D); + EXPECT_TRUE(mat2.isNull()); + auto variant = mat2.getDefault(); + EXPECT_TRUE(variant.isNull()); + EXPECT_FALSE(variant.canConvert()); + EXPECT_TRUE(variant.toString().isNull()); + EXPECT_TRUE(variant.toString().isEmpty()); + EXPECT_EQ(variant.toString().size(), 0); + + EXPECT_EQ(mat2.depth(), 0); + EXPECT_EQ(mat2.rows(), 0); + EXPECT_EQ(mat2.rows(0), 0); + EXPECT_THROW(mat2.rows(1), Materials::InvalidDepth); + + Base::Quantity quantity; + quantity.setInvalid(); + + EXPECT_EQ(mat2.addDepth(0, quantity), 0); + EXPECT_EQ(mat2.depth(), 1); + EXPECT_EQ(mat2.rows(0), 0); + EXPECT_THROW(mat2.rows(1), Materials::InvalidDepth); + + EXPECT_EQ(mat2.addDepth(quantity), 1); + EXPECT_EQ(mat2.depth(), 2); + EXPECT_EQ(mat2.rows(1), 0); + + EXPECT_THROW(mat2.addDepth(99, quantity), Materials::InvalidDepth); + EXPECT_EQ(mat2.addDepth(2, quantity), 2); + EXPECT_EQ(mat2.depth(), 3); + EXPECT_EQ(mat2.rows(2), 0); + + // Add rows + auto row = std::make_shared>(); + row->push_back(quantity); + row->push_back(quantity); + + EXPECT_EQ(mat2.rows(0), 0); + EXPECT_EQ(mat2.rows(1), 0); + EXPECT_EQ(mat2.rows(2), 0); + + mat2.addRow(0, row); + EXPECT_EQ(mat2.rows(0), 1); + EXPECT_EQ(mat2.rows(1), 0); + EXPECT_EQ(mat2.rows(2), 0); + + mat2.addRow(1, row); + EXPECT_EQ(mat2.rows(0), 1); + EXPECT_EQ(mat2.rows(1), 1); + EXPECT_EQ(mat2.rows(2), 0); + + mat2.addRow(2, row); + EXPECT_EQ(mat2.rows(0), 1); + EXPECT_EQ(mat2.rows(1), 1); + EXPECT_EQ(mat2.rows(2), 1); + + EXPECT_EQ(mat2.currentDepth(), 0); + mat2.addRow(row); + EXPECT_EQ(mat2.rows(0), 2); + EXPECT_EQ(mat2.rows(1), 1); + EXPECT_EQ(mat2.rows(2), 1); + + mat2.setCurrentDepth(2); + EXPECT_EQ(mat2.currentDepth(), 2); + mat2.addRow(row); + EXPECT_EQ(mat2.rows(0), 2); + EXPECT_EQ(mat2.rows(1), 1); + EXPECT_EQ(mat2.rows(2), 2); + + quantity = Base::Quantity::parse(QString::fromStdString("32 C")); + mat2.setDepthValue(quantity); + EXPECT_FALSE(mat2.getDepthValue(0).isValid()); + EXPECT_FALSE(mat2.getDepthValue(1).isValid()); + EXPECT_TRUE(mat2.getDepthValue(2).isValid()); + EXPECT_EQ(mat2.getDepthValue(2), Base::Quantity::parse(QString::fromStdString("32 C"))); + + mat2.setDepthValue(0, Base::Quantity::parse(QString::fromStdString("9.8 m/s/s"))); + EXPECT_TRUE(mat2.getDepthValue(0).isValid()); + EXPECT_FALSE(mat2.getDepthValue(1).isValid()); + EXPECT_TRUE(mat2.getDepthValue(2).isValid()); + EXPECT_EQ(mat2.getDepthValue(0), Base::Quantity::parse(QString::fromStdString("9.8 m/s/s"))); + EXPECT_EQ(mat2.getDepthValue(2), Base::Quantity::parse(QString::fromStdString("32 C"))); + + mat2.setDepthValue(1, Base::Quantity::parse(QString::fromStdString("120 MPa"))); + EXPECT_TRUE(mat2.getDepthValue(0).isValid()); + EXPECT_TRUE(mat2.getDepthValue(1).isValid()); + EXPECT_TRUE(mat2.getDepthValue(2).isValid()); + EXPECT_EQ(mat2.getDepthValue(0), Base::Quantity::parse(QString::fromStdString("9.8 m/s/s"))); + EXPECT_EQ(mat2.getDepthValue(1), Base::Quantity::parse(QString::fromStdString("120 MPa"))); + EXPECT_EQ(mat2.getDepthValue(2), Base::Quantity::parse(QString::fromStdString("32 C"))); + + // Rows are currently empty + EXPECT_THROW(mat2.getValue(2, 0), Materials::InvalidRow); + EXPECT_NO_THROW(mat2.getValue(0, 0)); + EXPECT_FALSE(mat2.getValue(0, 0).isValid()); + EXPECT_FALSE(mat2.getValue(0, 1).isValid()); + + // set to a valid quantity + mat2.setValue(0, 0, Base::Quantity::parse(QString::fromStdString("120 MPa"))); + EXPECT_TRUE(mat2.getValue(0, 0).isValid()); + mat2.setValue(0, 1, Base::Quantity::parse(QString::fromStdString("9.8 m/s/s"))); + EXPECT_TRUE(mat2.getValue(0, 1).isValid()); + EXPECT_THROW(mat2.setValue(0, 2, Base::Quantity::parse(QString::fromStdString("32 C"))), Materials::InvalidColumn); + +} + +// clang-format on diff --git a/tests/src/Mod/Material/App/TestMaterials.cpp b/tests/src/Mod/Material/App/TestMaterials.cpp new file mode 100644 index 0000000000..e06212c3d4 --- /dev/null +++ b/tests/src/Mod/Material/App/TestMaterials.cpp @@ -0,0 +1,339 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later +/*************************************************************************** + * Copyright (c) 2023 David Carter * + * * + * This file is part of FreeCAD. * + * * + * FreeCAD is free software: you can redistribute it and/or modify it * + * under the terms of the GNU Lesser General Public License as * + * published by the Free Software Foundation, either version 2.1 of the * + * License, or (at your option) any later version. * + * * + * FreeCAD is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with FreeCAD. If not, see * + * . * + * * + **************************************************************************/ + +#include "gtest/gtest.h" + +#include +#ifndef _PreComp_ +#endif + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +// clang-format off + +class TestMaterial : public ::testing::Test { + protected: + static void SetUpTestSuite() { + if (App::Application::GetARGC() == 0) { + constexpr int argc = 1; + std::array argv {"FreeCAD"}; + App::Application::Config()["ExeName"] = "FreeCAD"; + App::Application::init(argc, argv.data()); + } + } + + void SetUp() override { + _modelManager = new Materials::ModelManager(); + _materialManager = new Materials::MaterialManager(); + } + + // void TearDown() override {} + Materials::ModelManager* _modelManager; + Materials::MaterialManager* _materialManager; +}; + +TEST_F(TestMaterial, TestInstallation) +{ + EXPECT_NE(_modelManager, nullptr); + + // We should have loaded at least the system library + auto libraries = _materialManager->getMaterialLibraries(); + ASSERT_GT(libraries->size(), 0); + + // We should have at least one material + auto materials = _materialManager->getMaterials(); + ASSERT_GT(materials->size(), 0); +} + +TEST_F(TestMaterial, TestMaterialsWithModel) +{ + auto materials = _materialManager->materialsWithModel( + QString::fromStdString("f6f9e48c-b116-4e82-ad7f-3659a9219c50")); // IsotropicLinearElastic + EXPECT_GT(materials->size(), 0); + + auto materialsComplete = _materialManager->materialsWithModelComplete( + QString::fromStdString("f6f9e48c-b116-4e82-ad7f-3659a9219c50")); // IsotropicLinearElastic + EXPECT_LE(materialsComplete->size(), materials->size()); + + auto materialsLinearElastic = _materialManager->materialsWithModel( + QString::fromStdString("7b561d1d-fb9b-44f6-9da9-56a4f74d7536")); // LinearElastic + + // All LinearElastic models should be in IsotropicLinearElastic since it is inherited + EXPECT_LE(materialsLinearElastic->size(), materials->size()); + for (auto itp = materialsLinearElastic->begin(); itp != materialsLinearElastic->end(); itp++) { + auto mat = itp->first; + EXPECT_NO_THROW(materials->at(mat)); + } +} + +TEST_F(TestMaterial, TestMaterialByPath) +{ + auto steel = _materialManager->getMaterialByPath( + QString::fromStdString("StandardMaterial/Metal/Steel/CalculiX-Steel.FCMat"), + QString::fromStdString("System")); + EXPECT_NE(&steel, nullptr); + EXPECT_EQ(steel->getName(), QString::fromStdString("CalculiX-Steel")); + EXPECT_EQ(steel->getUUID(), QString::fromStdString("92589471-a6cb-4bbc-b748-d425a17dea7d")); + + // The same but with a leading '/' + auto steel2 = _materialManager->getMaterialByPath( + QString::fromStdString("/StandardMaterial/Metal/Steel/CalculiX-Steel.FCMat"), + QString::fromStdString("System")); + EXPECT_NE(&steel2, nullptr); + EXPECT_EQ(steel2->getName(), QString::fromStdString("CalculiX-Steel")); + EXPECT_EQ(steel2->getUUID(), QString::fromStdString("92589471-a6cb-4bbc-b748-d425a17dea7d")); + + // Same with the library name as a prefix + auto steel3 = _materialManager->getMaterialByPath( + QString::fromStdString("/System/StandardMaterial/Metal/Steel/CalculiX-Steel.FCMat"), + QString::fromStdString("System")); + EXPECT_NE(&steel3, nullptr); + EXPECT_EQ(steel3->getName(), QString::fromStdString("CalculiX-Steel")); + EXPECT_EQ(steel3->getUUID(), QString::fromStdString("92589471-a6cb-4bbc-b748-d425a17dea7d")); +} + +TEST_F(TestMaterial, TestAddPhysicalModel) +{ + // Start with an empty material + Materials::Material material; + auto models = material.getPhysicalModels(); + EXPECT_NE(&models, nullptr); + EXPECT_EQ(models->size(), 0); + + // Add a model + material.addPhysical(Materials::ModelUUIDs::ModelUUID_Electromagnetic_Default); + models = material.getPhysicalModels(); + EXPECT_EQ(models->size(), 1); + + // Add a second model + material.addPhysical(Materials::ModelUUIDs::ModelUUID_Mechanical_LinearElastic); + models = material.getPhysicalModels(); + EXPECT_EQ(models->size(), 2); + + // Add an inherited model + material.addPhysical(Materials::ModelUUIDs::ModelUUID_Mechanical_IsotropicLinearElastic); + models = material.getPhysicalModels(); + EXPECT_EQ(models->size(), 2); + + // Add a super model + material.clearModels(); + EXPECT_EQ(models->size(), 0); + + material.addPhysical(Materials::ModelUUIDs::ModelUUID_Mechanical_IsotropicLinearElastic); + models = material.getPhysicalModels(); + EXPECT_EQ(models->size(), 1); + material.addPhysical(Materials::ModelUUIDs::ModelUUID_Mechanical_LinearElastic); + models = material.getPhysicalModels(); + EXPECT_EQ(models->size(), 1); + + // Remove the inherited model + material.removePhysical(Materials::ModelUUIDs::ModelUUID_Mechanical_IsotropicLinearElastic); + models = material.getPhysicalModels(); + EXPECT_EQ(models->size(), 1); + + // Remove the super model + material.removePhysical(Materials::ModelUUIDs::ModelUUID_Mechanical_LinearElastic); + models = material.getPhysicalModels(); + EXPECT_EQ(models->size(), 0); +} + +TEST_F(TestMaterial, TestAddAppearanceModel) +{ + // Start with an empty material + Materials::Material material; + auto models = material.getAppearanceModels(); + EXPECT_NE(models, nullptr); + EXPECT_EQ(models->size(), 0); + + // Add a model + material.addAppearance(Materials::ModelUUIDs::ModelUUID_Rendering_Vector); + models = material.getAppearanceModels(); + EXPECT_EQ(models->size(), 1); + + // Add a second model + material.addAppearance(Materials::ModelUUIDs::ModelUUID_Rendering_Advanced); + models = material.getAppearanceModels(); + EXPECT_EQ(models->size(), 2); + + // Add an inherited model + material.addAppearance(Materials::ModelUUIDs::ModelUUID_Rendering_Basic); + models = material.getAppearanceModels(); + EXPECT_EQ(models->size(), 2); + + // Add a super model + material.clearModels(); + EXPECT_EQ(models->size(), 0); + + material.addAppearance(Materials::ModelUUIDs::ModelUUID_Rendering_Basic); + models = material.getAppearanceModels(); + EXPECT_EQ(models->size(), 1); + material.addAppearance(Materials::ModelUUIDs::ModelUUID_Rendering_Advanced); + models = material.getAppearanceModels(); + EXPECT_EQ(models->size(), 1); + + // Remove the inherited model + material.removeAppearance(Materials::ModelUUIDs::ModelUUID_Rendering_Basic); + models = material.getAppearanceModels(); + EXPECT_EQ(models->size(), 1); + + // Remove the super model + material.removeAppearance(Materials::ModelUUIDs::ModelUUID_Rendering_Advanced); + models = material.getAppearanceModels(); + EXPECT_EQ(models->size(), 0); +} + +QString parseQuantity(const char *string) +{ + QString value = QString::fromStdString(string); + return Base::Quantity::parse(value).getUserString(); +} + +TEST_F(TestMaterial, TestCalculiXSteel) +{ + auto steel = _materialManager->getMaterial(QString::fromStdString("92589471-a6cb-4bbc-b748-d425a17dea7d")); + EXPECT_EQ(steel->getName(), QString::fromStdString("CalculiX-Steel")); + EXPECT_EQ(steel->getUUID(), QString::fromStdString("92589471-a6cb-4bbc-b748-d425a17dea7d")); + + EXPECT_TRUE(steel->hasPhysicalModel(Materials::ModelUUIDs::ModelUUID_Mechanical_Density)); // Density + EXPECT_TRUE(steel->hasPhysicalModel(Materials::ModelUUIDs::ModelUUID_Mechanical_IsotropicLinearElastic)); // IsotropicLinearElastic + EXPECT_TRUE(steel->hasPhysicalModel(Materials::ModelUUIDs::ModelUUID_Thermal_Default)); // Thermal + EXPECT_FALSE(steel->hasPhysicalModel(Materials::ModelUUIDs::ModelUUID_Mechanical_LinearElastic)); // Legacy linear elastic - Not in the model + EXPECT_TRUE(steel->hasAppearanceModel(Materials::ModelUUIDs::ModelUUID_Rendering_Basic)); // BasicRendering - inherited from Steel.FCMat + + EXPECT_TRUE(steel->isPhysicalModelComplete(Materials::ModelUUIDs::ModelUUID_Mechanical_Density)); // Density + EXPECT_FALSE(steel->isPhysicalModelComplete(Materials::ModelUUIDs::ModelUUID_Mechanical_IsotropicLinearElastic)); // IsotropicLinearElastic - incomplete + EXPECT_TRUE(steel->isPhysicalModelComplete(Materials::ModelUUIDs::ModelUUID_Thermal_Default)); // Thermal + EXPECT_FALSE(steel->isPhysicalModelComplete(Materials::ModelUUIDs::ModelUUID_Mechanical_LinearElastic)); // Legacy linear elastic - Not in the model + EXPECT_TRUE(steel->isAppearanceModelComplete(Materials::ModelUUIDs::ModelUUID_Rendering_Basic)); // BasicRendering - inherited from Steel.FCMat + + EXPECT_TRUE(steel->hasPhysicalProperty(QString::fromStdString("Density"))); + EXPECT_TRUE(steel->hasPhysicalProperty(QString::fromStdString("BulkModulus"))); + EXPECT_TRUE(steel->hasPhysicalProperty(QString::fromStdString("PoissonRatio"))); + EXPECT_TRUE(steel->hasPhysicalProperty(QString::fromStdString("YoungsModulus"))); + EXPECT_TRUE(steel->hasPhysicalProperty(QString::fromStdString("ShearModulus"))); + EXPECT_TRUE(steel->hasPhysicalProperty(QString::fromStdString("SpecificHeat"))); + EXPECT_TRUE(steel->hasPhysicalProperty(QString::fromStdString("ThermalConductivity"))); + EXPECT_TRUE(steel->hasPhysicalProperty(QString::fromStdString("ThermalExpansionCoefficient"))); + EXPECT_TRUE(steel->hasAppearanceProperty(QString::fromStdString("AmbientColor"))); + EXPECT_TRUE(steel->hasAppearanceProperty(QString::fromStdString("DiffuseColor"))); + EXPECT_TRUE(steel->hasAppearanceProperty(QString::fromStdString("EmissiveColor"))); + EXPECT_TRUE(steel->hasAppearanceProperty(QString::fromStdString("Shininess"))); + EXPECT_TRUE(steel->hasAppearanceProperty(QString::fromStdString("SpecularColor"))); + EXPECT_TRUE(steel->hasAppearanceProperty(QString::fromStdString("Transparency"))); + + auto& properties = steel->getPhysicalProperties(); + EXPECT_NO_THROW(properties.at(QString::fromStdString("Density"))); + EXPECT_NO_THROW(properties.at(QString::fromStdString("BulkModulus"))); // This is different from the Python behaviour + EXPECT_NO_THROW(properties.at(QString::fromStdString("PoissonRatio"))); + EXPECT_NO_THROW(properties.at(QString::fromStdString("YoungsModulus"))); + EXPECT_NO_THROW(properties.at(QString::fromStdString("ShearModulus"))); + EXPECT_NO_THROW(properties.at(QString::fromStdString("SpecificHeat"))); + EXPECT_NO_THROW(properties.at(QString::fromStdString("ThermalConductivity"))); + EXPECT_NO_THROW(properties.at(QString::fromStdString("ThermalExpansionCoefficient"))); + EXPECT_THROW(properties.at(QString::fromStdString("AmbientColor")), std::out_of_range); + EXPECT_THROW(properties.at(QString::fromStdString("DiffuseColor")), std::out_of_range); + EXPECT_THROW(properties.at(QString::fromStdString("EmissiveColor")), std::out_of_range); + EXPECT_THROW(properties.at(QString::fromStdString("Shininess")), std::out_of_range); + EXPECT_THROW(properties.at(QString::fromStdString("SpecularColor")), std::out_of_range); + EXPECT_THROW(properties.at(QString::fromStdString("Transparency")), std::out_of_range); + + auto& properties1 = steel->getAppearanceProperties(); + EXPECT_THROW(properties1.at(QString::fromStdString("Density")), std::out_of_range); + EXPECT_THROW(properties1.at(QString::fromStdString("BulkModulus")), std::out_of_range); + EXPECT_THROW(properties1.at(QString::fromStdString("PoissonRatio")), std::out_of_range); + EXPECT_THROW(properties1.at(QString::fromStdString("YoungsModulus")), std::out_of_range); + EXPECT_THROW(properties1.at(QString::fromStdString("ShearModulus")), std::out_of_range); + EXPECT_THROW(properties1.at(QString::fromStdString("SpecificHeat")), std::out_of_range); + EXPECT_THROW(properties1.at(QString::fromStdString("ThermalConductivity")), std::out_of_range); + EXPECT_THROW(properties1.at(QString::fromStdString("ThermalExpansionCoefficient")), std::out_of_range); + EXPECT_NO_THROW(properties1.at(QString::fromStdString("AmbientColor"))); + EXPECT_NO_THROW(properties1.at(QString::fromStdString("DiffuseColor"))); + EXPECT_NO_THROW(properties1.at(QString::fromStdString("EmissiveColor"))); + EXPECT_NO_THROW(properties1.at(QString::fromStdString("Shininess"))); + EXPECT_NO_THROW(properties1.at(QString::fromStdString("SpecularColor"))); + EXPECT_NO_THROW(properties1.at(QString::fromStdString("Transparency"))); + + EXPECT_FALSE(properties[QString::fromStdString("Density")]->isNull()); + EXPECT_TRUE(properties[QString::fromStdString("BulkModulus")]->isNull()); + EXPECT_FALSE(properties[QString::fromStdString("PoissonRatio")]->isNull()); + EXPECT_FALSE(properties[QString::fromStdString("YoungsModulus")]->isNull()); + EXPECT_TRUE(properties[QString::fromStdString("ShearModulus")]->isNull()); + EXPECT_FALSE(properties[QString::fromStdString("SpecificHeat")]->isNull()); + EXPECT_FALSE(properties[QString::fromStdString("ThermalConductivity")]->isNull()); + EXPECT_FALSE(properties[QString::fromStdString("ThermalExpansionCoefficient")]->isNull()); + EXPECT_FALSE(properties1[QString::fromStdString("AmbientColor")]->isNull()); + EXPECT_FALSE(properties1[QString::fromStdString("DiffuseColor")]->isNull()); + EXPECT_FALSE(properties1[QString::fromStdString("EmissiveColor")]->isNull()); + EXPECT_FALSE(properties1[QString::fromStdString("Shininess")]->isNull()); + EXPECT_FALSE(properties1[QString::fromStdString("SpecularColor")]->isNull()); + EXPECT_FALSE(properties1[QString::fromStdString("Transparency")]->isNull()); + + EXPECT_EQ(properties[QString::fromStdString("Density")]->getString(), parseQuantity("7900.00 kg/m^3")); + EXPECT_EQ(properties[QString::fromStdString("PoissonRatio")]->getString(), QString::fromStdString("0.3")); + EXPECT_EQ(properties[QString::fromStdString("YoungsModulus")]->getString(), parseQuantity("210.00 GPa")); + EXPECT_EQ(properties[QString::fromStdString("SpecificHeat")]->getString(), parseQuantity("590.00 J/kg/K")); + EXPECT_EQ(properties[QString::fromStdString("ThermalConductivity")]->getString(), parseQuantity("43.00 W/m/K")); + EXPECT_EQ(properties[QString::fromStdString("ThermalExpansionCoefficient")]->getString(), parseQuantity("12.00 µm/m/K")); + EXPECT_EQ(properties1[QString::fromStdString("AmbientColor")]->getString(), QString::fromStdString("(0.0020, 0.0020, 0.0020, 1.0)")); + EXPECT_EQ(properties1[QString::fromStdString("DiffuseColor")]->getString(), QString::fromStdString("(0.0000, 0.0000, 0.0000, 1.0)")); + EXPECT_EQ(properties1[QString::fromStdString("EmissiveColor")]->getString(), QString::fromStdString("(0.0000, 0.0000, 0.0000, 1.0)")); + EXPECT_EQ(properties1[QString::fromStdString("Shininess")]->getString(), QString::fromStdString("0.06")); + EXPECT_EQ(properties1[QString::fromStdString("SpecularColor")]->getString(), QString::fromStdString("(0.9800, 0.9800, 0.9800, 1.0)")); + EXPECT_EQ(properties1[QString::fromStdString("Transparency")]->getString(), QString::fromStdString("0")); + + EXPECT_TRUE(properties[QString::fromStdString("BulkModulus")]->getString().isEmpty()); + EXPECT_TRUE(properties[QString::fromStdString("ShearModulus")]->getString().isEmpty()); + + // These are the preferred method of access + // + EXPECT_FLOAT_EQ(steel->getPhysicalQuantity(QString::fromStdString("Density")).getValue(), 7.9e-06); + EXPECT_FLOAT_EQ(steel->getPhysicalValue(QString::fromStdString("PoissonRatio")).toDouble(), 0.3); + EXPECT_FLOAT_EQ(steel->getPhysicalQuantity(QString::fromStdString("YoungsModulus")).getValue(), 210000000.0); + EXPECT_FLOAT_EQ(steel->getPhysicalQuantity(QString::fromStdString("SpecificHeat")).getValue(), 590000000.0); + EXPECT_FLOAT_EQ(steel->getPhysicalQuantity(QString::fromStdString("ThermalConductivity")).getValue(), 43000.0); + EXPECT_FLOAT_EQ(steel->getPhysicalQuantity(QString::fromStdString("ThermalExpansionCoefficient")).getValue(), 1.2e-05); + EXPECT_EQ(steel->getAppearanceValue(QString::fromStdString("AmbientColor")), QString::fromStdString("(0.0020, 0.0020, 0.0020, 1.0)")); + EXPECT_EQ(steel->getAppearanceValue(QString::fromStdString("DiffuseColor")), QString::fromStdString("(0.0000, 0.0000, 0.0000, 1.0)")); + EXPECT_EQ(steel->getAppearanceValue(QString::fromStdString("EmissiveColor")), QString::fromStdString("(0.0000, 0.0000, 0.0000, 1.0)")); + EXPECT_FLOAT_EQ(steel->getAppearanceValue(QString::fromStdString("Shininess")).toDouble(), 0.06); + EXPECT_EQ(steel->getAppearanceValue(QString::fromStdString("SpecularColor")), QString::fromStdString("(0.9800, 0.9800, 0.9800, 1.0)")); + EXPECT_FLOAT_EQ(steel->getAppearanceValue(QString::fromStdString("Transparency")).toDouble(), 0.0); + + EXPECT_EQ(steel->getPhysicalQuantity(QString::fromStdString("Density")).getUserString(), parseQuantity("7900.00 kg/m^3")); + EXPECT_EQ(steel->getPhysicalQuantity(QString::fromStdString("YoungsModulus")).getUserString(), parseQuantity("210.00 GPa")); + EXPECT_EQ(steel->getPhysicalQuantity(QString::fromStdString("SpecificHeat")).getUserString(), parseQuantity("590.00 J/kg/K")); + EXPECT_EQ(steel->getPhysicalQuantity(QString::fromStdString("ThermalConductivity")).getUserString(), parseQuantity("43.00 W/m/K")); + EXPECT_EQ(steel->getPhysicalQuantity(QString::fromStdString("ThermalExpansionCoefficient")).getUserString(), parseQuantity("12.00 µm/m/K")); + +} + +// clang-format on diff --git a/tests/src/Mod/Material/App/TestModel.cpp b/tests/src/Mod/Material/App/TestModel.cpp new file mode 100644 index 0000000000..c3f6e1b127 --- /dev/null +++ b/tests/src/Mod/Material/App/TestModel.cpp @@ -0,0 +1,140 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later +/*************************************************************************** + * Copyright (c) 2023 David Carter * + * * + * This file is part of FreeCAD. * + * * + * FreeCAD is free software: you can redistribute it and/or modify it * + * under the terms of the GNU Lesser General Public License as * + * published by the Free Software Foundation, either version 2.1 of the * + * License, or (at your option) any later version. * + * * + * FreeCAD is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with FreeCAD. If not, see * + * . * + * * + **************************************************************************/ + +#include "gtest/gtest.h" + +#include +#ifndef _PreComp_ +#endif + +#include + +#include + +#include +#include +#include + +// clang-format off + +class TestModel : public ::testing::Test { + protected: + static void SetUpTestSuite() { + if (App::Application::GetARGC() == 0) { + constexpr int argc = 1; + std::array argv {"FreeCAD"}; + App::Application::Config()["ExeName"] = "FreeCAD"; + App::Application::init(argc, argv.data()); + } + } + + void SetUp() override { + _modelManager = new Materials::ModelManager(); + } + + // void TearDown() override {} + Materials::ModelManager* _modelManager; +}; + +TEST_F(TestModel, TestApplication) +{ + ASSERT_NO_THROW(App::GetApplication()); +} + +TEST_F(TestModel, TestResources) +{ + try { + auto param = App::GetApplication().GetParameterGroupByPath( + "User parameter:BaseApp/Preferences/Mod/Material/Resources"); + EXPECT_NE(param, nullptr); + } + catch (const std::exception &e) + { + FAIL() << "Exception: " << e.what() << "\n"; + } +} + +TEST_F(TestModel, TestInstallation) +{ + EXPECT_NE(_modelManager, nullptr); + + // We should have loaded at least the system library + auto libraries = _modelManager->getModelLibraries(); + ASSERT_GT(libraries->size(), 0); + + // We should have at least one model + auto models = _modelManager->getModels(); + ASSERT_GT(models->size(), 0); +} + +TEST_F(TestModel, TestModelLoad) +{ + EXPECT_NE(_modelManager, nullptr); + + auto density = _modelManager->getModel(QString::fromStdString("454661e5-265b-4320-8e6f-fcf6223ac3af")); + EXPECT_EQ(density->getName(), QString::fromStdString("Density")); + EXPECT_EQ(density->getUUID(), QString::fromStdString("454661e5-265b-4320-8e6f-fcf6223ac3af")); + + auto& prop = (*density)[QString::fromStdString("Density")]; + EXPECT_EQ(prop.getName(), QString::fromStdString("Density")); +} + +TEST_F(TestModel, TestModelByPath) +{ + auto linearElastic = _modelManager->getModelByPath( + QString::fromStdString("Mechanical/LinearElastic.yml"), + QString::fromStdString("System")); + EXPECT_NE(&linearElastic, nullptr); + EXPECT_EQ(linearElastic->getName(), QString::fromStdString("Linear Elastic")); + EXPECT_EQ(linearElastic->getUUID(), QString::fromStdString("7b561d1d-fb9b-44f6-9da9-56a4f74d7536")); + + // The same but with a leading '/' + auto linearElastic2 = _modelManager->getModelByPath( + QString::fromStdString("/Mechanical/LinearElastic.yml"), + QString::fromStdString("System")); + EXPECT_NE(&linearElastic2, nullptr); + EXPECT_EQ(linearElastic2->getName(), QString::fromStdString("Linear Elastic")); + EXPECT_EQ(linearElastic2->getUUID(), QString::fromStdString("7b561d1d-fb9b-44f6-9da9-56a4f74d7536")); + + // Same with the library name as a prefix + auto linearElastic3 = _modelManager->getModelByPath( + QString::fromStdString("/System/Mechanical/LinearElastic.yml"), + QString::fromStdString("System")); + EXPECT_NE(&linearElastic3, nullptr); + EXPECT_EQ(linearElastic3->getName(), QString::fromStdString("Linear Elastic")); + EXPECT_EQ(linearElastic3->getUUID(), QString::fromStdString("7b561d1d-fb9b-44f6-9da9-56a4f74d7536")); + + // Test with the file system path + ASSERT_NO_THROW(linearElastic->getLibrary()); + ASSERT_NO_THROW(linearElastic->getLibrary()->getName()); + ASSERT_NO_THROW(linearElastic->getLibrary()->getDirectoryPath()); + EXPECT_EQ(linearElastic->getLibrary()->getName(), QString::fromStdString("System")); + QString path = linearElastic->getLibrary()->getDirectoryPath() + QString::fromStdString("/Mechanical/LinearElastic.yml"); + + ASSERT_NO_THROW(_modelManager->getModelByPath(path)); + auto linearElastic4 = _modelManager->getModelByPath(path); + EXPECT_NE(&linearElastic4, nullptr); + EXPECT_EQ(linearElastic4->getName(), QString::fromStdString("Linear Elastic")); + EXPECT_EQ(linearElastic4->getUUID(), QString::fromStdString("7b561d1d-fb9b-44f6-9da9-56a4f74d7536")); +} + +// clang-format on diff --git a/tests/src/Mod/Material/App/TestModelProperties.cpp b/tests/src/Mod/Material/App/TestModelProperties.cpp new file mode 100644 index 0000000000..06d21c689e --- /dev/null +++ b/tests/src/Mod/Material/App/TestModelProperties.cpp @@ -0,0 +1,144 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later +/*************************************************************************** + * Copyright (c) 2023 David Carter * + * * + * This file is part of FreeCAD. * + * * + * FreeCAD is free software: you can redistribute it and/or modify it * + * under the terms of the GNU Lesser General Public License as * + * published by the Free Software Foundation, either version 2.1 of the * + * License, or (at your option) any later version. * + * * + * FreeCAD is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with FreeCAD. If not, see * + * . * + * * + **************************************************************************/ + +#include "gtest/gtest.h" + +#include +#ifndef _PreComp_ +#endif + +#include +#include + +#include +#include + +#include +#include +#include +#include + +// clang-format off + +class TestModelProperties : public ::testing::Test { + protected: + static void SetUpTestSuite() { + // if (App::Application::GetARGC() == 0) { + // constexpr int argc = 1; + // std::array argv {"FreeCAD"}; + // App::Application::Config()["ExeName"] = "FreeCAD"; + // App::Application::init(argc, argv.data()); + // } + } + +// void SetUp() override { +// _modelManager = new Materials::ModelManager(); +// _materialManager = new Materials::MaterialManager(); +// } + + // void TearDown() override {} +// Materials::ModelManager* _modelManager; +// Materials::MaterialManager* _materialManager; +}; + +TEST_F(TestModelProperties, TestEmpty) +{ + auto prop = Materials::ModelProperty(); + EXPECT_TRUE(prop.getName().isNull()); + EXPECT_TRUE(prop.getPropertyType().isNull()); + EXPECT_TRUE(prop.getUnits().isNull()); + EXPECT_TRUE(prop.getURL().isNull()); + EXPECT_TRUE(prop.getDescription().isNull()); + EXPECT_TRUE(prop.getInheritance().isNull()); + EXPECT_FALSE(prop.isInherited()); + EXPECT_EQ(prop.columns(), 0); +} + +TEST_F(TestModelProperties, TestBasic) +{ + auto prop = Materials::ModelProperty(QString::fromStdString("1"), + QString::fromStdString("2"), + QString::fromStdString("3"), + QString::fromStdString("4"), + QString::fromStdString("5")); + EXPECT_EQ(prop.getName(), QString::fromStdString("1")); + EXPECT_EQ(prop.getPropertyType(), QString::fromStdString("2")); + EXPECT_EQ(prop.getUnits(), QString::fromStdString("3")); + EXPECT_EQ(prop.getURL(), QString::fromStdString("4")); + EXPECT_EQ(prop.getDescription(), QString::fromStdString("5")); + EXPECT_TRUE(prop.getInheritance().isNull()); + EXPECT_FALSE(prop.isInherited()); + EXPECT_EQ(prop.columns(), 0); + + prop.setInheritance(QString::fromStdString("12345")); + EXPECT_EQ(prop.getInheritance(), QString::fromStdString("12345")); + EXPECT_TRUE(prop.isInherited()); +} + +TEST_F(TestModelProperties, TestAddColumns) +{ + auto prop = Materials::ModelProperty(QString::fromStdString("1"), + QString::fromStdString("2"), + QString::fromStdString("3"), + QString::fromStdString("4"), + QString::fromStdString("5")); + auto prop1 = Materials::ModelProperty(QString::fromStdString("10"), + QString::fromStdString("9"), + QString::fromStdString("8"), + QString::fromStdString("7"), + QString::fromStdString("6")); + auto prop2 = Materials::ModelProperty(QString::fromStdString("a"), + QString::fromStdString("b"), + QString::fromStdString("c"), + QString::fromStdString("d"), + QString::fromStdString("e")); + + EXPECT_EQ(prop.columns(), 0); + prop.addColumn(prop1); + EXPECT_EQ(prop.columns(), 1); + prop.addColumn(prop2); + EXPECT_EQ(prop.columns(), 2); + + auto columns = prop.getColumns(); + auto entry1 = columns.at(0); + EXPECT_EQ(entry1.getName(), QString::fromStdString("10")); + EXPECT_EQ(entry1.getPropertyType(), QString::fromStdString("9")); + EXPECT_EQ(entry1.getUnits(), QString::fromStdString("8")); + EXPECT_EQ(entry1.getURL(), QString::fromStdString("7")); + EXPECT_EQ(entry1.getDescription(), QString::fromStdString("6")); + EXPECT_TRUE(entry1.getInheritance().isNull()); + EXPECT_FALSE(entry1.isInherited()); + EXPECT_EQ(entry1.columns(), 0); + + auto entry2 = columns.at(1); + EXPECT_EQ(entry2.getName(), QString::fromStdString("a")); + EXPECT_EQ(entry2.getPropertyType(), QString::fromStdString("b")); + EXPECT_EQ(entry2.getUnits(), QString::fromStdString("c")); + EXPECT_EQ(entry2.getURL(), QString::fromStdString("d")); + EXPECT_EQ(entry2.getDescription(), QString::fromStdString("e")); + EXPECT_TRUE(entry2.getInheritance().isNull()); + EXPECT_FALSE(entry2.isInherited()); + EXPECT_EQ(entry2.columns(), 0); + +} + +// clang-format on diff --git a/tests/src/Mod/Sketcher/App/SketchObject.cpp b/tests/src/Mod/Sketcher/App/SketchObject.cpp index 46e6c0cd7a..7b4e5ecfbb 100644 --- a/tests/src/Mod/Sketcher/App/SketchObject.cpp +++ b/tests/src/Mod/Sketcher/App/SketchObject.cpp @@ -10,18 +10,14 @@ #include #include #include +#include class SketchObjectTest: public ::testing::Test { protected: static void SetUpTestSuite() { - if (App::Application::GetARGC() == 0) { - int argc = 1; - char* argv[] = {"FreeCAD"}; - App::Application::Config()["ExeName"] = "FreeCAD"; - App::Application::init(argc, argv); - } + tests::initApplication(); } void SetUp() override From caff3e0eb1f0f96734df49a4701e97097759362f Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 23 Oct 2023 19:21:52 +0000 Subject: [PATCH 2/6] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/Mod/Fem/Gui/AppFemGui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Mod/Fem/Gui/AppFemGui.cpp b/src/Mod/Fem/Gui/AppFemGui.cpp index a6e8b665cd..c4f36d46a2 100644 --- a/src/Mod/Fem/Gui/AppFemGui.cpp +++ b/src/Mod/Fem/Gui/AppFemGui.cpp @@ -187,4 +187,4 @@ PyMOD_INIT_FUNC(FemGui) // clang-format on PyMOD_Return(mod); -} \ No newline at end of file +} From af83682e9b619c0aba45e69807884d20c0a1af47 Mon Sep 17 00:00:00 2001 From: David Carter Date: Mon, 23 Oct 2023 15:19:20 -0400 Subject: [PATCH 3/6] Material: Material editor enhancements Continues the work of the material subsystem improvements. This merge covers the continued development of the material editor. The primary improvements are in the handling of 2D and 3D array properties. These properties are now fully editable, and can be saved and restored. The cards now separate the author and license. These were previously saved as a single item. Future support will be provided for standard open source licenses. Saving operations validate the cards to ensure UUIDs of materials are considered. Warnings are given when a save could potentially impact the models, such as saving over a material instead of creating a new instance. The editor is still not complete. There are a number of functional elements, such as drag/drop operations, folder creation, and deletion operations that need to be added to the main tree. State needs to be saved and restored to improve the user experience. The appearance preview also needs significant work. This will be handled in a future PR. --- src/Mod/Fem/Gui/AppFemGui.cpp | 2 +- src/Mod/Fem/Gui/CMakeLists.txt | 6 + src/Mod/Material/App/AppMaterial.cpp | 2 + src/Mod/Material/App/Array2DPy.xml | 36 + src/Mod/Material/App/Array2DPyImpl.cpp | 85 ++ src/Mod/Material/App/CMakeLists.txt | 7 + src/Mod/Material/App/Exceptions.h | 106 +++ src/Mod/Material/App/FolderTree.h | 16 +- src/Mod/Material/App/MaterialConfigLoader.cpp | 62 +- src/Mod/Material/App/MaterialConfigLoader.h | 31 +- src/Mod/Material/App/MaterialLibrary.cpp | 286 ++++++- src/Mod/Material/App/MaterialLibrary.h | 67 +- src/Mod/Material/App/MaterialLoader.cpp | 313 ++++++-- src/Mod/Material/App/MaterialLoader.h | 62 +- src/Mod/Material/App/MaterialManager.cpp | 208 +++-- src/Mod/Material/App/MaterialManager.h | 73 +- .../Material/App/MaterialManagerPyImpl.cpp | 26 +- src/Mod/Material/App/MaterialPy.xml | 14 +- src/Mod/Material/App/MaterialPyImpl.cpp | 78 +- src/Mod/Material/App/MaterialValue.cpp | 564 ++++++++++++-- src/Mod/Material/App/MaterialValue.h | 177 +++-- src/Mod/Material/App/Materials.cpp | 729 +++++++++++++++--- src/Mod/Material/App/Materials.h | 183 +++-- src/Mod/Material/App/Model.cpp | 22 +- src/Mod/Material/App/Model.h | 81 +- src/Mod/Material/App/ModelLibrary.cpp | 83 +- src/Mod/Material/App/ModelLibrary.h | 43 +- src/Mod/Material/App/ModelLoader.cpp | 78 +- src/Mod/Material/App/ModelLoader.h | 45 +- src/Mod/Material/App/ModelManager.cpp | 107 ++- src/Mod/Material/App/ModelManager.h | 43 +- src/Mod/Material/App/ModelManagerPyImpl.cpp | 27 +- src/Mod/Material/App/ModelPropertyPyImpl.cpp | 4 - src/Mod/Material/App/ModelPyImpl.cpp | 26 +- src/Mod/Material/App/ModelUuids.cpp | 70 ++ src/Mod/Material/App/ModelUuids.h | 64 +- src/Mod/Material/App/PreCompiled.h | 4 - src/Mod/Material/App/UUIDsPy.xml | 116 +++ src/Mod/Material/App/UUIDsPyImpl.cpp | 139 ++++ src/Mod/Material/App/trim.h | 1 - src/Mod/Material/CMakeLists.txt | 23 +- src/Mod/Material/Gui/AppMatGui.cpp | 3 + src/Mod/Material/Gui/Array2D.cpp | 121 ++- src/Mod/Material/Gui/Array2D.h | 28 +- src/Mod/Material/Gui/Array3D.cpp | 259 ++++++- src/Mod/Material/Gui/Array3D.h | 32 +- src/Mod/Material/Gui/ArrayDelegate.cpp | 4 +- src/Mod/Material/Gui/ArrayDelegate.h | 11 +- src/Mod/Material/Gui/ArrayModel.cpp | 150 +++- src/Mod/Material/Gui/ArrayModel.h | 33 +- src/Mod/Material/Gui/DlgSettingsMaterial.h | 2 +- src/Mod/Material/Gui/MaterialDelegate.cpp | 16 +- src/Mod/Material/Gui/MaterialDelegate.h | 8 +- src/Mod/Material/Gui/MaterialSave.cpp | 394 +++++++++- src/Mod/Material/Gui/MaterialSave.h | 39 +- src/Mod/Material/Gui/MaterialSave.ui | 24 + src/Mod/Material/Gui/MaterialsEditor.cpp | 439 +++++++++-- src/Mod/Material/Gui/MaterialsEditor.h | 44 +- src/Mod/Material/Gui/MaterialsEditor.ui | 122 +-- src/Mod/Material/Gui/ModelSelect.cpp | 79 +- src/Mod/Material/Gui/ModelSelect.h | 24 +- src/Mod/Material/Gui/PreCompiled.h | 4 - src/Mod/Material/Gui/Workbench.cpp | 40 + src/Mod/Material/Gui/Workbench.h | 5 + .../Materials/Appearance/Aluminum.FCMat | 3 +- .../Materials/Appearance/Brass.FCMat | 3 +- .../Materials/Appearance/Bronze.FCMat | 3 +- .../Materials/Appearance/Chrome.FCMat | 3 +- .../Materials/Appearance/Copper.FCMat | 3 +- .../Appearance/DefaultAppearance.FCMat | 3 +- .../Materials/Appearance/Emerald.FCMat | 3 +- .../Resources/Materials/Appearance/Gold.FCMat | 3 +- .../Resources/Materials/Appearance/Jade.FCMat | 3 +- .../Materials/Appearance/Metalized.FCMat | 3 +- .../Materials/Appearance/NeonGNC.FCMat | 3 +- .../Materials/Appearance/NeonPHC.FCMat | 3 +- .../Materials/Appearance/Obsidian.FCMat | 3 +- .../Materials/Appearance/Pewter.FCMat | 3 +- .../Materials/Appearance/Plaster.FCMat | 3 +- .../Materials/Appearance/Plastic.FCMat | 3 +- .../Resources/Materials/Appearance/Ruby.FCMat | 3 +- .../Materials/Appearance/Satin.FCMat | 3 +- .../Materials/Appearance/ShinyPlastic.FCMat | 3 +- .../Materials/Appearance/Silver.FCMat | 3 +- .../Materials/Appearance/Steel.FCMat | 3 +- .../Materials/Appearance/Stone.FCMat | 3 +- .../Materials/FluidMaterial/Air.FCMat | 1 + .../Materials/FluidMaterial/Argon.FCMat | 1 + .../FluidMaterial/Carbon_dioxide.FCMat | 1 + .../Materials/FluidMaterial/Nitrogen.FCMat | 1 + .../Materials/FluidMaterial/None.FCMat | 1 + .../Materials/FluidMaterial/Water.FCMat | 1 + .../Aggregate/Concrete-EN-C35_45.FCMat | 3 +- .../Aggregate/Concrete-Generic.FCMat | 3 +- .../Aggregate/Reinforcement-FIB-B500.FCMat | 3 +- .../StandardMaterial/Carbon/Graphite.FCMat | 3 +- .../Glass/Glass-E-GlassFibre.FCMat | 3 +- .../Glass/Glass-Generic.FCMat | 3 +- .../Glass/Glass-S2-GlassFibre.FCMat | 3 +- .../Metal/Alloys/Invar-Generic.FCMat | 2 +- .../Metal/Aluminum/AlMg3F24.FCMat | 3 +- .../Metal/Aluminum/AlMgSi1F31.FCMat | 3 +- .../Metal/Aluminum/AlZn4-5Mg1F35.FCMat | 2 +- .../Metal/Aluminum/Aluminum-6061-T6.FCMat | 3 +- .../Metal/Aluminum/Aluminum-Generic.FCMat | 2 +- .../Metal/Copper/Copper-Generic.FCMat | 2 +- .../Metal/Iron/Iron-Generic.FCMat | 2 +- .../Metal/Steel/CalculiX-Steel.FCMat | 3 +- .../Metal/Steel/Steel-15CrNi6.FCMat | 3 +- .../Metal/Steel/Steel-17CrNiMo6.FCMat | 3 +- .../Metal/Steel/Steel-1C22.FCMat | 3 +- .../Metal/Steel/Steel-1C35.FCMat | 3 +- .../Metal/Steel/Steel-1C45.FCMat | 3 +- .../Metal/Steel/Steel-1C60.FCMat | 3 +- .../Metal/Steel/Steel-20NiCrMo2.FCMat | 3 +- .../Metal/Steel/Steel-28Mn6.FCMat | 3 +- .../Metal/Steel/Steel-2C10.FCMat | 3 +- .../Metal/Steel/Steel-30CrNiMo8.FCMat | 3 +- .../Metal/Steel/Steel-34CrNiMo6.FCMat | 3 +- .../Metal/Steel/Steel-36CrNiMo4.FCMat | 3 +- .../Metal/Steel/Steel-36NiCrMo16.FCMat | 3 +- .../Metal/Steel/Steel-3C15.FCMat | 3 +- .../Metal/Steel/Steel-3C22.FCMat | 3 +- .../Metal/Steel/Steel-3C35.FCMat | 3 +- .../Metal/Steel/Steel-3V45.FCMat | 3 +- .../Metal/Steel/Steel-C10.FCMat | 3 +- .../Metal/Steel/Steel-C15.FCMat | 3 +- .../Metal/Steel/Steel-C22E.FCMat | 3 +- .../Metal/Steel/Steel-C25E.FCMat | 3 +- .../Metal/Steel/Steel-C30E.FCMat | 3 +- .../Metal/Steel/Steel-C40E.FCMat | 3 +- .../Metal/Steel/Steel-C50E.FCMat | 3 +- .../Metal/Steel/Steel-C55E.FCMat | 3 +- .../Metal/Steel/Steel-C60E.FCMat | 3 +- .../Metal/Steel/Steel-E295-GC.FCMat | 3 +- .../Metal/Steel/Steel-E295.FCMat | 3 +- .../Metal/Steel/Steel-E335-GC.FCMat | 3 +- .../Metal/Steel/Steel-E335.FCMat | 3 +- .../Metal/Steel/Steel-E360-GC.FCMat | 3 +- .../Metal/Steel/Steel-E360.FCMat | 3 +- .../Metal/Steel/Steel-EN-GJL-100.FCMat | 3 +- .../Metal/Steel/Steel-EN-GJL-150.FCMat | 3 +- .../Metal/Steel/Steel-EN-GJL-200.FCMat | 3 +- .../Metal/Steel/Steel-EN-GJL-250.FCMat | 3 +- .../Metal/Steel/Steel-EN-GJL-300.FCMat | 3 +- .../Metal/Steel/Steel-EN-GJL-350.FCMat | 3 +- .../Metal/Steel/Steel-EN-GJMB-350-10.FCMat | 3 +- .../Metal/Steel/Steel-EN-GJMB-550-4.FCMat | 3 +- .../Metal/Steel/Steel-EN-GJMB-650-2.FCMat | 3 +- .../Metal/Steel/Steel-EN-GJMW-350-4.FCMat | 3 +- .../Metal/Steel/Steel-EN-GJMW-360-12.FCMat | 3 +- .../Metal/Steel/Steel-EN-GJMW-400-5.FCMat | 3 +- .../Metal/Steel/Steel-EN-GJMW-450-7.FCMat | 3 +- .../Metal/Steel/Steel-EN-GJS-400-15.FCMat | 3 +- .../Metal/Steel/Steel-EN-GJS-500-7.FCMat | 3 +- .../Metal/Steel/Steel-EN-GJS-600-3.FCMat | 3 +- .../Metal/Steel/Steel-EN-GJS-700-2.FCMat | 3 +- .../Metal/Steel/Steel-EN-GJS-800-1.FCMat | 3 +- .../Metal/Steel/Steel-G16Mn5.FCMat | 3 +- .../Metal/Steel/Steel-G200.FCMat | 3 +- .../Metal/Steel/Steel-G20Mn5.FCMat | 3 +- .../Metal/Steel/Steel-G230.FCMat | 3 +- .../Metal/Steel/Steel-G260.FCMat | 3 +- .../Metal/Steel/Steel-G300.FCMat | 3 +- .../Metal/Steel/Steel-G30Mn5.FCMat | 3 +- .../Metal/Steel/Steel-Generic.FCMat | 3 +- .../Metal/Steel/Steel-S185.FCMat | 3 +- .../Metal/Steel/Steel-S235JO.FCMat | 3 +- .../Metal/Steel/Steel-S235JR.FCMat | 3 +- .../Metal/Steel/Steel-S235JRG1.FCMat | 3 +- .../Metal/Steel/Steel-S260NC.FCMat | 3 +- .../Metal/Steel/Steel-S275JO.FCMat | 3 +- .../Metal/Steel/Steel-S275JR.FCMat | 3 +- .../Metal/Steel/Steel-S275N.FCMat | 3 +- .../Metal/Steel/Steel-S335JO.FCMat | 3 +- .../Metal/Steel/Steel-S335JR.FCMat | 3 +- .../Metal/Steel/Steel-S335N.FCMat | 3 +- .../Metal/Steel/Steel-S340MC.FCMat | 3 +- .../Metal/Steel/Steel-S355J2G3.FCMat | 3 +- .../Metal/Steel/Steel-S380MC.FCMat | 3 +- .../Metal/Steel/Steel-S420MC.FCMat | 3 +- .../Metal/Steel/Steel-S420N.FCMat | 3 +- .../Metal/Steel/Steel-S460MC.FCMat | 3 +- .../Metal/Steel/Steel-S460N.FCMat | 3 +- .../Metal/Steel/Steel-S500MC.FCMat | 3 +- .../Metal/Steel/Steel-S550MC.FCMat | 3 +- .../Metal/Steel/Steel-S690MC.FCMat | 3 +- .../Metal/Steel/Steel-St-37-2K.FCMat | 3 +- .../Metal/Steel/Steel-St-E-255.FCMat | 3 +- .../Metal/Steel/Steel-St-E-315.FCMat | 3 +- .../Metal/Steel/Steel-St-E-380.FCMat | 3 +- .../Metal/Steel/Steel-St-E-460.FCMat | 3 +- .../Metal/Steel/Steel-St-E-500.FCMat | 3 +- .../Metal/Steel/Steel-X2CrNiMoN17-13-3.FCMat | 3 +- .../Metal/Steel/Steel-X2CrNiN24-4.FCMat | 3 +- .../Metal/Steel/Steel-X39CrMo17-1.FCMat | 3 +- .../Metal/Steel/Steel-X3CrNiMo13-14.FCMat | 3 +- .../Metal/Steel/Steel-X5CrNi18-10.FCMat | 3 +- .../Metal/Steel/Steel-X5CrNiMo17-12-2.FCMat | 3 +- .../Metal/Steel/Steel-X6CrNiTi18-10.FCMat | 3 +- .../Metal/Titanium/Ti-6Al-4V.FCMat | 2 +- .../Thermoplast/ABS-Generic.FCMat | 3 +- .../Thermoplast/Acrylic-Glass-Generic.FCMat | 3 +- .../Thermoplast/PA6-Generic.FCMat | 3 +- .../Thermoplast/PET-Generic.FCMat | 3 +- .../Thermoplast/PLA-Generic.FCMat | 3 +- .../Thermoplast/PP-Generic.FCMat | 3 +- .../Thermoplast/PTFE-Generic.FCMat | 3 +- .../Thermoplast/PVC-Generic.FCMat | 3 +- .../StandardMaterial/Wood/Wood-Generic.FCMat | 3 +- src/Mod/Material/TestMaterialsApp.py | 219 +----- .../Material/materialtests/TestMaterials.py | 228 ++++++ src/Mod/Material/materialtests/TestModels.py | 79 ++ src/Mod/Material/materialtests/__init__.py | 0 src/Tools/updatecrowdin.py | 6 +- tests/src/Mod/Material/App/CMakeLists.txt | 6 +- .../Material/App/TestMaterialProperties.cpp | 226 ++++++ .../Mod/Material/App/TestMaterialValue.cpp | 310 ++++++++ tests/src/Mod/Material/App/TestMaterials.cpp | 339 ++++++++ tests/src/Mod/Material/App/TestModel.cpp | 140 ++++ .../Mod/Material/App/TestModelProperties.cpp | 144 ++++ 221 files changed, 6493 insertions(+), 1614 deletions(-) create mode 100644 src/Mod/Material/App/Array2DPy.xml create mode 100644 src/Mod/Material/App/Array2DPyImpl.cpp create mode 100644 src/Mod/Material/App/ModelUuids.cpp create mode 100644 src/Mod/Material/App/UUIDsPy.xml create mode 100644 src/Mod/Material/App/UUIDsPyImpl.cpp create mode 100644 src/Mod/Material/materialtests/TestMaterials.py create mode 100644 src/Mod/Material/materialtests/TestModels.py create mode 100644 src/Mod/Material/materialtests/__init__.py create mode 100644 tests/src/Mod/Material/App/TestMaterialProperties.cpp create mode 100644 tests/src/Mod/Material/App/TestMaterialValue.cpp create mode 100644 tests/src/Mod/Material/App/TestMaterials.cpp create mode 100644 tests/src/Mod/Material/App/TestModel.cpp create mode 100644 tests/src/Mod/Material/App/TestModelProperties.cpp diff --git a/src/Mod/Fem/Gui/AppFemGui.cpp b/src/Mod/Fem/Gui/AppFemGui.cpp index c4f36d46a2..a6e8b665cd 100644 --- a/src/Mod/Fem/Gui/AppFemGui.cpp +++ b/src/Mod/Fem/Gui/AppFemGui.cpp @@ -187,4 +187,4 @@ PyMOD_INIT_FUNC(FemGui) // clang-format on PyMOD_Return(mod); -} +} \ No newline at end of file diff --git a/src/Mod/Fem/Gui/CMakeLists.txt b/src/Mod/Fem/Gui/CMakeLists.txt index 5635bef1fc..af0fb7fcd6 100755 --- a/src/Mod/Fem/Gui/CMakeLists.txt +++ b/src/Mod/Fem/Gui/CMakeLists.txt @@ -9,6 +9,12 @@ elseif(CMAKE_COMPILER_IS_GNUCXX) add_compile_options(-Wno-pedantic) # needed for vtk headers endif() +if(MSVC) + add_definitions(-DFCGuiFem -DHAVE_ACOSH -DHAVE_ASINH -DHAVE_ATANH) +else(MSVC) + add_definitions(-DHAVE_LIMITS_H -DHAVE_CONFIG_H) +endif(MSVC) + if(BUILD_FEM_NETGEN) add_definitions(-DFCWithNetgen) endif(BUILD_FEM_NETGEN) diff --git a/src/Mod/Material/App/AppMaterial.cpp b/src/Mod/Material/App/AppMaterial.cpp index ced297ec95..9d2471c657 100644 --- a/src/Mod/Material/App/AppMaterial.cpp +++ b/src/Mod/Material/App/AppMaterial.cpp @@ -33,6 +33,7 @@ #include "ModelManagerPy.h" #include "ModelPropertyPy.h" #include "ModelPy.h" +#include "UUIDsPy.h" namespace Materials { @@ -68,6 +69,7 @@ PyMOD_INIT_FUNC(Material) Base::Interpreter().addType(&Materials::ModelManagerPy ::Type, module, "ModelManager"); Base::Interpreter().addType(&Materials::ModelPropertyPy ::Type, module, "ModelProperty"); Base::Interpreter().addType(&Materials::ModelPy ::Type, module, "Model"); + Base::Interpreter().addType(&Materials::UUIDsPy ::Type, module, "UUIDs"); PyMOD_Return(module); } diff --git a/src/Mod/Material/App/Array2DPy.xml b/src/Mod/Material/App/Array2DPy.xml new file mode 100644 index 0000000000..ba6f5f965f --- /dev/null +++ b/src/Mod/Material/App/Array2DPy.xml @@ -0,0 +1,36 @@ + + + + + + 2D Array of material properties. + + + + The number of rows in the array. + + + + + + The number of columns in the array. + + + + + + Get the default value for the first column of the array + + + + diff --git a/src/Mod/Material/App/Array2DPyImpl.cpp b/src/Mod/Material/App/Array2DPyImpl.cpp new file mode 100644 index 0000000000..02ef6e5465 --- /dev/null +++ b/src/Mod/Material/App/Array2DPyImpl.cpp @@ -0,0 +1,85 @@ +/*************************************************************************** + * Copyright (c) 2023 David Carter * + * * + * This file is part of FreeCAD. * + * * + * FreeCAD is free software: you can redistribute it and/or modify it * + * under the terms of the GNU Lesser General Public License as * + * published by the Free Software Foundation, either version 2.1 of the * + * License, or (at your option) any later version. * + * * + * FreeCAD is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with FreeCAD. If not, see * + * . * + * * + **************************************************************************/ + +#include "PreCompiled.h" + +#include "Array2DPy.h" +#include "Model.h" +#include "ModelLibrary.h" +#include "ModelPropertyPy.h" +#include "ModelUuids.h" + +#include "Array2DPy.cpp" + +using namespace Materials; + +// returns a string which represents the object e.g. when printed in python +std::string Array2DPy::representation() const +{ + std::stringstream str; + str << ""; + + return str.str(); +} + +PyObject* Array2DPy::PyMake(struct _typeobject*, PyObject*, PyObject*) // Python wrapper +{ + // never create such objects with the constructor + return new Array2DPy(new Material2DArray()); +} + +// constructor method +int Array2DPy::PyInit(PyObject* /*args*/, PyObject* /*kwd*/) +{ + return 0; +} + +Py::Int Array2DPy::getRows() const +{ + return Py::Int(getMaterial2DArrayPtr()->rows()); +} + +Py::Int Array2DPy::getColumns() const +{ + return Py::Int(getMaterial2DArrayPtr()->columns()); +} + +PyObject* Array2DPy::getDefaultValue(PyObject* args) +{ + char* name; + if (!PyArg_ParseTuple(args, "s", &name)) { + return nullptr; + } + + // QVariant value = getMaterial2DArrayPtr()->getPhysicalValue(QString::fromStdString(name)); + // return _pyObjectFromVariant(value); + return nullptr; +} + +PyObject* Array2DPy::getCustomAttributes(const char* /*attr*/) const +{ + return nullptr; +} + +int Array2DPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/) +{ + return 0; +} diff --git a/src/Mod/Material/App/CMakeLists.txt b/src/Mod/Material/App/CMakeLists.txt index 21258ea53a..ab2bc85745 100644 --- a/src/Mod/Material/App/CMakeLists.txt +++ b/src/Mod/Material/App/CMakeLists.txt @@ -33,14 +33,18 @@ list(APPEND Material_LIBS ${YAML_CPP_LIBRARIES} ) +generate_from_xml(Array2DPy) generate_from_xml(MaterialManagerPy) generate_from_xml(MaterialPy) generate_from_xml(ModelManagerPy) generate_from_xml(ModelPropertyPy) generate_from_xml(ModelPy) +generate_from_xml(UUIDsPy) SET(Python_SRCS Exceptions.h + Array2DPy.xml + Array2DPyImpl.cpp MaterialManagerPy.xml MaterialManagerPyImpl.cpp MaterialPy.xml @@ -51,6 +55,8 @@ SET(Python_SRCS ModelPropertyPyImpl.cpp ModelPy.xml ModelPyImpl.cpp + UUIDsPy.xml + UUIDsPyImpl.cpp ) SOURCE_GROUP("Python" FILES ${Python_SRCS}) @@ -78,6 +84,7 @@ SET(Material_SRCS ModelLoader.h ModelManager.cpp ModelManager.h + ModelUuids.cpp ModelUuids.h PreCompiled.cpp PreCompiled.h diff --git a/src/Mod/Material/App/Exceptions.h b/src/Mod/Material/App/Exceptions.h index c67e9df4eb..49152cd263 100644 --- a/src/Mod/Material/App/Exceptions.h +++ b/src/Mod/Material/App/Exceptions.h @@ -22,6 +22,8 @@ #ifndef MATERIAL_EXCEPTIONS_H #define MATERIAL_EXCEPTIONS_H +#include + #include #include @@ -37,6 +39,10 @@ public: { this->setMessage(msg); } + explicit Uninitialized(const QString& msg) + { + this->setMessage(msg.toStdString().c_str()); + } ~Uninitialized() noexcept override = default; }; @@ -49,9 +55,29 @@ public: { this->setMessage(msg); } + explicit ModelNotFound(const QString& msg) + { + this->setMessage(msg.toStdString().c_str()); + } ~ModelNotFound() noexcept override = default; }; +class InvalidMaterialType: public Base::Exception +{ +public: + InvalidMaterialType() + {} + explicit InvalidMaterialType(const char* msg) + { + this->setMessage(msg); + } + explicit InvalidMaterialType(const QString& msg) + { + this->setMessage(msg.toStdString().c_str()); + } + ~InvalidMaterialType() noexcept override = default; +}; + class MaterialNotFound: public Base::Exception { public: @@ -61,9 +87,29 @@ public: { this->setMessage(msg); } + explicit MaterialNotFound(const QString& msg) + { + this->setMessage(msg.toStdString().c_str()); + } ~MaterialNotFound() noexcept override = default; }; +class MaterialExists: public Base::Exception +{ +public: + MaterialExists() + {} + explicit MaterialExists(const char* msg) + { + this->setMessage(msg); + } + explicit MaterialExists(const QString& msg) + { + this->setMessage(msg.toStdString().c_str()); + } + ~MaterialExists() noexcept override = default; +}; + class PropertyNotFound: public Base::Exception { public: @@ -73,6 +119,10 @@ public: { this->setMessage(msg); } + explicit PropertyNotFound(const QString& msg) + { + this->setMessage(msg.toStdString().c_str()); + } ~PropertyNotFound() noexcept override = default; }; @@ -85,6 +135,10 @@ public: { this->setMessage(msg); } + explicit LibraryNotFound(const QString& msg) + { + this->setMessage(msg.toStdString().c_str()); + } ~LibraryNotFound() noexcept override = default; }; @@ -97,6 +151,10 @@ public: { this->setMessage(msg); } + explicit InvalidModel(const QString& msg) + { + this->setMessage(msg.toStdString().c_str()); + } ~InvalidModel() noexcept override = default; }; @@ -109,6 +167,10 @@ public: { this->setMessage(msg); } + explicit InvalidRow(const QString& msg) + { + this->setMessage(msg.toStdString().c_str()); + } ~InvalidRow() noexcept override = default; }; @@ -121,9 +183,29 @@ public: { this->setMessage(msg); } + explicit InvalidColumn(const QString& msg) + { + this->setMessage(msg.toStdString().c_str()); + } ~InvalidColumn() noexcept override = default; }; +class InvalidDepth: public Base::Exception +{ +public: + InvalidDepth() + {} + explicit InvalidDepth(char* msg) + { + this->setMessage(msg); + } + explicit InvalidDepth(const QString& msg) + { + this->setMessage(msg.toStdString().c_str()); + } + ~InvalidDepth() noexcept override = default; +}; + class InvalidIndex: public Base::Exception { public: @@ -133,6 +215,10 @@ public: { this->setMessage(msg); } + explicit InvalidIndex(const QString& msg) + { + this->setMessage(msg.toStdString().c_str()); + } ~InvalidIndex() noexcept override = default; }; @@ -145,9 +231,29 @@ public: { this->setMessage(msg); } + explicit UnknownValueType(const QString& msg) + { + this->setMessage(msg.toStdString().c_str()); + } ~UnknownValueType() noexcept override = default; }; +class DeleteError: public Base::Exception +{ +public: + DeleteError() + {} + explicit DeleteError(char* msg) + { + this->setMessage(msg); + } + explicit DeleteError(const QString& msg) + { + this->setMessage(msg.toStdString().c_str()); + } + ~DeleteError() noexcept override = default; +}; + } // namespace Materials #endif // MATERIAL_EXCEPTIONS_H diff --git a/src/Mod/Material/App/FolderTree.h b/src/Mod/Material/App/FolderTree.h index 2cc3133fa6..e2c450753c 100644 --- a/src/Mod/Material/App/FolderTree.h +++ b/src/Mod/Material/App/FolderTree.h @@ -22,10 +22,10 @@ #ifndef MATERIAL_FOLDERTREE_H #define MATERIAL_FOLDERTREE_H -#include #include #include +#include namespace Materials { @@ -53,25 +53,25 @@ public: _type = type; } - const std::shared_ptr*>> getFolder() const + const std::shared_ptr>>> getFolder() const { return _folder; } - std::shared_ptr*>> getFolder() + std::shared_ptr>>> getFolder() { return _folder; } - const T* getData() const + std::shared_ptr getData() const { return _data; } - void setFolder(std::shared_ptr*>> folder) + void setFolder(std::shared_ptr>>> folder) { setType(FolderNode); _folder = folder; } - void setData(const T* data) + void setData(std::shared_ptr data) { setType(DataNode); _data = data; @@ -79,8 +79,8 @@ public: private: NodeType _type; - std::shared_ptr*>> _folder; - const T* _data; + std::shared_ptr>>> _folder; + std::shared_ptr _data; }; } // namespace Materials diff --git a/src/Mod/Material/App/MaterialConfigLoader.cpp b/src/Mod/Material/App/MaterialConfigLoader.cpp index 6e5e287600..492730f2ec 100644 --- a/src/Mod/Material/App/MaterialConfigLoader.cpp +++ b/src/Mod/Material/App/MaterialConfigLoader.cpp @@ -85,7 +85,8 @@ QString MaterialConfigLoader::getAuthorAndLicense(const QString& path) return noAuthor; } -void MaterialConfigLoader::addVectorRendering(const QSettings& fcmat, Material* finalModel) +void MaterialConfigLoader::addVectorRendering(const QSettings& fcmat, + std::shared_ptr finalModel) { QString sectionFillPattern = value(fcmat, "VectorRendering/SectionFillPattern", ""); QString sectionLinewidth = value(fcmat, "VectorRendering/SectionLinewidth", ""); @@ -97,7 +98,7 @@ void MaterialConfigLoader::addVectorRendering(const QSettings& fcmat, Material* if (sectionFillPattern.length() + sectionLinewidth.length() + sectionColor.length() + viewColor.length() + viewFillPattern.length() + viewLinewidth.length() > 0) { - finalModel->addAppearance(ModelUUID_Rendering_Vector); + finalModel->addAppearance(ModelUUIDs::ModelUUID_Rendering_Vector); } // Now add the data @@ -109,7 +110,8 @@ void MaterialConfigLoader::addVectorRendering(const QSettings& fcmat, Material* setAppearanceValue(finalModel, "ViewLinewidth", viewLinewidth); } -void MaterialConfigLoader::addRendering(const QSettings& fcmat, Material* finalModel) +void MaterialConfigLoader::addRendering(const QSettings& fcmat, + std::shared_ptr finalModel) { QString ambientColor = value(fcmat, "Rendering/AmbientColor", ""); QString diffuseColor = value(fcmat, "Rendering/DiffuseColor", ""); @@ -139,13 +141,13 @@ void MaterialConfigLoader::addRendering(const QSettings& fcmat, Material* finalM } if (useAdvanced) { - finalModel->addAppearance(ModelUUID_Rendering_Advanced); + finalModel->addAppearance(ModelUUIDs::ModelUUID_Rendering_Advanced); } else if (useTexture) { - finalModel->addAppearance(ModelUUID_Rendering_Texture); + finalModel->addAppearance(ModelUUIDs::ModelUUID_Rendering_Texture); } else if (useBasic) { - finalModel->addAppearance(ModelUUID_Rendering_Basic); + finalModel->addAppearance(ModelUUIDs::ModelUUID_Rendering_Basic); } // Now add the data @@ -161,14 +163,14 @@ void MaterialConfigLoader::addRendering(const QSettings& fcmat, Material* finalM setAppearanceValue(finalModel, "VertexShader", vertexShader); } -void MaterialConfigLoader::addCosts(const QSettings& fcmat, Material* finalModel) +void MaterialConfigLoader::addCosts(const QSettings& fcmat, std::shared_ptr finalModel) { QString productURL = value(fcmat, "Cost/ProductURL", ""); QString specificPrice = value(fcmat, "Cost/SpecificPrice", ""); QString vendor = value(fcmat, "Cost/Vendor", ""); if (productURL.length() + specificPrice.length() + vendor.length() > 0) { - finalModel->addPhysical(ModelUUID_Costs_Default); + finalModel->addPhysical(ModelUUIDs::ModelUUID_Costs_Default); } // Now add the data @@ -177,7 +179,8 @@ void MaterialConfigLoader::addCosts(const QSettings& fcmat, Material* finalModel setPhysicalValue(finalModel, "Vendor", vendor); } -void MaterialConfigLoader::addArchitectural(const QSettings& fcmat, Material* finalModel) +void MaterialConfigLoader::addArchitectural(const QSettings& fcmat, + std::shared_ptr finalModel) { QString color = value(fcmat, "Architectural/Color", ""); QString environmentalEfficiencyClass = @@ -193,7 +196,7 @@ void MaterialConfigLoader::addArchitectural(const QSettings& fcmat, Material* fi + finish.length() + fireResistanceClass.length() + model.length() + soundTransmissionClass.length() + unitsPerQuantity.length() > 0) { - finalModel->addPhysical(ModelUUID_Architectural_Default); + finalModel->addPhysical(ModelUUIDs::ModelUUID_Architectural_Default); } // Now add the data @@ -207,7 +210,8 @@ void MaterialConfigLoader::addArchitectural(const QSettings& fcmat, Material* fi setPhysicalValue(finalModel, "UnitsPerQuantity", unitsPerQuantity); } -void MaterialConfigLoader::addElectromagnetic(const QSettings& fcmat, Material* finalModel) +void MaterialConfigLoader::addElectromagnetic(const QSettings& fcmat, + std::shared_ptr finalModel) { QString relativePermittivity = value(fcmat, "Electromagnetic/RelativePermittivity", ""); QString electricalConductivity = value(fcmat, "Electromagnetic/ElectricalConductivity", ""); @@ -216,7 +220,7 @@ void MaterialConfigLoader::addElectromagnetic(const QSettings& fcmat, Material* if (relativePermittivity.length() + electricalConductivity.length() + relativePermeability.length() > 0) { - finalModel->addPhysical(ModelUUID_Electromagnetic_Default); + finalModel->addPhysical(ModelUUIDs::ModelUUID_Electromagnetic_Default); } // Now add the data @@ -225,7 +229,7 @@ void MaterialConfigLoader::addElectromagnetic(const QSettings& fcmat, Material* setPhysicalValue(finalModel, "RelativePermeability", relativePermeability); } -void MaterialConfigLoader::addThermal(const QSettings& fcmat, Material* finalModel) +void MaterialConfigLoader::addThermal(const QSettings& fcmat, std::shared_ptr finalModel) { QString specificHeat = value(fcmat, "Thermal/SpecificHeat", ""); QString thermalConductivity = value(fcmat, "Thermal/ThermalConductivity", ""); @@ -233,7 +237,7 @@ void MaterialConfigLoader::addThermal(const QSettings& fcmat, Material* finalMod if (specificHeat.length() + thermalConductivity.length() + thermalExpansionCoefficient.length() > 0) { - finalModel->addPhysical(ModelUUID_Thermal_Default); + finalModel->addPhysical(ModelUUIDs::ModelUUID_Thermal_Default); } // Now add the data @@ -242,7 +246,7 @@ void MaterialConfigLoader::addThermal(const QSettings& fcmat, Material* finalMod setPhysicalValue(finalModel, "ThermalExpansionCoefficient", thermalExpansionCoefficient); } -void MaterialConfigLoader::addFluid(const QSettings& fcmat, Material* finalModel) +void MaterialConfigLoader::addFluid(const QSettings& fcmat, std::shared_ptr finalModel) { QString density = value(fcmat, "Fluidic/Density", ""); QString dynamicViscosity = value(fcmat, "Fluidic/DynamicViscosity", ""); @@ -260,10 +264,10 @@ void MaterialConfigLoader::addFluid(const QSettings& fcmat, Material* finalModel } if (useFluid) { - finalModel->addPhysical(ModelUUID_Fluid_Default); + finalModel->addPhysical(ModelUUIDs::ModelUUID_Fluid_Default); } else if (useDensity) { - finalModel->addPhysical(ModelUUID_Mechanical_Density); + finalModel->addPhysical(ModelUUIDs::ModelUUID_Mechanical_Density); } // Now add the data @@ -273,7 +277,8 @@ void MaterialConfigLoader::addFluid(const QSettings& fcmat, Material* finalModel setPhysicalValue(finalModel, "PrandtlNumber", prandtlNumber); } -void MaterialConfigLoader::addMechanical(const QSettings& fcmat, Material* finalModel) +void MaterialConfigLoader::addMechanical(const QSettings& fcmat, + std::shared_ptr finalModel) { QString density = value(fcmat, "Mechanical/Density", ""); QString bulkModulus = value(fcmat, "Mechanical/BulkModulus", ""); @@ -308,14 +313,14 @@ void MaterialConfigLoader::addMechanical(const QSettings& fcmat, Material* final } if (useLinearElastic) { - finalModel->addPhysical(ModelUUID_Mechanical_LinearElastic); + finalModel->addPhysical(ModelUUIDs::ModelUUID_Mechanical_LinearElastic); } else { if (useIso) { - finalModel->addPhysical(ModelUUID_Mechanical_IsotropicLinearElastic); + finalModel->addPhysical(ModelUUIDs::ModelUUID_Mechanical_IsotropicLinearElastic); } if (useDensity) { - finalModel->addPhysical(ModelUUID_Mechanical_Density); + finalModel->addPhysical(ModelUUIDs::ModelUUID_Mechanical_Density); } } @@ -334,10 +339,11 @@ void MaterialConfigLoader::addMechanical(const QSettings& fcmat, Material* final setPhysicalValue(finalModel, "Stiffness", stiffness); } -Material* MaterialConfigLoader::getMaterialFromPath(const MaterialLibrary& library, - const QString& path) +std::shared_ptr +MaterialConfigLoader::getMaterialFromPath(std::shared_ptr library, + const QString& path) { - QString authorAndLicense = getAuthorAndLicense(path); + QString author = getAuthorAndLicense(path); // Place them both in the author field QSettings fcmat(path, QSettings::IniFormat); @@ -352,15 +358,15 @@ Material* MaterialConfigLoader::getMaterialFromPath(const MaterialLibrary& libra QString sourceReference = value(fcmat, "ReferenceSource", ""); QString sourceURL = value(fcmat, "SourceURL", ""); - Material* finalModel = new Material(library, path, uuid, name); - finalModel->setAuthorAndLicense(authorAndLicense); + std::shared_ptr finalModel = std::make_shared(library, path, uuid, name); + finalModel->setAuthor(author); finalModel->setDescription(description); finalModel->setReference(sourceReference); finalModel->setURL(sourceURL); QString father = value(fcmat, "Father", ""); if (father.length() > 0) { - finalModel->addPhysical(ModelUUID_Legacy_Father); + finalModel->addPhysical(ModelUUIDs::ModelUUID_Legacy_Father); // Now add the data setPhysicalValue(finalModel, "Father", father); @@ -372,7 +378,7 @@ Material* MaterialConfigLoader::getMaterialFromPath(const MaterialLibrary& libra QString standardCode = value(fcmat, "StandardCode", ""); if (kindOfMaterial.length() + materialNumber.length() + norm.length() + standardCode.length() > 0) { - finalModel->addPhysical(ModelUUID_Legacy_MaterialStandard); + finalModel->addPhysical(ModelUUIDs::ModelUUID_Legacy_MaterialStandard); // Now add the data setPhysicalValue(finalModel, "KindOfMaterial", kindOfMaterial); diff --git a/src/Mod/Material/App/MaterialConfigLoader.h b/src/Mod/Material/App/MaterialConfigLoader.h index f2337cd04f..5d847d944c 100644 --- a/src/Mod/Material/App/MaterialConfigLoader.h +++ b/src/Mod/Material/App/MaterialConfigLoader.h @@ -22,6 +22,8 @@ #ifndef MATERIAL_MATERIALCONFIGLOADER_H #define MATERIAL_MATERIALCONFIGLOADER_H +#include + #include #include #include @@ -39,7 +41,8 @@ public: static bool isConfigStyle(const QString& path); - static Material* getMaterialFromPath(const MaterialLibrary& library, const QString& path); + static std::shared_ptr getMaterialFromPath(std::shared_ptr library, + const QString& path); private: static QString @@ -49,15 +52,17 @@ private: .toString(); } - static void - setPhysicalValue(Material* finalModel, const std::string& name, const QString& value) + static void setPhysicalValue(std::shared_ptr finalModel, + const std::string& name, + const QString& value) { if (value.length() > 0) { finalModel->setPhysicalValue(QString::fromStdString(name), value); } } - static void - setAppearanceValue(Material* finalModel, const std::string& name, const QString& value) + static void setAppearanceValue(std::shared_ptr finalModel, + const std::string& name, + const QString& value) { if (value.length() > 0) { finalModel->setAppearanceValue(QString::fromStdString(name), value); @@ -65,14 +70,14 @@ private: } static QString getAuthorAndLicense(const QString& path); - static void addMechanical(const QSettings& fcmat, Material* finalModel); - static void addFluid(const QSettings& fcmat, Material* finalModel); - static void addThermal(const QSettings& fcmat, Material* finalModel); - static void addElectromagnetic(const QSettings& fcmat, Material* finalModel); - static void addArchitectural(const QSettings& fcmat, Material* finalModel); - static void addCosts(const QSettings& fcmat, Material* finalModel); - static void addRendering(const QSettings& fcmat, Material* finalModel); - static void addVectorRendering(const QSettings& fcmat, Material* finalModel); + static void addMechanical(const QSettings& fcmat, std::shared_ptr finalModel); + static void addFluid(const QSettings& fcmat, std::shared_ptr finalModel); + static void addThermal(const QSettings& fcmat, std::shared_ptr finalModel); + static void addElectromagnetic(const QSettings& fcmat, std::shared_ptr finalModel); + static void addArchitectural(const QSettings& fcmat, std::shared_ptr finalModel); + static void addCosts(const QSettings& fcmat, std::shared_ptr finalModel); + static void addRendering(const QSettings& fcmat, std::shared_ptr finalModel); + static void addVectorRendering(const QSettings& fcmat, std::shared_ptr finalModel); }; } // namespace Materials diff --git a/src/Mod/Material/App/MaterialLibrary.cpp b/src/Mod/Material/App/MaterialLibrary.cpp index 3d5ee05a59..944ae9408d 100644 --- a/src/Mod/Material/App/MaterialLibrary.cpp +++ b/src/Mod/Material/App/MaterialLibrary.cpp @@ -21,11 +21,17 @@ #include "PreCompiled.h" #ifndef _PreComp_ +#include #endif +#include +#include + #include #include "MaterialLibrary.h" +#include "MaterialLoader.h" +#include "MaterialManager.h" #include "Materials.h" #include "ModelManager.h" @@ -34,9 +40,6 @@ using namespace Materials; /* TRANSLATOR Material::Materials */ -std::unique_ptr> MaterialLibrary::_materialPathMap = - std::make_unique>(); - TYPESYSTEM_SOURCE(Materials::MaterialLibrary, LibraryBase) MaterialLibrary::MaterialLibrary() @@ -48,24 +51,165 @@ MaterialLibrary::MaterialLibrary(const QString& libraryName, bool readOnly) : LibraryBase(libraryName, dir, icon) , _readOnly(readOnly) + , _materialPathMap(std::make_unique>>()) {} -void MaterialLibrary::createPath(const QString& path) -{ - Q_UNUSED(path) -} - -Material* MaterialLibrary::saveMaterial(Material& material, const QString& path, bool saveAsCopy) +void MaterialLibrary::createFolder(const QString& path) { QString filePath = getLocalPath(path); - Base::Console().Log("\tfilePath = '%s'\n", filePath.toStdString().c_str()); + // Base::Console().Log("\tfilePath = '%s'\n", filePath.toStdString().c_str()); + + QDir fileDir(filePath); + if (!fileDir.exists()) { + if (!fileDir.mkpath(filePath)) { + Base::Console().Error("Unable to create directory path '%s'\n", + filePath.toStdString().c_str()); + } + } +} + +// This accepts the filesystem path as returned from getLocalPath +void MaterialLibrary::deleteDir(MaterialManager& manager, const QString& path) +{ + // Base::Console().Log("Removing directory '%s'\n", path.toStdString().c_str()); + + // Remove the children first + QDirIterator it(path, QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot); + + // Add paths to a list so there are no iterator errors + QVector dirList; + QVector fileList; + while (it.hasNext()) { + auto pathname = it.next(); + QFileInfo file(pathname); + if (file.isFile()) { + fileList.push_back(pathname); + } + else if (file.isDir()) { + dirList.push_back(pathname); + } + } + + // Remove the subdirs first + while (!dirList.isEmpty()) { + QString dirPath = dirList.takeFirst(); + deleteDir(manager, dirPath); + } + + // Remove the files + while (!fileList.isEmpty()) { + QString filePath = fileList.takeFirst(); + deleteFile(manager, filePath); + } + + // Finally, remove ourself + QDir dir; + if (!dir.rmdir(path)) { + throw DeleteError(path); + } +} + +// This accepts the filesystem path as returned from getLocalPath +void MaterialLibrary::deleteFile(MaterialManager& manager, const QString& path) +{ + // Base::Console().Log("Removing file '%s'\n", path.toStdString().c_str()); + + if (QFile::remove(path)) { + // Remove from the map + QString rPath = getRelativePath(path); + // Base::Console().Log("\trpath '%s'\n", rPath.toStdString().c_str()); + try { + auto material = getMaterialByPath(rPath); + manager.remove(material->getUUID()); + } + catch (const MaterialNotFound&) { + Base::Console().Log("Unable to remove file from materials list\n"); + } + _materialPathMap->erase(rPath); + } + else { + QString error = QString::fromStdString("DeleteError: Unable to delete ") + path; + throw DeleteError(error); + } +} + +void MaterialLibrary::deleteRecursive(const QString& path) +{ + std::string pstring = path.toStdString(); + Base::Console().Log("\tdeleteRecursive '%s'\n", pstring.c_str()); + + if (isRoot(path)) { + return; + } + + QString filePath = getLocalPath(path); + // Base::Console().Log("\tfilePath = '%s'\n", filePath.toStdString().c_str()); + MaterialManager manager; + + QFileInfo info(filePath); + if (info.isDir()) { + deleteDir(manager, filePath); + } + else { + deleteFile(manager, filePath); + } +} + +void MaterialLibrary::updatePaths(const QString& oldPath, const QString& newPath) +{ + // Update the path map + QString op = getRelativePath(oldPath); + QString np = getRelativePath(newPath); + std::unique_ptr>> pathMap = + std::make_unique>>(); + for (auto itp = _materialPathMap->begin(); itp != _materialPathMap->end(); itp++) { + QString path = itp->first; + if (path.startsWith(op)) { + path = np + path.remove(0, op.size()); + } + Base::Console().Error("Path '%s' -> '%s'\n", + itp->first.toStdString().c_str(), + path.toStdString().c_str()); + itp->second->setDirectory(path); + (*pathMap)[path] = itp->second; + } + + _materialPathMap = std::move(pathMap); +} + +void MaterialLibrary::renameFolder(const QString& oldPath, const QString& newPath) +{ + QString filePath = getLocalPath(oldPath); + // Base::Console().Log("\tfilePath = '%s'\n", filePath.toStdString().c_str()); + QString newFilePath = getLocalPath(newPath); + // Base::Console().Log("\tnew filePath = '%s'\n", newFilePath.toStdString().c_str()); + + QDir fileDir(filePath); + if (fileDir.exists()) { + if (!fileDir.rename(filePath, newFilePath)) { + Base::Console().Error("Unable to rename directory path '%s'\n", + filePath.toStdString().c_str()); + } + } + + updatePaths(oldPath, newPath); +} + +std::shared_ptr MaterialLibrary::saveMaterial(std::shared_ptr material, + const QString& path, + bool overwrite, + bool saveAsCopy, + bool saveInherited) +{ + QString filePath = getLocalPath(path); + // Base::Console().Log("\tfilePath = '%s'\n", filePath.toStdString().c_str()); QFile file(filePath); // Update UUID if required // if name changed true - if (material.getName() != file.fileName()) { - material.newUuid(); - } + // if (material->getName() != file.fileName()) { + // material->newUuid(); + // } // if overwrite false having warned the user // if old format true, but already set @@ -79,43 +223,49 @@ Material* MaterialLibrary::saveMaterial(Material& material, const QString& path, } } + if (info.exists()) { + if (!overwrite) { + Base::Console().Error("File already exists '%s'\n", info.path().toStdString().c_str()); + throw MaterialExists(); + } + } + if (file.open(QIODevice::WriteOnly | QIODevice::Text)) { QTextStream stream(&file); -#if QT_VERSION < QT_VERSION_CHECK(6,0,0) stream.setCodec("UTF-8"); -#endif stream.setGenerateByteOrderMark(true); // Write the contents - material.setLibrary(*this); - material.setDirectory(getRelativePath(path)); - material.save(stream, saveAsCopy); + material->setLibrary(getptr()); + material->setDirectory(getRelativePath(path)); + material->save(stream, saveAsCopy, saveInherited); } return addMaterial(material, path); } -Material* MaterialLibrary::addMaterial(const Material& material, const QString& path) +bool MaterialLibrary::fileExists(const QString& path) const +{ + QString filePath = getLocalPath(path); + QFileInfo info(filePath); + + return info.exists(); +} + +std::shared_ptr MaterialLibrary::addMaterial(std::shared_ptr material, + const QString& path) { QString filePath = getRelativePath(path); - Material* newMaterial = new Material(material); - newMaterial->setLibrary(*this); + std::shared_ptr newMaterial = std::make_shared(*material); + newMaterial->setLibrary(getptr()); newMaterial->setDirectory(filePath); - try { - // If there's already a material at that path we'll replace it - Material* old = _materialPathMap->at(filePath); - delete old; - } - catch (const std::out_of_range&) { - } - (*_materialPathMap)[filePath] = newMaterial; return newMaterial; } -const Material& MaterialLibrary::getMaterialByPath(const QString& path) const +std::shared_ptr MaterialLibrary::getMaterialByPath(const QString& path) const { // Base::Console().Log("MaterialLibrary::getMaterialByPath(%s)\n", path.toStdString().c_str()); // for (auto itp = _materialPathMap->begin(); itp != _materialPathMap->end(); itp++) { @@ -124,10 +274,10 @@ const Material& MaterialLibrary::getMaterialByPath(const QString& path) const QString filePath = getRelativePath(path); try { - Material* material = _materialPathMap->at(filePath); - return *material; + auto material = _materialPathMap->at(filePath); + return material; } - catch (std::out_of_range&) { + catch (std::out_of_range& e) { throw MaterialNotFound(); } } @@ -136,14 +286,80 @@ const QString MaterialLibrary::getUUIDFromPath(const QString& path) const { QString filePath = getRelativePath(path); try { - Material* material = _materialPathMap->at(filePath); + auto material = _materialPathMap->at(filePath); return material->getUUID(); } - catch (std::out_of_range&) { + catch (std::out_of_range& e) { throw MaterialNotFound(); } } +std::shared_ptr>> +MaterialLibrary::getMaterialTree() const +{ + std::shared_ptr>> materialTree = + std::make_shared>>(); + + for (auto it = _materialPathMap->begin(); it != _materialPathMap->end(); it++) { + auto filename = it->first; + auto material = it->second; + + // Base::Console().Log("Relative path '%s'\n\t", filename.toStdString().c_str()); + QStringList list = filename.split(QString::fromStdString("/")); + + // Start at the root + std::shared_ptr>> node = materialTree; + for (auto itp = list.begin(); itp != list.end(); itp++) { + // Base::Console().Log("\t%s", itp->toStdString().c_str()); + if (itp->endsWith(QString::fromStdString(".FCMat"))) { + std::shared_ptr child = std::make_shared(); + child->setData(material); + (*node)[*itp] = child; + } + else { + // Add the folder only if it's not already there + if (node->count(*itp) == 0) { + auto mapPtr = + std::make_shared>>(); + std::shared_ptr child = std::make_shared(); + child->setFolder(mapPtr); + (*node)[*itp] = child; + node = mapPtr; + } + else { + node = (*node)[*itp]->getFolder(); + } + } + } + } + + // Empty folders aren't included in _materialPathMap, so we add them by looking at the file + // system + auto folderList = MaterialLoader::getMaterialFolders(*this); + for (auto folder : *folderList) { + QStringList list = folder.split(QString::fromStdString("/")); + + // Start at the root + auto node = materialTree; + for (auto itp = list.begin(); itp != list.end(); itp++) { + // Add the folder only if it's not already there + if (node->count(*itp) == 0) { + std::shared_ptr>> mapPtr = + std::make_shared>>(); + std::shared_ptr child = std::make_shared(); + child->setFolder(mapPtr); + (*node)[*itp] = child; + node = mapPtr; + } + else { + node = (*node)[*itp]->getFolder(); + } + } + } + + return materialTree; +} + TYPESYSTEM_SOURCE(Materials::MaterialExternalLibrary, MaterialLibrary::MaterialLibrary) MaterialExternalLibrary::MaterialExternalLibrary() diff --git a/src/Mod/Material/App/MaterialLibrary.h b/src/Mod/Material/App/MaterialLibrary.h index 8bb16f34f8..ce6d32dfd3 100644 --- a/src/Mod/Material/App/MaterialLibrary.h +++ b/src/Mod/Material/App/MaterialLibrary.h @@ -22,14 +22,17 @@ #ifndef MATERIAL_MATERIALLIBRARY_H #define MATERIAL_MATERIALLIBRARY_H -#include - -#include #include + #include #include #include +#include + +#include + +#include "Materials.h" #include "Model.h" #include "ModelLibrary.h" @@ -37,17 +40,19 @@ namespace Materials { class Material; +class MaterialManager; -class MaterialsExport MaterialLibrary: public LibraryBase +class MaterialsExport MaterialLibrary: public LibraryBase, + public std::enable_shared_from_this { - TYPESYSTEM_HEADER_WITH_OVERRIDE(); + TYPESYSTEM_HEADER(); public: MaterialLibrary(); - explicit MaterialLibrary(const QString& libraryName, - const QString& dir, - const QString& icon, - bool readOnly = true); + MaterialLibrary(const QString& libraryName, + const QString& dir, + const QString& icon, + bool readOnly = true); ~MaterialLibrary() override = default; bool operator==(const MaterialLibrary& library) const @@ -58,40 +63,60 @@ public: { return !operator==(library); } - const Material& getMaterialByPath(const QString& path) const; + std::shared_ptr getMaterialByPath(const QString& path) const; - void createPath(const QString& path); - Material* saveMaterial(Material& material, const QString& path, bool saveAsCopy); - Material* addMaterial(const Material& material, const QString& path); + void createFolder(const QString& path); + void renameFolder(const QString& oldPath, const QString& newPath); + void deleteRecursive(const QString& path); + + std::shared_ptr saveMaterial(std::shared_ptr material, + const QString& path, + bool overwrite, + bool saveAsCopy, + bool saveInherited); + bool fileExists(const QString& path) const; + std::shared_ptr addMaterial(std::shared_ptr material, const QString& path); + std::shared_ptr>> getMaterialTree() const; bool isReadOnly() const { return _readOnly; } + // Use this to get a shared_ptr for *this + std::shared_ptr getptr() + { + return shared_from_this(); + } + protected: + MaterialLibrary(const MaterialLibrary&) = default; + + void deleteDir(MaterialManager& manager, const QString& path); + void deleteFile(MaterialManager& manager, const QString& path); + + void updatePaths(const QString& oldPath, const QString& newPath); const QString getUUIDFromPath(const QString& path) const; bool _readOnly; - static std::unique_ptr> _materialPathMap; + std::unique_ptr>> _materialPathMap; }; class MaterialsExport MaterialExternalLibrary: public MaterialLibrary { - TYPESYSTEM_HEADER_WITH_OVERRIDE(); + TYPESYSTEM_HEADER(); public: MaterialExternalLibrary(); - explicit MaterialExternalLibrary(const QString& libraryName, - const QString& dir, - const QString& icon, - bool readOnly = true); + MaterialExternalLibrary(const QString& libraryName, + const QString& dir, + const QString& icon, + bool readOnly = true); ~MaterialExternalLibrary() override; }; } // namespace Materials -Q_DECLARE_METATYPE(Materials::MaterialLibrary) -Q_DECLARE_METATYPE(Materials::MaterialExternalLibrary) +Q_DECLARE_METATYPE(std::shared_ptr) #endif // MATERIAL_MATERIALLIBRARY_H diff --git a/src/Mod/Material/App/MaterialLoader.cpp b/src/Mod/Material/App/MaterialLoader.cpp index 8742d7df6b..34004bc0a6 100644 --- a/src/Mod/Material/App/MaterialLoader.cpp +++ b/src/Mod/Material/App/MaterialLoader.cpp @@ -24,13 +24,18 @@ #include #endif -#include -#include - #include #include +#include + +#include +#include +#include + +#include "Materials.h" #include "MaterialConfigLoader.h" +#include "MaterialLibrary.h" #include "MaterialLoader.h" #include "Model.h" #include "ModelManager.h" @@ -41,7 +46,7 @@ using namespace Materials; MaterialEntry::MaterialEntry() {} -MaterialEntry::MaterialEntry(const MaterialLibrary& library, +MaterialEntry::MaterialEntry(std::shared_ptr library, const QString& modelName, const QString& dir, const QString& modelUuid) @@ -51,7 +56,7 @@ MaterialEntry::MaterialEntry(const MaterialLibrary& library, , _uuid(modelUuid) {} -MaterialYamlEntry::MaterialYamlEntry(const MaterialLibrary& library, +MaterialYamlEntry::MaterialYamlEntry(std::shared_ptr library, const QString& modelName, const QString& dir, const QString& modelUuid, @@ -73,7 +78,82 @@ QString MaterialYamlEntry::yamlValue(const YAML::Node& node, return QString::fromStdString(defaultValue); } -void MaterialYamlEntry::addToTree(std::shared_ptr> materialMap) +std::shared_ptr MaterialYamlEntry::read2DArray(const YAML::Node& node) +{ + // Base::Console().Log("Read 2D Array\n"); + + auto array2d = std::make_shared(); + + if (node.size() == 2) { + // Get the default + Base::Quantity defaultValue = + Base::Quantity::parse(QString::fromStdString(node[0].as())); + array2d->setDefault(QVariant::fromValue(defaultValue)); + + auto yamlArray = node[1]; + for (std::size_t i = 0; i < yamlArray.size(); i++) { + auto yamlRow = yamlArray[i]; + + auto row = std::make_shared>(); + for (std::size_t j = 0; j < yamlRow.size(); j++) { + Base::Quantity q = + Base::Quantity::parse(QString::fromStdString(yamlRow[j].as())); + row->push_back(QVariant::fromValue(q)); + } + array2d->addRow(row); + } + } + + return array2d; +} + +std::shared_ptr MaterialYamlEntry::read3DArray(const YAML::Node& node) +{ + Base::Console().Log("Read 3D Array\n"); + + auto array3d = std::make_shared(); + + if (node.size() == 2) { + // Get the default + Base::Quantity defaultValue = + Base::Quantity::parse(QString::fromStdString(node[0].as())); + array3d->setDefault(QVariant::fromValue(defaultValue)); + + auto yamlArray = node[1]; + + for (std::size_t depth = 0; depth < yamlArray.size(); depth++) { + auto yamlDepth = yamlArray[depth]; + MaterialLoader::showYaml(yamlDepth); + for (auto it = yamlDepth.begin(); it != yamlDepth.end(); it++) { + MaterialLoader::showYaml(it->first); + MaterialLoader::showYaml(it->second); + + Base::Console().Log("Depth %d '%s'\n", depth, it->first.as().c_str()); + auto depthValue = + Base::Quantity::parse(QString::fromStdString(it->first.as())); + + array3d->addDepth(depth, depthValue); + + auto yamlTable = it->second; + for (std::size_t i = 0; i < yamlTable.size(); i++) { + auto yamlRow = yamlTable[i]; + + auto row = std::make_shared>(); + for (std::size_t j = 0; j < yamlRow.size(); j++) { + row->push_back(Base::Quantity::parse( + QString::fromStdString(yamlRow[j].as()))); + } + array3d->addRow(depth, row); + } + } + } + } + + return array3d; +} + +void MaterialYamlEntry::addToTree( + std::shared_ptr>> materialMap) { std::set exclude; exclude.insert(QString::fromStdString("General")); @@ -85,11 +165,14 @@ void MaterialYamlEntry::addToTree(std::shared_ptr> auto directory = getDirectory(); QString uuid = getUUID(); - QString authorAndLicense = yamlValue(yamlModel["General"], "AuthorAndLicense", ""); + QString author = yamlValue(yamlModel["General"], "Author", ""); + QString license = yamlValue(yamlModel["General"], "License", ""); QString description = yamlValue(yamlModel["General"], "Description", ""); - Material* finalModel = new Material(library, directory, uuid, name); - finalModel->setAuthorAndLicense(authorAndLicense); + std::shared_ptr finalModel = + std::make_shared(library, directory, uuid, name); + finalModel->setAuthor(author); + finalModel->setLicense(license); finalModel->setDescription(description); // Add inheritance list @@ -118,11 +201,34 @@ void MaterialYamlEntry::addToTree(std::shared_ptr> auto properties = yamlModel["Models"][modelName]; for (auto itp = properties.begin(); itp != properties.end(); itp++) { std::string propertyName = (itp->first).as(); - std::string propertyValue = (itp->second).as(); - if (finalModel->hasPhysicalProperty(QString::fromStdString(propertyName))) { - finalModel->setPhysicalValue(QString::fromStdString(propertyName), - QString::fromStdString(propertyValue)); + auto prop = + finalModel->getPhysicalProperty(QString::fromStdString(propertyName)); + auto type = prop->getType(); + + try { + if (type == MaterialValue::Array2D) { + auto array2d = read2DArray(itp->second); + finalModel->setPhysicalValue(QString::fromStdString(propertyName), + array2d); + } + else if (type == MaterialValue::Array3D) { + auto array3d = read3DArray(itp->second); + finalModel->setPhysicalValue(QString::fromStdString(propertyName), + array3d); + } + else { + std::string propertyValue = (itp->second).as(); + finalModel->setPhysicalValue(QString::fromStdString(propertyName), + QString::fromStdString(propertyValue)); + } + } + catch (const YAML::BadConversion& e) { + Base::Console().Log("Exception %s <%s:%s> - ignored\n", + e.what(), + name.toStdString().c_str(), + propertyName.c_str()); + } } else if (propertyName != "UUID") { Base::Console().Log("\tProperty '%s' is not described by any model. Ignored\n", @@ -147,11 +253,32 @@ void MaterialYamlEntry::addToTree(std::shared_ptr> auto properties = yamlModel["AppearanceModels"][modelName]; for (auto itp = properties.begin(); itp != properties.end(); itp++) { std::string propertyName = (itp->first).as(); - std::string propertyValue = (itp->second).as(); - if (finalModel->hasAppearanceProperty(QString::fromStdString(propertyName))) { - finalModel->setAppearanceValue(QString::fromStdString(propertyName), - QString::fromStdString(propertyValue)); + auto prop = + finalModel->getAppearanceProperty(QString::fromStdString(propertyName)); + auto type = prop->getType(); + + try { + if (type == MaterialValue::Array2D) { + auto array2d = read2DArray(itp->second); + finalModel->setAppearanceValue(QString::fromStdString(propertyName), + array2d); + } + else if (type == MaterialValue::Array3D) { + Base::Console().Log("Read 3D Array\n"); + } + else { + std::string propertyValue = (itp->second).as(); + finalModel->setAppearanceValue(QString::fromStdString(propertyName), + QString::fromStdString(propertyValue)); + } + } + catch (const YAML::BadConversion& e) { + Base::Console().Log("Exception %s <%s:%s> - ignored\n", + e.what(), + name.toStdString().c_str(), + propertyName.c_str()); + } } else if (propertyName != "UUID") { Base::Console().Log("\tProperty '%s' is not described by any model. Ignored\n", @@ -163,13 +290,15 @@ void MaterialYamlEntry::addToTree(std::shared_ptr> QString path = QDir(directory).absolutePath(); // Base::Console().Log("\tPath '%s'\n", path.toStdString().c_str()); - (*materialMap)[uuid] = library.addMaterial(*finalModel, path); + (*materialMap)[uuid] = library->addMaterial(finalModel, path); } -std::unique_ptr> MaterialLoader::_materialEntryMap = nullptr; +std::unique_ptr>> + MaterialLoader::_materialEntryMap = nullptr; -MaterialLoader::MaterialLoader(std::shared_ptr> materialMap, - std::shared_ptr> libraryList) +MaterialLoader::MaterialLoader( + std::shared_ptr>> materialMap, + std::shared_ptr>> libraryList) : _materialMap(materialMap) , _libraryList(libraryList) { @@ -182,25 +311,58 @@ MaterialLoader::MaterialLoader(std::shared_ptr> mat MaterialLoader::~MaterialLoader() {} -void MaterialLoader::addLibrary(MaterialLibrary* model) +void MaterialLoader::addLibrary(std::shared_ptr model) { _libraryList->push_back(model); } -MaterialEntry* MaterialLoader::getMaterialFromPath(MaterialLibrary& library, - const QString& path) const +std::shared_ptr +MaterialLoader::getMaterialFromYAML(std::shared_ptr library, + YAML::Node& yamlroot, + const QString& path) const { - MaterialEntry* model = nullptr; + std::shared_ptr model = nullptr; + + try { + const std::string uuid = yamlroot["General"]["UUID"].as(); + + // Always get the name from the filename + // QString name = QString::fromStdString(yamlroot["General"]["Name"].as()); + QFileInfo filepath(path); + QString name = + filepath.fileName().remove(QString::fromStdString(".FCMat"), Qt::CaseInsensitive); + + model = std::make_shared(library, + name, + path, + QString::fromStdString(uuid), + yamlroot); + // showYaml(yamlroot); + } + catch (YAML::Exception const& e) { + Base::Console().Error("YAML parsing error: '%s'\n", path.toStdString().c_str()); + Base::Console().Error("\t'%s'\n", e.what()); + showYaml(yamlroot); + } + + + return model; +} + +std::shared_ptr +MaterialLoader::getMaterialFromPath(std::shared_ptr library, + const QString& path) const +{ + std::shared_ptr model = nullptr; // Used for debugging - std::string uuid; std::string pathName = path.toStdString(); if (MaterialConfigLoader::isConfigStyle(path)) { - Base::Console().Log("Old format .FCMat file: '%s'\n", pathName.c_str()); - Material* material = MaterialConfigLoader::getMaterialFromPath(library, path); + // Base::Console().Log("Old format .FCMat file: '%s'\n", pathName.c_str()); + auto material = MaterialConfigLoader::getMaterialFromPath(library, path); if (material) { - (*_materialMap)[material->getUUID()] = library.addMaterial(*material, path); + (*_materialMap)[material->getUUID()] = library->addMaterial(material, path); } // Return the nullptr as there are no intermediate steps to take, such @@ -212,15 +374,7 @@ MaterialEntry* MaterialLoader::getMaterialFromPath(MaterialLibrary& library, try { yamlroot = YAML::LoadFile(pathName); - const std::string uuid = yamlroot["General"]["UUID"].as(); - // Always get the name from the filename - // QString name = QString::fromStdString(yamlroot["General"]["Name"].as()); - QFileInfo filepath(path); - QString name = - filepath.fileName().remove(QString::fromStdString(".FCMat"), Qt::CaseInsensitive); - - model = new MaterialYamlEntry(library, name, path, QString::fromStdString(uuid), yamlroot); - // showYaml(yamlroot); + model = getMaterialFromYAML(library, yamlroot, path); } catch (YAML::Exception const& e) { Base::Console().Error("YAML parsing error: '%s'\n", pathName.c_str()); @@ -242,7 +396,9 @@ void MaterialLoader::showYaml(const YAML::Node& yaml) } -void MaterialLoader::dereference(Material* material) +void MaterialLoader::dereference( + std::shared_ptr>> materialMap, + std::shared_ptr material) { // Avoid recursion if (material->getDereferenced()) { @@ -254,19 +410,20 @@ void MaterialLoader::dereference(Material* material) auto parentUUID = material->getParentUUID(); if (parentUUID.size() > 0) { - Material* parent; + std::shared_ptr parent; try { - parent = (*_materialMap)[parentUUID]; + parent = materialMap->at(parentUUID); } - catch (std::out_of_range&) { + catch (std::out_of_range& e) { Base::Console().Log( "Unable to apply inheritance for material '%s', parent '%s' not found.\n", material->getName().toStdString().c_str(), parentUUID.toStdString().c_str()); + return; } // Ensure the parent has been dereferenced - dereference(parent); + dereference(materialMap, parent); // Add physical models auto modelVector = parent->getPhysicalModels(); @@ -288,20 +445,20 @@ void MaterialLoader::dereference(Material* material) auto properties = parent->getPhysicalProperties(); for (auto itp = properties.begin(); itp != properties.end(); itp++) { auto name = itp->first; - auto property = static_cast(itp->second); + auto property = itp->second; - if (material->getPhysicalProperty(name).isNull()) { - material->getPhysicalProperty(name).setValue(property.getValue()); + if (material->getPhysicalProperty(name)->isNull()) { + material->getPhysicalProperty(name)->setValue(property->getValue()); } } properties = parent->getAppearanceProperties(); for (auto itp = properties.begin(); itp != properties.end(); itp++) { auto name = itp->first; - auto property = static_cast(itp->second); + auto property = itp->second; - if (material->getAppearanceProperty(name).isNull()) { - material->getAppearanceProperty(name).setValue(property.getValue()); + if (material->getAppearanceProperty(name)->isNull()) { + material->getAppearanceProperty(name)->setValue(property->getValue()); } } } @@ -309,13 +466,18 @@ void MaterialLoader::dereference(Material* material) material->markDereferenced(); } -void MaterialLoader::loadLibrary(MaterialLibrary& library) +void MaterialLoader::dereference(std::shared_ptr material) +{ + dereference(_materialMap, material); +} + +void MaterialLoader::loadLibrary(std::shared_ptr library) { if (_materialEntryMap == nullptr) { - _materialEntryMap = std::make_unique>(); + _materialEntryMap = std::make_unique>>(); } - QDirIterator it(library.getDirectory(), QDirIterator::Subdirectories); + QDirIterator it(library->getDirectory(), QDirIterator::Subdirectories); while (it.hasNext()) { auto pathname = it.next(); QFileInfo file(pathname); @@ -341,7 +503,7 @@ void MaterialLoader::loadLibraries() auto _libraryList = getMaterialLibraries(); if (_libraryList) { for (auto it = _libraryList->begin(); it != _libraryList->end(); it++) { - loadLibrary(**it); + loadLibrary(*it); } } @@ -350,7 +512,7 @@ void MaterialLoader::loadLibraries() } } -std::shared_ptr> MaterialLoader::getMaterialLibraries() +std::shared_ptr>> MaterialLoader::getMaterialLibraries() { auto param = App::GetApplication().GetParameterGroupByPath( "User parameter:BaseApp/Preferences/Mod/Material/Resources"); @@ -362,10 +524,11 @@ std::shared_ptr> MaterialLoader::getMaterialLibrarie if (useBuiltInMaterials) { QString resourceDir = QString::fromStdString(App::Application::getResourceDir() + "/Mod/Material/Resources/Materials"); - auto libData = new MaterialLibrary(QString::fromStdString("System"), - resourceDir, - QString::fromStdString(":/icons/freecad.svg"), - true); + auto libData = + std::make_shared(QString::fromStdString("System"), + resourceDir, + QString::fromStdString(":/icons/freecad.svg"), + true); _libraryList->push_back(libData); } @@ -382,10 +545,10 @@ std::shared_ptr> MaterialLoader::getMaterialLibrarie if (materialDir.length() > 0) { QDir dir(materialDir); if (dir.exists()) { - auto libData = new MaterialLibrary(moduleName, - materialDir, - materialIcon, - materialReadOnly); + auto libData = std::make_shared(moduleName, + materialDir, + materialIcon, + materialReadOnly); _libraryList->push_back(libData); } } @@ -397,12 +560,19 @@ std::shared_ptr> MaterialLoader::getMaterialLibrarie QString::fromStdString(App::Application::getUserAppDataDir() + "/Material"); if (!resourceDir.isEmpty()) { QDir materialDir(resourceDir); + if (!materialDir.exists()) { + // Try creating the user dir if it doesn't exist + if (!materialDir.mkpath(resourceDir)) { + Base::Console().Log("Unable to create user library '%s'\n", + resourceDir.toStdString().c_str()); + } + } if (materialDir.exists()) { - auto libData = - new MaterialLibrary(QString::fromStdString("User"), - resourceDir, - QString::fromStdString(":/icons/preferences-general.svg"), - false); + auto libData = std::make_shared( + QString::fromStdString("User"), + resourceDir, + QString::fromStdString(":/icons/preferences-general.svg"), + false); _libraryList->push_back(libData); } } @@ -413,10 +583,11 @@ std::shared_ptr> MaterialLoader::getMaterialLibrarie if (!resourceDir.isEmpty()) { QDir materialDir(resourceDir); if (materialDir.exists()) { - auto libData = new MaterialLibrary(QString::fromStdString("Custom"), - resourceDir, - QString::fromStdString(":/icons/user.svg"), - false); + auto libData = + std::make_shared(QString::fromStdString("Custom"), + resourceDir, + QString::fromStdString(":/icons/user.svg"), + false); _libraryList->push_back(libData); } } diff --git a/src/Mod/Material/App/MaterialLoader.h b/src/Mod/Material/App/MaterialLoader.h index f4bac08939..427d348630 100644 --- a/src/Mod/Material/App/MaterialLoader.h +++ b/src/Mod/Material/App/MaterialLoader.h @@ -22,6 +22,8 @@ #ifndef MATERIAL_MATERIALLOADER_H #define MATERIAL_MATERIALLOADER_H +#include + #include #include #include @@ -36,15 +38,16 @@ class MaterialEntry { public: MaterialEntry(); - explicit MaterialEntry(const MaterialLibrary& library, - const QString& modelName, - const QString& dir, - const QString& modelUuid); + MaterialEntry(std::shared_ptr library, + const QString& modelName, + const QString& dir, + const QString& modelUuid); virtual ~MaterialEntry() = default; - virtual void addToTree(std::shared_ptr> materialMap) = 0; + virtual void + addToTree(std::shared_ptr>> materialMap) = 0; - const MaterialLibrary& getLibrary() const + std::shared_ptr getLibrary() const { return _library; } @@ -62,7 +65,7 @@ public: } protected: - MaterialLibrary _library; + std::shared_ptr _library; QString _name; QString _directory; QString _uuid; @@ -71,14 +74,15 @@ protected: class MaterialYamlEntry: public MaterialEntry { public: - explicit MaterialYamlEntry(const MaterialLibrary& library, - const QString& modelName, - const QString& dir, - const QString& modelUuid, - const YAML::Node& modelData); + MaterialYamlEntry(std::shared_ptr library, + const QString& modelName, + const QString& dir, + const QString& modelUuid, + const YAML::Node& modelData); ~MaterialYamlEntry() override = default; - void addToTree(std::shared_ptr> materialMap) override; + void + addToTree(std::shared_ptr>> materialMap) override; const YAML::Node& getModel() const { @@ -94,6 +98,8 @@ private: QString yamlValue(const YAML::Node& node, const std::string& key, const std::string& defaultValue); + std::shared_ptr read2DArray(const YAML::Node& node); + std::shared_ptr read3DArray(const YAML::Node& node); YAML::Node _model; }; @@ -101,26 +107,34 @@ private: class MaterialLoader { public: - explicit MaterialLoader(std::shared_ptr> materialMap, - std::shared_ptr> libraryList); + MaterialLoader(std::shared_ptr>> materialMap, + std::shared_ptr>> libraryList); virtual ~MaterialLoader(); - std::shared_ptr> getMaterialLibraries(); + std::shared_ptr>> getMaterialLibraries(); static std::shared_ptr> getMaterialFolders(const MaterialLibrary& library); static void showYaml(const YAML::Node& yaml); + static void + dereference(std::shared_ptr>> materialMap, + std::shared_ptr material); + std::shared_ptr getMaterialFromYAML(std::shared_ptr library, + YAML::Node& yamlroot, + const QString& path) const; private: MaterialLoader(); - void addToTree(MaterialEntry* model); - void dereference(Material* material); - MaterialEntry* getMaterialFromPath(MaterialLibrary& library, const QString& path) const; - void addLibrary(MaterialLibrary* model); - void loadLibrary(MaterialLibrary& library); + void addToTree(std::shared_ptr model); + void dereference(std::shared_ptr material); + std::shared_ptr getMaterialFromPath(std::shared_ptr library, + const QString& path) const; + void addLibrary(std::shared_ptr model); + void loadLibrary(std::shared_ptr library); void loadLibraries(); - static std::unique_ptr> _materialEntryMap; - std::shared_ptr> _materialMap; - std::shared_ptr> _libraryList; + + static std::unique_ptr>> _materialEntryMap; + std::shared_ptr>> _materialMap; + std::shared_ptr>> _libraryList; }; } // namespace Materials diff --git a/src/Mod/Material/App/MaterialManager.cpp b/src/Mod/Material/App/MaterialManager.cpp index efbf45b0b9..f073b7a087 100644 --- a/src/Mod/Material/App/MaterialManager.cpp +++ b/src/Mod/Material/App/MaterialManager.cpp @@ -23,6 +23,7 @@ #ifndef _PreComp_ #endif +#include #include #include @@ -37,8 +38,10 @@ using namespace Materials; /* TRANSLATOR Material::Materials */ -std::shared_ptr> MaterialManager::_libraryList = nullptr; -std::shared_ptr> MaterialManager::_materialMap = nullptr; +std::shared_ptr>> MaterialManager::_libraryList = + nullptr; +std::shared_ptr>> MaterialManager::_materialMap = + nullptr; QMutex MaterialManager::_mutex; TYPESYSTEM_SOURCE(Materials::MaterialManager, Base::BaseClass) @@ -60,10 +63,10 @@ void MaterialManager::initLibraries() delete manager; - _materialMap = std::make_shared>(); + _materialMap = std::make_shared>>(); if (_libraryList == nullptr) { - _libraryList = std::make_shared>(); + _libraryList = std::make_shared>>(); } // Load the libraries @@ -71,23 +74,15 @@ void MaterialManager::initLibraries() } } -void MaterialManager::saveMaterial(MaterialLibrary* library, - Material& material, +void MaterialManager::saveMaterial(std::shared_ptr library, + std::shared_ptr material, const QString& path, - bool saveAsCopy) + bool overwrite, + bool saveAsCopy, + bool saveInherited) { - Material* newMaterial = library->saveMaterial(material, path, saveAsCopy); - - try { - Material* old = _materialMap->at(newMaterial->getUUID()); - if (old) { - delete old; - } - } - catch (const std::out_of_range&) { - } - - (*_materialMap)[material.getUUID()] = newMaterial; + auto newMaterial = library->saveMaterial(material, path, overwrite, saveAsCopy, saveInherited); + (*_materialMap)[newMaterial->getUUID()] = newMaterial; } bool MaterialManager::isMaterial(const fs::path& p) @@ -102,31 +97,43 @@ bool MaterialManager::isMaterial(const fs::path& p) return false; } -const Material& MaterialManager::getMaterial(const QString& uuid) const +bool MaterialManager::isMaterial(const QFileInfo& file) +{ + if (!file.isFile()) { + return false; + } + // check file extension + if (file.suffix() == QString::fromStdString("FCMat")) { + return true; + } + return false; +} + +std::shared_ptr MaterialManager::getMaterial(const QString& uuid) const { try { - return *(_materialMap->at(uuid)); + return _materialMap->at(uuid); } - catch (std::out_of_range&) { + catch (std::out_of_range& e) { throw MaterialNotFound(); } } -const Material& MaterialManager::getMaterialByPath(const QString& path) const +std::shared_ptr MaterialManager::getMaterialByPath(const QString& path) const { QString cleanPath = QDir::cleanPath(path); for (auto library : *_libraryList) { - Base::Console().Log("MaterialManager::getMaterialByPath() Checking library '%s'->'%s'\n", - library->getName().toStdString().c_str(), - library->getDirectory().toStdString().c_str()); + // Base::Console().Log("MaterialManager::getMaterialByPath() Checking library '%s'->'%s'\n", + // library->getName().toStdString().c_str(), + // library->getDirectory().toStdString().c_str()); if (cleanPath.startsWith(library->getDirectory())) { - Base::Console().Log("MaterialManager::getMaterialByPath() Library '%s'\n", - library->getDirectory().toStdString().c_str()); - Base::Console().Log("MaterialManager::getMaterialByPath() Path '%s'\n", - cleanPath.toStdString().c_str()); + // Base::Console().Log("MaterialManager::getMaterialByPath() Library '%s'\n", + // library->getDirectory().toStdString().c_str()); + // Base::Console().Log("MaterialManager::getMaterialByPath() Path '%s'\n", + // cleanPath.toStdString().c_str()); return library->getMaterialByPath(cleanPath); } } @@ -136,13 +143,51 @@ const Material& MaterialManager::getMaterialByPath(const QString& path) const throw MaterialNotFound(); } -const Material& MaterialManager::getMaterialByPath(const QString& path, const QString& lib) const +std::shared_ptr MaterialManager::getMaterialByPath(const QString& path, + const QString& lib) const { auto library = getLibrary(lib); // May throw LibraryNotFound return library->getMaterialByPath(path); // May throw MaterialNotFound } -MaterialLibrary* MaterialManager::getLibrary(const QString& name) const +bool MaterialManager::exists(const QString& uuid) const +{ + try { + auto material = getMaterial(uuid); + if (material.get() != nullptr) { + return true; + } + } + catch (const MaterialNotFound&) { + } + + return false; +} + +std::shared_ptr MaterialManager::getParent(std::shared_ptr material) +{ + if (material->getParentUUID().isEmpty()) { + throw MaterialNotFound(); + } + + return getMaterial(material->getParentUUID()); +} + +bool MaterialManager::exists(std::shared_ptr library, const QString& uuid) const +{ + try { + auto material = getMaterial(uuid); + if (material.get() != nullptr) { + return (*material->getLibrary() == *library); + } + } + catch (const MaterialNotFound&) { + } + + return false; +} + +std::shared_ptr MaterialManager::getLibrary(const QString& name) const { for (auto library : *_libraryList) { if (library->getName() == name) { @@ -153,13 +198,13 @@ MaterialLibrary* MaterialManager::getLibrary(const QString& name) const throw LibraryNotFound(); } -std::shared_ptr> MaterialManager::getMaterialLibraries() +std::shared_ptr>> MaterialManager::getMaterialLibraries() { if (_libraryList == nullptr) { if (_materialMap == nullptr) { - _materialMap = std::make_shared>(); + _materialMap = std::make_shared>>(); } - _libraryList = std::make_shared>(); + _libraryList = std::make_shared>>(); // Load the libraries MaterialLoader loader(_materialMap, _libraryList); @@ -167,87 +212,21 @@ std::shared_ptr> MaterialManager::getMaterialLibrari return _libraryList; } -std::shared_ptr> -MaterialManager::getMaterialTree(const MaterialLibrary& library) const -{ - std::shared_ptr> materialTree = - std::make_shared>(); - - for (auto it = _materialMap->begin(); it != _materialMap->end(); it++) { - auto filename = it->first; - auto material = it->second; - - if (material->getLibrary() == library) { - fs::path path = material->getDirectory().toStdString(); - - // Start at the root - auto node = materialTree; - for (auto itp = path.begin(); itp != path.end(); itp++) { - if (QString::fromStdString(itp->string()) - .endsWith(QString::fromStdString(".FCMat"))) { - MaterialTreeNode* child = new MaterialTreeNode(); - child->setData(material); - (*node)[QString::fromStdString(itp->string())] = child; - } - else { - // Add the folder only if it's not already there - QString folderName = QString::fromStdString(itp->string()); - std::shared_ptr> mapPtr; - if (node->count(folderName) == 0) { - mapPtr = std::make_shared>(); - MaterialTreeNode* child = new MaterialTreeNode(); - child->setFolder(mapPtr); - (*node)[folderName] = child; - node = mapPtr; - } - else { - node = (*node)[folderName]->getFolder(); - } - } - } - } - } - - auto folderList = getMaterialFolders(library); - for (auto folder : *folderList) { - fs::path path = folder.toStdString(); - - // Start at the root - auto node = materialTree; - for (auto itp = path.begin(); itp != path.end(); itp++) { - // Add the folder only if it's not already there - QString folderName = QString::fromStdString(itp->string()); - if (node->count(folderName) == 0) { - std::shared_ptr> mapPtr = - std::make_shared>(); - MaterialTreeNode* child = new MaterialTreeNode(); - child->setFolder(mapPtr); - (*node)[folderName] = child; - node = mapPtr; - } - else { - node = (*node)[folderName]->getFolder(); - } - } - } - - return materialTree; -} - std::shared_ptr> -MaterialManager::getMaterialFolders(const MaterialLibrary& library) const +MaterialManager::getMaterialFolders(std::shared_ptr library) const { - return MaterialLoader::getMaterialFolders(library); + return MaterialLoader::getMaterialFolders(*library); } -std::shared_ptr> MaterialManager::materialsWithModel(QString uuid) +std::shared_ptr>> +MaterialManager::materialsWithModel(QString uuid) { - std::shared_ptr> dict = - std::make_shared>(); + std::shared_ptr>> dict = + std::make_shared>>(); for (auto it = _materialMap->begin(); it != _materialMap->end(); it++) { QString key = it->first; - Material* material = it->second; + auto material = it->second; if (material->hasModel(uuid)) { (*dict)[key] = material; @@ -257,15 +236,15 @@ std::shared_ptr> MaterialManager::materialsWithMode return dict; } -std::shared_ptr> +std::shared_ptr>> MaterialManager::materialsWithModelComplete(QString uuid) { - std::shared_ptr> dict = - std::make_shared>(); + std::shared_ptr>> dict = + std::make_shared>>(); for (auto it = _materialMap->begin(); it != _materialMap->end(); it++) { QString key = it->first; - Material* material = it->second; + auto material = it->second; if (material->isModelComplete(uuid)) { (*dict)[key] = material; @@ -274,3 +253,8 @@ MaterialManager::materialsWithModelComplete(QString uuid) return dict; } + +void MaterialManager::dereference(std::shared_ptr material) +{ + MaterialLoader::dereference(_materialMap, material); +} diff --git a/src/Mod/Material/App/MaterialManager.h b/src/Mod/Material/App/MaterialManager.h index 03c423326d..af4261cd9f 100644 --- a/src/Mod/Material/App/MaterialManager.h +++ b/src/Mod/Material/App/MaterialManager.h @@ -22,61 +22,90 @@ #ifndef MATERIAL_MATERIALMANAGER_H #define MATERIAL_MATERIALMANAGER_H -#include +#include #include #include +#include + #include "FolderTree.h" #include "Materials.h" +#include "MaterialLibrary.h" + namespace fs = boost::filesystem; namespace Materials { -typedef FolderTreeNode MaterialTreeNode; - class MaterialsExport MaterialManager: public Base::BaseClass { - TYPESYSTEM_HEADER_WITH_OVERRIDE(); + TYPESYSTEM_HEADER(); public: MaterialManager(); ~MaterialManager() override = default; - std::shared_ptr> getMaterials() + std::shared_ptr>> getMaterials() { return _materialMap; } - const Material& getMaterial(const QString& uuid) const; - const Material& getMaterialByPath(const QString& path) const; - const Material& getMaterialByPath(const QString& path, const QString& library) const; - MaterialLibrary* getLibrary(const QString& name) const; + std::shared_ptr getMaterial(const QString& uuid) const; + std::shared_ptr getMaterialByPath(const QString& path) const; + std::shared_ptr getMaterialByPath(const QString& path, const QString& library) const; + std::shared_ptr getParent(std::shared_ptr material); + std::shared_ptr getLibrary(const QString& name) const; + bool exists(const QString& uuid) const; + bool exists(std::shared_ptr library, const QString& uuid) const; // Library management - static std::shared_ptr> getMaterialLibraries(); - std::shared_ptr> - getMaterialTree(const MaterialLibrary& library) const; - std::shared_ptr> getMaterialFolders(const MaterialLibrary& library) const; - void createPath(MaterialLibrary* library, const QString& path) + static std::shared_ptr>> getMaterialLibraries(); + std::shared_ptr>> + getMaterialTree(std::shared_ptr library) const { - library->createPath(path); + return library->getMaterialTree(); } - void saveMaterial(MaterialLibrary* library, - Material& material, + std::shared_ptr> + getMaterialFolders(std::shared_ptr library) const; + void createFolder(std::shared_ptr library, const QString& path) + { + library->createFolder(path); + } + void renameFolder(std::shared_ptr library, + const QString& oldPath, + const QString& newPath) + { + library->renameFolder(oldPath, newPath); + } + void deleteRecursive(std::shared_ptr library, const QString& path) + { + library->deleteRecursive(path); + } + void remove(const QString& uuid) + { + _materialMap->erase(uuid); + } + + void saveMaterial(std::shared_ptr library, + std::shared_ptr material, const QString& path, - bool saveAsCopy = true); + bool overwrite, + bool saveAsCopy, + bool saveInherited); static bool isMaterial(const fs::path& p); + static bool isMaterial(const QFileInfo& file); - std::shared_ptr> materialsWithModel(QString uuid); - std::shared_ptr> materialsWithModelComplete(QString uuid); + std::shared_ptr>> materialsWithModel(QString uuid); + std::shared_ptr>> + materialsWithModelComplete(QString uuid); + void dereference(std::shared_ptr material); private: - static std::shared_ptr> _libraryList; - static std::shared_ptr> _materialMap; + static std::shared_ptr>> _libraryList; + static std::shared_ptr>> _materialMap; static QMutex _mutex; static void initLibraries(); diff --git a/src/Mod/Material/App/MaterialManagerPyImpl.cpp b/src/Mod/Material/App/MaterialManagerPyImpl.cpp index 733b2cba2c..560e22c9e3 100644 --- a/src/Mod/Material/App/MaterialManagerPyImpl.cpp +++ b/src/Mod/Material/App/MaterialManagerPyImpl.cpp @@ -21,10 +21,6 @@ #include "PreCompiled.h" -#ifndef _PreComp_ -#include -#endif - #include "Exceptions.h" #include "MaterialManager.h" #include "MaterialManagerPy.h" @@ -64,9 +60,8 @@ PyObject* MaterialManagerPy::getMaterial(PyObject* args) } try { - const Material& material = - getMaterialManagerPtr()->getMaterial(QString::fromStdString(uuid)); - return new MaterialPy(new Material(material)); + auto material = getMaterialManagerPtr()->getMaterial(QString::fromStdString(uuid)); + return new MaterialPy(new Material(*material)); } catch (const MaterialNotFound&) { PyErr_SetString(PyExc_LookupError, "Material not found"); @@ -85,9 +80,9 @@ PyObject* MaterialManagerPy::getMaterialByPath(PyObject* args) QString libPath(QString::fromStdString(lib)); if (!libPath.isEmpty()) { try { - const Material& material = + auto material = getMaterialManagerPtr()->getMaterialByPath(QString::fromStdString(path), libPath); - return new MaterialPy(new Material(material)); + return new MaterialPy(new Material(*material)); } catch (const MaterialNotFound&) { PyErr_SetString(PyExc_LookupError, "Material not found"); @@ -100,9 +95,8 @@ PyObject* MaterialManagerPy::getMaterialByPath(PyObject* args) } try { - const Material& material = - getMaterialManagerPtr()->getMaterialByPath(QString::fromStdString(path)); - return new MaterialPy(new Material(material)); + auto material = getMaterialManagerPtr()->getMaterialByPath(QString::fromStdString(path)); + return new MaterialPy(new Material(*material)); } catch (const MaterialNotFound&) { PyErr_SetString(PyExc_LookupError, "Material not found"); @@ -116,7 +110,7 @@ Py::List MaterialManagerPy::getMaterialLibraries() const Py::List list; for (auto it = libraries->begin(); it != libraries->end(); it++) { - MaterialLibrary* lib = *it; + auto lib = *it; Py::Tuple libTuple(3); libTuple.setItem(0, Py::String(lib->getName().toStdString())); libTuple.setItem(1, Py::String(lib->getDirectoryPath().toStdString())); @@ -136,7 +130,7 @@ Py::Dict MaterialManagerPy::getMaterials() const for (auto it = materials->begin(); it != materials->end(); it++) { QString key = it->first; - Material* material = it->second; + auto material = it->second; PyObject* materialPy = new MaterialPy(new Material(*material)); dict.setItem(Py::String(key.toStdString()), Py::Object(materialPy, true)); @@ -168,7 +162,7 @@ PyObject* MaterialManagerPy::materialsWithModel(PyObject* args) for (auto it = materials->begin(); it != materials->end(); it++) { QString key = it->first; - Material* material = it->second; + auto material = it->second; PyObject* materialPy = new MaterialPy(new Material(*material)); PyDict_SetItem(dict, PyUnicode_FromString(key.toStdString().c_str()), materialPy); @@ -190,7 +184,7 @@ PyObject* MaterialManagerPy::materialsWithModelComplete(PyObject* args) for (auto it = materials->begin(); it != materials->end(); it++) { QString key = it->first; - Material* material = it->second; + auto material = it->second; PyObject* materialPy = new MaterialPy(new Material(*material)); PyDict_SetItem(dict, PyUnicode_FromString(key.toStdString().c_str()), materialPy); diff --git a/src/Mod/Material/App/MaterialPy.xml b/src/Mod/Material/App/MaterialPy.xml index d2ffb43da2..e16a95f804 100644 --- a/src/Mod/Material/App/MaterialPy.xml +++ b/src/Mod/Material/App/MaterialPy.xml @@ -77,10 +77,22 @@ - Author and license information. + deprecated -- Author and license information. + + + Author information. + + + + + + License information. + + + List of implemented models. diff --git a/src/Mod/Material/App/MaterialPyImpl.cpp b/src/Mod/Material/App/MaterialPyImpl.cpp index 8248f2951f..49d3668e99 100644 --- a/src/Mod/Material/App/MaterialPyImpl.cpp +++ b/src/Mod/Material/App/MaterialPyImpl.cpp @@ -21,20 +21,18 @@ #include "PreCompiled.h" -#ifndef _PreComp_ -#include -#endif - #include #include #include #include -#include "Exceptions.h" -#include "MaterialPy.h" #include "Materials.h" +#include "Exceptions.h" +#include "MaterialLibrary.h" +#include "MaterialPy.h" + #include "MaterialPy.cpp" using namespace Materials; @@ -49,11 +47,11 @@ std::string MaterialPy::representation() const str << "), UUID=("; str << ptr->getUUID().toStdString(); str << "), Library Name=("; - str << ptr->getLibrary().getName().toStdString(); + str << ptr->getLibrary()->getName().toStdString(); str << "), Library Root=("; - str << ptr->getLibrary().getDirectoryPath().toStdString(); + str << ptr->getLibrary()->getDirectoryPath().toStdString(); str << "), Library Icon=("; - str << ptr->getLibrary().getIconPath().toStdString(); + str << ptr->getLibrary()->getIconPath().toStdString(); str << "), Directory=("; str << ptr->getDirectory().toStdString(); // str << "), URL=("; @@ -93,17 +91,17 @@ int MaterialPy::PyInit(PyObject* /*args*/, PyObject* /*kwd*/) Py::String MaterialPy::getLibraryName() const { - return Py::String(getMaterialPtr()->getLibrary().getName().toStdString()); + return Py::String(getMaterialPtr()->getLibrary()->getName().toStdString()); } Py::String MaterialPy::getLibraryRoot() const { - return Py::String(getMaterialPtr()->getLibrary().getDirectoryPath().toStdString()); + return Py::String(getMaterialPtr()->getLibrary()->getDirectoryPath().toStdString()); } Py::String MaterialPy::getLibraryIcon() const { - return Py::String(getMaterialPtr()->getLibrary().getIconPath().toStdString()); + return Py::String(getMaterialPtr()->getLibrary()->getIconPath().toStdString()); } Py::String MaterialPy::getName() const @@ -146,15 +144,23 @@ Py::String MaterialPy::getAuthorAndLicense() const return Py::String(getMaterialPtr()->getAuthorAndLicense().toStdString()); } +Py::String MaterialPy::getAuthor() const +{ + return Py::String(getMaterialPtr()->getAuthor().toStdString()); +} + +Py::String MaterialPy::getLicense() const +{ + return Py::String(getMaterialPtr()->getLicense().toStdString()); +} + Py::List MaterialPy::getPhysicalModels() const { - const std::vector* models = getMaterialPtr()->getPhysicalModels(); + auto models = getMaterialPtr()->getPhysicalModels(); Py::List list; for (auto it = models->begin(); it != models->end(); it++) { - QString uuid = *it; - - list.append(Py::String(uuid.toStdString())); + list.append(Py::String(it->toStdString())); } return list; @@ -162,13 +168,11 @@ Py::List MaterialPy::getPhysicalModels() const Py::List MaterialPy::getAppearanceModels() const { - const std::vector* models = getMaterialPtr()->getAppearanceModels(); + auto models = getMaterialPtr()->getAppearanceModels(); Py::List list; for (auto it = models->begin(); it != models->end(); it++) { - QString uuid = *it; - - list.append(Py::String(uuid.toStdString())); + list.append(Py::String(it->toStdString())); } return list; @@ -176,13 +180,11 @@ Py::List MaterialPy::getAppearanceModels() const Py::List MaterialPy::getTags() const { - const std::list& tags = getMaterialPtr()->getTags(); + auto& tags = getMaterialPtr()->getTags(); Py::List list; for (auto it = tags.begin(); it != tags.end(); it++) { - QString uuid = *it; - - list.append(Py::String(uuid.toStdString())); + list.append(Py::String(it->toStdString())); } return list; @@ -272,6 +274,8 @@ Py::Dict MaterialPy::getProperties() const dict.setItem(Py::String("CardName"), Py::String(getMaterialPtr()->getName().toStdString())); dict.setItem(Py::String("AuthorAndLicense"), Py::String(getMaterialPtr()->getAuthorAndLicense().toStdString())); + dict.setItem(Py::String("Author"), Py::String(getMaterialPtr()->getAuthor().toStdString())); + dict.setItem(Py::String("License"), Py::String(getMaterialPtr()->getLicense().toStdString())); dict.setItem(Py::String("Name"), Py::String(getMaterialPtr()->getName().toStdString())); dict.setItem(Py::String("Description"), Py::String(getMaterialPtr()->getDescription().toStdString())); @@ -282,10 +286,10 @@ Py::Dict MaterialPy::getProperties() const auto properties = getMaterialPtr()->getPhysicalProperties(); for (auto it = properties.begin(); it != properties.end(); it++) { QString key = it->first; - MaterialProperty& materialProperty = it->second; + auto materialProperty = it->second; - if (!materialProperty.isNull()) { - auto value = materialProperty.getString(); + if (!materialProperty->isNull()) { + auto value = materialProperty->getString(); dict.setItem(Py::String(key.toStdString()), Py::String(value.toStdString())); } } @@ -293,10 +297,10 @@ Py::Dict MaterialPy::getProperties() const properties = getMaterialPtr()->getAppearanceProperties(); for (auto it = properties.begin(); it != properties.end(); it++) { QString key = it->first; - MaterialProperty& materialProperty = it->second; + auto materialProperty = it->second; - if (!materialProperty.isNull()) { - auto value = materialProperty.getString(); + if (!materialProperty->isNull()) { + auto value = materialProperty->getString(); dict.setItem(Py::String(key.toStdString()), Py::String(value.toStdString())); } } @@ -311,10 +315,10 @@ Py::Dict MaterialPy::getPhysicalProperties() const auto properties = getMaterialPtr()->getPhysicalProperties(); for (auto it = properties.begin(); it != properties.end(); it++) { QString key = it->first; - MaterialProperty& materialProperty = it->second; + auto materialProperty = it->second; - if (!materialProperty.isNull()) { - auto value = materialProperty.getString(); + if (!materialProperty->isNull()) { + auto value = materialProperty->getString(); dict.setItem(Py::String(key.toStdString()), Py::String(value.toStdString())); } } @@ -329,10 +333,10 @@ Py::Dict MaterialPy::getAppearanceProperties() const auto properties = getMaterialPtr()->getAppearanceProperties(); for (auto it = properties.begin(); it != properties.end(); it++) { QString key = it->first; - MaterialProperty& materialProperty = it->second; + auto materialProperty = it->second; - if (!materialProperty.isNull()) { - auto value = materialProperty.getString(); + if (!materialProperty->isNull()) { + auto value = materialProperty->getString(); dict.setItem(Py::String(key.toStdString()), Py::String(value.toStdString())); } } @@ -346,7 +350,7 @@ static PyObject* _pyObjectFromVariant(const QVariant& value) return new PyObject(); } - if (value.userType() == qMetaTypeId()) { + if (value.userType() == QMetaType::type("Base::Quantity")) { return new Base::QuantityPy(new Base::Quantity(value.value())); } else if (value.userType() == QMetaType::Double) { diff --git a/src/Mod/Material/App/MaterialValue.cpp b/src/Mod/Material/App/MaterialValue.cpp index 76805d369b..3229424696 100644 --- a/src/Mod/Material/App/MaterialValue.cpp +++ b/src/Mod/Material/App/MaterialValue.cpp @@ -23,7 +23,11 @@ #ifndef _PreComp_ #endif +#include + #include +#include +#include #include "Exceptions.h" #include "MaterialValue.h" @@ -33,29 +37,203 @@ using namespace Materials; /* TRANSLATOR Material::MaterialValue */ +TYPESYSTEM_SOURCE(Materials::MaterialValue, Base::BaseClass) + MaterialValue::MaterialValue() : _valueType(None) +{ + this->setInitialValue(None); +} + +MaterialValue::MaterialValue(const MaterialValue& other) + : _valueType(other._valueType) + , _value(other._value) {} MaterialValue::MaterialValue(ValueType type) : _valueType(type) -{} +{ + this->setInitialValue(None); +} + +MaterialValue::MaterialValue(ValueType type, ValueType inherited) + : _valueType(type) +{ + this->setInitialValue(inherited); +} + +MaterialValue& MaterialValue::operator=(const MaterialValue& other) +{ + if (this == &other) { + return *this; + } + + _valueType = other._valueType; + _value = other._value; + + return *this; +} + +bool MaterialValue::operator==(const MaterialValue& other) const +{ + if (this == &other) { + return true; + } + + return (_valueType == other._valueType) && (_value == other._value); +} + +void MaterialValue::setInitialValue(ValueType inherited) +{ + if (_valueType == String) { + _value = QVariant(static_cast(QMetaType::QString)); + } + else if (_valueType == Boolean) { + _value = QVariant(static_cast(QMetaType::Bool)); + } + else if (_valueType == Integer) { + _value = QVariant(static_cast(QMetaType::Int)); + } + else if (_valueType == Float) { + _value = QVariant(static_cast(QMetaType::Float)); + } + else if (_valueType == URL) { + _value = QVariant(static_cast(QMetaType::QString)); + } + else if (_valueType == Quantity) { + Base::Quantity q; + q.setInvalid(); + _value = QVariant::fromValue(q); + } + else if (_valueType == Color) { + _value = QVariant(static_cast(QMetaType::QString)); + } + else if (_valueType == File) { + _value = QVariant(static_cast(QMetaType::QString)); + } + else if (_valueType == Image) { + _value = QVariant(static_cast(QMetaType::QString)); + } + else if (_valueType == List) { + _value = QVariant(static_cast(QMetaType::QString)); + } + else if (_valueType == Array2D) { + if (_valueType != inherited) { + throw InvalidMaterialType("Initializing a regular material value as a 2D Array"); + } + + _value = QVariant(); // Uninitialized default value + } + else if (_valueType == Array3D) { + if (_valueType != inherited) { + throw InvalidMaterialType("Initializing a regular material value as a 3D Array"); + } + + _value = QVariant(); // Uninitialized default value + } + else { + // Default is to set the type to None and leave the variant uninitialized + _valueType = None; + _value = QVariant(); + } +} + +bool MaterialValue::isNull() const +{ + if (_value.isNull()) { + return true; + } + + if (_valueType == Quantity) { + return !_value.value().isValid(); + } + + return false; +} + +const QString MaterialValue::getYAMLString() const +{ + QString yaml = QString::fromStdString("\""); + if (!isNull()) { + if (getType() == MaterialValue::Quantity) { + Base::Quantity quantity = getValue().value(); + yaml += quantity.getUserString(); + } + else if (getType() == MaterialValue::Float) { + auto value = getValue(); + if (!value.isNull()) { + yaml += QString(QString::fromStdString("%1")).arg(value.toFloat(), 0, 'g', 6); + } + } + else { + yaml += getValue().toString(); + } + } + yaml += QString::fromStdString("\""); + return yaml; +} //=== +TYPESYSTEM_SOURCE(Materials::Material2DArray, Materials::MaterialValue) + Material2DArray::Material2DArray() - : MaterialValue(Array2D) + : MaterialValue(Array2D, Array2D) , _defaultSet(false) -{} - -MaterialValue Material2DArray::getDefault() const { - MaterialValue ret(_valueType); - ret.setValue(_value); - return ret; + // Initialize separatelt to prevent recursion + // setType(Array2D); } -const std::vector* Material2DArray::getRow(int row) const +Material2DArray::Material2DArray(const Material2DArray& other) + : MaterialValue(other) + , _defaultSet(other._defaultSet) +{ + deepCopy(other); +} + +Material2DArray& Material2DArray::operator=(const Material2DArray& other) +{ + if (this == &other) { + return *this; + } + + MaterialValue::operator=(other); + _defaultSet = other._defaultSet; + + deepCopy(other); + + return *this; +} + +void Material2DArray::deepCopy(const Material2DArray& other) +{ + // Deep copy + for (auto row : other._rows) { + std::vector v; + for (auto col : *row) { + QVariant newVariant(col); + v.push_back(newVariant); + } + addRow(std::make_shared>(v)); + } +} + +bool Material2DArray::isNull() const +{ + return rows() <= 0; +} + +const QVariant Material2DArray::getDefault() const +{ + if (_defaultSet) { + return _value; + } + + return QVariant(); +} + +std::shared_ptr> Material2DArray::getRow(int row) const { try { return _rows.at(row); @@ -65,7 +243,7 @@ const std::vector* Material2DArray::getRow(int row) const } } -std::vector* Material2DArray::getRow(int row) +std::shared_ptr> Material2DArray::getRow(int row) { try { return _rows.at(row); @@ -75,12 +253,12 @@ std::vector* Material2DArray::getRow(int row) } } -void Material2DArray::addRow(std::vector* row) +void Material2DArray::addRow(std::shared_ptr> row) { _rows.push_back(row); } -void Material2DArray::insertRow(int index, std::vector* row) +void Material2DArray::insertRow(int index, std::shared_ptr> row) { _rows.insert(_rows.begin() + index, row); } @@ -99,7 +277,7 @@ void Material2DArray::setValue(int row, int column, const QVariant& value) throw InvalidIndex(); } - std::vector* val = getRow(row); + auto val = getRow(row); try { val->at(column) = value; } @@ -124,10 +302,10 @@ const QVariant Material2DArray::getValue(int row, int column) const } } -void Material2DArray::dumpRow(const std::vector& row) const +void Material2DArray::dumpRow(std::shared_ptr> row) const { Base::Console().Log("row: "); - for (auto column : row) { + for (auto column : *row) { Base::Console().Log("'%s' ", column.toString().toStdString().c_str()); } Base::Console().Log("\n"); @@ -136,107 +314,389 @@ void Material2DArray::dumpRow(const std::vector& row) const void Material2DArray::dump() const { for (auto row : _rows) { - dumpRow(*row); + dumpRow(row); } } +const QString Material2DArray::getYAMLString() const +{ + if (isNull()) { + return QString(); + } + + // Set the correct indentation. 9 chars in this case + QString pad; + pad.fill(QChar::fromLatin1(' '), 9); + + // Save the default value + QString yaml = QString::fromStdString("\n - \""); + Base::Quantity quantity = getDefault().value(); + yaml += quantity.getUserString(); + yaml += QString::fromStdString("\"\n"); + + // Next the array contents + yaml += QString::fromStdString(" - ["); + bool firstRow = true; + for (auto row : _rows) { + if (!firstRow) { + // Each row is on its own line, padded for correct indentation + yaml += QString::fromStdString(",\n") + pad; + } + else { + firstRow = false; + } + yaml += QString::fromStdString("["); + + bool first = true; + for (auto column : *row) { + if (!first) { + // TODO: Fix for arrays with too many columns to fit on a single line + yaml += QString::fromStdString(", "); + } + else { + first = false; + } + yaml += QString::fromStdString("\""); + Base::Quantity quantity = column.value(); + yaml += quantity.getUserString(); + yaml += QString::fromStdString("\""); + } + + yaml += QString::fromStdString("]"); + } + yaml += QString::fromStdString("]"); + return yaml; +} + //=== +TYPESYSTEM_SOURCE(Materials::Material3DArray, Materials::MaterialValue) + Material3DArray::Material3DArray() - : MaterialValue(Array3D) + : MaterialValue(Array3D, Array3D) , _defaultSet(false) -{} - -MaterialValue Material3DArray::getDefault() const + , _currentDepth(0) { - MaterialValue ret(_valueType); - ret.setValue(_value); - return ret; + // Initialize separatelt to prevent recursion + // setType(Array3D); } -const std::vector*>& Material3DArray::getTable(const QVariant& depth) const +bool Material3DArray::isNull() const +{ + return depth() <= 0; +} + +const QVariant Material3DArray::getDefault() const +{ + return _value; +} + +const std::shared_ptr>>>& +Material3DArray::getTable(const Base::Quantity& depth) const +{ + for (auto it = _rowMap.begin(); it != _rowMap.end(); it++) { + if (std::get<0>(*it) == depth) { + return std::get<1>(*it); + } + } + + throw InvalidDepth(); +} + +const std::shared_ptr>>>& +Material3DArray::getTable(int depthIndex) const { try { - return _rowMap.at(depth); + return std::get<1>(_rowMap.at(depthIndex)); + } + catch (std::out_of_range const&) { + throw InvalidDepth(); + } +} + +const std::shared_ptr> Material3DArray::getRow(int depth, int row) const +{ + try { + return getTable(depth)->at(row); } catch (std::out_of_range const&) { throw InvalidRow(); } } -const std::vector& Material3DArray::getRow(const QVariant& depth, int row) const +std::shared_ptr> Material3DArray::getRow(int row) const +{ + // Check if we can convert otherwise throw error + return getRow(_currentDepth, row); +} + +std::shared_ptr> Material3DArray::getRow(int depth, int row) { try { - return *(_rowMap.at(depth).at(row)); + return getTable(depth)->at(row); } catch (std::out_of_range const&) { throw InvalidRow(); } } -const std::vector& Material3DArray::getRow(int row) const +std::shared_ptr> Material3DArray::getRow(int row) { - return getRow(getDefault().getValue().toString(), row); + return getRow(_currentDepth, row); } -std::vector& Material3DArray::getRow(const QVariant& depth, int row) +void Material3DArray::addRow(int depth, std::shared_ptr> row) { try { - return *(_rowMap.at(depth).at(row)); + getTable(depth)->push_back(row); } catch (std::out_of_range const&) { throw InvalidRow(); } } -std::vector& Material3DArray::getRow(int row) +void Material3DArray::addRow(std::shared_ptr> row) { - return getRow(getDefault().getValue().toString(), row); + addRow(_currentDepth, row); } -void Material3DArray::addRow(const QVariant& depth, std::vector* row) +int Material3DArray::addDepth(int depth, Base::Quantity value) { - _rowMap[depth].push_back(row); + if (depth == this->depth()) { + // Append to the end + return addDepth(value); + } + else if (depth > this->depth()) { + throw InvalidDepth(); + } + auto rowVector = std::make_shared>>>(); + auto entry = std::make_pair(value, rowVector); + _rowMap.insert(_rowMap.begin() + depth, entry); + + return depth; } -void Material3DArray::deleteRow(const QVariant& depth, int row) +int Material3DArray::addDepth(Base::Quantity value) { - Q_UNUSED(depth) - Q_UNUSED(row) + auto rowVector = std::make_shared>>>(); + auto entry = std::make_pair(value, rowVector); + _rowMap.push_back(entry); + + return depth() - 1; +} + +void Material3DArray::deleteDepth(int depth) +{ + deleteRows(depth); // This may throw an InvalidDepth + _rowMap.erase(_rowMap.begin() + depth); +} + +void Material3DArray::insertRow(int depth, + int row, + std::shared_ptr> rowData) +{ + try { + auto table = getTable(depth); + // auto it = table->begin(); + // std::advance(it, row); + table->insert(table->begin() + row, rowData); + } + catch (std::out_of_range const&) { + throw InvalidRow(); + } +} + +void Material3DArray::insertRow(int row, std::shared_ptr> rowData) +{ + insertRow(_currentDepth, row, rowData); +} + +void Material3DArray::deleteRow(int depth, int row) +{ + auto table = getTable(depth); + if (static_cast(row) >= table->size() || row < 0) { + throw InvalidRow(); + } + table->erase(table->begin() + row); +} + +void Material3DArray::deleteRow(int row) +{ + deleteRow(_currentDepth, row); } void Material3DArray::deleteRows(int depth) { - Q_UNUSED(depth) + auto table = getTable(depth); + table->clear(); } -void Material3DArray::setValue(const QVariant& depth, int row, int column, const QVariant& value) +void Material3DArray::deleteRows() { - Q_UNUSED(depth) - Q_UNUSED(row) - Q_UNUSED(column) - Q_UNUSED(value) + deleteRows(_currentDepth); } -void Material3DArray::setValue(int row, int column, const QVariant& value) +int Material3DArray::rows(int depth) const { - Q_UNUSED(row) - Q_UNUSED(column) - Q_UNUSED(value) + if (depth < 0 || (depth == 0 && this->depth() == 0)) { + return 0; + } + + return getTable(depth)->size(); } -const QVariant Material3DArray::getValue(const QVariant& depth, int row, int column) +int Material3DArray::columns(int depth) const +{ + if (depth < 0 || (depth == 0 && this->depth() == 0)) { + return 0; + } + if (rows() == 0) { + return 0; + } + + return getTable(depth)->at(0)->size(); +} + +void Material3DArray::setValue(int depth, int row, int column, const Base::Quantity& value) { auto val = getRow(depth, row); try { - return val.at(column); + val->at(column) = value; } catch (std::out_of_range const&) { throw InvalidColumn(); } } -const QVariant Material3DArray::getValue(int row, int column) +void Material3DArray::setValue(int row, int column, const Base::Quantity& value) { - return getValue(getDefault().getValue().toString(), row, column); + setValue(_currentDepth, row, column, value); +} + +void Material3DArray::setDepthValue(int depth, const Base::Quantity& value) +{ + try { + auto oldRows = getTable(depth); + _rowMap.at(depth) = std::pair(value, oldRows); + } + catch (std::out_of_range const&) { + throw InvalidRow(); + } +} + +void Material3DArray::setDepthValue(const Base::Quantity& value) +{ + setDepthValue(_currentDepth, value); +} + + +const Base::Quantity Material3DArray::getValue(int depth, int row, int column) const +{ + auto val = getRow(depth, row); + try { + return val->at(column); + } + catch (std::out_of_range const&) { + throw InvalidColumn(); + } +} + +const Base::Quantity Material3DArray::getValue(int row, int column) const +{ + return getValue(_currentDepth, row, column); +} + +const Base::Quantity Material3DArray::getDepthValue(int depth) const +{ + try { + return std::get<0>(_rowMap.at(depth)); + } + catch (std::out_of_range const&) { + throw InvalidRow(); + } +} + +int Material3DArray::currentDepth() const +{ + return _currentDepth; +} + +void Material3DArray::setCurrentDepth(int depth) +{ + if (depth < 0 || _rowMap.size() == 0) { + _currentDepth = 0; + } + else if (static_cast(depth) >= _rowMap.size()) { + _currentDepth = _rowMap.size() - 1; + } + else { + _currentDepth = depth; + } +} + +const QString Material3DArray::getYAMLString() const +{ + if (isNull()) { + return QString(); + } + + // Set the correct indentation. 7 chars + name length + QString pad; + pad.fill(QChar::fromLatin1(' '), 9); + + // Save the default value + QString yaml = QString::fromStdString("\n - \""); + Base::Quantity quantity = getDefault().value(); + yaml += quantity.getUserString(); + yaml += QString::fromStdString("\"\n"); + + // Next the array contents + yaml += QString::fromStdString(" - ["); + for (int depth = 0; depth < this->depth(); depth++) { + if (depth > 0) { + // Each row is on its own line, padded for correct indentation + yaml += QString::fromStdString(",\n") + pad; + } + + yaml += QString::fromStdString("\""); + auto value = getDepthValue(depth).getUserString(); + yaml += value; + yaml += QString::fromStdString("\": ["); + + QString pad2; + pad2.fill(QChar::fromLatin1(' '), 14 + value.length()); + + bool firstRow = true; + auto rows = getTable(depth); + for (auto row : *rows) { + if (!firstRow) { + // Each row is on its own line, padded for correct indentation + yaml += QString::fromStdString(",\n") + pad2; + } + else { + firstRow = false; + } + yaml += QString::fromStdString("["); + + bool first = true; + for (auto column : *row) { + if (!first) { + // TODO: Fix for arrays with too many columns to fit on a single line + yaml += QString::fromStdString(", "); + } + else { + first = false; + } + yaml += QString::fromStdString("\""); + // Base::Quantity quantity = column.value(); + yaml += column.getUserString(); + yaml += QString::fromStdString("\""); + } + + yaml += QString::fromStdString("]"); + } + yaml += QString::fromStdString("]"); + } + yaml += QString::fromStdString("]"); + return yaml; } diff --git a/src/Mod/Material/App/MaterialValue.h b/src/Mod/Material/App/MaterialValue.h index 409c137d30..8f1559ed31 100644 --- a/src/Mod/Material/App/MaterialValue.h +++ b/src/Mod/Material/App/MaterialValue.h @@ -22,15 +22,22 @@ #ifndef MATERIAL_MATERIALVALUE_H #define MATERIAL_MATERIALVALUE_H -#include +#include +#include #include +#include + +#include + namespace Materials { -class MaterialsExport MaterialValue +class MaterialsExport MaterialValue: public Base::BaseClass { + TYPESYSTEM_HEADER(); + public: enum ValueType { @@ -50,9 +57,17 @@ public: URL = 13 }; MaterialValue(); - explicit MaterialValue(ValueType type); + MaterialValue(const MaterialValue& other); + MaterialValue(ValueType type); virtual ~MaterialValue() = default; + MaterialValue& operator=(const MaterialValue& other); + virtual bool operator==(const MaterialValue& other) const; + bool operator!=(const MaterialValue& other) const + { + return !operator==(other); + } + ValueType getType() const { return _valueType; @@ -62,10 +77,8 @@ public: { return _value; } - bool isNull() const - { - return _value.isNull(); - } + virtual bool isNull() const; + virtual const QVariant getValueAt(const QVariant& value) const { Q_UNUSED(value); @@ -76,126 +89,182 @@ public: _value = value; } + virtual const QString getYAMLString() const; + protected: - ValueType _valueType; - QVariant _value; + MaterialValue(ValueType type, ValueType inherited); void setType(ValueType type) { _valueType = type; } + void setInitialValue(ValueType inherited); + + ValueType _valueType; + QVariant _value; }; class MaterialsExport Material2DArray: public MaterialValue { + TYPESYSTEM_HEADER_WITH_OVERRIDE(); + public: Material2DArray(); + Material2DArray(const Material2DArray& other); ~Material2DArray() override = default; - void setDefault(MaterialValue value) + Material2DArray& operator=(const Material2DArray& other); + + bool isNull() const override; + + void setDefault(MaterialValue value, bool markSet = true) { _value = value.getValue(); - _defaultSet = true; + _defaultSet = markSet; } - void setDefault(const QVariant& value) + void setDefault(const QVariant& value, bool markSet = true) { _value = value; - _defaultSet = true; + _defaultSet = markSet; } - MaterialValue getDefault() const; + void setDefault(const Base::Quantity& value, bool markSet = true) + { + _value = QVariant::fromValue(value); + _defaultSet = markSet; + } + const QVariant getDefault() const; bool defaultSet() const { return _defaultSet; } - const std::vector* getRow(int row) const; - std::vector* getRow(int row); + std::shared_ptr> getRow(int row) const; + std::shared_ptr> getRow(int row); int rows() const { return _rows.size(); } - void addRow(std::vector* row); - void insertRow(int index, std::vector* row); + int columns() const + { + if (rows() == 0) { + return 0; + } + + return _rows.at(0)->size(); + } + void addRow(std::shared_ptr> row); + void insertRow(int index, std::shared_ptr> row); void deleteRow(int row); void setValue(int row, int column, const QVariant& value); const QVariant getValue(int row, int column) const; + const QString getYAMLString() const override; + protected: - std::vector*> _rows; + void deepCopy(const Material2DArray& other); + + std::vector>> _rows; bool _defaultSet; private: - void dumpRow(const std::vector& row) const; + void dumpRow(std::shared_ptr> row) const; void dump() const; }; class MaterialsExport Material3DArray: public MaterialValue { + TYPESYSTEM_HEADER_WITH_OVERRIDE(); + public: Material3DArray(); ~Material3DArray() override = default; - void setDefault(MaterialValue value) + bool isNull() const override; + + void setDefault(MaterialValue value, bool markSet = true) { _value = value.getValue(); - _defaultSet = true; + _defaultSet = markSet; } - void setDefault(const QVariant& value) + void setDefault(const QVariant& value, bool markSet = true) { _value = value; - _defaultSet = true; + _defaultSet = markSet; } - MaterialValue getDefault() const; + void setDefault(const Base::Quantity& value, bool markSet = true) + { + _value = QVariant::fromValue(value); + _defaultSet = markSet; + } + const QVariant getDefault() const; bool defaultSet() const { return _defaultSet; } - const std::vector*>& getTable(const QVariant& depth) const; - const std::vector& getRow(const QVariant& depth, int row) const; - const std::vector& getRow(int row) const; - std::vector& getRow(const QVariant& depth, int row); - std::vector& getRow(int row); - void addRow(const QVariant& depth, std::vector* row); - void deleteRow(const QVariant& depth, int row); + const std::shared_ptr>>>& + getTable(const Base::Quantity& depth) const; + const std::shared_ptr>>>& + getTable(int depthIndex) const; + const std::shared_ptr> getRow(int depth, int row) const; + std::shared_ptr> getRow(int row) const; + std::shared_ptr> getRow(int depth, int row); + std::shared_ptr> getRow(int row); + void addRow(int depth, std::shared_ptr> row); + void addRow(std::shared_ptr> row); + int addDepth(int depth, Base::Quantity value); + int addDepth(Base::Quantity value); + void deleteDepth(int depth); + void insertRow(int depth, int row, std::shared_ptr> rowData); + void insertRow(int row, std::shared_ptr> rowData); + void deleteRow(int depth, int row); + void deleteRow(int row); void deleteRows(int depth); + void deleteRows(); int depth() const { return _rowMap.size(); } - int rows(const QVariant& depth) const + int rows(int depth) const; + int rows() const { - return getTable(depth).size(); + return rows(_currentDepth); + } + int columns(int depth) const; + int columns() const + { + return columns(_currentDepth); } - void setValue(const QVariant& depth, int row, int column, const QVariant& value); - void setValue(int row, int column, const QVariant& value); - const QVariant getValue(const QVariant& depth, int row, int column); - const QVariant getValue(int row, int column); + void setValue(int depth, int row, int column, const Base::Quantity& value); + void setValue(int row, int column, const Base::Quantity& value); + void setDepthValue(int depth, const Base::Quantity& value); + void setDepthValue(const Base::Quantity& value); + const Base::Quantity getValue(int depth, int row, int column) const; + const Base::Quantity getValue(int row, int column) const; + const Base::Quantity getDepthValue(int depth) const; + + int currentDepth() const; + void setCurrentDepth(int depth); + + const QString getYAMLString() const override; protected: -#if QT_VERSION < QT_VERSION_CHECK(6,0,0) - std::map*>> _rowMap; -#else - struct variant_comp - { - bool operator()(const QVariant& var1, - const QVariant& var2) const - { - return QVariant::compare(var1, var2) == QPartialOrdering::Less; - } - }; - std::map*>, variant_comp> _rowMap; -#endif - + std::vector< + std::pair>>>>> + _rowMap; bool _defaultSet; + int _currentDepth; }; } // namespace Materials Q_DECLARE_METATYPE(Materials::MaterialValue) -Q_DECLARE_METATYPE(Materials::Material2DArray) -Q_DECLARE_METATYPE(Materials::Material3DArray) +// Q_DECLARE_METATYPE(Materials::Material2DArray) +Q_DECLARE_METATYPE(std::shared_ptr) +// Q_DECLARE_METATYPE(Materials::Material3DArray) +Q_DECLARE_METATYPE(std::shared_ptr) #endif // MATERIAL_MATERIALVALUE_H diff --git a/src/Mod/Material/App/Materials.cpp b/src/Mod/Material/App/Materials.cpp index a2c3b23add..2ea280d8c4 100644 --- a/src/Mod/Material/App/Materials.cpp +++ b/src/Mod/Material/App/Materials.cpp @@ -29,8 +29,10 @@ #include #include -#include "MaterialManager.h" #include "Materials.h" + +#include "MaterialLibrary.h" +#include "MaterialManager.h" #include "ModelManager.h" @@ -58,10 +60,25 @@ MaterialProperty::MaterialProperty(const ModelProperty& property) } if (_valuePtr->getType() == MaterialValue::Array2D) { - std::static_pointer_cast(_valuePtr)->setDefault(getColumnNull(0)); + std::static_pointer_cast(_valuePtr)->setDefault(getColumnNull(0), false); } else if (_valuePtr->getType() == MaterialValue::Array3D) { - std::static_pointer_cast(_valuePtr)->setDefault(getColumnNull(0)); + std::static_pointer_cast(_valuePtr)->setDefault(getColumnNull(0), false); + } +} + +void MaterialProperty::copyValuePtr(std::shared_ptr value) +{ + if (value->getType() == MaterialValue::Array2D) { + _valuePtr = + std::make_shared(*(std::static_pointer_cast(value))); + } + else if (value->getType() == MaterialValue::Array3D) { + _valuePtr = + std::make_shared(*(std::static_pointer_cast(value))); + } + else { + _valuePtr = std::make_shared(*value); } } @@ -69,20 +86,16 @@ MaterialProperty::MaterialProperty(const MaterialProperty& other) : ModelProperty(other) { _modelUUID = other._modelUUID; - if (other._valuePtr != nullptr) { - _valuePtr = std::make_shared(*(other._valuePtr)); - } - else { - _valuePtr = nullptr; - } + copyValuePtr(other._valuePtr); for (auto it = other._columns.begin(); it != other._columns.end(); it++) { _columns.push_back(*it); } } -// MaterialProperty::~MaterialProperty() -// {} +MaterialProperty::MaterialProperty(std::shared_ptr other) + : MaterialProperty(*other) +{} void MaterialProperty::setModelUUID(const QString& uuid) { @@ -106,13 +119,28 @@ const std::shared_ptr MaterialProperty::getMaterialValue() const const QString MaterialProperty::getString() const { + if (isNull()) { + return QString(); + } if (getType() == MaterialValue::Quantity) { Base::Quantity quantity = getValue().value(); return quantity.getUserString(); } + else if (getType() == MaterialValue::Float) { + auto value = getValue(); + if (value.isNull()) { + return QString(); + } + return QString(QString::fromStdString("%1")).arg(value.toFloat(), 0, 'g', 6); + } return getValue().toString(); } +const QString MaterialProperty::getYAMLString() const +{ + return _valuePtr->getYAMLString(); +} + void MaterialProperty::setPropertyType(const QString& type) { ModelProperty::setPropertyType(type); @@ -229,7 +257,6 @@ QVariant MaterialProperty::getColumnNull(int column) const void MaterialProperty::setValue(const QVariant& value) { - // _valueType = MaterialValue::String; _valuePtr->setValue(value); } @@ -247,13 +274,21 @@ void MaterialProperty::setValue(const QString& value) else if (_valuePtr->getType() == MaterialValue::URL) { setURL(value); } + else if (_valuePtr->getType() == MaterialValue::Array2D) { + //_valuePtr->setValue(QVariant(std::make_shared())); + } + else if (_valuePtr->getType() == MaterialValue::Array3D) { + //_valuePtr = std::make_shared(); + } else if (_valuePtr->getType() == MaterialValue::Quantity) { // Base::Console().Log("\tParse quantity '%s'\n", value.toStdString().c_str()); try { setQuantity(Base::Quantity::parse(value)); } catch (const Base::ParserError& e) { - Base::Console().Log("Error '%s'\n", e.what()); + Base::Console().Log("MaterialProperty::setValue Error '%s' - '%s'\n", + e.what(), + value.toStdString().c_str()); // Save as a string setString(value); } @@ -263,6 +298,11 @@ void MaterialProperty::setValue(const QString& value) } } +void MaterialProperty::setValue(std::shared_ptr value) +{ + _valuePtr = value; +} + void MaterialProperty::setString(const QString& value) { // _valueType = MaterialValue::String; @@ -346,14 +386,9 @@ MaterialProperty& MaterialProperty::operator=(const MaterialProperty& other) } ModelProperty::operator=(other); - _modelUUID = other._modelUUID; - if (other._valuePtr != nullptr) { - _valuePtr = std::make_shared(*(other._valuePtr)); - } - else { - _valuePtr = nullptr; - } + _modelUUID = other._modelUUID; + copyValuePtr(other._valuePtr); _columns.clear(); for (auto it = other._columns.begin(); it != other._columns.end(); it++) { @@ -363,13 +398,26 @@ MaterialProperty& MaterialProperty::operator=(const MaterialProperty& other) return *this; } +bool MaterialProperty::operator==(const MaterialProperty& other) const +{ + if (this == &other) { + return true; + } + + if (ModelProperty::operator==(other)) { + return (*_valuePtr == *other._valuePtr); + } + return false; +} + TYPESYSTEM_SOURCE(Materials::Material, Base::BaseClass) Material::Material() : _dereferenced(false) + , _editState(ModelEdit_None) {} -Material::Material(const MaterialLibrary& library, +Material::Material(std::shared_ptr library, const QString& directory, const QString& uuid, const QString& name) @@ -387,7 +435,8 @@ Material::Material(const Material& other) , _directory(other._directory) , _uuid(other._uuid) , _name(other._name) - , _authorAndLicense(other._authorAndLicense) + , _author(other._author) + , _license(other._license) , _parentUuid(other._parentUuid) , _description(other._description) , _url(other._url) @@ -408,19 +457,31 @@ Material::Material(const Material& other) _allUuids.push_back(*it); } for (auto it = other._physical.begin(); it != other._physical.end(); it++) { - _physical[it->first] = MaterialProperty(it->second); + MaterialProperty prop = it->second; + _physical[it->first] = std::make_shared(prop); } for (auto it = other._appearance.begin(); it != other._appearance.end(); it++) { - _appearance[it->first] = MaterialProperty(it->second); + MaterialProperty prop = it->second; + _appearance[it->first] = std::make_shared(prop); } } -/* - * Destroys the object and frees any allocated resources - */ -Material::~Material() +const QString Material::getAuthorAndLicense() const { - // no need to delete child widgets, Qt does it all for us + QString authorAndLicense; + + // Combine the author and license field for backwards compatibility + if (!_author.isNull()) { + authorAndLicense = _author; + if (!_license.isNull()) { + authorAndLicense += QString::fromStdString(" ") + _license; + } + } + else if (!_license.isNull()) { + authorAndLicense = _license; + } + + return _license; } void Material::addModel(const QString& uuid) @@ -431,13 +492,13 @@ void Material::addModel(const QString& uuid) } } - _allUuids.push_back(uuid); + _allUuids << uuid; ModelManager manager; try { - const Model& model = manager.getModel(uuid); - auto inheritance = model.getInheritance(); + auto model = manager.getModel(uuid); + auto inheritance = model->getInheritance(); for (auto inherits = inheritance.begin(); inherits != inheritance.end(); inherits++) { addModel(*inherits); } @@ -446,6 +507,62 @@ void Material::addModel(const QString& uuid) } } +void Material::removeModel(const QString& uuid) +{ + Q_UNUSED(uuid); +} + +void Material::clearModels() +{ + _physicalUuids.clear(); + _appearanceUuids.clear(); + _allUuids.clear(); + _physical.clear(); + _appearance.clear(); +} + +void Material::setName(const QString& name) +{ + _name = name; + setEditStateExtend(); +} + +void Material::setAuthor(const QString& author) +{ + _author = author; + setEditStateExtend(); +} + +void Material::setLicense(const QString& license) +{ + _license = license; + setEditStateExtend(); +} + +void Material::setParentUUID(const QString& uuid) +{ + _parentUuid = uuid; + setEditStateExtend(); +} + +void Material::setDescription(const QString& description) +{ + _description = description; + setEditStateExtend(); +} + +void Material::setURL(const QString& url) +{ + _url = url; + setEditStateExtend(); +} + +void Material::setReference(const QString& reference) +{ + _reference = reference; + setEditStateExtend(); +} + void Material::setEditState(ModelEdit newState) { if (newState == ModelEdit_Extend) { @@ -458,6 +575,11 @@ void Material::setEditState(ModelEdit newState) } } +void Material::removeUUID(QStringList& uuidList, const QString& uuid) +{ + uuidList.removeAll(uuid); +} + void Material::addPhysical(const QString& uuid) { if (hasPhysicalModel(uuid)) { @@ -467,23 +589,32 @@ void Material::addPhysical(const QString& uuid) ModelManager manager; try { - const Model& model = manager.getModel(uuid); + auto model = manager.getModel(uuid); + + auto& inheritance = model->getInheritance(); + for (auto it = inheritance.begin(); it != inheritance.end(); it++) { + // Inherited models may already have the properties, so just + // remove the uuid + removeUUID(_physicalUuids, *it); + } _physicalUuids.push_back(uuid); addModel(uuid); setEditStateExtend(); - for (auto it = model.begin(); it != model.end(); it++) { + for (auto it = model->begin(); it != model->end(); it++) { QString propertyName = it->first; - ModelProperty property = static_cast(it->second); + if (!hasPhysicalProperty(propertyName)) { + ModelProperty property = static_cast(it->second); - try { - _physical[propertyName] = MaterialProperty(property); - } - catch (const UnknownValueType&) { - Base::Console().Error("Property '%s' has unknown type '%s'. Ignoring\n", - property.getName().toStdString().c_str(), - property.getPropertyType().toStdString().c_str()); + try { + _physical[propertyName] = std::make_shared(property); + } + catch (const UnknownValueType&) { + Base::Console().Error("Property '%s' has unknown type '%s'. Ignoring\n", + property.getName().toStdString().c_str(), + property.getPropertyType().toStdString().c_str()); + } } } } @@ -491,6 +622,47 @@ void Material::addPhysical(const QString& uuid) } } +void Material::removePhysical(const QString& uuid) +{ + if (!hasPhysicalModel(uuid)) { + return; + } + + // If it's an inherited model, do nothing + bool inherited = true; + for (auto it = _physicalUuids.begin(); it != _physicalUuids.end(); it++) { + if (*it == uuid) { + inherited = false; + break; + } + } + if (inherited) { + return; + } + + ModelManager manager; + + try { + auto model = manager.getModel(uuid); + + auto& inheritance = model->getInheritance(); + for (auto it = inheritance.begin(); it != inheritance.end(); it++) { + removeUUID(_physicalUuids, *it); + removeUUID(_allUuids, *it); + } + removeUUID(_physicalUuids, uuid); + removeUUID(_allUuids, uuid); + + for (auto it = model->begin(); it != model->end(); it++) { + _physical.erase(it->first); + } + + setEditStateAlter(); + } + catch (ModelNotFound const&) { + } +} + void Material::addAppearance(const QString& uuid) { if (hasAppearanceModel(uuid)) { @@ -500,26 +672,86 @@ void Material::addAppearance(const QString& uuid) ModelManager manager; try { - const Model& model = manager.getModel(uuid); + auto model = manager.getModel(uuid); + + auto& inheritance = model->getInheritance(); + for (auto it = inheritance.begin(); it != inheritance.end(); it++) { + // Inherited models may already have the properties, so just + // remove the uuid + removeUUID(_appearanceUuids, *it); + } _appearanceUuids.push_back(uuid); addModel(uuid); setEditStateExtend(); - for (auto it = model.begin(); it != model.end(); it++) { + for (auto it = model->begin(); it != model->end(); it++) { QString propertyName = it->first; - ModelProperty property = static_cast(it->second); + if (!hasAppearanceProperty(propertyName)) { + ModelProperty property = static_cast(it->second); - _appearance[propertyName] = MaterialProperty(property); + _appearance[propertyName] = std::make_shared(property); + } } } catch (ModelNotFound const&) { } } +void Material::removeAppearance(const QString& uuid) +{ + if (!hasAppearanceModel(uuid)) { + return; + } + + // If it's an inherited model, do nothing + bool inherited = true; + for (auto it = _appearanceUuids.begin(); it != _appearanceUuids.end(); it++) { + if (*it == uuid) { + inherited = false; + break; + } + } + if (inherited) { + return; + } + + ModelManager manager; + + try { + auto model = manager.getModel(uuid); + + auto& inheritance = model->getInheritance(); + for (auto it = inheritance.begin(); it != inheritance.end(); it++) { + removeUUID(_appearanceUuids, *it); + removeUUID(_allUuids, *it); + } + removeUUID(_appearanceUuids, uuid); + removeUUID(_allUuids, uuid); + + for (auto it = model->begin(); it != model->end(); it++) { + _appearance.erase(it->first); + } + + setEditStateAlter(); + } + catch (ModelNotFound const&) { + } +} + +void Material::setPropertyEditState(const QString& name) +{ + if (hasPhysicalProperty(name)) { + setPhysicalEditState(name); + } + else if (hasAppearanceProperty(name)) { + setAppearanceEditState(name); + } +} + void Material::setPhysicalEditState(const QString& name) { - if (getPhysicalProperty(name).isNull()) { + if (getPhysicalProperty(name)->isNull()) { setEditStateExtend(); } else { @@ -529,7 +761,7 @@ void Material::setPhysicalEditState(const QString& name) void Material::setAppearanceEditState(const QString& name) { - if (getAppearanceProperty(name).isNull()) { + if (getAppearanceProperty(name)->isNull()) { setEditStateExtend(); } else { @@ -541,38 +773,52 @@ void Material::setPhysicalValue(const QString& name, const QString& value) { setPhysicalEditState(name); - _physical[name].setValue(value); // may not be a string type + _physical[name]->setValue(value); // may not be a string type, conversion may be required } void Material::setPhysicalValue(const QString& name, int value) { setPhysicalEditState(name); - _physical[name].setInt(value); + _physical[name]->setInt(value); } void Material::setPhysicalValue(const QString& name, double value) { setPhysicalEditState(name); - _physical[name].setFloat(value); + _physical[name]->setFloat(value); } void Material::setPhysicalValue(const QString& name, const Base::Quantity value) { setPhysicalEditState(name); - _physical[name].setQuantity(value); + _physical[name]->setQuantity(value); +} + +void Material::setPhysicalValue(const QString& name, std::shared_ptr value) +{ + setPhysicalEditState(name); + + _physical[name]->setValue(value); } void Material::setAppearanceValue(const QString& name, const QString& value) { setAppearanceEditState(name); - _appearance[name].setValue(value); // may not be a string type + _appearance[name]->setValue(value); // may not be a string type, conversion may be required } -MaterialProperty& Material::getPhysicalProperty(const QString& name) +void Material::setAppearanceValue(const QString& name, std::shared_ptr value) +{ + setAppearanceEditState(name); + + _appearance[name]->setValue(value); +} + +std::shared_ptr Material::getPhysicalProperty(const QString& name) { try { return _physical.at(name); @@ -582,7 +828,7 @@ MaterialProperty& Material::getPhysicalProperty(const QString& name) } } -const MaterialProperty& Material::getPhysicalProperty(const QString& name) const +const std::shared_ptr Material::getPhysicalProperty(const QString& name) const { try { return _physical.at(name); @@ -592,7 +838,7 @@ const MaterialProperty& Material::getPhysicalProperty(const QString& name) const } } -MaterialProperty& Material::getAppearanceProperty(const QString& name) +std::shared_ptr Material::getAppearanceProperty(const QString& name) { try { return _appearance.at(name); @@ -602,7 +848,7 @@ MaterialProperty& Material::getAppearanceProperty(const QString& name) } } -const MaterialProperty& Material::getAppearanceProperty(const QString& name) const +const std::shared_ptr Material::getAppearanceProperty(const QString& name) const { try { return _appearance.at(name); @@ -612,29 +858,42 @@ const MaterialProperty& Material::getAppearanceProperty(const QString& name) con } } -const QVariant Material::getValue(const std::map& propertyList, - const QString& name) const +const QVariant +Material::getValue(const std::map>& propertyList, + const QString& name) const { try { - return propertyList.at(name).getValue(); + return propertyList.at(name)->getValue(); } catch (std::out_of_range const&) { throw PropertyNotFound(); } } -const QString Material::getValueString(const std::map& propertyList, - const QString& name) const +const QString +Material::getValueString(const std::map>& propertyList, + const QString& name) const { try { - if (propertyList.at(name).getType() == MaterialValue::Quantity) { - auto value = propertyList.at(name).getValue(); + auto property = propertyList.at(name); + if (property->isNull()) { + return QString(); + } + if (property->getType() == MaterialValue::Quantity) { + auto value = property->getValue(); if (value.isNull()) { return QString(); } return value.value().getUserString(); } - return propertyList.at(name).getValue().toString(); + else if (property->getType() == MaterialValue::Float) { + auto value = property->getValue(); + if (value.isNull()) { + return QString(); + } + return QString(QString::fromStdString("%1")).arg(value.toFloat(), 0, 'g', 6); + } + return property->getValue().toString(); } catch (std::out_of_range const&) { throw PropertyNotFound(); @@ -646,6 +905,11 @@ const QVariant Material::getPhysicalValue(const QString& name) const return getValue(_physical, name); } +const Base::Quantity Material::getPhysicalQuantity(const QString& name) const +{ + return getValue(_physical, name).value(); +} + const QString Material::getPhysicalValueString(const QString& name) const { return getValueString(_physical, name); @@ -656,6 +920,11 @@ const QVariant Material::getAppearanceValue(const QString& name) const return getValue(_appearance, name); } +const Base::Quantity Material::getAppearanceQuantity(const QString& name) const +{ + return getValue(_appearance, name).value(); +} + const QString Material::getAppearanceValueString(const QString& name) const { return getValueString(_appearance, name); @@ -685,13 +954,7 @@ bool Material::hasAppearanceProperty(const QString& name) const bool Material::hasModel(const QString& uuid) const { - for (QString modelUUID : _allUuids) { - if (modelUUID == uuid) { - return true; - } - } - - return false; + return _allUuids.contains(uuid); } bool Material::hasPhysicalModel(const QString& uuid) const @@ -703,8 +966,8 @@ bool Material::hasPhysicalModel(const QString& uuid) const ModelManager manager; try { - const Model& model = manager.getModel(uuid); - if (model.getType() == Model::ModelType_Physical) { + auto model = manager.getModel(uuid); + if (model->getType() == Model::ModelType_Physical) { return true; } } @@ -723,8 +986,8 @@ bool Material::hasAppearanceModel(const QString& uuid) const ModelManager manager; try { - const Model& model = manager.getModel(uuid); - if (model.getType() == Model::ModelType_Appearance) { + auto model = manager.getModel(uuid); + if (model->getType() == Model::ModelType_Appearance) { return true; } } @@ -743,12 +1006,12 @@ bool Material::isPhysicalModelComplete(const QString& uuid) const ModelManager manager; try { - const Model& model = manager.getModel(uuid); - for (auto it = model.begin(); it != model.end(); it++) { + auto model = manager.getModel(uuid); + for (auto it = model->begin(); it != model->end(); it++) { QString propertyName = it->first; - const MaterialProperty& property = getPhysicalProperty(propertyName); + auto property = getPhysicalProperty(propertyName); - if (property.isNull()) { + if (property->isNull()) { return false; } } @@ -769,12 +1032,12 @@ bool Material::isAppearanceModelComplete(const QString& uuid) const ModelManager manager; try { - const Model& model = manager.getModel(uuid); - for (auto it = model.begin(); it != model.end(); it++) { + auto model = manager.getModel(uuid); + for (auto it = model->begin(); it != model->end(); it++) { QString propertyName = it->first; - const MaterialProperty& property = getAppearanceProperty(propertyName); + auto property = getAppearanceProperty(propertyName); - if (property.isNull()) { + if (property->isNull()) { return false; } } @@ -791,8 +1054,11 @@ void Material::saveGeneral(QTextStream& stream) const stream << "General:\n"; stream << " UUID: \"" << _uuid << "\"\n"; stream << " Name: \"" << _name << "\"\n"; - if (!_authorAndLicense.isEmpty()) { - stream << " AuthorAndLicense: \"" << _authorAndLicense << "\"\n"; + if (!_author.isEmpty()) { + stream << " Author: \"" << _author << "\"\n"; + } + if (!_license.isEmpty()) { + stream << " License: \"" << _license << "\"\n"; } if (!_description.isEmpty()) { stream << " Description: \"" << _description << "\"\n"; @@ -810,52 +1076,157 @@ void Material::saveInherits(QTextStream& stream) const if (!_parentUuid.isEmpty()) { MaterialManager manager; - stream << "Inherits:\n"; - stream << " " << manager.getMaterial(_parentUuid).getName() << ":\n"; - stream << " UUID: \"" << _parentUuid << "\"\n"; + try { + auto material = manager.getMaterial(_parentUuid); + + stream << "Inherits:\n"; + stream << " " << material->getName() << ":\n"; + stream << " UUID: \"" << _parentUuid << "\"\n"; + } + catch (const MaterialNotFound&) { + } } } -void Material::saveModels(QTextStream& stream) const +bool Material::modelChanged(const std::shared_ptr parent, + const std::shared_ptr model) const +{ + for (auto itp = model->begin(); itp != model->end(); itp++) { + QString propertyName = itp->first; + auto property = getPhysicalProperty(propertyName); + try { + auto parentProperty = parent->getPhysicalProperty(propertyName); + + if (*property != *parentProperty) { + return true; + } + } + catch (const PropertyNotFound&) { + return true; + } + } + + return false; +} + +bool Material::modelAppearanceChanged(const std::shared_ptr parent, + const std::shared_ptr model) const +{ + for (auto itp = model->begin(); itp != model->end(); itp++) { + QString propertyName = itp->first; + auto property = getAppearanceProperty(propertyName); + try { + auto parentProperty = parent->getAppearanceProperty(propertyName); + + if (*property != *parentProperty) { + return true; + } + } + catch (const PropertyNotFound&) { + return true; + } + } + + return false; +} + +void Material::saveModels(QTextStream& stream, bool saveInherited) const { if (!_physical.empty()) { ModelManager modelManager; + MaterialManager materialManager; - stream << "Models:\n"; + bool inherited = saveInherited && (_parentUuid.size() > 0); + std::shared_ptr parent; + if (inherited) { + try { + parent = materialManager.getMaterial(_parentUuid); + } + catch (const MaterialNotFound&) { + inherited = false; + } + } + + bool headerPrinted = false; for (auto itm = _physicalUuids.begin(); itm != _physicalUuids.end(); itm++) { auto model = modelManager.getModel(*itm); - stream << " " << model.getName() << ":\n"; - stream << " UUID: \"" << model.getUUID() << "\"\n"; - for (auto itp = model.begin(); itp != model.end(); itp++) { - QString propertyName = itp->first; - const MaterialProperty& property = getPhysicalProperty(propertyName); + if (!inherited || modelChanged(parent, model)) { + if (!headerPrinted) { + stream << "Models:\n"; + headerPrinted = true; + } + stream << " " << model->getName() << ":\n"; + stream << " UUID: \"" << model->getUUID() << "\"\n"; + for (auto itp = model->begin(); itp != model->end(); itp++) { + QString propertyName = itp->first; + std::shared_ptr property = getPhysicalProperty(propertyName); + std::shared_ptr parentProperty; + try { + if (inherited) { + parentProperty = parent->getPhysicalProperty(propertyName); + } + } + catch (const PropertyNotFound&) { + Base::Console().Log("Material::saveModels Property not found '%s'\n", + propertyName.toStdString().c_str()); + } - if (!property.isNull()) { - stream << " " << propertyName << ": \"" - << getPhysicalValueString(propertyName) << "\"\n"; + if (!inherited || (*property != *parentProperty)) { + if (!property->isNull()) { + stream << " " << *property << "\n"; + } + } } } } } } -void Material::saveAppearanceModels(QTextStream& stream) const +void Material::saveAppearanceModels(QTextStream& stream, bool saveInherited) const { if (!_appearance.empty()) { ModelManager modelManager; + MaterialManager materialManager; - stream << "AppearanceModels:\n"; + bool inherited = saveInherited && (_parentUuid.size() > 0); + std::shared_ptr parent; + if (inherited) { + try { + parent = materialManager.getMaterial(_parentUuid); + } + catch (const MaterialNotFound&) { + inherited = false; + } + } + + bool headerPrinted = false; for (auto itm = _appearanceUuids.begin(); itm != _appearanceUuids.end(); itm++) { auto model = modelManager.getModel(*itm); - stream << " " << model.getName() << ":\n"; - stream << " UUID: \"" << model.getUUID() << "\"\n"; - for (auto itp = model.begin(); itp != model.end(); itp++) { - QString propertyName = itp->first; - const MaterialProperty& property = getAppearanceProperty(propertyName); + if (!inherited || modelAppearanceChanged(parent, model)) { + if (!headerPrinted) { + stream << "AppearanceModels:\n"; + headerPrinted = true; + } + stream << " " << model->getName() << ":\n"; + stream << " UUID: \"" << model->getUUID() << "\"\n"; + for (auto itp = model->begin(); itp != model->end(); itp++) { + QString propertyName = itp->first; + std::shared_ptr property = + getAppearanceProperty(propertyName); + std::shared_ptr parentProperty; + try { + if (inherited) { + parentProperty = parent->getAppearanceProperty(propertyName); + } + } + catch (const PropertyNotFound&) { + } - if (!property.isNull()) { - stream << " " << propertyName << ": \"" - << getAppearanceValueString(propertyName) << "\"\n"; + if (!inherited || (*property != *parentProperty)) { + if (!property->isNull()) { + stream << " " << *property << "\n"; + } + } } } } @@ -867,15 +1238,57 @@ void Material::newUuid() _uuid = QUuid::createUuid().toString(QUuid::WithoutBraces); } -void Material::save(QTextStream& stream, bool saveAsCopy) +QString Material::getModelByName(const QString& name) const { - Q_UNUSED(saveAsCopy) + ModelManager manager; - stream << "# File created by FreeCAD\n"; + for (auto it = _allUuids.begin(); it != _allUuids.end(); it++) { + try { + auto model = manager.getModel(*it); + if (model->getName() == name) { + return *it; + } + } + catch (ModelNotFound const&) { + } + } + + return QString(); +} + +void Material::save(QTextStream& stream, bool saveAsCopy, bool saveInherited) +{ + if (saveInherited && !saveAsCopy) { + // Check to see if we're an original or if we're already in the list of models + MaterialManager materialManager; + if (materialManager.exists(_uuid)) { + // Make a new version based on the current + setParentUUID(_uuid); + newUuid(); + } + } + + if (saveAsCopy) { + // Save it in the same format as the parent + if (_parentUuid.isEmpty()) { + saveInherited = false; + } + else { + saveInherited = true; + } + } + + stream << "---\n"; + stream << "# File created by " << QString::fromStdString(App::Application::Config()["ExeName"]) + << " " << QString::fromStdString(App::Application::Config()["ExeVersion"]) + << " Revision: " << QString::fromStdString(App::Application::Config()["BuildRevision"]) + << "\n"; saveGeneral(stream); - saveInherits(stream); - saveModels(stream); - saveAppearanceModels(stream); + if (saveInherited) { + saveInherits(stream); + } + saveModels(stream, saveInherited); + saveAppearanceModels(stream, saveInherited); } Material& Material::operator=(const Material& other) @@ -888,12 +1301,14 @@ Material& Material::operator=(const Material& other) _directory = other._directory; _uuid = other._uuid; _name = other._name; - _authorAndLicense = other._authorAndLicense; + _author = other._author; + _license = other._license; _parentUuid = other._parentUuid; _description = other._description; _url = other._url; _reference = other._reference; _dereferenced = other._dereferenced; + _editState = other._editState; _tags.clear(); for (auto it = other._tags.begin(); it != other._tags.end(); it++) { @@ -911,14 +1326,92 @@ Material& Material::operator=(const Material& other) for (auto it = other._allUuids.begin(); it != other._allUuids.end(); it++) { _allUuids.push_back(*it); } + + // Create copies of the properties rather than modify the originals _physical.clear(); for (auto it = other._physical.begin(); it != other._physical.end(); it++) { - _physical[it->first] = MaterialProperty(it->second); + MaterialProperty prop = it->second; + _physical[it->first] = std::make_shared(prop); } _appearance.clear(); for (auto it = other._appearance.begin(); it != other._appearance.end(); it++) { - _appearance[it->first] = MaterialProperty(it->second); + MaterialProperty prop = it->second; + _appearance[it->first] = std::make_shared(prop); } return *this; } + +/* + * Normalize models by removing any inherited models + */ +QStringList Material::normalizeModels(const QStringList& models) +{ + QStringList normalized; + + ModelManager manager; + + for (auto uuid : models) { + auto model = manager.getModel(uuid); + + bool found = false; + for (auto childUuid : models) { + if (uuid != childUuid) { + auto childModel = manager.getModel(childUuid); + if (childModel->inherits(childUuid)) { + // We're an inherited model + found = true; + break; + } + } + } + if (!found) { + normalized << uuid; + } + } + + return normalized; +} + +/* + * Set or change the base material for the current material, updating the properties as + * required. + */ +void Material::updateInheritance(const QString& parent) +{} + +/* + * Return a list of models that are defined in the parent material but not in this one + */ +QStringList Material::inheritedMissingModels(const Material& parent) +{ + QStringList missing; + for (auto uuid : parent._allUuids) { + if (!hasModel(uuid)) { + missing << uuid; + } + } + + return normalizeModels(missing); +} + +/* + * Return a list of models that are defined in this model but not the parent + */ +QStringList Material::inheritedAddedModels(const Material& parent) +{ + QStringList added; + for (auto uuid : _allUuids) { + if (!parent.hasModel(uuid)) { + added << uuid; + } + } + + return normalizeModels(added); +} + +/* + * Return a list of properties that have different values from the parent material + */ +void Material::inheritedPropertyDiff(const QString& parent) +{} diff --git a/src/Mod/Material/App/Materials.h b/src/Mod/Material/App/Materials.h index a4ff89cd44..c0b8cf7769 100644 --- a/src/Mod/Material/App/Materials.h +++ b/src/Mod/Material/App/Materials.h @@ -22,31 +22,34 @@ #ifndef MATERIAL_MATERIALS_H #define MATERIAL_MATERIALS_H -#include +#include -#include #include #include +#include #include #include +#include + +#include -#include "MaterialLibrary.h" #include "Model.h" -namespace fs = boost::filesystem; - namespace Materials { +class MaterialLibrary; + class MaterialsExport MaterialProperty: public ModelProperty { TYPESYSTEM_HEADER_WITH_OVERRIDE(); public: MaterialProperty(); - explicit MaterialProperty(const ModelProperty& property); - explicit MaterialProperty(const MaterialProperty& property); + MaterialProperty(const ModelProperty& property); + MaterialProperty(const MaterialProperty& property); + MaterialProperty(std::shared_ptr property); ~MaterialProperty() override = default; MaterialValue::ValueType getType() const @@ -63,6 +66,7 @@ public: std::shared_ptr getMaterialValue(); const std::shared_ptr getMaterialValue() const; const QString getString() const; + const QString getYAMLString() const; bool getBoolean() const; int getInt() const; double getFloat() const; @@ -79,6 +83,7 @@ public: void setPropertyType(const QString& type) override; void setValue(const QVariant& value); void setValue(const QString& value); + void setValue(std::shared_ptr value); void setString(const QString& value); void setBoolean(bool value); void setBoolean(int value); @@ -93,10 +98,23 @@ public: void setURL(const QString& value); MaterialProperty& operator=(const MaterialProperty& other); + friend QTextStream& operator<<(QTextStream& output, const MaterialProperty& property) + { + output << property.getName() << ": " << property.getYAMLString(); + return output; + } + bool operator==(const MaterialProperty& other) const; + bool operator!=(const MaterialProperty& other) const + { + return !operator==(other); + } + + // void save(QTextStream& stream); protected: void setType(const QString& type); // void setType(MaterialValue::ValueType type) { _valueType = type; } + void copyValuePtr(std::shared_ptr value); void addColumn(MaterialProperty& column) { @@ -122,14 +140,14 @@ public: }; Material(); - explicit Material(const MaterialLibrary& library, - const QString& directory, - const QString& uuid, - const QString& name); - explicit Material(const Material& other); - virtual ~Material(); + Material(std::shared_ptr library, + const QString& directory, + const QString& uuid, + const QString& name); + Material(const Material& other); + ~Material() override = default; - const MaterialLibrary& getLibrary() const + std::shared_ptr getLibrary() const { return _library; } @@ -145,9 +163,14 @@ public: { return _name; } - const QString getAuthorAndLicense() const + const QString getAuthorAndLicense() const; + const QString getAuthor() const { - return _authorAndLicense; + return _author; + } + const QString getLicense() const + { + return _license; } const QString getParentUUID() const { @@ -169,56 +192,39 @@ public: { return _editState; } - const std::list& getTags() const + const QStringList& getTags() const { return _tags; } - const std::vector* getPhysicalModels() const + const QStringList* getPhysicalModels() const { return &_physicalUuids; } - const std::vector* getAppearanceModels() const + const QStringList* getAppearanceModels() const { return &_appearanceUuids; } - void setLibrary(const MaterialLibrary& library) + void setLibrary(std::shared_ptr library) { _library = library; } void setDirectory(const QString& directory) { - Base::Console().Log("Materials::setDirectory(%s)\n", directory.toStdString().c_str()); _directory = directory; } void setUUID(const QString& uuid) { _uuid = uuid; } - void setName(const QString& name) - { - _name = name; - } - void setAuthorAndLicense(const QString& authorAndLicense) - { - _authorAndLicense = authorAndLicense; - } - void setParentUUID(const QString& uuid) - { - _parentUuid = uuid; - } - void setDescription(const QString& description) - { - _description = description; - } - void setURL(const QString& url) - { - _url = url; - } - void setReference(const QString& reference) - { - _reference = reference; - } + void setName(const QString& name); + void setAuthor(const QString& author); + void setLicense(const QString& license); + void setParentUUID(const QString& uuid); + void setDescription(const QString& description); + void setURL(const QString& url); + void setReference(const QString& reference); + void setEditState(ModelEdit newState); void setEditStateAlter() { @@ -228,6 +234,7 @@ public: { setEditState(ModelEdit_Extend); } + void setPropertyEditState(const QString& name); void setPhysicalEditState(const QString& name); void setAppearanceEditState(const QString& name); void resetEditState() @@ -243,23 +250,30 @@ public: Q_UNUSED(tag); } void addPhysical(const QString& uuid); + void removePhysical(const QString& uuid); void addAppearance(const QString& uuid); + void removeAppearance(const QString& uuid); + void clearModels(); void newUuid(); void setPhysicalValue(const QString& name, const QString& value); void setPhysicalValue(const QString& name, int value); void setPhysicalValue(const QString& name, double value); void setPhysicalValue(const QString& name, const Base::Quantity value); + void setPhysicalValue(const QString& name, std::shared_ptr value); void setAppearanceValue(const QString& name, const QString& value); + void setAppearanceValue(const QString& name, std::shared_ptr value); - MaterialProperty& getPhysicalProperty(const QString& name); - const MaterialProperty& getPhysicalProperty(const QString& name) const; - MaterialProperty& getAppearanceProperty(const QString& name); - const MaterialProperty& getAppearanceProperty(const QString& name) const; + std::shared_ptr getPhysicalProperty(const QString& name); + const std::shared_ptr getPhysicalProperty(const QString& name) const; + std::shared_ptr getAppearanceProperty(const QString& name); + const std::shared_ptr getAppearanceProperty(const QString& name) const; const QVariant getPhysicalValue(const QString& name) const; + const Base::Quantity getPhysicalQuantity(const QString& name) const; const QString getPhysicalValueString(const QString& name) const; const QVariant getAppearanceValue(const QString& name) const; + const Base::Quantity getAppearanceQuantity(const QString& name) const; const QString getAppearanceValueString(const QString& name) const; bool hasPhysicalProperty(const QString& name) const; bool hasAppearanceProperty(const QString& name) const; @@ -275,15 +289,17 @@ public: bool isPhysicalModelComplete(const QString& uuid) const; bool isAppearanceModelComplete(const QString& uuid) const; - const std::map& getPhysicalProperties() const + std::map>& getPhysicalProperties() { return _physical; } - const std::map& getAppearanceProperties() const + std::map>& getAppearanceProperties() { return _appearance; } + QString getModelByName(const QString& name) const; + bool getDereferenced() const { return _dereferenced; @@ -293,45 +309,80 @@ public: _dereferenced = true; } - void save(QTextStream& stream, bool saveAsCopy); + /* + * Normalize models by removing any inherited models + */ + QStringList normalizeModels(const QStringList& models); + + /* + * Set or change the base material for the current material, updating the properties as + * required. + */ + void updateInheritance(const QString& parent); + /* + * Return a list of models that are defined in the parent material but not in this one + */ + QStringList inheritedMissingModels(const Material& parent); + /* + * Return a list of models that are defined in this model but not the parent + */ + QStringList inheritedAddedModels(const Material& parent); + /* + * Return a list of properties that have different values from the parent material + */ + void inheritedPropertyDiff(const QString& parent); + + void save(QTextStream& stream, bool saveAsCopy, bool saveInherited); Material& operator=(const Material& other); protected: void addModel(const QString& uuid); + void removeModel(const QString& uuid); + void removeUUID(QStringList& uuidList, const QString& uuid); - const QVariant getValue(const std::map& propertyList, - const QString& name) const; - const QString getValueString(const std::map& propertyList, - const QString& name) const; + const QVariant + getValue(const std::map>& propertyList, + const QString& name) const; + const QString + getValueString(const std::map>& propertyList, + const QString& name) const; + bool modelChanged(const std::shared_ptr parent, + const std::shared_ptr model) const; + bool modelAppearanceChanged(const std::shared_ptr parent, + const std::shared_ptr model) const; void saveGeneral(QTextStream& stream) const; void saveInherits(QTextStream& stream) const; - void saveModels(QTextStream& stream) const; - void saveAppearanceModels(QTextStream& stream) const; + void saveModels(QTextStream& stream, bool saveInherited) const; + void saveAppearanceModels(QTextStream& stream, bool saveInherited) const; private: - MaterialLibrary _library; + std::shared_ptr _library; QString _directory; QString _uuid; QString _name; - QString _authorAndLicense; + QString _author; + QString _license; QString _parentUuid; QString _description; QString _url; QString _reference; - std::list _tags; - std::vector _physicalUuids; - std::vector _appearanceUuids; - std::vector _allUuids; // Includes inherited models - std::map _physical; - std::map _appearance; + QStringList _tags; + QStringList _physicalUuids; + QStringList _appearanceUuids; + QStringList _allUuids; // Includes inherited models + std::map> _physical; + std::map> _appearance; bool _dereferenced; ModelEdit _editState; }; +typedef FolderTreeNode MaterialTreeNode; + } // namespace Materials Q_DECLARE_METATYPE(Materials::Material*) +Q_DECLARE_METATYPE(std::shared_ptr) #endif // MATERIAL_MATERIALS_H diff --git a/src/Mod/Material/App/Model.cpp b/src/Mod/Material/App/Model.cpp index 87020a96fa..c9b95e85f8 100644 --- a/src/Mod/Material/App/Model.cpp +++ b/src/Mod/Material/App/Model.cpp @@ -23,10 +23,13 @@ #ifndef _PreComp_ #endif +#include + +#include + #include "Exceptions.h" #include "Model.h" #include "ModelLibrary.h" -#include using namespace Materials; @@ -81,12 +84,27 @@ ModelProperty& ModelProperty::operator=(const ModelProperty& other) return *this; } +bool ModelProperty::operator==(const ModelProperty& other) const +{ + if (this == &other) { + return true; + } + + if (&other == nullptr) { + return false; + } + + return (_name == other._name) && (_propertyType == other._propertyType) + && (_units == other._units) && (_url == other._url) && (_description == other._description) + && (_inheritance == other._inheritance); +} + TYPESYSTEM_SOURCE(Materials::Model, Base::BaseClass) Model::Model() {} -Model::Model(const ModelLibrary& library, +Model::Model(std::shared_ptr library, ModelType type, const QString& name, const QString& directory, diff --git a/src/Mod/Material/App/Model.h b/src/Mod/Material/App/Model.h index c286ffeb0c..fcf83efd47 100644 --- a/src/Mod/Material/App/Model.h +++ b/src/Mod/Material/App/Model.h @@ -22,31 +22,45 @@ #ifndef MATERIAL_MODEL_H #define MATERIAL_MODEL_H -#include +#include + +#include +#include +#include #include #include -#include -#include +#include + +#include "FolderTree.h" #include "MaterialValue.h" -#include "ModelLibrary.h" +// #include "ModelLibrary.h" namespace Materials { +class ModelLibrary; + +enum ModelFilter +{ + ModelFilter_None, + ModelFilter_Physical, + ModelFilter_Appearance +}; + class MaterialsExport ModelProperty: public Base::BaseClass { TYPESYSTEM_HEADER_WITH_OVERRIDE(); public: ModelProperty(); - explicit ModelProperty(const QString& name, - const QString& type, - const QString& units, - const QString& url, - const QString& description); - explicit ModelProperty(const ModelProperty& other); + ModelProperty(const QString& name, + const QString& type, + const QString& units, + const QString& url, + const QString& description); + ModelProperty(const ModelProperty& other); ~ModelProperty() override = default; const QString getName() const @@ -117,6 +131,11 @@ public: } ModelProperty& operator=(const ModelProperty& other); + bool operator==(const ModelProperty& other) const; + bool operator!=(const ModelProperty& other) const + { + return !operator==(other); + } private: QString _name; @@ -140,17 +159,17 @@ public: }; Model(); - explicit Model(const ModelLibrary& library, - ModelType type, - const QString& name, - const QString& directory, - const QString& uuid, - const QString& description, - const QString& url, - const QString& doi); + Model(std::shared_ptr library, + ModelType type, + const QString& name, + const QString& directory, + const QString& uuid, + const QString& description, + const QString& url, + const QString& doi); ~Model() override = default; - const ModelLibrary& getLibrary() const + std::shared_ptr getLibrary() const { return _library; } @@ -175,10 +194,10 @@ public: { return QDir(_directory).absolutePath(); } - const QString getRelativePath() const - { - return QDir(_directory).relativeFilePath(QDir(_directory).absolutePath()); - } + // const QString getRelativePath() const + // { + // return QDir(_directory).relativeFilePath(QDir(_directory).absolutePath()); + // } const QString getUUID() const { return _uuid; @@ -196,7 +215,7 @@ public: return _doi; } - void setLibrary(const ModelLibrary& library) + void setLibrary(std::shared_ptr library) { _library = library; } @@ -231,12 +250,16 @@ public: void addInheritance(const QString& uuid) { - _inheritedUuids.push_back(uuid); + _inheritedUuids << uuid; } - const std::vector& getInheritance() const + const QStringList& getInheritance() const { return _inheritedUuids; } + bool inherits(const QString& uuid) const + { + return _inheritedUuids.contains(uuid); + } bool operator==(const Model& m) const { @@ -281,7 +304,7 @@ public: } private: - ModelLibrary _library; + std::shared_ptr _library; ModelType _type; QString _name; QString _directory; @@ -289,10 +312,12 @@ private: QString _description; QString _url; QString _doi; - std::vector _inheritedUuids; + QStringList _inheritedUuids; std::map _properties; }; +typedef FolderTreeNode ModelTreeNode; + } // namespace Materials #endif // MATERIAL_MODEL_H diff --git a/src/Mod/Material/App/ModelLibrary.cpp b/src/Mod/Material/App/ModelLibrary.cpp index 901795bd30..7f866db939 100644 --- a/src/Mod/Material/App/ModelLibrary.cpp +++ b/src/Mod/Material/App/ModelLibrary.cpp @@ -30,6 +30,7 @@ #include "Exceptions.h" #include "Model.h" #include "ModelLibrary.h" +#include "ModelManager.h" using namespace Materials; @@ -66,6 +67,15 @@ QString LibraryBase::getLocalPath(const QString& path) const return filePath; } +bool LibraryBase::isRoot(const QString& path) const +{ + QString localPath = getLocalPath(path); + QString cleanPath = getLocalPath(QString::fromStdString("")); + std::string pLocal = localPath.toStdString(); + std::string pclean = cleanPath.toStdString(); + return (cleanPath == localPath); +} + QString LibraryBase::getRelativePath(const QString& path) const { QString filePath; @@ -97,17 +107,80 @@ TYPESYSTEM_SOURCE(Materials::ModelLibrary, LibraryBase) ModelLibrary::ModelLibrary(const QString& libraryName, const QString& dir, const QString& icon) : LibraryBase(libraryName, dir, icon) -{} +{ + _modelPathMap = std::make_unique>>(); +} ModelLibrary::ModelLibrary() -{} +{ + _modelPathMap = std::make_unique>>(); +} -Model* ModelLibrary::addModel(const Model& model, const QString& path) +std::shared_ptr ModelLibrary::getModelByPath(const QString& path) const { QString filePath = getRelativePath(path); - Model* newModel = new Model(model); - newModel->setLibrary(*this); + try { + std::shared_ptr model = _modelPathMap->at(filePath); + return model; + } + catch (std::out_of_range& e) { + throw ModelNotFound(); + } +} + +std::shared_ptr ModelLibrary::addModel(const Model& model, const QString& path) +{ + QString filePath = getRelativePath(path); + std::shared_ptr newModel = std::make_shared(model); + newModel->setLibrary(getptr()); newModel->setDirectory(filePath); + (*_modelPathMap)[filePath] = newModel; + return newModel; } + +std::shared_ptr>> +ModelLibrary::getModelTree(ModelFilter filter) const +{ + std::shared_ptr>> modelTree = + std::make_shared>>(); + + for (auto it = _modelPathMap->begin(); it != _modelPathMap->end(); it++) { + auto filename = it->first; + auto model = it->second; + + if (ModelManager::passFilter(filter, model->getType())) { + // Base::Console().Log("Relative path '%s'\n\t", filename.toStdString().c_str()); + QStringList list = filename.split(QString::fromStdString("/")); + + // Start at the root + std::shared_ptr>> node = modelTree; + for (auto itp = list.begin(); itp != list.end(); itp++) { + // Base::Console().Log("\t%s", itp->toStdString().c_str()); + if (ModelManager::isModel(*itp)) { + std::shared_ptr child = std::make_shared(); + child->setData(model); + (*node)[*itp] = child; + } + else { + // Add the folder only if it's not already there + if (node->count(*itp) == 0) { + auto mapPtr = + std::make_shared>>(); + std::shared_ptr child = std::make_shared(); + child->setFolder(mapPtr); + (*node)[*itp] = child; + node = mapPtr; + } + else { + node = (*node)[*itp]->getFolder(); + } + } + } + // Base::Console().Log("\n"); + } + } + + return modelTree; +} diff --git a/src/Mod/Material/App/ModelLibrary.h b/src/Mod/Material/App/ModelLibrary.h index ea42aa6d9a..8b9fa8b004 100644 --- a/src/Mod/Material/App/ModelLibrary.h +++ b/src/Mod/Material/App/ModelLibrary.h @@ -22,27 +22,30 @@ #ifndef MATERIAL_MODELLIBRARY_H #define MATERIAL_MODELLIBRARY_H -#include +#include -#include -#include #include #include -#include "MaterialValue.h" +#include +#include +#include + +#include "MaterialValue.h" +#include "Model.h" namespace Materials { -class Model; +// class Model; class MaterialsExport LibraryBase: public Base::BaseClass { - TYPESYSTEM_HEADER_WITH_OVERRIDE(); + TYPESYSTEM_HEADER(); public: LibraryBase(); - explicit LibraryBase(const QString& libraryName, const QString& dir, const QString& icon); + LibraryBase(const QString& libraryName, const QString& dir, const QString& icon); ~LibraryBase() override = default; const QString getName() const @@ -68,20 +71,24 @@ public: } QString getLocalPath(const QString& path) const; QString getRelativePath(const QString& path) const; + bool isRoot(const QString& path) const; private: + LibraryBase(const LibraryBase&); + QString _name; QString _directory; QString _iconPath; }; -class MaterialsExport ModelLibrary: public LibraryBase +class MaterialsExport ModelLibrary: public LibraryBase, + public std::enable_shared_from_this { - TYPESYSTEM_HEADER_WITH_OVERRIDE(); + TYPESYSTEM_HEADER(); public: ModelLibrary(); - explicit ModelLibrary(const QString& libraryName, const QString& dir, const QString& icon); + ModelLibrary(const QString& libraryName, const QString& dir, const QString& icon); ~ModelLibrary() override = default; bool operator==(const ModelLibrary& library) const @@ -92,8 +99,22 @@ public: { return !operator==(library); } + std::shared_ptr getModelByPath(const QString& path) const; - Model* addModel(const Model& model, const QString& path); + std::shared_ptr addModel(const Model& model, const QString& path); + + // Use this to get a shared_ptr for *this + std::shared_ptr getptr() + { + return shared_from_this(); + } + std::shared_ptr>> + getModelTree(ModelFilter filter) const; + +private: + ModelLibrary(const ModelLibrary&); + + std::unique_ptr>> _modelPathMap; }; } // namespace Materials diff --git a/src/Mod/Material/App/ModelLoader.cpp b/src/Mod/Material/App/ModelLoader.cpp index 0357b2b27e..b8e9ad582f 100644 --- a/src/Mod/Material/App/ModelLoader.cpp +++ b/src/Mod/Material/App/ModelLoader.cpp @@ -37,7 +37,7 @@ using namespace Materials; -ModelEntry::ModelEntry(const ModelLibrary& library, +ModelEntry::ModelEntry(std::shared_ptr library, const QString& baseName, const QString& modelName, const QString& dir, @@ -52,17 +52,18 @@ ModelEntry::ModelEntry(const ModelLibrary& library, , _dereferenced(false) {} -std::unique_ptr> ModelLoader::_modelEntryMap = nullptr; +std::unique_ptr>> ModelLoader::_modelEntryMap = + nullptr; -ModelLoader::ModelLoader(std::shared_ptr> modelMap, - std::shared_ptr> libraryList) +ModelLoader::ModelLoader(std::shared_ptr>> modelMap, + std::shared_ptr>> libraryList) : _modelMap(modelMap) , _libraryList(libraryList) { loadLibraries(); } -void ModelLoader::addLibrary(ModelLibrary* model) +void ModelLoader::addLibrary(std::shared_ptr model) { _libraryList->push_back(model); } @@ -84,12 +85,13 @@ const QString ModelLoader::getUUIDFromPath(const QString& path) const QString uuid = QString::fromStdString(yamlroot[base]["UUID"].as()); return uuid; } - catch (YAML::Exception&) { + catch (YAML::Exception& ex) { throw ModelNotFound(); } } -ModelEntry* ModelLoader::getModelFromPath(const ModelLibrary& library, const QString& path) const +std::shared_ptr ModelLoader::getModelFromPath(std::shared_ptr library, + const QString& path) const { QFile file(path); if (!file.exists()) { @@ -113,12 +115,12 @@ ModelEntry* ModelLoader::getModelFromPath(const ModelLibrary& library, const QSt throw InvalidModel(); } - ModelEntry* model = new ModelEntry(library, - QString::fromStdString(base), - QString::fromStdString(name), - path, - QString::fromStdString(uuid), - yamlroot); + std::shared_ptr model = std::make_shared(library, + QString::fromStdString(base), + QString::fromStdString(name), + path, + QString::fromStdString(uuid), + yamlroot); return model; } @@ -133,8 +135,8 @@ void ModelLoader::showYaml(const YAML::Node& yaml) const } void ModelLoader::dereference(const QString& uuid, - ModelEntry* parent, - const ModelEntry* child, + std::shared_ptr parent, + std::shared_ptr child, std::map, QString>* inheritances) { auto parentPtr = parent->getModelPtr(); @@ -168,7 +170,7 @@ void ModelLoader::dereference(const QString& uuid, } -void ModelLoader::dereference(ModelEntry* model, +void ModelLoader::dereference(std::shared_ptr model, std::map, QString>* inheritances) { // Avoid recursion @@ -185,10 +187,10 @@ void ModelLoader::dereference(ModelEntry* model, // This requires that all models have already been loaded undereferenced try { - const ModelEntry* child = (*_modelEntryMap)[nodeName]; + std::shared_ptr child = (*_modelEntryMap)[nodeName]; dereference(model->getUUID(), model, child, inheritances); } - catch (const std::out_of_range&) { + catch (const std::out_of_range& oor) { Base::Console().Log("Unable to find '%s' in model map\n", nodeName.toStdString().c_str()); } @@ -208,7 +210,7 @@ QString ModelLoader::yamlValue(const YAML::Node& node, return QString::fromStdString(defaultValue); } -void ModelLoader::addToTree(ModelEntry* model, +void ModelLoader::addToTree(std::shared_ptr model, std::map, QString>* inheritances) { std::set exclude; @@ -268,12 +270,12 @@ void ModelLoader::addToTree(ModelEntry* model, if (propType == QString::fromStdString("2DArray") || propType == QString::fromStdString("3DArray")) { - Base::Console().Log("Reading columns\n"); + // Base::Console().Log("Reading columns\n"); // Read the columns auto cols = yamlProp["Columns"]; for (auto col : cols) { std::string colName = col.first.as(); - Base::Console().Log("\tColumns '%s'\n", colName.c_str()); + // Base::Console().Log("\tColumns '%s'\n", colName.c_str()); auto colProp = cols[colName]; auto colPropType = yamlValue(colProp, "Type", ""); @@ -299,16 +301,16 @@ void ModelLoader::addToTree(ModelEntry* model, } } - (*_modelMap)[uuid] = library.addModel(*finalModel, directory); + (*_modelMap)[uuid] = library->addModel(*finalModel, directory); } -void ModelLoader::loadLibrary(const ModelLibrary& library) +void ModelLoader::loadLibrary(std::shared_ptr library) { if (_modelEntryMap == nullptr) { - _modelEntryMap = std::make_unique>(); + _modelEntryMap = std::make_unique>>(); } - QDirIterator it(library.getDirectory(), QDirIterator::Subdirectories); + QDirIterator it(library->getDirectory(), QDirIterator::Subdirectories); while (it.hasNext()) { auto pathname = it.next(); QFileInfo file(pathname); @@ -345,7 +347,7 @@ void ModelLoader::loadLibraries() getModelLibraries(); if (_libraryList) { for (auto it = _libraryList->begin(); it != _libraryList->end(); it++) { - loadLibrary(**it); + loadLibrary(*it); } } } @@ -362,9 +364,10 @@ void ModelLoader::getModelLibraries() if (useBuiltInMaterials) { QString resourceDir = QString::fromStdString(App::Application::getResourceDir() + "/Mod/Material/Resources/Models"); - auto libData = new ModelLibrary(QString::fromStdString("System"), - resourceDir, - QString::fromStdString(":/icons/freecad.svg")); + auto libData = + std::make_shared(QString::fromStdString("System"), + resourceDir, + QString::fromStdString(":/icons/freecad.svg")); _libraryList->push_back(libData); } @@ -380,7 +383,7 @@ void ModelLoader::getModelLibraries() if (modelDir.length() > 0) { QDir dir(modelDir); if (dir.exists()) { - auto libData = new ModelLibrary(moduleName, modelDir, modelIcon); + auto libData = std::make_shared(moduleName, modelDir, modelIcon); _libraryList->push_back(libData); } } @@ -393,10 +396,10 @@ void ModelLoader::getModelLibraries() if (!resourceDir.isEmpty()) { QDir materialDir(resourceDir); if (materialDir.exists()) { - auto libData = - new ModelLibrary(QString::fromStdString("User"), - resourceDir, - QString::fromStdString(":/icons/preferences-general.svg")); + auto libData = std::make_shared( + QString::fromStdString("User"), + resourceDir, + QString::fromStdString(":/icons/preferences-general.svg")); _libraryList->push_back(libData); } } @@ -407,9 +410,10 @@ void ModelLoader::getModelLibraries() if (!resourceDir.isEmpty()) { QDir materialDir(resourceDir); if (materialDir.exists()) { - auto libData = new ModelLibrary(QString::fromStdString("Custom"), - resourceDir, - QString::fromStdString(":/icons/user.svg")); + auto libData = + std::make_shared(QString::fromStdString("Custom"), + resourceDir, + QString::fromStdString(":/icons/user.svg")); _libraryList->push_back(libData); } } diff --git a/src/Mod/Material/App/ModelLoader.h b/src/Mod/Material/App/ModelLoader.h index b843b9e1fb..9db76092b3 100644 --- a/src/Mod/Material/App/ModelLoader.h +++ b/src/Mod/Material/App/ModelLoader.h @@ -22,6 +22,8 @@ #ifndef MATERIAL_MODELLOADER_H #define MATERIAL_MODELLOADER_H +#include + #include #include #include @@ -34,15 +36,15 @@ namespace Materials class ModelEntry { public: - explicit ModelEntry(const ModelLibrary& library, - const QString& baseName, - const QString& modelName, - const QString& dir, - const QString& modelUuid, - const YAML::Node& modelData); + ModelEntry(std::shared_ptr library, + const QString& baseName, + const QString& modelName, + const QString& dir, + const QString& modelUuid, + const YAML::Node& modelData); virtual ~ModelEntry() = default; - const ModelLibrary& getLibrary() const + std::shared_ptr getLibrary() const { return _library; } @@ -83,7 +85,7 @@ public: private: ModelEntry(); - ModelLibrary _library; + std::shared_ptr _library; QString _base; QString _name; QString _directory; @@ -95,8 +97,8 @@ private: class ModelLoader { public: - explicit ModelLoader(std::shared_ptr> modelMap, - std::shared_ptr> libraryList); + ModelLoader(std::shared_ptr>> modelMap, + std::shared_ptr>> libraryList); virtual ~ModelLoader() = default; static const QString getUUIDFromPath(const QString& path); @@ -107,21 +109,24 @@ private: void getModelLibraries(); QString yamlValue(const YAML::Node& node, const std::string& key, const std::string& defaultValue); - void addToTree(ModelEntry* model, std::map, QString>* inheritances); + void addToTree(std::shared_ptr model, + std::map, QString>* inheritances); void showYaml(const YAML::Node& yaml) const; void dereference(const QString& uuid, - ModelEntry* parent, - const ModelEntry* child, + std::shared_ptr parent, + std::shared_ptr child, std::map, QString>* inheritances); - void dereference(ModelEntry* model, + void dereference(std::shared_ptr model, std::map, QString>* inheritances); - ModelEntry* getModelFromPath(const ModelLibrary& library, const QString& path) const; - void addLibrary(ModelLibrary* model); - void loadLibrary(const ModelLibrary& library); + std::shared_ptr getModelFromPath(std::shared_ptr library, + const QString& path) const; + void addLibrary(std::shared_ptr model); + void loadLibrary(std::shared_ptr library); void loadLibraries(); - static std::unique_ptr> _modelEntryMap; - std::shared_ptr> _modelMap; - std::shared_ptr> _libraryList; + + static std::unique_ptr>> _modelEntryMap; + std::shared_ptr>> _modelMap; + std::shared_ptr>> _libraryList; }; } // namespace Materials diff --git a/src/Mod/Material/App/ModelManager.cpp b/src/Mod/Material/App/ModelManager.cpp index 2900fdde55..88d4e85012 100644 --- a/src/Mod/Material/App/ModelManager.cpp +++ b/src/Mod/Material/App/ModelManager.cpp @@ -23,6 +23,7 @@ #ifndef _PreComp_ #endif +#include #include #include @@ -34,8 +35,8 @@ using namespace Materials; -std::shared_ptr> ModelManager::_libraryList = nullptr; -std::shared_ptr> ModelManager::_modelMap = nullptr; +std::shared_ptr>> ModelManager::_libraryList = nullptr; +std::shared_ptr>> ModelManager::_modelMap = nullptr; QMutex ModelManager::_mutex; TYPESYSTEM_SOURCE(Materials::ModelManager, Base::BaseClass) @@ -50,9 +51,9 @@ void ModelManager::initLibraries() QMutexLocker locker(&_mutex); if (_modelMap == nullptr) { - _modelMap = std::make_shared>(); + _modelMap = std::make_shared>>(); if (_libraryList == nullptr) { - _libraryList = std::make_shared>(); + _libraryList = std::make_shared>>(); } // Load the libraries @@ -60,12 +61,12 @@ void ModelManager::initLibraries() } } -bool ModelManager::isModel(const fs::path& p) +bool ModelManager::isModel(const QString& file) { // if (!fs::is_regular_file(p)) // return false; // check file extension - if (p.extension() == ".yml") { + if (file.endsWith(QString::fromStdString(".yml"))) { return true; } return false; @@ -80,36 +81,62 @@ void ModelManager::refresh() ModelLoader loader(_modelMap, _libraryList); } -const Model& ModelManager::getModel(const QString& uuid) const +std::shared_ptr ModelManager::getModel(const QString& uuid) const { try { if (_modelMap == nullptr) { throw Uninitialized(); } - return *(_modelMap->at(uuid)); + return _modelMap->at(uuid); } catch (std::out_of_range const&) { throw ModelNotFound(); } } -const Model& ModelManager::getModelByPath(const QString& path) const +std::shared_ptr ModelManager::getModelByPath(const QString& path) const { - const QString& uuid = ModelLoader::getUUIDFromPath(path); - const Model& model = getModel(uuid); + QString cleanPath = QDir::cleanPath(path); - return model; + for (auto library : *_libraryList) { + // Base::Console().Log("ModelManager::getModelByPath() Checking library '%s'->'%s'\n", + // library->getName().toStdString().c_str(), + // library->getDirectory().toStdString().c_str()); + + + if (cleanPath.startsWith(library->getDirectory())) { + // Base::Console().Log("ModelManager::getModelByPath() Library '%s'\n", + // library->getDirectory().toStdString().c_str()); + // Base::Console().Log("ModelManager::getModelByPath() Path '%s'\n", + // cleanPath.toStdString().c_str()); + return library->getModelByPath(cleanPath); + } + } + Base::Console().Log("ModelManager::getModelByPath() Library not found for path '%s'\n", + cleanPath.toStdString().c_str()); + + throw MaterialNotFound(); } -const Model& ModelManager::getModelByPath(const QString& path, const QString& libraryPath) const +std::shared_ptr ModelManager::getModelByPath(const QString& path, const QString& lib) const { - QDir modelDir(QDir::cleanPath(libraryPath + QString::fromStdString("/") + path)); - QString absPath = modelDir.absolutePath(); - return getModelByPath(absPath); + auto library = getLibrary(lib); // May throw LibraryNotFound + return library->getModelByPath(path); // May throw ModelNotFound } -bool ModelManager::passFilter(ModelFilter filter, Model::ModelType modelType) const +std::shared_ptr ModelManager::getLibrary(const QString& name) const +{ + for (auto library : *_libraryList) { + if (library->getName() == name) { + return library; + } + } + + throw LibraryNotFound(); +} + +bool ModelManager::passFilter(ModelFilter filter, Model::ModelType modelType) { switch (filter) { case ModelFilter_None: @@ -124,49 +151,3 @@ bool ModelManager::passFilter(ModelFilter filter, Model::ModelType modelType) co return false; } - -std::shared_ptr> -ModelManager::getModelTree(const ModelLibrary& library, ModelFilter filter) const -{ - std::shared_ptr> modelTree = - std::make_shared>(); - - for (auto it = _modelMap->begin(); it != _modelMap->end(); it++) { - auto filename = it->first; - auto model = it->second; - - if (model->getLibrary() == library && passFilter(filter, model->getType())) { - fs::path path = model->getDirectory().toStdString(); - Base::Console().Log("Relative path '%s'\n\t", path.string().c_str()); - - // Start at the root - std::shared_ptr> node = modelTree; - for (auto itp = path.begin(); itp != path.end(); itp++) { - if (isModel(itp->string())) { - ModelTreeNode* child = new ModelTreeNode(); - child->setData(model); - (*node)[QString::fromStdString(itp->string())] = child; - } - else { - // Add the folder only if it's not already there - QString folderName = QString::fromStdString(itp->string()); - std::shared_ptr> mapPtr; - if (node->count(QString::fromStdString(itp->string())) == 0) { - mapPtr = std::make_shared>(); - ModelTreeNode* child = new ModelTreeNode(); - child->setFolder(mapPtr); - (*node)[QString::fromStdString(itp->string())] = child; - node = mapPtr; - } - else { - node = (*node)[QString::fromStdString(itp->string())]->getFolder(); - } - } - Base::Console().Log("'%s' ", itp->string().c_str()); - } - Base::Console().Log("\n"); - } - } - - return modelTree; -} diff --git a/src/Mod/Material/App/ModelManager.h b/src/Mod/Material/App/ModelManager.h index 5a5eed39ba..a1954d3419 100644 --- a/src/Mod/Material/App/ModelManager.h +++ b/src/Mod/Material/App/ModelManager.h @@ -22,62 +22,57 @@ #ifndef MATERIAL_MODELMANAGER_H #define MATERIAL_MODELMANAGER_H +#include + #include #include -#include - #include "Exceptions.h" #include "FolderTree.h" #include "Model.h" +#include "ModelLibrary.h" -namespace fs = boost::filesystem; namespace Materials { -typedef FolderTreeNode ModelTreeNode; - class MaterialsExport ModelManager: public Base::BaseClass { - TYPESYSTEM_HEADER_WITH_OVERRIDE(); + TYPESYSTEM_HEADER(); public: - enum ModelFilter - { - ModelFilter_None, - ModelFilter_Physical, - ModelFilter_Appearance - }; - ModelManager(); ~ModelManager() override = default; void refresh(); - std::shared_ptr> getModelLibraries() + std::shared_ptr>> getModelLibraries() { return _libraryList; } - std::shared_ptr> getModels() + std::shared_ptr>> getModels() { return _modelMap; } - std::shared_ptr> - getModelTree(const ModelLibrary& library, ModelFilter filter = ModelFilter_None) const; - const Model& getModel(const QString& uuid) const; - const Model& getModelByPath(const QString& path) const; - const Model& getModelByPath(const QString& path, const QString& libraryPath) const; + std::shared_ptr>> + getModelTree(std::shared_ptr library, ModelFilter filter = ModelFilter_None) const + { + return library->getModelTree(filter); + } + std::shared_ptr getModel(const QString& uuid) const; + std::shared_ptr getModelByPath(const QString& path) const; + std::shared_ptr getModelByPath(const QString& path, const QString& lib) const; + std::shared_ptr getLibrary(const QString& name) const; - static bool isModel(const fs::path& p); - bool passFilter(ModelFilter filter, Model::ModelType modelType) const; + static bool isModel(const QString& file); + static bool passFilter(ModelFilter filter, Model::ModelType modelType); private: static void initLibraries(); - static std::shared_ptr> _libraryList; - static std::shared_ptr> _modelMap; + static std::shared_ptr>> _libraryList; + static std::shared_ptr>> _modelMap; static QMutex _mutex; }; diff --git a/src/Mod/Material/App/ModelManagerPyImpl.cpp b/src/Mod/Material/App/ModelManagerPyImpl.cpp index 793a80a63b..b7b2608a26 100644 --- a/src/Mod/Material/App/ModelManagerPyImpl.cpp +++ b/src/Mod/Material/App/ModelManagerPyImpl.cpp @@ -21,10 +21,8 @@ #include "PreCompiled.h" -#ifndef _PreComp_ -#include -#endif - +#include "Model.h" +#include "ModelLibrary.h" #include "ModelManager.h" #include "ModelManagerPy.h" #include "ModelPy.h" @@ -62,8 +60,8 @@ PyObject* ModelManagerPy::getModel(PyObject* args) } try { - const Model model = getModelManagerPtr()->getModel(QString::fromStdString(uuid)); - return new ModelPy(new Model(model)); + auto model = getModelManagerPtr()->getModel(QString::fromStdString(uuid)); + return new ModelPy(new Model(*model)); } catch (ModelNotFound const&) { QString error = QString::fromStdString("Model not found:\n"); @@ -96,10 +94,9 @@ PyObject* ModelManagerPy::getModelByPath(PyObject* args) std::string libPath(lib); if (libPath.length() > 0) { try { - const Model& model = - getModelManagerPtr()->getModelByPath(QString::fromStdString(path), - QString::fromStdString(libPath)); - return new ModelPy(new Model(model)); + auto model = getModelManagerPtr()->getModelByPath(QString::fromStdString(path), + QString::fromStdString(libPath)); + return new ModelPy(new Model(*model)); } catch (ModelNotFound const&) { PyErr_SetString(PyExc_LookupError, "Model not found"); @@ -108,8 +105,8 @@ PyObject* ModelManagerPy::getModelByPath(PyObject* args) } try { - const Model& model = getModelManagerPtr()->getModelByPath(QString::fromStdString(path)); - return new ModelPy(new Model(model)); + auto model = getModelManagerPtr()->getModelByPath(QString::fromStdString(path)); + return new ModelPy(new Model(*model)); } catch (ModelNotFound const&) { PyErr_SetString(PyExc_LookupError, "Model not found"); @@ -119,11 +116,11 @@ PyObject* ModelManagerPy::getModelByPath(PyObject* args) Py::List ModelManagerPy::getModelLibraries() const { - std::shared_ptr> libraries = getModelManagerPtr()->getModelLibraries(); + auto libraries = getModelManagerPtr()->getModelLibraries(); Py::List list; for (auto it = libraries->begin(); it != libraries->end(); it++) { - ModelLibrary* lib = *it; + auto lib = *it; Py::Tuple libTuple(3); libTuple.setItem(0, Py::String(lib->getName().toStdString())); libTuple.setItem(1, Py::String(lib->getDirectoryPath().toStdString())); @@ -142,7 +139,7 @@ Py::Dict ModelManagerPy::getModels() const for (auto it = models->begin(); it != models->end(); it++) { QString key = it->first; - Model* model = it->second; + auto model = it->second; PyObject* modelPy = new ModelPy(new Model(*model)); dict.setItem(Py::String(key.toStdString()), Py::Object(modelPy, true)); diff --git a/src/Mod/Material/App/ModelPropertyPyImpl.cpp b/src/Mod/Material/App/ModelPropertyPyImpl.cpp index e87cb6f15f..d701df9da6 100644 --- a/src/Mod/Material/App/ModelPropertyPyImpl.cpp +++ b/src/Mod/Material/App/ModelPropertyPyImpl.cpp @@ -21,10 +21,6 @@ #include "PreCompiled.h" -#ifndef _PreComp_ -#include -#endif - #include "Model.h" #include "ModelPropertyPy.h" diff --git a/src/Mod/Material/App/ModelPyImpl.cpp b/src/Mod/Material/App/ModelPyImpl.cpp index 1d83d99e65..f450ee1f0b 100644 --- a/src/Mod/Material/App/ModelPyImpl.cpp +++ b/src/Mod/Material/App/ModelPyImpl.cpp @@ -21,13 +21,11 @@ #include "PreCompiled.h" -#ifndef _PreComp_ -#include -#endif - #include "Model.h" +#include "ModelLibrary.h" #include "ModelPropertyPy.h" #include "ModelPy.h" +#include "ModelUuids.h" #include "ModelPy.cpp" @@ -43,11 +41,11 @@ std::string ModelPy::representation() const str << "), UUID=("; str << ptr->getUUID().toStdString(); str << "), Library Name=("; - str << ptr->getLibrary().getName().toStdString(); + str << ptr->getLibrary()->getName().toStdString(); str << "), Library Root=("; - str << ptr->getLibrary().getDirectoryPath().toStdString(); + str << ptr->getLibrary()->getDirectoryPath().toStdString(); str << "), Library Icon=("; - str << ptr->getLibrary().getIconPath().toStdString(); + str << ptr->getLibrary()->getIconPath().toStdString(); str << "), Directory=("; str << ptr->getDirectory().toStdString(); str << "), URL=("; @@ -57,7 +55,7 @@ std::string ModelPy::representation() const str << "), Description=("; str << ptr->getDescription().toStdString(); str << "), Inherits=["; - const std::vector& inherited = getModelPtr()->getInheritance(); + auto& inherited = getModelPtr()->getInheritance(); for (auto it = inherited.begin(); it != inherited.end(); it++) { QString uuid = *it; if (it != inherited.begin()) { @@ -87,17 +85,17 @@ int ModelPy::PyInit(PyObject* /*args*/, PyObject* /*kwd*/) Py::String ModelPy::getLibraryName() const { - return Py::String(getModelPtr()->getLibrary().getName().toStdString()); + return Py::String(getModelPtr()->getLibrary()->getName().toStdString()); } Py::String ModelPy::getLibraryRoot() const { - return Py::String(getModelPtr()->getLibrary().getDirectoryPath().toStdString()); + return Py::String(getModelPtr()->getLibrary()->getDirectoryPath().toStdString()); } Py::String ModelPy::getLibraryIcon() const { - return Py::String(getModelPtr()->getLibrary().getIconPath().toStdString()); + return Py::String(getModelPtr()->getLibrary()->getIconPath().toStdString()); } Py::String ModelPy::getName() const @@ -132,13 +130,11 @@ Py::String ModelPy::getDOI() const Py::List ModelPy::getInherited() const { - const std::vector& inherited = getModelPtr()->getInheritance(); + auto& inherited = getModelPtr()->getInheritance(); Py::List list; for (auto it = inherited.begin(); it != inherited.end(); it++) { - QString uuid = *it; - - list.append(Py::String(uuid.toStdString())); + list.append(Py::String(it->toStdString())); } return list; diff --git a/src/Mod/Material/App/ModelUuids.cpp b/src/Mod/Material/App/ModelUuids.cpp new file mode 100644 index 0000000000..78c02ace68 --- /dev/null +++ b/src/Mod/Material/App/ModelUuids.cpp @@ -0,0 +1,70 @@ +/*************************************************************************** + * Copyright (c) 2023 David Carter * + * * + * This file is part of FreeCAD. * + * * + * FreeCAD is free software: you can redistribute it and/or modify it * + * under the terms of the GNU Lesser General Public License as * + * published by the Free Software Foundation, either version 2.1 of the * + * License, or (at your option) any later version. * + * * + * FreeCAD is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with FreeCAD. If not, see * + * . * + * * + **************************************************************************/ + +#include "PreCompiled.h" +#ifndef _PreComp_ +#endif + +#include "ModelUuids.h" + +using namespace Materials; + +TYPESYSTEM_SOURCE(Materials::ModelUUIDs, Base::BaseClass) + +const QString ModelUUIDs::ModelUUID_Legacy_Father = + QString::fromStdString("9cdda8b6-b606-4778-8f13-3934d8668e67"); +const QString ModelUUIDs::ModelUUID_Legacy_MaterialStandard = + QString::fromStdString("1e2c0088-904a-4537-925f-64064c07d700"); + +const QString ModelUUIDs::ModelUUID_Mechanical_Density = + QString::fromStdString("454661e5-265b-4320-8e6f-fcf6223ac3af"); +const QString ModelUUIDs::ModelUUID_Mechanical_IsotropicLinearElastic = + QString::fromStdString("f6f9e48c-b116-4e82-ad7f-3659a9219c50"); +const QString ModelUUIDs::ModelUUID_Mechanical_LinearElastic = + QString::fromStdString("7b561d1d-fb9b-44f6-9da9-56a4f74d7536"); +const QString ModelUUIDs::ModelUUID_Mechanical_OgdenYld2004p18 = + QString::fromStdString("3ef9e427-cc25-43f7-817f-79ff0d49625f"); +const QString ModelUUIDs::ModelUUID_Mechanical_OrthotropicLinearElastic = + QString::fromStdString("b19ccc6b-a431-418e-91c2-0ac8c649d146"); + +const QString ModelUUIDs::ModelUUID_Fluid_Default = + QString::fromStdString("1ae66d8c-1ba1-4211-ad12-b9917573b202"); + +const QString ModelUUIDs::ModelUUID_Thermal_Default = + QString::fromStdString("9959d007-a970-4ea7-bae4-3eb1b8b883c7"); + +const QString ModelUUIDs::ModelUUID_Electromagnetic_Default = + QString::fromStdString("b2eb5f48-74b3-4193-9fbb-948674f427f3"); + +const QString ModelUUIDs::ModelUUID_Architectural_Default = + QString::fromStdString("32439c3b-262f-4b7b-99a8-f7f44e5894c8"); + +const QString ModelUUIDs::ModelUUID_Costs_Default = + QString::fromStdString("881df808-8726-4c2e-be38-688bb6cce466"); + +const QString ModelUUIDs::ModelUUID_Rendering_Basic = + QString::fromStdString("f006c7e4-35b7-43d5-bbf9-c5d572309e6e"); +const QString ModelUUIDs::ModelUUID_Rendering_Texture = + QString::fromStdString("bbdcc65b-67ca-489c-bd5c-a36e33d1c160"); +const QString ModelUUIDs::ModelUUID_Rendering_Advanced = + QString::fromStdString("c880f092-cdae-43d6-a24b-55e884aacbbf"); +const QString ModelUUIDs::ModelUUID_Rendering_Vector = + QString::fromStdString("fdf5a80e-de50-4157-b2e5-b6e5f88b680e"); diff --git a/src/Mod/Material/App/ModelUuids.h b/src/Mod/Material/App/ModelUuids.h index d160f13ac4..db667940db 100644 --- a/src/Mod/Material/App/ModelUuids.h +++ b/src/Mod/Material/App/ModelUuids.h @@ -24,50 +24,48 @@ #include +#include + +#include + namespace Materials { -// UUIDs for predefined material models +class MaterialsExport ModelUUIDs: public Base::BaseClass +{ + TYPESYSTEM_HEADER_WITH_OVERRIDE(); -static const QString ModelUUID_Legacy_Father = - QString::fromStdString("9cdda8b6-b606-4778-8f13-3934d8668e67"); -static const QString ModelUUID_Legacy_MaterialStandard = - QString::fromStdString("1e2c0088-904a-4537-925f-64064c07d700"); +public: + ModelUUIDs() + {} + ~ModelUUIDs() override = default; -static const QString ModelUUID_Mechanical_Density = - QString::fromStdString("454661e5-265b-4320-8e6f-fcf6223ac3af"); -static const QString ModelUUID_Mechanical_IsotropicLinearElastic = - QString::fromStdString("f6f9e48c-b116-4e82-ad7f-3659a9219c50"); -static const QString ModelUUID_Mechanical_LinearElastic = - QString::fromStdString("7b561d1d-fb9b-44f6-9da9-56a4f74d7536"); -static const QString ModelUUID_Mechanical_OgdenYld2004p18 = - QString::fromStdString("3ef9e427-cc25-43f7-817f-79ff0d49625f"); -static const QString ModelUUID_Mechanical_OrthotropicLinearElastic = - QString::fromStdString("b19ccc6b-a431-418e-91c2-0ac8c649d146"); + // UUIDs for predefined material models -static const QString ModelUUID_Fluid_Default = - QString::fromStdString("1ae66d8c-1ba1-4211-ad12-b9917573b202"); + static const QString ModelUUID_Legacy_Father; + static const QString ModelUUID_Legacy_MaterialStandard; -static const QString ModelUUID_Thermal_Default = - QString::fromStdString("9959d007-a970-4ea7-bae4-3eb1b8b883c7"); + static const QString ModelUUID_Mechanical_Density; + static const QString ModelUUID_Mechanical_IsotropicLinearElastic; + static const QString ModelUUID_Mechanical_LinearElastic; + static const QString ModelUUID_Mechanical_OgdenYld2004p18; + static const QString ModelUUID_Mechanical_OrthotropicLinearElastic; -static const QString ModelUUID_Electromagnetic_Default = - QString::fromStdString("b2eb5f48-74b3-4193-9fbb-948674f427f3"); + static const QString ModelUUID_Fluid_Default; -static const QString ModelUUID_Architectural_Default = - QString::fromStdString("32439c3b-262f-4b7b-99a8-f7f44e5894c8"); + static const QString ModelUUID_Thermal_Default; -static const QString ModelUUID_Costs_Default = - QString::fromStdString("881df808-8726-4c2e-be38-688bb6cce466"); + static const QString ModelUUID_Electromagnetic_Default; -static const QString ModelUUID_Rendering_Basic = - QString::fromStdString("f006c7e4-35b7-43d5-bbf9-c5d572309e6e"); -static const QString ModelUUID_Rendering_Texture = - QString::fromStdString("bbdcc65b-67ca-489c-bd5c-a36e33d1c160"); -static const QString ModelUUID_Rendering_Advanced = - QString::fromStdString("c880f092-cdae-43d6-a24b-55e884aacbbf"); -static const QString ModelUUID_Rendering_Vector = - QString::fromStdString("fdf5a80e-de50-4157-b2e5-b6e5f88b680e"); + static const QString ModelUUID_Architectural_Default; + + static const QString ModelUUID_Costs_Default; + + static const QString ModelUUID_Rendering_Basic; + static const QString ModelUUID_Rendering_Texture; + static const QString ModelUUID_Rendering_Advanced; + static const QString ModelUUID_Rendering_Vector; +}; } // namespace Materials diff --git a/src/Mod/Material/App/PreCompiled.h b/src/Mod/Material/App/PreCompiled.h index c643eb4f42..f602f3773c 100644 --- a/src/Mod/Material/App/PreCompiled.h +++ b/src/Mod/Material/App/PreCompiled.h @@ -55,10 +55,6 @@ // Qt #include -// Boost -#include -#include - #endif //_PreComp_ #endif // MATERIAL_PRECOMPILED_H diff --git a/src/Mod/Material/App/UUIDsPy.xml b/src/Mod/Material/App/UUIDsPy.xml new file mode 100644 index 0000000000..29138e05c3 --- /dev/null +++ b/src/Mod/Material/App/UUIDsPy.xml @@ -0,0 +1,116 @@ + + + + + + Material model UUID identifiers. + + + + UUID for model System:Legacy/Father + + + + + + UUID for model System:Legacy/MaterialStandard + + + + + + UUID for model System:Mechanical/Density + + + + + + UUID for model System:Mechanical/IsotropicLinearElastic + + + + + + UUID for model System:Mechanical/LinearElastic + + + + + + UUID for model System:Mechanical/OgdenYld2004p18 + + + + + + UUID for model System:Mechanical/OrthotropicLinearElastic + + + + + + UUID for model System:Fluid/Fluid + + + + + + UUID for model System:Thermal/Thermal + + + + + + UUID for model System:Electromagnetic/Electromagnetic + + + + + + UUID for model System:Architectural/Architectural + + + + + + UUID for model System:Costs/Costs + + + + + + UUID for model System:Rendering/BasicRendering + + + + + + UUID for model System:Rendering/TextureRendering + + + + + + UUID for model System:Rendering/AdvancedRendering + + + + + + UUID for model System:Rendering/VectorRendering + + + + + diff --git a/src/Mod/Material/App/UUIDsPyImpl.cpp b/src/Mod/Material/App/UUIDsPyImpl.cpp new file mode 100644 index 0000000000..94d3fb9071 --- /dev/null +++ b/src/Mod/Material/App/UUIDsPyImpl.cpp @@ -0,0 +1,139 @@ +/*************************************************************************** + * Copyright (c) 2023 David Carter * + * * + * This file is part of FreeCAD. * + * * + * FreeCAD is free software: you can redistribute it and/or modify it * + * under the terms of the GNU Lesser General Public License as * + * published by the Free Software Foundation, either version 2.1 of the * + * License, or (at your option) any later version. * + * * + * FreeCAD is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with FreeCAD. If not, see * + * . * + * * + **************************************************************************/ + +#include "PreCompiled.h" + +#include "ModelUuids.h" + +#include "UUIDsPy.h" + +#include "UUIDsPy.cpp" + +using namespace Materials; + +// returns a string which represents the object e.g. when printed in python +std::string UUIDsPy::representation() const +{ + return {""}; +} + +PyObject* UUIDsPy::PyMake(struct _typeobject*, PyObject*, PyObject*) // Python wrapper +{ + // create a new instance of UUIDsPy and the Twin object + return new UUIDsPy(new ModelUUIDs); +} + +// constructor method +int UUIDsPy::PyInit(PyObject* /*args*/, PyObject* /*kwd*/) +{ + return 0; +} + +Py::String UUIDsPy::getFather() const +{ + return Py::String(ModelUUIDs::ModelUUID_Legacy_Father.toStdString()); +} + +Py::String UUIDsPy::getMaterialStandard() const +{ + return Py::String(ModelUUIDs::ModelUUID_Legacy_MaterialStandard.toStdString()); +} + +Py::String UUIDsPy::getDensity() const +{ + return Py::String(ModelUUIDs::ModelUUID_Mechanical_Density.toStdString()); +} + +Py::String UUIDsPy::getIsotropicLinearElastic() const +{ + return Py::String(ModelUUIDs::ModelUUID_Mechanical_IsotropicLinearElastic.toStdString()); +} + +Py::String UUIDsPy::getLinearElastic() const +{ + return Py::String(ModelUUIDs::ModelUUID_Mechanical_LinearElastic.toStdString()); +} + +Py::String UUIDsPy::getOgdenYld2004p18() const +{ + return Py::String(ModelUUIDs::ModelUUID_Mechanical_OgdenYld2004p18.toStdString()); +} + +Py::String UUIDsPy::getOrthotropicLinearElastic() const +{ + return Py::String(ModelUUIDs::ModelUUID_Mechanical_OrthotropicLinearElastic.toStdString()); +} + +Py::String UUIDsPy::getFluid() const +{ + return Py::String(ModelUUIDs::ModelUUID_Fluid_Default.toStdString()); +} + +Py::String UUIDsPy::getThermal() const +{ + return Py::String(ModelUUIDs::ModelUUID_Thermal_Default.toStdString()); +} + +Py::String UUIDsPy::getElectromagnetic() const +{ + return Py::String(ModelUUIDs::ModelUUID_Electromagnetic_Default.toStdString()); +} + +Py::String UUIDsPy::getArchitectural() const +{ + return Py::String(ModelUUIDs::ModelUUID_Architectural_Default.toStdString()); +} + +Py::String UUIDsPy::getCosts() const +{ + return Py::String(ModelUUIDs::ModelUUID_Costs_Default.toStdString()); +} + +Py::String UUIDsPy::getBasicRendering() const +{ + return Py::String(ModelUUIDs::ModelUUID_Rendering_Basic.toStdString()); +} + +Py::String UUIDsPy::getTextureRendering() const +{ + return Py::String(ModelUUIDs::ModelUUID_Rendering_Texture.toStdString()); +} + +Py::String UUIDsPy::getAdvancedRendering() const +{ + Base::Console().Log(getModelUUIDsPtr()->ModelUUID_Rendering_Advanced.toStdString().c_str()); + return Py::String(getModelUUIDsPtr()->ModelUUID_Rendering_Advanced.toStdString()); +} + +Py::String UUIDsPy::getVectorRendering() const +{ + return Py::String(ModelUUIDs::ModelUUID_Rendering_Vector.toStdString()); +} + +PyObject* UUIDsPy::getCustomAttributes(const char* /*attr*/) const +{ + return nullptr; +} + +int UUIDsPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/) +{ + return 0; +} diff --git a/src/Mod/Material/App/trim.h b/src/Mod/Material/App/trim.h index a8b4a94d84..c4b038567a 100644 --- a/src/Mod/Material/App/trim.h +++ b/src/Mod/Material/App/trim.h @@ -22,7 +22,6 @@ #ifndef MATERIAL_TRIM_H #define MATERIAL_TRIM_H -#include #include namespace Materials diff --git a/src/Mod/Material/CMakeLists.txt b/src/Mod/Material/CMakeLists.txt index b9ae72647d..6263b1ea80 100644 --- a/src/Mod/Material/CMakeLists.txt +++ b/src/Mod/Material/CMakeLists.txt @@ -194,7 +194,6 @@ SET(MaterialModel_Files Resources/Models/Legacy/Father.yml Resources/Models/Legacy/MaterialStandard.yml Resources/Models/Mechanical/Density.yml - Resources/Models/Mechanical/HypotheticalExample.yml Resources/Models/Mechanical/IsotropicLinearElastic.yml Resources/Models/Mechanical/LinearElastic.yml Resources/Models/Mechanical/OgdenYld2004p18.yml @@ -206,6 +205,21 @@ SET(MaterialModel_Files Resources/Models/Thermal/Thermal.yml ) +set(MaterialTest_Files + materialtests/__init__.py + materialtests/TestModels.py + materialtests/TestMaterials.py +) + +ADD_CUSTOM_TARGET(MateriaTestLib ALL + SOURCES ${MaterialTest_Files} +) + +fc_target_copy_resource(MateriaTestLib + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_BINARY_DIR}/Mod/Material + ${MaterialTest_Files}) + ADD_CUSTOM_TARGET(MaterialScripts ALL SOURCES ${MaterialScripts_Files} ${Material_QRC_SRCS} ) @@ -275,8 +289,13 @@ INSTALL( DESTINATION Mod/Material ) +INSTALL( + FILES ${MaterialTest_Files} + DESTINATION Mod/Material/materialtests +) + foreach(file ${MaterialLib_Files} ${FluidMaterial_Files} ${AppearanceLib_Files} ${MaterialModel_Files}) - get_filename_component(filepath ${file} DIRECTORY) + cmake_path(REMOVE_FILENAME file OUTPUT_VARIABLE filepath) INSTALL( FILES ${file} DESTINATION ${CMAKE_INSTALL_DATADIR}/Mod/Material/${filepath} diff --git a/src/Mod/Material/Gui/AppMatGui.cpp b/src/Mod/Material/Gui/AppMatGui.cpp index f20967589b..b424067ca3 100644 --- a/src/Mod/Material/Gui/AppMatGui.cpp +++ b/src/Mod/Material/Gui/AppMatGui.cpp @@ -96,6 +96,9 @@ PyMOD_INIT_FUNC(MatGui) // register preferences pages on Material, the order here will be the order of the tabs in pref // widget + Gui::Dialog::DlgPreferencesImp::setGroupData("Material", + "Material", + QObject::tr("Material workbench")); new Gui::PrefPageProducer( QT_TRANSLATE_NOOP("QObject", "Material")); diff --git a/src/Mod/Material/Gui/Array2D.cpp b/src/Mod/Material/Gui/Array2D.cpp index 5e39884d82..799dec92f2 100644 --- a/src/Mod/Material/Gui/Array2D.cpp +++ b/src/Mod/Material/Gui/Array2D.cpp @@ -24,6 +24,8 @@ #include #endif +#include + #include #include @@ -39,32 +41,52 @@ using namespace MatGui; /* TRANSLATOR MatGui::Array2D */ -Array2D::Array2D(const QString& propertyName, Materials::Material* material, QWidget* parent) +Array2D::Array2D(const QString& propertyName, + std::shared_ptr material, + QWidget* parent) : QDialog(parent) , ui(new Ui_Array2D) + , _material(material) { ui->setupUi(this); if (material->hasPhysicalProperty(propertyName)) { - _property = &(material->getPhysicalProperty(propertyName)); + _property = material->getPhysicalProperty(propertyName); } else if (material->hasAppearanceProperty(propertyName)) { - _property = &(material->getAppearanceProperty(propertyName)); + _property = material->getAppearanceProperty(propertyName); } else { + Base::Console().Log("Property '%s' not found\n", propertyName.toStdString().c_str()); _property = nullptr; } if (_property) { + Base::Console().Log("Value type %d\n", + static_cast(_property->getMaterialValue()->getType())); _value = std::static_pointer_cast(_property->getMaterialValue()); } else { + Base::Console().Log("No value loaded\n"); _value = nullptr; } + if (_value) { + Base::Console().Log("Value type %d\n", static_cast(_value->getType())); + // auto value = _property->getMaterialValue()->getValue(); + // Base::Console().Log("\tQVariant type %d\n", value.userType()); + } setupDefault(); setupArray(); + ui->tableView->setContextMenuPolicy(Qt::CustomContextMenu); + connect(ui->tableView, &QWidget::customContextMenuRequested, this, &Array2D::onContextMenu); + + _deleteAction.setText(tr("Delete row")); + _deleteAction.setShortcut(Qt::Key_Delete); + connect(&_deleteAction, &QAction::triggered, this, &Array2D::onDelete); + ui->tableView->addAction(&_deleteAction); + connect(ui->standardButtons, &QDialogButtonBox::accepted, this, &Array2D::accept); connect(ui->standardButtons, &QDialogButtonBox::rejected, this, &Array2D::reject); } @@ -77,13 +99,16 @@ void Array2D::setupDefault() try { const Materials::MaterialProperty& column1 = _property->getColumn(0); - QString label = QString::fromStdString("Default ") + column1.getName(); + QString label = tr("Default ") + column1.getName(); ui->labelDefault->setText(label); if (column1.getPropertyType() == QString::fromStdString("Quantity")) { ui->editDefault->setMinimum(std::numeric_limits::min()); ui->editDefault->setMaximum(std::numeric_limits::max()); ui->editDefault->setUnitText(_property->getColumnUnits(0)); - ui->editDefault->setValue(_value->getDefault().getValue().value()); + if (!_value->defaultSet()) { + _value->setDefault(_property->getColumnNull(0).value()); + } + ui->editDefault->setValue(_value->getDefault().value()); connect(ui->editDefault, qOverload(&Gui::QuantitySpinBox::valueChanged), @@ -134,15 +159,99 @@ void Array2D::setupArray() auto table = ui->tableView; auto model = new Array2DModel(_property, _value, this); table->setModel(model); - table->setEditTriggers(QAbstractItemView::AllEditTriggers); + // table->setEditTriggers(QAbstractItemView::AllEditTriggers); + table->setSelectionMode(QAbstractItemView::SingleSelection); setColumnWidths(table); setColumnDelegates(table); + connect(model, &QAbstractItemModel::dataChanged, this, &Array2D::onDataChanged); +} + +void Array2D::onDataChanged(const QModelIndex& topLeft, + const QModelIndex& bottomRight, + const QVector& roles) +{ + Q_UNUSED(topLeft) + Q_UNUSED(bottomRight) + Q_UNUSED(roles) + + _material->setEditStateAlter(); } void Array2D::defaultValueChanged(const Base::Quantity& value) { _value->setDefault(QVariant::fromValue(value)); + _material->setEditStateAlter(); +} + +void Array2D::onContextMenu(const QPoint& pos) +{ + Base::Console().Log("Array2D::onContextMenu(%d,%d)\n", pos.x(), pos.y()); + QModelIndex index = ui->tableView->indexAt(pos); + Base::Console().Log("\tindex at (%d,%d)\n", index.row(), index.column()); + + + QMenu contextMenu(tr("Context menu"), this); + + contextMenu.addAction(&_deleteAction); + + contextMenu.exec(ui->tableView->mapToGlobal(pos)); +} + +bool Array2D::newRow(const QModelIndex& index) +{ + Array2DModel* model = static_cast(ui->tableView->model()); + return model->newRow(index); +} + +void Array2D::onDelete(bool checked) +{ + Q_UNUSED(checked) + + Base::Console().Log("Array2D::onDelete()\n"); + QItemSelectionModel* selectionModel = ui->tableView->selectionModel(); + if (!selectionModel->hasSelection() || newRow(selectionModel->currentIndex())) { + Base::Console().Log("\tNothing selected\n"); + return; + } + + int res = confirmDelete(); + if (res == QMessageBox::Cancel) { + return; + } +} + +int Array2D::confirmDelete() +{ + QMessageBox box(this); + box.setIcon(QMessageBox::Question); + box.setWindowTitle(QObject::tr("Confirm Delete")); + + QString prompt = QObject::tr("Are you sure you want to delete the row?"); + box.setText(prompt); + + box.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel); + box.setDefaultButton(QMessageBox::Cancel); + box.setEscapeButton(QMessageBox::Cancel); + + int res = QMessageBox::Cancel; + box.adjustSize(); // Silence warnings from Qt on Windows + switch (box.exec()) { + case QMessageBox::Ok: + deleteSelected(); + res = QMessageBox::Ok; + break; + } + + return res; +} + +void Array2D::deleteSelected() +{ + Array2DModel* model = static_cast(ui->tableView->model()); + QItemSelectionModel* selectionModel = ui->tableView->selectionModel(); + auto index = selectionModel->currentIndex(); + model->deleteRow(index); } void Array2D::accept() diff --git a/src/Mod/Material/Gui/Array2D.h b/src/Mod/Material/Gui/Array2D.h index f32f97e93e..11af3e5366 100644 --- a/src/Mod/Material/Gui/Array2D.h +++ b/src/Mod/Material/Gui/Array2D.h @@ -22,14 +22,20 @@ #ifndef MATGUI_ARRAY2D_H #define MATGUI_ARRAY2D_H +#include + #include +#include #include +#include #include +#include #include -#include "ArrayModel.h" #include +#include "ArrayModel.h" + namespace MatGui { @@ -40,26 +46,38 @@ class Array2D: public QDialog Q_OBJECT public: - explicit Array2D(const QString& propertyName, - Materials::Material* material, - QWidget* parent = nullptr); + Array2D(const QString& propertyName, + std::shared_ptr material, + QWidget* parent = nullptr); ~Array2D() override = default; + void onDataChanged(const QModelIndex& topLeft, + const QModelIndex& bottomRight, + const QVector& roles = QVector()); void defaultValueChanged(const Base::Quantity& value); + void onDelete(bool checked); + void onContextMenu(const QPoint& pos); void accept() override; void reject() override; private: std::unique_ptr ui; - const Materials::MaterialProperty* _property; + std::shared_ptr _material; + std::shared_ptr _property; std::shared_ptr _value; + QAction _deleteAction; + void setupDefault(); void setHeaders(QStandardItemModel* model); void setColumnWidths(QTableView* table); void setColumnDelegates(QTableView* table); void setupArray(); + + bool newRow(const QModelIndex& index); + int confirmDelete(); + void deleteSelected(); }; } // namespace MatGui diff --git a/src/Mod/Material/Gui/Array3D.cpp b/src/Mod/Material/Gui/Array3D.cpp index 956a033204..58f6299d7e 100644 --- a/src/Mod/Material/Gui/Array3D.cpp +++ b/src/Mod/Material/Gui/Array3D.cpp @@ -25,9 +25,12 @@ #include #endif +#include + #include #include +#include #include "Array3D.h" #include "ArrayDelegate.h" @@ -37,19 +40,23 @@ using namespace MatGui; -Array3D::Array3D(const QString& propertyName, Materials::Material* material, QWidget* parent) +Array3D::Array3D(const QString& propertyName, + std::shared_ptr material, + QWidget* parent) : QDialog(parent) , ui(new Ui_Array3D) + , _material(material) { ui->setupUi(this); if (material->hasPhysicalProperty(propertyName)) { - _property = &(material->getPhysicalProperty(propertyName)); + _property = material->getPhysicalProperty(propertyName); } else if (material->hasAppearanceProperty(propertyName)) { - _property = &(material->getAppearanceProperty(propertyName)); + _property = material->getAppearanceProperty(propertyName); } else { + Base::Console().Log("Property '%s' not found\n", propertyName.toStdString().c_str()); _property = nullptr; } if (_property) { @@ -57,6 +64,7 @@ Array3D::Array3D(const QString& propertyName, Materials::Material* material, QWi std::static_pointer_cast(_property->getMaterialValue()); } else { + Base::Console().Log("No value loaded\n"); _value = nullptr; } @@ -64,6 +72,22 @@ Array3D::Array3D(const QString& propertyName, Materials::Material* material, QWi setupDepthArray(); setupArray(); + ui->table3D->setContextMenuPolicy(Qt::CustomContextMenu); + connect(ui->table3D, &QWidget::customContextMenuRequested, this, &Array3D::onDepthContextMenu); + + ui->table2D->setContextMenuPolicy(Qt::CustomContextMenu); + connect(ui->table2D, &QWidget::customContextMenuRequested, this, &Array3D::on2DContextMenu); + + _deleteDepthAction.setText(tr("Delete row")); + // _deleteDepthAction.setShortcut(Qt::Key_Delete); + connect(&_deleteDepthAction, &QAction::triggered, this, &Array3D::onDepthDelete); + ui->table3D->addAction(&_deleteDepthAction); + + _delete2DAction.setText(tr("Delete row")); + // _delete2DAction.setShortcut(Qt::Key_Delete); + connect(&_delete2DAction, &QAction::triggered, this, &Array3D::on2DDelete); + ui->table2D->addAction(&_delete2DAction); + Base::Console().Log("Material '%s'\n", material->getName().toStdString().c_str()); Base::Console().Log("\tproperty '%s'\n", propertyName.toStdString().c_str()); @@ -78,6 +102,10 @@ Array3D::Array3D(const QString& propertyName, Materials::Material* material, QWi &QPushButton::clicked, this, &Array3D::onCancel); + + + QItemSelectionModel* selectionModel = ui->table3D->selectionModel(); + connect(selectionModel, &QItemSelectionModel::selectionChanged, this, &Array3D::onSelectDepth); } bool Array3D::onSplitter(QEvent* e) @@ -95,13 +123,16 @@ void Array3D::setupDefault() try { auto& column1 = _property->getColumn(0); - QString label = QString::fromStdString("Default ") + column1.getName(); + QString label = tr("Default ") + column1.getName(); ui->labelDefault->setText(label); if (column1.getPropertyType() == QString::fromStdString("Quantity")) { ui->editDefault->setMinimum(std::numeric_limits::min()); ui->editDefault->setMaximum(std::numeric_limits::max()); ui->editDefault->setUnitText(_property->getColumnUnits(0)); - ui->editDefault->setValue(_value->getDefault().getValue().value()); + if (!_value->defaultSet()) { + _value->setDefault(_property->getColumnNull(0).value()); + } + ui->editDefault->setValue(_value->getDefault().value()); connect(ui->editDefault, qOverload(&Gui::QuantitySpinBox::valueChanged), @@ -117,6 +148,7 @@ void Array3D::setupDefault() void Array3D::defaultValueChanged(const Base::Quantity& value) { _value->setDefault(QVariant::fromValue(value)); + _material->setEditStateAlter(); } void Array3D::setDepthColumnDelegate(QTableView* table) @@ -140,10 +172,43 @@ void Array3D::setupDepthArray() auto table = ui->table3D; auto model = new Array3DDepthModel(_property, _value, this); table->setModel(model); - table->setEditTriggers(QAbstractItemView::AllEditTriggers); + // table->setEditTriggers(QAbstractItemView::AllEditTriggers); + table->setSelectionMode(QAbstractItemView::SingleSelection); setDepthColumnWidth(table); setDepthColumnDelegate(table); + connect(model, &QAbstractItemModel::rowsInserted, this, &Array3D::onRowsInserted); + connect(model, &QAbstractItemModel::rowsRemoved, this, &Array3D::onRowsRemoved); + connect(model, &QAbstractItemModel::dataChanged, this, &Array3D::onDataChanged); +} + +void Array3D::onRowsInserted(const QModelIndex& parent, int first, int last) +{ + Q_UNUSED(parent) + Q_UNUSED(first) + Q_UNUSED(last) + + update2DArray(); +} + +void Array3D::onRowsRemoved(const QModelIndex& parent, int first, int last) +{ + Q_UNUSED(parent) + Q_UNUSED(first) + Q_UNUSED(last) + + update2DArray(); +} + +void Array3D::onDataChanged(const QModelIndex& topLeft, + const QModelIndex& bottomRight, + const QVector& roles) +{ + Q_UNUSED(topLeft) + Q_UNUSED(bottomRight) + Q_UNUSED(roles) + + _material->setEditStateAlter(); } void Array3D::setColumnWidths(QTableView* table) @@ -174,10 +239,190 @@ void Array3D::setupArray() auto table = ui->table2D; auto model = new Array3DModel(_property, _value, this); table->setModel(model); - table->setEditTriggers(QAbstractItemView::AllEditTriggers); + // table->setEditTriggers(QAbstractItemView::AllEditTriggers); + table->setSelectionMode(QAbstractItemView::SingleSelection); setColumnWidths(table); setColumnDelegates(table); + + if (_value->depth() == 0) { + table->setEnabled(false); + } + connect(model, &QAbstractItemModel::dataChanged, this, &Array3D::onDataChanged); +} + +void Array3D::onSelectDepth(const QItemSelection& selected, const QItemSelection& deselected) +{ + Q_UNUSED(deselected); + + QModelIndexList indexes = selected.indexes(); + + // This should be a list of length 1 + for (auto it = indexes.begin(); it != indexes.end(); it++) { + _value->setCurrentDepth(it->row()); + break; + } + + update2DArray(); +} + +void Array3D::update2DArray() +{ + auto table = ui->table2D; + auto model = static_cast(table->model()); + model->updateData(); + table->setEnabled(_value->depth() > 0); +} + +void Array3D::onDepthContextMenu(const QPoint& pos) +{ + Base::Console().Log("Array3D::onDepthContextMenu(%d,%d)\n", pos.x(), pos.y()); + QModelIndex index = ui->table3D->indexAt(pos); + Base::Console().Log("\tindex at (%d,%d)\n", index.row(), index.column()); + + + QMenu contextMenu(tr("Context menu"), this); + + contextMenu.addAction(&_deleteDepthAction); + + contextMenu.exec(ui->table3D->mapToGlobal(pos)); +} + +bool Array3D::newDepthRow(const QModelIndex& index) +{ + Array3DDepthModel* model = static_cast(ui->table3D->model()); + return model->newRow(index); +} + +void Array3D::onDepthDelete(bool checked) +{ + Q_UNUSED(checked) + + Base::Console().Log("Array3D::onDepthDelete()\n"); + QItemSelectionModel* selectionModel = ui->table3D->selectionModel(); + if (!selectionModel->hasSelection() || newDepthRow(selectionModel->currentIndex())) { + Base::Console().Log("\tNothing selected\n"); + return; + } + + int res = confirmDepthDelete(); + if (res == QMessageBox::Cancel) { + return; + } +} + +int Array3D::confirmDepthDelete() +{ + QMessageBox box(this); + box.setIcon(QMessageBox::Question); + box.setWindowTitle(tr("Confirm Delete")); + + QString prompt = tr("Are you sure you want to delete the row?"); + box.setText(prompt); + box.setInformativeText(tr("Removing this will also remove all 2D contents.")); + + box.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel); + box.setDefaultButton(QMessageBox::Cancel); + box.setEscapeButton(QMessageBox::Cancel); + + int res = QMessageBox::Cancel; + box.adjustSize(); // Silence warnings from Qt on Windows + switch (box.exec()) { + case QMessageBox::Ok: + deleteDepthSelected(); + res = QMessageBox::Ok; + break; + } + + return res; +} + +void Array3D::deleteDepthSelected() +{ + Array3DDepthModel* model = static_cast(ui->table3D->model()); + QItemSelectionModel* selectionModel = ui->table3D->selectionModel(); + auto index = selectionModel->currentIndex(); + model->deleteRow(index); + + auto depth = _value->currentDepth(); + if (depth >= _value->depth()) { + depth = depth - 1; + } + _value->setCurrentDepth(depth); + update2DArray(); +} + +void Array3D::on2DContextMenu(const QPoint& pos) +{ + Base::Console().Log("Array3D::onDepthContextMenu(%d,%d)\n", pos.x(), pos.y()); + QModelIndex index = ui->table2D->indexAt(pos); + Base::Console().Log("\tindex at (%d,%d)\n", index.row(), index.column()); + + + QMenu contextMenu(tr("Context menu"), this); + + contextMenu.addAction(&_delete2DAction); + + // contextMenu.exec(mapToGlobal(pos)); + contextMenu.exec(ui->table2D->mapToGlobal(pos)); +} + +bool Array3D::new2DRow(const QModelIndex& index) +{ + Array3DModel* model = static_cast(ui->table2D->model()); + return model->newRow(index); +} + +void Array3D::on2DDelete(bool checked) +{ + Q_UNUSED(checked) + + Base::Console().Log("Array3D::on2DDelete()\n"); + QItemSelectionModel* selectionModel = ui->table2D->selectionModel(); + if (!selectionModel->hasSelection() || new2DRow(selectionModel->currentIndex())) { + Base::Console().Log("\tNothing selected\n"); + return; + } + + int res = confirm2dDelete(); + if (res == QMessageBox::Cancel) { + return; + } +} + +int Array3D::confirm2dDelete() +{ + QMessageBox box(this); + box.setIcon(QMessageBox::Question); + box.setWindowTitle(tr("Confirm Delete")); + + QString prompt = tr("Are you sure you want to delete the row?"); + box.setText(prompt); + + box.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel); + box.setDefaultButton(QMessageBox::Cancel); + box.setEscapeButton(QMessageBox::Cancel); + + int res = QMessageBox::Cancel; + box.adjustSize(); // Silence warnings from Qt on Windows + switch (box.exec()) { + case QMessageBox::Ok: + delete2DSelected(); + res = QMessageBox::Ok; + break; + } + + return res; +} + +void Array3D::delete2DSelected() +{ + Array3DModel* model = static_cast(ui->table2D->model()); + QItemSelectionModel* selectionModel = ui->table2D->selectionModel(); + auto index = selectionModel->currentIndex(); + model->deleteRow(index); + + update2DArray(); } void Array3D::onOk(bool checked) diff --git a/src/Mod/Material/Gui/Array3D.h b/src/Mod/Material/Gui/Array3D.h index 63cdb4cf46..e0c376e654 100644 --- a/src/Mod/Material/Gui/Array3D.h +++ b/src/Mod/Material/Gui/Array3D.h @@ -22,11 +22,10 @@ #ifndef MATGUI_ARRAY3D_H #define MATGUI_ARRAY3D_H +#include #include #include #include -#include - namespace MatGui { @@ -37,22 +36,42 @@ class Array3D: public QDialog Q_OBJECT public: - explicit Array3D(const QString& propertyName, - Materials::Material* material, - QWidget* parent = nullptr); + Array3D(const QString& propertyName, + std::shared_ptr material, + QWidget* parent = nullptr); ~Array3D() override = default; void defaultValueChanged(const Base::Quantity& value); + void onRowsInserted(const QModelIndex& parent, int first, int last); + void onRowsRemoved(const QModelIndex& parent, int first, int last); + void onDataChanged(const QModelIndex& topLeft, + const QModelIndex& bottomRight, + const QVector& roles = QVector()); + void onSelectDepth(const QItemSelection& selected, const QItemSelection& deselected); bool onSplitter(QEvent* e); + void onDepthDelete(bool checked); + int confirmDepthDelete(); + void deleteDepthSelected(); + void on2DDelete(bool checked); + int confirm2dDelete(); + void delete2DSelected(); + void onDepthContextMenu(const QPoint& pos); + void on2DContextMenu(const QPoint& pos); void onOk(bool checked); void onCancel(bool checked); private: std::unique_ptr ui; - const Materials::MaterialProperty* _property; + std::shared_ptr _material; + std::shared_ptr _property; std::shared_ptr _value; + QAction _deleteDepthAction; + QAction _delete2DAction; + + bool newDepthRow(const QModelIndex& index); + bool new2DRow(const QModelIndex& index); void setupDefault(); void setDepthColumnWidth(QTableView* table); void setDepthColumnDelegate(QTableView* table); @@ -60,6 +79,7 @@ private: void setColumnWidths(QTableView* table); void setColumnDelegates(QTableView* table); void setupArray(); + void update2DArray(); }; } // namespace MatGui diff --git a/src/Mod/Material/Gui/ArrayDelegate.cpp b/src/Mod/Material/Gui/ArrayDelegate.cpp index 95c030a159..255cac8168 100644 --- a/src/Mod/Material/Gui/ArrayDelegate.cpp +++ b/src/Mod/Material/Gui/ArrayDelegate.cpp @@ -156,8 +156,8 @@ QWidget* ArrayDelegate::createWidget(QWidget* parent, const QVariant& item) cons else if (_type == Materials::MaterialValue::Boolean) { Gui::PrefComboBox* combo = new Gui::PrefComboBox(parent); combo->insertItem(0, QString::fromStdString("")); - combo->insertItem(1, QString::fromStdString("False")); - combo->insertItem(2, QString::fromStdString("True")); + combo->insertItem(1, tr("False")); + combo->insertItem(2, tr("True")); combo->setCurrentText(item.toString()); widget = combo; } diff --git a/src/Mod/Material/Gui/ArrayDelegate.h b/src/Mod/Material/Gui/ArrayDelegate.h index 74e9c76c36..2f07398a79 100644 --- a/src/Mod/Material/Gui/ArrayDelegate.h +++ b/src/Mod/Material/Gui/ArrayDelegate.h @@ -22,8 +22,6 @@ #ifndef MATGUI_ArrayDelegate_H #define MATGUI_ArrayDelegate_H -#include - #include #include #include @@ -35,8 +33,6 @@ #include #include -namespace fs = boost::filesystem; - namespace MatGui { @@ -44,10 +40,9 @@ class ArrayDelegate: public QStyledItemDelegate { Q_OBJECT public: - explicit ArrayDelegate( - Materials::MaterialValue::ValueType type = Materials::MaterialValue::None, - QString units = QString(), - QObject* parent = nullptr); + ArrayDelegate(Materials::MaterialValue::ValueType type = Materials::MaterialValue::None, + QString units = QString(), + QObject* parent = nullptr); virtual ~ArrayDelegate() = default; void paint(QPainter* painter, diff --git a/src/Mod/Material/Gui/ArrayModel.cpp b/src/Mod/Material/Gui/ArrayModel.cpp index 24c0ba8b42..8c1156faeb 100644 --- a/src/Mod/Material/Gui/ArrayModel.cpp +++ b/src/Mod/Material/Gui/ArrayModel.cpp @@ -26,6 +26,7 @@ #include +#include #include #include @@ -46,7 +47,7 @@ AbstractArrayModel::AbstractArrayModel(QObject* parent) //=== -Array2DModel::Array2DModel(const Materials::MaterialProperty* property, +Array2DModel::Array2DModel(std::shared_ptr property, std::shared_ptr value, QObject* parent) : AbstractArrayModel(parent) @@ -68,6 +69,12 @@ bool Array2DModel::newRow(const QModelIndex& index) const return (index.row() == _value->rows()); } +void Array2DModel::deleteRow(const QModelIndex& index) +{ + removeRows(index.row(), 1); + Q_EMIT dataChanged(index, index); +} + int Array2DModel::columnCount(const QModelIndex& parent) const { Q_UNUSED(parent); @@ -145,7 +152,7 @@ bool Array2DModel::insertRows(int row, int count, const QModelIndex& parent) int columns = columnCount(); for (int i = 0; i < count; i++) { - std::vector* rowPtr = new std::vector(); + auto rowPtr = std::make_shared>(); for (int j = 0; j < columns; j++) { rowPtr->push_back(_property->getColumnNull(j)); } @@ -162,6 +169,10 @@ bool Array2DModel::removeRows(int row, int count, const QModelIndex& parent) { beginRemoveRows(parent, row, row + count - 1); + for (int i = 0; i < count; i++) { + _value->deleteRow(row); + } + endRemoveRows(); return false; @@ -187,7 +198,7 @@ bool Array2DModel::removeColumns(int column, int count, const QModelIndex& paren //=== -Array3DDepthModel::Array3DDepthModel(const Materials::MaterialProperty* property, +Array3DDepthModel::Array3DDepthModel(std::shared_ptr property, std::shared_ptr value, QObject* parent) : AbstractArrayModel(parent) @@ -209,26 +220,34 @@ bool Array3DDepthModel::newRow(const QModelIndex& index) const return (index.row() == _value->depth()); } +void Array3DDepthModel::deleteRow(const QModelIndex& index) +{ + removeRows(index.row(), 1); + Q_EMIT dataChanged(index, index); +} + QVariant Array3DDepthModel::data(const QModelIndex& index, int role) const { if (role == Qt::DisplayRole) { try { - return _value->getValue(index.row(), index.column()); + Base::Quantity q = _value->getDepthValue(index.row()); + return QVariant::fromValue(q); + } + catch (const Materials::InvalidDepth&) { + } + catch (const Materials::InvalidRow&) { + } + catch (const Materials::InvalidColumn&) { } catch (const Materials::InvalidIndex&) { } try { - auto column = _property->getColumnType(index.column()); - if (column == Materials::MaterialValue::Quantity) { - Base::Quantity q = Base::Quantity(0, _property->getColumnUnits(index.column())); - return QVariant::fromValue(q); - } + Base::Quantity q = Base::Quantity(0, _property->getColumnUnits(0)); + return QVariant::fromValue(q); } catch (const Materials::InvalidColumn&) { } - - return QString(); } return QVariant(); @@ -259,8 +278,9 @@ bool Array3DDepthModel::setData(const QModelIndex& index, const QVariant& value, if (index.row() == _value->depth()) { insertRows(index.row(), 1); + _value->setCurrentDepth(index.row()); } - _value->setValue(index.row(), index.column(), value); + _value->setDepthValue(index.row(), value.value()); Q_EMIT dataChanged(index, index); return true; @@ -277,14 +297,8 @@ bool Array3DDepthModel::insertRows(int row, int count, const QModelIndex& parent { beginInsertRows(parent, row, row + count - 1); - int columns = columnCount(); for (int i = 0; i < count; i++) { - std::vector* rowPtr = new std::vector(); - for (int j = 0; j < columns; j++) { - rowPtr->push_back(_property->getColumnNull(j)); - } - - // _value->insertRow(row, rowPtr); + _value->addDepth(row, Base::Quantity(0, _property->getColumnUnits(0))); } endInsertRows(); @@ -296,6 +310,10 @@ bool Array3DDepthModel::removeRows(int row, int count, const QModelIndex& parent { beginRemoveRows(parent, row, row + count - 1); + for (int i = 0; i < count; i++) { + _value->deleteDepth(row); + } + endRemoveRows(); return false; @@ -321,7 +339,7 @@ bool Array3DDepthModel::removeColumns(int column, int count, const QModelIndex& //=== -Array3DModel::Array3DModel(const Materials::MaterialProperty* property, +Array3DModel::Array3DModel(std::shared_ptr property, std::shared_ptr value, QObject* parent) : AbstractArrayModel(parent) @@ -335,7 +353,15 @@ int Array3DModel::rowCount(const QModelIndex& parent) const return 0; // No children } - return _value->depth() + 1; // Will always have 1 empty row + try { + return _value->rows() + 1; // Will always have 1 empty row + } + catch (const Materials::InvalidDepth&) { + return 1; + } + catch (const Materials::InvalidRow&) { + return 1; + } } int Array3DModel::columnCount(const QModelIndex& parent) const @@ -347,15 +373,36 @@ int Array3DModel::columnCount(const QModelIndex& parent) const bool Array3DModel::newRow(const QModelIndex& index) const { - return (index.row() == _value->depth()); + try { + return (index.row() == _value->rows()); + } + catch (const Materials::InvalidDepth&) { + return true; + } + catch (const Materials::InvalidRow&) { + return true; + } +} + +void Array3DModel::deleteRow(const QModelIndex& index) +{ + removeRows(index.row(), 1); + Q_EMIT dataChanged(index, index); } QVariant Array3DModel::data(const QModelIndex& index, int role) const { if (role == Qt::DisplayRole) { - Base::Console().Error("Row %d, column %d\n", index.row(), index.column()); + // Base::Console().Log("Row %d, column %d\n", index.row(), index.column()); try { - return _value->getValue(index.row(), index.column() + 1); + Base::Quantity q = _value->getValue(index.row(), index.column()); + return QVariant::fromValue(q); + } + catch (const Materials::InvalidDepth&) { + } + catch (const Materials::InvalidRow&) { + } + catch (const Materials::InvalidColumn&) { } catch (const Materials::InvalidIndex&) { } @@ -364,16 +411,11 @@ QVariant Array3DModel::data(const QModelIndex& index, int role) const } try { - auto column = _property->getColumnType(index.column() + 1); - if (column == Materials::MaterialValue::Quantity) { - Base::Quantity q = Base::Quantity(0, _property->getColumnUnits(index.column() - 1)); - return QVariant::fromValue(q); - } + Base::Quantity q = Base::Quantity(0, _property->getColumnUnits(index.column() + 1)); + return QVariant::fromValue(q); } catch (const Materials::InvalidColumn&) { } - - return QString(); } return QVariant(); @@ -402,10 +444,32 @@ bool Array3DModel::setData(const QModelIndex& index, const QVariant& value, int { Q_UNUSED(role); - if (index.row() == _value->depth()) { + Base::Console().Log("Array3DModel::setData at (%d, %d, %d)\n", + _value->currentDepth(), + index.row(), + index.column()); + + if (_value->depth() == 0) { + // Create the first row + // _value->addDepth(Base::Quantity(0, _property->getColumnUnits(0))); + return false; + } + + if (index.row() == _value->rows()) { insertRows(index.row(), 1); } - _value->setValue(index.row(), index.column(), value); + try { + _value->setValue(index.row(), index.column(), value.value()); + } + catch (const Materials::InvalidDepth&) { + Base::Console().Error("Array3DModel::setData - InvalidDepth"); + } + catch (const Materials::InvalidRow&) { + Base::Console().Error("Array3DModel::setData - invalidRow"); + } + catch (const Materials::InvalidColumn&) { + Base::Console().Error("Array3DModel::setData - InvalidColumn"); + } Q_EMIT dataChanged(index, index); return true; @@ -424,12 +488,12 @@ bool Array3DModel::insertRows(int row, int count, const QModelIndex& parent) int columns = columnCount(); for (int i = 0; i < count; i++) { - std::vector* rowPtr = new std::vector(); + auto rowPtr = std::make_shared>(); for (int j = 0; j < columns; j++) { - rowPtr->push_back(_property->getColumnNull(j)); + rowPtr->push_back(_property->getColumnNull(j).value()); } - // _value->insertRow(row, rowPtr); + _value->insertRow(row, rowPtr); } endInsertRows(); @@ -441,6 +505,10 @@ bool Array3DModel::removeRows(int row, int count, const QModelIndex& parent) { beginRemoveRows(parent, row, row + count - 1); + for (int i = 0; i < count; i++) { + _value->deleteRow(row); + } + endRemoveRows(); return false; @@ -463,3 +531,13 @@ bool Array3DModel::removeColumns(int column, int count, const QModelIndex& paren return false; } + +void Array3DModel::updateData() +{ + beginResetModel(); + + // The table has changed at this point, typically by setting the current depth. + // The existing structure needs to be cleared and the table redrawn. + + endResetModel(); +} diff --git a/src/Mod/Material/Gui/ArrayModel.h b/src/Mod/Material/Gui/ArrayModel.h index 7bb4f6816d..739bd6524d 100644 --- a/src/Mod/Material/Gui/ArrayModel.h +++ b/src/Mod/Material/Gui/ArrayModel.h @@ -22,6 +22,8 @@ #ifndef MATGUI_ARRAYMODEL_H #define MATGUI_ARRAYMODEL_H +#include + #include #include #include @@ -36,7 +38,7 @@ namespace MatGui class AbstractArrayModel: public QAbstractTableModel { public: - explicit AbstractArrayModel(QObject* parent = nullptr); + AbstractArrayModel(QObject* parent = nullptr); ~AbstractArrayModel() override = default; virtual bool newRow(const QModelIndex& index) const = 0; @@ -45,14 +47,15 @@ public: class Array2DModel: public AbstractArrayModel { public: - explicit Array2DModel(const Materials::MaterialProperty* property = nullptr, - std::shared_ptr value = nullptr, - QObject* parent = nullptr); + Array2DModel(std::shared_ptr property = nullptr, + std::shared_ptr value = nullptr, + QObject* parent = nullptr); ~Array2DModel() override = default; // Overridden virtual functions int rowCount(const QModelIndex& parent = QModelIndex()) const override; bool newRow(const QModelIndex& index) const override; + void deleteRow(const QModelIndex& index); int columnCount(const QModelIndex& parent = QModelIndex()) const override; QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; QVariant @@ -67,21 +70,22 @@ public: bool removeColumns(int column, int count, const QModelIndex& parent = QModelIndex()) override; private: - const Materials::MaterialProperty* _property; + std::shared_ptr _property; std::shared_ptr _value; }; class Array3DDepthModel: public AbstractArrayModel { public: - explicit Array3DDepthModel(const Materials::MaterialProperty* property = nullptr, - std::shared_ptr value = nullptr, - QObject* parent = nullptr); + Array3DDepthModel(std::shared_ptr property = nullptr, + std::shared_ptr value = nullptr, + QObject* parent = nullptr); ~Array3DDepthModel() override = default; // Overridden virtual functions int rowCount(const QModelIndex& parent = QModelIndex()) const override; bool newRow(const QModelIndex& index) const override; + void deleteRow(const QModelIndex& index); int columnCount(const QModelIndex& parent = QModelIndex()) const override { Q_UNUSED(parent) @@ -100,21 +104,22 @@ public: bool removeColumns(int column, int count, const QModelIndex& parent = QModelIndex()) override; private: - const Materials::MaterialProperty* _property; + std::shared_ptr _property; std::shared_ptr _value; }; class Array3DModel: public AbstractArrayModel { public: - explicit Array3DModel(const Materials::MaterialProperty* property = nullptr, - std::shared_ptr value = nullptr, - QObject* parent = nullptr); + Array3DModel(std::shared_ptr property = nullptr, + std::shared_ptr value = nullptr, + QObject* parent = nullptr); ~Array3DModel() override = default; // Overridden virtual functions int rowCount(const QModelIndex& parent = QModelIndex()) const override; bool newRow(const QModelIndex& index) const override; + void deleteRow(const QModelIndex& index); int columnCount(const QModelIndex& parent = QModelIndex()) const override; QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; QVariant @@ -128,8 +133,10 @@ public: bool insertColumns(int column, int count, const QModelIndex& parent = QModelIndex()) override; bool removeColumns(int column, int count, const QModelIndex& parent = QModelIndex()) override; + void updateData(); + private: - const Materials::MaterialProperty* _property; + std::shared_ptr _property; std::shared_ptr _value; }; diff --git a/src/Mod/Material/Gui/DlgSettingsMaterial.h b/src/Mod/Material/Gui/DlgSettingsMaterial.h index 4f62921794..183bfd555f 100644 --- a/src/Mod/Material/Gui/DlgSettingsMaterial.h +++ b/src/Mod/Material/Gui/DlgSettingsMaterial.h @@ -35,7 +35,7 @@ class DlgSettingsMaterial: public Gui::Dialog::PreferencePage Q_OBJECT public: - explicit DlgSettingsMaterial(QWidget* parent = nullptr); + DlgSettingsMaterial(QWidget* parent = nullptr); ~DlgSettingsMaterial() override = default; protected: diff --git a/src/Mod/Material/Gui/MaterialDelegate.cpp b/src/Mod/Material/Gui/MaterialDelegate.cpp index 92f96ab7dd..ee9d4b7144 100644 --- a/src/Mod/Material/Gui/MaterialDelegate.cpp +++ b/src/Mod/Material/Gui/MaterialDelegate.cpp @@ -88,7 +88,7 @@ bool MaterialDelegate::editorEvent(QEvent* event, std::string type = propertyType.toStdString(); if (type == "Color") { Base::Console().Log("Edit color\n"); - showColorModal(item); + showColorModal(item, propertyName); // Mark as handled return true; } @@ -109,7 +109,7 @@ bool MaterialDelegate::editorEvent(QEvent* event, return QStyledItemDelegate::editorEvent(event, model, option, index); } -void MaterialDelegate::showColorModal(QStandardItem* item) +void MaterialDelegate::showColorModal(QStandardItem* item, QString propertyName) { QColor currentColor; // = d->col; currentColor.setRgba(parseColor(item->text())); @@ -126,14 +126,18 @@ void MaterialDelegate::showColorModal(QStandardItem* item) connect(dlg, &QColorDialog::finished, this, [&](int result) { if (result == QDialog::Accepted) { + Base::Console().Log("Accepted\n"); QColor color = dlg->selectedColor(); if (color.isValid()) { + Base::Console().Log("isValid\n"); QString colorText = QString(QString::fromStdString("(%1,%2,%3,%4)")) .arg(color.red() / 255.0) .arg(color.green() / 255.0) .arg(color.blue() / 255.0) .arg(color.alpha() / 255.0); item->setText(colorText); + Q_EMIT const_cast(this)->propertyChange(propertyName, + item->text()); } } }); @@ -143,7 +147,7 @@ void MaterialDelegate::showColorModal(QStandardItem* item) void MaterialDelegate::showArray2DModal(const QString& propertyName, QStandardItem* item) { - Materials::Material* material = item->data().value(); + auto material = item->data().value>(); Array2D* dlg = new Array2D(propertyName, material); dlg->setAttribute(Qt::WA_DeleteOnClose); @@ -161,7 +165,7 @@ void MaterialDelegate::showArray2DModal(const QString& propertyName, QStandardIt void MaterialDelegate::showArray3DModal(const QString& propertyName, QStandardItem* item) { - Materials::Material* material = item->data().value(); + auto material = item->data().value>(); Array3D* dlg = new Array3D(propertyName, material); dlg->setAttribute(Qt::WA_DeleteOnClose); @@ -411,8 +415,8 @@ QWidget* MaterialDelegate::createWidget(QWidget* parent, else if (type == "Boolean") { Gui::PrefComboBox* combo = new Gui::PrefComboBox(parent); combo->insertItem(0, QString::fromStdString("")); - combo->insertItem(1, QString::fromStdString("False")); - combo->insertItem(2, QString::fromStdString("True")); + combo->insertItem(1, tr("False")); + combo->insertItem(2, tr("True")); combo->setCurrentText(propertyValue); widget = combo; } diff --git a/src/Mod/Material/Gui/MaterialDelegate.h b/src/Mod/Material/Gui/MaterialDelegate.h index 1febeb11cf..a395fa8d9f 100644 --- a/src/Mod/Material/Gui/MaterialDelegate.h +++ b/src/Mod/Material/Gui/MaterialDelegate.h @@ -22,8 +22,6 @@ #ifndef MATGUI_MATERIALDELEGATE_H #define MATGUI_MATERIALDELEGATE_H -#include - #include #include #include @@ -35,8 +33,6 @@ #include #include -namespace fs = boost::filesystem; - namespace MatGui { @@ -44,7 +40,7 @@ class MaterialDelegate: public QStyledItemDelegate { Q_OBJECT public: - explicit MaterialDelegate(QObject* parent = nullptr); + MaterialDelegate(QObject* parent = nullptr); ~MaterialDelegate() override = default; QWidget* createEditor(QWidget* parent, @@ -76,7 +72,7 @@ private: const QString& propertyValue, const QString& propertyUnits) const; QRgb parseColor(const QString& color) const; - void showColorModal(QStandardItem* item); + void showColorModal(QStandardItem* item, QString propertyName); void showArray2DModal(const QString& propertyName, QStandardItem* item); void showArray3DModal(const QString& propertyName, QStandardItem* item); }; diff --git a/src/Mod/Material/Gui/MaterialSave.cpp b/src/Mod/Material/Gui/MaterialSave.cpp index 58d610e4e8..853c973ea2 100644 --- a/src/Mod/Material/Gui/MaterialSave.cpp +++ b/src/Mod/Material/Gui/MaterialSave.cpp @@ -21,6 +21,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ +#include #include #include #endif @@ -36,12 +37,15 @@ using namespace MatGui; /* TRANSLATOR MatGui::MaterialsEditor */ -MaterialSave::MaterialSave(Materials::Material* material, QWidget* parent) +MaterialSave::MaterialSave(std::shared_ptr material, QWidget* parent) : QDialog(parent) , ui(new Ui_MaterialSave) , _material(material) + , _saveInherited(true) , _selectedPath(QString::fromStdString("/")) + , _selectedFull(QString::fromStdString("/")) , _selectedUUID(QString()) + , _deleteAction(this) { ui->setupUi(this); @@ -57,6 +61,9 @@ MaterialSave::MaterialSave(Materials::Material* material, QWidget* parent) } _filename = QString(ui->editFilename->text()); // No filename by default + ui->checkDerived->setChecked(_saveInherited); + connect(ui->checkDerived, &QCheckBox::stateChanged, this, &MaterialSave::onInherited); + connect(ui->standardButtons->button(QDialogButtonBox::Ok), &QPushButton::clicked, this, @@ -73,11 +80,25 @@ MaterialSave::MaterialSave(Materials::Material* material, QWidget* parent) connect(ui->buttonNewFolder, &QPushButton::clicked, this, &MaterialSave::onNewFolder); connect(ui->editFilename, &QLineEdit::textEdited, this, &MaterialSave::onFilename); + ui->treeMaterials->setContextMenuPolicy(Qt::CustomContextMenu); + connect(ui->treeMaterials, + &QWidget::customContextMenuRequested, + this, + &MaterialSave::onContextMenu); + + _deleteAction.setText(tr("Delete")); + _deleteAction.setShortcut(Qt::Key_Delete); + connect(&_deleteAction, &QAction::triggered, this, &MaterialSave::onDelete); + ui->treeMaterials->addAction(&_deleteAction); + QItemSelectionModel* selectionModel = ui->treeMaterials->selectionModel(); connect(selectionModel, &QItemSelectionModel::selectionChanged, this, &MaterialSave::onSelectModel); + + auto model = static_cast(ui->treeMaterials->model()); + connect(model, &QStandardItemModel::itemChanged, this, &MaterialSave::onItemChanged); } /* @@ -88,6 +109,13 @@ MaterialSave::~MaterialSave() // no need to delete child widgets, Qt does it all for us } +void MaterialSave::onInherited(int state) +{ + Q_UNUSED(state) + + _saveInherited = ui->checkDerived->isChecked(); +} + void MaterialSave::onOk(bool checked) { Q_UNUSED(checked) @@ -100,18 +128,145 @@ void MaterialSave::onOk(bool checked) } auto variant = ui->comboLibrary->currentData(); - auto library = variant.value(); + auto library = variant.value>(); QFileInfo filepath(_selectedPath + QString::fromStdString("/") + name + QString::fromStdString(".FCMat")); Base::Console().Log("saveMaterial(library(%s), material(%s), path(%s))\n", - library.getName().toStdString().c_str(), + library->getName().toStdString().c_str(), _material->getName().toStdString().c_str(), filepath.filePath().toStdString().c_str()); - _manager.saveMaterial(&library, *_material, filepath.filePath()); + + if (library->fileExists(filepath.filePath())) { + // confirm overwrite + auto res = confirmOverwrite(_filename); + if (res == QMessageBox::Cancel) { + return; + } + + _manager.saveMaterial(library, _material, filepath.filePath(), true, false, _saveInherited); + accept(); + return; + } + + bool saveAsCopy = false; + if (_manager.exists(_material->getUUID())) { + // Does it already exist in this library? + if (_manager.exists(library, _material->getUUID())) { + // Confirm saving a new material + auto res = confirmNewMaterial(); + if (res == QMessageBox::Cancel) { + return; + } + // saveAsCopy = false = already done + } + else { + // Copy or new + auto res = confirmCopy(); + if (res == QMessageBox::Cancel) { + return; + } + else if (res == QMessageBox::Save) { + // QMessageBox::Save saves as normal, a duplicate + saveAsCopy = true; + } + // QMessageBox::Ok saves a new material + } + } + + _manager + .saveMaterial(library, _material, filepath.filePath(), false, saveAsCopy, _saveInherited); accept(); } +int MaterialSave::confirmOverwrite(const QString& filename) +{ + QMessageBox box(this); + box.setIcon(QMessageBox::Question); + box.setWindowTitle(QObject::tr("Confirm Overwrite")); + + QFileInfo info(_selectedFull); + QString prompt = tr("Are you sure you want to save over '%1'?").arg(filename); + box.setText(prompt); + + box.setInformativeText(tr("Saving over the original file may cause other documents to break. " + "This is not recommended.")); + + box.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel); + box.setDefaultButton(QMessageBox::Cancel); + box.setEscapeButton(QMessageBox::Cancel); + + int res = QMessageBox::Cancel; + box.adjustSize(); // Silence warnings from Qt on Windows + switch (box.exec()) { + case QMessageBox::Ok: + res = QMessageBox::Ok; + break; + } + + return res; +} + +int MaterialSave::confirmNewMaterial() +{ + QMessageBox box(this); + box.setIcon(QMessageBox::Question); + box.setWindowTitle(tr("Confirm Save As New Material")); + + QString prompt = tr("Save as new material"); + box.setText(prompt); + + box.setInformativeText(tr( + "This material already exists in this library. Would you like to save as a new material?")); + + box.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel); + box.setDefaultButton(QMessageBox::Cancel); + box.setEscapeButton(QMessageBox::Cancel); + + int res = QMessageBox::Cancel; + box.adjustSize(); // Silence warnings from Qt on Windows + switch (box.exec()) { + case QMessageBox::Ok: + res = QMessageBox::Ok; + break; + } + + return res; +} + +int MaterialSave::confirmCopy() +{ + QMessageBox box(this); + box.setIcon(QMessageBox::Question); + box.setWindowTitle(tr("Confirm Save As Copy")); + + QString prompt = tr("Save as Copy"); + box.setText(prompt); + + box.setInformativeText(tr("Saving a copy is not recommended as it can break other documents. " + "We recommend you save as a new material.")); + + QPushButton* duplicateButton = box.addButton(tr("Save Copy"), QMessageBox::AcceptRole); + QPushButton* newButton = box.addButton(tr("Save As New"), QMessageBox::ActionRole); + QPushButton* cancelButton = box.addButton(QMessageBox::Cancel); + + box.setDefaultButton(cancelButton); + box.setEscapeButton(cancelButton); + + box.adjustSize(); // Silence warnings from Qt on Windows + box.exec(); + + int res = QMessageBox::Cancel; + if (box.clickedButton() == duplicateButton) { + res = QMessageBox::Save; + } + else if (box.clickedButton() == newButton) { + res = QMessageBox::Ok; + } + + return res; +} + void MaterialSave::onCancel(bool checked) { Q_UNUSED(checked) @@ -135,7 +290,7 @@ void MaterialSave::setLibraries() for (auto library : *libraries) { if (!library->isReadOnly()) { QVariant libraryVariant; - libraryVariant.setValue(*library); + libraryVariant.setValue(library); ui->comboLibrary->addItem(library->getName(), libraryVariant); } } @@ -163,31 +318,34 @@ void MaterialSave::addExpanded(QTreeView* tree, QStandardItemModel* parent, QSta void MaterialSave::addMaterials( QStandardItem& parent, - const std::shared_ptr> modelTree, + const std::shared_ptr>> + modelTree, const QIcon& folderIcon, const QIcon& icon) { auto tree = ui->treeMaterials; for (auto& mat : *modelTree) { - Materials::MaterialTreeNode* nodePtr = mat.second; + std::shared_ptr nodePtr = mat.second; if (nodePtr->getType() == Materials::MaterialTreeNode::DataNode) { - const Materials::Material* material = nodePtr->getData(); + std::shared_ptr material = nodePtr->getData(); QString uuid = material->getUUID(); Base::Console().Log("Material path '%s'\n", material->getDirectory().toStdString().c_str()); - // auto card = new QStandardItem(icon, material->getName()); auto card = new QStandardItem(icon, mat.first); - // card->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled - // | Qt::ItemIsDropEnabled); + card->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled + | Qt::ItemIsDropEnabled); card->setData(QVariant(uuid), Qt::UserRole); addExpanded(tree, &parent, card); } else { + Base::Console().Log("Material folder path '%s'\n", mat.first.toStdString().c_str()); auto node = new QStandardItem(folderIcon, mat.first); + node->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled + | Qt::ItemIsDropEnabled | Qt::ItemIsEditable); addExpanded(tree, &parent, node); - // node->setFlags(Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled); + auto treeMap = nodePtr->getFolder(); addMaterials(*node, treeMap, folderIcon, icon); } @@ -202,13 +360,14 @@ void MaterialSave::showSelectedTree() if (ui->comboLibrary->count() > 0) { auto variant = ui->comboLibrary->currentData(); - auto library = variant.value(); - QIcon icon(library.getIconPath()); + auto library = variant.value>(); + QIcon icon(library->getIconPath()); QIcon folderIcon(QString::fromStdString(":/icons/folder.svg")); - _libraryName = library.getName(); + _libraryName = library->getName(); _selectedPath = QString::fromStdString("/") + _libraryName; + _selectedFull = _selectedPath; - auto lib = new QStandardItem(library.getName()); + auto lib = new QStandardItem(library->getName()); lib->setFlags(Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled); addExpanded(tree, model, lib); @@ -246,6 +405,7 @@ void MaterialSave::onSelectModel(const QItemSelection& selected, const QItemSele if (indexes.count() == 0) { Base::Console().Log("Nothing selected\n"); _selectedPath = QString::fromStdString("/") + _libraryName; + _selectedFull = _selectedPath; _selectedUUID = QString(); Base::Console().Log("\tSelected path '%s'\n", _selectedPath.toStdString().c_str()); return; @@ -258,11 +418,13 @@ void MaterialSave::onSelectModel(const QItemSelection& selected, const QItemSele if (_selected.isValid()) { Base::Console().Log("\tuuid %s\n", _selected.toString().toStdString().c_str()); _selectedPath = getPath(item->parent()); + _selectedFull = getPath(item); _selectedUUID = _selected.toString(); _filename = item->text(); } else { _selectedPath = getPath(item); + _selectedFull = _selectedPath; _selectedUUID = QString(); } } @@ -282,6 +444,34 @@ void MaterialSave::currentTextChanged(const QString& value) showSelectedTree(); } +std::shared_ptr MaterialSave::currentLibrary() +{ + auto variant = ui->comboLibrary->currentData(); + return variant.value>(); +} + +void MaterialSave::createFolder(const QString& path) +{ + auto library = currentLibrary(); + + _manager.createFolder(library, path); +} + +void MaterialSave::renameFolder(const QString& oldPath, const QString& newPath) +{ + auto library = currentLibrary(); + + _manager.renameFolder(library, oldPath, newPath); +} + +void MaterialSave::deleteRecursive(const QString& path) +{ + // This will delete files, folders, and any children + auto library = currentLibrary(); + + _manager.deleteRecursive(library, path); +} + void MaterialSave::onNewFolder(bool checked) { Q_UNUSED(checked) @@ -293,16 +483,53 @@ void MaterialSave::onNewFolder(bool checked) current = model->index(0, 0); } auto item = model->itemFromIndex(current); + + // Check for existing folders starting "New Folder" to prevent duplicates + int newCount = 0; if (item->hasChildren()) { + for (auto i = 0; i < item->rowCount(); i++) { + auto child = item->child(i); + if (child->text().startsWith(tr("New Folder"))) { + newCount++; + } + } + } + + // Folders have no associated data + if (item->data(Qt::UserRole).isNull()) { Base::Console().Log("Add new folder to '%s'\n", item->text().toStdString().c_str()); QIcon folderIcon(QString::fromStdString(":/icons/folder.svg")); - auto node = new QStandardItem(folderIcon, QString::fromStdString("New Folder")); + QString folderName = tr("New Folder"); + if (newCount > 0) { + folderName += QString::number(newCount); + } + auto node = new QStandardItem(folderIcon, folderName); + node->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled + | Qt::ItemIsDropEnabled | Qt::ItemIsEditable); addExpanded(tree, item, node); - // node->setFlags(Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled); + + Base::Console().Log("New folder index valid: %s\n", + node->index().isValid() ? "true" : "false"); + + QItemSelectionModel* selectionModel = ui->treeMaterials->selectionModel(); + selectionModel->select(node->index(), + QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Current); + + createFolder(getPath(node)); } } +void MaterialSave::onItemChanged(QStandardItem* item) +{ + Base::Console().Log("MaterialSave::onItemChanged('%s')\n", item->text().toStdString().c_str()); + QString oldPath = _selectedPath; + _selectedPath = getPath(item); + _selectedFull = _selectedPath; + Base::Console().Log("\tSelected path '%s'\n", _selectedPath.toStdString().c_str()); + renameFolder(oldPath, _selectedPath); +} + void MaterialSave::onFilename(const QString& text) { Base::Console().Log("MaterialSave::onFilename('%s')\n", text.toStdString().c_str()); @@ -310,4 +537,135 @@ void MaterialSave::onFilename(const QString& text) _filename = text; } +QString MaterialSave::pathFromIndex(const QModelIndex& index) const +{ + auto model = static_cast(index.model()); + auto item = model->itemFromIndex(index); + return getPath(item); +} + +void MaterialSave::onContextMenu(const QPoint& pos) +{ + Base::Console().Log("MaterialSave::onContextMenu(%d,%d)\n", pos.x(), pos.y()); + QModelIndex index = ui->treeMaterials->indexAt(pos); + QString path = pathFromIndex(index); + Base::Console().Log("\tindex at (%d,%d)->'%s'\n", + index.row(), + index.column(), + path.toStdString().c_str()); + + + QMenu contextMenu(tr("Context menu"), this); + + // QAction action1(tr("Delete"), this); + // action1.setShortcut(Qt::Key_Delete); + // connect(&action1, &QAction::triggered, this, &MaterialSave::onDelete); + contextMenu.addAction(&_deleteAction); + + contextMenu.exec(ui->treeMaterials->mapToGlobal(pos)); +} + +void MaterialSave::onDelete(bool checked) +{ + Q_UNUSED(checked) + + Base::Console().Log("MaterialSave::onDelete()\n"); + QItemSelectionModel* selectionModel = ui->treeMaterials->selectionModel(); + if (!selectionModel->hasSelection()) { + Base::Console().Log("\tNothing selected\n"); + return; + } + + Base::Console().Log("\tSelected path '%s'\n", _selectedFull.toStdString().c_str()); + int res = confirmDelete(this); + if (res == QMessageBox::Cancel) { + return; + } +} + +int MaterialSave::confirmDelete(QWidget* parent) +{ + auto library = currentLibrary(); + + if (library->isRoot(_selectedFull)) { + return QMessageBox::Cancel; + } + + QMessageBox box(parent ? parent : this); + box.setIcon(QMessageBox::Question); + box.setWindowTitle(QObject::tr("Confirm Delete")); + + QFileInfo info(_selectedFull); + QString prompt = QObject::tr("Are you sure you want to delete '%1'?").arg(info.fileName()); + box.setText(prompt); + + if (selectedHasChildren()) { + box.setInformativeText(QObject::tr("Removing this will also remove all contents.")); + } + box.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel); + box.setDefaultButton(QMessageBox::Cancel); + box.setEscapeButton(QMessageBox::Cancel); + + int res = QMessageBox::Cancel; + box.adjustSize(); // Silence warnings from Qt on Windows + switch (box.exec()) { + case QMessageBox::Ok: + deleteSelected(); + res = QMessageBox::Ok; + break; + } + + return res; +} + +bool MaterialSave::selectedHasChildren() +{ + auto tree = ui->treeMaterials; + auto model = static_cast(tree->model()); + auto current = tree->currentIndex(); + if (!current.isValid()) { + current = model->index(0, 0); + } + auto item = model->itemFromIndex(current); + + return item->hasChildren(); +} + +void MaterialSave::deleteSelected() +{ + Base::Console().Log("\tDelete selected path '%s'\n", _selectedFull.toStdString().c_str()); + auto library = currentLibrary(); + + if (!library->isRoot(_selectedFull)) { + _manager.deleteRecursive(library, _selectedFull); + removeSelectedFromTree(); + } +} + +void MaterialSave::removeChildren(QStandardItem* item) +{ + while (item->rowCount() > 0) { + auto child = item->child(0); + removeChildren(child); + item->removeRow(0); + } +} + +void MaterialSave::removeSelectedFromTree() +{ + auto tree = ui->treeMaterials; + auto model = static_cast(tree->model()); + auto current = tree->currentIndex(); + if (current.row() >= 0) { + auto item = model->itemFromIndex(current); + + // Remove the children + removeChildren(item); + item->parent()->removeRow(item->row()); + } + + QItemSelectionModel* selectionModel = ui->treeMaterials->selectionModel(); + selectionModel->clear(); +} + #include "moc_MaterialSave.cpp" diff --git a/src/Mod/Material/Gui/MaterialSave.h b/src/Mod/Material/Gui/MaterialSave.h index 56dc196cd1..620c21ba70 100644 --- a/src/Mod/Material/Gui/MaterialSave.h +++ b/src/Mod/Material/Gui/MaterialSave.h @@ -22,8 +22,9 @@ #ifndef MATGUI_MATERIALSAVE_H #define MATGUI_MATERIALSAVE_H -// #include +#include +#include #include #include #include @@ -41,39 +42,61 @@ class MaterialSave: public QDialog Q_OBJECT public: - explicit MaterialSave(Materials::Material* material, QWidget* parent = nullptr); + MaterialSave(std::shared_ptr material, QWidget* parent = nullptr); ~MaterialSave() override; void setLibraries(); void createModelTree(); void addExpanded(QTreeView* tree, QStandardItem* parent, QStandardItem* child); void addExpanded(QTreeView* tree, QStandardItemModel* parent, QStandardItem* child); - void - addMaterials(QStandardItem& parent, - const std::shared_ptr> modelTree, - const QIcon& folderIcon, - const QIcon& icon); + void addMaterials( + QStandardItem& parent, + const std::shared_ptr>> + modelTree, + const QIcon& folderIcon, + const QIcon& icon); void showSelectedTree(); void onSelectModel(const QItemSelection& selected, const QItemSelection& deselected); void currentTextChanged(const QString& value); void onNewFolder(bool checked); + void onItemChanged(QStandardItem* item); void onFilename(const QString& text); + void onContextMenu(const QPoint& pos); + void onDelete(bool checked); + void onInherited(int state); void onOk(bool checked); void onCancel(bool checked); + int confirmOverwrite(const QString& filename); + int confirmNewMaterial(); + int confirmCopy(); void accept() override; void reject() override; private: std::unique_ptr ui; Materials::MaterialManager _manager; - Materials::Material* _material; + std::shared_ptr _material; + bool _saveInherited; QString _selectedPath; + QString _selectedFull; QString _selectedUUID; QString _libraryName; QString _filename; + QAction _deleteAction; + QString getPath(const QStandardItem* item) const; + std::shared_ptr currentLibrary(); + void createFolder(const QString& path); + void renameFolder(const QString& oldPath, const QString& newPath); + void deleteRecursive(const QString& path); + QString pathFromIndex(const QModelIndex& index) const; + int confirmDelete(QWidget* parent); + bool selectedHasChildren(); + void deleteSelected(); + void removeChildren(QStandardItem* item); + void removeSelectedFromTree(); }; } // namespace MatGui diff --git a/src/Mod/Material/Gui/MaterialSave.ui b/src/Mod/Material/Gui/MaterialSave.ui index a6a719e5a6..7298e6a23a 100644 --- a/src/Mod/Material/Gui/MaterialSave.ui +++ b/src/Mod/Material/Gui/MaterialSave.ui @@ -83,6 +83,30 @@ + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Save as Inherited + + + + + diff --git a/src/Mod/Material/Gui/MaterialsEditor.cpp b/src/Mod/Material/Gui/MaterialsEditor.cpp index 7916805b0c..c3c15c6b2a 100644 --- a/src/Mod/Material/Gui/MaterialsEditor.cpp +++ b/src/Mod/Material/Gui/MaterialsEditor.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -35,6 +36,7 @@ #include #include +#include #include #include #include @@ -61,6 +63,7 @@ using namespace MatGui; MaterialsEditor::MaterialsEditor(QWidget* parent) : QDialog(parent) , ui(new Ui_MaterialsEditor) + , _material(std::make_shared()) , _edited(false) { ui->setupUi(this); @@ -72,6 +75,7 @@ MaterialsEditor::MaterialsEditor(QWidget* parent) createPhysicalTree(); createAppearanceTree(); createPreviews(); + setMaterialDefaults(); ui->buttonURL->setIcon(QIcon(QString::fromStdString(":/icons/internet-web-browser.svg"))); @@ -88,12 +92,35 @@ MaterialsEditor::MaterialsEditor(QWidget* parent) this, &MaterialsEditor::onSave); + connect(ui->editName, &QLineEdit::textEdited, this, &MaterialsEditor::onName); + connect(ui->editAuthor, &QLineEdit::textEdited, this, &MaterialsEditor::onAuthor); + connect(ui->editLicense, &QLineEdit::textEdited, this, &MaterialsEditor::onLicense); + connect(ui->editSourceURL, &QLineEdit::textEdited, this, &MaterialsEditor::onSourceURL); + connect(ui->editSourceReference, + &QLineEdit::textEdited, + this, + &MaterialsEditor::onSourceReference); + connect(ui->editDescription, &QTextEdit::textChanged, this, &MaterialsEditor::onDescription); + connect(ui->buttonURL, &QPushButton::clicked, this, &MaterialsEditor::onURL); connect(ui->buttonPhysicalAdd, &QPushButton::clicked, this, &MaterialsEditor::onPhysicalAdd); + connect(ui->buttonPhysicalRemove, + &QPushButton::clicked, + this, + &MaterialsEditor::onPhysicalRemove); connect(ui->buttonAppearanceAdd, &QPushButton::clicked, this, &MaterialsEditor::onAppearanceAdd); + connect(ui->buttonAppearanceRemove, + &QPushButton::clicked, + this, + &MaterialsEditor::onAppearanceRemove); + connect(ui->buttonInheritNew, + &QPushButton::clicked, + this, + &MaterialsEditor::onInheritNewMaterial); + connect(ui->buttonNew, &QPushButton::clicked, this, &MaterialsEditor::onNewMaterial); connect(ui->buttonFavorite, &QPushButton::clicked, this, &MaterialsEditor::onFavourite); QItemSelectionModel* selectionModel = ui->treeMaterials->selectionModel(); @@ -101,6 +128,13 @@ MaterialsEditor::MaterialsEditor(QWidget* parent) &QItemSelectionModel::selectionChanged, this, &MaterialsEditor::onSelectMaterial); + connect(ui->treeMaterials, &QTreeView::doubleClicked, this, &MaterialsEditor::onDoubleClick); + + ui->treeMaterials->setContextMenuPolicy(Qt::CustomContextMenu); + connect(ui->treeMaterials, + &QWidget::customContextMenuRequested, + this, + &MaterialsEditor::onContextMenu); } void MaterialsEditor::getFavorites() @@ -144,7 +178,7 @@ void MaterialsEditor::addFavorite(const QString& uuid) { // Ensure it is a material. New, unsaved materials will not be try { - const Materials::Material& material = _materialManager.getMaterial(uuid); + auto material = _materialManager.getMaterial(uuid); Q_UNUSED(material) } catch (const Materials::MaterialNotFound&) { @@ -227,7 +261,7 @@ void MaterialsEditor::addRecent(const QString& uuid) { // Ensure it is a material. New, unsaved materials will not be try { - const Materials::Material& material = _materialManager.getMaterial(uuid); + auto material = _materialManager.getMaterial(uuid); Q_UNUSED(material) } catch (const Materials::MaterialNotFound&) { @@ -257,16 +291,46 @@ bool MaterialsEditor::isRecent(const QString& uuid) const return false; } +void MaterialsEditor::onName(const QString& text) +{ + _material->setName(text); +} + +void MaterialsEditor::onAuthor(const QString& text) +{ + _material->setAuthor(text); +} + +void MaterialsEditor::onLicense(const QString& text) +{ + _material->setLicense(text); +} + +void MaterialsEditor::onSourceURL(const QString& text) +{ + _material->setURL(text); +} + +void MaterialsEditor::onSourceReference(const QString& text) +{ + _material->setReference(text); +} + +void MaterialsEditor::onDescription() +{ + _material->setDescription(ui->editDescription->toPlainText()); +} + void MaterialsEditor::propertyChange(const QString& property, const QString value) { Base::Console().Log("MaterialsEditor::propertyChange(%s) = '%s'\n", property.toStdString().c_str(), value.toStdString().c_str()); - if (_material.hasPhysicalProperty(property)) { - _material.setPhysicalValue(property, value); + if (_material->hasPhysicalProperty(property)) { + _material->setPhysicalValue(property, value); } - else if (_material.hasAppearanceProperty(property)) { - _material.setAppearanceValue(property, value); + else if (_material->hasAppearanceProperty(property)) { + _material->setAppearanceValue(property, value); updatePreview(); } _edited = true; @@ -287,12 +351,12 @@ void MaterialsEditor::onPhysicalAdd(bool checked) { Q_UNUSED(checked) - ModelSelect dialog(this, Materials::ModelManager::ModelFilter_Physical); + ModelSelect dialog(this, Materials::ModelFilter_Physical); dialog.setModal(true); if (dialog.exec() == QDialog::Accepted) { QString selected = dialog.selectedModel(); Base::Console().Log("Selected model '%s'\n", selected.toStdString().c_str()); - _material.addPhysical(selected); + _material->addPhysical(selected); updateMaterial(); } else { @@ -300,16 +364,39 @@ void MaterialsEditor::onPhysicalAdd(bool checked) } } +void MaterialsEditor::onPhysicalRemove(bool checked) +{ + Q_UNUSED(checked) + + QItemSelectionModel* selectionModel = ui->treePhysicalProperties->selectionModel(); + if (selectionModel->hasSelection()) { + const QModelIndex index = selectionModel->currentIndex().siblingAtColumn(0); + + const QStandardItemModel* treeModel = static_cast(index.model()); + + // Check we're the material model root. + auto item = treeModel->itemFromIndex(index); + auto group = item->parent(); + if (!group) { + QString propertyName = index.data().toString(); + + QString uuid = _material->getModelByName(propertyName); + _material->removePhysical(uuid); + updateMaterial(); + } + } +} + void MaterialsEditor::onAppearanceAdd(bool checked) { Q_UNUSED(checked) - ModelSelect dialog(this, Materials::ModelManager::ModelFilter_Appearance); + ModelSelect dialog(this, Materials::ModelFilter_Appearance); dialog.setModal(true); if (dialog.exec() == QDialog::Accepted) { QString selected = dialog.selectedModel(); Base::Console().Log("Selected model '%s'\n", selected.toStdString().c_str()); - _material.addAppearance(selected); + _material->addAppearance(selected); updateMaterial(); } else { @@ -317,12 +404,35 @@ void MaterialsEditor::onAppearanceAdd(bool checked) } } +void MaterialsEditor::onAppearanceRemove(bool checked) +{ + Q_UNUSED(checked) + + QItemSelectionModel* selectionModel = ui->treeAppearance->selectionModel(); + if (selectionModel->hasSelection()) { + const QModelIndex index = selectionModel->currentIndex().siblingAtColumn(0); + + const QStandardItemModel* treeModel = static_cast(index.model()); + + // Check we're the material model root. + auto item = treeModel->itemFromIndex(index); + auto group = item->parent(); + if (!group) { + QString propertyName = index.data().toString(); + + QString uuid = _material->getModelByName(propertyName); + _material->removeAppearance(uuid); + updateMaterial(); + } + } +} + void MaterialsEditor::onFavourite(bool checked) { Q_UNUSED(checked) Base::Console().Log("Favorite\n"); - auto selected = _material.getUUID(); + auto selected = _material->getUUID(); if (isFavorite(selected)) { removeFavorite(selected); } @@ -331,6 +441,76 @@ void MaterialsEditor::onFavourite(bool checked) } } +void MaterialsEditor::setMaterialDefaults() +{ + _material->setName(tr("Unnamed")); + std::string Author = App::GetApplication() + .GetParameterGroupByPath("User parameter:BaseApp/Preferences/Document") + ->GetASCII("prefAuthor", ""); + _material->setAuthor(QString::fromStdString(Author)); + + // license stuff + auto paramGrp {App::GetApplication().GetParameterGroupByPath( + "User parameter:BaseApp/Preferences/Document")}; + auto index = static_cast(paramGrp->GetInt("prefLicenseType", 0)); + const char* name = App::licenseItems.at(index).at(App::posnOfFullName); + // const char* url = App::licenseItems.at(index).at(App::posnOfUrl); + // std::string licenseUrl = (paramGrp->GetASCII("prefLicenseUrl", url)); + _material->setLicense(QString::fromStdString(name)); + + // Empty materials will have no parent + _materialManager.dereference(_material); + + updateMaterial(); + _material->resetEditState(); +} + +void MaterialsEditor::onNewMaterial(bool checked) +{ + Q_UNUSED(checked) + + Base::Console().Log("New Material\n"); + + // Ensure data is saved (or discarded) before changing materials + if (_material->getEditState() != Materials::Material::ModelEdit_None) { + // Prompt the user to save or discard changes + Base::Console().Log("*** Material edited!!!\n"); + int res = confirmSave(this); + if (res == QMessageBox::Cancel) { + return; + } + } + + // Create a new material + _material = std::make_shared(); + setMaterialDefaults(); +} + +void MaterialsEditor::onInheritNewMaterial(bool checked) +{ + Q_UNUSED(checked) + + Base::Console().Log("Inherit New Material\n"); + + // Save the current UUID to use as out parent + auto parent = _material->getUUID(); + + // Ensure data is saved (or discarded) before changing materials + if (_material->getEditState() != Materials::Material::ModelEdit_None) { + // Prompt the user to save or discard changes + Base::Console().Log("*** Material edited!!!\n"); + int res = confirmSave(this); + if (res == QMessageBox::Cancel) { + return; + } + } + + // Create a new material + _material = std::make_shared(); + _material->setParentUUID(parent); + setMaterialDefaults(); +} + void MaterialsEditor::onOk(bool checked) { Q_UNUSED(checked) @@ -354,17 +534,18 @@ void MaterialsEditor::onSave(bool checked) void MaterialsEditor::saveMaterial() { - MaterialSave dialog(&_material, this); + MaterialSave dialog(_material, this); dialog.setModal(true); if (dialog.exec() == QDialog::Accepted) { - _material.resetEditState(); + updateMaterialGeneral(); + _material->resetEditState(); refreshMaterialTree(); } } void MaterialsEditor::accept() { - addRecent(_material.getUUID()); + addRecent(_material->getUUID()); QDialog::accept(); } @@ -379,15 +560,16 @@ void MaterialsEditor::reject() void MaterialsEditor::addMaterials( QStandardItem& parent, - const std::shared_ptr> modelTree, + const std::shared_ptr>> + modelTree, const QIcon& folderIcon, const QIcon& icon) { auto tree = ui->treeMaterials; for (auto& mat : *modelTree) { - Materials::MaterialTreeNode* nodePtr = mat.second; + std::shared_ptr nodePtr = mat.second; if (nodePtr->getType() == Materials::MaterialTreeNode::DataNode) { - const Materials::Material* material = nodePtr->getData(); + auto material = nodePtr->getData(); QString uuid = material->getUUID(); // Base::Console().Log("Material path '%s'\n", // material->getDirectory().toStdString().c_str()); @@ -429,9 +611,9 @@ void MaterialsEditor::createPhysicalTree() tree->setModel(model); QStringList headers; - headers.append(QString::fromStdString("Property")); - headers.append(QString::fromStdString("Value")); - headers.append(QString::fromStdString("Type")); + headers.append(tr("Property")); + headers.append(tr("Value")); + headers.append(tr("Type")); model->setHorizontalHeaderLabels(headers); tree->setColumnWidth(0, 250); @@ -444,6 +626,12 @@ void MaterialsEditor::createPhysicalTree() tree->setItemDelegateForColumn(1, delegate); connect(delegate, &MaterialDelegate::propertyChange, this, &MaterialsEditor::propertyChange); + + // QItemSelectionModel* selectionModel = ui->treePhysicalProperties->selectionModel(); + // connect(selectionModel, + // &QItemSelectionModel::selectionChanged, + // this, + // &MaterialsEditor::onSelectPhysicalProperty); } void MaterialsEditor::createPreviews() @@ -468,9 +656,9 @@ void MaterialsEditor::createAppearanceTree() tree->setModel(model); QStringList headers; - headers.append(QString::fromStdString("Property")); - headers.append(QString::fromStdString("Value")); - headers.append(QString::fromStdString("Type")); + headers.append(tr("Property")); + headers.append(tr("Value")); + headers.append(tr("Type")); model->setHorizontalHeaderLabels(headers); tree->setColumnWidth(0, 250); @@ -490,10 +678,10 @@ void MaterialsEditor::addRecents(QStandardItem* parent) auto tree = ui->treeMaterials; for (auto& uuid : _recents) { try { - const Materials::Material& material = getMaterialManager().getMaterial(uuid); + auto material = getMaterialManager().getMaterial(uuid); - QIcon icon = QIcon(material.getLibrary().getIconPath()); - auto card = new QStandardItem(icon, material.getName()); + QIcon icon = QIcon(material->getLibrary()->getIconPath()); + auto card = new QStandardItem(icon, libraryPath(material)); card->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled); card->setData(QVariant(uuid), Qt::UserRole); @@ -510,10 +698,10 @@ void MaterialsEditor::addFavorites(QStandardItem* parent) auto tree = ui->treeMaterials; for (auto& uuid : _favorites) { try { - const Materials::Material& material = getMaterialManager().getMaterial(uuid); + auto material = getMaterialManager().getMaterial(uuid); - QIcon icon = QIcon(material.getLibrary().getIconPath()); - auto card = new QStandardItem(icon, material.getName()); + QIcon icon = QIcon(material->getLibrary()->getIconPath()); + auto card = new QStandardItem(icon, libraryPath(material)); card->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled); card->setData(QVariant(uuid), Qt::UserRole); @@ -530,12 +718,12 @@ void MaterialsEditor::fillMaterialTree() auto tree = ui->treeMaterials; auto model = static_cast(tree->model()); - auto lib = new QStandardItem(QString::fromStdString("Favorites")); + auto lib = new QStandardItem(tr("Favorites")); lib->setFlags(Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled); addExpanded(tree, model, lib); addFavorites(lib); - lib = new QStandardItem(QString::fromStdString("Recent")); + lib = new QStandardItem(tr("Recent")); lib->setFlags(Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled); addExpanded(tree, model, lib); addRecents(lib); @@ -549,7 +737,7 @@ void MaterialsEditor::fillMaterialTree() QIcon icon(library->getIconPath()); QIcon folderIcon(QString::fromStdString(":/icons/folder.svg")); - auto modelTree = _materialManager.getMaterialTree(*library); + auto modelTree = _materialManager.getMaterialTree(library); addMaterials(*lib, modelTree, folderIcon, icon); } } @@ -582,23 +770,23 @@ void MaterialsEditor::updatePreview() const QString highlightColor; QString sectionColor; - if (_material.hasAppearanceProperty(QString::fromStdString("DiffuseColor"))) { - diffuseColor = _material.getAppearanceValueString(QString::fromStdString("DiffuseColor")); + if (_material->hasAppearanceProperty(QString::fromStdString("DiffuseColor"))) { + diffuseColor = _material->getAppearanceValueString(QString::fromStdString("DiffuseColor")); } - else if (_material.hasAppearanceProperty(QString::fromStdString("ViewColor"))) { - diffuseColor = _material.getAppearanceValueString(QString::fromStdString("ViewColor")); + else if (_material->hasAppearanceProperty(QString::fromStdString("ViewColor"))) { + diffuseColor = _material->getAppearanceValueString(QString::fromStdString("ViewColor")); } - else if (_material.hasAppearanceProperty(QString::fromStdString("Color"))) { - diffuseColor = _material.getAppearanceValueString(QString::fromStdString("Color")); + else if (_material->hasAppearanceProperty(QString::fromStdString("Color"))) { + diffuseColor = _material->getAppearanceValueString(QString::fromStdString("Color")); } - if (_material.hasAppearanceProperty(QString::fromStdString("SpecularColor"))) { + if (_material->hasAppearanceProperty(QString::fromStdString("SpecularColor"))) { highlightColor = - _material.getAppearanceValueString(QString::fromStdString("SpecularColor")); + _material->getAppearanceValueString(QString::fromStdString("SpecularColor")); } - if (_material.hasAppearanceProperty(QString::fromStdString("SectionColor"))) { - sectionColor = _material.getAppearanceValueString(QString::fromStdString("SectionColor")); + if (_material->hasAppearanceProperty(QString::fromStdString("SectionColor"))) { + sectionColor = _material->getAppearanceValueString(QString::fromStdString("SectionColor")); } if ((diffuseColor.length() + highlightColor.length()) > 0) { @@ -678,28 +866,28 @@ void MaterialsEditor::updateMaterialAppearance() treeModel->clear(); QStringList headers; - headers.append(QString::fromStdString("Property")); - headers.append(QString::fromStdString("Value")); - headers.append(QString::fromStdString("Type")); + headers.append(tr("Property")); + headers.append(tr("Value")); + headers.append(tr("Type")); treeModel->setHorizontalHeaderLabels(headers); tree->setColumnWidth(0, 250); tree->setColumnWidth(1, 250); tree->setColumnHidden(2, true); - const std::vector* models = _material.getAppearanceModels(); + auto models = _material->getAppearanceModels(); if (models) { for (auto it = models->begin(); it != models->end(); it++) { QString uuid = *it; try { - const Materials::Model& model = getModelManager().getModel(uuid); - QString name = model.getName(); + auto model = getModelManager().getModel(uuid); + QString name = model->getName(); auto modelRoot = new QStandardItem(name); modelRoot->setFlags(Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled); addExpanded(tree, treeModel, modelRoot); - for (auto itp = model.begin(); itp != model.end(); itp++) { + for (auto itp = model->begin(); itp != model->end(); itp++) { QList items; QString key = itp->first; @@ -707,10 +895,10 @@ void MaterialsEditor::updateMaterialAppearance() propertyItem->setToolTip(itp->second.getDescription()); items.append(propertyItem); - auto valueItem = new QStandardItem(_material.getAppearanceValueString(key)); + auto valueItem = new QStandardItem(_material->getAppearanceValueString(key)); valueItem->setToolTip(itp->second.getDescription()); QVariant variant; - variant.setValue(&_material); + variant.setValue(_material); valueItem->setData(variant); items.append(valueItem); @@ -737,10 +925,10 @@ void MaterialsEditor::updateMaterialProperties() treeModel->clear(); QStringList headers; - headers.append(QString::fromStdString("Property")); - headers.append(QString::fromStdString("Value")); - headers.append(QString::fromStdString("Type")); - headers.append(QString::fromStdString("Units")); + headers.append(tr("Property")); + headers.append(tr("Value")); + headers.append(tr("Type")); + headers.append(tr("Units")); treeModel->setHorizontalHeaderLabels(headers); tree->setColumnWidth(0, 250); @@ -748,19 +936,19 @@ void MaterialsEditor::updateMaterialProperties() tree->setColumnHidden(2, true); tree->setColumnHidden(3, true); - const std::vector* models = _material.getPhysicalModels(); + auto models = _material->getPhysicalModels(); if (models) { for (auto it = models->begin(); it != models->end(); it++) { QString uuid = *it; try { - const Materials::Model& model = getModelManager().getModel(uuid); - QString name = model.getName(); + auto model = getModelManager().getModel(uuid); + QString name = model->getName(); auto modelRoot = new QStandardItem(name); modelRoot->setFlags(Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled); addExpanded(tree, treeModel, modelRoot); - for (auto itp = model.begin(); itp != model.end(); itp++) { + for (auto itp = model->begin(); itp != model->end(); itp++) { QList items; QString key = itp->first; @@ -770,10 +958,10 @@ void MaterialsEditor::updateMaterialProperties() propertyItem->setToolTip(modelProperty.getDescription()); items.append(propertyItem); - auto valueItem = new QStandardItem(_material.getPhysicalValueString(key)); + auto valueItem = new QStandardItem(_material->getPhysicalValueString(key)); valueItem->setToolTip(modelProperty.getDescription()); QVariant variant; - variant.setValue(&_material); + variant.setValue(_material); valueItem->setData(variant); items.append(valueItem); @@ -794,17 +982,47 @@ void MaterialsEditor::updateMaterialProperties() } } +QString MaterialsEditor::libraryPath(std::shared_ptr material) const +{ + QString path; + auto library = material->getLibrary(); + if (library) { + path = QString::fromStdString("/%1/%2") + .arg(material->getLibrary()->getName()) + .arg(material->getDirectory()); + } + else { + path = QString::fromStdString("%1").arg(material->getDirectory()); + } + + return path; +} + +void MaterialsEditor::updateMaterialGeneral() +{ + QString parentString; + try { + auto parent = _materialManager.getParent(_material); + parentString = libraryPath(parent); + } + catch (const Materials::MaterialNotFound&) { + } + + // Update the general information + ui->editName->setText(_material->getName()); + ui->editAuthor->setText(_material->getAuthor()); + ui->editLicense->setText(_material->getLicense()); + ui->editParent->setText(parentString); + ui->editParent->setReadOnly(true); + ui->editSourceURL->setText(_material->getURL()); + ui->editSourceReference->setText(_material->getReference()); + // ui->editTags->setText(_material->getName()); + ui->editDescription->setText(_material->getDescription()); +} + void MaterialsEditor::updateMaterial() { - // Update the general information - ui->editName->setText(_material.getName()); - ui->editAuthorLicense->setText(_material.getAuthorAndLicense()); - // ui->editParent->setText(_material.getName()); - ui->editSourceURL->setText(_material.getURL()); - ui->editSourceReference->setText(_material.getReference()); - // ui->editTags->setText(_material.getName()); - ui->editDescription->setText(_material.getDescription()); - + updateMaterialGeneral(); updateMaterialProperties(); updateMaterialAppearance(); @@ -830,13 +1048,13 @@ void MaterialsEditor::onSelectMaterial(const QItemSelection& selected, } } - if (uuid.isEmpty() || uuid == _material.getUUID()) { + if (uuid.isEmpty() || uuid == _material->getUUID()) { Base::Console().Log("*** Unchanged material '%s'\n", uuid.toStdString().c_str()); return; } // Ensure data is saved (or discarded) before changing materials - if (_material.getEditState() != Materials::Material::ModelEdit_None) { + if (_material->getEditState() != Materials::Material::ModelEdit_None) { // Prompt the user to save or discard changes Base::Console().Log("*** Material edited!!!\n"); int res = confirmSave(this); @@ -847,16 +1065,85 @@ void MaterialsEditor::onSelectMaterial(const QItemSelection& selected, // Get the selected material try { - _material = getMaterialManager().getMaterial(uuid); + _material = std::make_shared(*getMaterialManager().getMaterial(uuid)); } catch (Materials::ModelNotFound const&) { Base::Console().Log("*** Unable to load material '%s'\n", uuid.toStdString().c_str()); - Materials::Material empty; - _material = empty; + _material = std::make_shared(); } updateMaterial(); - _material.resetEditState(); + _material->resetEditState(); +} + +void MaterialsEditor::onDoubleClick(const QModelIndex& index) +{ + Q_UNUSED(index) + + Base::Console().Log("MaterialsEditor::onDoubleClick()\n"); + accept(); +} + +void MaterialsEditor::onContextMenu(const QPoint& pos) +{ + Base::Console().Log("MaterialsEditor::onContextMenu(%d,%d)\n", pos.x(), pos.y()); + // QModelIndex index = ui->treeMaterials->indexAt(pos); + // QString path = pathFromIndex(index); + // Base::Console().Log("\tindex at (%d,%d)->'%s'\n", + // index.row(), + // index.column(), + // path.toStdString().c_str()); + + + QMenu contextMenu(tr("Context menu"), this); + + QAction action1(tr("Inherit from"), this); + // action1.setShortcut(Qt::Key_Delete); + connect(&action1, &QAction::triggered, this, &MaterialsEditor::onInherit); + contextMenu.addAction(&action1); + + QAction action2(tr("Inherit new material"), this); + // action1.setShortcut(Qt::Key_Delete); + connect(&action2, &QAction::triggered, this, &MaterialsEditor::onInheritNew); + contextMenu.addAction(&action2); + + contextMenu.exec(ui->treeMaterials->mapToGlobal(pos)); +} + +void MaterialsEditor::onInherit(bool checked) +{ + Q_UNUSED(checked) + + Base::Console().Log("MaterialsEditor::onInherit()\n"); + // QItemSelectionModel* selectionModel = ui->treeMaterials->selectionModel(); + // if (!selectionModel->hasSelection()) { + // Base::Console().Log("\tNothing selected\n"); + // return; + // } + + // Base::Console().Log("\tSelected path '%s'\n", _selectedFull.toStdString().c_str()); + // int res = confirmDelete(this); + // if (res == QMessageBox::Cancel) { + // return; + // } +} + +void MaterialsEditor::onInheritNew(bool checked) +{ + Q_UNUSED(checked) + + Base::Console().Log("MaterialsEditor::onInherit()\n"); + // QItemSelectionModel* selectionModel = ui->treeMaterials->selectionModel(); + // if (!selectionModel->hasSelection()) { + // Base::Console().Log("\tNothing selected\n"); + // return; + // } + + // Base::Console().Log("\tSelected path '%s'\n", _selectedFull.toStdString().c_str()); + // int res = confirmDelete(this); + // if (res == QMessageBox::Cancel) { + // return; + // } } int MaterialsEditor::confirmSave(QWidget* parent) diff --git a/src/Mod/Material/Gui/MaterialsEditor.h b/src/Mod/Material/Gui/MaterialsEditor.h index 6a1169724b..33f03b221d 100644 --- a/src/Mod/Material/Gui/MaterialsEditor.h +++ b/src/Mod/Material/Gui/MaterialsEditor.h @@ -22,10 +22,11 @@ #ifndef MATGUI_MATERIALSEDITOR_H #define MATGUI_MATERIALSEDITOR_H -#include +#include #include #include +#include #include #include #include @@ -35,8 +36,6 @@ #include #include -namespace fs = boost::filesystem; - namespace MatGui { @@ -47,14 +46,25 @@ class MaterialsEditor: public QDialog Q_OBJECT public: - explicit MaterialsEditor(QWidget* parent = nullptr); + MaterialsEditor(QWidget* parent = nullptr); ~MaterialsEditor() override = default; + void onName(const QString& text); + void onAuthor(const QString& text); + void onLicense(const QString& text); + void onSourceURL(const QString& text); + void onSourceReference(const QString& text); + void onDescription(); + void propertyChange(const QString& property, const QString value); + void onInheritNewMaterial(bool checked); + void onNewMaterial(bool checked); void onFavourite(bool checked); void onURL(bool checked); void onPhysicalAdd(bool checked); + void onPhysicalRemove(bool checked); void onAppearanceAdd(bool checked); + void onAppearanceRemove(bool checked); void onOk(bool checked); void onCancel(bool checked); void onSave(bool checked); @@ -70,10 +80,15 @@ public: return _modelManager; } + QString libraryPath(std::shared_ptr material) const; + void updateMaterialAppearance(); void updateMaterialProperties(); + void updateMaterialGeneral(); void updateMaterial(); void onSelectMaterial(const QItemSelection& selected, const QItemSelection& deselected); + void onDoubleClick(const QModelIndex& index); + void onContextMenu(const QPoint& pos); protected: int confirmSave(QWidget* parent); @@ -83,7 +98,7 @@ private: std::unique_ptr ui; Materials::MaterialManager _materialManager; Materials::ModelManager _modelManager; - Materials::Material _material; + std::shared_ptr _material; QSvgWidget* _rendered; QSvgWidget* _vectored; bool _edited; @@ -102,6 +117,10 @@ private: void addRecent(const QString& uuid); bool isRecent(const QString& uuid) const; + void onInherit(bool checked); + void onInheritNew(bool checked); + + void setMaterialDefaults(); void updatePreview() const; QString getColorHash(const QString& colorString, int colorRange = 255) const; @@ -115,15 +134,12 @@ private: void createMaterialTree(); void fillMaterialTree(); void refreshMaterialTree(); - void - addMaterials(QStandardItem& parent, - const std::shared_ptr> modelTree, - const QIcon& folderIcon, - const QIcon& icon); - bool isMaterial(const fs::path& p) const - { - return Materials::MaterialManager::isMaterial(p); - } + void addMaterials( + QStandardItem& parent, + const std::shared_ptr>> + modelTree, + const QIcon& folderIcon, + const QIcon& icon); }; } // namespace MatGui diff --git a/src/Mod/Material/Gui/MaterialsEditor.ui b/src/Mod/Material/Gui/MaterialsEditor.ui index 8533439e88..5825062271 100644 --- a/src/Mod/Material/Gui/MaterialsEditor.ui +++ b/src/Mod/Material/Gui/MaterialsEditor.ui @@ -68,19 +68,40 @@ 7 + + + + Parent + + + + + + + + + + Tags + + + + + + + Source URL + + + - + Description - - - @@ -88,54 +109,10 @@ - - - - Source Reference - - - - - - - Parent - - - - - - - - - - Author and License - - - - - - - - - - Tags - - - - - - - Source URL - - - - + - - - @@ -155,6 +132,39 @@ + + + + + + + Author + + + + + + + + + + Source Reference + + + + + + + + + + + + + License + + + @@ -172,6 +182,20 @@ + + + + &New + + + + + + + Inherit New + + + diff --git a/src/Mod/Material/Gui/ModelSelect.cpp b/src/Mod/Material/Gui/ModelSelect.cpp index 9b2d19ab38..55fc1a95e2 100644 --- a/src/Mod/Material/Gui/ModelSelect.cpp +++ b/src/Mod/Material/Gui/ModelSelect.cpp @@ -33,6 +33,8 @@ #include #include +#include + #include "ModelSelect.h" #include "ui_ModelSelect.h" @@ -41,7 +43,7 @@ using namespace MatGui; /* TRANSLATOR MatGui::ModelSelect */ -ModelSelect::ModelSelect(QWidget* parent, Materials::ModelManager::ModelFilter filter) +ModelSelect::ModelSelect(QWidget* parent, Materials::ModelFilter filter) : QDialog(parent) , _filter(filter) , ui(new Ui_ModelSelect) @@ -69,6 +71,7 @@ ModelSelect::ModelSelect(QWidget* parent, Materials::ModelManager::ModelFilter f connect(ui->buttonURL, &QPushButton::clicked, this, &ModelSelect::onURL); connect(ui->buttonDOI, &QPushButton::clicked, this, &ModelSelect::onDOI); connect(ui->buttonFavorite, &QPushButton::clicked, this, &ModelSelect::onFavourite); + connect(ui->treeModels, &QTreeView::doubleClicked, this, &ModelSelect::onDoubleClick); ui->standardButtons->button(QDialogButtonBox::Ok)->setEnabled(false); ui->buttonFavorite->setEnabled(false); @@ -232,14 +235,14 @@ void ModelSelect::addExpanded(QTreeView* tree, QStandardItemModel* parent, QStan void ModelSelect::addModels( QStandardItem& parent, - const std::shared_ptr> modelTree, + const std::shared_ptr>> modelTree, const QIcon& icon) { auto tree = ui->treeModels; for (auto& mod : *modelTree) { - Materials::ModelTreeNode* nodePtr = mod.second; + std::shared_ptr nodePtr = mod.second; if (nodePtr->getType() == Materials::ModelTreeNode::DataNode) { - const Materials::Model* model = nodePtr->getData(); + auto model = nodePtr->getData(); QString uuid = model->getUUID(); auto card = new QStandardItem(icon, model->getName()); @@ -264,11 +267,11 @@ void ModelSelect::addRecents(QStandardItem* parent) auto tree = ui->treeModels; for (auto& uuid : _recents) { try { - const Materials::Model& model = getModelManager().getModel(uuid); + auto model = getModelManager().getModel(uuid); - if (getModelManager().passFilter(_filter, model.getType())) { - QIcon icon = QIcon(model.getLibrary().getIconPath()); - auto card = new QStandardItem(icon, model.getName()); + if (getModelManager().passFilter(_filter, model->getType())) { + QIcon icon = QIcon(model->getLibrary()->getIconPath()); + auto card = new QStandardItem(icon, model->getName()); card->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled); card->setData(QVariant(uuid), Qt::UserRole); @@ -286,11 +289,11 @@ void ModelSelect::addFavorites(QStandardItem* parent) auto tree = ui->treeModels; for (auto& uuid : _favorites) { try { - const Materials::Model& model = getModelManager().getModel(uuid); + auto model = getModelManager().getModel(uuid); - if (getModelManager().passFilter(_filter, model.getType())) { - QIcon icon = QIcon(model.getLibrary().getIconPath()); - auto card = new QStandardItem(icon, model.getName()); + if (getModelManager().passFilter(_filter, model->getType())) { + QIcon icon = QIcon(model->getLibrary()->getIconPath()); + auto card = new QStandardItem(icon, model->getName()); card->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled); card->setData(QVariant(uuid), Qt::UserRole); @@ -305,8 +308,6 @@ void ModelSelect::addFavorites(QStandardItem* parent) void ModelSelect::createModelTree() { - // Materials::ModelManager modelManager; - auto tree = ui->treeModels; auto model = new QStandardItemModel(); tree->setModel(model); @@ -326,17 +327,16 @@ void ModelSelect::refreshModelTree() void ModelSelect::fillTree() { - // Materials::ModelManager modelManager; - auto tree = ui->treeModels; auto model = static_cast(tree->model()); + model->clear(); - auto lib = new QStandardItem(QString::fromStdString("Favorites")); + auto lib = new QStandardItem(tr("Favorites")); lib->setFlags(Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled); addExpanded(tree, model, lib); addFavorites(lib); - lib = new QStandardItem(QString::fromStdString("Recent")); + lib = new QStandardItem(tr("Recent")); lib->setFlags(Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled); addExpanded(tree, model, lib); addRecents(lib); @@ -347,7 +347,7 @@ void ModelSelect::fillTree() lib->setFlags(Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled); addExpanded(tree, model, lib); - auto modelTree = getModelManager().getModelTree(*library, _filter); + auto modelTree = getModelManager().getModelTree(library, _filter); addModels(*lib, modelTree, QIcon(library->getIconPath())); } } @@ -355,11 +355,11 @@ void ModelSelect::fillTree() void ModelSelect::setHeaders(QStandardItemModel* model) { QStringList headers; - headers.append(QString::fromStdString("Inherited")); - headers.append(QString::fromStdString("Property")); - headers.append(QString::fromStdString("Units")); - headers.append(QString::fromStdString("Description")); - headers.append(QString::fromStdString("URL")); + headers.append(tr("Inherited")); + headers.append(tr("Property")); + headers.append(tr("Units")); + headers.append(tr("Description")); + headers.append(tr("URL")); model->setHorizontalHeaderLabels(headers); } @@ -388,7 +388,7 @@ void ModelSelect::createModelProperties() // table->setItemDelegate(new MaterialDelegate(this)); } -void ModelSelect::updateModelProperties(const Materials::Model& model) +void ModelSelect::updateModelProperties(std::shared_ptr model) { QTableView* table = ui->tableProperties; QStandardItemModel* tableModel = static_cast(table->model()); @@ -397,7 +397,7 @@ void ModelSelect::updateModelProperties(const Materials::Model& model) setHeaders(tableModel); setColumnWidths(table); - for (auto itp = model.begin(); itp != model.end(); itp++) { + for (auto itp = model->begin(); itp != model->end(); itp++) { QList items; QString key = itp->first; @@ -428,19 +428,19 @@ void ModelSelect::updateModelProperties(const Materials::Model& model) void ModelSelect::updateMaterialModel(const QString& uuid) { - Materials::Model model = getModelManager().getModel(uuid); + auto model = getModelManager().getModel(uuid); // Update the general information - ui->editName->setText(model.getName()); - ui->editURL->setText(model.getURL()); - ui->editDOI->setText(model.getDOI()); - ui->editDescription->setText(model.getDescription()); + ui->editName->setText(model->getName()); + ui->editURL->setText(model->getURL()); + ui->editDOI->setText(model->getDOI()); + ui->editDescription->setText(model->getDescription()); - if (model.getType() == Materials::Model::ModelType_Physical) { - ui->tabWidget->setTabText(1, QString::fromStdString("Properties")); + if (model->getType() == Materials::Model::ModelType_Physical) { + ui->tabWidget->setTabText(1, tr("Properties")); } else { - ui->tabWidget->setTabText(1, QString::fromStdString("Appearance")); + ui->tabWidget->setTabText(1, tr("Appearance")); } updateModelProperties(model); } @@ -453,7 +453,7 @@ void ModelSelect::clearMaterialModel() ui->editDOI->setText(QString::fromStdString("")); ui->editDescription->setText(QString::fromStdString("")); - ui->tabWidget->setTabText(1, QString::fromStdString("Properties")); + ui->tabWidget->setTabText(1, tr("Properties")); QTableView* table = ui->tableProperties; QStandardItemModel* tableModel = static_cast(table->model()); @@ -467,6 +467,7 @@ void ModelSelect::onSelectModel(const QItemSelection& selected, const QItemSelec { Q_UNUSED(deselected); + Base::Console().Log("ModelSelect::onSelectModel()\n"); QStandardItemModel* model = static_cast(ui->treeModels->model()); QModelIndexList indexes = selected.indexes(); for (auto it = indexes.begin(); it != indexes.end(); it++) { @@ -491,6 +492,14 @@ void ModelSelect::onSelectModel(const QItemSelection& selected, const QItemSelec } } +void ModelSelect::onDoubleClick(const QModelIndex& index) +{ + Q_UNUSED(index) + + Base::Console().Log("ModelSelect::onDoubleClick()\n"); + accept(); +} + void ModelSelect::onURL(bool checked) { Q_UNUSED(checked) diff --git a/src/Mod/Material/Gui/ModelSelect.h b/src/Mod/Material/Gui/ModelSelect.h index a80e98fe65..57c3737411 100644 --- a/src/Mod/Material/Gui/ModelSelect.h +++ b/src/Mod/Material/Gui/ModelSelect.h @@ -22,7 +22,7 @@ #ifndef MATGUI_MODELSELECT_H #define MATGUI_MODELSELECT_H -#include +#include #include #include @@ -31,9 +31,7 @@ #include #include -#include - -namespace fs = boost::filesystem; +#include namespace MatGui { @@ -45,15 +43,15 @@ class ModelSelect: public QDialog Q_OBJECT public: - explicit ModelSelect( - QWidget* parent = nullptr, - Materials::ModelManager::ModelFilter filter = Materials::ModelManager::ModelFilter_None); + ModelSelect(QWidget* parent = nullptr, + Materials::ModelFilter filter = Materials::ModelFilter_None); ~ModelSelect() override; void onURL(bool checked); void onDOI(bool checked); void onFavourite(bool checked); void onSelectModel(const QItemSelection& selected, const QItemSelection& deselected); + void onDoubleClick(const QModelIndex& index); const QString& selectedModel() const { return _selected; @@ -77,9 +75,11 @@ private: void addExpanded(QTreeView* tree, QStandardItemModel* parent, QStandardItem* child); void addRecents(QStandardItem* parent); void addFavorites(QStandardItem* parent); - void addModels(QStandardItem& parent, - const std::shared_ptr> modelTree, - const QIcon& icon); + void + addModels(QStandardItem& parent, + const std::shared_ptr>> + modelTree, + const QIcon& icon); void updateMaterialModel(const QString& uuid); void clearMaterialModel(); void createModelTree(); @@ -88,14 +88,14 @@ private: void setHeaders(QStandardItemModel* model); void setColumnWidths(QTableView* table); - void updateModelProperties(const Materials::Model& model); + void updateModelProperties(std::shared_ptr model); void createModelProperties(); Materials::ModelManager& getModelManager() { return _modelManager; } - Materials::ModelManager::ModelFilter _filter; + Materials::ModelFilter _filter; std::unique_ptr ui; Materials::ModelManager _modelManager; QString _selected; diff --git a/src/Mod/Material/Gui/PreCompiled.h b/src/Mod/Material/Gui/PreCompiled.h index 6c9e2163ab..36cb312a6f 100644 --- a/src/Mod/Material/Gui/PreCompiled.h +++ b/src/Mod/Material/Gui/PreCompiled.h @@ -55,10 +55,6 @@ // OpenCasCade // #include -// Boost -#include -#include - // Qt Toolkit #ifndef __QtAll__ #include diff --git a/src/Mod/Material/Gui/Workbench.cpp b/src/Mod/Material/Gui/Workbench.cpp index 21c244052f..65ee6aa6b8 100644 --- a/src/Mod/Material/Gui/Workbench.cpp +++ b/src/Mod/Material/Gui/Workbench.cpp @@ -22,13 +22,53 @@ #include "PreCompiled.h" +#include +#include + #include "Workbench.h" using namespace MatGui; + +#if 0 // needed for Qt's lupdate utility + qApp->translate("Workbench", "&Materials"); + qApp->translate("Workbench", "Materials"); +#endif + /// @namespace MatGui @class Workbench TYPESYSTEM_SOURCE(MatGui::Workbench, Gui::StdWorkbench) Workbench::Workbench() = default; Workbench::~Workbench() = default; + +Gui::MenuItem* Workbench::setupMenuBar() const +{ + Gui::MenuItem* root = StdWorkbench::setupMenuBar(); + Gui::MenuItem* item = root->findItem("&Windows"); + + Gui::MenuItem* part = new Gui::MenuItem; + root->insertItem(item, part); + part->setCommand("&Materials"); + *part << "Materials_Edit"; + + return root; +} + +Gui::ToolBarItem* Workbench::setupToolBars() const +{ + Gui::ToolBarItem* root = StdWorkbench::setupToolBars(); + + Gui::ToolBarItem* solids = new Gui::ToolBarItem(root); + solids->setCommand("Materials"); + *solids << "Materials_Edit"; + + return root; +} + +Gui::ToolBarItem* Workbench::setupCommandBars() const +{ + // Part tools + Gui::ToolBarItem* root = new Gui::ToolBarItem; + return root; +} diff --git a/src/Mod/Material/Gui/Workbench.h b/src/Mod/Material/Gui/Workbench.h index d0de5238c6..fe3800fca7 100644 --- a/src/Mod/Material/Gui/Workbench.h +++ b/src/Mod/Material/Gui/Workbench.h @@ -39,6 +39,11 @@ class MatGuiExport Workbench: public Gui::StdWorkbench public: Workbench(); ~Workbench() override; + +protected: + Gui::MenuItem* setupMenuBar() const override; + Gui::ToolBarItem* setupToolBars() const override; + Gui::ToolBarItem* setupCommandBars() const override; }; } // namespace MatGui diff --git a/src/Mod/Material/Resources/Materials/Appearance/Aluminum.FCMat b/src/Mod/Material/Resources/Materials/Appearance/Aluminum.FCMat index d33f1d0ef4..df4bfa6d55 100644 --- a/src/Mod/Material/Resources/Materials/Appearance/Aluminum.FCMat +++ b/src/Mod/Material/Resources/Materials/Appearance/Aluminum.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "d1f317f0-5ffa-4798-8ab3-af2ff0b5182c" - AuthorAndLicense: "(c) 2023 David Carter" + Author: "David Carter" + License: "GPL-2.0-or-later" Name: "Aluminum" Description: "Defines the Aluminum appearance properties" AppearanceModels: diff --git a/src/Mod/Material/Resources/Materials/Appearance/Brass.FCMat b/src/Mod/Material/Resources/Materials/Appearance/Brass.FCMat index f17c932862..7c84d933f4 100644 --- a/src/Mod/Material/Resources/Materials/Appearance/Brass.FCMat +++ b/src/Mod/Material/Resources/Materials/Appearance/Brass.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "4151e19c-fd6a-4ca4-83d4-d5e17d76cb9c" - AuthorAndLicense: "(c) 2023 David Carter" + Author: "David Carter" + License: "GPL-2.0-or-later" Name: "Brass" Description: "Defines the Brass appearance properties" AppearanceModels: diff --git a/src/Mod/Material/Resources/Materials/Appearance/Bronze.FCMat b/src/Mod/Material/Resources/Materials/Appearance/Bronze.FCMat index bc6c294526..18f0b94a57 100644 --- a/src/Mod/Material/Resources/Materials/Appearance/Bronze.FCMat +++ b/src/Mod/Material/Resources/Materials/Appearance/Bronze.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "ae194589-02d4-4e9b-98a7-f523f660d510" - AuthorAndLicense: "(c) 2023 David Carter" + Author: "David Carter" + License: "GPL-2.0-or-later" Name: "Bronze" Description: "Defines the Bronze appearance properties" AppearanceModels: diff --git a/src/Mod/Material/Resources/Materials/Appearance/Chrome.FCMat b/src/Mod/Material/Resources/Materials/Appearance/Chrome.FCMat index dccbfaec0e..646c2d8891 100644 --- a/src/Mod/Material/Resources/Materials/Appearance/Chrome.FCMat +++ b/src/Mod/Material/Resources/Materials/Appearance/Chrome.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "a9544b88-dde7-4d05-9bdb-c008a4e88dc1" - AuthorAndLicense: "(c) 2023 David Carter" + Author: "David Carter" + License: "GPL-2.0-or-later" Name: "Chrome" Description: "Defines the Chrome appearance properties" AppearanceModels: diff --git a/src/Mod/Material/Resources/Materials/Appearance/Copper.FCMat b/src/Mod/Material/Resources/Materials/Appearance/Copper.FCMat index 643ca6ed06..2e04a10667 100644 --- a/src/Mod/Material/Resources/Materials/Appearance/Copper.FCMat +++ b/src/Mod/Material/Resources/Materials/Appearance/Copper.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "524cad9b-b841-4037-9851-badeca7dcee2" - AuthorAndLicense: "(c) 2023 David Carter" + Author: "David Carter" + License: "GPL-2.0-or-later" Name: "Copper" Description: "Defines the Copper appearance properties" AppearanceModels: diff --git a/src/Mod/Material/Resources/Materials/Appearance/DefaultAppearance.FCMat b/src/Mod/Material/Resources/Materials/Appearance/DefaultAppearance.FCMat index 9795ceae40..9c6eb2f497 100644 --- a/src/Mod/Material/Resources/Materials/Appearance/DefaultAppearance.FCMat +++ b/src/Mod/Material/Resources/Materials/Appearance/DefaultAppearance.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "5dbb7be6-8b63-479b-ab4c-87be02ead973" - AuthorAndLicense: "(c) 2023 David Carter" + Author: "David Carter" + License: "GPL-2.0-or-later" Name: "Default Appearance" Description: "Defines the default appearance properties" AppearanceModels: diff --git a/src/Mod/Material/Resources/Materials/Appearance/Emerald.FCMat b/src/Mod/Material/Resources/Materials/Appearance/Emerald.FCMat index d98a8f1153..519b79bdd6 100644 --- a/src/Mod/Material/Resources/Materials/Appearance/Emerald.FCMat +++ b/src/Mod/Material/Resources/Materials/Appearance/Emerald.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "54def35f-a6bf-472e-8410-dc9fb4b143cf" - AuthorAndLicense: "(c) 2023 David Carter" + Author: "David Carter" + License: "GPL-2.0-or-later" Name: "Emerald" Description: "Defines the Emerald appearance properties" AppearanceModels: diff --git a/src/Mod/Material/Resources/Materials/Appearance/Gold.FCMat b/src/Mod/Material/Resources/Materials/Appearance/Gold.FCMat index 170b7d1302..4805837cf3 100644 --- a/src/Mod/Material/Resources/Materials/Appearance/Gold.FCMat +++ b/src/Mod/Material/Resources/Materials/Appearance/Gold.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "85257e2c-be3f-40a1-b03f-0bd4ba58ca08" - AuthorAndLicense: "(c) 2023 David Carter" + Author: "David Carter" + License: "GPL-2.0-or-later" Name: "Gold" Description: "Defines the Gold appearance properties" AppearanceModels: diff --git a/src/Mod/Material/Resources/Materials/Appearance/Jade.FCMat b/src/Mod/Material/Resources/Materials/Appearance/Jade.FCMat index 3a956ebff2..af9b12ceeb 100644 --- a/src/Mod/Material/Resources/Materials/Appearance/Jade.FCMat +++ b/src/Mod/Material/Resources/Materials/Appearance/Jade.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "cddfa21f-0715-49dd-b35b-951c076fa52c" - AuthorAndLicense: "(c) 2023 David Carter" + Author: "David Carter" + License: "GPL-2.0-or-later" Name: "Jade" Description: "Defines the Jade appearance properties" AppearanceModels: diff --git a/src/Mod/Material/Resources/Materials/Appearance/Metalized.FCMat b/src/Mod/Material/Resources/Materials/Appearance/Metalized.FCMat index 11892dc311..9c9d2feb2d 100644 --- a/src/Mod/Material/Resources/Materials/Appearance/Metalized.FCMat +++ b/src/Mod/Material/Resources/Materials/Appearance/Metalized.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "d149a177-07f1-4e53-9bad-0b5bf0663600" - AuthorAndLicense: "(c) 2023 David Carter" + Author: "David Carter" + License: "GPL-2.0-or-later" Name: "Metalized" Description: "Defines the Metalized appearance properties" AppearanceModels: diff --git a/src/Mod/Material/Resources/Materials/Appearance/NeonGNC.FCMat b/src/Mod/Material/Resources/Materials/Appearance/NeonGNC.FCMat index ddf2092e1c..00a226c0ca 100644 --- a/src/Mod/Material/Resources/Materials/Appearance/NeonGNC.FCMat +++ b/src/Mod/Material/Resources/Materials/Appearance/NeonGNC.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "c0341eef-0897-4fcf-a7f7-eddf1a2600a5" - AuthorAndLicense: "(c) 2023 David Carter" + Author: "David Carter" + License: "GPL-2.0-or-later" Name: "Neon GNC" Description: "Defines the Neon GNC appearance properties" AppearanceModels: diff --git a/src/Mod/Material/Resources/Materials/Appearance/NeonPHC.FCMat b/src/Mod/Material/Resources/Materials/Appearance/NeonPHC.FCMat index ed315a25b6..ea1473d575 100644 --- a/src/Mod/Material/Resources/Materials/Appearance/NeonPHC.FCMat +++ b/src/Mod/Material/Resources/Materials/Appearance/NeonPHC.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "add2d6b2-c8fb-4777-a80a-52bae97300ae" - AuthorAndLicense: "(c) 2023 David Carter" + Author: "David Carter" + License: "GPL-2.0-or-later" Name: "Neon PHC" Description: "Defines the Neon PHC appearance properties" AppearanceModels: diff --git a/src/Mod/Material/Resources/Materials/Appearance/Obsidian.FCMat b/src/Mod/Material/Resources/Materials/Appearance/Obsidian.FCMat index e4f366cff9..3496efb8ea 100644 --- a/src/Mod/Material/Resources/Materials/Appearance/Obsidian.FCMat +++ b/src/Mod/Material/Resources/Materials/Appearance/Obsidian.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "a004c270-7d2c-4898-bec6-b1120edacea9" - AuthorAndLicense: "(c) 2023 David Carter" + Author: "David Carter" + License: "GPL-2.0-or-later" Name: "Obsidian" Description: "Defines the Obsidian appearance properties" AppearanceModels: diff --git a/src/Mod/Material/Resources/Materials/Appearance/Pewter.FCMat b/src/Mod/Material/Resources/Materials/Appearance/Pewter.FCMat index b7592ea3df..b263611987 100644 --- a/src/Mod/Material/Resources/Materials/Appearance/Pewter.FCMat +++ b/src/Mod/Material/Resources/Materials/Appearance/Pewter.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "a61853b9-ec9f-403e-9726-0a938731aecd" - AuthorAndLicense: "(c) 2023 David Carter" + Author: "David Carter" + License: "GPL-2.0-or-later" Name: "Pewter" Description: "Defines the Pewter appearance properties" AppearanceModels: diff --git a/src/Mod/Material/Resources/Materials/Appearance/Plaster.FCMat b/src/Mod/Material/Resources/Materials/Appearance/Plaster.FCMat index 70f6c8932a..d969f84f02 100644 --- a/src/Mod/Material/Resources/Materials/Appearance/Plaster.FCMat +++ b/src/Mod/Material/Resources/Materials/Appearance/Plaster.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "569dccb6-c64b-4dd0-9d3c-1b78f40ad1a5" - AuthorAndLicense: "(c) 2023 David Carter" + Author: "David Carter" + License: "GPL-2.0-or-later" Name: "Plaster" Description: "Defines the Plaster appearance properties" AppearanceModels: diff --git a/src/Mod/Material/Resources/Materials/Appearance/Plastic.FCMat b/src/Mod/Material/Resources/Materials/Appearance/Plastic.FCMat index 2484521dca..efcc9df554 100644 --- a/src/Mod/Material/Resources/Materials/Appearance/Plastic.FCMat +++ b/src/Mod/Material/Resources/Materials/Appearance/Plastic.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "a74622cd-0e2d-4a96-b8c4-fefcc82ac694" - AuthorAndLicense: "(c) 2023 David Carter" + Author: "David Carter" + License: "GPL-2.0-or-later" Name: "Plastic" Description: "Defines the Plastic appearance properties" AppearanceModels: diff --git a/src/Mod/Material/Resources/Materials/Appearance/Ruby.FCMat b/src/Mod/Material/Resources/Materials/Appearance/Ruby.FCMat index 5a8138ba39..eac38bb236 100644 --- a/src/Mod/Material/Resources/Materials/Appearance/Ruby.FCMat +++ b/src/Mod/Material/Resources/Materials/Appearance/Ruby.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "953261a0-cc48-41f8-a3f9-7b20ae3f9b56" - AuthorAndLicense: "(c) 2023 David Carter" + Author: "David Carter" + License: "GPL-2.0-or-later" Name: "Ruby" Description: "Defines the Ruby appearance properties" AppearanceModels: diff --git a/src/Mod/Material/Resources/Materials/Appearance/Satin.FCMat b/src/Mod/Material/Resources/Materials/Appearance/Satin.FCMat index 97a198c206..211f1441df 100644 --- a/src/Mod/Material/Resources/Materials/Appearance/Satin.FCMat +++ b/src/Mod/Material/Resources/Materials/Appearance/Satin.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "951b54ae-86b6-46d2-b452-60bd6a3ba1bb" - AuthorAndLicense: "(c) 2023 David Carter" + Author: "David Carter" + License: "GPL-2.0-or-later" Name: "Satin" Description: "Defines the Satin appearance properties" AppearanceModels: diff --git a/src/Mod/Material/Resources/Materials/Appearance/ShinyPlastic.FCMat b/src/Mod/Material/Resources/Materials/Appearance/ShinyPlastic.FCMat index 75853c01bc..221be76449 100644 --- a/src/Mod/Material/Resources/Materials/Appearance/ShinyPlastic.FCMat +++ b/src/Mod/Material/Resources/Materials/Appearance/ShinyPlastic.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "591c4c4a-22ba-4a9a-869d-e5610107d69a" - AuthorAndLicense: "(c) 2023 David Carter" + Author: "David Carter" + License: "GPL-2.0-or-later" Name: "Shiny Plastic" Description: "Defines the Shiny Plastic appearance properties" AppearanceModels: diff --git a/src/Mod/Material/Resources/Materials/Appearance/Silver.FCMat b/src/Mod/Material/Resources/Materials/Appearance/Silver.FCMat index b3354a150a..dbdedc9a27 100644 --- a/src/Mod/Material/Resources/Materials/Appearance/Silver.FCMat +++ b/src/Mod/Material/Resources/Materials/Appearance/Silver.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "62839fb0-d854-4b44-92df-b7249213de49" - AuthorAndLicense: "(c) 2023 David Carter" + Author: "David Carter" + License: "GPL-2.0-or-later" Name: "Silver" Description: "Defines the Silver appearance properties" AppearanceModels: diff --git a/src/Mod/Material/Resources/Materials/Appearance/Steel.FCMat b/src/Mod/Material/Resources/Materials/Appearance/Steel.FCMat index 7bebcd8a90..bc9e1acc99 100644 --- a/src/Mod/Material/Resources/Materials/Appearance/Steel.FCMat +++ b/src/Mod/Material/Resources/Materials/Appearance/Steel.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "4b849c55-6b3a-4f75-a055-40c0d0324596" - AuthorAndLicense: "(c) 2023 David Carter" + Author: "David Carter" + License: "GPL-2.0-or-later" Name: "Steel" Description: "Defines the Steel appearance properties" AppearanceModels: diff --git a/src/Mod/Material/Resources/Materials/Appearance/Stone.FCMat b/src/Mod/Material/Resources/Materials/Appearance/Stone.FCMat index 8c3910ee5d..74436298ba 100644 --- a/src/Mod/Material/Resources/Materials/Appearance/Stone.FCMat +++ b/src/Mod/Material/Resources/Materials/Appearance/Stone.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "a9f54d61-cc98-46df-8734-b0543ceb4e45" - AuthorAndLicense: "(c) 2023 David Carter" + Author: "David Carter" + License: "GPL-2.0-or-later" Name: "Stone" Description: "Defines the Stone appearance properties" AppearanceModels: diff --git a/src/Mod/Material/Resources/Materials/FluidMaterial/Air.FCMat b/src/Mod/Material/Resources/Materials/FluidMaterial/Air.FCMat index 6a5be9c27c..025c280566 100644 --- a/src/Mod/Material/Resources/Materials/FluidMaterial/Air.FCMat +++ b/src/Mod/Material/Resources/Materials/FluidMaterial/Air.FCMat @@ -1,6 +1,7 @@ # File created by ConvertFCMat.py General: UUID: "94370b96-c97e-4a3f-83b2-11d7461f7da7" + License: "GPL-2.0-or-later" Name: "Air" Description: "Dry air properties at 20 Degrees Celsius and 1 atm" Models: diff --git a/src/Mod/Material/Resources/Materials/FluidMaterial/Argon.FCMat b/src/Mod/Material/Resources/Materials/FluidMaterial/Argon.FCMat index 1607bd59da..235f07091c 100644 --- a/src/Mod/Material/Resources/Materials/FluidMaterial/Argon.FCMat +++ b/src/Mod/Material/Resources/Materials/FluidMaterial/Argon.FCMat @@ -1,6 +1,7 @@ # File created by ConvertFCMat.py General: UUID: "e359c5b5-eae2-42b1-9ef6-edde21d706ee" + License: "GPL-2.0-or-later" Name: "Argon" Description: "Argon properties at 20 Degrees Celsius and 1 atm" Models: diff --git a/src/Mod/Material/Resources/Materials/FluidMaterial/Carbon_dioxide.FCMat b/src/Mod/Material/Resources/Materials/FluidMaterial/Carbon_dioxide.FCMat index 7ffe282fed..fdfc5a94c9 100644 --- a/src/Mod/Material/Resources/Materials/FluidMaterial/Carbon_dioxide.FCMat +++ b/src/Mod/Material/Resources/Materials/FluidMaterial/Carbon_dioxide.FCMat @@ -1,6 +1,7 @@ # File created by ConvertFCMat.py General: UUID: "ef0e4040-a498-48c3-a87b-e996bfd89195" + License: "GPL-2.0-or-later" Name: "Carbon dioxide" Description: "Carbon dioxide properties at 20 Degrees Celsius and 1 atm" Models: diff --git a/src/Mod/Material/Resources/Materials/FluidMaterial/Nitrogen.FCMat b/src/Mod/Material/Resources/Materials/FluidMaterial/Nitrogen.FCMat index bd5fd3ea07..d7c81bea31 100644 --- a/src/Mod/Material/Resources/Materials/FluidMaterial/Nitrogen.FCMat +++ b/src/Mod/Material/Resources/Materials/FluidMaterial/Nitrogen.FCMat @@ -1,6 +1,7 @@ # File created by ConvertFCMat.py General: UUID: "8d02a797-5e0a-4e40-803a-75fc66de8de6" + License: "GPL-2.0-or-later" Name: "Nitrogen" Description: "Nitrogen properties at 20 Degrees Celsius and 1 atm" Models: diff --git a/src/Mod/Material/Resources/Materials/FluidMaterial/None.FCMat b/src/Mod/Material/Resources/Materials/FluidMaterial/None.FCMat index 40094e2d06..8497cd58bb 100644 --- a/src/Mod/Material/Resources/Materials/FluidMaterial/None.FCMat +++ b/src/Mod/Material/Resources/Materials/FluidMaterial/None.FCMat @@ -1,6 +1,7 @@ # File created by ConvertFCMat.py General: UUID: "944a8018-09bf-48f6-a7b3-aa8f6a00a310" + License: "GPL-2.0-or-later" Name: "None" Description: "None" Models: diff --git a/src/Mod/Material/Resources/Materials/FluidMaterial/Water.FCMat b/src/Mod/Material/Resources/Materials/FluidMaterial/Water.FCMat index aa4c8d35cc..6f0fe7c6dc 100644 --- a/src/Mod/Material/Resources/Materials/FluidMaterial/Water.FCMat +++ b/src/Mod/Material/Resources/Materials/FluidMaterial/Water.FCMat @@ -1,6 +1,7 @@ # File created by ConvertFCMat.py General: UUID: "7e5559d5-be15-4571-a72f-20c39edd41cf" + License: "GPL-2.0-or-later" Name: "Water" Description: "Standard distilled water properties at 20 Degrees Celsius and 1 atm" ReferenceSource: "''" diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Aggregate/Concrete-EN-C35_45.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Aggregate/Concrete-EN-C35_45.FCMat index fa6eabb71f..281b959ca6 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Aggregate/Concrete-EN-C35_45.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Aggregate/Concrete-EN-C35_45.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "dba76940-a910-4a3b-ab73-a9f412ac69d9" - AuthorAndLicense: "(c) 2019 Bernd Hahnebach (CC-BY 3.0)" + Author: "Bernd Hahnebach" + License: "CC-BY-3.0" Name: "Concrete-EN-C35/45" Description: "Concrete matrix for reinforcement material examples, 0.6 x 0.75 x 35 MPa = 15.75 MPa (https://forum.freecad.org/viewtopic.php?f=18&t=33106&start=200#p311075)" Inherits: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Aggregate/Concrete-Generic.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Aggregate/Concrete-Generic.FCMat index 994874548d..72e4c9af4a 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Aggregate/Concrete-Generic.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Aggregate/Concrete-Generic.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "26042aa5-56e6-4d99-8b63-dd8b9ea5a37a" - AuthorAndLicense: "(c) 2013 Yorik van Havre (CC-BY 3.0)" + Author: "Yorik van Havre" + License: "CC-BY-3.0" Name: "Concrete" Description: "A standard C-25 construction concrete" Inherits: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Aggregate/Reinforcement-FIB-B500.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Aggregate/Reinforcement-FIB-B500.FCMat index 13ac6afc77..70e70e1916 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Aggregate/Reinforcement-FIB-B500.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Aggregate/Reinforcement-FIB-B500.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "57507cd4-d22f-4d86-9794-fdb1ec8cd098" - AuthorAndLicense: "(c) 2019 Bernd Hahnebach (CC-BY 3.0)" + Author: "Bernd Hahnebach" + License: "CC-BY-3.0" Name: "Reinforcement-Harry" Description: "Reinforcement inside concrete for reinforcement material examples, from fib examples, 0.84 x 0.75 x 500 MPa = 315 MPa (https://forum.freecad.org/viewtopic.php?f=18&t=33106&start=200#p311705)" Inherits: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Carbon/Graphite.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Carbon/Graphite.FCMat index e66b987f2e..5983299e4a 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Carbon/Graphite.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Carbon/Graphite.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "5c67b675-69a2-4782-902a-bb90c3952f07" - AuthorAndLicense: "Uwe Stöhr, LGPL" + Author: "Uwe Stöhr" + License: "LGPL-2.0-or-later" Name: "Graphite" Description: "Typical material properties for pure graphite" ReferenceSource: "Properties and characteristics of graphite" diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Glass/Glass-E-GlassFibre.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Glass/Glass-E-GlassFibre.FCMat index 034f5271f0..862f02108f 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Glass/Glass-E-GlassFibre.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Glass/Glass-E-GlassFibre.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "a02bf9d7-6e3e-4e36-881b-10779ee9f706" - AuthorAndLicense: "(c) 2015 DaviKaur (CC-BY 3.0)" + Author: "DaviKaur" + License: "CC-BY-3.0" Name: "Glass-E" Description: "Glass Fibre" Models: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Glass/Glass-Generic.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Glass/Glass-Generic.FCMat index 1502a1e85b..9074cfe621 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Glass/Glass-Generic.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Glass/Glass-Generic.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "3e3a3e13-04a4-410e-8e36-bbd83ca66847" - AuthorAndLicense: "(c) 2015 Przemo Firszt (CC-BY 3.0)" + Author: "Przemo Firszt" + License: "CC-BY-3.0" Name: "Glass" Description: "Generic soda-lime glass" Models: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Glass/Glass-S2-GlassFibre.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Glass/Glass-S2-GlassFibre.FCMat index 79d993d62d..70daa6df5b 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Glass/Glass-S2-GlassFibre.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Glass/Glass-S2-GlassFibre.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "0c4943e0-248b-4df9-88d9-3b4dd84dfc68" - AuthorAndLicense: "(c) 2015 DaviKaur (CC-BY 3.0)" + Author: "DaviKaur" + License: "CC-BY-3.0" Name: "Glass-S2" Description: "Glass Fibre" Models: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Alloys/Invar-Generic.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Alloys/Invar-Generic.FCMat index 1653bde1ae..80fce39425 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Alloys/Invar-Generic.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Alloys/Invar-Generic.FCMat @@ -1,7 +1,7 @@ # File created by ConvertFCMat.py General: UUID: "27745e16-2a10-4c8e-bd22-59971806909c" - AuthorAndLicense: "Uwe Stöhr" + Author: "Uwe Stöhr" Name: "Invar Generic" Models: Father: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Aluminum/AlMg3F24.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Aluminum/AlMg3F24.FCMat index d3ea2edf4c..b7a7da8f77 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Aluminum/AlMg3F24.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Aluminum/AlMg3F24.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "0051bddf-6f62-4406-b8c9-569322880564" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "AlMg3F24" Inherits: Aluminum: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Aluminum/AlMgSi1F31.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Aluminum/AlMgSi1F31.FCMat index ce7ad3a053..7d27af3936 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Aluminum/AlMgSi1F31.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Aluminum/AlMgSi1F31.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "460e02a3-b6cd-4662-b2f6-8c9d44146c66" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "AlMgSi1F31" Inherits: Aluminum: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Aluminum/AlZn4-5Mg1F35.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Aluminum/AlZn4-5Mg1F35.FCMat index 9ff117b0ed..cae2453d1e 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Aluminum/AlZn4-5Mg1F35.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Aluminum/AlZn4-5Mg1F35.FCMat @@ -1,7 +1,7 @@ # File created by ConvertFCMat.py General: UUID: "05f8f1b2-b92b-4e41-8de9-1e064e78a165" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + License: "LGPL-2.0-or-later" Name: "AlZn4,5Mg1F35" Inherits: Aluminum: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Aluminum/Aluminum-6061-T6.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Aluminum/Aluminum-6061-T6.FCMat index 648350b109..3fe4777c23 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Aluminum/Aluminum-6061-T6.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Aluminum/Aluminum-6061-T6.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "68b152b2-fd5e-4f10-8db0-1a2df3fe0fda" - AuthorAndLicense: "(c) 2016 Mandeep Singh (CC-BY 3.0)" + Author: "Mandeep Singh" + License: "CC-BY-3.0" Name: "Aluminum 6061-T6" Description: "Precipitation-hardened, Nonferrous Aluminum alloy" Inherits: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Aluminum/Aluminum-Generic.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Aluminum/Aluminum-Generic.FCMat index c518eaf674..d96cd80218 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Aluminum/Aluminum-Generic.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Aluminum/Aluminum-Generic.FCMat @@ -1,7 +1,7 @@ # File created by ConvertFCMat.py General: UUID: "9bf060e9-1663-44a2-88e2-2ff6ee858efe" - AuthorAndLicense: "Uwe Stöhr" + Author: "Uwe Stöhr" Name: "Aluminum Generic" Inherits: Aluminum: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Copper/Copper-Generic.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Copper/Copper-Generic.FCMat index 8188c3a553..8379ecba69 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Copper/Copper-Generic.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Copper/Copper-Generic.FCMat @@ -1,7 +1,7 @@ # File created by ConvertFCMat.py General: UUID: "6c03899d-496e-4c60-a41b-3d66f2337fb9" - AuthorAndLicense: "Uwe Stöhr" + Author: "Uwe Stöhr" Name: "Copper Generic" Inherits: Copper: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Iron/Iron-Generic.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Iron/Iron-Generic.FCMat index f99d52a37f..f33cdf155f 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Iron/Iron-Generic.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Iron/Iron-Generic.FCMat @@ -1,7 +1,7 @@ # File created by ConvertFCMat.py General: UUID: "1826c364-d26a-43fb-8f61-288281236836" - AuthorAndLicense: "Uwe Stöhr" + Author: "Uwe Stöhr" Name: "Iron Generic" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/CalculiX-Steel.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/CalculiX-Steel.FCMat index 7763a27728..5105e234d2 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/CalculiX-Steel.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/CalculiX-Steel.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "92589471-a6cb-4bbc-b748-d425a17dea7d" - AuthorAndLicense: "(c) 2013 Juergen Riegel (CC-BY 3.0)" + Author: "Juergen Riegel" + License: "CC-BY-3.0" Name: "CalculiX-Steel" Description: "Standard steel material for CalculiX sample calculations" Inherits: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-15CrNi6.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-15CrNi6.FCMat index c1be13ce98..e719b9b5e6 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-15CrNi6.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-15CrNi6.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "6822df30-db32-4a68-a8d7-aaddcb9649d1" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "15CrNi6" Description: "High-strength carbon steel" Inherits: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-17CrNiMo6.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-17CrNiMo6.FCMat index 462e784536..247c10e733 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-17CrNiMo6.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-17CrNiMo6.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "e4c76f15-00af-4498-ac57-beaf49c150e9" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "17CrNiMo6" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-1C22.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-1C22.FCMat index f36307b08d..4f0271aff2 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-1C22.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-1C22.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "c424fe3d-5f49-4c39-9467-8a2a800076aa" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "1C22" Description: "Case hardened alloy steel" Inherits: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-1C35.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-1C35.FCMat index 8cc577729a..0c5702696b 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-1C35.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-1C35.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "cd932bad-4085-459f-aea6-1da737ae38ae" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "1C35" Description: "Non-alloy quality steel" Inherits: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-1C45.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-1C45.FCMat index 9433799bcb..4fabe2bb90 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-1C45.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-1C45.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "958b7a5c-4764-4a2f-a450-2153a41fb5ec" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "1C45" Description: "Non-alloy quality steel" Inherits: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-1C60.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-1C60.FCMat index dac83e2809..45ae6f0566 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-1C60.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-1C60.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "9717f953-1cfc-41a6-8974-3ad45188ad48" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "1C60" Description: "Non-alloy quality steel" Inherits: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-20NiCrMo2.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-20NiCrMo2.FCMat index f63fc2cd6b..af5e731492 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-20NiCrMo2.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-20NiCrMo2.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "1c759697-7aef-4a14-92c5-5bf84b99a4f0" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "20NiCrMo2" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-28Mn6.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-28Mn6.FCMat index 5166ff1d58..c310e12ec6 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-28Mn6.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-28Mn6.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "6894c597-5771-4b56-825f-ce7d5e4689f4" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "28Mn6" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-2C10.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-2C10.FCMat index bb25674809..55e4894152 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-2C10.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-2C10.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "a7be39a1-1686-4fee-a1d5-81ef73b82d16" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "2C10" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-30CrNiMo8.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-30CrNiMo8.FCMat index b8edc93d8e..276e40f244 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-30CrNiMo8.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-30CrNiMo8.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "a6d96264-affc-4406-9816-75099c1fa0d9" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "30CrNiMo8" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-34CrNiMo6.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-34CrNiMo6.FCMat index 4c02195cf8..67ce48abdb 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-34CrNiMo6.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-34CrNiMo6.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "e69448d5-2517-4c00-9e70-ebeb11ca017f" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "34CrNiMo6" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-36CrNiMo4.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-36CrNiMo4.FCMat index f1635de298..e41bf67f6b 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-36CrNiMo4.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-36CrNiMo4.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "3e78b767-5530-4d69-a541-cf33a5a2ad19" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "36CrNiMo4" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-36NiCrMo16.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-36NiCrMo16.FCMat index 1a9e29753a..be7b82a8fe 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-36NiCrMo16.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-36NiCrMo16.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "3fdf729c-bec4-4bfa-ba94-b0c9e51a2040" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "36NiCrMo16" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-3C15.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-3C15.FCMat index 6ad2a41287..5384f6afb0 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-3C15.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-3C15.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "605fd7b6-caa3-400d-b6d7-ed52c0f5da21" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "3C15" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-3C22.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-3C22.FCMat index 19c035f0a4..bb8f193f81 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-3C22.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-3C22.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "7313f076-faf4-41dd-8dae-1b9a586990dc" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "3C22" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-3C35.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-3C35.FCMat index 583523ea88..91c2f6478f 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-3C35.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-3C35.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "251cc54e-4a5a-4cd3-9c9e-006c416d7ce9" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "3C35" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-3V45.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-3V45.FCMat index 193f19e1b9..189f0f3b04 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-3V45.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-3V45.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "d2e12a80-fd17-42db-99d8-62971f65ee84" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "3V45" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C10.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C10.FCMat index b72f563c88..016b585afa 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C10.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C10.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "9086ae2f-3b2e-4654-9665-0fe31effb8a2" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "C10" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C15.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C15.FCMat index 6a11819478..47d53206b6 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C15.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C15.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "06ae5c92-de7b-46c9-984d-4dd87964bc5c" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "C15" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C22E.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C22E.FCMat index 932930426e..09bbdc3424 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C22E.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C22E.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "befa2489-dba0-41c5-aa83-7cca2ac8947b" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "C22E" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C25E.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C25E.FCMat index 12f65b3acc..fecc163322 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C25E.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C25E.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "b95d3de5-36af-41cd-a6dd-3f647b1d4eee" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "C25E" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C30E.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C30E.FCMat index d6cfe2d8c3..8dc09c6ca6 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C30E.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C30E.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "e88e1e86-fad2-4c70-b185-4b2975e7fba5" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "C30E" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C40E.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C40E.FCMat index c777dc3028..1ccb48ea77 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C40E.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C40E.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "5b33f177-b0da-4ffa-acb5-a3b23ab6e630" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "C40E" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C50E.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C50E.FCMat index 3a73bb97f7..10122e36fa 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C50E.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C50E.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "6821be5f-5471-4939-bb1d-866f83018090" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "C50E" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C55E.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C55E.FCMat index be4341ad95..27da081e4e 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C55E.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C55E.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "d60a21c9-9c4b-4463-b133-bb0e84ce46b2" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "C55E" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C60E.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C60E.FCMat index 7c0c04301b..7ae48bda84 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C60E.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C60E.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "56027b3e-876e-4c0e-9f39-242feaa67e13" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "C60E" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-E295-GC.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-E295-GC.FCMat index 9b314d4c01..1cae3d8294 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-E295-GC.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-E295-GC.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "fc010ef8-91de-4099-9a73-605c01dd117c" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "E295 GC" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-E295.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-E295.FCMat index e74c218799..d919a2b3f1 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-E295.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-E295.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "f1567a1c-995f-4feb-8baf-09ade3e830c5" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "E295" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-E335-GC.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-E335-GC.FCMat index 9612056c9b..b4a6f21b2b 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-E335-GC.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-E335-GC.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "ab901ecc-d880-4cb4-b400-dbe4fd9b0f0a" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "E335 GC" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-E335.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-E335.FCMat index 7ca7e2a764..44e9e013db 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-E335.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-E335.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "da418876-f80e-4793-8fc8-a6040a694389" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "E335" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-E360-GC.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-E360-GC.FCMat index aa14d78d49..69ee63fa8d 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-E360-GC.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-E360-GC.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "4c311592-659b-4ef0-bac9-5cffe9e70612" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "E360 GC" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-E360.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-E360.FCMat index 6ed1535ce0..086b7b9ddb 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-E360.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-E360.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "dfba065e-2bfb-4fe3-8eec-dfb1cb6274fe" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "E360" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJL-100.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJL-100.FCMat index 282a042e41..8bac4460a4 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJL-100.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJL-100.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "5a1d56e3-8180-4f81-a0d7-887fb08e3752" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "EN-GJL-100" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJL-150.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJL-150.FCMat index f4c9e2ca3c..e68bdbd697 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJL-150.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJL-150.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "7a2aa3c4-10fa-44b0-9420-37ae74207fa3" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "EN-GJL-150" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJL-200.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJL-200.FCMat index aca3e5b83a..ed3218a3ff 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJL-200.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJL-200.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "8ae26e72-65b6-4f93-9fbe-9e3f17a2e1b5" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "EN-GJL-200" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJL-250.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJL-250.FCMat index 13d4da1f70..5272f9b931 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJL-250.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJL-250.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "71f32e31-656e-4f94-a5f0-5b656b9367c6" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "EN-GJL-250" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJL-300.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJL-300.FCMat index 489a2e3c24..2dd95eb99d 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJL-300.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJL-300.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "6db01463-7772-4d0e-ab81-fae6d45ce669" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "EN-GJL-300" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJL-350.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJL-350.FCMat index 9922275365..f463241b6d 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJL-350.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJL-350.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "c4ff4bef-4885-41d5-904f-9c71a8018c98" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "EN-GJL-350" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMB-350-10.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMB-350-10.FCMat index 05dc53a302..e3068a9035 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMB-350-10.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMB-350-10.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "eec1833a-424a-4c4f-bdf2-6f8377845d54" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "EN-GJMB-350-10" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMB-550-4.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMB-550-4.FCMat index 7e8b518d5c..d4e4f44237 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMB-550-4.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMB-550-4.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "095140bb-df01-4bb9-8ff3-062aa91ec48c" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "EN-GJMB-550-4" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMB-650-2.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMB-650-2.FCMat index d22fcd93ad..d11ba1c726 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMB-650-2.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMB-650-2.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "490a348c-f508-4599-a5e0-2f6b211126d5" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "EN-GJMB-650-2" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMW-350-4.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMW-350-4.FCMat index 148e26a9b3..ebb8694572 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMW-350-4.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMW-350-4.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "a97c3eab-a1e8-472b-ba40-519a0d660019" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "EN-GJMW-350-4" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMW-360-12.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMW-360-12.FCMat index 604538d200..e1c40edde3 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMW-360-12.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMW-360-12.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "81a865af-79b6-4e0b-98ad-5cde134ad99e" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "EN-GJMW-360-12" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMW-400-5.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMW-400-5.FCMat index db74ef871c..9220b27f79 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMW-400-5.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMW-400-5.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "9d71fc9c-960a-47e8-afa8-a86a24b3ff89" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "EN-GJMW-400-5" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMW-450-7.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMW-450-7.FCMat index 0e6de5ac4e..1e9d4e28d1 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMW-450-7.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMW-450-7.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "c0eedc49-d63b-429d-be63-ef0ea442f45c" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "EN-GJMW-450-7" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJS-400-15.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJS-400-15.FCMat index ab7c0b2163..051c98f0ec 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJS-400-15.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJS-400-15.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "f6300691-ecf0-4846-acb1-8c2bad3359a8" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "EN-GJS-400-15" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJS-500-7.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJS-500-7.FCMat index 5a28f4356f..1c28126097 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJS-500-7.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJS-500-7.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "51aabe6f-642b-4f47-9006-1c8c3613a422" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "EN-GJS-500-7" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJS-600-3.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJS-600-3.FCMat index 0f3f5d7ed9..1de6ec6cf9 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJS-600-3.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJS-600-3.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "eb573f18-5a7b-493b-bfda-d711f03f7f71" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "EN-GJS-600-3" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJS-700-2.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJS-700-2.FCMat index 28c327f104..3e1f7625de 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJS-700-2.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJS-700-2.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "9a194e62-d2e4-466d-92ba-2707107c4e3c" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "EN-GJS-700-2" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJS-800-1.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJS-800-1.FCMat index 071d813334..9ad715e980 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJS-800-1.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJS-800-1.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "97c444f9-83ae-48d8-98e5-603349d06f7e" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "EN-GJS-800-1" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G16Mn5.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G16Mn5.FCMat index 97d45db1ae..bdede7e22a 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G16Mn5.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G16Mn5.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "fc5c14ba-4885-4c75-aaf6-0ec4f2365f40" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "G16Mn5" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G200.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G200.FCMat index 51965ab4d2..2c61fce091 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G200.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G200.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "8d799def-e941-4cb6-b48d-72b9a292fafe" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "G200" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G20Mn5.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G20Mn5.FCMat index 7e1e9c8e6d..b7bbf43d10 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G20Mn5.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G20Mn5.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "d384d1e5-e2fe-4e09-9a0f-78e5670425ee" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "G20Mn5" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G230.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G230.FCMat index 2c11dcd9f6..114fd54038 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G230.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G230.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "53931707-6fe7-4ac0-ac7a-e9ddfec70fa5" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "G230" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G260.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G260.FCMat index 4c4b62744e..71e5f54ef6 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G260.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G260.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "22971112-d137-4db1-9349-edf5e281e333" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "G260" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G300.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G300.FCMat index 8c0acbd1cd..488a762db6 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G300.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G300.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "33f1c891-7488-4324-9af9-cbdde6726b49" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "G300" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G30Mn5.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G30Mn5.FCMat index bb11cbee52..91675dc395 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G30Mn5.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G30Mn5.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "e03df70c-ceb8-4317-825d-1195c8c178d0" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "G30Mn5" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-Generic.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-Generic.FCMat index c2fead712a..e291486c4a 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-Generic.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-Generic.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "90bbd8ef-8623-4d78-b3bf-e0bdb9b74dd3" - AuthorAndLicense: "(c) 2013 Juergen Riegel (CC-BY 3.0)" + Author: "Juergen Riegel" + License: "CC-BY-3.0" Name: "Steel-Generic" Description: "This is a blend Steel material card. The values are at the low end of the spectrum. If you need a more precise material definition use the more specialised steel cards." Inherits: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S185.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S185.FCMat index ebba16c9d5..c8f0ada537 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S185.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S185.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "6f32981a-7bbf-49a1-842c-7567a195fa7e" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "S185" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S235JO.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S235JO.FCMat index 3f26e56e56..c484567ffd 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S235JO.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S235JO.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "5b13e02a-b173-4e2d-95fd-a30d9e0f7cf5" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "S235JO" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S235JR.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S235JR.FCMat index 5c4cf2a2ca..657975b9c7 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S235JR.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S235JR.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "4a96627d-6518-458c-8ccf-846f69fd8a50" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "S235JR" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S235JRG1.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S235JRG1.FCMat index a4949171a9..fe1182e815 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S235JRG1.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S235JRG1.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "d8cc450d-7d6d-4377-8a8d-ffe3cf30fcb2" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "S235JRG1" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S260NC.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S260NC.FCMat index 09cf375caa..b9e5794e79 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S260NC.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S260NC.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "4994efd8-fc7b-41b3-ad61-9d98d1bdbe6e" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "S260NC" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S275JO.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S275JO.FCMat index 95a8ec460a..56fb705e76 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S275JO.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S275JO.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "f9deac5f-91a4-41aa-b49c-ef09ec4613e2" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "S275JO" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S275JR.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S275JR.FCMat index 9d57c21c9d..c3da4512c9 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S275JR.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S275JR.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "30e4da7d-1fe3-41de-911a-a42e3405bb7b" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "S275JR" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S275N.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S275N.FCMat index 18c0439561..59a1888016 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S275N.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S275N.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "07592e35-3e1a-470f-8eda-f4bee7d9cb4a" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "S275N" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S335JO.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S335JO.FCMat index c8ae2510e0..c7fbcc90db 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S335JO.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S335JO.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "c50ad549-b4f4-47ab-9bc6-4eb5191da111" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "S335JO" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S335JR.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S335JR.FCMat index 931e9d418f..83ac7fe653 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S335JR.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S335JR.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "dbd04cee-3b92-4b79-a208-58547ebe3807" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "S335JR" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S335N.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S335N.FCMat index 231271d7cd..e7d8fc174b 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S335N.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S335N.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "16d7f1d5-449f-4b9e-b57a-7ea114fda115" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "S335N" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S340MC.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S340MC.FCMat index a3e0a90eb4..baccd4ca36 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S340MC.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S340MC.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "5785ea5e-3376-47dd-8dc2-f1267c47e9bc" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "S340MC" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S355J2G3.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S355J2G3.FCMat index 71b783d323..72e7ca9845 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S355J2G3.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S355J2G3.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "b9e861ee-93fb-4eca-a2de-03579bc503c1" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "S355J2G3" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S380MC.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S380MC.FCMat index aa8d2c2c94..b28262ff49 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S380MC.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S380MC.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "da2a429b-8763-4586-be3d-620e7dd30271" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "S380MC" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S420MC.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S420MC.FCMat index 41b6518bed..407d553894 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S420MC.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S420MC.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "c3452eff-f68e-4cfd-a24e-27e2abcd01ac" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "S420MC" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S420N.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S420N.FCMat index a8a2d0b6cd..74f00df70f 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S420N.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S420N.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "902f2d4a-5bd0-44bf-9c14-54462ba6778b" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "S420N" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S460MC.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S460MC.FCMat index 2b972e87ef..7834dca011 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S460MC.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S460MC.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "c254dac5-3ee3-49b9-b8d4-16d20d21c94f" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "S460MC" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S460N.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S460N.FCMat index d3c96c9639..536b5df413 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S460N.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S460N.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "f0ae245a-1041-4674-ac4f-bf212dda6009" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "S460N" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S500MC.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S500MC.FCMat index 7703c36586..679dfaf447 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S500MC.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S500MC.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "ad8e2007-ee73-4b71-8830-6d40a8407284" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "S500MC" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S550MC.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S550MC.FCMat index 9ac063cd0d..b7c5bc08b2 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S550MC.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S550MC.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "b7308026-9278-4346-b157-2b3da280b61b" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "S550MC" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S690MC.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S690MC.FCMat index 1d979fd02c..223f410073 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S690MC.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S690MC.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "41360af5-98ed-4125-a89c-ff711e4dd2bf" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "S690MC" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-St-37-2K.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-St-37-2K.FCMat index 0478534039..9f6476151e 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-St-37-2K.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-St-37-2K.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "e97be20f-246a-48b5-9718-3d39486e7af2" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "St 37-2K" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-St-E-255.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-St-E-255.FCMat index 230b39f30a..2b5057f72a 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-St-E-255.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-St-E-255.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "1078eb9f-ac3e-4b24-b40e-b9ead77828e0" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "St E 255" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-St-E-315.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-St-E-315.FCMat index efcc99b6f9..3d15c2d2df 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-St-E-315.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-St-E-315.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "74ca3b08-d561-4440-a4c2-d9b839b66670" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "St E 315" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-St-E-380.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-St-E-380.FCMat index f2d7b9df43..33b2d3c85a 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-St-E-380.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-St-E-380.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "a1b62461-7abc-45da-9a3c-3068367d2990" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "St E 380" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-St-E-460.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-St-E-460.FCMat index 9ec5596e74..5bc873d0d9 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-St-E-460.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-St-E-460.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "b312ad7b-95d4-4ca5-9736-360dbed918ee" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "St E 460" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-St-E-500.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-St-E-500.FCMat index 7c08645652..c5bc2706f3 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-St-E-500.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-St-E-500.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "90fb6bd4-05db-4d44-ba89-280b5a060921" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "St E 500" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X2CrNiMoN17-13-3.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X2CrNiMoN17-13-3.FCMat index 104b026672..083668673d 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X2CrNiMoN17-13-3.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X2CrNiMoN17-13-3.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "a05b5f9b-27b9-4554-8feb-553f9d6027ef" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "X2CrNiMoN17-13-3" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X2CrNiN24-4.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X2CrNiN24-4.FCMat index f59cd81717..d048a4677c 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X2CrNiN24-4.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X2CrNiN24-4.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "be74ada5-2775-41fc-a44b-36df6fb5e0b8" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "X2CrNiN24-4" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X39CrMo17-1.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X39CrMo17-1.FCMat index ec90558bbe..485f5099a7 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X39CrMo17-1.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X39CrMo17-1.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "9e7069ef-296d-401d-9331-d3e11267c2e0" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "X39CrMo17-1" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X3CrNiMo13-14.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X3CrNiMo13-14.FCMat index b4fc5986dd..87ec296574 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X3CrNiMo13-14.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X3CrNiMo13-14.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "88632101-8868-407a-a95f-01773b5f2245" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "X3CrNiMo13-14" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X5CrNi18-10.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X5CrNi18-10.FCMat index e8c5f023bf..0e0a81db1e 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X5CrNi18-10.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X5CrNi18-10.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "e5329208-0c38-47ec-8c59-e7bf6a35801d" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "X5CrNi18-10" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X5CrNiMo17-12-2.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X5CrNiMo17-12-2.FCMat index 5bf2b0b38b..f115a63bff 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X5CrNiMo17-12-2.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X5CrNiMo17-12-2.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "7625a484-96de-438d-b251-2b71044cfa88" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "X5CrNiMo17-12-2" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X6CrNiTi18-10.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X6CrNiTi18-10.FCMat index 8e04da41e5..76366b8f64 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X6CrNiTi18-10.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X6CrNiTi18-10.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "2c577c45-ebae-46b2-9e36-e41fbcce9286" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "X6CrNiTi18-10" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Titanium/Ti-6Al-4V.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Titanium/Ti-6Al-4V.FCMat index b68cc7b6d0..ee1b06c1b0 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Titanium/Ti-6Al-4V.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Titanium/Ti-6Al-4V.FCMat @@ -1,7 +1,7 @@ # File created by ConvertFCMat.py General: UUID: "f8013463-8008-4063-818c-ab6884cfa015" - AuthorAndLicense: "vlk" + Author: "vlk" Name: "Ti-6Al-4V (Grade 5)" Models: Father: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/ABS-Generic.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/ABS-Generic.FCMat index d85813be24..b5fba41f91 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/ABS-Generic.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/ABS-Generic.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "73371529-2983-47dd-b988-6739a2e20029" - AuthorAndLicense: "(c) 2013 Juergen Riegel (CC-BY 3.0)" + Author: "Juergen Riegel" + License: "CC-BY-3.0" Name: "ABS" Description: "This is a blend AcrylnitrilButadienStyrol (ABS) material card. The values are at the low end of the spectrum. If you need a more precise material definition use the more specialised ABS-blend cards." SourceURL: "http://www.matweb.com/search/DataSheet.aspx?MatGUID=eb7a78f5948d481c9493a67f0d089646" diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/Acrylic-Glass-Generic.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/Acrylic-Glass-Generic.FCMat index 086f0b1ad5..8daa44d95b 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/Acrylic-Glass-Generic.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/Acrylic-Glass-Generic.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "f255cd82-91d5-4e97-9032-1843128a2eaa" - AuthorAndLicense: "(c) 2016 Przemo Firszt (CC-BY 3.0)" + Author: "Przemo Firszt" + License: "CC-BY-3.0" Name: "Acrylic Glass" Description: "Poly(methyl methacrylate) (PMMA, acrylic, acrylic glass, trade names Plexiglas, Acrylite, Lucite, Perspex) a transparent thermoplastic often used in sheet form as a lightweight or shatter-resistant alternative to glass." SourceURL: "http://www.matweb.com/search/DataSheet.aspx?MatGUID=632572aeef2a4224b5ac8fbd4f1b6f77" diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/PA6-Generic.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/PA6-Generic.FCMat index 1a16486a01..2460f65648 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/PA6-Generic.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/PA6-Generic.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "9d59dc3b-ce66-4bec-82c9-b962082e7c9e" - AuthorAndLicense: "(c) 2019 Uwe Stöhr (CC-BY 3.0)" + Author: "Uwe Stöhr" + License: "CC-BY-3.0" Name: "Polyamide 6" SourceURL: "http://www.matweb.com/search/datasheet.aspx?MatGUID=8d78f3cfcb6f49d595896ce6ce6a2ef1" Models: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/PET-Generic.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/PET-Generic.FCMat index 6822285250..c80562e2b1 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/PET-Generic.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/PET-Generic.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "f73004e3-6fb4-4591-8be7-89d1370be312" - AuthorAndLicense: "(c) 2019 Uwe Stöhr (CC-BY 3.0)" + Author: "Uwe Stöhr" + License: "CC-BY-3.0" Name: "PET" SourceURL: "http://www.matweb.com/search/DataSheet.aspx?MatGUID=a696bdcdff6f41dd98f8eec3599eaa20" Models: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/PLA-Generic.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/PLA-Generic.FCMat index f1f23fd796..1eab389a6d 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/PLA-Generic.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/PLA-Generic.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "93861244-fbbe-41a9-a7e0-aeed53abd782" - AuthorAndLicense: "(c) 2019 Uwe Stöhr (CC-BY 3.0)" + Author: "Uwe Stöhr" + License: "CC-BY-3.0" Name: "PLA" Description: "Polylactic acid or polylactide (PLA, Poly) is a biodegradable thermoplastic aliphatic polyester derived from renewable resources, such as corn starch, tapioca roots, chips, starch or sugarcane." SourceURL: "https://www.sd3d.com/wp-content/uploads/2017/06/MaterialTDS-PLA_01.pdf" diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/PP-Generic.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/PP-Generic.FCMat index 19a8d81b6b..39c439f422 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/PP-Generic.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/PP-Generic.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "0e669f57-de27-4915-9a02-124f36047972" - AuthorAndLicense: "(c) 2019 Uwe Stöhr (CC-BY 3.0)" + Author: "Uwe Stöhr" + License: "CC-BY-3.0" Name: "Polypropylene" SourceURL: "http://www.matweb.com/search/DataSheet.aspx?MatGUID=a882a1c603374e278d062f106dfda95b" Models: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/PTFE-Generic.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/PTFE-Generic.FCMat index b7091e9e05..8cdd2fcb2b 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/PTFE-Generic.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/PTFE-Generic.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "8ce226db-43ef-4471-93f1-07e7276aa276" - AuthorAndLicense: "(c) 2019 Uwe Stöhr (CC-BY 3.0)" + Author: "Uwe Stöhr" + License: "CC-BY-3.0" Name: "PTFE" SourceURL: "http://www.matweb.com/search/datasheet.aspx?MatGUID=4d14eac958e5401a8fd152e1261b6843" Models: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/PVC-Generic.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/PVC-Generic.FCMat index dfde218e7f..f94f4e5b11 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/PVC-Generic.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/PVC-Generic.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "758cfc44-f4ad-4605-8645-75e9e6b053ab" - AuthorAndLicense: "(c) 2019 Uwe Stöhr (CC-BY 3.0)" + Author: "Uwe Stöhr" + License: "CC-BY-3.0" Name: "PVC" SourceURL: "http://www.matweb.com/search/DataSheet.aspx?MatGUID=1f650966ec834bb8833dd4c6e3116079" Models: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Wood/Wood-Generic.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Wood/Wood-Generic.FCMat index 9c64883f91..4f87fd1b6d 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Wood/Wood-Generic.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Wood/Wood-Generic.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "b588224e-e8d6-47ad-ba1f-a058333fd1c6" - AuthorAndLicense: "(c) 2015 Bernd Hahnebach (CC-BY 3.0)" + Author: "Bernd Hahnebach" + License: "CC-BY-3.0" Name: "Wood" Description: "A standard construction wood" Models: diff --git a/src/Mod/Material/TestMaterialsApp.py b/src/Mod/Material/TestMaterialsApp.py index 4679987368..30d562dc6f 100644 --- a/src/Mod/Material/TestMaterialsApp.py +++ b/src/Mod/Material/TestMaterialsApp.py @@ -26,220 +26,5 @@ import unittest import FreeCAD import Material -parseQuantity = FreeCAD.Units.parseQuantity -# import locale -# locale.setpreferredencoding("UTF8") - -class MaterialTestCases(unittest.TestCase): - def setUp(self): - self.ModelManager = Material.ModelManager() - self.MaterialManager = Material.MaterialManager() - - def testModelManager(self): - self.assertIn("ModelLibraries", dir(self.ModelManager)) - self.assertIn("Models", dir(self.ModelManager)) - - def testMaterialManager(self): - self.assertIn("MaterialLibraries", dir(self.MaterialManager)) - self.assertIn("Materials", dir(self.MaterialManager)) - - def testModelLoad(self): - density = self.ModelManager.getModel("454661e5-265b-4320-8e6f-fcf6223ac3af") - self.assertIsNotNone(density) - self.assertEqual(density.Name, "Density") - self.assertEqual(density.UUID, "454661e5-265b-4320-8e6f-fcf6223ac3af") - self.assertIn("Density", density.Properties) - prop = density.Properties["Density"] - self.assertIn("Description", dir(prop)) - self.assertIn("Name", dir(prop)) - self.assertIn("Type", dir(prop)) - self.assertIn("URL", dir(prop)) - self.assertIn("Units", dir(prop)) - self.assertEqual(prop.Name, "Density") - - def testCalculiXSteel(self): - steel = self.MaterialManager.getMaterial("92589471-a6cb-4bbc-b748-d425a17dea7d") - self.assertIsNotNone(steel) - self.assertEqual(steel.Name, "CalculiX-Steel") - self.assertEqual(steel.UUID, "92589471-a6cb-4bbc-b748-d425a17dea7d") - - self.assertTrue(steel.hasPhysicalModel('454661e5-265b-4320-8e6f-fcf6223ac3af')) # Density - self.assertTrue(steel.hasPhysicalModel('f6f9e48c-b116-4e82-ad7f-3659a9219c50')) # IsotropicLinearElastic - self.assertTrue(steel.hasPhysicalModel('9959d007-a970-4ea7-bae4-3eb1b8b883c7')) # Thermal - self.assertFalse(steel.hasPhysicalModel('7b561d1d-fb9b-44f6-9da9-56a4f74d7536')) # Legacy linear elastic - Not in the model - self.assertTrue(steel.hasAppearanceModel('f006c7e4-35b7-43d5-bbf9-c5d572309e6e')) # BasicRendering - inherited from Steel.FCMat - - self.assertTrue(steel.isPhysicalModelComplete('454661e5-265b-4320-8e6f-fcf6223ac3af')) # Density - self.assertFalse(steel.isPhysicalModelComplete('f6f9e48c-b116-4e82-ad7f-3659a9219c50')) # IsotropicLinearElastic - incomplete - self.assertTrue(steel.isPhysicalModelComplete('9959d007-a970-4ea7-bae4-3eb1b8b883c7')) # Thermal - self.assertFalse(steel.isPhysicalModelComplete('7b561d1d-fb9b-44f6-9da9-56a4f74d7536')) # Legacy linear elastic - Not in the model - self.assertTrue(steel.isAppearanceModelComplete('f006c7e4-35b7-43d5-bbf9-c5d572309e6e')) # BasicRendering - inherited from Steel.FCMat - - self.assertTrue(steel.hasPhysicalProperty("Density")) - self.assertTrue(steel.hasPhysicalProperty("BulkModulus")) - self.assertTrue(steel.hasPhysicalProperty("PoissonRatio")) - self.assertTrue(steel.hasPhysicalProperty("YoungsModulus")) - self.assertTrue(steel.hasPhysicalProperty("ShearModulus")) - self.assertTrue(steel.hasPhysicalProperty("SpecificHeat")) - self.assertTrue(steel.hasPhysicalProperty("ThermalConductivity")) - self.assertTrue(steel.hasPhysicalProperty("ThermalExpansionCoefficient")) - self.assertTrue(steel.hasAppearanceProperty("AmbientColor")) - self.assertTrue(steel.hasAppearanceProperty("DiffuseColor")) - self.assertTrue(steel.hasAppearanceProperty("EmissiveColor")) - self.assertTrue(steel.hasAppearanceProperty("Shininess")) - self.assertTrue(steel.hasAppearanceProperty("SpecularColor")) - self.assertTrue(steel.hasAppearanceProperty("Transparency")) - - properties = steel.PhysicalProperties - self.assertIn("Density", properties) - self.assertNotIn("BulkModulus", properties) - self.assertIn("PoissonRatio", properties) - self.assertIn("YoungsModulus", properties) - self.assertNotIn("ShearModulus", properties) - self.assertIn("SpecificHeat", properties) - self.assertIn("ThermalConductivity", properties) - self.assertIn("ThermalExpansionCoefficient", properties) - self.assertNotIn("AmbientColor", properties) - self.assertNotIn("DiffuseColor", properties) - self.assertNotIn("EmissiveColor", properties) - self.assertNotIn("Shininess", properties) - self.assertNotIn("SpecularColor", properties) - self.assertNotIn("Transparency", properties) - - properties = steel.AppearanceProperties - self.assertNotIn("Density", properties) - self.assertNotIn("BulkModulus", properties) - self.assertNotIn("PoissonRatio", properties) - self.assertNotIn("YoungsModulus", properties) - self.assertNotIn("ShearModulus", properties) - self.assertNotIn("SpecificHeat", properties) - self.assertNotIn("ThermalConductivity", properties) - self.assertNotIn("ThermalExpansionCoefficient", properties) - self.assertIn("AmbientColor", properties) - self.assertIn("DiffuseColor", properties) - self.assertIn("EmissiveColor", properties) - self.assertIn("Shininess", properties) - self.assertIn("SpecularColor", properties) - self.assertIn("Transparency", properties) - - properties = steel.Properties - self.assertIn("Density", properties) - self.assertNotIn("BulkModulus", properties) - self.assertIn("PoissonRatio", properties) - self.assertIn("YoungsModulus", properties) - self.assertNotIn("ShearModulus", properties) - self.assertIn("SpecificHeat", properties) - self.assertIn("ThermalConductivity", properties) - self.assertIn("ThermalExpansionCoefficient", properties) - self.assertIn("AmbientColor", properties) - self.assertIn("DiffuseColor", properties) - self.assertIn("EmissiveColor", properties) - self.assertIn("Shininess", properties) - self.assertIn("SpecularColor", properties) - self.assertIn("Transparency", properties) - - # - # The test for ThermalExpansionCoefficient causes problems with some localizations - # due to the Unicode mu character in the units. I don't have a solution to this - # yet so it's commented out for now - print("Density " + properties["Density"]) - # print("BulkModulus " + properties["BulkModulus"]) - print("PoissonRatio " + properties["PoissonRatio"]) - print("YoungsModulus " + properties["YoungsModulus"]) - # print("ShearModulus " + properties["ShearModulus"]) - print("SpecificHeat " + properties["SpecificHeat"]) - print("ThermalConductivity " + properties["ThermalConductivity"]) - # print("ThermalExpansionCoefficient " + properties["ThermalExpansionCoefficient"]) - print("AmbientColor " + properties["AmbientColor"]) - print("DiffuseColor " + properties["DiffuseColor"]) - print("EmissiveColor " + properties["EmissiveColor"]) - print("Shininess " + properties["Shininess"]) - print("SpecularColor " + properties["SpecularColor"]) - print("Transparency " + properties["Transparency"]) - - self.assertTrue(len(properties["Density"]) > 0) - # self.assertTrue(len(properties["BulkModulus"]) == 0) - self.assertTrue(len(properties["PoissonRatio"]) > 0) - self.assertTrue(len(properties["YoungsModulus"]) > 0) - # self.assertTrue(len(properties["ShearModulus"]) == 0) - self.assertTrue(len(properties["SpecificHeat"]) > 0) - self.assertTrue(len(properties["ThermalConductivity"]) > 0) - self.assertTrue(len(properties["ThermalExpansionCoefficient"]) > 0) - self.assertTrue(len(properties["AmbientColor"]) > 0) - self.assertTrue(len(properties["DiffuseColor"]) > 0) - self.assertTrue(len(properties["EmissiveColor"]) > 0) - self.assertTrue(len(properties["Shininess"]) > 0) - self.assertTrue(len(properties["SpecularColor"]) > 0) - self.assertTrue(len(properties["Transparency"]) > 0) - - self.assertEqual(properties["Density"], parseQuantity("7900.00 kg/m^3").UserString) - # self.assertEqual(properties["BulkModulus"], "") - self.assertAlmostEqual(parseQuantity(properties["PoissonRatio"]).Value, parseQuantity("0.30000001192092896").Value) - self.assertEqual(properties["YoungsModulus"], parseQuantity("210.00 GPa").UserString) - # self.assertEqual(properties["ShearModulus"], "") - self.assertEqual(properties["SpecificHeat"], parseQuantity("590.00 J/kg/K").UserString) - self.assertEqual(properties["ThermalConductivity"], parseQuantity("43.00 W/m/K").UserString) - self.assertEqual(properties["ThermalExpansionCoefficient"], parseQuantity("12.00 µm/m/K").UserString) - self.assertEqual(properties["AmbientColor"], "(0.0020, 0.0020, 0.0020, 1.0)") - self.assertEqual(properties["DiffuseColor"], "(0.0000, 0.0000, 0.0000, 1.0)") - self.assertEqual(properties["EmissiveColor"], "(0.0000, 0.0000, 0.0000, 1.0)") - self.assertAlmostEqual(parseQuantity(properties["Shininess"]).Value, parseQuantity("0.05999999865889549").Value) - self.assertEqual(properties["SpecularColor"], "(0.9800, 0.9800, 0.9800, 1.0)") - self.assertAlmostEqual(parseQuantity(properties["Transparency"]).Value, parseQuantity("0").Value) - - print("Density " + steel.getPhysicalValue("Density").UserString) - # print("BulkModulus " + properties["BulkModulus"]) - print("PoissonRatio %f" % steel.getPhysicalValue("PoissonRatio")) - print("YoungsModulus " + steel.getPhysicalValue("YoungsModulus").UserString) - # print("ShearModulus " + properties["ShearModulus"]) - print("SpecificHeat " + steel.getPhysicalValue("SpecificHeat").UserString) - print("ThermalConductivity " + steel.getPhysicalValue("ThermalConductivity").UserString) - # print("ThermalExpansionCoefficient " + steel.getPhysicalValue("ThermalExpansionCoefficient").UserString) - print("AmbientColor " + steel.getAppearanceValue("AmbientColor")) - print("DiffuseColor " + steel.getAppearanceValue("DiffuseColor")) - print("EmissiveColor " + steel.getAppearanceValue("EmissiveColor")) - print("Shininess %f" % steel.getAppearanceValue("Shininess")) - print("SpecularColor " + steel.getAppearanceValue("SpecularColor")) - print("Transparency %f" % steel.getAppearanceValue("Transparency")) - - self.assertAlmostEqual(steel.getPhysicalValue("Density").Value, 7.9e-06) - self.assertAlmostEqual(steel.getPhysicalValue("PoissonRatio"), 0.3) - self.assertAlmostEqual(steel.getPhysicalValue("YoungsModulus").Value, 210000000.0) - self.assertAlmostEqual(steel.getPhysicalValue("SpecificHeat").Value, 590000000.0) - self.assertAlmostEqual(steel.getPhysicalValue("ThermalConductivity").Value, 43000.0) - self.assertAlmostEqual(steel.getPhysicalValue("ThermalExpansionCoefficient").Value, 1.2e-05) - self.assertEqual(steel.getAppearanceValue("AmbientColor"), "(0.0020, 0.0020, 0.0020, 1.0)") - self.assertEqual(steel.getAppearanceValue("DiffuseColor"), "(0.0000, 0.0000, 0.0000, 1.0)") - self.assertEqual(steel.getAppearanceValue("EmissiveColor"), "(0.0000, 0.0000, 0.0000, 1.0)") - self.assertAlmostEqual(steel.getAppearanceValue("Shininess"), 0.06) - self.assertEqual(steel.getAppearanceValue("SpecularColor"), "(0.9800, 0.9800, 0.9800, 1.0)") - self.assertAlmostEqual(steel.getAppearanceValue("Transparency"), 0.0) - - def testMaterialsWithModel(self): - materials = self.MaterialManager.materialsWithModel('f6f9e48c-b116-4e82-ad7f-3659a9219c50') # IsotropicLinearElastic - materialsComplete = self.MaterialManager.materialsWithModelComplete('f6f9e48c-b116-4e82-ad7f-3659a9219c50') # IsotropicLinearElastic - - self.assertTrue(len(materialsComplete) <= len(materials)) # Not all will be complete - - materialsLinearElastic = self.MaterialManager.materialsWithModel('7b561d1d-fb9b-44f6-9da9-56a4f74d7536') # LinearElastic - - # All LinearElastic models should be in IsotropicLinearElastic since it is inherited - self.assertTrue(len(materialsLinearElastic) <= len(materials)) - for mat in materialsLinearElastic: - self.assertIn(mat, materials) - - def testMaterialByPath(self): - steel = self.MaterialManager.getMaterialByPath('StandardMaterial/Metal/Steel/CalculiX-Steel.FCMat', 'System') - self.assertIsNotNone(steel) - self.assertEqual(steel.Name, "CalculiX-Steel") - self.assertEqual(steel.UUID, "92589471-a6cb-4bbc-b748-d425a17dea7d") - - steel2 = self.MaterialManager.getMaterialByPath('/StandardMaterial/Metal/Steel/CalculiX-Steel.FCMat', 'System') - self.assertIsNotNone(steel2) - self.assertEqual(steel2.Name, "CalculiX-Steel") - self.assertEqual(steel2.UUID, "92589471-a6cb-4bbc-b748-d425a17dea7d") - - steel3 = self.MaterialManager.getMaterialByPath('/System/StandardMaterial/Metal/Steel/CalculiX-Steel.FCMat', 'System') - self.assertIsNotNone(steel3) - self.assertEqual(steel3.Name, "CalculiX-Steel") - self.assertEqual(steel3.UUID, "92589471-a6cb-4bbc-b748-d425a17dea7d") +from materialtests.TestModels import ModelTestCases +from materialtests.TestMaterials import MaterialTestCases diff --git a/src/Mod/Material/materialtests/TestMaterials.py b/src/Mod/Material/materialtests/TestMaterials.py new file mode 100644 index 0000000000..7e8cb030df --- /dev/null +++ b/src/Mod/Material/materialtests/TestMaterials.py @@ -0,0 +1,228 @@ +#************************************************************************** +# Copyright (c) 2023 David Carter * +# * +# This file is part of the FreeCAD CAx development system. * +# * +# This program is free software; you can redistribute it and/or modify * +# it under the terms of the GNU Lesser General Public License (LGPL) * +# as published by the Free Software Foundation; either version 2 of * +# the License, or (at your option) any later version. * +# for detail see the LICENCE text file. * +# * +# FreeCAD is distributed in the hope that it will be useful, * +# but WITHOUT ANY WARRANTY; without even the implied warranty of * +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +# GNU Library General Public License for more details. * +# * +# You should have received a copy of the GNU Library General Public * +# License along with FreeCAD; if not, write to the Free Software * +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * +# USA * +#************************************************************************** + +# import FreeCAD +from os import walk +import unittest +import FreeCAD +import Material + +parseQuantity = FreeCAD.Units.parseQuantity + +class MaterialTestCases(unittest.TestCase): + def setUp(self): + self.ModelManager = Material.ModelManager() + self.MaterialManager = Material.MaterialManager() + self.uuids = Material.UUIDs() + + def testMaterialManager(self): + self.assertIn("MaterialLibraries", dir(self.MaterialManager)) + self.assertIn("Materials", dir(self.MaterialManager)) + + def testCalculiXSteel(self): + steel = self.MaterialManager.getMaterial("92589471-a6cb-4bbc-b748-d425a17dea7d") + self.assertIsNotNone(steel) + self.assertEqual(steel.Name, "CalculiX-Steel") + self.assertEqual(steel.UUID, "92589471-a6cb-4bbc-b748-d425a17dea7d") + + self.assertTrue(steel.hasPhysicalModel(self.uuids.Density)) + self.assertTrue(steel.hasPhysicalModel(self.uuids.IsotropicLinearElastic)) + self.assertTrue(steel.hasPhysicalModel(self.uuids.Thermal)) + self.assertFalse(steel.hasPhysicalModel(self.uuids.LinearElastic)) # Not in the model + self.assertTrue(steel.hasAppearanceModel(self.uuids.BasicRendering)) # inherited from Steel.FCMat + + self.assertTrue(steel.isPhysicalModelComplete(self.uuids.Density)) + self.assertFalse(steel.isPhysicalModelComplete(self.uuids.IsotropicLinearElastic)) + self.assertTrue(steel.isPhysicalModelComplete(self.uuids.Thermal)) + self.assertFalse(steel.isPhysicalModelComplete(self.uuids.LinearElastic)) # Not in the model + self.assertTrue(steel.isAppearanceModelComplete(self.uuids.BasicRendering)) # inherited from Steel.FCMat + + self.assertTrue(steel.hasPhysicalProperty("Density")) + self.assertTrue(steel.hasPhysicalProperty("BulkModulus")) + self.assertTrue(steel.hasPhysicalProperty("PoissonRatio")) + self.assertTrue(steel.hasPhysicalProperty("YoungsModulus")) + self.assertTrue(steel.hasPhysicalProperty("ShearModulus")) + self.assertTrue(steel.hasPhysicalProperty("SpecificHeat")) + self.assertTrue(steel.hasPhysicalProperty("ThermalConductivity")) + self.assertTrue(steel.hasPhysicalProperty("ThermalExpansionCoefficient")) + self.assertTrue(steel.hasAppearanceProperty("AmbientColor")) + self.assertTrue(steel.hasAppearanceProperty("DiffuseColor")) + self.assertTrue(steel.hasAppearanceProperty("EmissiveColor")) + self.assertTrue(steel.hasAppearanceProperty("Shininess")) + self.assertTrue(steel.hasAppearanceProperty("SpecularColor")) + self.assertTrue(steel.hasAppearanceProperty("Transparency")) + + properties = steel.PhysicalProperties + self.assertIn("Density", properties) + self.assertNotIn("BulkModulus", properties) + self.assertIn("PoissonRatio", properties) + self.assertIn("YoungsModulus", properties) + self.assertNotIn("ShearModulus", properties) + self.assertIn("SpecificHeat", properties) + self.assertIn("ThermalConductivity", properties) + self.assertIn("ThermalExpansionCoefficient", properties) + self.assertNotIn("AmbientColor", properties) + self.assertNotIn("DiffuseColor", properties) + self.assertNotIn("EmissiveColor", properties) + self.assertNotIn("Shininess", properties) + self.assertNotIn("SpecularColor", properties) + self.assertNotIn("Transparency", properties) + + properties = steel.AppearanceProperties + self.assertNotIn("Density", properties) + self.assertNotIn("BulkModulus", properties) + self.assertNotIn("PoissonRatio", properties) + self.assertNotIn("YoungsModulus", properties) + self.assertNotIn("ShearModulus", properties) + self.assertNotIn("SpecificHeat", properties) + self.assertNotIn("ThermalConductivity", properties) + self.assertNotIn("ThermalExpansionCoefficient", properties) + self.assertIn("AmbientColor", properties) + self.assertIn("DiffuseColor", properties) + self.assertIn("EmissiveColor", properties) + self.assertIn("Shininess", properties) + self.assertIn("SpecularColor", properties) + self.assertIn("Transparency", properties) + + properties = steel.Properties + self.assertIn("Density", properties) + self.assertNotIn("BulkModulus", properties) + self.assertIn("PoissonRatio", properties) + self.assertIn("YoungsModulus", properties) + self.assertNotIn("ShearModulus", properties) + self.assertIn("SpecificHeat", properties) + self.assertIn("ThermalConductivity", properties) + self.assertIn("ThermalExpansionCoefficient", properties) + self.assertIn("AmbientColor", properties) + self.assertIn("DiffuseColor", properties) + self.assertIn("EmissiveColor", properties) + self.assertIn("Shininess", properties) + self.assertIn("SpecularColor", properties) + self.assertIn("Transparency", properties) + + # + # The test for ThermalExpansionCoefficient causes problems with some localizations + # due to the Unicode mu character in the units. This will happen with + # locales that don't support UTF8 such as zh_CN (It does support UTF-8) + # + # When this is a problem simply comment the lines printing ThermalExpansionCoefficient + print("Density " + properties["Density"]) + # print("BulkModulus " + properties["BulkModulus"]) + print("PoissonRatio " + properties["PoissonRatio"]) + print("YoungsModulus " + properties["YoungsModulus"]) + # print("ShearModulus " + properties["ShearModulus"]) + print("SpecificHeat " + properties["SpecificHeat"]) + print("ThermalConductivity " + properties["ThermalConductivity"]) + print("ThermalExpansionCoefficient " + properties["ThermalExpansionCoefficient"]) + print("AmbientColor " + properties["AmbientColor"]) + print("DiffuseColor " + properties["DiffuseColor"]) + print("EmissiveColor " + properties["EmissiveColor"]) + print("Shininess " + properties["Shininess"]) + print("SpecularColor " + properties["SpecularColor"]) + print("Transparency " + properties["Transparency"]) + + self.assertTrue(len(properties["Density"]) > 0) + # self.assertTrue(len(properties["BulkModulus"]) == 0) + self.assertTrue(len(properties["PoissonRatio"]) > 0) + self.assertTrue(len(properties["YoungsModulus"]) > 0) + # self.assertTrue(len(properties["ShearModulus"]) == 0) + self.assertTrue(len(properties["SpecificHeat"]) > 0) + self.assertTrue(len(properties["ThermalConductivity"]) > 0) + self.assertTrue(len(properties["ThermalExpansionCoefficient"]) > 0) + self.assertTrue(len(properties["AmbientColor"]) > 0) + self.assertTrue(len(properties["DiffuseColor"]) > 0) + self.assertTrue(len(properties["EmissiveColor"]) > 0) + self.assertTrue(len(properties["Shininess"]) > 0) + self.assertTrue(len(properties["SpecularColor"]) > 0) + self.assertTrue(len(properties["Transparency"]) > 0) + + self.assertEqual(properties["Density"], parseQuantity("7900.00 kg/m^3").UserString) + # self.assertEqual(properties["BulkModulus"], "") + self.assertAlmostEqual(parseQuantity(properties["PoissonRatio"]).Value, parseQuantity("0.3").Value) + self.assertEqual(properties["YoungsModulus"], parseQuantity("210.00 GPa").UserString) + # self.assertEqual(properties["ShearModulus"], "") + self.assertEqual(properties["SpecificHeat"], parseQuantity("590.00 J/kg/K").UserString) + self.assertEqual(properties["ThermalConductivity"], parseQuantity("43.00 W/m/K").UserString) + self.assertEqual(properties["ThermalExpansionCoefficient"], parseQuantity("12.00 µm/m/K").UserString) + self.assertEqual(properties["AmbientColor"], "(0.0020, 0.0020, 0.0020, 1.0)") + self.assertEqual(properties["DiffuseColor"], "(0.0000, 0.0000, 0.0000, 1.0)") + self.assertEqual(properties["EmissiveColor"], "(0.0000, 0.0000, 0.0000, 1.0)") + self.assertAlmostEqual(parseQuantity(properties["Shininess"]).Value, parseQuantity("0.06").Value) + self.assertEqual(properties["SpecularColor"], "(0.9800, 0.9800, 0.9800, 1.0)") + self.assertAlmostEqual(parseQuantity(properties["Transparency"]).Value, parseQuantity("0").Value) + + print("Density " + steel.getPhysicalValue("Density").UserString) + # print("BulkModulus " + properties["BulkModulus"]) + print("PoissonRatio %f" % steel.getPhysicalValue("PoissonRatio")) + print("YoungsModulus " + steel.getPhysicalValue("YoungsModulus").UserString) + # print("ShearModulus " + properties["ShearModulus"]) + print("SpecificHeat " + steel.getPhysicalValue("SpecificHeat").UserString) + print("ThermalConductivity " + steel.getPhysicalValue("ThermalConductivity").UserString) + print("ThermalExpansionCoefficient " + steel.getPhysicalValue("ThermalExpansionCoefficient").UserString) + print("AmbientColor " + steel.getAppearanceValue("AmbientColor")) + print("DiffuseColor " + steel.getAppearanceValue("DiffuseColor")) + print("EmissiveColor " + steel.getAppearanceValue("EmissiveColor")) + print("Shininess %f" % steel.getAppearanceValue("Shininess")) + print("SpecularColor " + steel.getAppearanceValue("SpecularColor")) + print("Transparency %f" % steel.getAppearanceValue("Transparency")) + + self.assertAlmostEqual(steel.getPhysicalValue("Density").Value, 7.9e-06) + self.assertAlmostEqual(steel.getPhysicalValue("PoissonRatio"), 0.3) + self.assertAlmostEqual(steel.getPhysicalValue("YoungsModulus").Value, 210000000.0) + self.assertAlmostEqual(steel.getPhysicalValue("SpecificHeat").Value, 590000000.0) + self.assertAlmostEqual(steel.getPhysicalValue("ThermalConductivity").Value, 43000.0) + self.assertAlmostEqual(steel.getPhysicalValue("ThermalExpansionCoefficient").Value, 1.2e-05) + self.assertEqual(steel.getAppearanceValue("AmbientColor"), "(0.0020, 0.0020, 0.0020, 1.0)") + self.assertEqual(steel.getAppearanceValue("DiffuseColor"), "(0.0000, 0.0000, 0.0000, 1.0)") + self.assertEqual(steel.getAppearanceValue("EmissiveColor"), "(0.0000, 0.0000, 0.0000, 1.0)") + self.assertAlmostEqual(steel.getAppearanceValue("Shininess"), 0.06) + self.assertEqual(steel.getAppearanceValue("SpecularColor"), "(0.9800, 0.9800, 0.9800, 1.0)") + self.assertAlmostEqual(steel.getAppearanceValue("Transparency"), 0.0) + + def testMaterialsWithModel(self): + materials = self.MaterialManager.materialsWithModel('f6f9e48c-b116-4e82-ad7f-3659a9219c50') # IsotropicLinearElastic + materialsComplete = self.MaterialManager.materialsWithModelComplete('f6f9e48c-b116-4e82-ad7f-3659a9219c50') # IsotropicLinearElastic + + self.assertTrue(len(materialsComplete) <= len(materials)) # Not all will be complete + + materialsLinearElastic = self.MaterialManager.materialsWithModel('7b561d1d-fb9b-44f6-9da9-56a4f74d7536') # LinearElastic + + # All LinearElastic models should be in IsotropicLinearElastic since it is inherited + self.assertTrue(len(materialsLinearElastic) <= len(materials)) + for mat in materialsLinearElastic: + self.assertIn(mat, materials) + + def testMaterialByPath(self): + steel = self.MaterialManager.getMaterialByPath('StandardMaterial/Metal/Steel/CalculiX-Steel.FCMat', 'System') + self.assertIsNotNone(steel) + self.assertEqual(steel.Name, "CalculiX-Steel") + self.assertEqual(steel.UUID, "92589471-a6cb-4bbc-b748-d425a17dea7d") + + steel2 = self.MaterialManager.getMaterialByPath('/StandardMaterial/Metal/Steel/CalculiX-Steel.FCMat', 'System') + self.assertIsNotNone(steel2) + self.assertEqual(steel2.Name, "CalculiX-Steel") + self.assertEqual(steel2.UUID, "92589471-a6cb-4bbc-b748-d425a17dea7d") + + steel3 = self.MaterialManager.getMaterialByPath('/System/StandardMaterial/Metal/Steel/CalculiX-Steel.FCMat', 'System') + self.assertIsNotNone(steel3) + self.assertEqual(steel3.Name, "CalculiX-Steel") + self.assertEqual(steel3.UUID, "92589471-a6cb-4bbc-b748-d425a17dea7d") diff --git a/src/Mod/Material/materialtests/TestModels.py b/src/Mod/Material/materialtests/TestModels.py new file mode 100644 index 0000000000..d4fd143442 --- /dev/null +++ b/src/Mod/Material/materialtests/TestModels.py @@ -0,0 +1,79 @@ +#************************************************************************** +# Copyright (c) 2023 David Carter * +# * +# This file is part of the FreeCAD CAx development system. * +# * +# This program is free software; you can redistribute it and/or modify * +# it under the terms of the GNU Lesser General Public License (LGPL) * +# as published by the Free Software Foundation; either version 2 of * +# the License, or (at your option) any later version. * +# for detail see the LICENCE text file. * +# * +# FreeCAD is distributed in the hope that it will be useful, * +# but WITHOUT ANY WARRANTY; without even the implied warranty of * +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +# GNU Library General Public License for more details. * +# * +# You should have received a copy of the GNU Library General Public * +# License along with FreeCAD; if not, write to the Free Software * +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * +# USA * +#************************************************************************** + +# import FreeCAD +from os import walk +import unittest +import FreeCAD +import Material + +parseQuantity = FreeCAD.Units.parseQuantity +# import locale +# locale.setpreferredencoding("UTF8") + +class ModelTestCases(unittest.TestCase): + def setUp(self): + self.ModelManager = Material.ModelManager() + self.uuids = Material.UUIDs() + + def testModelManager(self): + self.assertIn("ModelLibraries", dir(self.ModelManager)) + self.assertIn("Models", dir(self.ModelManager)) + + def testUUIDs(self): + self.assertTrue(self.uuids.Father, "9cdda8b6-b606-4778-8f13-3934d8668e67") + self.assertTrue(self.uuids.MaterialStandard, "1e2c0088-904a-4537-925f-64064c07d700") + + self.assertTrue(self.uuids.Density, "454661e5-265b-4320-8e6f-fcf6223ac3af") + self.assertTrue(self.uuids.IsotropicLinearElastic, "f6f9e48c-b116-4e82-ad7f-3659a9219c50") + self.assertTrue(self.uuids.LinearElastic,"7b561d1d-fb9b-44f6-9da9-56a4f74d7536") + self.assertTrue(self.uuids.OgdenYld2004p18, "3ef9e427-cc25-43f7-817f-79ff0d49625f") + self.assertTrue(self.uuids.OrthotropicLinearElastic, "b19ccc6b-a431-418e-91c2-0ac8c649d146") + + self.assertTrue(self.uuids.Fluid, "1ae66d8c-1ba1-4211-ad12-b9917573b202") + + self.assertTrue(self.uuids.Thermal, "9959d007-a970-4ea7-bae4-3eb1b8b883c7") + + self.assertTrue(self.uuids.Electromagnetic, "b2eb5f48-74b3-4193-9fbb-948674f427f3") + + self.assertTrue(self.uuids.Architectural, "32439c3b-262f-4b7b-99a8-f7f44e5894c8") + + self.assertTrue(self.uuids.Costs, "881df808-8726-4c2e-be38-688bb6cce466") + + self.assertTrue(self.uuids.BasicRendering, "f006c7e4-35b7-43d5-bbf9-c5d572309e6e") + self.assertTrue(self.uuids.TextureRendering, "bbdcc65b-67ca-489c-bd5c-a36e33d1c160") + self.assertTrue(self.uuids.AdvancedRendering, "c880f092-cdae-43d6-a24b-55e884aacbbf") + self.assertTrue(self.uuids.VectorRendering, "fdf5a80e-de50-4157-b2e5-b6e5f88b680e") + + def testModelLoad(self): + density = self.ModelManager.getModel(self.uuids.Density) + self.assertIsNotNone(density) + self.assertEqual(density.Name, "Density") + self.assertEqual(density.UUID, "454661e5-265b-4320-8e6f-fcf6223ac3af") + self.assertIn("Density", density.Properties) + prop = density.Properties["Density"] + self.assertIn("Description", dir(prop)) + self.assertIn("Name", dir(prop)) + self.assertIn("Type", dir(prop)) + self.assertIn("URL", dir(prop)) + self.assertIn("Units", dir(prop)) + self.assertEqual(prop.Name, "Density") diff --git a/src/Mod/Material/materialtests/__init__.py b/src/Mod/Material/materialtests/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/Tools/updatecrowdin.py b/src/Tools/updatecrowdin.py index 57c17d890f..15f197b48c 100755 --- a/src/Tools/updatecrowdin.py +++ b/src/Tools/updatecrowdin.py @@ -96,7 +96,6 @@ GENERATE_QM = { "Cloud", "Draft", "Inspection", - "Material", "OpenSCAD", "Tux", "Help", @@ -135,6 +134,11 @@ locations = [ "../Mod/Inspection/Gui/Resources/translations", "../Mod/Inspection/Gui/Resources/Inspection.qrc", ], + [ + "Material", + "../Mod/Material/Gui/Resources/translations", + "../Mod/Material/Gui/Resources/Material.qrc", + ], [ "Mesh", "../Mod/Mesh/Gui/Resources/translations", diff --git a/tests/src/Mod/Material/App/CMakeLists.txt b/tests/src/Mod/Material/App/CMakeLists.txt index 879f74ef06..1e1fe038b7 100644 --- a/tests/src/Mod/Material/App/CMakeLists.txt +++ b/tests/src/Mod/Material/App/CMakeLists.txt @@ -2,5 +2,9 @@ target_sources( Material_tests_run PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR}/Model.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/TestMaterialProperties.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/TestMaterials.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/TestMaterialValue.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/TestModel.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/TestModelProperties.cpp ) diff --git a/tests/src/Mod/Material/App/TestMaterialProperties.cpp b/tests/src/Mod/Material/App/TestMaterialProperties.cpp new file mode 100644 index 0000000000..bac0b1adee --- /dev/null +++ b/tests/src/Mod/Material/App/TestMaterialProperties.cpp @@ -0,0 +1,226 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later +/*************************************************************************** + * Copyright (c) 2023 David Carter * + * * + * This file is part of FreeCAD. * + * * + * FreeCAD is free software: you can redistribute it and/or modify it * + * under the terms of the GNU Lesser General Public License as * + * published by the Free Software Foundation, either version 2.1 of the * + * License, or (at your option) any later version. * + * * + * FreeCAD is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with FreeCAD. If not, see * + * . * + * * + **************************************************************************/ + +#include "gtest/gtest.h" + +#include +#ifndef _PreComp_ +#endif + +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include + +class TestMaterialProperties: public ::testing::Test +{ +protected: + static void SetUpTestSuite() + {} + + void SetUp() override + { + // 2D Properties + modelProp = Materials::ModelProperty(QString::fromStdString("Density"), // Name + QString::fromStdString("2DArray"), // Type + QString::fromStdString(""), // Units + QString::fromStdString(""), // URL + QString::fromStdString("desc")); // Description + modelProp1 = Materials::ModelProperty(QString::fromStdString("Temperature"), + QString::fromStdString("Quantity"), + QString::fromStdString("C"), + QString::fromStdString(""), + QString::fromStdString("desc1")); + modelProp2 = Materials::ModelProperty( + QString::fromStdString("Density"), + QString::fromStdString("Quantity"), + QString::fromStdString("kg/m^3"), + QString::fromStdString("https://en.wikipedia.org/wiki/Density"), + QString::fromStdString("desc2")); + + modelProp.addColumn(modelProp1); + modelProp.addColumn(modelProp2); + + // 3D properties + model3DProp = Materials::ModelProperty( + QString::fromStdString("StressStrain"), // Name + QString::fromStdString("3DArray"), // Type + QString::fromStdString(""), // Units + QString::fromStdString(""), // URL + QString::fromStdString("3 Dimensional array showing stress and strain as a function of " + "temperature")); // Description + model3DProp1 = Materials::ModelProperty(QString::fromStdString("Temperature"), + QString::fromStdString("Quantity"), + QString::fromStdString("C"), + QString::fromStdString(""), + QString::fromStdString("desc1")); + model3DProp2 = Materials::ModelProperty(QString::fromStdString("Stress"), + QString::fromStdString("Quantity"), + QString::fromStdString("MPa"), + QString::fromStdString(""), + QString::fromStdString("desc2")); + model3DProp3 = Materials::ModelProperty(QString::fromStdString("Strain"), + QString::fromStdString("Quantity"), + QString::fromStdString("MPa"), + QString::fromStdString(""), + QString::fromStdString("desc3")); + + model3DProp.addColumn(model3DProp1); + model3DProp.addColumn(model3DProp2); + model3DProp.addColumn(model3DProp3); + } + + // void TearDown() override {} + + Materials::ModelProperty modelProp; + Materials::ModelProperty modelProp1; + Materials::ModelProperty modelProp2; + Materials::ModelProperty model3DProp; + Materials::ModelProperty model3DProp1; + Materials::ModelProperty model3DProp2; + Materials::ModelProperty model3DProp3; +}; + +TEST_F(TestMaterialProperties, TestEmpty) +{ + Materials::MaterialProperty prop; + EXPECT_EQ(prop.getType(), Materials::MaterialValue::None); + EXPECT_TRUE(prop.isNull()); + auto variant = prop.getValue(); + EXPECT_TRUE(variant.isNull()); + EXPECT_FALSE(variant.canConvert()); + EXPECT_TRUE(variant.toString().isNull()); + EXPECT_TRUE(variant.toString().isEmpty()); + EXPECT_EQ(variant.toString().size(), 0); +} + +TEST_F(TestMaterialProperties, TestSingle) +{ + Materials::MaterialProperty prop(modelProp1); + EXPECT_EQ(prop.getType(), Materials::MaterialValue::Quantity); + EXPECT_TRUE(prop.isNull()); + auto variant = prop.getValue(); + EXPECT_TRUE(variant.canConvert()); + EXPECT_FALSE(variant.value().isValid()); + EXPECT_FALSE(variant.canConvert()); + EXPECT_TRUE(variant.toString().isNull()); + EXPECT_TRUE(variant.toString().isEmpty()); + EXPECT_EQ(variant.toString().size(), 0); +} + +void check2DArray(Materials::MaterialProperty& prop) +{ + EXPECT_EQ(prop.getType(), Materials::MaterialValue::Array2D); + EXPECT_TRUE(prop.isNull()); + auto array = std::static_pointer_cast(prop.getMaterialValue()); + EXPECT_FALSE(array->defaultSet()); + EXPECT_EQ(array->rows(), 0); + auto variant = prop.getValue(); // Throw an error? + // Getting a default value is not yet defined or implemented + // EXPECT_TRUE(variant.canConvert()); + // EXPECT_TRUE(variant.isNull()); + // EXPECT_FALSE(variant.value().isValid()); -- the variant is null + EXPECT_FALSE(variant.canConvert()); + EXPECT_TRUE(variant.toString().isNull()); + EXPECT_TRUE(variant.toString().isEmpty()); + EXPECT_EQ(variant.toString().size(), 0); + + // Check the columns + EXPECT_EQ(prop.columns(), 2); +} + +TEST_F(TestMaterialProperties, Test2DArray) +{ + Materials::MaterialProperty prop(modelProp); + check2DArray(prop); +} + +TEST_F(TestMaterialProperties, Test2DArrayCopy) +{ + Materials::MaterialProperty propBase(modelProp); + Materials::MaterialProperty prop(propBase); + check2DArray(prop); +} + +TEST_F(TestMaterialProperties, Test2DArrayAssignment) +{ + Materials::MaterialProperty propBase(modelProp); + Materials::MaterialProperty prop; + + prop = propBase; + check2DArray(prop); +} + +void check3DArray(Materials::MaterialProperty& prop) +{ + EXPECT_EQ(prop.getType(), Materials::MaterialValue::Array3D); + EXPECT_TRUE(prop.isNull()); + auto array = std::static_pointer_cast(prop.getMaterialValue()); + EXPECT_FALSE(array->defaultSet()); + EXPECT_EQ(array->depth(), 0); + auto variant = prop.getValue(); // Throw an error? + // Getting a default value is not yet defined or implemented + // EXPECT_TRUE(variant.canConvert()); + // EXPECT_TRUE(variant.isNull()); + // EXPECT_FALSE(variant.value().isValid()); -- the variant is null + EXPECT_FALSE(variant.canConvert()); + EXPECT_TRUE(variant.toString().isNull()); + EXPECT_TRUE(variant.toString().isEmpty()); + EXPECT_EQ(variant.toString().size(), 0); + + // Check the columns + EXPECT_EQ(prop.columns(), 3); +} + +TEST_F(TestMaterialProperties, Test3DArray) +{ + Materials::MaterialProperty prop(model3DProp); + check3DArray(prop); +} + +TEST_F(TestMaterialProperties, Test3DArrayCopy) +{ + Materials::MaterialProperty propBase(model3DProp); + Materials::MaterialProperty prop(propBase); + check3DArray(prop); +} + +TEST_F(TestMaterialProperties, Test3DArrayAssignment) +{ + Materials::MaterialProperty propBase(model3DProp); + Materials::MaterialProperty prop; + + prop = propBase; + check3DArray(prop); +} + +// clang-format off + +// clang-format on diff --git a/tests/src/Mod/Material/App/TestMaterialValue.cpp b/tests/src/Mod/Material/App/TestMaterialValue.cpp new file mode 100644 index 0000000000..d39023f939 --- /dev/null +++ b/tests/src/Mod/Material/App/TestMaterialValue.cpp @@ -0,0 +1,310 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later +/*************************************************************************** + * Copyright (c) 2023 David Carter * + * * + * This file is part of FreeCAD. * + * * + * FreeCAD is free software: you can redistribute it and/or modify it * + * under the terms of the GNU Lesser General Public License as * + * published by the Free Software Foundation, either version 2.1 of the * + * License, or (at your option) any later version. * + * * + * FreeCAD is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with FreeCAD. If not, see * + * . * + * * + **************************************************************************/ + +#include "gtest/gtest.h" + +#include +#ifndef _PreComp_ +#endif + +#include +#include + +#include +#include + +#include +#include +#include +#include + +// clang-format off + +class TestMaterialValue : public ::testing::Test { + protected: + static void SetUpTestSuite() { + // if (App::Application::GetARGC() == 0) { + // constexpr int argc = 1; + // std::array argv {"FreeCAD"}; + // App::Application::Config()["ExeName"] = "FreeCAD"; + // App::Application::init(argc, argv.data()); + // } + } + +// void SetUp() override { +// _modelManager = new Materials::ModelManager(); +// _materialManager = new Materials::MaterialManager(); +// } + + // void TearDown() override {} +// Materials::ModelManager* _modelManager; +// Materials::MaterialManager* _materialManager; +}; + +TEST_F(TestMaterialValue, TestNoneType) +{ + auto mat1 = Materials::MaterialValue(); + EXPECT_EQ(mat1.getType(), Materials::MaterialValue::None); + EXPECT_TRUE(mat1.isNull()); + auto variant = mat1.getValue(); + EXPECT_TRUE(variant.isNull()); + EXPECT_FALSE(variant.canConvert()); + EXPECT_TRUE(variant.toString().isNull()); + EXPECT_TRUE(variant.toString().isEmpty()); + EXPECT_EQ(variant.toString().size(), 0); +} + +TEST_F(TestMaterialValue, TestStringType) +{ + auto mat1 = Materials::MaterialValue(Materials::MaterialValue::String); + EXPECT_EQ(mat1.getType(), Materials::MaterialValue::String); + EXPECT_TRUE(mat1.isNull()); + auto variant = mat1.getValue(); + EXPECT_TRUE(variant.isNull()); + EXPECT_TRUE(variant.canConvert()); + EXPECT_TRUE(variant.toString().isNull()); + EXPECT_TRUE(variant.toString().isEmpty()); + EXPECT_EQ(variant.toString().size(), 0); +} + +TEST_F(TestMaterialValue, TestBooleanType) +{ + auto mat1 = Materials::MaterialValue(Materials::MaterialValue::Boolean); + EXPECT_EQ(mat1.getType(), Materials::MaterialValue::Boolean); + EXPECT_TRUE(mat1.isNull()); + auto variant = mat1.getValue(); + EXPECT_TRUE(variant.isNull()); + EXPECT_TRUE(variant.canConvert()); + EXPECT_FALSE(variant.toString().isNull()); + EXPECT_FALSE(variant.toString().isEmpty()); + EXPECT_EQ(variant.toString().size(), 5); + EXPECT_EQ(variant.toString(), QString::fromStdString("false")); + EXPECT_EQ(variant.toBool(), false); +} + +TEST_F(TestMaterialValue, TestIntegerType) +{ + auto mat1 = Materials::MaterialValue(Materials::MaterialValue::Integer); + EXPECT_EQ(mat1.getType(), Materials::MaterialValue::Integer); + EXPECT_TRUE(mat1.isNull()); + auto variant = mat1.getValue(); + EXPECT_TRUE(variant.isNull()); + EXPECT_TRUE(variant.canConvert()); + EXPECT_FALSE(variant.toString().isNull()); + EXPECT_FALSE(variant.toString().isEmpty()); + EXPECT_EQ(variant.toString().size(), 1); + EXPECT_EQ(variant.toString(), QString::fromStdString("0")); + EXPECT_EQ(variant.toInt(), 0); +} + +TEST_F(TestMaterialValue, TestFloatType) +{ + auto mat1 = Materials::MaterialValue(Materials::MaterialValue::Float); + EXPECT_EQ(mat1.getType(), Materials::MaterialValue::Float); + EXPECT_TRUE(mat1.isNull()); + auto variant = mat1.getValue(); + EXPECT_TRUE(variant.isNull()); + EXPECT_TRUE(variant.canConvert()); + EXPECT_FALSE(variant.toString().isNull()); + EXPECT_FALSE(variant.toString().isEmpty()); + EXPECT_EQ(variant.toString().size(), 1); + EXPECT_EQ(variant.toString(), QString::fromStdString("0")); + EXPECT_EQ(variant.toFloat(), 0); +} + +TEST_F(TestMaterialValue, TestQuantityType) +{ + auto mat1 = Materials::MaterialValue(Materials::MaterialValue::Quantity); + EXPECT_EQ(mat1.getType(), Materials::MaterialValue::Quantity); + EXPECT_TRUE(mat1.isNull()); + + auto variant = mat1.getValue(); + EXPECT_FALSE(variant.isNull()); + EXPECT_TRUE(variant.canConvert()); + EXPECT_TRUE(variant.toString().isNull()); + EXPECT_TRUE(variant.toString().isEmpty()); + EXPECT_EQ(variant.toString().size(), 0); + + auto quantity = variant.value(); + EXPECT_FALSE(quantity.isValid()); + EXPECT_EQ(quantity.getUserString(), QString::fromStdString("nan ")); + EXPECT_TRUE(std::isnan(quantity.getValue())); + + // Test a copy + auto mat2 = Materials::MaterialValue(mat1); + EXPECT_EQ(mat2.getType(), Materials::MaterialValue::Quantity); + EXPECT_TRUE(mat2.isNull()); + + variant = mat2.getValue(); + EXPECT_FALSE(variant.isNull()); + EXPECT_TRUE(variant.canConvert()); + EXPECT_TRUE(variant.toString().isNull()); + EXPECT_TRUE(variant.toString().isEmpty()); + EXPECT_EQ(variant.toString().size(), 0); + + quantity = variant.value(); + EXPECT_FALSE(quantity.isValid()); + EXPECT_EQ(quantity.getUserString(), QString::fromStdString("nan ")); + EXPECT_TRUE(std::isnan(quantity.getValue())); +} + +TEST_F(TestMaterialValue, TestListType) +{ + auto mat1 = Materials::MaterialValue(Materials::MaterialValue::List); + EXPECT_EQ(mat1.getType(), Materials::MaterialValue::List); + EXPECT_TRUE(mat1.isNull()); + auto variant = mat1.getValue(); + EXPECT_TRUE(variant.isNull()); + EXPECT_TRUE(variant.canConvert()); + EXPECT_TRUE(variant.toString().isNull()); + EXPECT_TRUE(variant.toString().isEmpty()); + EXPECT_EQ(variant.toString().size(), 0); +} + +TEST_F(TestMaterialValue, TestArray2DType) +{ + EXPECT_THROW(auto mat1 = Materials::MaterialValue(Materials::MaterialValue::Array2D), Materials::InvalidMaterialType); + + auto mat2 = Materials::Material2DArray(); + EXPECT_EQ(mat2.getType(), Materials::MaterialValue::Array2D); + EXPECT_TRUE(mat2.isNull()); + auto variant = mat2.getDefault(); + EXPECT_TRUE(variant.isNull()); + EXPECT_FALSE(variant.canConvert()); + EXPECT_TRUE(variant.toString().isNull()); + EXPECT_TRUE(variant.toString().isEmpty()); + EXPECT_EQ(variant.toString().size(), 0); + + EXPECT_EQ(mat2.rows(), 0); +} + +TEST_F(TestMaterialValue, TestArray3DType) +{ + EXPECT_THROW(auto mat1 = Materials::MaterialValue(Materials::MaterialValue::Array3D), Materials::InvalidMaterialType); + + auto mat2 = Materials::Material3DArray(); + EXPECT_EQ(mat2.getType(), Materials::MaterialValue::Array3D); + EXPECT_TRUE(mat2.isNull()); + auto variant = mat2.getDefault(); + EXPECT_TRUE(variant.isNull()); + EXPECT_FALSE(variant.canConvert()); + EXPECT_TRUE(variant.toString().isNull()); + EXPECT_TRUE(variant.toString().isEmpty()); + EXPECT_EQ(variant.toString().size(), 0); + + EXPECT_EQ(mat2.depth(), 0); + EXPECT_EQ(mat2.rows(), 0); + EXPECT_EQ(mat2.rows(0), 0); + EXPECT_THROW(mat2.rows(1), Materials::InvalidDepth); + + Base::Quantity quantity; + quantity.setInvalid(); + + EXPECT_EQ(mat2.addDepth(0, quantity), 0); + EXPECT_EQ(mat2.depth(), 1); + EXPECT_EQ(mat2.rows(0), 0); + EXPECT_THROW(mat2.rows(1), Materials::InvalidDepth); + + EXPECT_EQ(mat2.addDepth(quantity), 1); + EXPECT_EQ(mat2.depth(), 2); + EXPECT_EQ(mat2.rows(1), 0); + + EXPECT_THROW(mat2.addDepth(99, quantity), Materials::InvalidDepth); + EXPECT_EQ(mat2.addDepth(2, quantity), 2); + EXPECT_EQ(mat2.depth(), 3); + EXPECT_EQ(mat2.rows(2), 0); + + // Add rows + auto row = std::make_shared>(); + row->push_back(quantity); + row->push_back(quantity); + + EXPECT_EQ(mat2.rows(0), 0); + EXPECT_EQ(mat2.rows(1), 0); + EXPECT_EQ(mat2.rows(2), 0); + + mat2.addRow(0, row); + EXPECT_EQ(mat2.rows(0), 1); + EXPECT_EQ(mat2.rows(1), 0); + EXPECT_EQ(mat2.rows(2), 0); + + mat2.addRow(1, row); + EXPECT_EQ(mat2.rows(0), 1); + EXPECT_EQ(mat2.rows(1), 1); + EXPECT_EQ(mat2.rows(2), 0); + + mat2.addRow(2, row); + EXPECT_EQ(mat2.rows(0), 1); + EXPECT_EQ(mat2.rows(1), 1); + EXPECT_EQ(mat2.rows(2), 1); + + EXPECT_EQ(mat2.currentDepth(), 0); + mat2.addRow(row); + EXPECT_EQ(mat2.rows(0), 2); + EXPECT_EQ(mat2.rows(1), 1); + EXPECT_EQ(mat2.rows(2), 1); + + mat2.setCurrentDepth(2); + EXPECT_EQ(mat2.currentDepth(), 2); + mat2.addRow(row); + EXPECT_EQ(mat2.rows(0), 2); + EXPECT_EQ(mat2.rows(1), 1); + EXPECT_EQ(mat2.rows(2), 2); + + quantity = Base::Quantity::parse(QString::fromStdString("32 C")); + mat2.setDepthValue(quantity); + EXPECT_FALSE(mat2.getDepthValue(0).isValid()); + EXPECT_FALSE(mat2.getDepthValue(1).isValid()); + EXPECT_TRUE(mat2.getDepthValue(2).isValid()); + EXPECT_EQ(mat2.getDepthValue(2), Base::Quantity::parse(QString::fromStdString("32 C"))); + + mat2.setDepthValue(0, Base::Quantity::parse(QString::fromStdString("9.8 m/s/s"))); + EXPECT_TRUE(mat2.getDepthValue(0).isValid()); + EXPECT_FALSE(mat2.getDepthValue(1).isValid()); + EXPECT_TRUE(mat2.getDepthValue(2).isValid()); + EXPECT_EQ(mat2.getDepthValue(0), Base::Quantity::parse(QString::fromStdString("9.8 m/s/s"))); + EXPECT_EQ(mat2.getDepthValue(2), Base::Quantity::parse(QString::fromStdString("32 C"))); + + mat2.setDepthValue(1, Base::Quantity::parse(QString::fromStdString("120 MPa"))); + EXPECT_TRUE(mat2.getDepthValue(0).isValid()); + EXPECT_TRUE(mat2.getDepthValue(1).isValid()); + EXPECT_TRUE(mat2.getDepthValue(2).isValid()); + EXPECT_EQ(mat2.getDepthValue(0), Base::Quantity::parse(QString::fromStdString("9.8 m/s/s"))); + EXPECT_EQ(mat2.getDepthValue(1), Base::Quantity::parse(QString::fromStdString("120 MPa"))); + EXPECT_EQ(mat2.getDepthValue(2), Base::Quantity::parse(QString::fromStdString("32 C"))); + + // Rows are currently empty + EXPECT_THROW(mat2.getValue(2, 0), Materials::InvalidRow); + EXPECT_NO_THROW(mat2.getValue(0, 0)); + EXPECT_FALSE(mat2.getValue(0, 0).isValid()); + EXPECT_FALSE(mat2.getValue(0, 1).isValid()); + + // set to a valid quantity + mat2.setValue(0, 0, Base::Quantity::parse(QString::fromStdString("120 MPa"))); + EXPECT_TRUE(mat2.getValue(0, 0).isValid()); + mat2.setValue(0, 1, Base::Quantity::parse(QString::fromStdString("9.8 m/s/s"))); + EXPECT_TRUE(mat2.getValue(0, 1).isValid()); + EXPECT_THROW(mat2.setValue(0, 2, Base::Quantity::parse(QString::fromStdString("32 C"))), Materials::InvalidColumn); + +} + +// clang-format on diff --git a/tests/src/Mod/Material/App/TestMaterials.cpp b/tests/src/Mod/Material/App/TestMaterials.cpp new file mode 100644 index 0000000000..e06212c3d4 --- /dev/null +++ b/tests/src/Mod/Material/App/TestMaterials.cpp @@ -0,0 +1,339 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later +/*************************************************************************** + * Copyright (c) 2023 David Carter * + * * + * This file is part of FreeCAD. * + * * + * FreeCAD is free software: you can redistribute it and/or modify it * + * under the terms of the GNU Lesser General Public License as * + * published by the Free Software Foundation, either version 2.1 of the * + * License, or (at your option) any later version. * + * * + * FreeCAD is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with FreeCAD. If not, see * + * . * + * * + **************************************************************************/ + +#include "gtest/gtest.h" + +#include +#ifndef _PreComp_ +#endif + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +// clang-format off + +class TestMaterial : public ::testing::Test { + protected: + static void SetUpTestSuite() { + if (App::Application::GetARGC() == 0) { + constexpr int argc = 1; + std::array argv {"FreeCAD"}; + App::Application::Config()["ExeName"] = "FreeCAD"; + App::Application::init(argc, argv.data()); + } + } + + void SetUp() override { + _modelManager = new Materials::ModelManager(); + _materialManager = new Materials::MaterialManager(); + } + + // void TearDown() override {} + Materials::ModelManager* _modelManager; + Materials::MaterialManager* _materialManager; +}; + +TEST_F(TestMaterial, TestInstallation) +{ + EXPECT_NE(_modelManager, nullptr); + + // We should have loaded at least the system library + auto libraries = _materialManager->getMaterialLibraries(); + ASSERT_GT(libraries->size(), 0); + + // We should have at least one material + auto materials = _materialManager->getMaterials(); + ASSERT_GT(materials->size(), 0); +} + +TEST_F(TestMaterial, TestMaterialsWithModel) +{ + auto materials = _materialManager->materialsWithModel( + QString::fromStdString("f6f9e48c-b116-4e82-ad7f-3659a9219c50")); // IsotropicLinearElastic + EXPECT_GT(materials->size(), 0); + + auto materialsComplete = _materialManager->materialsWithModelComplete( + QString::fromStdString("f6f9e48c-b116-4e82-ad7f-3659a9219c50")); // IsotropicLinearElastic + EXPECT_LE(materialsComplete->size(), materials->size()); + + auto materialsLinearElastic = _materialManager->materialsWithModel( + QString::fromStdString("7b561d1d-fb9b-44f6-9da9-56a4f74d7536")); // LinearElastic + + // All LinearElastic models should be in IsotropicLinearElastic since it is inherited + EXPECT_LE(materialsLinearElastic->size(), materials->size()); + for (auto itp = materialsLinearElastic->begin(); itp != materialsLinearElastic->end(); itp++) { + auto mat = itp->first; + EXPECT_NO_THROW(materials->at(mat)); + } +} + +TEST_F(TestMaterial, TestMaterialByPath) +{ + auto steel = _materialManager->getMaterialByPath( + QString::fromStdString("StandardMaterial/Metal/Steel/CalculiX-Steel.FCMat"), + QString::fromStdString("System")); + EXPECT_NE(&steel, nullptr); + EXPECT_EQ(steel->getName(), QString::fromStdString("CalculiX-Steel")); + EXPECT_EQ(steel->getUUID(), QString::fromStdString("92589471-a6cb-4bbc-b748-d425a17dea7d")); + + // The same but with a leading '/' + auto steel2 = _materialManager->getMaterialByPath( + QString::fromStdString("/StandardMaterial/Metal/Steel/CalculiX-Steel.FCMat"), + QString::fromStdString("System")); + EXPECT_NE(&steel2, nullptr); + EXPECT_EQ(steel2->getName(), QString::fromStdString("CalculiX-Steel")); + EXPECT_EQ(steel2->getUUID(), QString::fromStdString("92589471-a6cb-4bbc-b748-d425a17dea7d")); + + // Same with the library name as a prefix + auto steel3 = _materialManager->getMaterialByPath( + QString::fromStdString("/System/StandardMaterial/Metal/Steel/CalculiX-Steel.FCMat"), + QString::fromStdString("System")); + EXPECT_NE(&steel3, nullptr); + EXPECT_EQ(steel3->getName(), QString::fromStdString("CalculiX-Steel")); + EXPECT_EQ(steel3->getUUID(), QString::fromStdString("92589471-a6cb-4bbc-b748-d425a17dea7d")); +} + +TEST_F(TestMaterial, TestAddPhysicalModel) +{ + // Start with an empty material + Materials::Material material; + auto models = material.getPhysicalModels(); + EXPECT_NE(&models, nullptr); + EXPECT_EQ(models->size(), 0); + + // Add a model + material.addPhysical(Materials::ModelUUIDs::ModelUUID_Electromagnetic_Default); + models = material.getPhysicalModels(); + EXPECT_EQ(models->size(), 1); + + // Add a second model + material.addPhysical(Materials::ModelUUIDs::ModelUUID_Mechanical_LinearElastic); + models = material.getPhysicalModels(); + EXPECT_EQ(models->size(), 2); + + // Add an inherited model + material.addPhysical(Materials::ModelUUIDs::ModelUUID_Mechanical_IsotropicLinearElastic); + models = material.getPhysicalModels(); + EXPECT_EQ(models->size(), 2); + + // Add a super model + material.clearModels(); + EXPECT_EQ(models->size(), 0); + + material.addPhysical(Materials::ModelUUIDs::ModelUUID_Mechanical_IsotropicLinearElastic); + models = material.getPhysicalModels(); + EXPECT_EQ(models->size(), 1); + material.addPhysical(Materials::ModelUUIDs::ModelUUID_Mechanical_LinearElastic); + models = material.getPhysicalModels(); + EXPECT_EQ(models->size(), 1); + + // Remove the inherited model + material.removePhysical(Materials::ModelUUIDs::ModelUUID_Mechanical_IsotropicLinearElastic); + models = material.getPhysicalModels(); + EXPECT_EQ(models->size(), 1); + + // Remove the super model + material.removePhysical(Materials::ModelUUIDs::ModelUUID_Mechanical_LinearElastic); + models = material.getPhysicalModels(); + EXPECT_EQ(models->size(), 0); +} + +TEST_F(TestMaterial, TestAddAppearanceModel) +{ + // Start with an empty material + Materials::Material material; + auto models = material.getAppearanceModels(); + EXPECT_NE(models, nullptr); + EXPECT_EQ(models->size(), 0); + + // Add a model + material.addAppearance(Materials::ModelUUIDs::ModelUUID_Rendering_Vector); + models = material.getAppearanceModels(); + EXPECT_EQ(models->size(), 1); + + // Add a second model + material.addAppearance(Materials::ModelUUIDs::ModelUUID_Rendering_Advanced); + models = material.getAppearanceModels(); + EXPECT_EQ(models->size(), 2); + + // Add an inherited model + material.addAppearance(Materials::ModelUUIDs::ModelUUID_Rendering_Basic); + models = material.getAppearanceModels(); + EXPECT_EQ(models->size(), 2); + + // Add a super model + material.clearModels(); + EXPECT_EQ(models->size(), 0); + + material.addAppearance(Materials::ModelUUIDs::ModelUUID_Rendering_Basic); + models = material.getAppearanceModels(); + EXPECT_EQ(models->size(), 1); + material.addAppearance(Materials::ModelUUIDs::ModelUUID_Rendering_Advanced); + models = material.getAppearanceModels(); + EXPECT_EQ(models->size(), 1); + + // Remove the inherited model + material.removeAppearance(Materials::ModelUUIDs::ModelUUID_Rendering_Basic); + models = material.getAppearanceModels(); + EXPECT_EQ(models->size(), 1); + + // Remove the super model + material.removeAppearance(Materials::ModelUUIDs::ModelUUID_Rendering_Advanced); + models = material.getAppearanceModels(); + EXPECT_EQ(models->size(), 0); +} + +QString parseQuantity(const char *string) +{ + QString value = QString::fromStdString(string); + return Base::Quantity::parse(value).getUserString(); +} + +TEST_F(TestMaterial, TestCalculiXSteel) +{ + auto steel = _materialManager->getMaterial(QString::fromStdString("92589471-a6cb-4bbc-b748-d425a17dea7d")); + EXPECT_EQ(steel->getName(), QString::fromStdString("CalculiX-Steel")); + EXPECT_EQ(steel->getUUID(), QString::fromStdString("92589471-a6cb-4bbc-b748-d425a17dea7d")); + + EXPECT_TRUE(steel->hasPhysicalModel(Materials::ModelUUIDs::ModelUUID_Mechanical_Density)); // Density + EXPECT_TRUE(steel->hasPhysicalModel(Materials::ModelUUIDs::ModelUUID_Mechanical_IsotropicLinearElastic)); // IsotropicLinearElastic + EXPECT_TRUE(steel->hasPhysicalModel(Materials::ModelUUIDs::ModelUUID_Thermal_Default)); // Thermal + EXPECT_FALSE(steel->hasPhysicalModel(Materials::ModelUUIDs::ModelUUID_Mechanical_LinearElastic)); // Legacy linear elastic - Not in the model + EXPECT_TRUE(steel->hasAppearanceModel(Materials::ModelUUIDs::ModelUUID_Rendering_Basic)); // BasicRendering - inherited from Steel.FCMat + + EXPECT_TRUE(steel->isPhysicalModelComplete(Materials::ModelUUIDs::ModelUUID_Mechanical_Density)); // Density + EXPECT_FALSE(steel->isPhysicalModelComplete(Materials::ModelUUIDs::ModelUUID_Mechanical_IsotropicLinearElastic)); // IsotropicLinearElastic - incomplete + EXPECT_TRUE(steel->isPhysicalModelComplete(Materials::ModelUUIDs::ModelUUID_Thermal_Default)); // Thermal + EXPECT_FALSE(steel->isPhysicalModelComplete(Materials::ModelUUIDs::ModelUUID_Mechanical_LinearElastic)); // Legacy linear elastic - Not in the model + EXPECT_TRUE(steel->isAppearanceModelComplete(Materials::ModelUUIDs::ModelUUID_Rendering_Basic)); // BasicRendering - inherited from Steel.FCMat + + EXPECT_TRUE(steel->hasPhysicalProperty(QString::fromStdString("Density"))); + EXPECT_TRUE(steel->hasPhysicalProperty(QString::fromStdString("BulkModulus"))); + EXPECT_TRUE(steel->hasPhysicalProperty(QString::fromStdString("PoissonRatio"))); + EXPECT_TRUE(steel->hasPhysicalProperty(QString::fromStdString("YoungsModulus"))); + EXPECT_TRUE(steel->hasPhysicalProperty(QString::fromStdString("ShearModulus"))); + EXPECT_TRUE(steel->hasPhysicalProperty(QString::fromStdString("SpecificHeat"))); + EXPECT_TRUE(steel->hasPhysicalProperty(QString::fromStdString("ThermalConductivity"))); + EXPECT_TRUE(steel->hasPhysicalProperty(QString::fromStdString("ThermalExpansionCoefficient"))); + EXPECT_TRUE(steel->hasAppearanceProperty(QString::fromStdString("AmbientColor"))); + EXPECT_TRUE(steel->hasAppearanceProperty(QString::fromStdString("DiffuseColor"))); + EXPECT_TRUE(steel->hasAppearanceProperty(QString::fromStdString("EmissiveColor"))); + EXPECT_TRUE(steel->hasAppearanceProperty(QString::fromStdString("Shininess"))); + EXPECT_TRUE(steel->hasAppearanceProperty(QString::fromStdString("SpecularColor"))); + EXPECT_TRUE(steel->hasAppearanceProperty(QString::fromStdString("Transparency"))); + + auto& properties = steel->getPhysicalProperties(); + EXPECT_NO_THROW(properties.at(QString::fromStdString("Density"))); + EXPECT_NO_THROW(properties.at(QString::fromStdString("BulkModulus"))); // This is different from the Python behaviour + EXPECT_NO_THROW(properties.at(QString::fromStdString("PoissonRatio"))); + EXPECT_NO_THROW(properties.at(QString::fromStdString("YoungsModulus"))); + EXPECT_NO_THROW(properties.at(QString::fromStdString("ShearModulus"))); + EXPECT_NO_THROW(properties.at(QString::fromStdString("SpecificHeat"))); + EXPECT_NO_THROW(properties.at(QString::fromStdString("ThermalConductivity"))); + EXPECT_NO_THROW(properties.at(QString::fromStdString("ThermalExpansionCoefficient"))); + EXPECT_THROW(properties.at(QString::fromStdString("AmbientColor")), std::out_of_range); + EXPECT_THROW(properties.at(QString::fromStdString("DiffuseColor")), std::out_of_range); + EXPECT_THROW(properties.at(QString::fromStdString("EmissiveColor")), std::out_of_range); + EXPECT_THROW(properties.at(QString::fromStdString("Shininess")), std::out_of_range); + EXPECT_THROW(properties.at(QString::fromStdString("SpecularColor")), std::out_of_range); + EXPECT_THROW(properties.at(QString::fromStdString("Transparency")), std::out_of_range); + + auto& properties1 = steel->getAppearanceProperties(); + EXPECT_THROW(properties1.at(QString::fromStdString("Density")), std::out_of_range); + EXPECT_THROW(properties1.at(QString::fromStdString("BulkModulus")), std::out_of_range); + EXPECT_THROW(properties1.at(QString::fromStdString("PoissonRatio")), std::out_of_range); + EXPECT_THROW(properties1.at(QString::fromStdString("YoungsModulus")), std::out_of_range); + EXPECT_THROW(properties1.at(QString::fromStdString("ShearModulus")), std::out_of_range); + EXPECT_THROW(properties1.at(QString::fromStdString("SpecificHeat")), std::out_of_range); + EXPECT_THROW(properties1.at(QString::fromStdString("ThermalConductivity")), std::out_of_range); + EXPECT_THROW(properties1.at(QString::fromStdString("ThermalExpansionCoefficient")), std::out_of_range); + EXPECT_NO_THROW(properties1.at(QString::fromStdString("AmbientColor"))); + EXPECT_NO_THROW(properties1.at(QString::fromStdString("DiffuseColor"))); + EXPECT_NO_THROW(properties1.at(QString::fromStdString("EmissiveColor"))); + EXPECT_NO_THROW(properties1.at(QString::fromStdString("Shininess"))); + EXPECT_NO_THROW(properties1.at(QString::fromStdString("SpecularColor"))); + EXPECT_NO_THROW(properties1.at(QString::fromStdString("Transparency"))); + + EXPECT_FALSE(properties[QString::fromStdString("Density")]->isNull()); + EXPECT_TRUE(properties[QString::fromStdString("BulkModulus")]->isNull()); + EXPECT_FALSE(properties[QString::fromStdString("PoissonRatio")]->isNull()); + EXPECT_FALSE(properties[QString::fromStdString("YoungsModulus")]->isNull()); + EXPECT_TRUE(properties[QString::fromStdString("ShearModulus")]->isNull()); + EXPECT_FALSE(properties[QString::fromStdString("SpecificHeat")]->isNull()); + EXPECT_FALSE(properties[QString::fromStdString("ThermalConductivity")]->isNull()); + EXPECT_FALSE(properties[QString::fromStdString("ThermalExpansionCoefficient")]->isNull()); + EXPECT_FALSE(properties1[QString::fromStdString("AmbientColor")]->isNull()); + EXPECT_FALSE(properties1[QString::fromStdString("DiffuseColor")]->isNull()); + EXPECT_FALSE(properties1[QString::fromStdString("EmissiveColor")]->isNull()); + EXPECT_FALSE(properties1[QString::fromStdString("Shininess")]->isNull()); + EXPECT_FALSE(properties1[QString::fromStdString("SpecularColor")]->isNull()); + EXPECT_FALSE(properties1[QString::fromStdString("Transparency")]->isNull()); + + EXPECT_EQ(properties[QString::fromStdString("Density")]->getString(), parseQuantity("7900.00 kg/m^3")); + EXPECT_EQ(properties[QString::fromStdString("PoissonRatio")]->getString(), QString::fromStdString("0.3")); + EXPECT_EQ(properties[QString::fromStdString("YoungsModulus")]->getString(), parseQuantity("210.00 GPa")); + EXPECT_EQ(properties[QString::fromStdString("SpecificHeat")]->getString(), parseQuantity("590.00 J/kg/K")); + EXPECT_EQ(properties[QString::fromStdString("ThermalConductivity")]->getString(), parseQuantity("43.00 W/m/K")); + EXPECT_EQ(properties[QString::fromStdString("ThermalExpansionCoefficient")]->getString(), parseQuantity("12.00 µm/m/K")); + EXPECT_EQ(properties1[QString::fromStdString("AmbientColor")]->getString(), QString::fromStdString("(0.0020, 0.0020, 0.0020, 1.0)")); + EXPECT_EQ(properties1[QString::fromStdString("DiffuseColor")]->getString(), QString::fromStdString("(0.0000, 0.0000, 0.0000, 1.0)")); + EXPECT_EQ(properties1[QString::fromStdString("EmissiveColor")]->getString(), QString::fromStdString("(0.0000, 0.0000, 0.0000, 1.0)")); + EXPECT_EQ(properties1[QString::fromStdString("Shininess")]->getString(), QString::fromStdString("0.06")); + EXPECT_EQ(properties1[QString::fromStdString("SpecularColor")]->getString(), QString::fromStdString("(0.9800, 0.9800, 0.9800, 1.0)")); + EXPECT_EQ(properties1[QString::fromStdString("Transparency")]->getString(), QString::fromStdString("0")); + + EXPECT_TRUE(properties[QString::fromStdString("BulkModulus")]->getString().isEmpty()); + EXPECT_TRUE(properties[QString::fromStdString("ShearModulus")]->getString().isEmpty()); + + // These are the preferred method of access + // + EXPECT_FLOAT_EQ(steel->getPhysicalQuantity(QString::fromStdString("Density")).getValue(), 7.9e-06); + EXPECT_FLOAT_EQ(steel->getPhysicalValue(QString::fromStdString("PoissonRatio")).toDouble(), 0.3); + EXPECT_FLOAT_EQ(steel->getPhysicalQuantity(QString::fromStdString("YoungsModulus")).getValue(), 210000000.0); + EXPECT_FLOAT_EQ(steel->getPhysicalQuantity(QString::fromStdString("SpecificHeat")).getValue(), 590000000.0); + EXPECT_FLOAT_EQ(steel->getPhysicalQuantity(QString::fromStdString("ThermalConductivity")).getValue(), 43000.0); + EXPECT_FLOAT_EQ(steel->getPhysicalQuantity(QString::fromStdString("ThermalExpansionCoefficient")).getValue(), 1.2e-05); + EXPECT_EQ(steel->getAppearanceValue(QString::fromStdString("AmbientColor")), QString::fromStdString("(0.0020, 0.0020, 0.0020, 1.0)")); + EXPECT_EQ(steel->getAppearanceValue(QString::fromStdString("DiffuseColor")), QString::fromStdString("(0.0000, 0.0000, 0.0000, 1.0)")); + EXPECT_EQ(steel->getAppearanceValue(QString::fromStdString("EmissiveColor")), QString::fromStdString("(0.0000, 0.0000, 0.0000, 1.0)")); + EXPECT_FLOAT_EQ(steel->getAppearanceValue(QString::fromStdString("Shininess")).toDouble(), 0.06); + EXPECT_EQ(steel->getAppearanceValue(QString::fromStdString("SpecularColor")), QString::fromStdString("(0.9800, 0.9800, 0.9800, 1.0)")); + EXPECT_FLOAT_EQ(steel->getAppearanceValue(QString::fromStdString("Transparency")).toDouble(), 0.0); + + EXPECT_EQ(steel->getPhysicalQuantity(QString::fromStdString("Density")).getUserString(), parseQuantity("7900.00 kg/m^3")); + EXPECT_EQ(steel->getPhysicalQuantity(QString::fromStdString("YoungsModulus")).getUserString(), parseQuantity("210.00 GPa")); + EXPECT_EQ(steel->getPhysicalQuantity(QString::fromStdString("SpecificHeat")).getUserString(), parseQuantity("590.00 J/kg/K")); + EXPECT_EQ(steel->getPhysicalQuantity(QString::fromStdString("ThermalConductivity")).getUserString(), parseQuantity("43.00 W/m/K")); + EXPECT_EQ(steel->getPhysicalQuantity(QString::fromStdString("ThermalExpansionCoefficient")).getUserString(), parseQuantity("12.00 µm/m/K")); + +} + +// clang-format on diff --git a/tests/src/Mod/Material/App/TestModel.cpp b/tests/src/Mod/Material/App/TestModel.cpp new file mode 100644 index 0000000000..c3f6e1b127 --- /dev/null +++ b/tests/src/Mod/Material/App/TestModel.cpp @@ -0,0 +1,140 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later +/*************************************************************************** + * Copyright (c) 2023 David Carter * + * * + * This file is part of FreeCAD. * + * * + * FreeCAD is free software: you can redistribute it and/or modify it * + * under the terms of the GNU Lesser General Public License as * + * published by the Free Software Foundation, either version 2.1 of the * + * License, or (at your option) any later version. * + * * + * FreeCAD is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with FreeCAD. If not, see * + * . * + * * + **************************************************************************/ + +#include "gtest/gtest.h" + +#include +#ifndef _PreComp_ +#endif + +#include + +#include + +#include +#include +#include + +// clang-format off + +class TestModel : public ::testing::Test { + protected: + static void SetUpTestSuite() { + if (App::Application::GetARGC() == 0) { + constexpr int argc = 1; + std::array argv {"FreeCAD"}; + App::Application::Config()["ExeName"] = "FreeCAD"; + App::Application::init(argc, argv.data()); + } + } + + void SetUp() override { + _modelManager = new Materials::ModelManager(); + } + + // void TearDown() override {} + Materials::ModelManager* _modelManager; +}; + +TEST_F(TestModel, TestApplication) +{ + ASSERT_NO_THROW(App::GetApplication()); +} + +TEST_F(TestModel, TestResources) +{ + try { + auto param = App::GetApplication().GetParameterGroupByPath( + "User parameter:BaseApp/Preferences/Mod/Material/Resources"); + EXPECT_NE(param, nullptr); + } + catch (const std::exception &e) + { + FAIL() << "Exception: " << e.what() << "\n"; + } +} + +TEST_F(TestModel, TestInstallation) +{ + EXPECT_NE(_modelManager, nullptr); + + // We should have loaded at least the system library + auto libraries = _modelManager->getModelLibraries(); + ASSERT_GT(libraries->size(), 0); + + // We should have at least one model + auto models = _modelManager->getModels(); + ASSERT_GT(models->size(), 0); +} + +TEST_F(TestModel, TestModelLoad) +{ + EXPECT_NE(_modelManager, nullptr); + + auto density = _modelManager->getModel(QString::fromStdString("454661e5-265b-4320-8e6f-fcf6223ac3af")); + EXPECT_EQ(density->getName(), QString::fromStdString("Density")); + EXPECT_EQ(density->getUUID(), QString::fromStdString("454661e5-265b-4320-8e6f-fcf6223ac3af")); + + auto& prop = (*density)[QString::fromStdString("Density")]; + EXPECT_EQ(prop.getName(), QString::fromStdString("Density")); +} + +TEST_F(TestModel, TestModelByPath) +{ + auto linearElastic = _modelManager->getModelByPath( + QString::fromStdString("Mechanical/LinearElastic.yml"), + QString::fromStdString("System")); + EXPECT_NE(&linearElastic, nullptr); + EXPECT_EQ(linearElastic->getName(), QString::fromStdString("Linear Elastic")); + EXPECT_EQ(linearElastic->getUUID(), QString::fromStdString("7b561d1d-fb9b-44f6-9da9-56a4f74d7536")); + + // The same but with a leading '/' + auto linearElastic2 = _modelManager->getModelByPath( + QString::fromStdString("/Mechanical/LinearElastic.yml"), + QString::fromStdString("System")); + EXPECT_NE(&linearElastic2, nullptr); + EXPECT_EQ(linearElastic2->getName(), QString::fromStdString("Linear Elastic")); + EXPECT_EQ(linearElastic2->getUUID(), QString::fromStdString("7b561d1d-fb9b-44f6-9da9-56a4f74d7536")); + + // Same with the library name as a prefix + auto linearElastic3 = _modelManager->getModelByPath( + QString::fromStdString("/System/Mechanical/LinearElastic.yml"), + QString::fromStdString("System")); + EXPECT_NE(&linearElastic3, nullptr); + EXPECT_EQ(linearElastic3->getName(), QString::fromStdString("Linear Elastic")); + EXPECT_EQ(linearElastic3->getUUID(), QString::fromStdString("7b561d1d-fb9b-44f6-9da9-56a4f74d7536")); + + // Test with the file system path + ASSERT_NO_THROW(linearElastic->getLibrary()); + ASSERT_NO_THROW(linearElastic->getLibrary()->getName()); + ASSERT_NO_THROW(linearElastic->getLibrary()->getDirectoryPath()); + EXPECT_EQ(linearElastic->getLibrary()->getName(), QString::fromStdString("System")); + QString path = linearElastic->getLibrary()->getDirectoryPath() + QString::fromStdString("/Mechanical/LinearElastic.yml"); + + ASSERT_NO_THROW(_modelManager->getModelByPath(path)); + auto linearElastic4 = _modelManager->getModelByPath(path); + EXPECT_NE(&linearElastic4, nullptr); + EXPECT_EQ(linearElastic4->getName(), QString::fromStdString("Linear Elastic")); + EXPECT_EQ(linearElastic4->getUUID(), QString::fromStdString("7b561d1d-fb9b-44f6-9da9-56a4f74d7536")); +} + +// clang-format on diff --git a/tests/src/Mod/Material/App/TestModelProperties.cpp b/tests/src/Mod/Material/App/TestModelProperties.cpp new file mode 100644 index 0000000000..06d21c689e --- /dev/null +++ b/tests/src/Mod/Material/App/TestModelProperties.cpp @@ -0,0 +1,144 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later +/*************************************************************************** + * Copyright (c) 2023 David Carter * + * * + * This file is part of FreeCAD. * + * * + * FreeCAD is free software: you can redistribute it and/or modify it * + * under the terms of the GNU Lesser General Public License as * + * published by the Free Software Foundation, either version 2.1 of the * + * License, or (at your option) any later version. * + * * + * FreeCAD is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with FreeCAD. If not, see * + * . * + * * + **************************************************************************/ + +#include "gtest/gtest.h" + +#include +#ifndef _PreComp_ +#endif + +#include +#include + +#include +#include + +#include +#include +#include +#include + +// clang-format off + +class TestModelProperties : public ::testing::Test { + protected: + static void SetUpTestSuite() { + // if (App::Application::GetARGC() == 0) { + // constexpr int argc = 1; + // std::array argv {"FreeCAD"}; + // App::Application::Config()["ExeName"] = "FreeCAD"; + // App::Application::init(argc, argv.data()); + // } + } + +// void SetUp() override { +// _modelManager = new Materials::ModelManager(); +// _materialManager = new Materials::MaterialManager(); +// } + + // void TearDown() override {} +// Materials::ModelManager* _modelManager; +// Materials::MaterialManager* _materialManager; +}; + +TEST_F(TestModelProperties, TestEmpty) +{ + auto prop = Materials::ModelProperty(); + EXPECT_TRUE(prop.getName().isNull()); + EXPECT_TRUE(prop.getPropertyType().isNull()); + EXPECT_TRUE(prop.getUnits().isNull()); + EXPECT_TRUE(prop.getURL().isNull()); + EXPECT_TRUE(prop.getDescription().isNull()); + EXPECT_TRUE(prop.getInheritance().isNull()); + EXPECT_FALSE(prop.isInherited()); + EXPECT_EQ(prop.columns(), 0); +} + +TEST_F(TestModelProperties, TestBasic) +{ + auto prop = Materials::ModelProperty(QString::fromStdString("1"), + QString::fromStdString("2"), + QString::fromStdString("3"), + QString::fromStdString("4"), + QString::fromStdString("5")); + EXPECT_EQ(prop.getName(), QString::fromStdString("1")); + EXPECT_EQ(prop.getPropertyType(), QString::fromStdString("2")); + EXPECT_EQ(prop.getUnits(), QString::fromStdString("3")); + EXPECT_EQ(prop.getURL(), QString::fromStdString("4")); + EXPECT_EQ(prop.getDescription(), QString::fromStdString("5")); + EXPECT_TRUE(prop.getInheritance().isNull()); + EXPECT_FALSE(prop.isInherited()); + EXPECT_EQ(prop.columns(), 0); + + prop.setInheritance(QString::fromStdString("12345")); + EXPECT_EQ(prop.getInheritance(), QString::fromStdString("12345")); + EXPECT_TRUE(prop.isInherited()); +} + +TEST_F(TestModelProperties, TestAddColumns) +{ + auto prop = Materials::ModelProperty(QString::fromStdString("1"), + QString::fromStdString("2"), + QString::fromStdString("3"), + QString::fromStdString("4"), + QString::fromStdString("5")); + auto prop1 = Materials::ModelProperty(QString::fromStdString("10"), + QString::fromStdString("9"), + QString::fromStdString("8"), + QString::fromStdString("7"), + QString::fromStdString("6")); + auto prop2 = Materials::ModelProperty(QString::fromStdString("a"), + QString::fromStdString("b"), + QString::fromStdString("c"), + QString::fromStdString("d"), + QString::fromStdString("e")); + + EXPECT_EQ(prop.columns(), 0); + prop.addColumn(prop1); + EXPECT_EQ(prop.columns(), 1); + prop.addColumn(prop2); + EXPECT_EQ(prop.columns(), 2); + + auto columns = prop.getColumns(); + auto entry1 = columns.at(0); + EXPECT_EQ(entry1.getName(), QString::fromStdString("10")); + EXPECT_EQ(entry1.getPropertyType(), QString::fromStdString("9")); + EXPECT_EQ(entry1.getUnits(), QString::fromStdString("8")); + EXPECT_EQ(entry1.getURL(), QString::fromStdString("7")); + EXPECT_EQ(entry1.getDescription(), QString::fromStdString("6")); + EXPECT_TRUE(entry1.getInheritance().isNull()); + EXPECT_FALSE(entry1.isInherited()); + EXPECT_EQ(entry1.columns(), 0); + + auto entry2 = columns.at(1); + EXPECT_EQ(entry2.getName(), QString::fromStdString("a")); + EXPECT_EQ(entry2.getPropertyType(), QString::fromStdString("b")); + EXPECT_EQ(entry2.getUnits(), QString::fromStdString("c")); + EXPECT_EQ(entry2.getURL(), QString::fromStdString("d")); + EXPECT_EQ(entry2.getDescription(), QString::fromStdString("e")); + EXPECT_TRUE(entry2.getInheritance().isNull()); + EXPECT_FALSE(entry2.isInherited()); + EXPECT_EQ(entry2.columns(), 0); + +} + +// clang-format on From 42a16bd29a8ad23d12ffd03b3d73ad5de4b8119b Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 23 Oct 2023 19:25:06 +0000 Subject: [PATCH 4/6] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/Mod/Fem/Gui/AppFemGui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Mod/Fem/Gui/AppFemGui.cpp b/src/Mod/Fem/Gui/AppFemGui.cpp index a6e8b665cd..c4f36d46a2 100644 --- a/src/Mod/Fem/Gui/AppFemGui.cpp +++ b/src/Mod/Fem/Gui/AppFemGui.cpp @@ -187,4 +187,4 @@ PyMOD_INIT_FUNC(FemGui) // clang-format on PyMOD_Return(mod); -} \ No newline at end of file +} From d1e96a5195390d50b65d6e7f146533454215526b Mon Sep 17 00:00:00 2001 From: David Carter Date: Mon, 23 Oct 2023 15:19:20 -0400 Subject: [PATCH 5/6] Material: Material editor enhancements Continues the work of the material subsystem improvements. This merge covers the continued development of the material editor. The primary improvements are in the handling of 2D and 3D array properties. These properties are now fully editable, and can be saved and restored. The cards now separate the author and license. These were previously saved as a single item. Future support will be provided for standard open source licenses. Saving operations validate the cards to ensure UUIDs of materials are considered. Warnings are given when a save could potentially impact the models, such as saving over a material instead of creating a new instance. The editor is still not complete. There are a number of functional elements, such as drag/drop operations, folder creation, and deletion operations that need to be added to the main tree. State needs to be saved and restored to improve the user experience. The appearance preview also needs significant work. This will be handled in a future PR. --- src/Mod/Fem/Gui/AppFemGui.cpp | 2 +- src/Mod/Fem/Gui/CMakeLists.txt | 6 + src/Mod/Material/App/AppMaterial.cpp | 2 + src/Mod/Material/App/Array2DPy.xml | 36 + src/Mod/Material/App/Array2DPyImpl.cpp | 85 ++ src/Mod/Material/App/CMakeLists.txt | 7 + src/Mod/Material/App/Exceptions.h | 106 +++ src/Mod/Material/App/FolderTree.h | 16 +- src/Mod/Material/App/MaterialConfigLoader.cpp | 62 +- src/Mod/Material/App/MaterialConfigLoader.h | 31 +- src/Mod/Material/App/MaterialLibrary.cpp | 286 ++++++- src/Mod/Material/App/MaterialLibrary.h | 67 +- src/Mod/Material/App/MaterialLoader.cpp | 313 ++++++-- src/Mod/Material/App/MaterialLoader.h | 62 +- src/Mod/Material/App/MaterialManager.cpp | 208 +++-- src/Mod/Material/App/MaterialManager.h | 73 +- .../Material/App/MaterialManagerPyImpl.cpp | 26 +- src/Mod/Material/App/MaterialPy.xml | 14 +- src/Mod/Material/App/MaterialPyImpl.cpp | 78 +- src/Mod/Material/App/MaterialValue.cpp | 564 ++++++++++++-- src/Mod/Material/App/MaterialValue.h | 177 +++-- src/Mod/Material/App/Materials.cpp | 729 +++++++++++++++--- src/Mod/Material/App/Materials.h | 183 +++-- src/Mod/Material/App/Model.cpp | 22 +- src/Mod/Material/App/Model.h | 81 +- src/Mod/Material/App/ModelLibrary.cpp | 83 +- src/Mod/Material/App/ModelLibrary.h | 43 +- src/Mod/Material/App/ModelLoader.cpp | 78 +- src/Mod/Material/App/ModelLoader.h | 45 +- src/Mod/Material/App/ModelManager.cpp | 107 ++- src/Mod/Material/App/ModelManager.h | 43 +- src/Mod/Material/App/ModelManagerPyImpl.cpp | 27 +- src/Mod/Material/App/ModelPropertyPyImpl.cpp | 4 - src/Mod/Material/App/ModelPyImpl.cpp | 26 +- src/Mod/Material/App/ModelUuids.cpp | 70 ++ src/Mod/Material/App/ModelUuids.h | 64 +- src/Mod/Material/App/PreCompiled.h | 4 - src/Mod/Material/App/UUIDsPy.xml | 116 +++ src/Mod/Material/App/UUIDsPyImpl.cpp | 139 ++++ src/Mod/Material/App/trim.h | 1 - src/Mod/Material/CMakeLists.txt | 23 +- src/Mod/Material/Gui/AppMatGui.cpp | 3 + src/Mod/Material/Gui/Array2D.cpp | 121 ++- src/Mod/Material/Gui/Array2D.h | 28 +- src/Mod/Material/Gui/Array3D.cpp | 259 ++++++- src/Mod/Material/Gui/Array3D.h | 32 +- src/Mod/Material/Gui/ArrayDelegate.cpp | 4 +- src/Mod/Material/Gui/ArrayDelegate.h | 11 +- src/Mod/Material/Gui/ArrayModel.cpp | 150 +++- src/Mod/Material/Gui/ArrayModel.h | 33 +- src/Mod/Material/Gui/DlgSettingsMaterial.h | 2 +- src/Mod/Material/Gui/MaterialDelegate.cpp | 16 +- src/Mod/Material/Gui/MaterialDelegate.h | 8 +- src/Mod/Material/Gui/MaterialSave.cpp | 394 +++++++++- src/Mod/Material/Gui/MaterialSave.h | 39 +- src/Mod/Material/Gui/MaterialSave.ui | 24 + src/Mod/Material/Gui/MaterialsEditor.cpp | 439 +++++++++-- src/Mod/Material/Gui/MaterialsEditor.h | 44 +- src/Mod/Material/Gui/MaterialsEditor.ui | 122 +-- src/Mod/Material/Gui/ModelSelect.cpp | 79 +- src/Mod/Material/Gui/ModelSelect.h | 24 +- src/Mod/Material/Gui/PreCompiled.h | 4 - src/Mod/Material/Gui/Workbench.cpp | 40 + src/Mod/Material/Gui/Workbench.h | 5 + .../Materials/Appearance/Aluminum.FCMat | 3 +- .../Materials/Appearance/Brass.FCMat | 3 +- .../Materials/Appearance/Bronze.FCMat | 3 +- .../Materials/Appearance/Chrome.FCMat | 3 +- .../Materials/Appearance/Copper.FCMat | 3 +- .../Appearance/DefaultAppearance.FCMat | 3 +- .../Materials/Appearance/Emerald.FCMat | 3 +- .../Resources/Materials/Appearance/Gold.FCMat | 3 +- .../Resources/Materials/Appearance/Jade.FCMat | 3 +- .../Materials/Appearance/Metalized.FCMat | 3 +- .../Materials/Appearance/NeonGNC.FCMat | 3 +- .../Materials/Appearance/NeonPHC.FCMat | 3 +- .../Materials/Appearance/Obsidian.FCMat | 3 +- .../Materials/Appearance/Pewter.FCMat | 3 +- .../Materials/Appearance/Plaster.FCMat | 3 +- .../Materials/Appearance/Plastic.FCMat | 3 +- .../Resources/Materials/Appearance/Ruby.FCMat | 3 +- .../Materials/Appearance/Satin.FCMat | 3 +- .../Materials/Appearance/ShinyPlastic.FCMat | 3 +- .../Materials/Appearance/Silver.FCMat | 3 +- .../Materials/Appearance/Steel.FCMat | 3 +- .../Materials/Appearance/Stone.FCMat | 3 +- .../Materials/FluidMaterial/Air.FCMat | 1 + .../Materials/FluidMaterial/Argon.FCMat | 1 + .../FluidMaterial/Carbon_dioxide.FCMat | 1 + .../Materials/FluidMaterial/Nitrogen.FCMat | 1 + .../Materials/FluidMaterial/None.FCMat | 1 + .../Materials/FluidMaterial/Water.FCMat | 1 + .../Aggregate/Concrete-EN-C35_45.FCMat | 3 +- .../Aggregate/Concrete-Generic.FCMat | 3 +- .../Aggregate/Reinforcement-FIB-B500.FCMat | 3 +- .../StandardMaterial/Carbon/Graphite.FCMat | 3 +- .../Glass/Glass-E-GlassFibre.FCMat | 3 +- .../Glass/Glass-Generic.FCMat | 3 +- .../Glass/Glass-S2-GlassFibre.FCMat | 3 +- .../Metal/Alloys/Invar-Generic.FCMat | 2 +- .../Metal/Aluminum/AlMg3F24.FCMat | 3 +- .../Metal/Aluminum/AlMgSi1F31.FCMat | 3 +- .../Metal/Aluminum/AlZn4-5Mg1F35.FCMat | 2 +- .../Metal/Aluminum/Aluminum-6061-T6.FCMat | 3 +- .../Metal/Aluminum/Aluminum-Generic.FCMat | 2 +- .../Metal/Copper/Copper-Generic.FCMat | 2 +- .../Metal/Iron/Iron-Generic.FCMat | 2 +- .../Metal/Steel/CalculiX-Steel.FCMat | 3 +- .../Metal/Steel/Steel-15CrNi6.FCMat | 3 +- .../Metal/Steel/Steel-17CrNiMo6.FCMat | 3 +- .../Metal/Steel/Steel-1C22.FCMat | 3 +- .../Metal/Steel/Steel-1C35.FCMat | 3 +- .../Metal/Steel/Steel-1C45.FCMat | 3 +- .../Metal/Steel/Steel-1C60.FCMat | 3 +- .../Metal/Steel/Steel-20NiCrMo2.FCMat | 3 +- .../Metal/Steel/Steel-28Mn6.FCMat | 3 +- .../Metal/Steel/Steel-2C10.FCMat | 3 +- .../Metal/Steel/Steel-30CrNiMo8.FCMat | 3 +- .../Metal/Steel/Steel-34CrNiMo6.FCMat | 3 +- .../Metal/Steel/Steel-36CrNiMo4.FCMat | 3 +- .../Metal/Steel/Steel-36NiCrMo16.FCMat | 3 +- .../Metal/Steel/Steel-3C15.FCMat | 3 +- .../Metal/Steel/Steel-3C22.FCMat | 3 +- .../Metal/Steel/Steel-3C35.FCMat | 3 +- .../Metal/Steel/Steel-3V45.FCMat | 3 +- .../Metal/Steel/Steel-C10.FCMat | 3 +- .../Metal/Steel/Steel-C15.FCMat | 3 +- .../Metal/Steel/Steel-C22E.FCMat | 3 +- .../Metal/Steel/Steel-C25E.FCMat | 3 +- .../Metal/Steel/Steel-C30E.FCMat | 3 +- .../Metal/Steel/Steel-C40E.FCMat | 3 +- .../Metal/Steel/Steel-C50E.FCMat | 3 +- .../Metal/Steel/Steel-C55E.FCMat | 3 +- .../Metal/Steel/Steel-C60E.FCMat | 3 +- .../Metal/Steel/Steel-E295-GC.FCMat | 3 +- .../Metal/Steel/Steel-E295.FCMat | 3 +- .../Metal/Steel/Steel-E335-GC.FCMat | 3 +- .../Metal/Steel/Steel-E335.FCMat | 3 +- .../Metal/Steel/Steel-E360-GC.FCMat | 3 +- .../Metal/Steel/Steel-E360.FCMat | 3 +- .../Metal/Steel/Steel-EN-GJL-100.FCMat | 3 +- .../Metal/Steel/Steel-EN-GJL-150.FCMat | 3 +- .../Metal/Steel/Steel-EN-GJL-200.FCMat | 3 +- .../Metal/Steel/Steel-EN-GJL-250.FCMat | 3 +- .../Metal/Steel/Steel-EN-GJL-300.FCMat | 3 +- .../Metal/Steel/Steel-EN-GJL-350.FCMat | 3 +- .../Metal/Steel/Steel-EN-GJMB-350-10.FCMat | 3 +- .../Metal/Steel/Steel-EN-GJMB-550-4.FCMat | 3 +- .../Metal/Steel/Steel-EN-GJMB-650-2.FCMat | 3 +- .../Metal/Steel/Steel-EN-GJMW-350-4.FCMat | 3 +- .../Metal/Steel/Steel-EN-GJMW-360-12.FCMat | 3 +- .../Metal/Steel/Steel-EN-GJMW-400-5.FCMat | 3 +- .../Metal/Steel/Steel-EN-GJMW-450-7.FCMat | 3 +- .../Metal/Steel/Steel-EN-GJS-400-15.FCMat | 3 +- .../Metal/Steel/Steel-EN-GJS-500-7.FCMat | 3 +- .../Metal/Steel/Steel-EN-GJS-600-3.FCMat | 3 +- .../Metal/Steel/Steel-EN-GJS-700-2.FCMat | 3 +- .../Metal/Steel/Steel-EN-GJS-800-1.FCMat | 3 +- .../Metal/Steel/Steel-G16Mn5.FCMat | 3 +- .../Metal/Steel/Steel-G200.FCMat | 3 +- .../Metal/Steel/Steel-G20Mn5.FCMat | 3 +- .../Metal/Steel/Steel-G230.FCMat | 3 +- .../Metal/Steel/Steel-G260.FCMat | 3 +- .../Metal/Steel/Steel-G300.FCMat | 3 +- .../Metal/Steel/Steel-G30Mn5.FCMat | 3 +- .../Metal/Steel/Steel-Generic.FCMat | 3 +- .../Metal/Steel/Steel-S185.FCMat | 3 +- .../Metal/Steel/Steel-S235JO.FCMat | 3 +- .../Metal/Steel/Steel-S235JR.FCMat | 3 +- .../Metal/Steel/Steel-S235JRG1.FCMat | 3 +- .../Metal/Steel/Steel-S260NC.FCMat | 3 +- .../Metal/Steel/Steel-S275JO.FCMat | 3 +- .../Metal/Steel/Steel-S275JR.FCMat | 3 +- .../Metal/Steel/Steel-S275N.FCMat | 3 +- .../Metal/Steel/Steel-S335JO.FCMat | 3 +- .../Metal/Steel/Steel-S335JR.FCMat | 3 +- .../Metal/Steel/Steel-S335N.FCMat | 3 +- .../Metal/Steel/Steel-S340MC.FCMat | 3 +- .../Metal/Steel/Steel-S355J2G3.FCMat | 3 +- .../Metal/Steel/Steel-S380MC.FCMat | 3 +- .../Metal/Steel/Steel-S420MC.FCMat | 3 +- .../Metal/Steel/Steel-S420N.FCMat | 3 +- .../Metal/Steel/Steel-S460MC.FCMat | 3 +- .../Metal/Steel/Steel-S460N.FCMat | 3 +- .../Metal/Steel/Steel-S500MC.FCMat | 3 +- .../Metal/Steel/Steel-S550MC.FCMat | 3 +- .../Metal/Steel/Steel-S690MC.FCMat | 3 +- .../Metal/Steel/Steel-St-37-2K.FCMat | 3 +- .../Metal/Steel/Steel-St-E-255.FCMat | 3 +- .../Metal/Steel/Steel-St-E-315.FCMat | 3 +- .../Metal/Steel/Steel-St-E-380.FCMat | 3 +- .../Metal/Steel/Steel-St-E-460.FCMat | 3 +- .../Metal/Steel/Steel-St-E-500.FCMat | 3 +- .../Metal/Steel/Steel-X2CrNiMoN17-13-3.FCMat | 3 +- .../Metal/Steel/Steel-X2CrNiN24-4.FCMat | 3 +- .../Metal/Steel/Steel-X39CrMo17-1.FCMat | 3 +- .../Metal/Steel/Steel-X3CrNiMo13-14.FCMat | 3 +- .../Metal/Steel/Steel-X5CrNi18-10.FCMat | 3 +- .../Metal/Steel/Steel-X5CrNiMo17-12-2.FCMat | 3 +- .../Metal/Steel/Steel-X6CrNiTi18-10.FCMat | 3 +- .../Metal/Titanium/Ti-6Al-4V.FCMat | 2 +- .../Thermoplast/ABS-Generic.FCMat | 3 +- .../Thermoplast/Acrylic-Glass-Generic.FCMat | 3 +- .../Thermoplast/PA6-Generic.FCMat | 3 +- .../Thermoplast/PET-Generic.FCMat | 3 +- .../Thermoplast/PLA-Generic.FCMat | 3 +- .../Thermoplast/PP-Generic.FCMat | 3 +- .../Thermoplast/PTFE-Generic.FCMat | 3 +- .../Thermoplast/PVC-Generic.FCMat | 3 +- .../StandardMaterial/Wood/Wood-Generic.FCMat | 3 +- src/Mod/Material/TestMaterialsApp.py | 219 +----- .../Material/materialtests/TestMaterials.py | 228 ++++++ src/Mod/Material/materialtests/TestModels.py | 79 ++ src/Mod/Material/materialtests/__init__.py | 0 src/Tools/updatecrowdin.py | 6 +- tests/src/Mod/Material/App/CMakeLists.txt | 6 +- .../Material/App/TestMaterialProperties.cpp | 226 ++++++ .../Mod/Material/App/TestMaterialValue.cpp | 310 ++++++++ tests/src/Mod/Material/App/TestMaterials.cpp | 339 ++++++++ tests/src/Mod/Material/App/TestModel.cpp | 140 ++++ .../Mod/Material/App/TestModelProperties.cpp | 144 ++++ 221 files changed, 6493 insertions(+), 1614 deletions(-) create mode 100644 src/Mod/Material/App/Array2DPy.xml create mode 100644 src/Mod/Material/App/Array2DPyImpl.cpp create mode 100644 src/Mod/Material/App/ModelUuids.cpp create mode 100644 src/Mod/Material/App/UUIDsPy.xml create mode 100644 src/Mod/Material/App/UUIDsPyImpl.cpp create mode 100644 src/Mod/Material/materialtests/TestMaterials.py create mode 100644 src/Mod/Material/materialtests/TestModels.py create mode 100644 src/Mod/Material/materialtests/__init__.py create mode 100644 tests/src/Mod/Material/App/TestMaterialProperties.cpp create mode 100644 tests/src/Mod/Material/App/TestMaterialValue.cpp create mode 100644 tests/src/Mod/Material/App/TestMaterials.cpp create mode 100644 tests/src/Mod/Material/App/TestModel.cpp create mode 100644 tests/src/Mod/Material/App/TestModelProperties.cpp diff --git a/src/Mod/Fem/Gui/AppFemGui.cpp b/src/Mod/Fem/Gui/AppFemGui.cpp index c4f36d46a2..a6e8b665cd 100644 --- a/src/Mod/Fem/Gui/AppFemGui.cpp +++ b/src/Mod/Fem/Gui/AppFemGui.cpp @@ -187,4 +187,4 @@ PyMOD_INIT_FUNC(FemGui) // clang-format on PyMOD_Return(mod); -} +} \ No newline at end of file diff --git a/src/Mod/Fem/Gui/CMakeLists.txt b/src/Mod/Fem/Gui/CMakeLists.txt index 5635bef1fc..af0fb7fcd6 100755 --- a/src/Mod/Fem/Gui/CMakeLists.txt +++ b/src/Mod/Fem/Gui/CMakeLists.txt @@ -9,6 +9,12 @@ elseif(CMAKE_COMPILER_IS_GNUCXX) add_compile_options(-Wno-pedantic) # needed for vtk headers endif() +if(MSVC) + add_definitions(-DFCGuiFem -DHAVE_ACOSH -DHAVE_ASINH -DHAVE_ATANH) +else(MSVC) + add_definitions(-DHAVE_LIMITS_H -DHAVE_CONFIG_H) +endif(MSVC) + if(BUILD_FEM_NETGEN) add_definitions(-DFCWithNetgen) endif(BUILD_FEM_NETGEN) diff --git a/src/Mod/Material/App/AppMaterial.cpp b/src/Mod/Material/App/AppMaterial.cpp index ced297ec95..9d2471c657 100644 --- a/src/Mod/Material/App/AppMaterial.cpp +++ b/src/Mod/Material/App/AppMaterial.cpp @@ -33,6 +33,7 @@ #include "ModelManagerPy.h" #include "ModelPropertyPy.h" #include "ModelPy.h" +#include "UUIDsPy.h" namespace Materials { @@ -68,6 +69,7 @@ PyMOD_INIT_FUNC(Material) Base::Interpreter().addType(&Materials::ModelManagerPy ::Type, module, "ModelManager"); Base::Interpreter().addType(&Materials::ModelPropertyPy ::Type, module, "ModelProperty"); Base::Interpreter().addType(&Materials::ModelPy ::Type, module, "Model"); + Base::Interpreter().addType(&Materials::UUIDsPy ::Type, module, "UUIDs"); PyMOD_Return(module); } diff --git a/src/Mod/Material/App/Array2DPy.xml b/src/Mod/Material/App/Array2DPy.xml new file mode 100644 index 0000000000..ba6f5f965f --- /dev/null +++ b/src/Mod/Material/App/Array2DPy.xml @@ -0,0 +1,36 @@ + + + + + + 2D Array of material properties. + + + + The number of rows in the array. + + + + + + The number of columns in the array. + + + + + + Get the default value for the first column of the array + + + + diff --git a/src/Mod/Material/App/Array2DPyImpl.cpp b/src/Mod/Material/App/Array2DPyImpl.cpp new file mode 100644 index 0000000000..02ef6e5465 --- /dev/null +++ b/src/Mod/Material/App/Array2DPyImpl.cpp @@ -0,0 +1,85 @@ +/*************************************************************************** + * Copyright (c) 2023 David Carter * + * * + * This file is part of FreeCAD. * + * * + * FreeCAD is free software: you can redistribute it and/or modify it * + * under the terms of the GNU Lesser General Public License as * + * published by the Free Software Foundation, either version 2.1 of the * + * License, or (at your option) any later version. * + * * + * FreeCAD is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with FreeCAD. If not, see * + * . * + * * + **************************************************************************/ + +#include "PreCompiled.h" + +#include "Array2DPy.h" +#include "Model.h" +#include "ModelLibrary.h" +#include "ModelPropertyPy.h" +#include "ModelUuids.h" + +#include "Array2DPy.cpp" + +using namespace Materials; + +// returns a string which represents the object e.g. when printed in python +std::string Array2DPy::representation() const +{ + std::stringstream str; + str << ""; + + return str.str(); +} + +PyObject* Array2DPy::PyMake(struct _typeobject*, PyObject*, PyObject*) // Python wrapper +{ + // never create such objects with the constructor + return new Array2DPy(new Material2DArray()); +} + +// constructor method +int Array2DPy::PyInit(PyObject* /*args*/, PyObject* /*kwd*/) +{ + return 0; +} + +Py::Int Array2DPy::getRows() const +{ + return Py::Int(getMaterial2DArrayPtr()->rows()); +} + +Py::Int Array2DPy::getColumns() const +{ + return Py::Int(getMaterial2DArrayPtr()->columns()); +} + +PyObject* Array2DPy::getDefaultValue(PyObject* args) +{ + char* name; + if (!PyArg_ParseTuple(args, "s", &name)) { + return nullptr; + } + + // QVariant value = getMaterial2DArrayPtr()->getPhysicalValue(QString::fromStdString(name)); + // return _pyObjectFromVariant(value); + return nullptr; +} + +PyObject* Array2DPy::getCustomAttributes(const char* /*attr*/) const +{ + return nullptr; +} + +int Array2DPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/) +{ + return 0; +} diff --git a/src/Mod/Material/App/CMakeLists.txt b/src/Mod/Material/App/CMakeLists.txt index 21258ea53a..ab2bc85745 100644 --- a/src/Mod/Material/App/CMakeLists.txt +++ b/src/Mod/Material/App/CMakeLists.txt @@ -33,14 +33,18 @@ list(APPEND Material_LIBS ${YAML_CPP_LIBRARIES} ) +generate_from_xml(Array2DPy) generate_from_xml(MaterialManagerPy) generate_from_xml(MaterialPy) generate_from_xml(ModelManagerPy) generate_from_xml(ModelPropertyPy) generate_from_xml(ModelPy) +generate_from_xml(UUIDsPy) SET(Python_SRCS Exceptions.h + Array2DPy.xml + Array2DPyImpl.cpp MaterialManagerPy.xml MaterialManagerPyImpl.cpp MaterialPy.xml @@ -51,6 +55,8 @@ SET(Python_SRCS ModelPropertyPyImpl.cpp ModelPy.xml ModelPyImpl.cpp + UUIDsPy.xml + UUIDsPyImpl.cpp ) SOURCE_GROUP("Python" FILES ${Python_SRCS}) @@ -78,6 +84,7 @@ SET(Material_SRCS ModelLoader.h ModelManager.cpp ModelManager.h + ModelUuids.cpp ModelUuids.h PreCompiled.cpp PreCompiled.h diff --git a/src/Mod/Material/App/Exceptions.h b/src/Mod/Material/App/Exceptions.h index c67e9df4eb..49152cd263 100644 --- a/src/Mod/Material/App/Exceptions.h +++ b/src/Mod/Material/App/Exceptions.h @@ -22,6 +22,8 @@ #ifndef MATERIAL_EXCEPTIONS_H #define MATERIAL_EXCEPTIONS_H +#include + #include #include @@ -37,6 +39,10 @@ public: { this->setMessage(msg); } + explicit Uninitialized(const QString& msg) + { + this->setMessage(msg.toStdString().c_str()); + } ~Uninitialized() noexcept override = default; }; @@ -49,9 +55,29 @@ public: { this->setMessage(msg); } + explicit ModelNotFound(const QString& msg) + { + this->setMessage(msg.toStdString().c_str()); + } ~ModelNotFound() noexcept override = default; }; +class InvalidMaterialType: public Base::Exception +{ +public: + InvalidMaterialType() + {} + explicit InvalidMaterialType(const char* msg) + { + this->setMessage(msg); + } + explicit InvalidMaterialType(const QString& msg) + { + this->setMessage(msg.toStdString().c_str()); + } + ~InvalidMaterialType() noexcept override = default; +}; + class MaterialNotFound: public Base::Exception { public: @@ -61,9 +87,29 @@ public: { this->setMessage(msg); } + explicit MaterialNotFound(const QString& msg) + { + this->setMessage(msg.toStdString().c_str()); + } ~MaterialNotFound() noexcept override = default; }; +class MaterialExists: public Base::Exception +{ +public: + MaterialExists() + {} + explicit MaterialExists(const char* msg) + { + this->setMessage(msg); + } + explicit MaterialExists(const QString& msg) + { + this->setMessage(msg.toStdString().c_str()); + } + ~MaterialExists() noexcept override = default; +}; + class PropertyNotFound: public Base::Exception { public: @@ -73,6 +119,10 @@ public: { this->setMessage(msg); } + explicit PropertyNotFound(const QString& msg) + { + this->setMessage(msg.toStdString().c_str()); + } ~PropertyNotFound() noexcept override = default; }; @@ -85,6 +135,10 @@ public: { this->setMessage(msg); } + explicit LibraryNotFound(const QString& msg) + { + this->setMessage(msg.toStdString().c_str()); + } ~LibraryNotFound() noexcept override = default; }; @@ -97,6 +151,10 @@ public: { this->setMessage(msg); } + explicit InvalidModel(const QString& msg) + { + this->setMessage(msg.toStdString().c_str()); + } ~InvalidModel() noexcept override = default; }; @@ -109,6 +167,10 @@ public: { this->setMessage(msg); } + explicit InvalidRow(const QString& msg) + { + this->setMessage(msg.toStdString().c_str()); + } ~InvalidRow() noexcept override = default; }; @@ -121,9 +183,29 @@ public: { this->setMessage(msg); } + explicit InvalidColumn(const QString& msg) + { + this->setMessage(msg.toStdString().c_str()); + } ~InvalidColumn() noexcept override = default; }; +class InvalidDepth: public Base::Exception +{ +public: + InvalidDepth() + {} + explicit InvalidDepth(char* msg) + { + this->setMessage(msg); + } + explicit InvalidDepth(const QString& msg) + { + this->setMessage(msg.toStdString().c_str()); + } + ~InvalidDepth() noexcept override = default; +}; + class InvalidIndex: public Base::Exception { public: @@ -133,6 +215,10 @@ public: { this->setMessage(msg); } + explicit InvalidIndex(const QString& msg) + { + this->setMessage(msg.toStdString().c_str()); + } ~InvalidIndex() noexcept override = default; }; @@ -145,9 +231,29 @@ public: { this->setMessage(msg); } + explicit UnknownValueType(const QString& msg) + { + this->setMessage(msg.toStdString().c_str()); + } ~UnknownValueType() noexcept override = default; }; +class DeleteError: public Base::Exception +{ +public: + DeleteError() + {} + explicit DeleteError(char* msg) + { + this->setMessage(msg); + } + explicit DeleteError(const QString& msg) + { + this->setMessage(msg.toStdString().c_str()); + } + ~DeleteError() noexcept override = default; +}; + } // namespace Materials #endif // MATERIAL_EXCEPTIONS_H diff --git a/src/Mod/Material/App/FolderTree.h b/src/Mod/Material/App/FolderTree.h index 2cc3133fa6..e2c450753c 100644 --- a/src/Mod/Material/App/FolderTree.h +++ b/src/Mod/Material/App/FolderTree.h @@ -22,10 +22,10 @@ #ifndef MATERIAL_FOLDERTREE_H #define MATERIAL_FOLDERTREE_H -#include #include #include +#include namespace Materials { @@ -53,25 +53,25 @@ public: _type = type; } - const std::shared_ptr*>> getFolder() const + const std::shared_ptr>>> getFolder() const { return _folder; } - std::shared_ptr*>> getFolder() + std::shared_ptr>>> getFolder() { return _folder; } - const T* getData() const + std::shared_ptr getData() const { return _data; } - void setFolder(std::shared_ptr*>> folder) + void setFolder(std::shared_ptr>>> folder) { setType(FolderNode); _folder = folder; } - void setData(const T* data) + void setData(std::shared_ptr data) { setType(DataNode); _data = data; @@ -79,8 +79,8 @@ public: private: NodeType _type; - std::shared_ptr*>> _folder; - const T* _data; + std::shared_ptr>>> _folder; + std::shared_ptr _data; }; } // namespace Materials diff --git a/src/Mod/Material/App/MaterialConfigLoader.cpp b/src/Mod/Material/App/MaterialConfigLoader.cpp index 6e5e287600..492730f2ec 100644 --- a/src/Mod/Material/App/MaterialConfigLoader.cpp +++ b/src/Mod/Material/App/MaterialConfigLoader.cpp @@ -85,7 +85,8 @@ QString MaterialConfigLoader::getAuthorAndLicense(const QString& path) return noAuthor; } -void MaterialConfigLoader::addVectorRendering(const QSettings& fcmat, Material* finalModel) +void MaterialConfigLoader::addVectorRendering(const QSettings& fcmat, + std::shared_ptr finalModel) { QString sectionFillPattern = value(fcmat, "VectorRendering/SectionFillPattern", ""); QString sectionLinewidth = value(fcmat, "VectorRendering/SectionLinewidth", ""); @@ -97,7 +98,7 @@ void MaterialConfigLoader::addVectorRendering(const QSettings& fcmat, Material* if (sectionFillPattern.length() + sectionLinewidth.length() + sectionColor.length() + viewColor.length() + viewFillPattern.length() + viewLinewidth.length() > 0) { - finalModel->addAppearance(ModelUUID_Rendering_Vector); + finalModel->addAppearance(ModelUUIDs::ModelUUID_Rendering_Vector); } // Now add the data @@ -109,7 +110,8 @@ void MaterialConfigLoader::addVectorRendering(const QSettings& fcmat, Material* setAppearanceValue(finalModel, "ViewLinewidth", viewLinewidth); } -void MaterialConfigLoader::addRendering(const QSettings& fcmat, Material* finalModel) +void MaterialConfigLoader::addRendering(const QSettings& fcmat, + std::shared_ptr finalModel) { QString ambientColor = value(fcmat, "Rendering/AmbientColor", ""); QString diffuseColor = value(fcmat, "Rendering/DiffuseColor", ""); @@ -139,13 +141,13 @@ void MaterialConfigLoader::addRendering(const QSettings& fcmat, Material* finalM } if (useAdvanced) { - finalModel->addAppearance(ModelUUID_Rendering_Advanced); + finalModel->addAppearance(ModelUUIDs::ModelUUID_Rendering_Advanced); } else if (useTexture) { - finalModel->addAppearance(ModelUUID_Rendering_Texture); + finalModel->addAppearance(ModelUUIDs::ModelUUID_Rendering_Texture); } else if (useBasic) { - finalModel->addAppearance(ModelUUID_Rendering_Basic); + finalModel->addAppearance(ModelUUIDs::ModelUUID_Rendering_Basic); } // Now add the data @@ -161,14 +163,14 @@ void MaterialConfigLoader::addRendering(const QSettings& fcmat, Material* finalM setAppearanceValue(finalModel, "VertexShader", vertexShader); } -void MaterialConfigLoader::addCosts(const QSettings& fcmat, Material* finalModel) +void MaterialConfigLoader::addCosts(const QSettings& fcmat, std::shared_ptr finalModel) { QString productURL = value(fcmat, "Cost/ProductURL", ""); QString specificPrice = value(fcmat, "Cost/SpecificPrice", ""); QString vendor = value(fcmat, "Cost/Vendor", ""); if (productURL.length() + specificPrice.length() + vendor.length() > 0) { - finalModel->addPhysical(ModelUUID_Costs_Default); + finalModel->addPhysical(ModelUUIDs::ModelUUID_Costs_Default); } // Now add the data @@ -177,7 +179,8 @@ void MaterialConfigLoader::addCosts(const QSettings& fcmat, Material* finalModel setPhysicalValue(finalModel, "Vendor", vendor); } -void MaterialConfigLoader::addArchitectural(const QSettings& fcmat, Material* finalModel) +void MaterialConfigLoader::addArchitectural(const QSettings& fcmat, + std::shared_ptr finalModel) { QString color = value(fcmat, "Architectural/Color", ""); QString environmentalEfficiencyClass = @@ -193,7 +196,7 @@ void MaterialConfigLoader::addArchitectural(const QSettings& fcmat, Material* fi + finish.length() + fireResistanceClass.length() + model.length() + soundTransmissionClass.length() + unitsPerQuantity.length() > 0) { - finalModel->addPhysical(ModelUUID_Architectural_Default); + finalModel->addPhysical(ModelUUIDs::ModelUUID_Architectural_Default); } // Now add the data @@ -207,7 +210,8 @@ void MaterialConfigLoader::addArchitectural(const QSettings& fcmat, Material* fi setPhysicalValue(finalModel, "UnitsPerQuantity", unitsPerQuantity); } -void MaterialConfigLoader::addElectromagnetic(const QSettings& fcmat, Material* finalModel) +void MaterialConfigLoader::addElectromagnetic(const QSettings& fcmat, + std::shared_ptr finalModel) { QString relativePermittivity = value(fcmat, "Electromagnetic/RelativePermittivity", ""); QString electricalConductivity = value(fcmat, "Electromagnetic/ElectricalConductivity", ""); @@ -216,7 +220,7 @@ void MaterialConfigLoader::addElectromagnetic(const QSettings& fcmat, Material* if (relativePermittivity.length() + electricalConductivity.length() + relativePermeability.length() > 0) { - finalModel->addPhysical(ModelUUID_Electromagnetic_Default); + finalModel->addPhysical(ModelUUIDs::ModelUUID_Electromagnetic_Default); } // Now add the data @@ -225,7 +229,7 @@ void MaterialConfigLoader::addElectromagnetic(const QSettings& fcmat, Material* setPhysicalValue(finalModel, "RelativePermeability", relativePermeability); } -void MaterialConfigLoader::addThermal(const QSettings& fcmat, Material* finalModel) +void MaterialConfigLoader::addThermal(const QSettings& fcmat, std::shared_ptr finalModel) { QString specificHeat = value(fcmat, "Thermal/SpecificHeat", ""); QString thermalConductivity = value(fcmat, "Thermal/ThermalConductivity", ""); @@ -233,7 +237,7 @@ void MaterialConfigLoader::addThermal(const QSettings& fcmat, Material* finalMod if (specificHeat.length() + thermalConductivity.length() + thermalExpansionCoefficient.length() > 0) { - finalModel->addPhysical(ModelUUID_Thermal_Default); + finalModel->addPhysical(ModelUUIDs::ModelUUID_Thermal_Default); } // Now add the data @@ -242,7 +246,7 @@ void MaterialConfigLoader::addThermal(const QSettings& fcmat, Material* finalMod setPhysicalValue(finalModel, "ThermalExpansionCoefficient", thermalExpansionCoefficient); } -void MaterialConfigLoader::addFluid(const QSettings& fcmat, Material* finalModel) +void MaterialConfigLoader::addFluid(const QSettings& fcmat, std::shared_ptr finalModel) { QString density = value(fcmat, "Fluidic/Density", ""); QString dynamicViscosity = value(fcmat, "Fluidic/DynamicViscosity", ""); @@ -260,10 +264,10 @@ void MaterialConfigLoader::addFluid(const QSettings& fcmat, Material* finalModel } if (useFluid) { - finalModel->addPhysical(ModelUUID_Fluid_Default); + finalModel->addPhysical(ModelUUIDs::ModelUUID_Fluid_Default); } else if (useDensity) { - finalModel->addPhysical(ModelUUID_Mechanical_Density); + finalModel->addPhysical(ModelUUIDs::ModelUUID_Mechanical_Density); } // Now add the data @@ -273,7 +277,8 @@ void MaterialConfigLoader::addFluid(const QSettings& fcmat, Material* finalModel setPhysicalValue(finalModel, "PrandtlNumber", prandtlNumber); } -void MaterialConfigLoader::addMechanical(const QSettings& fcmat, Material* finalModel) +void MaterialConfigLoader::addMechanical(const QSettings& fcmat, + std::shared_ptr finalModel) { QString density = value(fcmat, "Mechanical/Density", ""); QString bulkModulus = value(fcmat, "Mechanical/BulkModulus", ""); @@ -308,14 +313,14 @@ void MaterialConfigLoader::addMechanical(const QSettings& fcmat, Material* final } if (useLinearElastic) { - finalModel->addPhysical(ModelUUID_Mechanical_LinearElastic); + finalModel->addPhysical(ModelUUIDs::ModelUUID_Mechanical_LinearElastic); } else { if (useIso) { - finalModel->addPhysical(ModelUUID_Mechanical_IsotropicLinearElastic); + finalModel->addPhysical(ModelUUIDs::ModelUUID_Mechanical_IsotropicLinearElastic); } if (useDensity) { - finalModel->addPhysical(ModelUUID_Mechanical_Density); + finalModel->addPhysical(ModelUUIDs::ModelUUID_Mechanical_Density); } } @@ -334,10 +339,11 @@ void MaterialConfigLoader::addMechanical(const QSettings& fcmat, Material* final setPhysicalValue(finalModel, "Stiffness", stiffness); } -Material* MaterialConfigLoader::getMaterialFromPath(const MaterialLibrary& library, - const QString& path) +std::shared_ptr +MaterialConfigLoader::getMaterialFromPath(std::shared_ptr library, + const QString& path) { - QString authorAndLicense = getAuthorAndLicense(path); + QString author = getAuthorAndLicense(path); // Place them both in the author field QSettings fcmat(path, QSettings::IniFormat); @@ -352,15 +358,15 @@ Material* MaterialConfigLoader::getMaterialFromPath(const MaterialLibrary& libra QString sourceReference = value(fcmat, "ReferenceSource", ""); QString sourceURL = value(fcmat, "SourceURL", ""); - Material* finalModel = new Material(library, path, uuid, name); - finalModel->setAuthorAndLicense(authorAndLicense); + std::shared_ptr finalModel = std::make_shared(library, path, uuid, name); + finalModel->setAuthor(author); finalModel->setDescription(description); finalModel->setReference(sourceReference); finalModel->setURL(sourceURL); QString father = value(fcmat, "Father", ""); if (father.length() > 0) { - finalModel->addPhysical(ModelUUID_Legacy_Father); + finalModel->addPhysical(ModelUUIDs::ModelUUID_Legacy_Father); // Now add the data setPhysicalValue(finalModel, "Father", father); @@ -372,7 +378,7 @@ Material* MaterialConfigLoader::getMaterialFromPath(const MaterialLibrary& libra QString standardCode = value(fcmat, "StandardCode", ""); if (kindOfMaterial.length() + materialNumber.length() + norm.length() + standardCode.length() > 0) { - finalModel->addPhysical(ModelUUID_Legacy_MaterialStandard); + finalModel->addPhysical(ModelUUIDs::ModelUUID_Legacy_MaterialStandard); // Now add the data setPhysicalValue(finalModel, "KindOfMaterial", kindOfMaterial); diff --git a/src/Mod/Material/App/MaterialConfigLoader.h b/src/Mod/Material/App/MaterialConfigLoader.h index f2337cd04f..5d847d944c 100644 --- a/src/Mod/Material/App/MaterialConfigLoader.h +++ b/src/Mod/Material/App/MaterialConfigLoader.h @@ -22,6 +22,8 @@ #ifndef MATERIAL_MATERIALCONFIGLOADER_H #define MATERIAL_MATERIALCONFIGLOADER_H +#include + #include #include #include @@ -39,7 +41,8 @@ public: static bool isConfigStyle(const QString& path); - static Material* getMaterialFromPath(const MaterialLibrary& library, const QString& path); + static std::shared_ptr getMaterialFromPath(std::shared_ptr library, + const QString& path); private: static QString @@ -49,15 +52,17 @@ private: .toString(); } - static void - setPhysicalValue(Material* finalModel, const std::string& name, const QString& value) + static void setPhysicalValue(std::shared_ptr finalModel, + const std::string& name, + const QString& value) { if (value.length() > 0) { finalModel->setPhysicalValue(QString::fromStdString(name), value); } } - static void - setAppearanceValue(Material* finalModel, const std::string& name, const QString& value) + static void setAppearanceValue(std::shared_ptr finalModel, + const std::string& name, + const QString& value) { if (value.length() > 0) { finalModel->setAppearanceValue(QString::fromStdString(name), value); @@ -65,14 +70,14 @@ private: } static QString getAuthorAndLicense(const QString& path); - static void addMechanical(const QSettings& fcmat, Material* finalModel); - static void addFluid(const QSettings& fcmat, Material* finalModel); - static void addThermal(const QSettings& fcmat, Material* finalModel); - static void addElectromagnetic(const QSettings& fcmat, Material* finalModel); - static void addArchitectural(const QSettings& fcmat, Material* finalModel); - static void addCosts(const QSettings& fcmat, Material* finalModel); - static void addRendering(const QSettings& fcmat, Material* finalModel); - static void addVectorRendering(const QSettings& fcmat, Material* finalModel); + static void addMechanical(const QSettings& fcmat, std::shared_ptr finalModel); + static void addFluid(const QSettings& fcmat, std::shared_ptr finalModel); + static void addThermal(const QSettings& fcmat, std::shared_ptr finalModel); + static void addElectromagnetic(const QSettings& fcmat, std::shared_ptr finalModel); + static void addArchitectural(const QSettings& fcmat, std::shared_ptr finalModel); + static void addCosts(const QSettings& fcmat, std::shared_ptr finalModel); + static void addRendering(const QSettings& fcmat, std::shared_ptr finalModel); + static void addVectorRendering(const QSettings& fcmat, std::shared_ptr finalModel); }; } // namespace Materials diff --git a/src/Mod/Material/App/MaterialLibrary.cpp b/src/Mod/Material/App/MaterialLibrary.cpp index 3d5ee05a59..944ae9408d 100644 --- a/src/Mod/Material/App/MaterialLibrary.cpp +++ b/src/Mod/Material/App/MaterialLibrary.cpp @@ -21,11 +21,17 @@ #include "PreCompiled.h" #ifndef _PreComp_ +#include #endif +#include +#include + #include #include "MaterialLibrary.h" +#include "MaterialLoader.h" +#include "MaterialManager.h" #include "Materials.h" #include "ModelManager.h" @@ -34,9 +40,6 @@ using namespace Materials; /* TRANSLATOR Material::Materials */ -std::unique_ptr> MaterialLibrary::_materialPathMap = - std::make_unique>(); - TYPESYSTEM_SOURCE(Materials::MaterialLibrary, LibraryBase) MaterialLibrary::MaterialLibrary() @@ -48,24 +51,165 @@ MaterialLibrary::MaterialLibrary(const QString& libraryName, bool readOnly) : LibraryBase(libraryName, dir, icon) , _readOnly(readOnly) + , _materialPathMap(std::make_unique>>()) {} -void MaterialLibrary::createPath(const QString& path) -{ - Q_UNUSED(path) -} - -Material* MaterialLibrary::saveMaterial(Material& material, const QString& path, bool saveAsCopy) +void MaterialLibrary::createFolder(const QString& path) { QString filePath = getLocalPath(path); - Base::Console().Log("\tfilePath = '%s'\n", filePath.toStdString().c_str()); + // Base::Console().Log("\tfilePath = '%s'\n", filePath.toStdString().c_str()); + + QDir fileDir(filePath); + if (!fileDir.exists()) { + if (!fileDir.mkpath(filePath)) { + Base::Console().Error("Unable to create directory path '%s'\n", + filePath.toStdString().c_str()); + } + } +} + +// This accepts the filesystem path as returned from getLocalPath +void MaterialLibrary::deleteDir(MaterialManager& manager, const QString& path) +{ + // Base::Console().Log("Removing directory '%s'\n", path.toStdString().c_str()); + + // Remove the children first + QDirIterator it(path, QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot); + + // Add paths to a list so there are no iterator errors + QVector dirList; + QVector fileList; + while (it.hasNext()) { + auto pathname = it.next(); + QFileInfo file(pathname); + if (file.isFile()) { + fileList.push_back(pathname); + } + else if (file.isDir()) { + dirList.push_back(pathname); + } + } + + // Remove the subdirs first + while (!dirList.isEmpty()) { + QString dirPath = dirList.takeFirst(); + deleteDir(manager, dirPath); + } + + // Remove the files + while (!fileList.isEmpty()) { + QString filePath = fileList.takeFirst(); + deleteFile(manager, filePath); + } + + // Finally, remove ourself + QDir dir; + if (!dir.rmdir(path)) { + throw DeleteError(path); + } +} + +// This accepts the filesystem path as returned from getLocalPath +void MaterialLibrary::deleteFile(MaterialManager& manager, const QString& path) +{ + // Base::Console().Log("Removing file '%s'\n", path.toStdString().c_str()); + + if (QFile::remove(path)) { + // Remove from the map + QString rPath = getRelativePath(path); + // Base::Console().Log("\trpath '%s'\n", rPath.toStdString().c_str()); + try { + auto material = getMaterialByPath(rPath); + manager.remove(material->getUUID()); + } + catch (const MaterialNotFound&) { + Base::Console().Log("Unable to remove file from materials list\n"); + } + _materialPathMap->erase(rPath); + } + else { + QString error = QString::fromStdString("DeleteError: Unable to delete ") + path; + throw DeleteError(error); + } +} + +void MaterialLibrary::deleteRecursive(const QString& path) +{ + std::string pstring = path.toStdString(); + Base::Console().Log("\tdeleteRecursive '%s'\n", pstring.c_str()); + + if (isRoot(path)) { + return; + } + + QString filePath = getLocalPath(path); + // Base::Console().Log("\tfilePath = '%s'\n", filePath.toStdString().c_str()); + MaterialManager manager; + + QFileInfo info(filePath); + if (info.isDir()) { + deleteDir(manager, filePath); + } + else { + deleteFile(manager, filePath); + } +} + +void MaterialLibrary::updatePaths(const QString& oldPath, const QString& newPath) +{ + // Update the path map + QString op = getRelativePath(oldPath); + QString np = getRelativePath(newPath); + std::unique_ptr>> pathMap = + std::make_unique>>(); + for (auto itp = _materialPathMap->begin(); itp != _materialPathMap->end(); itp++) { + QString path = itp->first; + if (path.startsWith(op)) { + path = np + path.remove(0, op.size()); + } + Base::Console().Error("Path '%s' -> '%s'\n", + itp->first.toStdString().c_str(), + path.toStdString().c_str()); + itp->second->setDirectory(path); + (*pathMap)[path] = itp->second; + } + + _materialPathMap = std::move(pathMap); +} + +void MaterialLibrary::renameFolder(const QString& oldPath, const QString& newPath) +{ + QString filePath = getLocalPath(oldPath); + // Base::Console().Log("\tfilePath = '%s'\n", filePath.toStdString().c_str()); + QString newFilePath = getLocalPath(newPath); + // Base::Console().Log("\tnew filePath = '%s'\n", newFilePath.toStdString().c_str()); + + QDir fileDir(filePath); + if (fileDir.exists()) { + if (!fileDir.rename(filePath, newFilePath)) { + Base::Console().Error("Unable to rename directory path '%s'\n", + filePath.toStdString().c_str()); + } + } + + updatePaths(oldPath, newPath); +} + +std::shared_ptr MaterialLibrary::saveMaterial(std::shared_ptr material, + const QString& path, + bool overwrite, + bool saveAsCopy, + bool saveInherited) +{ + QString filePath = getLocalPath(path); + // Base::Console().Log("\tfilePath = '%s'\n", filePath.toStdString().c_str()); QFile file(filePath); // Update UUID if required // if name changed true - if (material.getName() != file.fileName()) { - material.newUuid(); - } + // if (material->getName() != file.fileName()) { + // material->newUuid(); + // } // if overwrite false having warned the user // if old format true, but already set @@ -79,43 +223,49 @@ Material* MaterialLibrary::saveMaterial(Material& material, const QString& path, } } + if (info.exists()) { + if (!overwrite) { + Base::Console().Error("File already exists '%s'\n", info.path().toStdString().c_str()); + throw MaterialExists(); + } + } + if (file.open(QIODevice::WriteOnly | QIODevice::Text)) { QTextStream stream(&file); -#if QT_VERSION < QT_VERSION_CHECK(6,0,0) stream.setCodec("UTF-8"); -#endif stream.setGenerateByteOrderMark(true); // Write the contents - material.setLibrary(*this); - material.setDirectory(getRelativePath(path)); - material.save(stream, saveAsCopy); + material->setLibrary(getptr()); + material->setDirectory(getRelativePath(path)); + material->save(stream, saveAsCopy, saveInherited); } return addMaterial(material, path); } -Material* MaterialLibrary::addMaterial(const Material& material, const QString& path) +bool MaterialLibrary::fileExists(const QString& path) const +{ + QString filePath = getLocalPath(path); + QFileInfo info(filePath); + + return info.exists(); +} + +std::shared_ptr MaterialLibrary::addMaterial(std::shared_ptr material, + const QString& path) { QString filePath = getRelativePath(path); - Material* newMaterial = new Material(material); - newMaterial->setLibrary(*this); + std::shared_ptr newMaterial = std::make_shared(*material); + newMaterial->setLibrary(getptr()); newMaterial->setDirectory(filePath); - try { - // If there's already a material at that path we'll replace it - Material* old = _materialPathMap->at(filePath); - delete old; - } - catch (const std::out_of_range&) { - } - (*_materialPathMap)[filePath] = newMaterial; return newMaterial; } -const Material& MaterialLibrary::getMaterialByPath(const QString& path) const +std::shared_ptr MaterialLibrary::getMaterialByPath(const QString& path) const { // Base::Console().Log("MaterialLibrary::getMaterialByPath(%s)\n", path.toStdString().c_str()); // for (auto itp = _materialPathMap->begin(); itp != _materialPathMap->end(); itp++) { @@ -124,10 +274,10 @@ const Material& MaterialLibrary::getMaterialByPath(const QString& path) const QString filePath = getRelativePath(path); try { - Material* material = _materialPathMap->at(filePath); - return *material; + auto material = _materialPathMap->at(filePath); + return material; } - catch (std::out_of_range&) { + catch (std::out_of_range& e) { throw MaterialNotFound(); } } @@ -136,14 +286,80 @@ const QString MaterialLibrary::getUUIDFromPath(const QString& path) const { QString filePath = getRelativePath(path); try { - Material* material = _materialPathMap->at(filePath); + auto material = _materialPathMap->at(filePath); return material->getUUID(); } - catch (std::out_of_range&) { + catch (std::out_of_range& e) { throw MaterialNotFound(); } } +std::shared_ptr>> +MaterialLibrary::getMaterialTree() const +{ + std::shared_ptr>> materialTree = + std::make_shared>>(); + + for (auto it = _materialPathMap->begin(); it != _materialPathMap->end(); it++) { + auto filename = it->first; + auto material = it->second; + + // Base::Console().Log("Relative path '%s'\n\t", filename.toStdString().c_str()); + QStringList list = filename.split(QString::fromStdString("/")); + + // Start at the root + std::shared_ptr>> node = materialTree; + for (auto itp = list.begin(); itp != list.end(); itp++) { + // Base::Console().Log("\t%s", itp->toStdString().c_str()); + if (itp->endsWith(QString::fromStdString(".FCMat"))) { + std::shared_ptr child = std::make_shared(); + child->setData(material); + (*node)[*itp] = child; + } + else { + // Add the folder only if it's not already there + if (node->count(*itp) == 0) { + auto mapPtr = + std::make_shared>>(); + std::shared_ptr child = std::make_shared(); + child->setFolder(mapPtr); + (*node)[*itp] = child; + node = mapPtr; + } + else { + node = (*node)[*itp]->getFolder(); + } + } + } + } + + // Empty folders aren't included in _materialPathMap, so we add them by looking at the file + // system + auto folderList = MaterialLoader::getMaterialFolders(*this); + for (auto folder : *folderList) { + QStringList list = folder.split(QString::fromStdString("/")); + + // Start at the root + auto node = materialTree; + for (auto itp = list.begin(); itp != list.end(); itp++) { + // Add the folder only if it's not already there + if (node->count(*itp) == 0) { + std::shared_ptr>> mapPtr = + std::make_shared>>(); + std::shared_ptr child = std::make_shared(); + child->setFolder(mapPtr); + (*node)[*itp] = child; + node = mapPtr; + } + else { + node = (*node)[*itp]->getFolder(); + } + } + } + + return materialTree; +} + TYPESYSTEM_SOURCE(Materials::MaterialExternalLibrary, MaterialLibrary::MaterialLibrary) MaterialExternalLibrary::MaterialExternalLibrary() diff --git a/src/Mod/Material/App/MaterialLibrary.h b/src/Mod/Material/App/MaterialLibrary.h index 8bb16f34f8..ce6d32dfd3 100644 --- a/src/Mod/Material/App/MaterialLibrary.h +++ b/src/Mod/Material/App/MaterialLibrary.h @@ -22,14 +22,17 @@ #ifndef MATERIAL_MATERIALLIBRARY_H #define MATERIAL_MATERIALLIBRARY_H -#include - -#include #include + #include #include #include +#include + +#include + +#include "Materials.h" #include "Model.h" #include "ModelLibrary.h" @@ -37,17 +40,19 @@ namespace Materials { class Material; +class MaterialManager; -class MaterialsExport MaterialLibrary: public LibraryBase +class MaterialsExport MaterialLibrary: public LibraryBase, + public std::enable_shared_from_this { - TYPESYSTEM_HEADER_WITH_OVERRIDE(); + TYPESYSTEM_HEADER(); public: MaterialLibrary(); - explicit MaterialLibrary(const QString& libraryName, - const QString& dir, - const QString& icon, - bool readOnly = true); + MaterialLibrary(const QString& libraryName, + const QString& dir, + const QString& icon, + bool readOnly = true); ~MaterialLibrary() override = default; bool operator==(const MaterialLibrary& library) const @@ -58,40 +63,60 @@ public: { return !operator==(library); } - const Material& getMaterialByPath(const QString& path) const; + std::shared_ptr getMaterialByPath(const QString& path) const; - void createPath(const QString& path); - Material* saveMaterial(Material& material, const QString& path, bool saveAsCopy); - Material* addMaterial(const Material& material, const QString& path); + void createFolder(const QString& path); + void renameFolder(const QString& oldPath, const QString& newPath); + void deleteRecursive(const QString& path); + + std::shared_ptr saveMaterial(std::shared_ptr material, + const QString& path, + bool overwrite, + bool saveAsCopy, + bool saveInherited); + bool fileExists(const QString& path) const; + std::shared_ptr addMaterial(std::shared_ptr material, const QString& path); + std::shared_ptr>> getMaterialTree() const; bool isReadOnly() const { return _readOnly; } + // Use this to get a shared_ptr for *this + std::shared_ptr getptr() + { + return shared_from_this(); + } + protected: + MaterialLibrary(const MaterialLibrary&) = default; + + void deleteDir(MaterialManager& manager, const QString& path); + void deleteFile(MaterialManager& manager, const QString& path); + + void updatePaths(const QString& oldPath, const QString& newPath); const QString getUUIDFromPath(const QString& path) const; bool _readOnly; - static std::unique_ptr> _materialPathMap; + std::unique_ptr>> _materialPathMap; }; class MaterialsExport MaterialExternalLibrary: public MaterialLibrary { - TYPESYSTEM_HEADER_WITH_OVERRIDE(); + TYPESYSTEM_HEADER(); public: MaterialExternalLibrary(); - explicit MaterialExternalLibrary(const QString& libraryName, - const QString& dir, - const QString& icon, - bool readOnly = true); + MaterialExternalLibrary(const QString& libraryName, + const QString& dir, + const QString& icon, + bool readOnly = true); ~MaterialExternalLibrary() override; }; } // namespace Materials -Q_DECLARE_METATYPE(Materials::MaterialLibrary) -Q_DECLARE_METATYPE(Materials::MaterialExternalLibrary) +Q_DECLARE_METATYPE(std::shared_ptr) #endif // MATERIAL_MATERIALLIBRARY_H diff --git a/src/Mod/Material/App/MaterialLoader.cpp b/src/Mod/Material/App/MaterialLoader.cpp index 8742d7df6b..34004bc0a6 100644 --- a/src/Mod/Material/App/MaterialLoader.cpp +++ b/src/Mod/Material/App/MaterialLoader.cpp @@ -24,13 +24,18 @@ #include #endif -#include -#include - #include #include +#include + +#include +#include +#include + +#include "Materials.h" #include "MaterialConfigLoader.h" +#include "MaterialLibrary.h" #include "MaterialLoader.h" #include "Model.h" #include "ModelManager.h" @@ -41,7 +46,7 @@ using namespace Materials; MaterialEntry::MaterialEntry() {} -MaterialEntry::MaterialEntry(const MaterialLibrary& library, +MaterialEntry::MaterialEntry(std::shared_ptr library, const QString& modelName, const QString& dir, const QString& modelUuid) @@ -51,7 +56,7 @@ MaterialEntry::MaterialEntry(const MaterialLibrary& library, , _uuid(modelUuid) {} -MaterialYamlEntry::MaterialYamlEntry(const MaterialLibrary& library, +MaterialYamlEntry::MaterialYamlEntry(std::shared_ptr library, const QString& modelName, const QString& dir, const QString& modelUuid, @@ -73,7 +78,82 @@ QString MaterialYamlEntry::yamlValue(const YAML::Node& node, return QString::fromStdString(defaultValue); } -void MaterialYamlEntry::addToTree(std::shared_ptr> materialMap) +std::shared_ptr MaterialYamlEntry::read2DArray(const YAML::Node& node) +{ + // Base::Console().Log("Read 2D Array\n"); + + auto array2d = std::make_shared(); + + if (node.size() == 2) { + // Get the default + Base::Quantity defaultValue = + Base::Quantity::parse(QString::fromStdString(node[0].as())); + array2d->setDefault(QVariant::fromValue(defaultValue)); + + auto yamlArray = node[1]; + for (std::size_t i = 0; i < yamlArray.size(); i++) { + auto yamlRow = yamlArray[i]; + + auto row = std::make_shared>(); + for (std::size_t j = 0; j < yamlRow.size(); j++) { + Base::Quantity q = + Base::Quantity::parse(QString::fromStdString(yamlRow[j].as())); + row->push_back(QVariant::fromValue(q)); + } + array2d->addRow(row); + } + } + + return array2d; +} + +std::shared_ptr MaterialYamlEntry::read3DArray(const YAML::Node& node) +{ + Base::Console().Log("Read 3D Array\n"); + + auto array3d = std::make_shared(); + + if (node.size() == 2) { + // Get the default + Base::Quantity defaultValue = + Base::Quantity::parse(QString::fromStdString(node[0].as())); + array3d->setDefault(QVariant::fromValue(defaultValue)); + + auto yamlArray = node[1]; + + for (std::size_t depth = 0; depth < yamlArray.size(); depth++) { + auto yamlDepth = yamlArray[depth]; + MaterialLoader::showYaml(yamlDepth); + for (auto it = yamlDepth.begin(); it != yamlDepth.end(); it++) { + MaterialLoader::showYaml(it->first); + MaterialLoader::showYaml(it->second); + + Base::Console().Log("Depth %d '%s'\n", depth, it->first.as().c_str()); + auto depthValue = + Base::Quantity::parse(QString::fromStdString(it->first.as())); + + array3d->addDepth(depth, depthValue); + + auto yamlTable = it->second; + for (std::size_t i = 0; i < yamlTable.size(); i++) { + auto yamlRow = yamlTable[i]; + + auto row = std::make_shared>(); + for (std::size_t j = 0; j < yamlRow.size(); j++) { + row->push_back(Base::Quantity::parse( + QString::fromStdString(yamlRow[j].as()))); + } + array3d->addRow(depth, row); + } + } + } + } + + return array3d; +} + +void MaterialYamlEntry::addToTree( + std::shared_ptr>> materialMap) { std::set exclude; exclude.insert(QString::fromStdString("General")); @@ -85,11 +165,14 @@ void MaterialYamlEntry::addToTree(std::shared_ptr> auto directory = getDirectory(); QString uuid = getUUID(); - QString authorAndLicense = yamlValue(yamlModel["General"], "AuthorAndLicense", ""); + QString author = yamlValue(yamlModel["General"], "Author", ""); + QString license = yamlValue(yamlModel["General"], "License", ""); QString description = yamlValue(yamlModel["General"], "Description", ""); - Material* finalModel = new Material(library, directory, uuid, name); - finalModel->setAuthorAndLicense(authorAndLicense); + std::shared_ptr finalModel = + std::make_shared(library, directory, uuid, name); + finalModel->setAuthor(author); + finalModel->setLicense(license); finalModel->setDescription(description); // Add inheritance list @@ -118,11 +201,34 @@ void MaterialYamlEntry::addToTree(std::shared_ptr> auto properties = yamlModel["Models"][modelName]; for (auto itp = properties.begin(); itp != properties.end(); itp++) { std::string propertyName = (itp->first).as(); - std::string propertyValue = (itp->second).as(); - if (finalModel->hasPhysicalProperty(QString::fromStdString(propertyName))) { - finalModel->setPhysicalValue(QString::fromStdString(propertyName), - QString::fromStdString(propertyValue)); + auto prop = + finalModel->getPhysicalProperty(QString::fromStdString(propertyName)); + auto type = prop->getType(); + + try { + if (type == MaterialValue::Array2D) { + auto array2d = read2DArray(itp->second); + finalModel->setPhysicalValue(QString::fromStdString(propertyName), + array2d); + } + else if (type == MaterialValue::Array3D) { + auto array3d = read3DArray(itp->second); + finalModel->setPhysicalValue(QString::fromStdString(propertyName), + array3d); + } + else { + std::string propertyValue = (itp->second).as(); + finalModel->setPhysicalValue(QString::fromStdString(propertyName), + QString::fromStdString(propertyValue)); + } + } + catch (const YAML::BadConversion& e) { + Base::Console().Log("Exception %s <%s:%s> - ignored\n", + e.what(), + name.toStdString().c_str(), + propertyName.c_str()); + } } else if (propertyName != "UUID") { Base::Console().Log("\tProperty '%s' is not described by any model. Ignored\n", @@ -147,11 +253,32 @@ void MaterialYamlEntry::addToTree(std::shared_ptr> auto properties = yamlModel["AppearanceModels"][modelName]; for (auto itp = properties.begin(); itp != properties.end(); itp++) { std::string propertyName = (itp->first).as(); - std::string propertyValue = (itp->second).as(); - if (finalModel->hasAppearanceProperty(QString::fromStdString(propertyName))) { - finalModel->setAppearanceValue(QString::fromStdString(propertyName), - QString::fromStdString(propertyValue)); + auto prop = + finalModel->getAppearanceProperty(QString::fromStdString(propertyName)); + auto type = prop->getType(); + + try { + if (type == MaterialValue::Array2D) { + auto array2d = read2DArray(itp->second); + finalModel->setAppearanceValue(QString::fromStdString(propertyName), + array2d); + } + else if (type == MaterialValue::Array3D) { + Base::Console().Log("Read 3D Array\n"); + } + else { + std::string propertyValue = (itp->second).as(); + finalModel->setAppearanceValue(QString::fromStdString(propertyName), + QString::fromStdString(propertyValue)); + } + } + catch (const YAML::BadConversion& e) { + Base::Console().Log("Exception %s <%s:%s> - ignored\n", + e.what(), + name.toStdString().c_str(), + propertyName.c_str()); + } } else if (propertyName != "UUID") { Base::Console().Log("\tProperty '%s' is not described by any model. Ignored\n", @@ -163,13 +290,15 @@ void MaterialYamlEntry::addToTree(std::shared_ptr> QString path = QDir(directory).absolutePath(); // Base::Console().Log("\tPath '%s'\n", path.toStdString().c_str()); - (*materialMap)[uuid] = library.addMaterial(*finalModel, path); + (*materialMap)[uuid] = library->addMaterial(finalModel, path); } -std::unique_ptr> MaterialLoader::_materialEntryMap = nullptr; +std::unique_ptr>> + MaterialLoader::_materialEntryMap = nullptr; -MaterialLoader::MaterialLoader(std::shared_ptr> materialMap, - std::shared_ptr> libraryList) +MaterialLoader::MaterialLoader( + std::shared_ptr>> materialMap, + std::shared_ptr>> libraryList) : _materialMap(materialMap) , _libraryList(libraryList) { @@ -182,25 +311,58 @@ MaterialLoader::MaterialLoader(std::shared_ptr> mat MaterialLoader::~MaterialLoader() {} -void MaterialLoader::addLibrary(MaterialLibrary* model) +void MaterialLoader::addLibrary(std::shared_ptr model) { _libraryList->push_back(model); } -MaterialEntry* MaterialLoader::getMaterialFromPath(MaterialLibrary& library, - const QString& path) const +std::shared_ptr +MaterialLoader::getMaterialFromYAML(std::shared_ptr library, + YAML::Node& yamlroot, + const QString& path) const { - MaterialEntry* model = nullptr; + std::shared_ptr model = nullptr; + + try { + const std::string uuid = yamlroot["General"]["UUID"].as(); + + // Always get the name from the filename + // QString name = QString::fromStdString(yamlroot["General"]["Name"].as()); + QFileInfo filepath(path); + QString name = + filepath.fileName().remove(QString::fromStdString(".FCMat"), Qt::CaseInsensitive); + + model = std::make_shared(library, + name, + path, + QString::fromStdString(uuid), + yamlroot); + // showYaml(yamlroot); + } + catch (YAML::Exception const& e) { + Base::Console().Error("YAML parsing error: '%s'\n", path.toStdString().c_str()); + Base::Console().Error("\t'%s'\n", e.what()); + showYaml(yamlroot); + } + + + return model; +} + +std::shared_ptr +MaterialLoader::getMaterialFromPath(std::shared_ptr library, + const QString& path) const +{ + std::shared_ptr model = nullptr; // Used for debugging - std::string uuid; std::string pathName = path.toStdString(); if (MaterialConfigLoader::isConfigStyle(path)) { - Base::Console().Log("Old format .FCMat file: '%s'\n", pathName.c_str()); - Material* material = MaterialConfigLoader::getMaterialFromPath(library, path); + // Base::Console().Log("Old format .FCMat file: '%s'\n", pathName.c_str()); + auto material = MaterialConfigLoader::getMaterialFromPath(library, path); if (material) { - (*_materialMap)[material->getUUID()] = library.addMaterial(*material, path); + (*_materialMap)[material->getUUID()] = library->addMaterial(material, path); } // Return the nullptr as there are no intermediate steps to take, such @@ -212,15 +374,7 @@ MaterialEntry* MaterialLoader::getMaterialFromPath(MaterialLibrary& library, try { yamlroot = YAML::LoadFile(pathName); - const std::string uuid = yamlroot["General"]["UUID"].as(); - // Always get the name from the filename - // QString name = QString::fromStdString(yamlroot["General"]["Name"].as()); - QFileInfo filepath(path); - QString name = - filepath.fileName().remove(QString::fromStdString(".FCMat"), Qt::CaseInsensitive); - - model = new MaterialYamlEntry(library, name, path, QString::fromStdString(uuid), yamlroot); - // showYaml(yamlroot); + model = getMaterialFromYAML(library, yamlroot, path); } catch (YAML::Exception const& e) { Base::Console().Error("YAML parsing error: '%s'\n", pathName.c_str()); @@ -242,7 +396,9 @@ void MaterialLoader::showYaml(const YAML::Node& yaml) } -void MaterialLoader::dereference(Material* material) +void MaterialLoader::dereference( + std::shared_ptr>> materialMap, + std::shared_ptr material) { // Avoid recursion if (material->getDereferenced()) { @@ -254,19 +410,20 @@ void MaterialLoader::dereference(Material* material) auto parentUUID = material->getParentUUID(); if (parentUUID.size() > 0) { - Material* parent; + std::shared_ptr parent; try { - parent = (*_materialMap)[parentUUID]; + parent = materialMap->at(parentUUID); } - catch (std::out_of_range&) { + catch (std::out_of_range& e) { Base::Console().Log( "Unable to apply inheritance for material '%s', parent '%s' not found.\n", material->getName().toStdString().c_str(), parentUUID.toStdString().c_str()); + return; } // Ensure the parent has been dereferenced - dereference(parent); + dereference(materialMap, parent); // Add physical models auto modelVector = parent->getPhysicalModels(); @@ -288,20 +445,20 @@ void MaterialLoader::dereference(Material* material) auto properties = parent->getPhysicalProperties(); for (auto itp = properties.begin(); itp != properties.end(); itp++) { auto name = itp->first; - auto property = static_cast(itp->second); + auto property = itp->second; - if (material->getPhysicalProperty(name).isNull()) { - material->getPhysicalProperty(name).setValue(property.getValue()); + if (material->getPhysicalProperty(name)->isNull()) { + material->getPhysicalProperty(name)->setValue(property->getValue()); } } properties = parent->getAppearanceProperties(); for (auto itp = properties.begin(); itp != properties.end(); itp++) { auto name = itp->first; - auto property = static_cast(itp->second); + auto property = itp->second; - if (material->getAppearanceProperty(name).isNull()) { - material->getAppearanceProperty(name).setValue(property.getValue()); + if (material->getAppearanceProperty(name)->isNull()) { + material->getAppearanceProperty(name)->setValue(property->getValue()); } } } @@ -309,13 +466,18 @@ void MaterialLoader::dereference(Material* material) material->markDereferenced(); } -void MaterialLoader::loadLibrary(MaterialLibrary& library) +void MaterialLoader::dereference(std::shared_ptr material) +{ + dereference(_materialMap, material); +} + +void MaterialLoader::loadLibrary(std::shared_ptr library) { if (_materialEntryMap == nullptr) { - _materialEntryMap = std::make_unique>(); + _materialEntryMap = std::make_unique>>(); } - QDirIterator it(library.getDirectory(), QDirIterator::Subdirectories); + QDirIterator it(library->getDirectory(), QDirIterator::Subdirectories); while (it.hasNext()) { auto pathname = it.next(); QFileInfo file(pathname); @@ -341,7 +503,7 @@ void MaterialLoader::loadLibraries() auto _libraryList = getMaterialLibraries(); if (_libraryList) { for (auto it = _libraryList->begin(); it != _libraryList->end(); it++) { - loadLibrary(**it); + loadLibrary(*it); } } @@ -350,7 +512,7 @@ void MaterialLoader::loadLibraries() } } -std::shared_ptr> MaterialLoader::getMaterialLibraries() +std::shared_ptr>> MaterialLoader::getMaterialLibraries() { auto param = App::GetApplication().GetParameterGroupByPath( "User parameter:BaseApp/Preferences/Mod/Material/Resources"); @@ -362,10 +524,11 @@ std::shared_ptr> MaterialLoader::getMaterialLibrarie if (useBuiltInMaterials) { QString resourceDir = QString::fromStdString(App::Application::getResourceDir() + "/Mod/Material/Resources/Materials"); - auto libData = new MaterialLibrary(QString::fromStdString("System"), - resourceDir, - QString::fromStdString(":/icons/freecad.svg"), - true); + auto libData = + std::make_shared(QString::fromStdString("System"), + resourceDir, + QString::fromStdString(":/icons/freecad.svg"), + true); _libraryList->push_back(libData); } @@ -382,10 +545,10 @@ std::shared_ptr> MaterialLoader::getMaterialLibrarie if (materialDir.length() > 0) { QDir dir(materialDir); if (dir.exists()) { - auto libData = new MaterialLibrary(moduleName, - materialDir, - materialIcon, - materialReadOnly); + auto libData = std::make_shared(moduleName, + materialDir, + materialIcon, + materialReadOnly); _libraryList->push_back(libData); } } @@ -397,12 +560,19 @@ std::shared_ptr> MaterialLoader::getMaterialLibrarie QString::fromStdString(App::Application::getUserAppDataDir() + "/Material"); if (!resourceDir.isEmpty()) { QDir materialDir(resourceDir); + if (!materialDir.exists()) { + // Try creating the user dir if it doesn't exist + if (!materialDir.mkpath(resourceDir)) { + Base::Console().Log("Unable to create user library '%s'\n", + resourceDir.toStdString().c_str()); + } + } if (materialDir.exists()) { - auto libData = - new MaterialLibrary(QString::fromStdString("User"), - resourceDir, - QString::fromStdString(":/icons/preferences-general.svg"), - false); + auto libData = std::make_shared( + QString::fromStdString("User"), + resourceDir, + QString::fromStdString(":/icons/preferences-general.svg"), + false); _libraryList->push_back(libData); } } @@ -413,10 +583,11 @@ std::shared_ptr> MaterialLoader::getMaterialLibrarie if (!resourceDir.isEmpty()) { QDir materialDir(resourceDir); if (materialDir.exists()) { - auto libData = new MaterialLibrary(QString::fromStdString("Custom"), - resourceDir, - QString::fromStdString(":/icons/user.svg"), - false); + auto libData = + std::make_shared(QString::fromStdString("Custom"), + resourceDir, + QString::fromStdString(":/icons/user.svg"), + false); _libraryList->push_back(libData); } } diff --git a/src/Mod/Material/App/MaterialLoader.h b/src/Mod/Material/App/MaterialLoader.h index f4bac08939..427d348630 100644 --- a/src/Mod/Material/App/MaterialLoader.h +++ b/src/Mod/Material/App/MaterialLoader.h @@ -22,6 +22,8 @@ #ifndef MATERIAL_MATERIALLOADER_H #define MATERIAL_MATERIALLOADER_H +#include + #include #include #include @@ -36,15 +38,16 @@ class MaterialEntry { public: MaterialEntry(); - explicit MaterialEntry(const MaterialLibrary& library, - const QString& modelName, - const QString& dir, - const QString& modelUuid); + MaterialEntry(std::shared_ptr library, + const QString& modelName, + const QString& dir, + const QString& modelUuid); virtual ~MaterialEntry() = default; - virtual void addToTree(std::shared_ptr> materialMap) = 0; + virtual void + addToTree(std::shared_ptr>> materialMap) = 0; - const MaterialLibrary& getLibrary() const + std::shared_ptr getLibrary() const { return _library; } @@ -62,7 +65,7 @@ public: } protected: - MaterialLibrary _library; + std::shared_ptr _library; QString _name; QString _directory; QString _uuid; @@ -71,14 +74,15 @@ protected: class MaterialYamlEntry: public MaterialEntry { public: - explicit MaterialYamlEntry(const MaterialLibrary& library, - const QString& modelName, - const QString& dir, - const QString& modelUuid, - const YAML::Node& modelData); + MaterialYamlEntry(std::shared_ptr library, + const QString& modelName, + const QString& dir, + const QString& modelUuid, + const YAML::Node& modelData); ~MaterialYamlEntry() override = default; - void addToTree(std::shared_ptr> materialMap) override; + void + addToTree(std::shared_ptr>> materialMap) override; const YAML::Node& getModel() const { @@ -94,6 +98,8 @@ private: QString yamlValue(const YAML::Node& node, const std::string& key, const std::string& defaultValue); + std::shared_ptr read2DArray(const YAML::Node& node); + std::shared_ptr read3DArray(const YAML::Node& node); YAML::Node _model; }; @@ -101,26 +107,34 @@ private: class MaterialLoader { public: - explicit MaterialLoader(std::shared_ptr> materialMap, - std::shared_ptr> libraryList); + MaterialLoader(std::shared_ptr>> materialMap, + std::shared_ptr>> libraryList); virtual ~MaterialLoader(); - std::shared_ptr> getMaterialLibraries(); + std::shared_ptr>> getMaterialLibraries(); static std::shared_ptr> getMaterialFolders(const MaterialLibrary& library); static void showYaml(const YAML::Node& yaml); + static void + dereference(std::shared_ptr>> materialMap, + std::shared_ptr material); + std::shared_ptr getMaterialFromYAML(std::shared_ptr library, + YAML::Node& yamlroot, + const QString& path) const; private: MaterialLoader(); - void addToTree(MaterialEntry* model); - void dereference(Material* material); - MaterialEntry* getMaterialFromPath(MaterialLibrary& library, const QString& path) const; - void addLibrary(MaterialLibrary* model); - void loadLibrary(MaterialLibrary& library); + void addToTree(std::shared_ptr model); + void dereference(std::shared_ptr material); + std::shared_ptr getMaterialFromPath(std::shared_ptr library, + const QString& path) const; + void addLibrary(std::shared_ptr model); + void loadLibrary(std::shared_ptr library); void loadLibraries(); - static std::unique_ptr> _materialEntryMap; - std::shared_ptr> _materialMap; - std::shared_ptr> _libraryList; + + static std::unique_ptr>> _materialEntryMap; + std::shared_ptr>> _materialMap; + std::shared_ptr>> _libraryList; }; } // namespace Materials diff --git a/src/Mod/Material/App/MaterialManager.cpp b/src/Mod/Material/App/MaterialManager.cpp index efbf45b0b9..f073b7a087 100644 --- a/src/Mod/Material/App/MaterialManager.cpp +++ b/src/Mod/Material/App/MaterialManager.cpp @@ -23,6 +23,7 @@ #ifndef _PreComp_ #endif +#include #include #include @@ -37,8 +38,10 @@ using namespace Materials; /* TRANSLATOR Material::Materials */ -std::shared_ptr> MaterialManager::_libraryList = nullptr; -std::shared_ptr> MaterialManager::_materialMap = nullptr; +std::shared_ptr>> MaterialManager::_libraryList = + nullptr; +std::shared_ptr>> MaterialManager::_materialMap = + nullptr; QMutex MaterialManager::_mutex; TYPESYSTEM_SOURCE(Materials::MaterialManager, Base::BaseClass) @@ -60,10 +63,10 @@ void MaterialManager::initLibraries() delete manager; - _materialMap = std::make_shared>(); + _materialMap = std::make_shared>>(); if (_libraryList == nullptr) { - _libraryList = std::make_shared>(); + _libraryList = std::make_shared>>(); } // Load the libraries @@ -71,23 +74,15 @@ void MaterialManager::initLibraries() } } -void MaterialManager::saveMaterial(MaterialLibrary* library, - Material& material, +void MaterialManager::saveMaterial(std::shared_ptr library, + std::shared_ptr material, const QString& path, - bool saveAsCopy) + bool overwrite, + bool saveAsCopy, + bool saveInherited) { - Material* newMaterial = library->saveMaterial(material, path, saveAsCopy); - - try { - Material* old = _materialMap->at(newMaterial->getUUID()); - if (old) { - delete old; - } - } - catch (const std::out_of_range&) { - } - - (*_materialMap)[material.getUUID()] = newMaterial; + auto newMaterial = library->saveMaterial(material, path, overwrite, saveAsCopy, saveInherited); + (*_materialMap)[newMaterial->getUUID()] = newMaterial; } bool MaterialManager::isMaterial(const fs::path& p) @@ -102,31 +97,43 @@ bool MaterialManager::isMaterial(const fs::path& p) return false; } -const Material& MaterialManager::getMaterial(const QString& uuid) const +bool MaterialManager::isMaterial(const QFileInfo& file) +{ + if (!file.isFile()) { + return false; + } + // check file extension + if (file.suffix() == QString::fromStdString("FCMat")) { + return true; + } + return false; +} + +std::shared_ptr MaterialManager::getMaterial(const QString& uuid) const { try { - return *(_materialMap->at(uuid)); + return _materialMap->at(uuid); } - catch (std::out_of_range&) { + catch (std::out_of_range& e) { throw MaterialNotFound(); } } -const Material& MaterialManager::getMaterialByPath(const QString& path) const +std::shared_ptr MaterialManager::getMaterialByPath(const QString& path) const { QString cleanPath = QDir::cleanPath(path); for (auto library : *_libraryList) { - Base::Console().Log("MaterialManager::getMaterialByPath() Checking library '%s'->'%s'\n", - library->getName().toStdString().c_str(), - library->getDirectory().toStdString().c_str()); + // Base::Console().Log("MaterialManager::getMaterialByPath() Checking library '%s'->'%s'\n", + // library->getName().toStdString().c_str(), + // library->getDirectory().toStdString().c_str()); if (cleanPath.startsWith(library->getDirectory())) { - Base::Console().Log("MaterialManager::getMaterialByPath() Library '%s'\n", - library->getDirectory().toStdString().c_str()); - Base::Console().Log("MaterialManager::getMaterialByPath() Path '%s'\n", - cleanPath.toStdString().c_str()); + // Base::Console().Log("MaterialManager::getMaterialByPath() Library '%s'\n", + // library->getDirectory().toStdString().c_str()); + // Base::Console().Log("MaterialManager::getMaterialByPath() Path '%s'\n", + // cleanPath.toStdString().c_str()); return library->getMaterialByPath(cleanPath); } } @@ -136,13 +143,51 @@ const Material& MaterialManager::getMaterialByPath(const QString& path) const throw MaterialNotFound(); } -const Material& MaterialManager::getMaterialByPath(const QString& path, const QString& lib) const +std::shared_ptr MaterialManager::getMaterialByPath(const QString& path, + const QString& lib) const { auto library = getLibrary(lib); // May throw LibraryNotFound return library->getMaterialByPath(path); // May throw MaterialNotFound } -MaterialLibrary* MaterialManager::getLibrary(const QString& name) const +bool MaterialManager::exists(const QString& uuid) const +{ + try { + auto material = getMaterial(uuid); + if (material.get() != nullptr) { + return true; + } + } + catch (const MaterialNotFound&) { + } + + return false; +} + +std::shared_ptr MaterialManager::getParent(std::shared_ptr material) +{ + if (material->getParentUUID().isEmpty()) { + throw MaterialNotFound(); + } + + return getMaterial(material->getParentUUID()); +} + +bool MaterialManager::exists(std::shared_ptr library, const QString& uuid) const +{ + try { + auto material = getMaterial(uuid); + if (material.get() != nullptr) { + return (*material->getLibrary() == *library); + } + } + catch (const MaterialNotFound&) { + } + + return false; +} + +std::shared_ptr MaterialManager::getLibrary(const QString& name) const { for (auto library : *_libraryList) { if (library->getName() == name) { @@ -153,13 +198,13 @@ MaterialLibrary* MaterialManager::getLibrary(const QString& name) const throw LibraryNotFound(); } -std::shared_ptr> MaterialManager::getMaterialLibraries() +std::shared_ptr>> MaterialManager::getMaterialLibraries() { if (_libraryList == nullptr) { if (_materialMap == nullptr) { - _materialMap = std::make_shared>(); + _materialMap = std::make_shared>>(); } - _libraryList = std::make_shared>(); + _libraryList = std::make_shared>>(); // Load the libraries MaterialLoader loader(_materialMap, _libraryList); @@ -167,87 +212,21 @@ std::shared_ptr> MaterialManager::getMaterialLibrari return _libraryList; } -std::shared_ptr> -MaterialManager::getMaterialTree(const MaterialLibrary& library) const -{ - std::shared_ptr> materialTree = - std::make_shared>(); - - for (auto it = _materialMap->begin(); it != _materialMap->end(); it++) { - auto filename = it->first; - auto material = it->second; - - if (material->getLibrary() == library) { - fs::path path = material->getDirectory().toStdString(); - - // Start at the root - auto node = materialTree; - for (auto itp = path.begin(); itp != path.end(); itp++) { - if (QString::fromStdString(itp->string()) - .endsWith(QString::fromStdString(".FCMat"))) { - MaterialTreeNode* child = new MaterialTreeNode(); - child->setData(material); - (*node)[QString::fromStdString(itp->string())] = child; - } - else { - // Add the folder only if it's not already there - QString folderName = QString::fromStdString(itp->string()); - std::shared_ptr> mapPtr; - if (node->count(folderName) == 0) { - mapPtr = std::make_shared>(); - MaterialTreeNode* child = new MaterialTreeNode(); - child->setFolder(mapPtr); - (*node)[folderName] = child; - node = mapPtr; - } - else { - node = (*node)[folderName]->getFolder(); - } - } - } - } - } - - auto folderList = getMaterialFolders(library); - for (auto folder : *folderList) { - fs::path path = folder.toStdString(); - - // Start at the root - auto node = materialTree; - for (auto itp = path.begin(); itp != path.end(); itp++) { - // Add the folder only if it's not already there - QString folderName = QString::fromStdString(itp->string()); - if (node->count(folderName) == 0) { - std::shared_ptr> mapPtr = - std::make_shared>(); - MaterialTreeNode* child = new MaterialTreeNode(); - child->setFolder(mapPtr); - (*node)[folderName] = child; - node = mapPtr; - } - else { - node = (*node)[folderName]->getFolder(); - } - } - } - - return materialTree; -} - std::shared_ptr> -MaterialManager::getMaterialFolders(const MaterialLibrary& library) const +MaterialManager::getMaterialFolders(std::shared_ptr library) const { - return MaterialLoader::getMaterialFolders(library); + return MaterialLoader::getMaterialFolders(*library); } -std::shared_ptr> MaterialManager::materialsWithModel(QString uuid) +std::shared_ptr>> +MaterialManager::materialsWithModel(QString uuid) { - std::shared_ptr> dict = - std::make_shared>(); + std::shared_ptr>> dict = + std::make_shared>>(); for (auto it = _materialMap->begin(); it != _materialMap->end(); it++) { QString key = it->first; - Material* material = it->second; + auto material = it->second; if (material->hasModel(uuid)) { (*dict)[key] = material; @@ -257,15 +236,15 @@ std::shared_ptr> MaterialManager::materialsWithMode return dict; } -std::shared_ptr> +std::shared_ptr>> MaterialManager::materialsWithModelComplete(QString uuid) { - std::shared_ptr> dict = - std::make_shared>(); + std::shared_ptr>> dict = + std::make_shared>>(); for (auto it = _materialMap->begin(); it != _materialMap->end(); it++) { QString key = it->first; - Material* material = it->second; + auto material = it->second; if (material->isModelComplete(uuid)) { (*dict)[key] = material; @@ -274,3 +253,8 @@ MaterialManager::materialsWithModelComplete(QString uuid) return dict; } + +void MaterialManager::dereference(std::shared_ptr material) +{ + MaterialLoader::dereference(_materialMap, material); +} diff --git a/src/Mod/Material/App/MaterialManager.h b/src/Mod/Material/App/MaterialManager.h index 03c423326d..af4261cd9f 100644 --- a/src/Mod/Material/App/MaterialManager.h +++ b/src/Mod/Material/App/MaterialManager.h @@ -22,61 +22,90 @@ #ifndef MATERIAL_MATERIALMANAGER_H #define MATERIAL_MATERIALMANAGER_H -#include +#include #include #include +#include + #include "FolderTree.h" #include "Materials.h" +#include "MaterialLibrary.h" + namespace fs = boost::filesystem; namespace Materials { -typedef FolderTreeNode MaterialTreeNode; - class MaterialsExport MaterialManager: public Base::BaseClass { - TYPESYSTEM_HEADER_WITH_OVERRIDE(); + TYPESYSTEM_HEADER(); public: MaterialManager(); ~MaterialManager() override = default; - std::shared_ptr> getMaterials() + std::shared_ptr>> getMaterials() { return _materialMap; } - const Material& getMaterial(const QString& uuid) const; - const Material& getMaterialByPath(const QString& path) const; - const Material& getMaterialByPath(const QString& path, const QString& library) const; - MaterialLibrary* getLibrary(const QString& name) const; + std::shared_ptr getMaterial(const QString& uuid) const; + std::shared_ptr getMaterialByPath(const QString& path) const; + std::shared_ptr getMaterialByPath(const QString& path, const QString& library) const; + std::shared_ptr getParent(std::shared_ptr material); + std::shared_ptr getLibrary(const QString& name) const; + bool exists(const QString& uuid) const; + bool exists(std::shared_ptr library, const QString& uuid) const; // Library management - static std::shared_ptr> getMaterialLibraries(); - std::shared_ptr> - getMaterialTree(const MaterialLibrary& library) const; - std::shared_ptr> getMaterialFolders(const MaterialLibrary& library) const; - void createPath(MaterialLibrary* library, const QString& path) + static std::shared_ptr>> getMaterialLibraries(); + std::shared_ptr>> + getMaterialTree(std::shared_ptr library) const { - library->createPath(path); + return library->getMaterialTree(); } - void saveMaterial(MaterialLibrary* library, - Material& material, + std::shared_ptr> + getMaterialFolders(std::shared_ptr library) const; + void createFolder(std::shared_ptr library, const QString& path) + { + library->createFolder(path); + } + void renameFolder(std::shared_ptr library, + const QString& oldPath, + const QString& newPath) + { + library->renameFolder(oldPath, newPath); + } + void deleteRecursive(std::shared_ptr library, const QString& path) + { + library->deleteRecursive(path); + } + void remove(const QString& uuid) + { + _materialMap->erase(uuid); + } + + void saveMaterial(std::shared_ptr library, + std::shared_ptr material, const QString& path, - bool saveAsCopy = true); + bool overwrite, + bool saveAsCopy, + bool saveInherited); static bool isMaterial(const fs::path& p); + static bool isMaterial(const QFileInfo& file); - std::shared_ptr> materialsWithModel(QString uuid); - std::shared_ptr> materialsWithModelComplete(QString uuid); + std::shared_ptr>> materialsWithModel(QString uuid); + std::shared_ptr>> + materialsWithModelComplete(QString uuid); + void dereference(std::shared_ptr material); private: - static std::shared_ptr> _libraryList; - static std::shared_ptr> _materialMap; + static std::shared_ptr>> _libraryList; + static std::shared_ptr>> _materialMap; static QMutex _mutex; static void initLibraries(); diff --git a/src/Mod/Material/App/MaterialManagerPyImpl.cpp b/src/Mod/Material/App/MaterialManagerPyImpl.cpp index 733b2cba2c..560e22c9e3 100644 --- a/src/Mod/Material/App/MaterialManagerPyImpl.cpp +++ b/src/Mod/Material/App/MaterialManagerPyImpl.cpp @@ -21,10 +21,6 @@ #include "PreCompiled.h" -#ifndef _PreComp_ -#include -#endif - #include "Exceptions.h" #include "MaterialManager.h" #include "MaterialManagerPy.h" @@ -64,9 +60,8 @@ PyObject* MaterialManagerPy::getMaterial(PyObject* args) } try { - const Material& material = - getMaterialManagerPtr()->getMaterial(QString::fromStdString(uuid)); - return new MaterialPy(new Material(material)); + auto material = getMaterialManagerPtr()->getMaterial(QString::fromStdString(uuid)); + return new MaterialPy(new Material(*material)); } catch (const MaterialNotFound&) { PyErr_SetString(PyExc_LookupError, "Material not found"); @@ -85,9 +80,9 @@ PyObject* MaterialManagerPy::getMaterialByPath(PyObject* args) QString libPath(QString::fromStdString(lib)); if (!libPath.isEmpty()) { try { - const Material& material = + auto material = getMaterialManagerPtr()->getMaterialByPath(QString::fromStdString(path), libPath); - return new MaterialPy(new Material(material)); + return new MaterialPy(new Material(*material)); } catch (const MaterialNotFound&) { PyErr_SetString(PyExc_LookupError, "Material not found"); @@ -100,9 +95,8 @@ PyObject* MaterialManagerPy::getMaterialByPath(PyObject* args) } try { - const Material& material = - getMaterialManagerPtr()->getMaterialByPath(QString::fromStdString(path)); - return new MaterialPy(new Material(material)); + auto material = getMaterialManagerPtr()->getMaterialByPath(QString::fromStdString(path)); + return new MaterialPy(new Material(*material)); } catch (const MaterialNotFound&) { PyErr_SetString(PyExc_LookupError, "Material not found"); @@ -116,7 +110,7 @@ Py::List MaterialManagerPy::getMaterialLibraries() const Py::List list; for (auto it = libraries->begin(); it != libraries->end(); it++) { - MaterialLibrary* lib = *it; + auto lib = *it; Py::Tuple libTuple(3); libTuple.setItem(0, Py::String(lib->getName().toStdString())); libTuple.setItem(1, Py::String(lib->getDirectoryPath().toStdString())); @@ -136,7 +130,7 @@ Py::Dict MaterialManagerPy::getMaterials() const for (auto it = materials->begin(); it != materials->end(); it++) { QString key = it->first; - Material* material = it->second; + auto material = it->second; PyObject* materialPy = new MaterialPy(new Material(*material)); dict.setItem(Py::String(key.toStdString()), Py::Object(materialPy, true)); @@ -168,7 +162,7 @@ PyObject* MaterialManagerPy::materialsWithModel(PyObject* args) for (auto it = materials->begin(); it != materials->end(); it++) { QString key = it->first; - Material* material = it->second; + auto material = it->second; PyObject* materialPy = new MaterialPy(new Material(*material)); PyDict_SetItem(dict, PyUnicode_FromString(key.toStdString().c_str()), materialPy); @@ -190,7 +184,7 @@ PyObject* MaterialManagerPy::materialsWithModelComplete(PyObject* args) for (auto it = materials->begin(); it != materials->end(); it++) { QString key = it->first; - Material* material = it->second; + auto material = it->second; PyObject* materialPy = new MaterialPy(new Material(*material)); PyDict_SetItem(dict, PyUnicode_FromString(key.toStdString().c_str()), materialPy); diff --git a/src/Mod/Material/App/MaterialPy.xml b/src/Mod/Material/App/MaterialPy.xml index d2ffb43da2..e16a95f804 100644 --- a/src/Mod/Material/App/MaterialPy.xml +++ b/src/Mod/Material/App/MaterialPy.xml @@ -77,10 +77,22 @@ - Author and license information. + deprecated -- Author and license information. + + + Author information. + + + + + + License information. + + + List of implemented models. diff --git a/src/Mod/Material/App/MaterialPyImpl.cpp b/src/Mod/Material/App/MaterialPyImpl.cpp index 8248f2951f..49d3668e99 100644 --- a/src/Mod/Material/App/MaterialPyImpl.cpp +++ b/src/Mod/Material/App/MaterialPyImpl.cpp @@ -21,20 +21,18 @@ #include "PreCompiled.h" -#ifndef _PreComp_ -#include -#endif - #include #include #include #include -#include "Exceptions.h" -#include "MaterialPy.h" #include "Materials.h" +#include "Exceptions.h" +#include "MaterialLibrary.h" +#include "MaterialPy.h" + #include "MaterialPy.cpp" using namespace Materials; @@ -49,11 +47,11 @@ std::string MaterialPy::representation() const str << "), UUID=("; str << ptr->getUUID().toStdString(); str << "), Library Name=("; - str << ptr->getLibrary().getName().toStdString(); + str << ptr->getLibrary()->getName().toStdString(); str << "), Library Root=("; - str << ptr->getLibrary().getDirectoryPath().toStdString(); + str << ptr->getLibrary()->getDirectoryPath().toStdString(); str << "), Library Icon=("; - str << ptr->getLibrary().getIconPath().toStdString(); + str << ptr->getLibrary()->getIconPath().toStdString(); str << "), Directory=("; str << ptr->getDirectory().toStdString(); // str << "), URL=("; @@ -93,17 +91,17 @@ int MaterialPy::PyInit(PyObject* /*args*/, PyObject* /*kwd*/) Py::String MaterialPy::getLibraryName() const { - return Py::String(getMaterialPtr()->getLibrary().getName().toStdString()); + return Py::String(getMaterialPtr()->getLibrary()->getName().toStdString()); } Py::String MaterialPy::getLibraryRoot() const { - return Py::String(getMaterialPtr()->getLibrary().getDirectoryPath().toStdString()); + return Py::String(getMaterialPtr()->getLibrary()->getDirectoryPath().toStdString()); } Py::String MaterialPy::getLibraryIcon() const { - return Py::String(getMaterialPtr()->getLibrary().getIconPath().toStdString()); + return Py::String(getMaterialPtr()->getLibrary()->getIconPath().toStdString()); } Py::String MaterialPy::getName() const @@ -146,15 +144,23 @@ Py::String MaterialPy::getAuthorAndLicense() const return Py::String(getMaterialPtr()->getAuthorAndLicense().toStdString()); } +Py::String MaterialPy::getAuthor() const +{ + return Py::String(getMaterialPtr()->getAuthor().toStdString()); +} + +Py::String MaterialPy::getLicense() const +{ + return Py::String(getMaterialPtr()->getLicense().toStdString()); +} + Py::List MaterialPy::getPhysicalModels() const { - const std::vector* models = getMaterialPtr()->getPhysicalModels(); + auto models = getMaterialPtr()->getPhysicalModels(); Py::List list; for (auto it = models->begin(); it != models->end(); it++) { - QString uuid = *it; - - list.append(Py::String(uuid.toStdString())); + list.append(Py::String(it->toStdString())); } return list; @@ -162,13 +168,11 @@ Py::List MaterialPy::getPhysicalModels() const Py::List MaterialPy::getAppearanceModels() const { - const std::vector* models = getMaterialPtr()->getAppearanceModels(); + auto models = getMaterialPtr()->getAppearanceModels(); Py::List list; for (auto it = models->begin(); it != models->end(); it++) { - QString uuid = *it; - - list.append(Py::String(uuid.toStdString())); + list.append(Py::String(it->toStdString())); } return list; @@ -176,13 +180,11 @@ Py::List MaterialPy::getAppearanceModels() const Py::List MaterialPy::getTags() const { - const std::list& tags = getMaterialPtr()->getTags(); + auto& tags = getMaterialPtr()->getTags(); Py::List list; for (auto it = tags.begin(); it != tags.end(); it++) { - QString uuid = *it; - - list.append(Py::String(uuid.toStdString())); + list.append(Py::String(it->toStdString())); } return list; @@ -272,6 +274,8 @@ Py::Dict MaterialPy::getProperties() const dict.setItem(Py::String("CardName"), Py::String(getMaterialPtr()->getName().toStdString())); dict.setItem(Py::String("AuthorAndLicense"), Py::String(getMaterialPtr()->getAuthorAndLicense().toStdString())); + dict.setItem(Py::String("Author"), Py::String(getMaterialPtr()->getAuthor().toStdString())); + dict.setItem(Py::String("License"), Py::String(getMaterialPtr()->getLicense().toStdString())); dict.setItem(Py::String("Name"), Py::String(getMaterialPtr()->getName().toStdString())); dict.setItem(Py::String("Description"), Py::String(getMaterialPtr()->getDescription().toStdString())); @@ -282,10 +286,10 @@ Py::Dict MaterialPy::getProperties() const auto properties = getMaterialPtr()->getPhysicalProperties(); for (auto it = properties.begin(); it != properties.end(); it++) { QString key = it->first; - MaterialProperty& materialProperty = it->second; + auto materialProperty = it->second; - if (!materialProperty.isNull()) { - auto value = materialProperty.getString(); + if (!materialProperty->isNull()) { + auto value = materialProperty->getString(); dict.setItem(Py::String(key.toStdString()), Py::String(value.toStdString())); } } @@ -293,10 +297,10 @@ Py::Dict MaterialPy::getProperties() const properties = getMaterialPtr()->getAppearanceProperties(); for (auto it = properties.begin(); it != properties.end(); it++) { QString key = it->first; - MaterialProperty& materialProperty = it->second; + auto materialProperty = it->second; - if (!materialProperty.isNull()) { - auto value = materialProperty.getString(); + if (!materialProperty->isNull()) { + auto value = materialProperty->getString(); dict.setItem(Py::String(key.toStdString()), Py::String(value.toStdString())); } } @@ -311,10 +315,10 @@ Py::Dict MaterialPy::getPhysicalProperties() const auto properties = getMaterialPtr()->getPhysicalProperties(); for (auto it = properties.begin(); it != properties.end(); it++) { QString key = it->first; - MaterialProperty& materialProperty = it->second; + auto materialProperty = it->second; - if (!materialProperty.isNull()) { - auto value = materialProperty.getString(); + if (!materialProperty->isNull()) { + auto value = materialProperty->getString(); dict.setItem(Py::String(key.toStdString()), Py::String(value.toStdString())); } } @@ -329,10 +333,10 @@ Py::Dict MaterialPy::getAppearanceProperties() const auto properties = getMaterialPtr()->getAppearanceProperties(); for (auto it = properties.begin(); it != properties.end(); it++) { QString key = it->first; - MaterialProperty& materialProperty = it->second; + auto materialProperty = it->second; - if (!materialProperty.isNull()) { - auto value = materialProperty.getString(); + if (!materialProperty->isNull()) { + auto value = materialProperty->getString(); dict.setItem(Py::String(key.toStdString()), Py::String(value.toStdString())); } } @@ -346,7 +350,7 @@ static PyObject* _pyObjectFromVariant(const QVariant& value) return new PyObject(); } - if (value.userType() == qMetaTypeId()) { + if (value.userType() == QMetaType::type("Base::Quantity")) { return new Base::QuantityPy(new Base::Quantity(value.value())); } else if (value.userType() == QMetaType::Double) { diff --git a/src/Mod/Material/App/MaterialValue.cpp b/src/Mod/Material/App/MaterialValue.cpp index 76805d369b..3229424696 100644 --- a/src/Mod/Material/App/MaterialValue.cpp +++ b/src/Mod/Material/App/MaterialValue.cpp @@ -23,7 +23,11 @@ #ifndef _PreComp_ #endif +#include + #include +#include +#include #include "Exceptions.h" #include "MaterialValue.h" @@ -33,29 +37,203 @@ using namespace Materials; /* TRANSLATOR Material::MaterialValue */ +TYPESYSTEM_SOURCE(Materials::MaterialValue, Base::BaseClass) + MaterialValue::MaterialValue() : _valueType(None) +{ + this->setInitialValue(None); +} + +MaterialValue::MaterialValue(const MaterialValue& other) + : _valueType(other._valueType) + , _value(other._value) {} MaterialValue::MaterialValue(ValueType type) : _valueType(type) -{} +{ + this->setInitialValue(None); +} + +MaterialValue::MaterialValue(ValueType type, ValueType inherited) + : _valueType(type) +{ + this->setInitialValue(inherited); +} + +MaterialValue& MaterialValue::operator=(const MaterialValue& other) +{ + if (this == &other) { + return *this; + } + + _valueType = other._valueType; + _value = other._value; + + return *this; +} + +bool MaterialValue::operator==(const MaterialValue& other) const +{ + if (this == &other) { + return true; + } + + return (_valueType == other._valueType) && (_value == other._value); +} + +void MaterialValue::setInitialValue(ValueType inherited) +{ + if (_valueType == String) { + _value = QVariant(static_cast(QMetaType::QString)); + } + else if (_valueType == Boolean) { + _value = QVariant(static_cast(QMetaType::Bool)); + } + else if (_valueType == Integer) { + _value = QVariant(static_cast(QMetaType::Int)); + } + else if (_valueType == Float) { + _value = QVariant(static_cast(QMetaType::Float)); + } + else if (_valueType == URL) { + _value = QVariant(static_cast(QMetaType::QString)); + } + else if (_valueType == Quantity) { + Base::Quantity q; + q.setInvalid(); + _value = QVariant::fromValue(q); + } + else if (_valueType == Color) { + _value = QVariant(static_cast(QMetaType::QString)); + } + else if (_valueType == File) { + _value = QVariant(static_cast(QMetaType::QString)); + } + else if (_valueType == Image) { + _value = QVariant(static_cast(QMetaType::QString)); + } + else if (_valueType == List) { + _value = QVariant(static_cast(QMetaType::QString)); + } + else if (_valueType == Array2D) { + if (_valueType != inherited) { + throw InvalidMaterialType("Initializing a regular material value as a 2D Array"); + } + + _value = QVariant(); // Uninitialized default value + } + else if (_valueType == Array3D) { + if (_valueType != inherited) { + throw InvalidMaterialType("Initializing a regular material value as a 3D Array"); + } + + _value = QVariant(); // Uninitialized default value + } + else { + // Default is to set the type to None and leave the variant uninitialized + _valueType = None; + _value = QVariant(); + } +} + +bool MaterialValue::isNull() const +{ + if (_value.isNull()) { + return true; + } + + if (_valueType == Quantity) { + return !_value.value().isValid(); + } + + return false; +} + +const QString MaterialValue::getYAMLString() const +{ + QString yaml = QString::fromStdString("\""); + if (!isNull()) { + if (getType() == MaterialValue::Quantity) { + Base::Quantity quantity = getValue().value(); + yaml += quantity.getUserString(); + } + else if (getType() == MaterialValue::Float) { + auto value = getValue(); + if (!value.isNull()) { + yaml += QString(QString::fromStdString("%1")).arg(value.toFloat(), 0, 'g', 6); + } + } + else { + yaml += getValue().toString(); + } + } + yaml += QString::fromStdString("\""); + return yaml; +} //=== +TYPESYSTEM_SOURCE(Materials::Material2DArray, Materials::MaterialValue) + Material2DArray::Material2DArray() - : MaterialValue(Array2D) + : MaterialValue(Array2D, Array2D) , _defaultSet(false) -{} - -MaterialValue Material2DArray::getDefault() const { - MaterialValue ret(_valueType); - ret.setValue(_value); - return ret; + // Initialize separatelt to prevent recursion + // setType(Array2D); } -const std::vector* Material2DArray::getRow(int row) const +Material2DArray::Material2DArray(const Material2DArray& other) + : MaterialValue(other) + , _defaultSet(other._defaultSet) +{ + deepCopy(other); +} + +Material2DArray& Material2DArray::operator=(const Material2DArray& other) +{ + if (this == &other) { + return *this; + } + + MaterialValue::operator=(other); + _defaultSet = other._defaultSet; + + deepCopy(other); + + return *this; +} + +void Material2DArray::deepCopy(const Material2DArray& other) +{ + // Deep copy + for (auto row : other._rows) { + std::vector v; + for (auto col : *row) { + QVariant newVariant(col); + v.push_back(newVariant); + } + addRow(std::make_shared>(v)); + } +} + +bool Material2DArray::isNull() const +{ + return rows() <= 0; +} + +const QVariant Material2DArray::getDefault() const +{ + if (_defaultSet) { + return _value; + } + + return QVariant(); +} + +std::shared_ptr> Material2DArray::getRow(int row) const { try { return _rows.at(row); @@ -65,7 +243,7 @@ const std::vector* Material2DArray::getRow(int row) const } } -std::vector* Material2DArray::getRow(int row) +std::shared_ptr> Material2DArray::getRow(int row) { try { return _rows.at(row); @@ -75,12 +253,12 @@ std::vector* Material2DArray::getRow(int row) } } -void Material2DArray::addRow(std::vector* row) +void Material2DArray::addRow(std::shared_ptr> row) { _rows.push_back(row); } -void Material2DArray::insertRow(int index, std::vector* row) +void Material2DArray::insertRow(int index, std::shared_ptr> row) { _rows.insert(_rows.begin() + index, row); } @@ -99,7 +277,7 @@ void Material2DArray::setValue(int row, int column, const QVariant& value) throw InvalidIndex(); } - std::vector* val = getRow(row); + auto val = getRow(row); try { val->at(column) = value; } @@ -124,10 +302,10 @@ const QVariant Material2DArray::getValue(int row, int column) const } } -void Material2DArray::dumpRow(const std::vector& row) const +void Material2DArray::dumpRow(std::shared_ptr> row) const { Base::Console().Log("row: "); - for (auto column : row) { + for (auto column : *row) { Base::Console().Log("'%s' ", column.toString().toStdString().c_str()); } Base::Console().Log("\n"); @@ -136,107 +314,389 @@ void Material2DArray::dumpRow(const std::vector& row) const void Material2DArray::dump() const { for (auto row : _rows) { - dumpRow(*row); + dumpRow(row); } } +const QString Material2DArray::getYAMLString() const +{ + if (isNull()) { + return QString(); + } + + // Set the correct indentation. 9 chars in this case + QString pad; + pad.fill(QChar::fromLatin1(' '), 9); + + // Save the default value + QString yaml = QString::fromStdString("\n - \""); + Base::Quantity quantity = getDefault().value(); + yaml += quantity.getUserString(); + yaml += QString::fromStdString("\"\n"); + + // Next the array contents + yaml += QString::fromStdString(" - ["); + bool firstRow = true; + for (auto row : _rows) { + if (!firstRow) { + // Each row is on its own line, padded for correct indentation + yaml += QString::fromStdString(",\n") + pad; + } + else { + firstRow = false; + } + yaml += QString::fromStdString("["); + + bool first = true; + for (auto column : *row) { + if (!first) { + // TODO: Fix for arrays with too many columns to fit on a single line + yaml += QString::fromStdString(", "); + } + else { + first = false; + } + yaml += QString::fromStdString("\""); + Base::Quantity quantity = column.value(); + yaml += quantity.getUserString(); + yaml += QString::fromStdString("\""); + } + + yaml += QString::fromStdString("]"); + } + yaml += QString::fromStdString("]"); + return yaml; +} + //=== +TYPESYSTEM_SOURCE(Materials::Material3DArray, Materials::MaterialValue) + Material3DArray::Material3DArray() - : MaterialValue(Array3D) + : MaterialValue(Array3D, Array3D) , _defaultSet(false) -{} - -MaterialValue Material3DArray::getDefault() const + , _currentDepth(0) { - MaterialValue ret(_valueType); - ret.setValue(_value); - return ret; + // Initialize separatelt to prevent recursion + // setType(Array3D); } -const std::vector*>& Material3DArray::getTable(const QVariant& depth) const +bool Material3DArray::isNull() const +{ + return depth() <= 0; +} + +const QVariant Material3DArray::getDefault() const +{ + return _value; +} + +const std::shared_ptr>>>& +Material3DArray::getTable(const Base::Quantity& depth) const +{ + for (auto it = _rowMap.begin(); it != _rowMap.end(); it++) { + if (std::get<0>(*it) == depth) { + return std::get<1>(*it); + } + } + + throw InvalidDepth(); +} + +const std::shared_ptr>>>& +Material3DArray::getTable(int depthIndex) const { try { - return _rowMap.at(depth); + return std::get<1>(_rowMap.at(depthIndex)); + } + catch (std::out_of_range const&) { + throw InvalidDepth(); + } +} + +const std::shared_ptr> Material3DArray::getRow(int depth, int row) const +{ + try { + return getTable(depth)->at(row); } catch (std::out_of_range const&) { throw InvalidRow(); } } -const std::vector& Material3DArray::getRow(const QVariant& depth, int row) const +std::shared_ptr> Material3DArray::getRow(int row) const +{ + // Check if we can convert otherwise throw error + return getRow(_currentDepth, row); +} + +std::shared_ptr> Material3DArray::getRow(int depth, int row) { try { - return *(_rowMap.at(depth).at(row)); + return getTable(depth)->at(row); } catch (std::out_of_range const&) { throw InvalidRow(); } } -const std::vector& Material3DArray::getRow(int row) const +std::shared_ptr> Material3DArray::getRow(int row) { - return getRow(getDefault().getValue().toString(), row); + return getRow(_currentDepth, row); } -std::vector& Material3DArray::getRow(const QVariant& depth, int row) +void Material3DArray::addRow(int depth, std::shared_ptr> row) { try { - return *(_rowMap.at(depth).at(row)); + getTable(depth)->push_back(row); } catch (std::out_of_range const&) { throw InvalidRow(); } } -std::vector& Material3DArray::getRow(int row) +void Material3DArray::addRow(std::shared_ptr> row) { - return getRow(getDefault().getValue().toString(), row); + addRow(_currentDepth, row); } -void Material3DArray::addRow(const QVariant& depth, std::vector* row) +int Material3DArray::addDepth(int depth, Base::Quantity value) { - _rowMap[depth].push_back(row); + if (depth == this->depth()) { + // Append to the end + return addDepth(value); + } + else if (depth > this->depth()) { + throw InvalidDepth(); + } + auto rowVector = std::make_shared>>>(); + auto entry = std::make_pair(value, rowVector); + _rowMap.insert(_rowMap.begin() + depth, entry); + + return depth; } -void Material3DArray::deleteRow(const QVariant& depth, int row) +int Material3DArray::addDepth(Base::Quantity value) { - Q_UNUSED(depth) - Q_UNUSED(row) + auto rowVector = std::make_shared>>>(); + auto entry = std::make_pair(value, rowVector); + _rowMap.push_back(entry); + + return depth() - 1; +} + +void Material3DArray::deleteDepth(int depth) +{ + deleteRows(depth); // This may throw an InvalidDepth + _rowMap.erase(_rowMap.begin() + depth); +} + +void Material3DArray::insertRow(int depth, + int row, + std::shared_ptr> rowData) +{ + try { + auto table = getTable(depth); + // auto it = table->begin(); + // std::advance(it, row); + table->insert(table->begin() + row, rowData); + } + catch (std::out_of_range const&) { + throw InvalidRow(); + } +} + +void Material3DArray::insertRow(int row, std::shared_ptr> rowData) +{ + insertRow(_currentDepth, row, rowData); +} + +void Material3DArray::deleteRow(int depth, int row) +{ + auto table = getTable(depth); + if (static_cast(row) >= table->size() || row < 0) { + throw InvalidRow(); + } + table->erase(table->begin() + row); +} + +void Material3DArray::deleteRow(int row) +{ + deleteRow(_currentDepth, row); } void Material3DArray::deleteRows(int depth) { - Q_UNUSED(depth) + auto table = getTable(depth); + table->clear(); } -void Material3DArray::setValue(const QVariant& depth, int row, int column, const QVariant& value) +void Material3DArray::deleteRows() { - Q_UNUSED(depth) - Q_UNUSED(row) - Q_UNUSED(column) - Q_UNUSED(value) + deleteRows(_currentDepth); } -void Material3DArray::setValue(int row, int column, const QVariant& value) +int Material3DArray::rows(int depth) const { - Q_UNUSED(row) - Q_UNUSED(column) - Q_UNUSED(value) + if (depth < 0 || (depth == 0 && this->depth() == 0)) { + return 0; + } + + return getTable(depth)->size(); } -const QVariant Material3DArray::getValue(const QVariant& depth, int row, int column) +int Material3DArray::columns(int depth) const +{ + if (depth < 0 || (depth == 0 && this->depth() == 0)) { + return 0; + } + if (rows() == 0) { + return 0; + } + + return getTable(depth)->at(0)->size(); +} + +void Material3DArray::setValue(int depth, int row, int column, const Base::Quantity& value) { auto val = getRow(depth, row); try { - return val.at(column); + val->at(column) = value; } catch (std::out_of_range const&) { throw InvalidColumn(); } } -const QVariant Material3DArray::getValue(int row, int column) +void Material3DArray::setValue(int row, int column, const Base::Quantity& value) { - return getValue(getDefault().getValue().toString(), row, column); + setValue(_currentDepth, row, column, value); +} + +void Material3DArray::setDepthValue(int depth, const Base::Quantity& value) +{ + try { + auto oldRows = getTable(depth); + _rowMap.at(depth) = std::pair(value, oldRows); + } + catch (std::out_of_range const&) { + throw InvalidRow(); + } +} + +void Material3DArray::setDepthValue(const Base::Quantity& value) +{ + setDepthValue(_currentDepth, value); +} + + +const Base::Quantity Material3DArray::getValue(int depth, int row, int column) const +{ + auto val = getRow(depth, row); + try { + return val->at(column); + } + catch (std::out_of_range const&) { + throw InvalidColumn(); + } +} + +const Base::Quantity Material3DArray::getValue(int row, int column) const +{ + return getValue(_currentDepth, row, column); +} + +const Base::Quantity Material3DArray::getDepthValue(int depth) const +{ + try { + return std::get<0>(_rowMap.at(depth)); + } + catch (std::out_of_range const&) { + throw InvalidRow(); + } +} + +int Material3DArray::currentDepth() const +{ + return _currentDepth; +} + +void Material3DArray::setCurrentDepth(int depth) +{ + if (depth < 0 || _rowMap.size() == 0) { + _currentDepth = 0; + } + else if (static_cast(depth) >= _rowMap.size()) { + _currentDepth = _rowMap.size() - 1; + } + else { + _currentDepth = depth; + } +} + +const QString Material3DArray::getYAMLString() const +{ + if (isNull()) { + return QString(); + } + + // Set the correct indentation. 7 chars + name length + QString pad; + pad.fill(QChar::fromLatin1(' '), 9); + + // Save the default value + QString yaml = QString::fromStdString("\n - \""); + Base::Quantity quantity = getDefault().value(); + yaml += quantity.getUserString(); + yaml += QString::fromStdString("\"\n"); + + // Next the array contents + yaml += QString::fromStdString(" - ["); + for (int depth = 0; depth < this->depth(); depth++) { + if (depth > 0) { + // Each row is on its own line, padded for correct indentation + yaml += QString::fromStdString(",\n") + pad; + } + + yaml += QString::fromStdString("\""); + auto value = getDepthValue(depth).getUserString(); + yaml += value; + yaml += QString::fromStdString("\": ["); + + QString pad2; + pad2.fill(QChar::fromLatin1(' '), 14 + value.length()); + + bool firstRow = true; + auto rows = getTable(depth); + for (auto row : *rows) { + if (!firstRow) { + // Each row is on its own line, padded for correct indentation + yaml += QString::fromStdString(",\n") + pad2; + } + else { + firstRow = false; + } + yaml += QString::fromStdString("["); + + bool first = true; + for (auto column : *row) { + if (!first) { + // TODO: Fix for arrays with too many columns to fit on a single line + yaml += QString::fromStdString(", "); + } + else { + first = false; + } + yaml += QString::fromStdString("\""); + // Base::Quantity quantity = column.value(); + yaml += column.getUserString(); + yaml += QString::fromStdString("\""); + } + + yaml += QString::fromStdString("]"); + } + yaml += QString::fromStdString("]"); + } + yaml += QString::fromStdString("]"); + return yaml; } diff --git a/src/Mod/Material/App/MaterialValue.h b/src/Mod/Material/App/MaterialValue.h index 409c137d30..8f1559ed31 100644 --- a/src/Mod/Material/App/MaterialValue.h +++ b/src/Mod/Material/App/MaterialValue.h @@ -22,15 +22,22 @@ #ifndef MATERIAL_MATERIALVALUE_H #define MATERIAL_MATERIALVALUE_H -#include +#include +#include #include +#include + +#include + namespace Materials { -class MaterialsExport MaterialValue +class MaterialsExport MaterialValue: public Base::BaseClass { + TYPESYSTEM_HEADER(); + public: enum ValueType { @@ -50,9 +57,17 @@ public: URL = 13 }; MaterialValue(); - explicit MaterialValue(ValueType type); + MaterialValue(const MaterialValue& other); + MaterialValue(ValueType type); virtual ~MaterialValue() = default; + MaterialValue& operator=(const MaterialValue& other); + virtual bool operator==(const MaterialValue& other) const; + bool operator!=(const MaterialValue& other) const + { + return !operator==(other); + } + ValueType getType() const { return _valueType; @@ -62,10 +77,8 @@ public: { return _value; } - bool isNull() const - { - return _value.isNull(); - } + virtual bool isNull() const; + virtual const QVariant getValueAt(const QVariant& value) const { Q_UNUSED(value); @@ -76,126 +89,182 @@ public: _value = value; } + virtual const QString getYAMLString() const; + protected: - ValueType _valueType; - QVariant _value; + MaterialValue(ValueType type, ValueType inherited); void setType(ValueType type) { _valueType = type; } + void setInitialValue(ValueType inherited); + + ValueType _valueType; + QVariant _value; }; class MaterialsExport Material2DArray: public MaterialValue { + TYPESYSTEM_HEADER_WITH_OVERRIDE(); + public: Material2DArray(); + Material2DArray(const Material2DArray& other); ~Material2DArray() override = default; - void setDefault(MaterialValue value) + Material2DArray& operator=(const Material2DArray& other); + + bool isNull() const override; + + void setDefault(MaterialValue value, bool markSet = true) { _value = value.getValue(); - _defaultSet = true; + _defaultSet = markSet; } - void setDefault(const QVariant& value) + void setDefault(const QVariant& value, bool markSet = true) { _value = value; - _defaultSet = true; + _defaultSet = markSet; } - MaterialValue getDefault() const; + void setDefault(const Base::Quantity& value, bool markSet = true) + { + _value = QVariant::fromValue(value); + _defaultSet = markSet; + } + const QVariant getDefault() const; bool defaultSet() const { return _defaultSet; } - const std::vector* getRow(int row) const; - std::vector* getRow(int row); + std::shared_ptr> getRow(int row) const; + std::shared_ptr> getRow(int row); int rows() const { return _rows.size(); } - void addRow(std::vector* row); - void insertRow(int index, std::vector* row); + int columns() const + { + if (rows() == 0) { + return 0; + } + + return _rows.at(0)->size(); + } + void addRow(std::shared_ptr> row); + void insertRow(int index, std::shared_ptr> row); void deleteRow(int row); void setValue(int row, int column, const QVariant& value); const QVariant getValue(int row, int column) const; + const QString getYAMLString() const override; + protected: - std::vector*> _rows; + void deepCopy(const Material2DArray& other); + + std::vector>> _rows; bool _defaultSet; private: - void dumpRow(const std::vector& row) const; + void dumpRow(std::shared_ptr> row) const; void dump() const; }; class MaterialsExport Material3DArray: public MaterialValue { + TYPESYSTEM_HEADER_WITH_OVERRIDE(); + public: Material3DArray(); ~Material3DArray() override = default; - void setDefault(MaterialValue value) + bool isNull() const override; + + void setDefault(MaterialValue value, bool markSet = true) { _value = value.getValue(); - _defaultSet = true; + _defaultSet = markSet; } - void setDefault(const QVariant& value) + void setDefault(const QVariant& value, bool markSet = true) { _value = value; - _defaultSet = true; + _defaultSet = markSet; } - MaterialValue getDefault() const; + void setDefault(const Base::Quantity& value, bool markSet = true) + { + _value = QVariant::fromValue(value); + _defaultSet = markSet; + } + const QVariant getDefault() const; bool defaultSet() const { return _defaultSet; } - const std::vector*>& getTable(const QVariant& depth) const; - const std::vector& getRow(const QVariant& depth, int row) const; - const std::vector& getRow(int row) const; - std::vector& getRow(const QVariant& depth, int row); - std::vector& getRow(int row); - void addRow(const QVariant& depth, std::vector* row); - void deleteRow(const QVariant& depth, int row); + const std::shared_ptr>>>& + getTable(const Base::Quantity& depth) const; + const std::shared_ptr>>>& + getTable(int depthIndex) const; + const std::shared_ptr> getRow(int depth, int row) const; + std::shared_ptr> getRow(int row) const; + std::shared_ptr> getRow(int depth, int row); + std::shared_ptr> getRow(int row); + void addRow(int depth, std::shared_ptr> row); + void addRow(std::shared_ptr> row); + int addDepth(int depth, Base::Quantity value); + int addDepth(Base::Quantity value); + void deleteDepth(int depth); + void insertRow(int depth, int row, std::shared_ptr> rowData); + void insertRow(int row, std::shared_ptr> rowData); + void deleteRow(int depth, int row); + void deleteRow(int row); void deleteRows(int depth); + void deleteRows(); int depth() const { return _rowMap.size(); } - int rows(const QVariant& depth) const + int rows(int depth) const; + int rows() const { - return getTable(depth).size(); + return rows(_currentDepth); + } + int columns(int depth) const; + int columns() const + { + return columns(_currentDepth); } - void setValue(const QVariant& depth, int row, int column, const QVariant& value); - void setValue(int row, int column, const QVariant& value); - const QVariant getValue(const QVariant& depth, int row, int column); - const QVariant getValue(int row, int column); + void setValue(int depth, int row, int column, const Base::Quantity& value); + void setValue(int row, int column, const Base::Quantity& value); + void setDepthValue(int depth, const Base::Quantity& value); + void setDepthValue(const Base::Quantity& value); + const Base::Quantity getValue(int depth, int row, int column) const; + const Base::Quantity getValue(int row, int column) const; + const Base::Quantity getDepthValue(int depth) const; + + int currentDepth() const; + void setCurrentDepth(int depth); + + const QString getYAMLString() const override; protected: -#if QT_VERSION < QT_VERSION_CHECK(6,0,0) - std::map*>> _rowMap; -#else - struct variant_comp - { - bool operator()(const QVariant& var1, - const QVariant& var2) const - { - return QVariant::compare(var1, var2) == QPartialOrdering::Less; - } - }; - std::map*>, variant_comp> _rowMap; -#endif - + std::vector< + std::pair>>>>> + _rowMap; bool _defaultSet; + int _currentDepth; }; } // namespace Materials Q_DECLARE_METATYPE(Materials::MaterialValue) -Q_DECLARE_METATYPE(Materials::Material2DArray) -Q_DECLARE_METATYPE(Materials::Material3DArray) +// Q_DECLARE_METATYPE(Materials::Material2DArray) +Q_DECLARE_METATYPE(std::shared_ptr) +// Q_DECLARE_METATYPE(Materials::Material3DArray) +Q_DECLARE_METATYPE(std::shared_ptr) #endif // MATERIAL_MATERIALVALUE_H diff --git a/src/Mod/Material/App/Materials.cpp b/src/Mod/Material/App/Materials.cpp index a2c3b23add..2ea280d8c4 100644 --- a/src/Mod/Material/App/Materials.cpp +++ b/src/Mod/Material/App/Materials.cpp @@ -29,8 +29,10 @@ #include #include -#include "MaterialManager.h" #include "Materials.h" + +#include "MaterialLibrary.h" +#include "MaterialManager.h" #include "ModelManager.h" @@ -58,10 +60,25 @@ MaterialProperty::MaterialProperty(const ModelProperty& property) } if (_valuePtr->getType() == MaterialValue::Array2D) { - std::static_pointer_cast(_valuePtr)->setDefault(getColumnNull(0)); + std::static_pointer_cast(_valuePtr)->setDefault(getColumnNull(0), false); } else if (_valuePtr->getType() == MaterialValue::Array3D) { - std::static_pointer_cast(_valuePtr)->setDefault(getColumnNull(0)); + std::static_pointer_cast(_valuePtr)->setDefault(getColumnNull(0), false); + } +} + +void MaterialProperty::copyValuePtr(std::shared_ptr value) +{ + if (value->getType() == MaterialValue::Array2D) { + _valuePtr = + std::make_shared(*(std::static_pointer_cast(value))); + } + else if (value->getType() == MaterialValue::Array3D) { + _valuePtr = + std::make_shared(*(std::static_pointer_cast(value))); + } + else { + _valuePtr = std::make_shared(*value); } } @@ -69,20 +86,16 @@ MaterialProperty::MaterialProperty(const MaterialProperty& other) : ModelProperty(other) { _modelUUID = other._modelUUID; - if (other._valuePtr != nullptr) { - _valuePtr = std::make_shared(*(other._valuePtr)); - } - else { - _valuePtr = nullptr; - } + copyValuePtr(other._valuePtr); for (auto it = other._columns.begin(); it != other._columns.end(); it++) { _columns.push_back(*it); } } -// MaterialProperty::~MaterialProperty() -// {} +MaterialProperty::MaterialProperty(std::shared_ptr other) + : MaterialProperty(*other) +{} void MaterialProperty::setModelUUID(const QString& uuid) { @@ -106,13 +119,28 @@ const std::shared_ptr MaterialProperty::getMaterialValue() const const QString MaterialProperty::getString() const { + if (isNull()) { + return QString(); + } if (getType() == MaterialValue::Quantity) { Base::Quantity quantity = getValue().value(); return quantity.getUserString(); } + else if (getType() == MaterialValue::Float) { + auto value = getValue(); + if (value.isNull()) { + return QString(); + } + return QString(QString::fromStdString("%1")).arg(value.toFloat(), 0, 'g', 6); + } return getValue().toString(); } +const QString MaterialProperty::getYAMLString() const +{ + return _valuePtr->getYAMLString(); +} + void MaterialProperty::setPropertyType(const QString& type) { ModelProperty::setPropertyType(type); @@ -229,7 +257,6 @@ QVariant MaterialProperty::getColumnNull(int column) const void MaterialProperty::setValue(const QVariant& value) { - // _valueType = MaterialValue::String; _valuePtr->setValue(value); } @@ -247,13 +274,21 @@ void MaterialProperty::setValue(const QString& value) else if (_valuePtr->getType() == MaterialValue::URL) { setURL(value); } + else if (_valuePtr->getType() == MaterialValue::Array2D) { + //_valuePtr->setValue(QVariant(std::make_shared())); + } + else if (_valuePtr->getType() == MaterialValue::Array3D) { + //_valuePtr = std::make_shared(); + } else if (_valuePtr->getType() == MaterialValue::Quantity) { // Base::Console().Log("\tParse quantity '%s'\n", value.toStdString().c_str()); try { setQuantity(Base::Quantity::parse(value)); } catch (const Base::ParserError& e) { - Base::Console().Log("Error '%s'\n", e.what()); + Base::Console().Log("MaterialProperty::setValue Error '%s' - '%s'\n", + e.what(), + value.toStdString().c_str()); // Save as a string setString(value); } @@ -263,6 +298,11 @@ void MaterialProperty::setValue(const QString& value) } } +void MaterialProperty::setValue(std::shared_ptr value) +{ + _valuePtr = value; +} + void MaterialProperty::setString(const QString& value) { // _valueType = MaterialValue::String; @@ -346,14 +386,9 @@ MaterialProperty& MaterialProperty::operator=(const MaterialProperty& other) } ModelProperty::operator=(other); - _modelUUID = other._modelUUID; - if (other._valuePtr != nullptr) { - _valuePtr = std::make_shared(*(other._valuePtr)); - } - else { - _valuePtr = nullptr; - } + _modelUUID = other._modelUUID; + copyValuePtr(other._valuePtr); _columns.clear(); for (auto it = other._columns.begin(); it != other._columns.end(); it++) { @@ -363,13 +398,26 @@ MaterialProperty& MaterialProperty::operator=(const MaterialProperty& other) return *this; } +bool MaterialProperty::operator==(const MaterialProperty& other) const +{ + if (this == &other) { + return true; + } + + if (ModelProperty::operator==(other)) { + return (*_valuePtr == *other._valuePtr); + } + return false; +} + TYPESYSTEM_SOURCE(Materials::Material, Base::BaseClass) Material::Material() : _dereferenced(false) + , _editState(ModelEdit_None) {} -Material::Material(const MaterialLibrary& library, +Material::Material(std::shared_ptr library, const QString& directory, const QString& uuid, const QString& name) @@ -387,7 +435,8 @@ Material::Material(const Material& other) , _directory(other._directory) , _uuid(other._uuid) , _name(other._name) - , _authorAndLicense(other._authorAndLicense) + , _author(other._author) + , _license(other._license) , _parentUuid(other._parentUuid) , _description(other._description) , _url(other._url) @@ -408,19 +457,31 @@ Material::Material(const Material& other) _allUuids.push_back(*it); } for (auto it = other._physical.begin(); it != other._physical.end(); it++) { - _physical[it->first] = MaterialProperty(it->second); + MaterialProperty prop = it->second; + _physical[it->first] = std::make_shared(prop); } for (auto it = other._appearance.begin(); it != other._appearance.end(); it++) { - _appearance[it->first] = MaterialProperty(it->second); + MaterialProperty prop = it->second; + _appearance[it->first] = std::make_shared(prop); } } -/* - * Destroys the object and frees any allocated resources - */ -Material::~Material() +const QString Material::getAuthorAndLicense() const { - // no need to delete child widgets, Qt does it all for us + QString authorAndLicense; + + // Combine the author and license field for backwards compatibility + if (!_author.isNull()) { + authorAndLicense = _author; + if (!_license.isNull()) { + authorAndLicense += QString::fromStdString(" ") + _license; + } + } + else if (!_license.isNull()) { + authorAndLicense = _license; + } + + return _license; } void Material::addModel(const QString& uuid) @@ -431,13 +492,13 @@ void Material::addModel(const QString& uuid) } } - _allUuids.push_back(uuid); + _allUuids << uuid; ModelManager manager; try { - const Model& model = manager.getModel(uuid); - auto inheritance = model.getInheritance(); + auto model = manager.getModel(uuid); + auto inheritance = model->getInheritance(); for (auto inherits = inheritance.begin(); inherits != inheritance.end(); inherits++) { addModel(*inherits); } @@ -446,6 +507,62 @@ void Material::addModel(const QString& uuid) } } +void Material::removeModel(const QString& uuid) +{ + Q_UNUSED(uuid); +} + +void Material::clearModels() +{ + _physicalUuids.clear(); + _appearanceUuids.clear(); + _allUuids.clear(); + _physical.clear(); + _appearance.clear(); +} + +void Material::setName(const QString& name) +{ + _name = name; + setEditStateExtend(); +} + +void Material::setAuthor(const QString& author) +{ + _author = author; + setEditStateExtend(); +} + +void Material::setLicense(const QString& license) +{ + _license = license; + setEditStateExtend(); +} + +void Material::setParentUUID(const QString& uuid) +{ + _parentUuid = uuid; + setEditStateExtend(); +} + +void Material::setDescription(const QString& description) +{ + _description = description; + setEditStateExtend(); +} + +void Material::setURL(const QString& url) +{ + _url = url; + setEditStateExtend(); +} + +void Material::setReference(const QString& reference) +{ + _reference = reference; + setEditStateExtend(); +} + void Material::setEditState(ModelEdit newState) { if (newState == ModelEdit_Extend) { @@ -458,6 +575,11 @@ void Material::setEditState(ModelEdit newState) } } +void Material::removeUUID(QStringList& uuidList, const QString& uuid) +{ + uuidList.removeAll(uuid); +} + void Material::addPhysical(const QString& uuid) { if (hasPhysicalModel(uuid)) { @@ -467,23 +589,32 @@ void Material::addPhysical(const QString& uuid) ModelManager manager; try { - const Model& model = manager.getModel(uuid); + auto model = manager.getModel(uuid); + + auto& inheritance = model->getInheritance(); + for (auto it = inheritance.begin(); it != inheritance.end(); it++) { + // Inherited models may already have the properties, so just + // remove the uuid + removeUUID(_physicalUuids, *it); + } _physicalUuids.push_back(uuid); addModel(uuid); setEditStateExtend(); - for (auto it = model.begin(); it != model.end(); it++) { + for (auto it = model->begin(); it != model->end(); it++) { QString propertyName = it->first; - ModelProperty property = static_cast(it->second); + if (!hasPhysicalProperty(propertyName)) { + ModelProperty property = static_cast(it->second); - try { - _physical[propertyName] = MaterialProperty(property); - } - catch (const UnknownValueType&) { - Base::Console().Error("Property '%s' has unknown type '%s'. Ignoring\n", - property.getName().toStdString().c_str(), - property.getPropertyType().toStdString().c_str()); + try { + _physical[propertyName] = std::make_shared(property); + } + catch (const UnknownValueType&) { + Base::Console().Error("Property '%s' has unknown type '%s'. Ignoring\n", + property.getName().toStdString().c_str(), + property.getPropertyType().toStdString().c_str()); + } } } } @@ -491,6 +622,47 @@ void Material::addPhysical(const QString& uuid) } } +void Material::removePhysical(const QString& uuid) +{ + if (!hasPhysicalModel(uuid)) { + return; + } + + // If it's an inherited model, do nothing + bool inherited = true; + for (auto it = _physicalUuids.begin(); it != _physicalUuids.end(); it++) { + if (*it == uuid) { + inherited = false; + break; + } + } + if (inherited) { + return; + } + + ModelManager manager; + + try { + auto model = manager.getModel(uuid); + + auto& inheritance = model->getInheritance(); + for (auto it = inheritance.begin(); it != inheritance.end(); it++) { + removeUUID(_physicalUuids, *it); + removeUUID(_allUuids, *it); + } + removeUUID(_physicalUuids, uuid); + removeUUID(_allUuids, uuid); + + for (auto it = model->begin(); it != model->end(); it++) { + _physical.erase(it->first); + } + + setEditStateAlter(); + } + catch (ModelNotFound const&) { + } +} + void Material::addAppearance(const QString& uuid) { if (hasAppearanceModel(uuid)) { @@ -500,26 +672,86 @@ void Material::addAppearance(const QString& uuid) ModelManager manager; try { - const Model& model = manager.getModel(uuid); + auto model = manager.getModel(uuid); + + auto& inheritance = model->getInheritance(); + for (auto it = inheritance.begin(); it != inheritance.end(); it++) { + // Inherited models may already have the properties, so just + // remove the uuid + removeUUID(_appearanceUuids, *it); + } _appearanceUuids.push_back(uuid); addModel(uuid); setEditStateExtend(); - for (auto it = model.begin(); it != model.end(); it++) { + for (auto it = model->begin(); it != model->end(); it++) { QString propertyName = it->first; - ModelProperty property = static_cast(it->second); + if (!hasAppearanceProperty(propertyName)) { + ModelProperty property = static_cast(it->second); - _appearance[propertyName] = MaterialProperty(property); + _appearance[propertyName] = std::make_shared(property); + } } } catch (ModelNotFound const&) { } } +void Material::removeAppearance(const QString& uuid) +{ + if (!hasAppearanceModel(uuid)) { + return; + } + + // If it's an inherited model, do nothing + bool inherited = true; + for (auto it = _appearanceUuids.begin(); it != _appearanceUuids.end(); it++) { + if (*it == uuid) { + inherited = false; + break; + } + } + if (inherited) { + return; + } + + ModelManager manager; + + try { + auto model = manager.getModel(uuid); + + auto& inheritance = model->getInheritance(); + for (auto it = inheritance.begin(); it != inheritance.end(); it++) { + removeUUID(_appearanceUuids, *it); + removeUUID(_allUuids, *it); + } + removeUUID(_appearanceUuids, uuid); + removeUUID(_allUuids, uuid); + + for (auto it = model->begin(); it != model->end(); it++) { + _appearance.erase(it->first); + } + + setEditStateAlter(); + } + catch (ModelNotFound const&) { + } +} + +void Material::setPropertyEditState(const QString& name) +{ + if (hasPhysicalProperty(name)) { + setPhysicalEditState(name); + } + else if (hasAppearanceProperty(name)) { + setAppearanceEditState(name); + } +} + void Material::setPhysicalEditState(const QString& name) { - if (getPhysicalProperty(name).isNull()) { + if (getPhysicalProperty(name)->isNull()) { setEditStateExtend(); } else { @@ -529,7 +761,7 @@ void Material::setPhysicalEditState(const QString& name) void Material::setAppearanceEditState(const QString& name) { - if (getAppearanceProperty(name).isNull()) { + if (getAppearanceProperty(name)->isNull()) { setEditStateExtend(); } else { @@ -541,38 +773,52 @@ void Material::setPhysicalValue(const QString& name, const QString& value) { setPhysicalEditState(name); - _physical[name].setValue(value); // may not be a string type + _physical[name]->setValue(value); // may not be a string type, conversion may be required } void Material::setPhysicalValue(const QString& name, int value) { setPhysicalEditState(name); - _physical[name].setInt(value); + _physical[name]->setInt(value); } void Material::setPhysicalValue(const QString& name, double value) { setPhysicalEditState(name); - _physical[name].setFloat(value); + _physical[name]->setFloat(value); } void Material::setPhysicalValue(const QString& name, const Base::Quantity value) { setPhysicalEditState(name); - _physical[name].setQuantity(value); + _physical[name]->setQuantity(value); +} + +void Material::setPhysicalValue(const QString& name, std::shared_ptr value) +{ + setPhysicalEditState(name); + + _physical[name]->setValue(value); } void Material::setAppearanceValue(const QString& name, const QString& value) { setAppearanceEditState(name); - _appearance[name].setValue(value); // may not be a string type + _appearance[name]->setValue(value); // may not be a string type, conversion may be required } -MaterialProperty& Material::getPhysicalProperty(const QString& name) +void Material::setAppearanceValue(const QString& name, std::shared_ptr value) +{ + setAppearanceEditState(name); + + _appearance[name]->setValue(value); +} + +std::shared_ptr Material::getPhysicalProperty(const QString& name) { try { return _physical.at(name); @@ -582,7 +828,7 @@ MaterialProperty& Material::getPhysicalProperty(const QString& name) } } -const MaterialProperty& Material::getPhysicalProperty(const QString& name) const +const std::shared_ptr Material::getPhysicalProperty(const QString& name) const { try { return _physical.at(name); @@ -592,7 +838,7 @@ const MaterialProperty& Material::getPhysicalProperty(const QString& name) const } } -MaterialProperty& Material::getAppearanceProperty(const QString& name) +std::shared_ptr Material::getAppearanceProperty(const QString& name) { try { return _appearance.at(name); @@ -602,7 +848,7 @@ MaterialProperty& Material::getAppearanceProperty(const QString& name) } } -const MaterialProperty& Material::getAppearanceProperty(const QString& name) const +const std::shared_ptr Material::getAppearanceProperty(const QString& name) const { try { return _appearance.at(name); @@ -612,29 +858,42 @@ const MaterialProperty& Material::getAppearanceProperty(const QString& name) con } } -const QVariant Material::getValue(const std::map& propertyList, - const QString& name) const +const QVariant +Material::getValue(const std::map>& propertyList, + const QString& name) const { try { - return propertyList.at(name).getValue(); + return propertyList.at(name)->getValue(); } catch (std::out_of_range const&) { throw PropertyNotFound(); } } -const QString Material::getValueString(const std::map& propertyList, - const QString& name) const +const QString +Material::getValueString(const std::map>& propertyList, + const QString& name) const { try { - if (propertyList.at(name).getType() == MaterialValue::Quantity) { - auto value = propertyList.at(name).getValue(); + auto property = propertyList.at(name); + if (property->isNull()) { + return QString(); + } + if (property->getType() == MaterialValue::Quantity) { + auto value = property->getValue(); if (value.isNull()) { return QString(); } return value.value().getUserString(); } - return propertyList.at(name).getValue().toString(); + else if (property->getType() == MaterialValue::Float) { + auto value = property->getValue(); + if (value.isNull()) { + return QString(); + } + return QString(QString::fromStdString("%1")).arg(value.toFloat(), 0, 'g', 6); + } + return property->getValue().toString(); } catch (std::out_of_range const&) { throw PropertyNotFound(); @@ -646,6 +905,11 @@ const QVariant Material::getPhysicalValue(const QString& name) const return getValue(_physical, name); } +const Base::Quantity Material::getPhysicalQuantity(const QString& name) const +{ + return getValue(_physical, name).value(); +} + const QString Material::getPhysicalValueString(const QString& name) const { return getValueString(_physical, name); @@ -656,6 +920,11 @@ const QVariant Material::getAppearanceValue(const QString& name) const return getValue(_appearance, name); } +const Base::Quantity Material::getAppearanceQuantity(const QString& name) const +{ + return getValue(_appearance, name).value(); +} + const QString Material::getAppearanceValueString(const QString& name) const { return getValueString(_appearance, name); @@ -685,13 +954,7 @@ bool Material::hasAppearanceProperty(const QString& name) const bool Material::hasModel(const QString& uuid) const { - for (QString modelUUID : _allUuids) { - if (modelUUID == uuid) { - return true; - } - } - - return false; + return _allUuids.contains(uuid); } bool Material::hasPhysicalModel(const QString& uuid) const @@ -703,8 +966,8 @@ bool Material::hasPhysicalModel(const QString& uuid) const ModelManager manager; try { - const Model& model = manager.getModel(uuid); - if (model.getType() == Model::ModelType_Physical) { + auto model = manager.getModel(uuid); + if (model->getType() == Model::ModelType_Physical) { return true; } } @@ -723,8 +986,8 @@ bool Material::hasAppearanceModel(const QString& uuid) const ModelManager manager; try { - const Model& model = manager.getModel(uuid); - if (model.getType() == Model::ModelType_Appearance) { + auto model = manager.getModel(uuid); + if (model->getType() == Model::ModelType_Appearance) { return true; } } @@ -743,12 +1006,12 @@ bool Material::isPhysicalModelComplete(const QString& uuid) const ModelManager manager; try { - const Model& model = manager.getModel(uuid); - for (auto it = model.begin(); it != model.end(); it++) { + auto model = manager.getModel(uuid); + for (auto it = model->begin(); it != model->end(); it++) { QString propertyName = it->first; - const MaterialProperty& property = getPhysicalProperty(propertyName); + auto property = getPhysicalProperty(propertyName); - if (property.isNull()) { + if (property->isNull()) { return false; } } @@ -769,12 +1032,12 @@ bool Material::isAppearanceModelComplete(const QString& uuid) const ModelManager manager; try { - const Model& model = manager.getModel(uuid); - for (auto it = model.begin(); it != model.end(); it++) { + auto model = manager.getModel(uuid); + for (auto it = model->begin(); it != model->end(); it++) { QString propertyName = it->first; - const MaterialProperty& property = getAppearanceProperty(propertyName); + auto property = getAppearanceProperty(propertyName); - if (property.isNull()) { + if (property->isNull()) { return false; } } @@ -791,8 +1054,11 @@ void Material::saveGeneral(QTextStream& stream) const stream << "General:\n"; stream << " UUID: \"" << _uuid << "\"\n"; stream << " Name: \"" << _name << "\"\n"; - if (!_authorAndLicense.isEmpty()) { - stream << " AuthorAndLicense: \"" << _authorAndLicense << "\"\n"; + if (!_author.isEmpty()) { + stream << " Author: \"" << _author << "\"\n"; + } + if (!_license.isEmpty()) { + stream << " License: \"" << _license << "\"\n"; } if (!_description.isEmpty()) { stream << " Description: \"" << _description << "\"\n"; @@ -810,52 +1076,157 @@ void Material::saveInherits(QTextStream& stream) const if (!_parentUuid.isEmpty()) { MaterialManager manager; - stream << "Inherits:\n"; - stream << " " << manager.getMaterial(_parentUuid).getName() << ":\n"; - stream << " UUID: \"" << _parentUuid << "\"\n"; + try { + auto material = manager.getMaterial(_parentUuid); + + stream << "Inherits:\n"; + stream << " " << material->getName() << ":\n"; + stream << " UUID: \"" << _parentUuid << "\"\n"; + } + catch (const MaterialNotFound&) { + } } } -void Material::saveModels(QTextStream& stream) const +bool Material::modelChanged(const std::shared_ptr parent, + const std::shared_ptr model) const +{ + for (auto itp = model->begin(); itp != model->end(); itp++) { + QString propertyName = itp->first; + auto property = getPhysicalProperty(propertyName); + try { + auto parentProperty = parent->getPhysicalProperty(propertyName); + + if (*property != *parentProperty) { + return true; + } + } + catch (const PropertyNotFound&) { + return true; + } + } + + return false; +} + +bool Material::modelAppearanceChanged(const std::shared_ptr parent, + const std::shared_ptr model) const +{ + for (auto itp = model->begin(); itp != model->end(); itp++) { + QString propertyName = itp->first; + auto property = getAppearanceProperty(propertyName); + try { + auto parentProperty = parent->getAppearanceProperty(propertyName); + + if (*property != *parentProperty) { + return true; + } + } + catch (const PropertyNotFound&) { + return true; + } + } + + return false; +} + +void Material::saveModels(QTextStream& stream, bool saveInherited) const { if (!_physical.empty()) { ModelManager modelManager; + MaterialManager materialManager; - stream << "Models:\n"; + bool inherited = saveInherited && (_parentUuid.size() > 0); + std::shared_ptr parent; + if (inherited) { + try { + parent = materialManager.getMaterial(_parentUuid); + } + catch (const MaterialNotFound&) { + inherited = false; + } + } + + bool headerPrinted = false; for (auto itm = _physicalUuids.begin(); itm != _physicalUuids.end(); itm++) { auto model = modelManager.getModel(*itm); - stream << " " << model.getName() << ":\n"; - stream << " UUID: \"" << model.getUUID() << "\"\n"; - for (auto itp = model.begin(); itp != model.end(); itp++) { - QString propertyName = itp->first; - const MaterialProperty& property = getPhysicalProperty(propertyName); + if (!inherited || modelChanged(parent, model)) { + if (!headerPrinted) { + stream << "Models:\n"; + headerPrinted = true; + } + stream << " " << model->getName() << ":\n"; + stream << " UUID: \"" << model->getUUID() << "\"\n"; + for (auto itp = model->begin(); itp != model->end(); itp++) { + QString propertyName = itp->first; + std::shared_ptr property = getPhysicalProperty(propertyName); + std::shared_ptr parentProperty; + try { + if (inherited) { + parentProperty = parent->getPhysicalProperty(propertyName); + } + } + catch (const PropertyNotFound&) { + Base::Console().Log("Material::saveModels Property not found '%s'\n", + propertyName.toStdString().c_str()); + } - if (!property.isNull()) { - stream << " " << propertyName << ": \"" - << getPhysicalValueString(propertyName) << "\"\n"; + if (!inherited || (*property != *parentProperty)) { + if (!property->isNull()) { + stream << " " << *property << "\n"; + } + } } } } } } -void Material::saveAppearanceModels(QTextStream& stream) const +void Material::saveAppearanceModels(QTextStream& stream, bool saveInherited) const { if (!_appearance.empty()) { ModelManager modelManager; + MaterialManager materialManager; - stream << "AppearanceModels:\n"; + bool inherited = saveInherited && (_parentUuid.size() > 0); + std::shared_ptr parent; + if (inherited) { + try { + parent = materialManager.getMaterial(_parentUuid); + } + catch (const MaterialNotFound&) { + inherited = false; + } + } + + bool headerPrinted = false; for (auto itm = _appearanceUuids.begin(); itm != _appearanceUuids.end(); itm++) { auto model = modelManager.getModel(*itm); - stream << " " << model.getName() << ":\n"; - stream << " UUID: \"" << model.getUUID() << "\"\n"; - for (auto itp = model.begin(); itp != model.end(); itp++) { - QString propertyName = itp->first; - const MaterialProperty& property = getAppearanceProperty(propertyName); + if (!inherited || modelAppearanceChanged(parent, model)) { + if (!headerPrinted) { + stream << "AppearanceModels:\n"; + headerPrinted = true; + } + stream << " " << model->getName() << ":\n"; + stream << " UUID: \"" << model->getUUID() << "\"\n"; + for (auto itp = model->begin(); itp != model->end(); itp++) { + QString propertyName = itp->first; + std::shared_ptr property = + getAppearanceProperty(propertyName); + std::shared_ptr parentProperty; + try { + if (inherited) { + parentProperty = parent->getAppearanceProperty(propertyName); + } + } + catch (const PropertyNotFound&) { + } - if (!property.isNull()) { - stream << " " << propertyName << ": \"" - << getAppearanceValueString(propertyName) << "\"\n"; + if (!inherited || (*property != *parentProperty)) { + if (!property->isNull()) { + stream << " " << *property << "\n"; + } + } } } } @@ -867,15 +1238,57 @@ void Material::newUuid() _uuid = QUuid::createUuid().toString(QUuid::WithoutBraces); } -void Material::save(QTextStream& stream, bool saveAsCopy) +QString Material::getModelByName(const QString& name) const { - Q_UNUSED(saveAsCopy) + ModelManager manager; - stream << "# File created by FreeCAD\n"; + for (auto it = _allUuids.begin(); it != _allUuids.end(); it++) { + try { + auto model = manager.getModel(*it); + if (model->getName() == name) { + return *it; + } + } + catch (ModelNotFound const&) { + } + } + + return QString(); +} + +void Material::save(QTextStream& stream, bool saveAsCopy, bool saveInherited) +{ + if (saveInherited && !saveAsCopy) { + // Check to see if we're an original or if we're already in the list of models + MaterialManager materialManager; + if (materialManager.exists(_uuid)) { + // Make a new version based on the current + setParentUUID(_uuid); + newUuid(); + } + } + + if (saveAsCopy) { + // Save it in the same format as the parent + if (_parentUuid.isEmpty()) { + saveInherited = false; + } + else { + saveInherited = true; + } + } + + stream << "---\n"; + stream << "# File created by " << QString::fromStdString(App::Application::Config()["ExeName"]) + << " " << QString::fromStdString(App::Application::Config()["ExeVersion"]) + << " Revision: " << QString::fromStdString(App::Application::Config()["BuildRevision"]) + << "\n"; saveGeneral(stream); - saveInherits(stream); - saveModels(stream); - saveAppearanceModels(stream); + if (saveInherited) { + saveInherits(stream); + } + saveModels(stream, saveInherited); + saveAppearanceModels(stream, saveInherited); } Material& Material::operator=(const Material& other) @@ -888,12 +1301,14 @@ Material& Material::operator=(const Material& other) _directory = other._directory; _uuid = other._uuid; _name = other._name; - _authorAndLicense = other._authorAndLicense; + _author = other._author; + _license = other._license; _parentUuid = other._parentUuid; _description = other._description; _url = other._url; _reference = other._reference; _dereferenced = other._dereferenced; + _editState = other._editState; _tags.clear(); for (auto it = other._tags.begin(); it != other._tags.end(); it++) { @@ -911,14 +1326,92 @@ Material& Material::operator=(const Material& other) for (auto it = other._allUuids.begin(); it != other._allUuids.end(); it++) { _allUuids.push_back(*it); } + + // Create copies of the properties rather than modify the originals _physical.clear(); for (auto it = other._physical.begin(); it != other._physical.end(); it++) { - _physical[it->first] = MaterialProperty(it->second); + MaterialProperty prop = it->second; + _physical[it->first] = std::make_shared(prop); } _appearance.clear(); for (auto it = other._appearance.begin(); it != other._appearance.end(); it++) { - _appearance[it->first] = MaterialProperty(it->second); + MaterialProperty prop = it->second; + _appearance[it->first] = std::make_shared(prop); } return *this; } + +/* + * Normalize models by removing any inherited models + */ +QStringList Material::normalizeModels(const QStringList& models) +{ + QStringList normalized; + + ModelManager manager; + + for (auto uuid : models) { + auto model = manager.getModel(uuid); + + bool found = false; + for (auto childUuid : models) { + if (uuid != childUuid) { + auto childModel = manager.getModel(childUuid); + if (childModel->inherits(childUuid)) { + // We're an inherited model + found = true; + break; + } + } + } + if (!found) { + normalized << uuid; + } + } + + return normalized; +} + +/* + * Set or change the base material for the current material, updating the properties as + * required. + */ +void Material::updateInheritance(const QString& parent) +{} + +/* + * Return a list of models that are defined in the parent material but not in this one + */ +QStringList Material::inheritedMissingModels(const Material& parent) +{ + QStringList missing; + for (auto uuid : parent._allUuids) { + if (!hasModel(uuid)) { + missing << uuid; + } + } + + return normalizeModels(missing); +} + +/* + * Return a list of models that are defined in this model but not the parent + */ +QStringList Material::inheritedAddedModels(const Material& parent) +{ + QStringList added; + for (auto uuid : _allUuids) { + if (!parent.hasModel(uuid)) { + added << uuid; + } + } + + return normalizeModels(added); +} + +/* + * Return a list of properties that have different values from the parent material + */ +void Material::inheritedPropertyDiff(const QString& parent) +{} diff --git a/src/Mod/Material/App/Materials.h b/src/Mod/Material/App/Materials.h index a4ff89cd44..c0b8cf7769 100644 --- a/src/Mod/Material/App/Materials.h +++ b/src/Mod/Material/App/Materials.h @@ -22,31 +22,34 @@ #ifndef MATERIAL_MATERIALS_H #define MATERIAL_MATERIALS_H -#include +#include -#include #include #include +#include #include #include +#include + +#include -#include "MaterialLibrary.h" #include "Model.h" -namespace fs = boost::filesystem; - namespace Materials { +class MaterialLibrary; + class MaterialsExport MaterialProperty: public ModelProperty { TYPESYSTEM_HEADER_WITH_OVERRIDE(); public: MaterialProperty(); - explicit MaterialProperty(const ModelProperty& property); - explicit MaterialProperty(const MaterialProperty& property); + MaterialProperty(const ModelProperty& property); + MaterialProperty(const MaterialProperty& property); + MaterialProperty(std::shared_ptr property); ~MaterialProperty() override = default; MaterialValue::ValueType getType() const @@ -63,6 +66,7 @@ public: std::shared_ptr getMaterialValue(); const std::shared_ptr getMaterialValue() const; const QString getString() const; + const QString getYAMLString() const; bool getBoolean() const; int getInt() const; double getFloat() const; @@ -79,6 +83,7 @@ public: void setPropertyType(const QString& type) override; void setValue(const QVariant& value); void setValue(const QString& value); + void setValue(std::shared_ptr value); void setString(const QString& value); void setBoolean(bool value); void setBoolean(int value); @@ -93,10 +98,23 @@ public: void setURL(const QString& value); MaterialProperty& operator=(const MaterialProperty& other); + friend QTextStream& operator<<(QTextStream& output, const MaterialProperty& property) + { + output << property.getName() << ": " << property.getYAMLString(); + return output; + } + bool operator==(const MaterialProperty& other) const; + bool operator!=(const MaterialProperty& other) const + { + return !operator==(other); + } + + // void save(QTextStream& stream); protected: void setType(const QString& type); // void setType(MaterialValue::ValueType type) { _valueType = type; } + void copyValuePtr(std::shared_ptr value); void addColumn(MaterialProperty& column) { @@ -122,14 +140,14 @@ public: }; Material(); - explicit Material(const MaterialLibrary& library, - const QString& directory, - const QString& uuid, - const QString& name); - explicit Material(const Material& other); - virtual ~Material(); + Material(std::shared_ptr library, + const QString& directory, + const QString& uuid, + const QString& name); + Material(const Material& other); + ~Material() override = default; - const MaterialLibrary& getLibrary() const + std::shared_ptr getLibrary() const { return _library; } @@ -145,9 +163,14 @@ public: { return _name; } - const QString getAuthorAndLicense() const + const QString getAuthorAndLicense() const; + const QString getAuthor() const { - return _authorAndLicense; + return _author; + } + const QString getLicense() const + { + return _license; } const QString getParentUUID() const { @@ -169,56 +192,39 @@ public: { return _editState; } - const std::list& getTags() const + const QStringList& getTags() const { return _tags; } - const std::vector* getPhysicalModels() const + const QStringList* getPhysicalModels() const { return &_physicalUuids; } - const std::vector* getAppearanceModels() const + const QStringList* getAppearanceModels() const { return &_appearanceUuids; } - void setLibrary(const MaterialLibrary& library) + void setLibrary(std::shared_ptr library) { _library = library; } void setDirectory(const QString& directory) { - Base::Console().Log("Materials::setDirectory(%s)\n", directory.toStdString().c_str()); _directory = directory; } void setUUID(const QString& uuid) { _uuid = uuid; } - void setName(const QString& name) - { - _name = name; - } - void setAuthorAndLicense(const QString& authorAndLicense) - { - _authorAndLicense = authorAndLicense; - } - void setParentUUID(const QString& uuid) - { - _parentUuid = uuid; - } - void setDescription(const QString& description) - { - _description = description; - } - void setURL(const QString& url) - { - _url = url; - } - void setReference(const QString& reference) - { - _reference = reference; - } + void setName(const QString& name); + void setAuthor(const QString& author); + void setLicense(const QString& license); + void setParentUUID(const QString& uuid); + void setDescription(const QString& description); + void setURL(const QString& url); + void setReference(const QString& reference); + void setEditState(ModelEdit newState); void setEditStateAlter() { @@ -228,6 +234,7 @@ public: { setEditState(ModelEdit_Extend); } + void setPropertyEditState(const QString& name); void setPhysicalEditState(const QString& name); void setAppearanceEditState(const QString& name); void resetEditState() @@ -243,23 +250,30 @@ public: Q_UNUSED(tag); } void addPhysical(const QString& uuid); + void removePhysical(const QString& uuid); void addAppearance(const QString& uuid); + void removeAppearance(const QString& uuid); + void clearModels(); void newUuid(); void setPhysicalValue(const QString& name, const QString& value); void setPhysicalValue(const QString& name, int value); void setPhysicalValue(const QString& name, double value); void setPhysicalValue(const QString& name, const Base::Quantity value); + void setPhysicalValue(const QString& name, std::shared_ptr value); void setAppearanceValue(const QString& name, const QString& value); + void setAppearanceValue(const QString& name, std::shared_ptr value); - MaterialProperty& getPhysicalProperty(const QString& name); - const MaterialProperty& getPhysicalProperty(const QString& name) const; - MaterialProperty& getAppearanceProperty(const QString& name); - const MaterialProperty& getAppearanceProperty(const QString& name) const; + std::shared_ptr getPhysicalProperty(const QString& name); + const std::shared_ptr getPhysicalProperty(const QString& name) const; + std::shared_ptr getAppearanceProperty(const QString& name); + const std::shared_ptr getAppearanceProperty(const QString& name) const; const QVariant getPhysicalValue(const QString& name) const; + const Base::Quantity getPhysicalQuantity(const QString& name) const; const QString getPhysicalValueString(const QString& name) const; const QVariant getAppearanceValue(const QString& name) const; + const Base::Quantity getAppearanceQuantity(const QString& name) const; const QString getAppearanceValueString(const QString& name) const; bool hasPhysicalProperty(const QString& name) const; bool hasAppearanceProperty(const QString& name) const; @@ -275,15 +289,17 @@ public: bool isPhysicalModelComplete(const QString& uuid) const; bool isAppearanceModelComplete(const QString& uuid) const; - const std::map& getPhysicalProperties() const + std::map>& getPhysicalProperties() { return _physical; } - const std::map& getAppearanceProperties() const + std::map>& getAppearanceProperties() { return _appearance; } + QString getModelByName(const QString& name) const; + bool getDereferenced() const { return _dereferenced; @@ -293,45 +309,80 @@ public: _dereferenced = true; } - void save(QTextStream& stream, bool saveAsCopy); + /* + * Normalize models by removing any inherited models + */ + QStringList normalizeModels(const QStringList& models); + + /* + * Set or change the base material for the current material, updating the properties as + * required. + */ + void updateInheritance(const QString& parent); + /* + * Return a list of models that are defined in the parent material but not in this one + */ + QStringList inheritedMissingModels(const Material& parent); + /* + * Return a list of models that are defined in this model but not the parent + */ + QStringList inheritedAddedModels(const Material& parent); + /* + * Return a list of properties that have different values from the parent material + */ + void inheritedPropertyDiff(const QString& parent); + + void save(QTextStream& stream, bool saveAsCopy, bool saveInherited); Material& operator=(const Material& other); protected: void addModel(const QString& uuid); + void removeModel(const QString& uuid); + void removeUUID(QStringList& uuidList, const QString& uuid); - const QVariant getValue(const std::map& propertyList, - const QString& name) const; - const QString getValueString(const std::map& propertyList, - const QString& name) const; + const QVariant + getValue(const std::map>& propertyList, + const QString& name) const; + const QString + getValueString(const std::map>& propertyList, + const QString& name) const; + bool modelChanged(const std::shared_ptr parent, + const std::shared_ptr model) const; + bool modelAppearanceChanged(const std::shared_ptr parent, + const std::shared_ptr model) const; void saveGeneral(QTextStream& stream) const; void saveInherits(QTextStream& stream) const; - void saveModels(QTextStream& stream) const; - void saveAppearanceModels(QTextStream& stream) const; + void saveModels(QTextStream& stream, bool saveInherited) const; + void saveAppearanceModels(QTextStream& stream, bool saveInherited) const; private: - MaterialLibrary _library; + std::shared_ptr _library; QString _directory; QString _uuid; QString _name; - QString _authorAndLicense; + QString _author; + QString _license; QString _parentUuid; QString _description; QString _url; QString _reference; - std::list _tags; - std::vector _physicalUuids; - std::vector _appearanceUuids; - std::vector _allUuids; // Includes inherited models - std::map _physical; - std::map _appearance; + QStringList _tags; + QStringList _physicalUuids; + QStringList _appearanceUuids; + QStringList _allUuids; // Includes inherited models + std::map> _physical; + std::map> _appearance; bool _dereferenced; ModelEdit _editState; }; +typedef FolderTreeNode MaterialTreeNode; + } // namespace Materials Q_DECLARE_METATYPE(Materials::Material*) +Q_DECLARE_METATYPE(std::shared_ptr) #endif // MATERIAL_MATERIALS_H diff --git a/src/Mod/Material/App/Model.cpp b/src/Mod/Material/App/Model.cpp index 87020a96fa..c9b95e85f8 100644 --- a/src/Mod/Material/App/Model.cpp +++ b/src/Mod/Material/App/Model.cpp @@ -23,10 +23,13 @@ #ifndef _PreComp_ #endif +#include + +#include + #include "Exceptions.h" #include "Model.h" #include "ModelLibrary.h" -#include using namespace Materials; @@ -81,12 +84,27 @@ ModelProperty& ModelProperty::operator=(const ModelProperty& other) return *this; } +bool ModelProperty::operator==(const ModelProperty& other) const +{ + if (this == &other) { + return true; + } + + if (&other == nullptr) { + return false; + } + + return (_name == other._name) && (_propertyType == other._propertyType) + && (_units == other._units) && (_url == other._url) && (_description == other._description) + && (_inheritance == other._inheritance); +} + TYPESYSTEM_SOURCE(Materials::Model, Base::BaseClass) Model::Model() {} -Model::Model(const ModelLibrary& library, +Model::Model(std::shared_ptr library, ModelType type, const QString& name, const QString& directory, diff --git a/src/Mod/Material/App/Model.h b/src/Mod/Material/App/Model.h index c286ffeb0c..fcf83efd47 100644 --- a/src/Mod/Material/App/Model.h +++ b/src/Mod/Material/App/Model.h @@ -22,31 +22,45 @@ #ifndef MATERIAL_MODEL_H #define MATERIAL_MODEL_H -#include +#include + +#include +#include +#include #include #include -#include -#include +#include + +#include "FolderTree.h" #include "MaterialValue.h" -#include "ModelLibrary.h" +// #include "ModelLibrary.h" namespace Materials { +class ModelLibrary; + +enum ModelFilter +{ + ModelFilter_None, + ModelFilter_Physical, + ModelFilter_Appearance +}; + class MaterialsExport ModelProperty: public Base::BaseClass { TYPESYSTEM_HEADER_WITH_OVERRIDE(); public: ModelProperty(); - explicit ModelProperty(const QString& name, - const QString& type, - const QString& units, - const QString& url, - const QString& description); - explicit ModelProperty(const ModelProperty& other); + ModelProperty(const QString& name, + const QString& type, + const QString& units, + const QString& url, + const QString& description); + ModelProperty(const ModelProperty& other); ~ModelProperty() override = default; const QString getName() const @@ -117,6 +131,11 @@ public: } ModelProperty& operator=(const ModelProperty& other); + bool operator==(const ModelProperty& other) const; + bool operator!=(const ModelProperty& other) const + { + return !operator==(other); + } private: QString _name; @@ -140,17 +159,17 @@ public: }; Model(); - explicit Model(const ModelLibrary& library, - ModelType type, - const QString& name, - const QString& directory, - const QString& uuid, - const QString& description, - const QString& url, - const QString& doi); + Model(std::shared_ptr library, + ModelType type, + const QString& name, + const QString& directory, + const QString& uuid, + const QString& description, + const QString& url, + const QString& doi); ~Model() override = default; - const ModelLibrary& getLibrary() const + std::shared_ptr getLibrary() const { return _library; } @@ -175,10 +194,10 @@ public: { return QDir(_directory).absolutePath(); } - const QString getRelativePath() const - { - return QDir(_directory).relativeFilePath(QDir(_directory).absolutePath()); - } + // const QString getRelativePath() const + // { + // return QDir(_directory).relativeFilePath(QDir(_directory).absolutePath()); + // } const QString getUUID() const { return _uuid; @@ -196,7 +215,7 @@ public: return _doi; } - void setLibrary(const ModelLibrary& library) + void setLibrary(std::shared_ptr library) { _library = library; } @@ -231,12 +250,16 @@ public: void addInheritance(const QString& uuid) { - _inheritedUuids.push_back(uuid); + _inheritedUuids << uuid; } - const std::vector& getInheritance() const + const QStringList& getInheritance() const { return _inheritedUuids; } + bool inherits(const QString& uuid) const + { + return _inheritedUuids.contains(uuid); + } bool operator==(const Model& m) const { @@ -281,7 +304,7 @@ public: } private: - ModelLibrary _library; + std::shared_ptr _library; ModelType _type; QString _name; QString _directory; @@ -289,10 +312,12 @@ private: QString _description; QString _url; QString _doi; - std::vector _inheritedUuids; + QStringList _inheritedUuids; std::map _properties; }; +typedef FolderTreeNode ModelTreeNode; + } // namespace Materials #endif // MATERIAL_MODEL_H diff --git a/src/Mod/Material/App/ModelLibrary.cpp b/src/Mod/Material/App/ModelLibrary.cpp index 901795bd30..7f866db939 100644 --- a/src/Mod/Material/App/ModelLibrary.cpp +++ b/src/Mod/Material/App/ModelLibrary.cpp @@ -30,6 +30,7 @@ #include "Exceptions.h" #include "Model.h" #include "ModelLibrary.h" +#include "ModelManager.h" using namespace Materials; @@ -66,6 +67,15 @@ QString LibraryBase::getLocalPath(const QString& path) const return filePath; } +bool LibraryBase::isRoot(const QString& path) const +{ + QString localPath = getLocalPath(path); + QString cleanPath = getLocalPath(QString::fromStdString("")); + std::string pLocal = localPath.toStdString(); + std::string pclean = cleanPath.toStdString(); + return (cleanPath == localPath); +} + QString LibraryBase::getRelativePath(const QString& path) const { QString filePath; @@ -97,17 +107,80 @@ TYPESYSTEM_SOURCE(Materials::ModelLibrary, LibraryBase) ModelLibrary::ModelLibrary(const QString& libraryName, const QString& dir, const QString& icon) : LibraryBase(libraryName, dir, icon) -{} +{ + _modelPathMap = std::make_unique>>(); +} ModelLibrary::ModelLibrary() -{} +{ + _modelPathMap = std::make_unique>>(); +} -Model* ModelLibrary::addModel(const Model& model, const QString& path) +std::shared_ptr ModelLibrary::getModelByPath(const QString& path) const { QString filePath = getRelativePath(path); - Model* newModel = new Model(model); - newModel->setLibrary(*this); + try { + std::shared_ptr model = _modelPathMap->at(filePath); + return model; + } + catch (std::out_of_range& e) { + throw ModelNotFound(); + } +} + +std::shared_ptr ModelLibrary::addModel(const Model& model, const QString& path) +{ + QString filePath = getRelativePath(path); + std::shared_ptr newModel = std::make_shared(model); + newModel->setLibrary(getptr()); newModel->setDirectory(filePath); + (*_modelPathMap)[filePath] = newModel; + return newModel; } + +std::shared_ptr>> +ModelLibrary::getModelTree(ModelFilter filter) const +{ + std::shared_ptr>> modelTree = + std::make_shared>>(); + + for (auto it = _modelPathMap->begin(); it != _modelPathMap->end(); it++) { + auto filename = it->first; + auto model = it->second; + + if (ModelManager::passFilter(filter, model->getType())) { + // Base::Console().Log("Relative path '%s'\n\t", filename.toStdString().c_str()); + QStringList list = filename.split(QString::fromStdString("/")); + + // Start at the root + std::shared_ptr>> node = modelTree; + for (auto itp = list.begin(); itp != list.end(); itp++) { + // Base::Console().Log("\t%s", itp->toStdString().c_str()); + if (ModelManager::isModel(*itp)) { + std::shared_ptr child = std::make_shared(); + child->setData(model); + (*node)[*itp] = child; + } + else { + // Add the folder only if it's not already there + if (node->count(*itp) == 0) { + auto mapPtr = + std::make_shared>>(); + std::shared_ptr child = std::make_shared(); + child->setFolder(mapPtr); + (*node)[*itp] = child; + node = mapPtr; + } + else { + node = (*node)[*itp]->getFolder(); + } + } + } + // Base::Console().Log("\n"); + } + } + + return modelTree; +} diff --git a/src/Mod/Material/App/ModelLibrary.h b/src/Mod/Material/App/ModelLibrary.h index ea42aa6d9a..8b9fa8b004 100644 --- a/src/Mod/Material/App/ModelLibrary.h +++ b/src/Mod/Material/App/ModelLibrary.h @@ -22,27 +22,30 @@ #ifndef MATERIAL_MODELLIBRARY_H #define MATERIAL_MODELLIBRARY_H -#include +#include -#include -#include #include #include -#include "MaterialValue.h" +#include +#include +#include + +#include "MaterialValue.h" +#include "Model.h" namespace Materials { -class Model; +// class Model; class MaterialsExport LibraryBase: public Base::BaseClass { - TYPESYSTEM_HEADER_WITH_OVERRIDE(); + TYPESYSTEM_HEADER(); public: LibraryBase(); - explicit LibraryBase(const QString& libraryName, const QString& dir, const QString& icon); + LibraryBase(const QString& libraryName, const QString& dir, const QString& icon); ~LibraryBase() override = default; const QString getName() const @@ -68,20 +71,24 @@ public: } QString getLocalPath(const QString& path) const; QString getRelativePath(const QString& path) const; + bool isRoot(const QString& path) const; private: + LibraryBase(const LibraryBase&); + QString _name; QString _directory; QString _iconPath; }; -class MaterialsExport ModelLibrary: public LibraryBase +class MaterialsExport ModelLibrary: public LibraryBase, + public std::enable_shared_from_this { - TYPESYSTEM_HEADER_WITH_OVERRIDE(); + TYPESYSTEM_HEADER(); public: ModelLibrary(); - explicit ModelLibrary(const QString& libraryName, const QString& dir, const QString& icon); + ModelLibrary(const QString& libraryName, const QString& dir, const QString& icon); ~ModelLibrary() override = default; bool operator==(const ModelLibrary& library) const @@ -92,8 +99,22 @@ public: { return !operator==(library); } + std::shared_ptr getModelByPath(const QString& path) const; - Model* addModel(const Model& model, const QString& path); + std::shared_ptr addModel(const Model& model, const QString& path); + + // Use this to get a shared_ptr for *this + std::shared_ptr getptr() + { + return shared_from_this(); + } + std::shared_ptr>> + getModelTree(ModelFilter filter) const; + +private: + ModelLibrary(const ModelLibrary&); + + std::unique_ptr>> _modelPathMap; }; } // namespace Materials diff --git a/src/Mod/Material/App/ModelLoader.cpp b/src/Mod/Material/App/ModelLoader.cpp index 0357b2b27e..b8e9ad582f 100644 --- a/src/Mod/Material/App/ModelLoader.cpp +++ b/src/Mod/Material/App/ModelLoader.cpp @@ -37,7 +37,7 @@ using namespace Materials; -ModelEntry::ModelEntry(const ModelLibrary& library, +ModelEntry::ModelEntry(std::shared_ptr library, const QString& baseName, const QString& modelName, const QString& dir, @@ -52,17 +52,18 @@ ModelEntry::ModelEntry(const ModelLibrary& library, , _dereferenced(false) {} -std::unique_ptr> ModelLoader::_modelEntryMap = nullptr; +std::unique_ptr>> ModelLoader::_modelEntryMap = + nullptr; -ModelLoader::ModelLoader(std::shared_ptr> modelMap, - std::shared_ptr> libraryList) +ModelLoader::ModelLoader(std::shared_ptr>> modelMap, + std::shared_ptr>> libraryList) : _modelMap(modelMap) , _libraryList(libraryList) { loadLibraries(); } -void ModelLoader::addLibrary(ModelLibrary* model) +void ModelLoader::addLibrary(std::shared_ptr model) { _libraryList->push_back(model); } @@ -84,12 +85,13 @@ const QString ModelLoader::getUUIDFromPath(const QString& path) const QString uuid = QString::fromStdString(yamlroot[base]["UUID"].as()); return uuid; } - catch (YAML::Exception&) { + catch (YAML::Exception& ex) { throw ModelNotFound(); } } -ModelEntry* ModelLoader::getModelFromPath(const ModelLibrary& library, const QString& path) const +std::shared_ptr ModelLoader::getModelFromPath(std::shared_ptr library, + const QString& path) const { QFile file(path); if (!file.exists()) { @@ -113,12 +115,12 @@ ModelEntry* ModelLoader::getModelFromPath(const ModelLibrary& library, const QSt throw InvalidModel(); } - ModelEntry* model = new ModelEntry(library, - QString::fromStdString(base), - QString::fromStdString(name), - path, - QString::fromStdString(uuid), - yamlroot); + std::shared_ptr model = std::make_shared(library, + QString::fromStdString(base), + QString::fromStdString(name), + path, + QString::fromStdString(uuid), + yamlroot); return model; } @@ -133,8 +135,8 @@ void ModelLoader::showYaml(const YAML::Node& yaml) const } void ModelLoader::dereference(const QString& uuid, - ModelEntry* parent, - const ModelEntry* child, + std::shared_ptr parent, + std::shared_ptr child, std::map, QString>* inheritances) { auto parentPtr = parent->getModelPtr(); @@ -168,7 +170,7 @@ void ModelLoader::dereference(const QString& uuid, } -void ModelLoader::dereference(ModelEntry* model, +void ModelLoader::dereference(std::shared_ptr model, std::map, QString>* inheritances) { // Avoid recursion @@ -185,10 +187,10 @@ void ModelLoader::dereference(ModelEntry* model, // This requires that all models have already been loaded undereferenced try { - const ModelEntry* child = (*_modelEntryMap)[nodeName]; + std::shared_ptr child = (*_modelEntryMap)[nodeName]; dereference(model->getUUID(), model, child, inheritances); } - catch (const std::out_of_range&) { + catch (const std::out_of_range& oor) { Base::Console().Log("Unable to find '%s' in model map\n", nodeName.toStdString().c_str()); } @@ -208,7 +210,7 @@ QString ModelLoader::yamlValue(const YAML::Node& node, return QString::fromStdString(defaultValue); } -void ModelLoader::addToTree(ModelEntry* model, +void ModelLoader::addToTree(std::shared_ptr model, std::map, QString>* inheritances) { std::set exclude; @@ -268,12 +270,12 @@ void ModelLoader::addToTree(ModelEntry* model, if (propType == QString::fromStdString("2DArray") || propType == QString::fromStdString("3DArray")) { - Base::Console().Log("Reading columns\n"); + // Base::Console().Log("Reading columns\n"); // Read the columns auto cols = yamlProp["Columns"]; for (auto col : cols) { std::string colName = col.first.as(); - Base::Console().Log("\tColumns '%s'\n", colName.c_str()); + // Base::Console().Log("\tColumns '%s'\n", colName.c_str()); auto colProp = cols[colName]; auto colPropType = yamlValue(colProp, "Type", ""); @@ -299,16 +301,16 @@ void ModelLoader::addToTree(ModelEntry* model, } } - (*_modelMap)[uuid] = library.addModel(*finalModel, directory); + (*_modelMap)[uuid] = library->addModel(*finalModel, directory); } -void ModelLoader::loadLibrary(const ModelLibrary& library) +void ModelLoader::loadLibrary(std::shared_ptr library) { if (_modelEntryMap == nullptr) { - _modelEntryMap = std::make_unique>(); + _modelEntryMap = std::make_unique>>(); } - QDirIterator it(library.getDirectory(), QDirIterator::Subdirectories); + QDirIterator it(library->getDirectory(), QDirIterator::Subdirectories); while (it.hasNext()) { auto pathname = it.next(); QFileInfo file(pathname); @@ -345,7 +347,7 @@ void ModelLoader::loadLibraries() getModelLibraries(); if (_libraryList) { for (auto it = _libraryList->begin(); it != _libraryList->end(); it++) { - loadLibrary(**it); + loadLibrary(*it); } } } @@ -362,9 +364,10 @@ void ModelLoader::getModelLibraries() if (useBuiltInMaterials) { QString resourceDir = QString::fromStdString(App::Application::getResourceDir() + "/Mod/Material/Resources/Models"); - auto libData = new ModelLibrary(QString::fromStdString("System"), - resourceDir, - QString::fromStdString(":/icons/freecad.svg")); + auto libData = + std::make_shared(QString::fromStdString("System"), + resourceDir, + QString::fromStdString(":/icons/freecad.svg")); _libraryList->push_back(libData); } @@ -380,7 +383,7 @@ void ModelLoader::getModelLibraries() if (modelDir.length() > 0) { QDir dir(modelDir); if (dir.exists()) { - auto libData = new ModelLibrary(moduleName, modelDir, modelIcon); + auto libData = std::make_shared(moduleName, modelDir, modelIcon); _libraryList->push_back(libData); } } @@ -393,10 +396,10 @@ void ModelLoader::getModelLibraries() if (!resourceDir.isEmpty()) { QDir materialDir(resourceDir); if (materialDir.exists()) { - auto libData = - new ModelLibrary(QString::fromStdString("User"), - resourceDir, - QString::fromStdString(":/icons/preferences-general.svg")); + auto libData = std::make_shared( + QString::fromStdString("User"), + resourceDir, + QString::fromStdString(":/icons/preferences-general.svg")); _libraryList->push_back(libData); } } @@ -407,9 +410,10 @@ void ModelLoader::getModelLibraries() if (!resourceDir.isEmpty()) { QDir materialDir(resourceDir); if (materialDir.exists()) { - auto libData = new ModelLibrary(QString::fromStdString("Custom"), - resourceDir, - QString::fromStdString(":/icons/user.svg")); + auto libData = + std::make_shared(QString::fromStdString("Custom"), + resourceDir, + QString::fromStdString(":/icons/user.svg")); _libraryList->push_back(libData); } } diff --git a/src/Mod/Material/App/ModelLoader.h b/src/Mod/Material/App/ModelLoader.h index b843b9e1fb..9db76092b3 100644 --- a/src/Mod/Material/App/ModelLoader.h +++ b/src/Mod/Material/App/ModelLoader.h @@ -22,6 +22,8 @@ #ifndef MATERIAL_MODELLOADER_H #define MATERIAL_MODELLOADER_H +#include + #include #include #include @@ -34,15 +36,15 @@ namespace Materials class ModelEntry { public: - explicit ModelEntry(const ModelLibrary& library, - const QString& baseName, - const QString& modelName, - const QString& dir, - const QString& modelUuid, - const YAML::Node& modelData); + ModelEntry(std::shared_ptr library, + const QString& baseName, + const QString& modelName, + const QString& dir, + const QString& modelUuid, + const YAML::Node& modelData); virtual ~ModelEntry() = default; - const ModelLibrary& getLibrary() const + std::shared_ptr getLibrary() const { return _library; } @@ -83,7 +85,7 @@ public: private: ModelEntry(); - ModelLibrary _library; + std::shared_ptr _library; QString _base; QString _name; QString _directory; @@ -95,8 +97,8 @@ private: class ModelLoader { public: - explicit ModelLoader(std::shared_ptr> modelMap, - std::shared_ptr> libraryList); + ModelLoader(std::shared_ptr>> modelMap, + std::shared_ptr>> libraryList); virtual ~ModelLoader() = default; static const QString getUUIDFromPath(const QString& path); @@ -107,21 +109,24 @@ private: void getModelLibraries(); QString yamlValue(const YAML::Node& node, const std::string& key, const std::string& defaultValue); - void addToTree(ModelEntry* model, std::map, QString>* inheritances); + void addToTree(std::shared_ptr model, + std::map, QString>* inheritances); void showYaml(const YAML::Node& yaml) const; void dereference(const QString& uuid, - ModelEntry* parent, - const ModelEntry* child, + std::shared_ptr parent, + std::shared_ptr child, std::map, QString>* inheritances); - void dereference(ModelEntry* model, + void dereference(std::shared_ptr model, std::map, QString>* inheritances); - ModelEntry* getModelFromPath(const ModelLibrary& library, const QString& path) const; - void addLibrary(ModelLibrary* model); - void loadLibrary(const ModelLibrary& library); + std::shared_ptr getModelFromPath(std::shared_ptr library, + const QString& path) const; + void addLibrary(std::shared_ptr model); + void loadLibrary(std::shared_ptr library); void loadLibraries(); - static std::unique_ptr> _modelEntryMap; - std::shared_ptr> _modelMap; - std::shared_ptr> _libraryList; + + static std::unique_ptr>> _modelEntryMap; + std::shared_ptr>> _modelMap; + std::shared_ptr>> _libraryList; }; } // namespace Materials diff --git a/src/Mod/Material/App/ModelManager.cpp b/src/Mod/Material/App/ModelManager.cpp index 2900fdde55..88d4e85012 100644 --- a/src/Mod/Material/App/ModelManager.cpp +++ b/src/Mod/Material/App/ModelManager.cpp @@ -23,6 +23,7 @@ #ifndef _PreComp_ #endif +#include #include #include @@ -34,8 +35,8 @@ using namespace Materials; -std::shared_ptr> ModelManager::_libraryList = nullptr; -std::shared_ptr> ModelManager::_modelMap = nullptr; +std::shared_ptr>> ModelManager::_libraryList = nullptr; +std::shared_ptr>> ModelManager::_modelMap = nullptr; QMutex ModelManager::_mutex; TYPESYSTEM_SOURCE(Materials::ModelManager, Base::BaseClass) @@ -50,9 +51,9 @@ void ModelManager::initLibraries() QMutexLocker locker(&_mutex); if (_modelMap == nullptr) { - _modelMap = std::make_shared>(); + _modelMap = std::make_shared>>(); if (_libraryList == nullptr) { - _libraryList = std::make_shared>(); + _libraryList = std::make_shared>>(); } // Load the libraries @@ -60,12 +61,12 @@ void ModelManager::initLibraries() } } -bool ModelManager::isModel(const fs::path& p) +bool ModelManager::isModel(const QString& file) { // if (!fs::is_regular_file(p)) // return false; // check file extension - if (p.extension() == ".yml") { + if (file.endsWith(QString::fromStdString(".yml"))) { return true; } return false; @@ -80,36 +81,62 @@ void ModelManager::refresh() ModelLoader loader(_modelMap, _libraryList); } -const Model& ModelManager::getModel(const QString& uuid) const +std::shared_ptr ModelManager::getModel(const QString& uuid) const { try { if (_modelMap == nullptr) { throw Uninitialized(); } - return *(_modelMap->at(uuid)); + return _modelMap->at(uuid); } catch (std::out_of_range const&) { throw ModelNotFound(); } } -const Model& ModelManager::getModelByPath(const QString& path) const +std::shared_ptr ModelManager::getModelByPath(const QString& path) const { - const QString& uuid = ModelLoader::getUUIDFromPath(path); - const Model& model = getModel(uuid); + QString cleanPath = QDir::cleanPath(path); - return model; + for (auto library : *_libraryList) { + // Base::Console().Log("ModelManager::getModelByPath() Checking library '%s'->'%s'\n", + // library->getName().toStdString().c_str(), + // library->getDirectory().toStdString().c_str()); + + + if (cleanPath.startsWith(library->getDirectory())) { + // Base::Console().Log("ModelManager::getModelByPath() Library '%s'\n", + // library->getDirectory().toStdString().c_str()); + // Base::Console().Log("ModelManager::getModelByPath() Path '%s'\n", + // cleanPath.toStdString().c_str()); + return library->getModelByPath(cleanPath); + } + } + Base::Console().Log("ModelManager::getModelByPath() Library not found for path '%s'\n", + cleanPath.toStdString().c_str()); + + throw MaterialNotFound(); } -const Model& ModelManager::getModelByPath(const QString& path, const QString& libraryPath) const +std::shared_ptr ModelManager::getModelByPath(const QString& path, const QString& lib) const { - QDir modelDir(QDir::cleanPath(libraryPath + QString::fromStdString("/") + path)); - QString absPath = modelDir.absolutePath(); - return getModelByPath(absPath); + auto library = getLibrary(lib); // May throw LibraryNotFound + return library->getModelByPath(path); // May throw ModelNotFound } -bool ModelManager::passFilter(ModelFilter filter, Model::ModelType modelType) const +std::shared_ptr ModelManager::getLibrary(const QString& name) const +{ + for (auto library : *_libraryList) { + if (library->getName() == name) { + return library; + } + } + + throw LibraryNotFound(); +} + +bool ModelManager::passFilter(ModelFilter filter, Model::ModelType modelType) { switch (filter) { case ModelFilter_None: @@ -124,49 +151,3 @@ bool ModelManager::passFilter(ModelFilter filter, Model::ModelType modelType) co return false; } - -std::shared_ptr> -ModelManager::getModelTree(const ModelLibrary& library, ModelFilter filter) const -{ - std::shared_ptr> modelTree = - std::make_shared>(); - - for (auto it = _modelMap->begin(); it != _modelMap->end(); it++) { - auto filename = it->first; - auto model = it->second; - - if (model->getLibrary() == library && passFilter(filter, model->getType())) { - fs::path path = model->getDirectory().toStdString(); - Base::Console().Log("Relative path '%s'\n\t", path.string().c_str()); - - // Start at the root - std::shared_ptr> node = modelTree; - for (auto itp = path.begin(); itp != path.end(); itp++) { - if (isModel(itp->string())) { - ModelTreeNode* child = new ModelTreeNode(); - child->setData(model); - (*node)[QString::fromStdString(itp->string())] = child; - } - else { - // Add the folder only if it's not already there - QString folderName = QString::fromStdString(itp->string()); - std::shared_ptr> mapPtr; - if (node->count(QString::fromStdString(itp->string())) == 0) { - mapPtr = std::make_shared>(); - ModelTreeNode* child = new ModelTreeNode(); - child->setFolder(mapPtr); - (*node)[QString::fromStdString(itp->string())] = child; - node = mapPtr; - } - else { - node = (*node)[QString::fromStdString(itp->string())]->getFolder(); - } - } - Base::Console().Log("'%s' ", itp->string().c_str()); - } - Base::Console().Log("\n"); - } - } - - return modelTree; -} diff --git a/src/Mod/Material/App/ModelManager.h b/src/Mod/Material/App/ModelManager.h index 5a5eed39ba..a1954d3419 100644 --- a/src/Mod/Material/App/ModelManager.h +++ b/src/Mod/Material/App/ModelManager.h @@ -22,62 +22,57 @@ #ifndef MATERIAL_MODELMANAGER_H #define MATERIAL_MODELMANAGER_H +#include + #include #include -#include - #include "Exceptions.h" #include "FolderTree.h" #include "Model.h" +#include "ModelLibrary.h" -namespace fs = boost::filesystem; namespace Materials { -typedef FolderTreeNode ModelTreeNode; - class MaterialsExport ModelManager: public Base::BaseClass { - TYPESYSTEM_HEADER_WITH_OVERRIDE(); + TYPESYSTEM_HEADER(); public: - enum ModelFilter - { - ModelFilter_None, - ModelFilter_Physical, - ModelFilter_Appearance - }; - ModelManager(); ~ModelManager() override = default; void refresh(); - std::shared_ptr> getModelLibraries() + std::shared_ptr>> getModelLibraries() { return _libraryList; } - std::shared_ptr> getModels() + std::shared_ptr>> getModels() { return _modelMap; } - std::shared_ptr> - getModelTree(const ModelLibrary& library, ModelFilter filter = ModelFilter_None) const; - const Model& getModel(const QString& uuid) const; - const Model& getModelByPath(const QString& path) const; - const Model& getModelByPath(const QString& path, const QString& libraryPath) const; + std::shared_ptr>> + getModelTree(std::shared_ptr library, ModelFilter filter = ModelFilter_None) const + { + return library->getModelTree(filter); + } + std::shared_ptr getModel(const QString& uuid) const; + std::shared_ptr getModelByPath(const QString& path) const; + std::shared_ptr getModelByPath(const QString& path, const QString& lib) const; + std::shared_ptr getLibrary(const QString& name) const; - static bool isModel(const fs::path& p); - bool passFilter(ModelFilter filter, Model::ModelType modelType) const; + static bool isModel(const QString& file); + static bool passFilter(ModelFilter filter, Model::ModelType modelType); private: static void initLibraries(); - static std::shared_ptr> _libraryList; - static std::shared_ptr> _modelMap; + static std::shared_ptr>> _libraryList; + static std::shared_ptr>> _modelMap; static QMutex _mutex; }; diff --git a/src/Mod/Material/App/ModelManagerPyImpl.cpp b/src/Mod/Material/App/ModelManagerPyImpl.cpp index 793a80a63b..b7b2608a26 100644 --- a/src/Mod/Material/App/ModelManagerPyImpl.cpp +++ b/src/Mod/Material/App/ModelManagerPyImpl.cpp @@ -21,10 +21,8 @@ #include "PreCompiled.h" -#ifndef _PreComp_ -#include -#endif - +#include "Model.h" +#include "ModelLibrary.h" #include "ModelManager.h" #include "ModelManagerPy.h" #include "ModelPy.h" @@ -62,8 +60,8 @@ PyObject* ModelManagerPy::getModel(PyObject* args) } try { - const Model model = getModelManagerPtr()->getModel(QString::fromStdString(uuid)); - return new ModelPy(new Model(model)); + auto model = getModelManagerPtr()->getModel(QString::fromStdString(uuid)); + return new ModelPy(new Model(*model)); } catch (ModelNotFound const&) { QString error = QString::fromStdString("Model not found:\n"); @@ -96,10 +94,9 @@ PyObject* ModelManagerPy::getModelByPath(PyObject* args) std::string libPath(lib); if (libPath.length() > 0) { try { - const Model& model = - getModelManagerPtr()->getModelByPath(QString::fromStdString(path), - QString::fromStdString(libPath)); - return new ModelPy(new Model(model)); + auto model = getModelManagerPtr()->getModelByPath(QString::fromStdString(path), + QString::fromStdString(libPath)); + return new ModelPy(new Model(*model)); } catch (ModelNotFound const&) { PyErr_SetString(PyExc_LookupError, "Model not found"); @@ -108,8 +105,8 @@ PyObject* ModelManagerPy::getModelByPath(PyObject* args) } try { - const Model& model = getModelManagerPtr()->getModelByPath(QString::fromStdString(path)); - return new ModelPy(new Model(model)); + auto model = getModelManagerPtr()->getModelByPath(QString::fromStdString(path)); + return new ModelPy(new Model(*model)); } catch (ModelNotFound const&) { PyErr_SetString(PyExc_LookupError, "Model not found"); @@ -119,11 +116,11 @@ PyObject* ModelManagerPy::getModelByPath(PyObject* args) Py::List ModelManagerPy::getModelLibraries() const { - std::shared_ptr> libraries = getModelManagerPtr()->getModelLibraries(); + auto libraries = getModelManagerPtr()->getModelLibraries(); Py::List list; for (auto it = libraries->begin(); it != libraries->end(); it++) { - ModelLibrary* lib = *it; + auto lib = *it; Py::Tuple libTuple(3); libTuple.setItem(0, Py::String(lib->getName().toStdString())); libTuple.setItem(1, Py::String(lib->getDirectoryPath().toStdString())); @@ -142,7 +139,7 @@ Py::Dict ModelManagerPy::getModels() const for (auto it = models->begin(); it != models->end(); it++) { QString key = it->first; - Model* model = it->second; + auto model = it->second; PyObject* modelPy = new ModelPy(new Model(*model)); dict.setItem(Py::String(key.toStdString()), Py::Object(modelPy, true)); diff --git a/src/Mod/Material/App/ModelPropertyPyImpl.cpp b/src/Mod/Material/App/ModelPropertyPyImpl.cpp index e87cb6f15f..d701df9da6 100644 --- a/src/Mod/Material/App/ModelPropertyPyImpl.cpp +++ b/src/Mod/Material/App/ModelPropertyPyImpl.cpp @@ -21,10 +21,6 @@ #include "PreCompiled.h" -#ifndef _PreComp_ -#include -#endif - #include "Model.h" #include "ModelPropertyPy.h" diff --git a/src/Mod/Material/App/ModelPyImpl.cpp b/src/Mod/Material/App/ModelPyImpl.cpp index 1d83d99e65..f450ee1f0b 100644 --- a/src/Mod/Material/App/ModelPyImpl.cpp +++ b/src/Mod/Material/App/ModelPyImpl.cpp @@ -21,13 +21,11 @@ #include "PreCompiled.h" -#ifndef _PreComp_ -#include -#endif - #include "Model.h" +#include "ModelLibrary.h" #include "ModelPropertyPy.h" #include "ModelPy.h" +#include "ModelUuids.h" #include "ModelPy.cpp" @@ -43,11 +41,11 @@ std::string ModelPy::representation() const str << "), UUID=("; str << ptr->getUUID().toStdString(); str << "), Library Name=("; - str << ptr->getLibrary().getName().toStdString(); + str << ptr->getLibrary()->getName().toStdString(); str << "), Library Root=("; - str << ptr->getLibrary().getDirectoryPath().toStdString(); + str << ptr->getLibrary()->getDirectoryPath().toStdString(); str << "), Library Icon=("; - str << ptr->getLibrary().getIconPath().toStdString(); + str << ptr->getLibrary()->getIconPath().toStdString(); str << "), Directory=("; str << ptr->getDirectory().toStdString(); str << "), URL=("; @@ -57,7 +55,7 @@ std::string ModelPy::representation() const str << "), Description=("; str << ptr->getDescription().toStdString(); str << "), Inherits=["; - const std::vector& inherited = getModelPtr()->getInheritance(); + auto& inherited = getModelPtr()->getInheritance(); for (auto it = inherited.begin(); it != inherited.end(); it++) { QString uuid = *it; if (it != inherited.begin()) { @@ -87,17 +85,17 @@ int ModelPy::PyInit(PyObject* /*args*/, PyObject* /*kwd*/) Py::String ModelPy::getLibraryName() const { - return Py::String(getModelPtr()->getLibrary().getName().toStdString()); + return Py::String(getModelPtr()->getLibrary()->getName().toStdString()); } Py::String ModelPy::getLibraryRoot() const { - return Py::String(getModelPtr()->getLibrary().getDirectoryPath().toStdString()); + return Py::String(getModelPtr()->getLibrary()->getDirectoryPath().toStdString()); } Py::String ModelPy::getLibraryIcon() const { - return Py::String(getModelPtr()->getLibrary().getIconPath().toStdString()); + return Py::String(getModelPtr()->getLibrary()->getIconPath().toStdString()); } Py::String ModelPy::getName() const @@ -132,13 +130,11 @@ Py::String ModelPy::getDOI() const Py::List ModelPy::getInherited() const { - const std::vector& inherited = getModelPtr()->getInheritance(); + auto& inherited = getModelPtr()->getInheritance(); Py::List list; for (auto it = inherited.begin(); it != inherited.end(); it++) { - QString uuid = *it; - - list.append(Py::String(uuid.toStdString())); + list.append(Py::String(it->toStdString())); } return list; diff --git a/src/Mod/Material/App/ModelUuids.cpp b/src/Mod/Material/App/ModelUuids.cpp new file mode 100644 index 0000000000..78c02ace68 --- /dev/null +++ b/src/Mod/Material/App/ModelUuids.cpp @@ -0,0 +1,70 @@ +/*************************************************************************** + * Copyright (c) 2023 David Carter * + * * + * This file is part of FreeCAD. * + * * + * FreeCAD is free software: you can redistribute it and/or modify it * + * under the terms of the GNU Lesser General Public License as * + * published by the Free Software Foundation, either version 2.1 of the * + * License, or (at your option) any later version. * + * * + * FreeCAD is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with FreeCAD. If not, see * + * . * + * * + **************************************************************************/ + +#include "PreCompiled.h" +#ifndef _PreComp_ +#endif + +#include "ModelUuids.h" + +using namespace Materials; + +TYPESYSTEM_SOURCE(Materials::ModelUUIDs, Base::BaseClass) + +const QString ModelUUIDs::ModelUUID_Legacy_Father = + QString::fromStdString("9cdda8b6-b606-4778-8f13-3934d8668e67"); +const QString ModelUUIDs::ModelUUID_Legacy_MaterialStandard = + QString::fromStdString("1e2c0088-904a-4537-925f-64064c07d700"); + +const QString ModelUUIDs::ModelUUID_Mechanical_Density = + QString::fromStdString("454661e5-265b-4320-8e6f-fcf6223ac3af"); +const QString ModelUUIDs::ModelUUID_Mechanical_IsotropicLinearElastic = + QString::fromStdString("f6f9e48c-b116-4e82-ad7f-3659a9219c50"); +const QString ModelUUIDs::ModelUUID_Mechanical_LinearElastic = + QString::fromStdString("7b561d1d-fb9b-44f6-9da9-56a4f74d7536"); +const QString ModelUUIDs::ModelUUID_Mechanical_OgdenYld2004p18 = + QString::fromStdString("3ef9e427-cc25-43f7-817f-79ff0d49625f"); +const QString ModelUUIDs::ModelUUID_Mechanical_OrthotropicLinearElastic = + QString::fromStdString("b19ccc6b-a431-418e-91c2-0ac8c649d146"); + +const QString ModelUUIDs::ModelUUID_Fluid_Default = + QString::fromStdString("1ae66d8c-1ba1-4211-ad12-b9917573b202"); + +const QString ModelUUIDs::ModelUUID_Thermal_Default = + QString::fromStdString("9959d007-a970-4ea7-bae4-3eb1b8b883c7"); + +const QString ModelUUIDs::ModelUUID_Electromagnetic_Default = + QString::fromStdString("b2eb5f48-74b3-4193-9fbb-948674f427f3"); + +const QString ModelUUIDs::ModelUUID_Architectural_Default = + QString::fromStdString("32439c3b-262f-4b7b-99a8-f7f44e5894c8"); + +const QString ModelUUIDs::ModelUUID_Costs_Default = + QString::fromStdString("881df808-8726-4c2e-be38-688bb6cce466"); + +const QString ModelUUIDs::ModelUUID_Rendering_Basic = + QString::fromStdString("f006c7e4-35b7-43d5-bbf9-c5d572309e6e"); +const QString ModelUUIDs::ModelUUID_Rendering_Texture = + QString::fromStdString("bbdcc65b-67ca-489c-bd5c-a36e33d1c160"); +const QString ModelUUIDs::ModelUUID_Rendering_Advanced = + QString::fromStdString("c880f092-cdae-43d6-a24b-55e884aacbbf"); +const QString ModelUUIDs::ModelUUID_Rendering_Vector = + QString::fromStdString("fdf5a80e-de50-4157-b2e5-b6e5f88b680e"); diff --git a/src/Mod/Material/App/ModelUuids.h b/src/Mod/Material/App/ModelUuids.h index d160f13ac4..db667940db 100644 --- a/src/Mod/Material/App/ModelUuids.h +++ b/src/Mod/Material/App/ModelUuids.h @@ -24,50 +24,48 @@ #include +#include + +#include + namespace Materials { -// UUIDs for predefined material models +class MaterialsExport ModelUUIDs: public Base::BaseClass +{ + TYPESYSTEM_HEADER_WITH_OVERRIDE(); -static const QString ModelUUID_Legacy_Father = - QString::fromStdString("9cdda8b6-b606-4778-8f13-3934d8668e67"); -static const QString ModelUUID_Legacy_MaterialStandard = - QString::fromStdString("1e2c0088-904a-4537-925f-64064c07d700"); +public: + ModelUUIDs() + {} + ~ModelUUIDs() override = default; -static const QString ModelUUID_Mechanical_Density = - QString::fromStdString("454661e5-265b-4320-8e6f-fcf6223ac3af"); -static const QString ModelUUID_Mechanical_IsotropicLinearElastic = - QString::fromStdString("f6f9e48c-b116-4e82-ad7f-3659a9219c50"); -static const QString ModelUUID_Mechanical_LinearElastic = - QString::fromStdString("7b561d1d-fb9b-44f6-9da9-56a4f74d7536"); -static const QString ModelUUID_Mechanical_OgdenYld2004p18 = - QString::fromStdString("3ef9e427-cc25-43f7-817f-79ff0d49625f"); -static const QString ModelUUID_Mechanical_OrthotropicLinearElastic = - QString::fromStdString("b19ccc6b-a431-418e-91c2-0ac8c649d146"); + // UUIDs for predefined material models -static const QString ModelUUID_Fluid_Default = - QString::fromStdString("1ae66d8c-1ba1-4211-ad12-b9917573b202"); + static const QString ModelUUID_Legacy_Father; + static const QString ModelUUID_Legacy_MaterialStandard; -static const QString ModelUUID_Thermal_Default = - QString::fromStdString("9959d007-a970-4ea7-bae4-3eb1b8b883c7"); + static const QString ModelUUID_Mechanical_Density; + static const QString ModelUUID_Mechanical_IsotropicLinearElastic; + static const QString ModelUUID_Mechanical_LinearElastic; + static const QString ModelUUID_Mechanical_OgdenYld2004p18; + static const QString ModelUUID_Mechanical_OrthotropicLinearElastic; -static const QString ModelUUID_Electromagnetic_Default = - QString::fromStdString("b2eb5f48-74b3-4193-9fbb-948674f427f3"); + static const QString ModelUUID_Fluid_Default; -static const QString ModelUUID_Architectural_Default = - QString::fromStdString("32439c3b-262f-4b7b-99a8-f7f44e5894c8"); + static const QString ModelUUID_Thermal_Default; -static const QString ModelUUID_Costs_Default = - QString::fromStdString("881df808-8726-4c2e-be38-688bb6cce466"); + static const QString ModelUUID_Electromagnetic_Default; -static const QString ModelUUID_Rendering_Basic = - QString::fromStdString("f006c7e4-35b7-43d5-bbf9-c5d572309e6e"); -static const QString ModelUUID_Rendering_Texture = - QString::fromStdString("bbdcc65b-67ca-489c-bd5c-a36e33d1c160"); -static const QString ModelUUID_Rendering_Advanced = - QString::fromStdString("c880f092-cdae-43d6-a24b-55e884aacbbf"); -static const QString ModelUUID_Rendering_Vector = - QString::fromStdString("fdf5a80e-de50-4157-b2e5-b6e5f88b680e"); + static const QString ModelUUID_Architectural_Default; + + static const QString ModelUUID_Costs_Default; + + static const QString ModelUUID_Rendering_Basic; + static const QString ModelUUID_Rendering_Texture; + static const QString ModelUUID_Rendering_Advanced; + static const QString ModelUUID_Rendering_Vector; +}; } // namespace Materials diff --git a/src/Mod/Material/App/PreCompiled.h b/src/Mod/Material/App/PreCompiled.h index c643eb4f42..f602f3773c 100644 --- a/src/Mod/Material/App/PreCompiled.h +++ b/src/Mod/Material/App/PreCompiled.h @@ -55,10 +55,6 @@ // Qt #include -// Boost -#include -#include - #endif //_PreComp_ #endif // MATERIAL_PRECOMPILED_H diff --git a/src/Mod/Material/App/UUIDsPy.xml b/src/Mod/Material/App/UUIDsPy.xml new file mode 100644 index 0000000000..29138e05c3 --- /dev/null +++ b/src/Mod/Material/App/UUIDsPy.xml @@ -0,0 +1,116 @@ + + + + + + Material model UUID identifiers. + + + + UUID for model System:Legacy/Father + + + + + + UUID for model System:Legacy/MaterialStandard + + + + + + UUID for model System:Mechanical/Density + + + + + + UUID for model System:Mechanical/IsotropicLinearElastic + + + + + + UUID for model System:Mechanical/LinearElastic + + + + + + UUID for model System:Mechanical/OgdenYld2004p18 + + + + + + UUID for model System:Mechanical/OrthotropicLinearElastic + + + + + + UUID for model System:Fluid/Fluid + + + + + + UUID for model System:Thermal/Thermal + + + + + + UUID for model System:Electromagnetic/Electromagnetic + + + + + + UUID for model System:Architectural/Architectural + + + + + + UUID for model System:Costs/Costs + + + + + + UUID for model System:Rendering/BasicRendering + + + + + + UUID for model System:Rendering/TextureRendering + + + + + + UUID for model System:Rendering/AdvancedRendering + + + + + + UUID for model System:Rendering/VectorRendering + + + + + diff --git a/src/Mod/Material/App/UUIDsPyImpl.cpp b/src/Mod/Material/App/UUIDsPyImpl.cpp new file mode 100644 index 0000000000..94d3fb9071 --- /dev/null +++ b/src/Mod/Material/App/UUIDsPyImpl.cpp @@ -0,0 +1,139 @@ +/*************************************************************************** + * Copyright (c) 2023 David Carter * + * * + * This file is part of FreeCAD. * + * * + * FreeCAD is free software: you can redistribute it and/or modify it * + * under the terms of the GNU Lesser General Public License as * + * published by the Free Software Foundation, either version 2.1 of the * + * License, or (at your option) any later version. * + * * + * FreeCAD is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with FreeCAD. If not, see * + * . * + * * + **************************************************************************/ + +#include "PreCompiled.h" + +#include "ModelUuids.h" + +#include "UUIDsPy.h" + +#include "UUIDsPy.cpp" + +using namespace Materials; + +// returns a string which represents the object e.g. when printed in python +std::string UUIDsPy::representation() const +{ + return {""}; +} + +PyObject* UUIDsPy::PyMake(struct _typeobject*, PyObject*, PyObject*) // Python wrapper +{ + // create a new instance of UUIDsPy and the Twin object + return new UUIDsPy(new ModelUUIDs); +} + +// constructor method +int UUIDsPy::PyInit(PyObject* /*args*/, PyObject* /*kwd*/) +{ + return 0; +} + +Py::String UUIDsPy::getFather() const +{ + return Py::String(ModelUUIDs::ModelUUID_Legacy_Father.toStdString()); +} + +Py::String UUIDsPy::getMaterialStandard() const +{ + return Py::String(ModelUUIDs::ModelUUID_Legacy_MaterialStandard.toStdString()); +} + +Py::String UUIDsPy::getDensity() const +{ + return Py::String(ModelUUIDs::ModelUUID_Mechanical_Density.toStdString()); +} + +Py::String UUIDsPy::getIsotropicLinearElastic() const +{ + return Py::String(ModelUUIDs::ModelUUID_Mechanical_IsotropicLinearElastic.toStdString()); +} + +Py::String UUIDsPy::getLinearElastic() const +{ + return Py::String(ModelUUIDs::ModelUUID_Mechanical_LinearElastic.toStdString()); +} + +Py::String UUIDsPy::getOgdenYld2004p18() const +{ + return Py::String(ModelUUIDs::ModelUUID_Mechanical_OgdenYld2004p18.toStdString()); +} + +Py::String UUIDsPy::getOrthotropicLinearElastic() const +{ + return Py::String(ModelUUIDs::ModelUUID_Mechanical_OrthotropicLinearElastic.toStdString()); +} + +Py::String UUIDsPy::getFluid() const +{ + return Py::String(ModelUUIDs::ModelUUID_Fluid_Default.toStdString()); +} + +Py::String UUIDsPy::getThermal() const +{ + return Py::String(ModelUUIDs::ModelUUID_Thermal_Default.toStdString()); +} + +Py::String UUIDsPy::getElectromagnetic() const +{ + return Py::String(ModelUUIDs::ModelUUID_Electromagnetic_Default.toStdString()); +} + +Py::String UUIDsPy::getArchitectural() const +{ + return Py::String(ModelUUIDs::ModelUUID_Architectural_Default.toStdString()); +} + +Py::String UUIDsPy::getCosts() const +{ + return Py::String(ModelUUIDs::ModelUUID_Costs_Default.toStdString()); +} + +Py::String UUIDsPy::getBasicRendering() const +{ + return Py::String(ModelUUIDs::ModelUUID_Rendering_Basic.toStdString()); +} + +Py::String UUIDsPy::getTextureRendering() const +{ + return Py::String(ModelUUIDs::ModelUUID_Rendering_Texture.toStdString()); +} + +Py::String UUIDsPy::getAdvancedRendering() const +{ + Base::Console().Log(getModelUUIDsPtr()->ModelUUID_Rendering_Advanced.toStdString().c_str()); + return Py::String(getModelUUIDsPtr()->ModelUUID_Rendering_Advanced.toStdString()); +} + +Py::String UUIDsPy::getVectorRendering() const +{ + return Py::String(ModelUUIDs::ModelUUID_Rendering_Vector.toStdString()); +} + +PyObject* UUIDsPy::getCustomAttributes(const char* /*attr*/) const +{ + return nullptr; +} + +int UUIDsPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/) +{ + return 0; +} diff --git a/src/Mod/Material/App/trim.h b/src/Mod/Material/App/trim.h index a8b4a94d84..c4b038567a 100644 --- a/src/Mod/Material/App/trim.h +++ b/src/Mod/Material/App/trim.h @@ -22,7 +22,6 @@ #ifndef MATERIAL_TRIM_H #define MATERIAL_TRIM_H -#include #include namespace Materials diff --git a/src/Mod/Material/CMakeLists.txt b/src/Mod/Material/CMakeLists.txt index b9ae72647d..6263b1ea80 100644 --- a/src/Mod/Material/CMakeLists.txt +++ b/src/Mod/Material/CMakeLists.txt @@ -194,7 +194,6 @@ SET(MaterialModel_Files Resources/Models/Legacy/Father.yml Resources/Models/Legacy/MaterialStandard.yml Resources/Models/Mechanical/Density.yml - Resources/Models/Mechanical/HypotheticalExample.yml Resources/Models/Mechanical/IsotropicLinearElastic.yml Resources/Models/Mechanical/LinearElastic.yml Resources/Models/Mechanical/OgdenYld2004p18.yml @@ -206,6 +205,21 @@ SET(MaterialModel_Files Resources/Models/Thermal/Thermal.yml ) +set(MaterialTest_Files + materialtests/__init__.py + materialtests/TestModels.py + materialtests/TestMaterials.py +) + +ADD_CUSTOM_TARGET(MateriaTestLib ALL + SOURCES ${MaterialTest_Files} +) + +fc_target_copy_resource(MateriaTestLib + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_BINARY_DIR}/Mod/Material + ${MaterialTest_Files}) + ADD_CUSTOM_TARGET(MaterialScripts ALL SOURCES ${MaterialScripts_Files} ${Material_QRC_SRCS} ) @@ -275,8 +289,13 @@ INSTALL( DESTINATION Mod/Material ) +INSTALL( + FILES ${MaterialTest_Files} + DESTINATION Mod/Material/materialtests +) + foreach(file ${MaterialLib_Files} ${FluidMaterial_Files} ${AppearanceLib_Files} ${MaterialModel_Files}) - get_filename_component(filepath ${file} DIRECTORY) + cmake_path(REMOVE_FILENAME file OUTPUT_VARIABLE filepath) INSTALL( FILES ${file} DESTINATION ${CMAKE_INSTALL_DATADIR}/Mod/Material/${filepath} diff --git a/src/Mod/Material/Gui/AppMatGui.cpp b/src/Mod/Material/Gui/AppMatGui.cpp index f20967589b..b424067ca3 100644 --- a/src/Mod/Material/Gui/AppMatGui.cpp +++ b/src/Mod/Material/Gui/AppMatGui.cpp @@ -96,6 +96,9 @@ PyMOD_INIT_FUNC(MatGui) // register preferences pages on Material, the order here will be the order of the tabs in pref // widget + Gui::Dialog::DlgPreferencesImp::setGroupData("Material", + "Material", + QObject::tr("Material workbench")); new Gui::PrefPageProducer( QT_TRANSLATE_NOOP("QObject", "Material")); diff --git a/src/Mod/Material/Gui/Array2D.cpp b/src/Mod/Material/Gui/Array2D.cpp index 5e39884d82..799dec92f2 100644 --- a/src/Mod/Material/Gui/Array2D.cpp +++ b/src/Mod/Material/Gui/Array2D.cpp @@ -24,6 +24,8 @@ #include #endif +#include + #include #include @@ -39,32 +41,52 @@ using namespace MatGui; /* TRANSLATOR MatGui::Array2D */ -Array2D::Array2D(const QString& propertyName, Materials::Material* material, QWidget* parent) +Array2D::Array2D(const QString& propertyName, + std::shared_ptr material, + QWidget* parent) : QDialog(parent) , ui(new Ui_Array2D) + , _material(material) { ui->setupUi(this); if (material->hasPhysicalProperty(propertyName)) { - _property = &(material->getPhysicalProperty(propertyName)); + _property = material->getPhysicalProperty(propertyName); } else if (material->hasAppearanceProperty(propertyName)) { - _property = &(material->getAppearanceProperty(propertyName)); + _property = material->getAppearanceProperty(propertyName); } else { + Base::Console().Log("Property '%s' not found\n", propertyName.toStdString().c_str()); _property = nullptr; } if (_property) { + Base::Console().Log("Value type %d\n", + static_cast(_property->getMaterialValue()->getType())); _value = std::static_pointer_cast(_property->getMaterialValue()); } else { + Base::Console().Log("No value loaded\n"); _value = nullptr; } + if (_value) { + Base::Console().Log("Value type %d\n", static_cast(_value->getType())); + // auto value = _property->getMaterialValue()->getValue(); + // Base::Console().Log("\tQVariant type %d\n", value.userType()); + } setupDefault(); setupArray(); + ui->tableView->setContextMenuPolicy(Qt::CustomContextMenu); + connect(ui->tableView, &QWidget::customContextMenuRequested, this, &Array2D::onContextMenu); + + _deleteAction.setText(tr("Delete row")); + _deleteAction.setShortcut(Qt::Key_Delete); + connect(&_deleteAction, &QAction::triggered, this, &Array2D::onDelete); + ui->tableView->addAction(&_deleteAction); + connect(ui->standardButtons, &QDialogButtonBox::accepted, this, &Array2D::accept); connect(ui->standardButtons, &QDialogButtonBox::rejected, this, &Array2D::reject); } @@ -77,13 +99,16 @@ void Array2D::setupDefault() try { const Materials::MaterialProperty& column1 = _property->getColumn(0); - QString label = QString::fromStdString("Default ") + column1.getName(); + QString label = tr("Default ") + column1.getName(); ui->labelDefault->setText(label); if (column1.getPropertyType() == QString::fromStdString("Quantity")) { ui->editDefault->setMinimum(std::numeric_limits::min()); ui->editDefault->setMaximum(std::numeric_limits::max()); ui->editDefault->setUnitText(_property->getColumnUnits(0)); - ui->editDefault->setValue(_value->getDefault().getValue().value()); + if (!_value->defaultSet()) { + _value->setDefault(_property->getColumnNull(0).value()); + } + ui->editDefault->setValue(_value->getDefault().value()); connect(ui->editDefault, qOverload(&Gui::QuantitySpinBox::valueChanged), @@ -134,15 +159,99 @@ void Array2D::setupArray() auto table = ui->tableView; auto model = new Array2DModel(_property, _value, this); table->setModel(model); - table->setEditTriggers(QAbstractItemView::AllEditTriggers); + // table->setEditTriggers(QAbstractItemView::AllEditTriggers); + table->setSelectionMode(QAbstractItemView::SingleSelection); setColumnWidths(table); setColumnDelegates(table); + connect(model, &QAbstractItemModel::dataChanged, this, &Array2D::onDataChanged); +} + +void Array2D::onDataChanged(const QModelIndex& topLeft, + const QModelIndex& bottomRight, + const QVector& roles) +{ + Q_UNUSED(topLeft) + Q_UNUSED(bottomRight) + Q_UNUSED(roles) + + _material->setEditStateAlter(); } void Array2D::defaultValueChanged(const Base::Quantity& value) { _value->setDefault(QVariant::fromValue(value)); + _material->setEditStateAlter(); +} + +void Array2D::onContextMenu(const QPoint& pos) +{ + Base::Console().Log("Array2D::onContextMenu(%d,%d)\n", pos.x(), pos.y()); + QModelIndex index = ui->tableView->indexAt(pos); + Base::Console().Log("\tindex at (%d,%d)\n", index.row(), index.column()); + + + QMenu contextMenu(tr("Context menu"), this); + + contextMenu.addAction(&_deleteAction); + + contextMenu.exec(ui->tableView->mapToGlobal(pos)); +} + +bool Array2D::newRow(const QModelIndex& index) +{ + Array2DModel* model = static_cast(ui->tableView->model()); + return model->newRow(index); +} + +void Array2D::onDelete(bool checked) +{ + Q_UNUSED(checked) + + Base::Console().Log("Array2D::onDelete()\n"); + QItemSelectionModel* selectionModel = ui->tableView->selectionModel(); + if (!selectionModel->hasSelection() || newRow(selectionModel->currentIndex())) { + Base::Console().Log("\tNothing selected\n"); + return; + } + + int res = confirmDelete(); + if (res == QMessageBox::Cancel) { + return; + } +} + +int Array2D::confirmDelete() +{ + QMessageBox box(this); + box.setIcon(QMessageBox::Question); + box.setWindowTitle(QObject::tr("Confirm Delete")); + + QString prompt = QObject::tr("Are you sure you want to delete the row?"); + box.setText(prompt); + + box.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel); + box.setDefaultButton(QMessageBox::Cancel); + box.setEscapeButton(QMessageBox::Cancel); + + int res = QMessageBox::Cancel; + box.adjustSize(); // Silence warnings from Qt on Windows + switch (box.exec()) { + case QMessageBox::Ok: + deleteSelected(); + res = QMessageBox::Ok; + break; + } + + return res; +} + +void Array2D::deleteSelected() +{ + Array2DModel* model = static_cast(ui->tableView->model()); + QItemSelectionModel* selectionModel = ui->tableView->selectionModel(); + auto index = selectionModel->currentIndex(); + model->deleteRow(index); } void Array2D::accept() diff --git a/src/Mod/Material/Gui/Array2D.h b/src/Mod/Material/Gui/Array2D.h index f32f97e93e..11af3e5366 100644 --- a/src/Mod/Material/Gui/Array2D.h +++ b/src/Mod/Material/Gui/Array2D.h @@ -22,14 +22,20 @@ #ifndef MATGUI_ARRAY2D_H #define MATGUI_ARRAY2D_H +#include + #include +#include #include +#include #include +#include #include -#include "ArrayModel.h" #include +#include "ArrayModel.h" + namespace MatGui { @@ -40,26 +46,38 @@ class Array2D: public QDialog Q_OBJECT public: - explicit Array2D(const QString& propertyName, - Materials::Material* material, - QWidget* parent = nullptr); + Array2D(const QString& propertyName, + std::shared_ptr material, + QWidget* parent = nullptr); ~Array2D() override = default; + void onDataChanged(const QModelIndex& topLeft, + const QModelIndex& bottomRight, + const QVector& roles = QVector()); void defaultValueChanged(const Base::Quantity& value); + void onDelete(bool checked); + void onContextMenu(const QPoint& pos); void accept() override; void reject() override; private: std::unique_ptr ui; - const Materials::MaterialProperty* _property; + std::shared_ptr _material; + std::shared_ptr _property; std::shared_ptr _value; + QAction _deleteAction; + void setupDefault(); void setHeaders(QStandardItemModel* model); void setColumnWidths(QTableView* table); void setColumnDelegates(QTableView* table); void setupArray(); + + bool newRow(const QModelIndex& index); + int confirmDelete(); + void deleteSelected(); }; } // namespace MatGui diff --git a/src/Mod/Material/Gui/Array3D.cpp b/src/Mod/Material/Gui/Array3D.cpp index 956a033204..58f6299d7e 100644 --- a/src/Mod/Material/Gui/Array3D.cpp +++ b/src/Mod/Material/Gui/Array3D.cpp @@ -25,9 +25,12 @@ #include #endif +#include + #include #include +#include #include "Array3D.h" #include "ArrayDelegate.h" @@ -37,19 +40,23 @@ using namespace MatGui; -Array3D::Array3D(const QString& propertyName, Materials::Material* material, QWidget* parent) +Array3D::Array3D(const QString& propertyName, + std::shared_ptr material, + QWidget* parent) : QDialog(parent) , ui(new Ui_Array3D) + , _material(material) { ui->setupUi(this); if (material->hasPhysicalProperty(propertyName)) { - _property = &(material->getPhysicalProperty(propertyName)); + _property = material->getPhysicalProperty(propertyName); } else if (material->hasAppearanceProperty(propertyName)) { - _property = &(material->getAppearanceProperty(propertyName)); + _property = material->getAppearanceProperty(propertyName); } else { + Base::Console().Log("Property '%s' not found\n", propertyName.toStdString().c_str()); _property = nullptr; } if (_property) { @@ -57,6 +64,7 @@ Array3D::Array3D(const QString& propertyName, Materials::Material* material, QWi std::static_pointer_cast(_property->getMaterialValue()); } else { + Base::Console().Log("No value loaded\n"); _value = nullptr; } @@ -64,6 +72,22 @@ Array3D::Array3D(const QString& propertyName, Materials::Material* material, QWi setupDepthArray(); setupArray(); + ui->table3D->setContextMenuPolicy(Qt::CustomContextMenu); + connect(ui->table3D, &QWidget::customContextMenuRequested, this, &Array3D::onDepthContextMenu); + + ui->table2D->setContextMenuPolicy(Qt::CustomContextMenu); + connect(ui->table2D, &QWidget::customContextMenuRequested, this, &Array3D::on2DContextMenu); + + _deleteDepthAction.setText(tr("Delete row")); + // _deleteDepthAction.setShortcut(Qt::Key_Delete); + connect(&_deleteDepthAction, &QAction::triggered, this, &Array3D::onDepthDelete); + ui->table3D->addAction(&_deleteDepthAction); + + _delete2DAction.setText(tr("Delete row")); + // _delete2DAction.setShortcut(Qt::Key_Delete); + connect(&_delete2DAction, &QAction::triggered, this, &Array3D::on2DDelete); + ui->table2D->addAction(&_delete2DAction); + Base::Console().Log("Material '%s'\n", material->getName().toStdString().c_str()); Base::Console().Log("\tproperty '%s'\n", propertyName.toStdString().c_str()); @@ -78,6 +102,10 @@ Array3D::Array3D(const QString& propertyName, Materials::Material* material, QWi &QPushButton::clicked, this, &Array3D::onCancel); + + + QItemSelectionModel* selectionModel = ui->table3D->selectionModel(); + connect(selectionModel, &QItemSelectionModel::selectionChanged, this, &Array3D::onSelectDepth); } bool Array3D::onSplitter(QEvent* e) @@ -95,13 +123,16 @@ void Array3D::setupDefault() try { auto& column1 = _property->getColumn(0); - QString label = QString::fromStdString("Default ") + column1.getName(); + QString label = tr("Default ") + column1.getName(); ui->labelDefault->setText(label); if (column1.getPropertyType() == QString::fromStdString("Quantity")) { ui->editDefault->setMinimum(std::numeric_limits::min()); ui->editDefault->setMaximum(std::numeric_limits::max()); ui->editDefault->setUnitText(_property->getColumnUnits(0)); - ui->editDefault->setValue(_value->getDefault().getValue().value()); + if (!_value->defaultSet()) { + _value->setDefault(_property->getColumnNull(0).value()); + } + ui->editDefault->setValue(_value->getDefault().value()); connect(ui->editDefault, qOverload(&Gui::QuantitySpinBox::valueChanged), @@ -117,6 +148,7 @@ void Array3D::setupDefault() void Array3D::defaultValueChanged(const Base::Quantity& value) { _value->setDefault(QVariant::fromValue(value)); + _material->setEditStateAlter(); } void Array3D::setDepthColumnDelegate(QTableView* table) @@ -140,10 +172,43 @@ void Array3D::setupDepthArray() auto table = ui->table3D; auto model = new Array3DDepthModel(_property, _value, this); table->setModel(model); - table->setEditTriggers(QAbstractItemView::AllEditTriggers); + // table->setEditTriggers(QAbstractItemView::AllEditTriggers); + table->setSelectionMode(QAbstractItemView::SingleSelection); setDepthColumnWidth(table); setDepthColumnDelegate(table); + connect(model, &QAbstractItemModel::rowsInserted, this, &Array3D::onRowsInserted); + connect(model, &QAbstractItemModel::rowsRemoved, this, &Array3D::onRowsRemoved); + connect(model, &QAbstractItemModel::dataChanged, this, &Array3D::onDataChanged); +} + +void Array3D::onRowsInserted(const QModelIndex& parent, int first, int last) +{ + Q_UNUSED(parent) + Q_UNUSED(first) + Q_UNUSED(last) + + update2DArray(); +} + +void Array3D::onRowsRemoved(const QModelIndex& parent, int first, int last) +{ + Q_UNUSED(parent) + Q_UNUSED(first) + Q_UNUSED(last) + + update2DArray(); +} + +void Array3D::onDataChanged(const QModelIndex& topLeft, + const QModelIndex& bottomRight, + const QVector& roles) +{ + Q_UNUSED(topLeft) + Q_UNUSED(bottomRight) + Q_UNUSED(roles) + + _material->setEditStateAlter(); } void Array3D::setColumnWidths(QTableView* table) @@ -174,10 +239,190 @@ void Array3D::setupArray() auto table = ui->table2D; auto model = new Array3DModel(_property, _value, this); table->setModel(model); - table->setEditTriggers(QAbstractItemView::AllEditTriggers); + // table->setEditTriggers(QAbstractItemView::AllEditTriggers); + table->setSelectionMode(QAbstractItemView::SingleSelection); setColumnWidths(table); setColumnDelegates(table); + + if (_value->depth() == 0) { + table->setEnabled(false); + } + connect(model, &QAbstractItemModel::dataChanged, this, &Array3D::onDataChanged); +} + +void Array3D::onSelectDepth(const QItemSelection& selected, const QItemSelection& deselected) +{ + Q_UNUSED(deselected); + + QModelIndexList indexes = selected.indexes(); + + // This should be a list of length 1 + for (auto it = indexes.begin(); it != indexes.end(); it++) { + _value->setCurrentDepth(it->row()); + break; + } + + update2DArray(); +} + +void Array3D::update2DArray() +{ + auto table = ui->table2D; + auto model = static_cast(table->model()); + model->updateData(); + table->setEnabled(_value->depth() > 0); +} + +void Array3D::onDepthContextMenu(const QPoint& pos) +{ + Base::Console().Log("Array3D::onDepthContextMenu(%d,%d)\n", pos.x(), pos.y()); + QModelIndex index = ui->table3D->indexAt(pos); + Base::Console().Log("\tindex at (%d,%d)\n", index.row(), index.column()); + + + QMenu contextMenu(tr("Context menu"), this); + + contextMenu.addAction(&_deleteDepthAction); + + contextMenu.exec(ui->table3D->mapToGlobal(pos)); +} + +bool Array3D::newDepthRow(const QModelIndex& index) +{ + Array3DDepthModel* model = static_cast(ui->table3D->model()); + return model->newRow(index); +} + +void Array3D::onDepthDelete(bool checked) +{ + Q_UNUSED(checked) + + Base::Console().Log("Array3D::onDepthDelete()\n"); + QItemSelectionModel* selectionModel = ui->table3D->selectionModel(); + if (!selectionModel->hasSelection() || newDepthRow(selectionModel->currentIndex())) { + Base::Console().Log("\tNothing selected\n"); + return; + } + + int res = confirmDepthDelete(); + if (res == QMessageBox::Cancel) { + return; + } +} + +int Array3D::confirmDepthDelete() +{ + QMessageBox box(this); + box.setIcon(QMessageBox::Question); + box.setWindowTitle(tr("Confirm Delete")); + + QString prompt = tr("Are you sure you want to delete the row?"); + box.setText(prompt); + box.setInformativeText(tr("Removing this will also remove all 2D contents.")); + + box.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel); + box.setDefaultButton(QMessageBox::Cancel); + box.setEscapeButton(QMessageBox::Cancel); + + int res = QMessageBox::Cancel; + box.adjustSize(); // Silence warnings from Qt on Windows + switch (box.exec()) { + case QMessageBox::Ok: + deleteDepthSelected(); + res = QMessageBox::Ok; + break; + } + + return res; +} + +void Array3D::deleteDepthSelected() +{ + Array3DDepthModel* model = static_cast(ui->table3D->model()); + QItemSelectionModel* selectionModel = ui->table3D->selectionModel(); + auto index = selectionModel->currentIndex(); + model->deleteRow(index); + + auto depth = _value->currentDepth(); + if (depth >= _value->depth()) { + depth = depth - 1; + } + _value->setCurrentDepth(depth); + update2DArray(); +} + +void Array3D::on2DContextMenu(const QPoint& pos) +{ + Base::Console().Log("Array3D::onDepthContextMenu(%d,%d)\n", pos.x(), pos.y()); + QModelIndex index = ui->table2D->indexAt(pos); + Base::Console().Log("\tindex at (%d,%d)\n", index.row(), index.column()); + + + QMenu contextMenu(tr("Context menu"), this); + + contextMenu.addAction(&_delete2DAction); + + // contextMenu.exec(mapToGlobal(pos)); + contextMenu.exec(ui->table2D->mapToGlobal(pos)); +} + +bool Array3D::new2DRow(const QModelIndex& index) +{ + Array3DModel* model = static_cast(ui->table2D->model()); + return model->newRow(index); +} + +void Array3D::on2DDelete(bool checked) +{ + Q_UNUSED(checked) + + Base::Console().Log("Array3D::on2DDelete()\n"); + QItemSelectionModel* selectionModel = ui->table2D->selectionModel(); + if (!selectionModel->hasSelection() || new2DRow(selectionModel->currentIndex())) { + Base::Console().Log("\tNothing selected\n"); + return; + } + + int res = confirm2dDelete(); + if (res == QMessageBox::Cancel) { + return; + } +} + +int Array3D::confirm2dDelete() +{ + QMessageBox box(this); + box.setIcon(QMessageBox::Question); + box.setWindowTitle(tr("Confirm Delete")); + + QString prompt = tr("Are you sure you want to delete the row?"); + box.setText(prompt); + + box.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel); + box.setDefaultButton(QMessageBox::Cancel); + box.setEscapeButton(QMessageBox::Cancel); + + int res = QMessageBox::Cancel; + box.adjustSize(); // Silence warnings from Qt on Windows + switch (box.exec()) { + case QMessageBox::Ok: + delete2DSelected(); + res = QMessageBox::Ok; + break; + } + + return res; +} + +void Array3D::delete2DSelected() +{ + Array3DModel* model = static_cast(ui->table2D->model()); + QItemSelectionModel* selectionModel = ui->table2D->selectionModel(); + auto index = selectionModel->currentIndex(); + model->deleteRow(index); + + update2DArray(); } void Array3D::onOk(bool checked) diff --git a/src/Mod/Material/Gui/Array3D.h b/src/Mod/Material/Gui/Array3D.h index 63cdb4cf46..e0c376e654 100644 --- a/src/Mod/Material/Gui/Array3D.h +++ b/src/Mod/Material/Gui/Array3D.h @@ -22,11 +22,10 @@ #ifndef MATGUI_ARRAY3D_H #define MATGUI_ARRAY3D_H +#include #include #include #include -#include - namespace MatGui { @@ -37,22 +36,42 @@ class Array3D: public QDialog Q_OBJECT public: - explicit Array3D(const QString& propertyName, - Materials::Material* material, - QWidget* parent = nullptr); + Array3D(const QString& propertyName, + std::shared_ptr material, + QWidget* parent = nullptr); ~Array3D() override = default; void defaultValueChanged(const Base::Quantity& value); + void onRowsInserted(const QModelIndex& parent, int first, int last); + void onRowsRemoved(const QModelIndex& parent, int first, int last); + void onDataChanged(const QModelIndex& topLeft, + const QModelIndex& bottomRight, + const QVector& roles = QVector()); + void onSelectDepth(const QItemSelection& selected, const QItemSelection& deselected); bool onSplitter(QEvent* e); + void onDepthDelete(bool checked); + int confirmDepthDelete(); + void deleteDepthSelected(); + void on2DDelete(bool checked); + int confirm2dDelete(); + void delete2DSelected(); + void onDepthContextMenu(const QPoint& pos); + void on2DContextMenu(const QPoint& pos); void onOk(bool checked); void onCancel(bool checked); private: std::unique_ptr ui; - const Materials::MaterialProperty* _property; + std::shared_ptr _material; + std::shared_ptr _property; std::shared_ptr _value; + QAction _deleteDepthAction; + QAction _delete2DAction; + + bool newDepthRow(const QModelIndex& index); + bool new2DRow(const QModelIndex& index); void setupDefault(); void setDepthColumnWidth(QTableView* table); void setDepthColumnDelegate(QTableView* table); @@ -60,6 +79,7 @@ private: void setColumnWidths(QTableView* table); void setColumnDelegates(QTableView* table); void setupArray(); + void update2DArray(); }; } // namespace MatGui diff --git a/src/Mod/Material/Gui/ArrayDelegate.cpp b/src/Mod/Material/Gui/ArrayDelegate.cpp index 95c030a159..255cac8168 100644 --- a/src/Mod/Material/Gui/ArrayDelegate.cpp +++ b/src/Mod/Material/Gui/ArrayDelegate.cpp @@ -156,8 +156,8 @@ QWidget* ArrayDelegate::createWidget(QWidget* parent, const QVariant& item) cons else if (_type == Materials::MaterialValue::Boolean) { Gui::PrefComboBox* combo = new Gui::PrefComboBox(parent); combo->insertItem(0, QString::fromStdString("")); - combo->insertItem(1, QString::fromStdString("False")); - combo->insertItem(2, QString::fromStdString("True")); + combo->insertItem(1, tr("False")); + combo->insertItem(2, tr("True")); combo->setCurrentText(item.toString()); widget = combo; } diff --git a/src/Mod/Material/Gui/ArrayDelegate.h b/src/Mod/Material/Gui/ArrayDelegate.h index 74e9c76c36..2f07398a79 100644 --- a/src/Mod/Material/Gui/ArrayDelegate.h +++ b/src/Mod/Material/Gui/ArrayDelegate.h @@ -22,8 +22,6 @@ #ifndef MATGUI_ArrayDelegate_H #define MATGUI_ArrayDelegate_H -#include - #include #include #include @@ -35,8 +33,6 @@ #include #include -namespace fs = boost::filesystem; - namespace MatGui { @@ -44,10 +40,9 @@ class ArrayDelegate: public QStyledItemDelegate { Q_OBJECT public: - explicit ArrayDelegate( - Materials::MaterialValue::ValueType type = Materials::MaterialValue::None, - QString units = QString(), - QObject* parent = nullptr); + ArrayDelegate(Materials::MaterialValue::ValueType type = Materials::MaterialValue::None, + QString units = QString(), + QObject* parent = nullptr); virtual ~ArrayDelegate() = default; void paint(QPainter* painter, diff --git a/src/Mod/Material/Gui/ArrayModel.cpp b/src/Mod/Material/Gui/ArrayModel.cpp index 24c0ba8b42..8c1156faeb 100644 --- a/src/Mod/Material/Gui/ArrayModel.cpp +++ b/src/Mod/Material/Gui/ArrayModel.cpp @@ -26,6 +26,7 @@ #include +#include #include #include @@ -46,7 +47,7 @@ AbstractArrayModel::AbstractArrayModel(QObject* parent) //=== -Array2DModel::Array2DModel(const Materials::MaterialProperty* property, +Array2DModel::Array2DModel(std::shared_ptr property, std::shared_ptr value, QObject* parent) : AbstractArrayModel(parent) @@ -68,6 +69,12 @@ bool Array2DModel::newRow(const QModelIndex& index) const return (index.row() == _value->rows()); } +void Array2DModel::deleteRow(const QModelIndex& index) +{ + removeRows(index.row(), 1); + Q_EMIT dataChanged(index, index); +} + int Array2DModel::columnCount(const QModelIndex& parent) const { Q_UNUSED(parent); @@ -145,7 +152,7 @@ bool Array2DModel::insertRows(int row, int count, const QModelIndex& parent) int columns = columnCount(); for (int i = 0; i < count; i++) { - std::vector* rowPtr = new std::vector(); + auto rowPtr = std::make_shared>(); for (int j = 0; j < columns; j++) { rowPtr->push_back(_property->getColumnNull(j)); } @@ -162,6 +169,10 @@ bool Array2DModel::removeRows(int row, int count, const QModelIndex& parent) { beginRemoveRows(parent, row, row + count - 1); + for (int i = 0; i < count; i++) { + _value->deleteRow(row); + } + endRemoveRows(); return false; @@ -187,7 +198,7 @@ bool Array2DModel::removeColumns(int column, int count, const QModelIndex& paren //=== -Array3DDepthModel::Array3DDepthModel(const Materials::MaterialProperty* property, +Array3DDepthModel::Array3DDepthModel(std::shared_ptr property, std::shared_ptr value, QObject* parent) : AbstractArrayModel(parent) @@ -209,26 +220,34 @@ bool Array3DDepthModel::newRow(const QModelIndex& index) const return (index.row() == _value->depth()); } +void Array3DDepthModel::deleteRow(const QModelIndex& index) +{ + removeRows(index.row(), 1); + Q_EMIT dataChanged(index, index); +} + QVariant Array3DDepthModel::data(const QModelIndex& index, int role) const { if (role == Qt::DisplayRole) { try { - return _value->getValue(index.row(), index.column()); + Base::Quantity q = _value->getDepthValue(index.row()); + return QVariant::fromValue(q); + } + catch (const Materials::InvalidDepth&) { + } + catch (const Materials::InvalidRow&) { + } + catch (const Materials::InvalidColumn&) { } catch (const Materials::InvalidIndex&) { } try { - auto column = _property->getColumnType(index.column()); - if (column == Materials::MaterialValue::Quantity) { - Base::Quantity q = Base::Quantity(0, _property->getColumnUnits(index.column())); - return QVariant::fromValue(q); - } + Base::Quantity q = Base::Quantity(0, _property->getColumnUnits(0)); + return QVariant::fromValue(q); } catch (const Materials::InvalidColumn&) { } - - return QString(); } return QVariant(); @@ -259,8 +278,9 @@ bool Array3DDepthModel::setData(const QModelIndex& index, const QVariant& value, if (index.row() == _value->depth()) { insertRows(index.row(), 1); + _value->setCurrentDepth(index.row()); } - _value->setValue(index.row(), index.column(), value); + _value->setDepthValue(index.row(), value.value()); Q_EMIT dataChanged(index, index); return true; @@ -277,14 +297,8 @@ bool Array3DDepthModel::insertRows(int row, int count, const QModelIndex& parent { beginInsertRows(parent, row, row + count - 1); - int columns = columnCount(); for (int i = 0; i < count; i++) { - std::vector* rowPtr = new std::vector(); - for (int j = 0; j < columns; j++) { - rowPtr->push_back(_property->getColumnNull(j)); - } - - // _value->insertRow(row, rowPtr); + _value->addDepth(row, Base::Quantity(0, _property->getColumnUnits(0))); } endInsertRows(); @@ -296,6 +310,10 @@ bool Array3DDepthModel::removeRows(int row, int count, const QModelIndex& parent { beginRemoveRows(parent, row, row + count - 1); + for (int i = 0; i < count; i++) { + _value->deleteDepth(row); + } + endRemoveRows(); return false; @@ -321,7 +339,7 @@ bool Array3DDepthModel::removeColumns(int column, int count, const QModelIndex& //=== -Array3DModel::Array3DModel(const Materials::MaterialProperty* property, +Array3DModel::Array3DModel(std::shared_ptr property, std::shared_ptr value, QObject* parent) : AbstractArrayModel(parent) @@ -335,7 +353,15 @@ int Array3DModel::rowCount(const QModelIndex& parent) const return 0; // No children } - return _value->depth() + 1; // Will always have 1 empty row + try { + return _value->rows() + 1; // Will always have 1 empty row + } + catch (const Materials::InvalidDepth&) { + return 1; + } + catch (const Materials::InvalidRow&) { + return 1; + } } int Array3DModel::columnCount(const QModelIndex& parent) const @@ -347,15 +373,36 @@ int Array3DModel::columnCount(const QModelIndex& parent) const bool Array3DModel::newRow(const QModelIndex& index) const { - return (index.row() == _value->depth()); + try { + return (index.row() == _value->rows()); + } + catch (const Materials::InvalidDepth&) { + return true; + } + catch (const Materials::InvalidRow&) { + return true; + } +} + +void Array3DModel::deleteRow(const QModelIndex& index) +{ + removeRows(index.row(), 1); + Q_EMIT dataChanged(index, index); } QVariant Array3DModel::data(const QModelIndex& index, int role) const { if (role == Qt::DisplayRole) { - Base::Console().Error("Row %d, column %d\n", index.row(), index.column()); + // Base::Console().Log("Row %d, column %d\n", index.row(), index.column()); try { - return _value->getValue(index.row(), index.column() + 1); + Base::Quantity q = _value->getValue(index.row(), index.column()); + return QVariant::fromValue(q); + } + catch (const Materials::InvalidDepth&) { + } + catch (const Materials::InvalidRow&) { + } + catch (const Materials::InvalidColumn&) { } catch (const Materials::InvalidIndex&) { } @@ -364,16 +411,11 @@ QVariant Array3DModel::data(const QModelIndex& index, int role) const } try { - auto column = _property->getColumnType(index.column() + 1); - if (column == Materials::MaterialValue::Quantity) { - Base::Quantity q = Base::Quantity(0, _property->getColumnUnits(index.column() - 1)); - return QVariant::fromValue(q); - } + Base::Quantity q = Base::Quantity(0, _property->getColumnUnits(index.column() + 1)); + return QVariant::fromValue(q); } catch (const Materials::InvalidColumn&) { } - - return QString(); } return QVariant(); @@ -402,10 +444,32 @@ bool Array3DModel::setData(const QModelIndex& index, const QVariant& value, int { Q_UNUSED(role); - if (index.row() == _value->depth()) { + Base::Console().Log("Array3DModel::setData at (%d, %d, %d)\n", + _value->currentDepth(), + index.row(), + index.column()); + + if (_value->depth() == 0) { + // Create the first row + // _value->addDepth(Base::Quantity(0, _property->getColumnUnits(0))); + return false; + } + + if (index.row() == _value->rows()) { insertRows(index.row(), 1); } - _value->setValue(index.row(), index.column(), value); + try { + _value->setValue(index.row(), index.column(), value.value()); + } + catch (const Materials::InvalidDepth&) { + Base::Console().Error("Array3DModel::setData - InvalidDepth"); + } + catch (const Materials::InvalidRow&) { + Base::Console().Error("Array3DModel::setData - invalidRow"); + } + catch (const Materials::InvalidColumn&) { + Base::Console().Error("Array3DModel::setData - InvalidColumn"); + } Q_EMIT dataChanged(index, index); return true; @@ -424,12 +488,12 @@ bool Array3DModel::insertRows(int row, int count, const QModelIndex& parent) int columns = columnCount(); for (int i = 0; i < count; i++) { - std::vector* rowPtr = new std::vector(); + auto rowPtr = std::make_shared>(); for (int j = 0; j < columns; j++) { - rowPtr->push_back(_property->getColumnNull(j)); + rowPtr->push_back(_property->getColumnNull(j).value()); } - // _value->insertRow(row, rowPtr); + _value->insertRow(row, rowPtr); } endInsertRows(); @@ -441,6 +505,10 @@ bool Array3DModel::removeRows(int row, int count, const QModelIndex& parent) { beginRemoveRows(parent, row, row + count - 1); + for (int i = 0; i < count; i++) { + _value->deleteRow(row); + } + endRemoveRows(); return false; @@ -463,3 +531,13 @@ bool Array3DModel::removeColumns(int column, int count, const QModelIndex& paren return false; } + +void Array3DModel::updateData() +{ + beginResetModel(); + + // The table has changed at this point, typically by setting the current depth. + // The existing structure needs to be cleared and the table redrawn. + + endResetModel(); +} diff --git a/src/Mod/Material/Gui/ArrayModel.h b/src/Mod/Material/Gui/ArrayModel.h index 7bb4f6816d..739bd6524d 100644 --- a/src/Mod/Material/Gui/ArrayModel.h +++ b/src/Mod/Material/Gui/ArrayModel.h @@ -22,6 +22,8 @@ #ifndef MATGUI_ARRAYMODEL_H #define MATGUI_ARRAYMODEL_H +#include + #include #include #include @@ -36,7 +38,7 @@ namespace MatGui class AbstractArrayModel: public QAbstractTableModel { public: - explicit AbstractArrayModel(QObject* parent = nullptr); + AbstractArrayModel(QObject* parent = nullptr); ~AbstractArrayModel() override = default; virtual bool newRow(const QModelIndex& index) const = 0; @@ -45,14 +47,15 @@ public: class Array2DModel: public AbstractArrayModel { public: - explicit Array2DModel(const Materials::MaterialProperty* property = nullptr, - std::shared_ptr value = nullptr, - QObject* parent = nullptr); + Array2DModel(std::shared_ptr property = nullptr, + std::shared_ptr value = nullptr, + QObject* parent = nullptr); ~Array2DModel() override = default; // Overridden virtual functions int rowCount(const QModelIndex& parent = QModelIndex()) const override; bool newRow(const QModelIndex& index) const override; + void deleteRow(const QModelIndex& index); int columnCount(const QModelIndex& parent = QModelIndex()) const override; QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; QVariant @@ -67,21 +70,22 @@ public: bool removeColumns(int column, int count, const QModelIndex& parent = QModelIndex()) override; private: - const Materials::MaterialProperty* _property; + std::shared_ptr _property; std::shared_ptr _value; }; class Array3DDepthModel: public AbstractArrayModel { public: - explicit Array3DDepthModel(const Materials::MaterialProperty* property = nullptr, - std::shared_ptr value = nullptr, - QObject* parent = nullptr); + Array3DDepthModel(std::shared_ptr property = nullptr, + std::shared_ptr value = nullptr, + QObject* parent = nullptr); ~Array3DDepthModel() override = default; // Overridden virtual functions int rowCount(const QModelIndex& parent = QModelIndex()) const override; bool newRow(const QModelIndex& index) const override; + void deleteRow(const QModelIndex& index); int columnCount(const QModelIndex& parent = QModelIndex()) const override { Q_UNUSED(parent) @@ -100,21 +104,22 @@ public: bool removeColumns(int column, int count, const QModelIndex& parent = QModelIndex()) override; private: - const Materials::MaterialProperty* _property; + std::shared_ptr _property; std::shared_ptr _value; }; class Array3DModel: public AbstractArrayModel { public: - explicit Array3DModel(const Materials::MaterialProperty* property = nullptr, - std::shared_ptr value = nullptr, - QObject* parent = nullptr); + Array3DModel(std::shared_ptr property = nullptr, + std::shared_ptr value = nullptr, + QObject* parent = nullptr); ~Array3DModel() override = default; // Overridden virtual functions int rowCount(const QModelIndex& parent = QModelIndex()) const override; bool newRow(const QModelIndex& index) const override; + void deleteRow(const QModelIndex& index); int columnCount(const QModelIndex& parent = QModelIndex()) const override; QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; QVariant @@ -128,8 +133,10 @@ public: bool insertColumns(int column, int count, const QModelIndex& parent = QModelIndex()) override; bool removeColumns(int column, int count, const QModelIndex& parent = QModelIndex()) override; + void updateData(); + private: - const Materials::MaterialProperty* _property; + std::shared_ptr _property; std::shared_ptr _value; }; diff --git a/src/Mod/Material/Gui/DlgSettingsMaterial.h b/src/Mod/Material/Gui/DlgSettingsMaterial.h index 4f62921794..183bfd555f 100644 --- a/src/Mod/Material/Gui/DlgSettingsMaterial.h +++ b/src/Mod/Material/Gui/DlgSettingsMaterial.h @@ -35,7 +35,7 @@ class DlgSettingsMaterial: public Gui::Dialog::PreferencePage Q_OBJECT public: - explicit DlgSettingsMaterial(QWidget* parent = nullptr); + DlgSettingsMaterial(QWidget* parent = nullptr); ~DlgSettingsMaterial() override = default; protected: diff --git a/src/Mod/Material/Gui/MaterialDelegate.cpp b/src/Mod/Material/Gui/MaterialDelegate.cpp index 92f96ab7dd..ee9d4b7144 100644 --- a/src/Mod/Material/Gui/MaterialDelegate.cpp +++ b/src/Mod/Material/Gui/MaterialDelegate.cpp @@ -88,7 +88,7 @@ bool MaterialDelegate::editorEvent(QEvent* event, std::string type = propertyType.toStdString(); if (type == "Color") { Base::Console().Log("Edit color\n"); - showColorModal(item); + showColorModal(item, propertyName); // Mark as handled return true; } @@ -109,7 +109,7 @@ bool MaterialDelegate::editorEvent(QEvent* event, return QStyledItemDelegate::editorEvent(event, model, option, index); } -void MaterialDelegate::showColorModal(QStandardItem* item) +void MaterialDelegate::showColorModal(QStandardItem* item, QString propertyName) { QColor currentColor; // = d->col; currentColor.setRgba(parseColor(item->text())); @@ -126,14 +126,18 @@ void MaterialDelegate::showColorModal(QStandardItem* item) connect(dlg, &QColorDialog::finished, this, [&](int result) { if (result == QDialog::Accepted) { + Base::Console().Log("Accepted\n"); QColor color = dlg->selectedColor(); if (color.isValid()) { + Base::Console().Log("isValid\n"); QString colorText = QString(QString::fromStdString("(%1,%2,%3,%4)")) .arg(color.red() / 255.0) .arg(color.green() / 255.0) .arg(color.blue() / 255.0) .arg(color.alpha() / 255.0); item->setText(colorText); + Q_EMIT const_cast(this)->propertyChange(propertyName, + item->text()); } } }); @@ -143,7 +147,7 @@ void MaterialDelegate::showColorModal(QStandardItem* item) void MaterialDelegate::showArray2DModal(const QString& propertyName, QStandardItem* item) { - Materials::Material* material = item->data().value(); + auto material = item->data().value>(); Array2D* dlg = new Array2D(propertyName, material); dlg->setAttribute(Qt::WA_DeleteOnClose); @@ -161,7 +165,7 @@ void MaterialDelegate::showArray2DModal(const QString& propertyName, QStandardIt void MaterialDelegate::showArray3DModal(const QString& propertyName, QStandardItem* item) { - Materials::Material* material = item->data().value(); + auto material = item->data().value>(); Array3D* dlg = new Array3D(propertyName, material); dlg->setAttribute(Qt::WA_DeleteOnClose); @@ -411,8 +415,8 @@ QWidget* MaterialDelegate::createWidget(QWidget* parent, else if (type == "Boolean") { Gui::PrefComboBox* combo = new Gui::PrefComboBox(parent); combo->insertItem(0, QString::fromStdString("")); - combo->insertItem(1, QString::fromStdString("False")); - combo->insertItem(2, QString::fromStdString("True")); + combo->insertItem(1, tr("False")); + combo->insertItem(2, tr("True")); combo->setCurrentText(propertyValue); widget = combo; } diff --git a/src/Mod/Material/Gui/MaterialDelegate.h b/src/Mod/Material/Gui/MaterialDelegate.h index 1febeb11cf..a395fa8d9f 100644 --- a/src/Mod/Material/Gui/MaterialDelegate.h +++ b/src/Mod/Material/Gui/MaterialDelegate.h @@ -22,8 +22,6 @@ #ifndef MATGUI_MATERIALDELEGATE_H #define MATGUI_MATERIALDELEGATE_H -#include - #include #include #include @@ -35,8 +33,6 @@ #include #include -namespace fs = boost::filesystem; - namespace MatGui { @@ -44,7 +40,7 @@ class MaterialDelegate: public QStyledItemDelegate { Q_OBJECT public: - explicit MaterialDelegate(QObject* parent = nullptr); + MaterialDelegate(QObject* parent = nullptr); ~MaterialDelegate() override = default; QWidget* createEditor(QWidget* parent, @@ -76,7 +72,7 @@ private: const QString& propertyValue, const QString& propertyUnits) const; QRgb parseColor(const QString& color) const; - void showColorModal(QStandardItem* item); + void showColorModal(QStandardItem* item, QString propertyName); void showArray2DModal(const QString& propertyName, QStandardItem* item); void showArray3DModal(const QString& propertyName, QStandardItem* item); }; diff --git a/src/Mod/Material/Gui/MaterialSave.cpp b/src/Mod/Material/Gui/MaterialSave.cpp index 58d610e4e8..853c973ea2 100644 --- a/src/Mod/Material/Gui/MaterialSave.cpp +++ b/src/Mod/Material/Gui/MaterialSave.cpp @@ -21,6 +21,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ +#include #include #include #endif @@ -36,12 +37,15 @@ using namespace MatGui; /* TRANSLATOR MatGui::MaterialsEditor */ -MaterialSave::MaterialSave(Materials::Material* material, QWidget* parent) +MaterialSave::MaterialSave(std::shared_ptr material, QWidget* parent) : QDialog(parent) , ui(new Ui_MaterialSave) , _material(material) + , _saveInherited(true) , _selectedPath(QString::fromStdString("/")) + , _selectedFull(QString::fromStdString("/")) , _selectedUUID(QString()) + , _deleteAction(this) { ui->setupUi(this); @@ -57,6 +61,9 @@ MaterialSave::MaterialSave(Materials::Material* material, QWidget* parent) } _filename = QString(ui->editFilename->text()); // No filename by default + ui->checkDerived->setChecked(_saveInherited); + connect(ui->checkDerived, &QCheckBox::stateChanged, this, &MaterialSave::onInherited); + connect(ui->standardButtons->button(QDialogButtonBox::Ok), &QPushButton::clicked, this, @@ -73,11 +80,25 @@ MaterialSave::MaterialSave(Materials::Material* material, QWidget* parent) connect(ui->buttonNewFolder, &QPushButton::clicked, this, &MaterialSave::onNewFolder); connect(ui->editFilename, &QLineEdit::textEdited, this, &MaterialSave::onFilename); + ui->treeMaterials->setContextMenuPolicy(Qt::CustomContextMenu); + connect(ui->treeMaterials, + &QWidget::customContextMenuRequested, + this, + &MaterialSave::onContextMenu); + + _deleteAction.setText(tr("Delete")); + _deleteAction.setShortcut(Qt::Key_Delete); + connect(&_deleteAction, &QAction::triggered, this, &MaterialSave::onDelete); + ui->treeMaterials->addAction(&_deleteAction); + QItemSelectionModel* selectionModel = ui->treeMaterials->selectionModel(); connect(selectionModel, &QItemSelectionModel::selectionChanged, this, &MaterialSave::onSelectModel); + + auto model = static_cast(ui->treeMaterials->model()); + connect(model, &QStandardItemModel::itemChanged, this, &MaterialSave::onItemChanged); } /* @@ -88,6 +109,13 @@ MaterialSave::~MaterialSave() // no need to delete child widgets, Qt does it all for us } +void MaterialSave::onInherited(int state) +{ + Q_UNUSED(state) + + _saveInherited = ui->checkDerived->isChecked(); +} + void MaterialSave::onOk(bool checked) { Q_UNUSED(checked) @@ -100,18 +128,145 @@ void MaterialSave::onOk(bool checked) } auto variant = ui->comboLibrary->currentData(); - auto library = variant.value(); + auto library = variant.value>(); QFileInfo filepath(_selectedPath + QString::fromStdString("/") + name + QString::fromStdString(".FCMat")); Base::Console().Log("saveMaterial(library(%s), material(%s), path(%s))\n", - library.getName().toStdString().c_str(), + library->getName().toStdString().c_str(), _material->getName().toStdString().c_str(), filepath.filePath().toStdString().c_str()); - _manager.saveMaterial(&library, *_material, filepath.filePath()); + + if (library->fileExists(filepath.filePath())) { + // confirm overwrite + auto res = confirmOverwrite(_filename); + if (res == QMessageBox::Cancel) { + return; + } + + _manager.saveMaterial(library, _material, filepath.filePath(), true, false, _saveInherited); + accept(); + return; + } + + bool saveAsCopy = false; + if (_manager.exists(_material->getUUID())) { + // Does it already exist in this library? + if (_manager.exists(library, _material->getUUID())) { + // Confirm saving a new material + auto res = confirmNewMaterial(); + if (res == QMessageBox::Cancel) { + return; + } + // saveAsCopy = false = already done + } + else { + // Copy or new + auto res = confirmCopy(); + if (res == QMessageBox::Cancel) { + return; + } + else if (res == QMessageBox::Save) { + // QMessageBox::Save saves as normal, a duplicate + saveAsCopy = true; + } + // QMessageBox::Ok saves a new material + } + } + + _manager + .saveMaterial(library, _material, filepath.filePath(), false, saveAsCopy, _saveInherited); accept(); } +int MaterialSave::confirmOverwrite(const QString& filename) +{ + QMessageBox box(this); + box.setIcon(QMessageBox::Question); + box.setWindowTitle(QObject::tr("Confirm Overwrite")); + + QFileInfo info(_selectedFull); + QString prompt = tr("Are you sure you want to save over '%1'?").arg(filename); + box.setText(prompt); + + box.setInformativeText(tr("Saving over the original file may cause other documents to break. " + "This is not recommended.")); + + box.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel); + box.setDefaultButton(QMessageBox::Cancel); + box.setEscapeButton(QMessageBox::Cancel); + + int res = QMessageBox::Cancel; + box.adjustSize(); // Silence warnings from Qt on Windows + switch (box.exec()) { + case QMessageBox::Ok: + res = QMessageBox::Ok; + break; + } + + return res; +} + +int MaterialSave::confirmNewMaterial() +{ + QMessageBox box(this); + box.setIcon(QMessageBox::Question); + box.setWindowTitle(tr("Confirm Save As New Material")); + + QString prompt = tr("Save as new material"); + box.setText(prompt); + + box.setInformativeText(tr( + "This material already exists in this library. Would you like to save as a new material?")); + + box.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel); + box.setDefaultButton(QMessageBox::Cancel); + box.setEscapeButton(QMessageBox::Cancel); + + int res = QMessageBox::Cancel; + box.adjustSize(); // Silence warnings from Qt on Windows + switch (box.exec()) { + case QMessageBox::Ok: + res = QMessageBox::Ok; + break; + } + + return res; +} + +int MaterialSave::confirmCopy() +{ + QMessageBox box(this); + box.setIcon(QMessageBox::Question); + box.setWindowTitle(tr("Confirm Save As Copy")); + + QString prompt = tr("Save as Copy"); + box.setText(prompt); + + box.setInformativeText(tr("Saving a copy is not recommended as it can break other documents. " + "We recommend you save as a new material.")); + + QPushButton* duplicateButton = box.addButton(tr("Save Copy"), QMessageBox::AcceptRole); + QPushButton* newButton = box.addButton(tr("Save As New"), QMessageBox::ActionRole); + QPushButton* cancelButton = box.addButton(QMessageBox::Cancel); + + box.setDefaultButton(cancelButton); + box.setEscapeButton(cancelButton); + + box.adjustSize(); // Silence warnings from Qt on Windows + box.exec(); + + int res = QMessageBox::Cancel; + if (box.clickedButton() == duplicateButton) { + res = QMessageBox::Save; + } + else if (box.clickedButton() == newButton) { + res = QMessageBox::Ok; + } + + return res; +} + void MaterialSave::onCancel(bool checked) { Q_UNUSED(checked) @@ -135,7 +290,7 @@ void MaterialSave::setLibraries() for (auto library : *libraries) { if (!library->isReadOnly()) { QVariant libraryVariant; - libraryVariant.setValue(*library); + libraryVariant.setValue(library); ui->comboLibrary->addItem(library->getName(), libraryVariant); } } @@ -163,31 +318,34 @@ void MaterialSave::addExpanded(QTreeView* tree, QStandardItemModel* parent, QSta void MaterialSave::addMaterials( QStandardItem& parent, - const std::shared_ptr> modelTree, + const std::shared_ptr>> + modelTree, const QIcon& folderIcon, const QIcon& icon) { auto tree = ui->treeMaterials; for (auto& mat : *modelTree) { - Materials::MaterialTreeNode* nodePtr = mat.second; + std::shared_ptr nodePtr = mat.second; if (nodePtr->getType() == Materials::MaterialTreeNode::DataNode) { - const Materials::Material* material = nodePtr->getData(); + std::shared_ptr material = nodePtr->getData(); QString uuid = material->getUUID(); Base::Console().Log("Material path '%s'\n", material->getDirectory().toStdString().c_str()); - // auto card = new QStandardItem(icon, material->getName()); auto card = new QStandardItem(icon, mat.first); - // card->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled - // | Qt::ItemIsDropEnabled); + card->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled + | Qt::ItemIsDropEnabled); card->setData(QVariant(uuid), Qt::UserRole); addExpanded(tree, &parent, card); } else { + Base::Console().Log("Material folder path '%s'\n", mat.first.toStdString().c_str()); auto node = new QStandardItem(folderIcon, mat.first); + node->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled + | Qt::ItemIsDropEnabled | Qt::ItemIsEditable); addExpanded(tree, &parent, node); - // node->setFlags(Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled); + auto treeMap = nodePtr->getFolder(); addMaterials(*node, treeMap, folderIcon, icon); } @@ -202,13 +360,14 @@ void MaterialSave::showSelectedTree() if (ui->comboLibrary->count() > 0) { auto variant = ui->comboLibrary->currentData(); - auto library = variant.value(); - QIcon icon(library.getIconPath()); + auto library = variant.value>(); + QIcon icon(library->getIconPath()); QIcon folderIcon(QString::fromStdString(":/icons/folder.svg")); - _libraryName = library.getName(); + _libraryName = library->getName(); _selectedPath = QString::fromStdString("/") + _libraryName; + _selectedFull = _selectedPath; - auto lib = new QStandardItem(library.getName()); + auto lib = new QStandardItem(library->getName()); lib->setFlags(Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled); addExpanded(tree, model, lib); @@ -246,6 +405,7 @@ void MaterialSave::onSelectModel(const QItemSelection& selected, const QItemSele if (indexes.count() == 0) { Base::Console().Log("Nothing selected\n"); _selectedPath = QString::fromStdString("/") + _libraryName; + _selectedFull = _selectedPath; _selectedUUID = QString(); Base::Console().Log("\tSelected path '%s'\n", _selectedPath.toStdString().c_str()); return; @@ -258,11 +418,13 @@ void MaterialSave::onSelectModel(const QItemSelection& selected, const QItemSele if (_selected.isValid()) { Base::Console().Log("\tuuid %s\n", _selected.toString().toStdString().c_str()); _selectedPath = getPath(item->parent()); + _selectedFull = getPath(item); _selectedUUID = _selected.toString(); _filename = item->text(); } else { _selectedPath = getPath(item); + _selectedFull = _selectedPath; _selectedUUID = QString(); } } @@ -282,6 +444,34 @@ void MaterialSave::currentTextChanged(const QString& value) showSelectedTree(); } +std::shared_ptr MaterialSave::currentLibrary() +{ + auto variant = ui->comboLibrary->currentData(); + return variant.value>(); +} + +void MaterialSave::createFolder(const QString& path) +{ + auto library = currentLibrary(); + + _manager.createFolder(library, path); +} + +void MaterialSave::renameFolder(const QString& oldPath, const QString& newPath) +{ + auto library = currentLibrary(); + + _manager.renameFolder(library, oldPath, newPath); +} + +void MaterialSave::deleteRecursive(const QString& path) +{ + // This will delete files, folders, and any children + auto library = currentLibrary(); + + _manager.deleteRecursive(library, path); +} + void MaterialSave::onNewFolder(bool checked) { Q_UNUSED(checked) @@ -293,16 +483,53 @@ void MaterialSave::onNewFolder(bool checked) current = model->index(0, 0); } auto item = model->itemFromIndex(current); + + // Check for existing folders starting "New Folder" to prevent duplicates + int newCount = 0; if (item->hasChildren()) { + for (auto i = 0; i < item->rowCount(); i++) { + auto child = item->child(i); + if (child->text().startsWith(tr("New Folder"))) { + newCount++; + } + } + } + + // Folders have no associated data + if (item->data(Qt::UserRole).isNull()) { Base::Console().Log("Add new folder to '%s'\n", item->text().toStdString().c_str()); QIcon folderIcon(QString::fromStdString(":/icons/folder.svg")); - auto node = new QStandardItem(folderIcon, QString::fromStdString("New Folder")); + QString folderName = tr("New Folder"); + if (newCount > 0) { + folderName += QString::number(newCount); + } + auto node = new QStandardItem(folderIcon, folderName); + node->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled + | Qt::ItemIsDropEnabled | Qt::ItemIsEditable); addExpanded(tree, item, node); - // node->setFlags(Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled); + + Base::Console().Log("New folder index valid: %s\n", + node->index().isValid() ? "true" : "false"); + + QItemSelectionModel* selectionModel = ui->treeMaterials->selectionModel(); + selectionModel->select(node->index(), + QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Current); + + createFolder(getPath(node)); } } +void MaterialSave::onItemChanged(QStandardItem* item) +{ + Base::Console().Log("MaterialSave::onItemChanged('%s')\n", item->text().toStdString().c_str()); + QString oldPath = _selectedPath; + _selectedPath = getPath(item); + _selectedFull = _selectedPath; + Base::Console().Log("\tSelected path '%s'\n", _selectedPath.toStdString().c_str()); + renameFolder(oldPath, _selectedPath); +} + void MaterialSave::onFilename(const QString& text) { Base::Console().Log("MaterialSave::onFilename('%s')\n", text.toStdString().c_str()); @@ -310,4 +537,135 @@ void MaterialSave::onFilename(const QString& text) _filename = text; } +QString MaterialSave::pathFromIndex(const QModelIndex& index) const +{ + auto model = static_cast(index.model()); + auto item = model->itemFromIndex(index); + return getPath(item); +} + +void MaterialSave::onContextMenu(const QPoint& pos) +{ + Base::Console().Log("MaterialSave::onContextMenu(%d,%d)\n", pos.x(), pos.y()); + QModelIndex index = ui->treeMaterials->indexAt(pos); + QString path = pathFromIndex(index); + Base::Console().Log("\tindex at (%d,%d)->'%s'\n", + index.row(), + index.column(), + path.toStdString().c_str()); + + + QMenu contextMenu(tr("Context menu"), this); + + // QAction action1(tr("Delete"), this); + // action1.setShortcut(Qt::Key_Delete); + // connect(&action1, &QAction::triggered, this, &MaterialSave::onDelete); + contextMenu.addAction(&_deleteAction); + + contextMenu.exec(ui->treeMaterials->mapToGlobal(pos)); +} + +void MaterialSave::onDelete(bool checked) +{ + Q_UNUSED(checked) + + Base::Console().Log("MaterialSave::onDelete()\n"); + QItemSelectionModel* selectionModel = ui->treeMaterials->selectionModel(); + if (!selectionModel->hasSelection()) { + Base::Console().Log("\tNothing selected\n"); + return; + } + + Base::Console().Log("\tSelected path '%s'\n", _selectedFull.toStdString().c_str()); + int res = confirmDelete(this); + if (res == QMessageBox::Cancel) { + return; + } +} + +int MaterialSave::confirmDelete(QWidget* parent) +{ + auto library = currentLibrary(); + + if (library->isRoot(_selectedFull)) { + return QMessageBox::Cancel; + } + + QMessageBox box(parent ? parent : this); + box.setIcon(QMessageBox::Question); + box.setWindowTitle(QObject::tr("Confirm Delete")); + + QFileInfo info(_selectedFull); + QString prompt = QObject::tr("Are you sure you want to delete '%1'?").arg(info.fileName()); + box.setText(prompt); + + if (selectedHasChildren()) { + box.setInformativeText(QObject::tr("Removing this will also remove all contents.")); + } + box.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel); + box.setDefaultButton(QMessageBox::Cancel); + box.setEscapeButton(QMessageBox::Cancel); + + int res = QMessageBox::Cancel; + box.adjustSize(); // Silence warnings from Qt on Windows + switch (box.exec()) { + case QMessageBox::Ok: + deleteSelected(); + res = QMessageBox::Ok; + break; + } + + return res; +} + +bool MaterialSave::selectedHasChildren() +{ + auto tree = ui->treeMaterials; + auto model = static_cast(tree->model()); + auto current = tree->currentIndex(); + if (!current.isValid()) { + current = model->index(0, 0); + } + auto item = model->itemFromIndex(current); + + return item->hasChildren(); +} + +void MaterialSave::deleteSelected() +{ + Base::Console().Log("\tDelete selected path '%s'\n", _selectedFull.toStdString().c_str()); + auto library = currentLibrary(); + + if (!library->isRoot(_selectedFull)) { + _manager.deleteRecursive(library, _selectedFull); + removeSelectedFromTree(); + } +} + +void MaterialSave::removeChildren(QStandardItem* item) +{ + while (item->rowCount() > 0) { + auto child = item->child(0); + removeChildren(child); + item->removeRow(0); + } +} + +void MaterialSave::removeSelectedFromTree() +{ + auto tree = ui->treeMaterials; + auto model = static_cast(tree->model()); + auto current = tree->currentIndex(); + if (current.row() >= 0) { + auto item = model->itemFromIndex(current); + + // Remove the children + removeChildren(item); + item->parent()->removeRow(item->row()); + } + + QItemSelectionModel* selectionModel = ui->treeMaterials->selectionModel(); + selectionModel->clear(); +} + #include "moc_MaterialSave.cpp" diff --git a/src/Mod/Material/Gui/MaterialSave.h b/src/Mod/Material/Gui/MaterialSave.h index 56dc196cd1..620c21ba70 100644 --- a/src/Mod/Material/Gui/MaterialSave.h +++ b/src/Mod/Material/Gui/MaterialSave.h @@ -22,8 +22,9 @@ #ifndef MATGUI_MATERIALSAVE_H #define MATGUI_MATERIALSAVE_H -// #include +#include +#include #include #include #include @@ -41,39 +42,61 @@ class MaterialSave: public QDialog Q_OBJECT public: - explicit MaterialSave(Materials::Material* material, QWidget* parent = nullptr); + MaterialSave(std::shared_ptr material, QWidget* parent = nullptr); ~MaterialSave() override; void setLibraries(); void createModelTree(); void addExpanded(QTreeView* tree, QStandardItem* parent, QStandardItem* child); void addExpanded(QTreeView* tree, QStandardItemModel* parent, QStandardItem* child); - void - addMaterials(QStandardItem& parent, - const std::shared_ptr> modelTree, - const QIcon& folderIcon, - const QIcon& icon); + void addMaterials( + QStandardItem& parent, + const std::shared_ptr>> + modelTree, + const QIcon& folderIcon, + const QIcon& icon); void showSelectedTree(); void onSelectModel(const QItemSelection& selected, const QItemSelection& deselected); void currentTextChanged(const QString& value); void onNewFolder(bool checked); + void onItemChanged(QStandardItem* item); void onFilename(const QString& text); + void onContextMenu(const QPoint& pos); + void onDelete(bool checked); + void onInherited(int state); void onOk(bool checked); void onCancel(bool checked); + int confirmOverwrite(const QString& filename); + int confirmNewMaterial(); + int confirmCopy(); void accept() override; void reject() override; private: std::unique_ptr ui; Materials::MaterialManager _manager; - Materials::Material* _material; + std::shared_ptr _material; + bool _saveInherited; QString _selectedPath; + QString _selectedFull; QString _selectedUUID; QString _libraryName; QString _filename; + QAction _deleteAction; + QString getPath(const QStandardItem* item) const; + std::shared_ptr currentLibrary(); + void createFolder(const QString& path); + void renameFolder(const QString& oldPath, const QString& newPath); + void deleteRecursive(const QString& path); + QString pathFromIndex(const QModelIndex& index) const; + int confirmDelete(QWidget* parent); + bool selectedHasChildren(); + void deleteSelected(); + void removeChildren(QStandardItem* item); + void removeSelectedFromTree(); }; } // namespace MatGui diff --git a/src/Mod/Material/Gui/MaterialSave.ui b/src/Mod/Material/Gui/MaterialSave.ui index a6a719e5a6..7298e6a23a 100644 --- a/src/Mod/Material/Gui/MaterialSave.ui +++ b/src/Mod/Material/Gui/MaterialSave.ui @@ -83,6 +83,30 @@ + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Save as Inherited + + + + + diff --git a/src/Mod/Material/Gui/MaterialsEditor.cpp b/src/Mod/Material/Gui/MaterialsEditor.cpp index 7916805b0c..c3c15c6b2a 100644 --- a/src/Mod/Material/Gui/MaterialsEditor.cpp +++ b/src/Mod/Material/Gui/MaterialsEditor.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -35,6 +36,7 @@ #include #include +#include #include #include #include @@ -61,6 +63,7 @@ using namespace MatGui; MaterialsEditor::MaterialsEditor(QWidget* parent) : QDialog(parent) , ui(new Ui_MaterialsEditor) + , _material(std::make_shared()) , _edited(false) { ui->setupUi(this); @@ -72,6 +75,7 @@ MaterialsEditor::MaterialsEditor(QWidget* parent) createPhysicalTree(); createAppearanceTree(); createPreviews(); + setMaterialDefaults(); ui->buttonURL->setIcon(QIcon(QString::fromStdString(":/icons/internet-web-browser.svg"))); @@ -88,12 +92,35 @@ MaterialsEditor::MaterialsEditor(QWidget* parent) this, &MaterialsEditor::onSave); + connect(ui->editName, &QLineEdit::textEdited, this, &MaterialsEditor::onName); + connect(ui->editAuthor, &QLineEdit::textEdited, this, &MaterialsEditor::onAuthor); + connect(ui->editLicense, &QLineEdit::textEdited, this, &MaterialsEditor::onLicense); + connect(ui->editSourceURL, &QLineEdit::textEdited, this, &MaterialsEditor::onSourceURL); + connect(ui->editSourceReference, + &QLineEdit::textEdited, + this, + &MaterialsEditor::onSourceReference); + connect(ui->editDescription, &QTextEdit::textChanged, this, &MaterialsEditor::onDescription); + connect(ui->buttonURL, &QPushButton::clicked, this, &MaterialsEditor::onURL); connect(ui->buttonPhysicalAdd, &QPushButton::clicked, this, &MaterialsEditor::onPhysicalAdd); + connect(ui->buttonPhysicalRemove, + &QPushButton::clicked, + this, + &MaterialsEditor::onPhysicalRemove); connect(ui->buttonAppearanceAdd, &QPushButton::clicked, this, &MaterialsEditor::onAppearanceAdd); + connect(ui->buttonAppearanceRemove, + &QPushButton::clicked, + this, + &MaterialsEditor::onAppearanceRemove); + connect(ui->buttonInheritNew, + &QPushButton::clicked, + this, + &MaterialsEditor::onInheritNewMaterial); + connect(ui->buttonNew, &QPushButton::clicked, this, &MaterialsEditor::onNewMaterial); connect(ui->buttonFavorite, &QPushButton::clicked, this, &MaterialsEditor::onFavourite); QItemSelectionModel* selectionModel = ui->treeMaterials->selectionModel(); @@ -101,6 +128,13 @@ MaterialsEditor::MaterialsEditor(QWidget* parent) &QItemSelectionModel::selectionChanged, this, &MaterialsEditor::onSelectMaterial); + connect(ui->treeMaterials, &QTreeView::doubleClicked, this, &MaterialsEditor::onDoubleClick); + + ui->treeMaterials->setContextMenuPolicy(Qt::CustomContextMenu); + connect(ui->treeMaterials, + &QWidget::customContextMenuRequested, + this, + &MaterialsEditor::onContextMenu); } void MaterialsEditor::getFavorites() @@ -144,7 +178,7 @@ void MaterialsEditor::addFavorite(const QString& uuid) { // Ensure it is a material. New, unsaved materials will not be try { - const Materials::Material& material = _materialManager.getMaterial(uuid); + auto material = _materialManager.getMaterial(uuid); Q_UNUSED(material) } catch (const Materials::MaterialNotFound&) { @@ -227,7 +261,7 @@ void MaterialsEditor::addRecent(const QString& uuid) { // Ensure it is a material. New, unsaved materials will not be try { - const Materials::Material& material = _materialManager.getMaterial(uuid); + auto material = _materialManager.getMaterial(uuid); Q_UNUSED(material) } catch (const Materials::MaterialNotFound&) { @@ -257,16 +291,46 @@ bool MaterialsEditor::isRecent(const QString& uuid) const return false; } +void MaterialsEditor::onName(const QString& text) +{ + _material->setName(text); +} + +void MaterialsEditor::onAuthor(const QString& text) +{ + _material->setAuthor(text); +} + +void MaterialsEditor::onLicense(const QString& text) +{ + _material->setLicense(text); +} + +void MaterialsEditor::onSourceURL(const QString& text) +{ + _material->setURL(text); +} + +void MaterialsEditor::onSourceReference(const QString& text) +{ + _material->setReference(text); +} + +void MaterialsEditor::onDescription() +{ + _material->setDescription(ui->editDescription->toPlainText()); +} + void MaterialsEditor::propertyChange(const QString& property, const QString value) { Base::Console().Log("MaterialsEditor::propertyChange(%s) = '%s'\n", property.toStdString().c_str(), value.toStdString().c_str()); - if (_material.hasPhysicalProperty(property)) { - _material.setPhysicalValue(property, value); + if (_material->hasPhysicalProperty(property)) { + _material->setPhysicalValue(property, value); } - else if (_material.hasAppearanceProperty(property)) { - _material.setAppearanceValue(property, value); + else if (_material->hasAppearanceProperty(property)) { + _material->setAppearanceValue(property, value); updatePreview(); } _edited = true; @@ -287,12 +351,12 @@ void MaterialsEditor::onPhysicalAdd(bool checked) { Q_UNUSED(checked) - ModelSelect dialog(this, Materials::ModelManager::ModelFilter_Physical); + ModelSelect dialog(this, Materials::ModelFilter_Physical); dialog.setModal(true); if (dialog.exec() == QDialog::Accepted) { QString selected = dialog.selectedModel(); Base::Console().Log("Selected model '%s'\n", selected.toStdString().c_str()); - _material.addPhysical(selected); + _material->addPhysical(selected); updateMaterial(); } else { @@ -300,16 +364,39 @@ void MaterialsEditor::onPhysicalAdd(bool checked) } } +void MaterialsEditor::onPhysicalRemove(bool checked) +{ + Q_UNUSED(checked) + + QItemSelectionModel* selectionModel = ui->treePhysicalProperties->selectionModel(); + if (selectionModel->hasSelection()) { + const QModelIndex index = selectionModel->currentIndex().siblingAtColumn(0); + + const QStandardItemModel* treeModel = static_cast(index.model()); + + // Check we're the material model root. + auto item = treeModel->itemFromIndex(index); + auto group = item->parent(); + if (!group) { + QString propertyName = index.data().toString(); + + QString uuid = _material->getModelByName(propertyName); + _material->removePhysical(uuid); + updateMaterial(); + } + } +} + void MaterialsEditor::onAppearanceAdd(bool checked) { Q_UNUSED(checked) - ModelSelect dialog(this, Materials::ModelManager::ModelFilter_Appearance); + ModelSelect dialog(this, Materials::ModelFilter_Appearance); dialog.setModal(true); if (dialog.exec() == QDialog::Accepted) { QString selected = dialog.selectedModel(); Base::Console().Log("Selected model '%s'\n", selected.toStdString().c_str()); - _material.addAppearance(selected); + _material->addAppearance(selected); updateMaterial(); } else { @@ -317,12 +404,35 @@ void MaterialsEditor::onAppearanceAdd(bool checked) } } +void MaterialsEditor::onAppearanceRemove(bool checked) +{ + Q_UNUSED(checked) + + QItemSelectionModel* selectionModel = ui->treeAppearance->selectionModel(); + if (selectionModel->hasSelection()) { + const QModelIndex index = selectionModel->currentIndex().siblingAtColumn(0); + + const QStandardItemModel* treeModel = static_cast(index.model()); + + // Check we're the material model root. + auto item = treeModel->itemFromIndex(index); + auto group = item->parent(); + if (!group) { + QString propertyName = index.data().toString(); + + QString uuid = _material->getModelByName(propertyName); + _material->removeAppearance(uuid); + updateMaterial(); + } + } +} + void MaterialsEditor::onFavourite(bool checked) { Q_UNUSED(checked) Base::Console().Log("Favorite\n"); - auto selected = _material.getUUID(); + auto selected = _material->getUUID(); if (isFavorite(selected)) { removeFavorite(selected); } @@ -331,6 +441,76 @@ void MaterialsEditor::onFavourite(bool checked) } } +void MaterialsEditor::setMaterialDefaults() +{ + _material->setName(tr("Unnamed")); + std::string Author = App::GetApplication() + .GetParameterGroupByPath("User parameter:BaseApp/Preferences/Document") + ->GetASCII("prefAuthor", ""); + _material->setAuthor(QString::fromStdString(Author)); + + // license stuff + auto paramGrp {App::GetApplication().GetParameterGroupByPath( + "User parameter:BaseApp/Preferences/Document")}; + auto index = static_cast(paramGrp->GetInt("prefLicenseType", 0)); + const char* name = App::licenseItems.at(index).at(App::posnOfFullName); + // const char* url = App::licenseItems.at(index).at(App::posnOfUrl); + // std::string licenseUrl = (paramGrp->GetASCII("prefLicenseUrl", url)); + _material->setLicense(QString::fromStdString(name)); + + // Empty materials will have no parent + _materialManager.dereference(_material); + + updateMaterial(); + _material->resetEditState(); +} + +void MaterialsEditor::onNewMaterial(bool checked) +{ + Q_UNUSED(checked) + + Base::Console().Log("New Material\n"); + + // Ensure data is saved (or discarded) before changing materials + if (_material->getEditState() != Materials::Material::ModelEdit_None) { + // Prompt the user to save or discard changes + Base::Console().Log("*** Material edited!!!\n"); + int res = confirmSave(this); + if (res == QMessageBox::Cancel) { + return; + } + } + + // Create a new material + _material = std::make_shared(); + setMaterialDefaults(); +} + +void MaterialsEditor::onInheritNewMaterial(bool checked) +{ + Q_UNUSED(checked) + + Base::Console().Log("Inherit New Material\n"); + + // Save the current UUID to use as out parent + auto parent = _material->getUUID(); + + // Ensure data is saved (or discarded) before changing materials + if (_material->getEditState() != Materials::Material::ModelEdit_None) { + // Prompt the user to save or discard changes + Base::Console().Log("*** Material edited!!!\n"); + int res = confirmSave(this); + if (res == QMessageBox::Cancel) { + return; + } + } + + // Create a new material + _material = std::make_shared(); + _material->setParentUUID(parent); + setMaterialDefaults(); +} + void MaterialsEditor::onOk(bool checked) { Q_UNUSED(checked) @@ -354,17 +534,18 @@ void MaterialsEditor::onSave(bool checked) void MaterialsEditor::saveMaterial() { - MaterialSave dialog(&_material, this); + MaterialSave dialog(_material, this); dialog.setModal(true); if (dialog.exec() == QDialog::Accepted) { - _material.resetEditState(); + updateMaterialGeneral(); + _material->resetEditState(); refreshMaterialTree(); } } void MaterialsEditor::accept() { - addRecent(_material.getUUID()); + addRecent(_material->getUUID()); QDialog::accept(); } @@ -379,15 +560,16 @@ void MaterialsEditor::reject() void MaterialsEditor::addMaterials( QStandardItem& parent, - const std::shared_ptr> modelTree, + const std::shared_ptr>> + modelTree, const QIcon& folderIcon, const QIcon& icon) { auto tree = ui->treeMaterials; for (auto& mat : *modelTree) { - Materials::MaterialTreeNode* nodePtr = mat.second; + std::shared_ptr nodePtr = mat.second; if (nodePtr->getType() == Materials::MaterialTreeNode::DataNode) { - const Materials::Material* material = nodePtr->getData(); + auto material = nodePtr->getData(); QString uuid = material->getUUID(); // Base::Console().Log("Material path '%s'\n", // material->getDirectory().toStdString().c_str()); @@ -429,9 +611,9 @@ void MaterialsEditor::createPhysicalTree() tree->setModel(model); QStringList headers; - headers.append(QString::fromStdString("Property")); - headers.append(QString::fromStdString("Value")); - headers.append(QString::fromStdString("Type")); + headers.append(tr("Property")); + headers.append(tr("Value")); + headers.append(tr("Type")); model->setHorizontalHeaderLabels(headers); tree->setColumnWidth(0, 250); @@ -444,6 +626,12 @@ void MaterialsEditor::createPhysicalTree() tree->setItemDelegateForColumn(1, delegate); connect(delegate, &MaterialDelegate::propertyChange, this, &MaterialsEditor::propertyChange); + + // QItemSelectionModel* selectionModel = ui->treePhysicalProperties->selectionModel(); + // connect(selectionModel, + // &QItemSelectionModel::selectionChanged, + // this, + // &MaterialsEditor::onSelectPhysicalProperty); } void MaterialsEditor::createPreviews() @@ -468,9 +656,9 @@ void MaterialsEditor::createAppearanceTree() tree->setModel(model); QStringList headers; - headers.append(QString::fromStdString("Property")); - headers.append(QString::fromStdString("Value")); - headers.append(QString::fromStdString("Type")); + headers.append(tr("Property")); + headers.append(tr("Value")); + headers.append(tr("Type")); model->setHorizontalHeaderLabels(headers); tree->setColumnWidth(0, 250); @@ -490,10 +678,10 @@ void MaterialsEditor::addRecents(QStandardItem* parent) auto tree = ui->treeMaterials; for (auto& uuid : _recents) { try { - const Materials::Material& material = getMaterialManager().getMaterial(uuid); + auto material = getMaterialManager().getMaterial(uuid); - QIcon icon = QIcon(material.getLibrary().getIconPath()); - auto card = new QStandardItem(icon, material.getName()); + QIcon icon = QIcon(material->getLibrary()->getIconPath()); + auto card = new QStandardItem(icon, libraryPath(material)); card->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled); card->setData(QVariant(uuid), Qt::UserRole); @@ -510,10 +698,10 @@ void MaterialsEditor::addFavorites(QStandardItem* parent) auto tree = ui->treeMaterials; for (auto& uuid : _favorites) { try { - const Materials::Material& material = getMaterialManager().getMaterial(uuid); + auto material = getMaterialManager().getMaterial(uuid); - QIcon icon = QIcon(material.getLibrary().getIconPath()); - auto card = new QStandardItem(icon, material.getName()); + QIcon icon = QIcon(material->getLibrary()->getIconPath()); + auto card = new QStandardItem(icon, libraryPath(material)); card->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled); card->setData(QVariant(uuid), Qt::UserRole); @@ -530,12 +718,12 @@ void MaterialsEditor::fillMaterialTree() auto tree = ui->treeMaterials; auto model = static_cast(tree->model()); - auto lib = new QStandardItem(QString::fromStdString("Favorites")); + auto lib = new QStandardItem(tr("Favorites")); lib->setFlags(Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled); addExpanded(tree, model, lib); addFavorites(lib); - lib = new QStandardItem(QString::fromStdString("Recent")); + lib = new QStandardItem(tr("Recent")); lib->setFlags(Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled); addExpanded(tree, model, lib); addRecents(lib); @@ -549,7 +737,7 @@ void MaterialsEditor::fillMaterialTree() QIcon icon(library->getIconPath()); QIcon folderIcon(QString::fromStdString(":/icons/folder.svg")); - auto modelTree = _materialManager.getMaterialTree(*library); + auto modelTree = _materialManager.getMaterialTree(library); addMaterials(*lib, modelTree, folderIcon, icon); } } @@ -582,23 +770,23 @@ void MaterialsEditor::updatePreview() const QString highlightColor; QString sectionColor; - if (_material.hasAppearanceProperty(QString::fromStdString("DiffuseColor"))) { - diffuseColor = _material.getAppearanceValueString(QString::fromStdString("DiffuseColor")); + if (_material->hasAppearanceProperty(QString::fromStdString("DiffuseColor"))) { + diffuseColor = _material->getAppearanceValueString(QString::fromStdString("DiffuseColor")); } - else if (_material.hasAppearanceProperty(QString::fromStdString("ViewColor"))) { - diffuseColor = _material.getAppearanceValueString(QString::fromStdString("ViewColor")); + else if (_material->hasAppearanceProperty(QString::fromStdString("ViewColor"))) { + diffuseColor = _material->getAppearanceValueString(QString::fromStdString("ViewColor")); } - else if (_material.hasAppearanceProperty(QString::fromStdString("Color"))) { - diffuseColor = _material.getAppearanceValueString(QString::fromStdString("Color")); + else if (_material->hasAppearanceProperty(QString::fromStdString("Color"))) { + diffuseColor = _material->getAppearanceValueString(QString::fromStdString("Color")); } - if (_material.hasAppearanceProperty(QString::fromStdString("SpecularColor"))) { + if (_material->hasAppearanceProperty(QString::fromStdString("SpecularColor"))) { highlightColor = - _material.getAppearanceValueString(QString::fromStdString("SpecularColor")); + _material->getAppearanceValueString(QString::fromStdString("SpecularColor")); } - if (_material.hasAppearanceProperty(QString::fromStdString("SectionColor"))) { - sectionColor = _material.getAppearanceValueString(QString::fromStdString("SectionColor")); + if (_material->hasAppearanceProperty(QString::fromStdString("SectionColor"))) { + sectionColor = _material->getAppearanceValueString(QString::fromStdString("SectionColor")); } if ((diffuseColor.length() + highlightColor.length()) > 0) { @@ -678,28 +866,28 @@ void MaterialsEditor::updateMaterialAppearance() treeModel->clear(); QStringList headers; - headers.append(QString::fromStdString("Property")); - headers.append(QString::fromStdString("Value")); - headers.append(QString::fromStdString("Type")); + headers.append(tr("Property")); + headers.append(tr("Value")); + headers.append(tr("Type")); treeModel->setHorizontalHeaderLabels(headers); tree->setColumnWidth(0, 250); tree->setColumnWidth(1, 250); tree->setColumnHidden(2, true); - const std::vector* models = _material.getAppearanceModels(); + auto models = _material->getAppearanceModels(); if (models) { for (auto it = models->begin(); it != models->end(); it++) { QString uuid = *it; try { - const Materials::Model& model = getModelManager().getModel(uuid); - QString name = model.getName(); + auto model = getModelManager().getModel(uuid); + QString name = model->getName(); auto modelRoot = new QStandardItem(name); modelRoot->setFlags(Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled); addExpanded(tree, treeModel, modelRoot); - for (auto itp = model.begin(); itp != model.end(); itp++) { + for (auto itp = model->begin(); itp != model->end(); itp++) { QList items; QString key = itp->first; @@ -707,10 +895,10 @@ void MaterialsEditor::updateMaterialAppearance() propertyItem->setToolTip(itp->second.getDescription()); items.append(propertyItem); - auto valueItem = new QStandardItem(_material.getAppearanceValueString(key)); + auto valueItem = new QStandardItem(_material->getAppearanceValueString(key)); valueItem->setToolTip(itp->second.getDescription()); QVariant variant; - variant.setValue(&_material); + variant.setValue(_material); valueItem->setData(variant); items.append(valueItem); @@ -737,10 +925,10 @@ void MaterialsEditor::updateMaterialProperties() treeModel->clear(); QStringList headers; - headers.append(QString::fromStdString("Property")); - headers.append(QString::fromStdString("Value")); - headers.append(QString::fromStdString("Type")); - headers.append(QString::fromStdString("Units")); + headers.append(tr("Property")); + headers.append(tr("Value")); + headers.append(tr("Type")); + headers.append(tr("Units")); treeModel->setHorizontalHeaderLabels(headers); tree->setColumnWidth(0, 250); @@ -748,19 +936,19 @@ void MaterialsEditor::updateMaterialProperties() tree->setColumnHidden(2, true); tree->setColumnHidden(3, true); - const std::vector* models = _material.getPhysicalModels(); + auto models = _material->getPhysicalModels(); if (models) { for (auto it = models->begin(); it != models->end(); it++) { QString uuid = *it; try { - const Materials::Model& model = getModelManager().getModel(uuid); - QString name = model.getName(); + auto model = getModelManager().getModel(uuid); + QString name = model->getName(); auto modelRoot = new QStandardItem(name); modelRoot->setFlags(Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled); addExpanded(tree, treeModel, modelRoot); - for (auto itp = model.begin(); itp != model.end(); itp++) { + for (auto itp = model->begin(); itp != model->end(); itp++) { QList items; QString key = itp->first; @@ -770,10 +958,10 @@ void MaterialsEditor::updateMaterialProperties() propertyItem->setToolTip(modelProperty.getDescription()); items.append(propertyItem); - auto valueItem = new QStandardItem(_material.getPhysicalValueString(key)); + auto valueItem = new QStandardItem(_material->getPhysicalValueString(key)); valueItem->setToolTip(modelProperty.getDescription()); QVariant variant; - variant.setValue(&_material); + variant.setValue(_material); valueItem->setData(variant); items.append(valueItem); @@ -794,17 +982,47 @@ void MaterialsEditor::updateMaterialProperties() } } +QString MaterialsEditor::libraryPath(std::shared_ptr material) const +{ + QString path; + auto library = material->getLibrary(); + if (library) { + path = QString::fromStdString("/%1/%2") + .arg(material->getLibrary()->getName()) + .arg(material->getDirectory()); + } + else { + path = QString::fromStdString("%1").arg(material->getDirectory()); + } + + return path; +} + +void MaterialsEditor::updateMaterialGeneral() +{ + QString parentString; + try { + auto parent = _materialManager.getParent(_material); + parentString = libraryPath(parent); + } + catch (const Materials::MaterialNotFound&) { + } + + // Update the general information + ui->editName->setText(_material->getName()); + ui->editAuthor->setText(_material->getAuthor()); + ui->editLicense->setText(_material->getLicense()); + ui->editParent->setText(parentString); + ui->editParent->setReadOnly(true); + ui->editSourceURL->setText(_material->getURL()); + ui->editSourceReference->setText(_material->getReference()); + // ui->editTags->setText(_material->getName()); + ui->editDescription->setText(_material->getDescription()); +} + void MaterialsEditor::updateMaterial() { - // Update the general information - ui->editName->setText(_material.getName()); - ui->editAuthorLicense->setText(_material.getAuthorAndLicense()); - // ui->editParent->setText(_material.getName()); - ui->editSourceURL->setText(_material.getURL()); - ui->editSourceReference->setText(_material.getReference()); - // ui->editTags->setText(_material.getName()); - ui->editDescription->setText(_material.getDescription()); - + updateMaterialGeneral(); updateMaterialProperties(); updateMaterialAppearance(); @@ -830,13 +1048,13 @@ void MaterialsEditor::onSelectMaterial(const QItemSelection& selected, } } - if (uuid.isEmpty() || uuid == _material.getUUID()) { + if (uuid.isEmpty() || uuid == _material->getUUID()) { Base::Console().Log("*** Unchanged material '%s'\n", uuid.toStdString().c_str()); return; } // Ensure data is saved (or discarded) before changing materials - if (_material.getEditState() != Materials::Material::ModelEdit_None) { + if (_material->getEditState() != Materials::Material::ModelEdit_None) { // Prompt the user to save or discard changes Base::Console().Log("*** Material edited!!!\n"); int res = confirmSave(this); @@ -847,16 +1065,85 @@ void MaterialsEditor::onSelectMaterial(const QItemSelection& selected, // Get the selected material try { - _material = getMaterialManager().getMaterial(uuid); + _material = std::make_shared(*getMaterialManager().getMaterial(uuid)); } catch (Materials::ModelNotFound const&) { Base::Console().Log("*** Unable to load material '%s'\n", uuid.toStdString().c_str()); - Materials::Material empty; - _material = empty; + _material = std::make_shared(); } updateMaterial(); - _material.resetEditState(); + _material->resetEditState(); +} + +void MaterialsEditor::onDoubleClick(const QModelIndex& index) +{ + Q_UNUSED(index) + + Base::Console().Log("MaterialsEditor::onDoubleClick()\n"); + accept(); +} + +void MaterialsEditor::onContextMenu(const QPoint& pos) +{ + Base::Console().Log("MaterialsEditor::onContextMenu(%d,%d)\n", pos.x(), pos.y()); + // QModelIndex index = ui->treeMaterials->indexAt(pos); + // QString path = pathFromIndex(index); + // Base::Console().Log("\tindex at (%d,%d)->'%s'\n", + // index.row(), + // index.column(), + // path.toStdString().c_str()); + + + QMenu contextMenu(tr("Context menu"), this); + + QAction action1(tr("Inherit from"), this); + // action1.setShortcut(Qt::Key_Delete); + connect(&action1, &QAction::triggered, this, &MaterialsEditor::onInherit); + contextMenu.addAction(&action1); + + QAction action2(tr("Inherit new material"), this); + // action1.setShortcut(Qt::Key_Delete); + connect(&action2, &QAction::triggered, this, &MaterialsEditor::onInheritNew); + contextMenu.addAction(&action2); + + contextMenu.exec(ui->treeMaterials->mapToGlobal(pos)); +} + +void MaterialsEditor::onInherit(bool checked) +{ + Q_UNUSED(checked) + + Base::Console().Log("MaterialsEditor::onInherit()\n"); + // QItemSelectionModel* selectionModel = ui->treeMaterials->selectionModel(); + // if (!selectionModel->hasSelection()) { + // Base::Console().Log("\tNothing selected\n"); + // return; + // } + + // Base::Console().Log("\tSelected path '%s'\n", _selectedFull.toStdString().c_str()); + // int res = confirmDelete(this); + // if (res == QMessageBox::Cancel) { + // return; + // } +} + +void MaterialsEditor::onInheritNew(bool checked) +{ + Q_UNUSED(checked) + + Base::Console().Log("MaterialsEditor::onInherit()\n"); + // QItemSelectionModel* selectionModel = ui->treeMaterials->selectionModel(); + // if (!selectionModel->hasSelection()) { + // Base::Console().Log("\tNothing selected\n"); + // return; + // } + + // Base::Console().Log("\tSelected path '%s'\n", _selectedFull.toStdString().c_str()); + // int res = confirmDelete(this); + // if (res == QMessageBox::Cancel) { + // return; + // } } int MaterialsEditor::confirmSave(QWidget* parent) diff --git a/src/Mod/Material/Gui/MaterialsEditor.h b/src/Mod/Material/Gui/MaterialsEditor.h index 6a1169724b..33f03b221d 100644 --- a/src/Mod/Material/Gui/MaterialsEditor.h +++ b/src/Mod/Material/Gui/MaterialsEditor.h @@ -22,10 +22,11 @@ #ifndef MATGUI_MATERIALSEDITOR_H #define MATGUI_MATERIALSEDITOR_H -#include +#include #include #include +#include #include #include #include @@ -35,8 +36,6 @@ #include #include -namespace fs = boost::filesystem; - namespace MatGui { @@ -47,14 +46,25 @@ class MaterialsEditor: public QDialog Q_OBJECT public: - explicit MaterialsEditor(QWidget* parent = nullptr); + MaterialsEditor(QWidget* parent = nullptr); ~MaterialsEditor() override = default; + void onName(const QString& text); + void onAuthor(const QString& text); + void onLicense(const QString& text); + void onSourceURL(const QString& text); + void onSourceReference(const QString& text); + void onDescription(); + void propertyChange(const QString& property, const QString value); + void onInheritNewMaterial(bool checked); + void onNewMaterial(bool checked); void onFavourite(bool checked); void onURL(bool checked); void onPhysicalAdd(bool checked); + void onPhysicalRemove(bool checked); void onAppearanceAdd(bool checked); + void onAppearanceRemove(bool checked); void onOk(bool checked); void onCancel(bool checked); void onSave(bool checked); @@ -70,10 +80,15 @@ public: return _modelManager; } + QString libraryPath(std::shared_ptr material) const; + void updateMaterialAppearance(); void updateMaterialProperties(); + void updateMaterialGeneral(); void updateMaterial(); void onSelectMaterial(const QItemSelection& selected, const QItemSelection& deselected); + void onDoubleClick(const QModelIndex& index); + void onContextMenu(const QPoint& pos); protected: int confirmSave(QWidget* parent); @@ -83,7 +98,7 @@ private: std::unique_ptr ui; Materials::MaterialManager _materialManager; Materials::ModelManager _modelManager; - Materials::Material _material; + std::shared_ptr _material; QSvgWidget* _rendered; QSvgWidget* _vectored; bool _edited; @@ -102,6 +117,10 @@ private: void addRecent(const QString& uuid); bool isRecent(const QString& uuid) const; + void onInherit(bool checked); + void onInheritNew(bool checked); + + void setMaterialDefaults(); void updatePreview() const; QString getColorHash(const QString& colorString, int colorRange = 255) const; @@ -115,15 +134,12 @@ private: void createMaterialTree(); void fillMaterialTree(); void refreshMaterialTree(); - void - addMaterials(QStandardItem& parent, - const std::shared_ptr> modelTree, - const QIcon& folderIcon, - const QIcon& icon); - bool isMaterial(const fs::path& p) const - { - return Materials::MaterialManager::isMaterial(p); - } + void addMaterials( + QStandardItem& parent, + const std::shared_ptr>> + modelTree, + const QIcon& folderIcon, + const QIcon& icon); }; } // namespace MatGui diff --git a/src/Mod/Material/Gui/MaterialsEditor.ui b/src/Mod/Material/Gui/MaterialsEditor.ui index 8533439e88..5825062271 100644 --- a/src/Mod/Material/Gui/MaterialsEditor.ui +++ b/src/Mod/Material/Gui/MaterialsEditor.ui @@ -68,19 +68,40 @@ 7 + + + + Parent + + + + + + + + + + Tags + + + + + + + Source URL + + + - + Description - - - @@ -88,54 +109,10 @@ - - - - Source Reference - - - - - - - Parent - - - - - - - - - - Author and License - - - - - - - - - - Tags - - - - - - - Source URL - - - - + - - - @@ -155,6 +132,39 @@ + + + + + + + Author + + + + + + + + + + Source Reference + + + + + + + + + + + + + License + + + @@ -172,6 +182,20 @@ + + + + &New + + + + + + + Inherit New + + + diff --git a/src/Mod/Material/Gui/ModelSelect.cpp b/src/Mod/Material/Gui/ModelSelect.cpp index 9b2d19ab38..55fc1a95e2 100644 --- a/src/Mod/Material/Gui/ModelSelect.cpp +++ b/src/Mod/Material/Gui/ModelSelect.cpp @@ -33,6 +33,8 @@ #include #include +#include + #include "ModelSelect.h" #include "ui_ModelSelect.h" @@ -41,7 +43,7 @@ using namespace MatGui; /* TRANSLATOR MatGui::ModelSelect */ -ModelSelect::ModelSelect(QWidget* parent, Materials::ModelManager::ModelFilter filter) +ModelSelect::ModelSelect(QWidget* parent, Materials::ModelFilter filter) : QDialog(parent) , _filter(filter) , ui(new Ui_ModelSelect) @@ -69,6 +71,7 @@ ModelSelect::ModelSelect(QWidget* parent, Materials::ModelManager::ModelFilter f connect(ui->buttonURL, &QPushButton::clicked, this, &ModelSelect::onURL); connect(ui->buttonDOI, &QPushButton::clicked, this, &ModelSelect::onDOI); connect(ui->buttonFavorite, &QPushButton::clicked, this, &ModelSelect::onFavourite); + connect(ui->treeModels, &QTreeView::doubleClicked, this, &ModelSelect::onDoubleClick); ui->standardButtons->button(QDialogButtonBox::Ok)->setEnabled(false); ui->buttonFavorite->setEnabled(false); @@ -232,14 +235,14 @@ void ModelSelect::addExpanded(QTreeView* tree, QStandardItemModel* parent, QStan void ModelSelect::addModels( QStandardItem& parent, - const std::shared_ptr> modelTree, + const std::shared_ptr>> modelTree, const QIcon& icon) { auto tree = ui->treeModels; for (auto& mod : *modelTree) { - Materials::ModelTreeNode* nodePtr = mod.second; + std::shared_ptr nodePtr = mod.second; if (nodePtr->getType() == Materials::ModelTreeNode::DataNode) { - const Materials::Model* model = nodePtr->getData(); + auto model = nodePtr->getData(); QString uuid = model->getUUID(); auto card = new QStandardItem(icon, model->getName()); @@ -264,11 +267,11 @@ void ModelSelect::addRecents(QStandardItem* parent) auto tree = ui->treeModels; for (auto& uuid : _recents) { try { - const Materials::Model& model = getModelManager().getModel(uuid); + auto model = getModelManager().getModel(uuid); - if (getModelManager().passFilter(_filter, model.getType())) { - QIcon icon = QIcon(model.getLibrary().getIconPath()); - auto card = new QStandardItem(icon, model.getName()); + if (getModelManager().passFilter(_filter, model->getType())) { + QIcon icon = QIcon(model->getLibrary()->getIconPath()); + auto card = new QStandardItem(icon, model->getName()); card->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled); card->setData(QVariant(uuid), Qt::UserRole); @@ -286,11 +289,11 @@ void ModelSelect::addFavorites(QStandardItem* parent) auto tree = ui->treeModels; for (auto& uuid : _favorites) { try { - const Materials::Model& model = getModelManager().getModel(uuid); + auto model = getModelManager().getModel(uuid); - if (getModelManager().passFilter(_filter, model.getType())) { - QIcon icon = QIcon(model.getLibrary().getIconPath()); - auto card = new QStandardItem(icon, model.getName()); + if (getModelManager().passFilter(_filter, model->getType())) { + QIcon icon = QIcon(model->getLibrary()->getIconPath()); + auto card = new QStandardItem(icon, model->getName()); card->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled); card->setData(QVariant(uuid), Qt::UserRole); @@ -305,8 +308,6 @@ void ModelSelect::addFavorites(QStandardItem* parent) void ModelSelect::createModelTree() { - // Materials::ModelManager modelManager; - auto tree = ui->treeModels; auto model = new QStandardItemModel(); tree->setModel(model); @@ -326,17 +327,16 @@ void ModelSelect::refreshModelTree() void ModelSelect::fillTree() { - // Materials::ModelManager modelManager; - auto tree = ui->treeModels; auto model = static_cast(tree->model()); + model->clear(); - auto lib = new QStandardItem(QString::fromStdString("Favorites")); + auto lib = new QStandardItem(tr("Favorites")); lib->setFlags(Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled); addExpanded(tree, model, lib); addFavorites(lib); - lib = new QStandardItem(QString::fromStdString("Recent")); + lib = new QStandardItem(tr("Recent")); lib->setFlags(Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled); addExpanded(tree, model, lib); addRecents(lib); @@ -347,7 +347,7 @@ void ModelSelect::fillTree() lib->setFlags(Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled); addExpanded(tree, model, lib); - auto modelTree = getModelManager().getModelTree(*library, _filter); + auto modelTree = getModelManager().getModelTree(library, _filter); addModels(*lib, modelTree, QIcon(library->getIconPath())); } } @@ -355,11 +355,11 @@ void ModelSelect::fillTree() void ModelSelect::setHeaders(QStandardItemModel* model) { QStringList headers; - headers.append(QString::fromStdString("Inherited")); - headers.append(QString::fromStdString("Property")); - headers.append(QString::fromStdString("Units")); - headers.append(QString::fromStdString("Description")); - headers.append(QString::fromStdString("URL")); + headers.append(tr("Inherited")); + headers.append(tr("Property")); + headers.append(tr("Units")); + headers.append(tr("Description")); + headers.append(tr("URL")); model->setHorizontalHeaderLabels(headers); } @@ -388,7 +388,7 @@ void ModelSelect::createModelProperties() // table->setItemDelegate(new MaterialDelegate(this)); } -void ModelSelect::updateModelProperties(const Materials::Model& model) +void ModelSelect::updateModelProperties(std::shared_ptr model) { QTableView* table = ui->tableProperties; QStandardItemModel* tableModel = static_cast(table->model()); @@ -397,7 +397,7 @@ void ModelSelect::updateModelProperties(const Materials::Model& model) setHeaders(tableModel); setColumnWidths(table); - for (auto itp = model.begin(); itp != model.end(); itp++) { + for (auto itp = model->begin(); itp != model->end(); itp++) { QList items; QString key = itp->first; @@ -428,19 +428,19 @@ void ModelSelect::updateModelProperties(const Materials::Model& model) void ModelSelect::updateMaterialModel(const QString& uuid) { - Materials::Model model = getModelManager().getModel(uuid); + auto model = getModelManager().getModel(uuid); // Update the general information - ui->editName->setText(model.getName()); - ui->editURL->setText(model.getURL()); - ui->editDOI->setText(model.getDOI()); - ui->editDescription->setText(model.getDescription()); + ui->editName->setText(model->getName()); + ui->editURL->setText(model->getURL()); + ui->editDOI->setText(model->getDOI()); + ui->editDescription->setText(model->getDescription()); - if (model.getType() == Materials::Model::ModelType_Physical) { - ui->tabWidget->setTabText(1, QString::fromStdString("Properties")); + if (model->getType() == Materials::Model::ModelType_Physical) { + ui->tabWidget->setTabText(1, tr("Properties")); } else { - ui->tabWidget->setTabText(1, QString::fromStdString("Appearance")); + ui->tabWidget->setTabText(1, tr("Appearance")); } updateModelProperties(model); } @@ -453,7 +453,7 @@ void ModelSelect::clearMaterialModel() ui->editDOI->setText(QString::fromStdString("")); ui->editDescription->setText(QString::fromStdString("")); - ui->tabWidget->setTabText(1, QString::fromStdString("Properties")); + ui->tabWidget->setTabText(1, tr("Properties")); QTableView* table = ui->tableProperties; QStandardItemModel* tableModel = static_cast(table->model()); @@ -467,6 +467,7 @@ void ModelSelect::onSelectModel(const QItemSelection& selected, const QItemSelec { Q_UNUSED(deselected); + Base::Console().Log("ModelSelect::onSelectModel()\n"); QStandardItemModel* model = static_cast(ui->treeModels->model()); QModelIndexList indexes = selected.indexes(); for (auto it = indexes.begin(); it != indexes.end(); it++) { @@ -491,6 +492,14 @@ void ModelSelect::onSelectModel(const QItemSelection& selected, const QItemSelec } } +void ModelSelect::onDoubleClick(const QModelIndex& index) +{ + Q_UNUSED(index) + + Base::Console().Log("ModelSelect::onDoubleClick()\n"); + accept(); +} + void ModelSelect::onURL(bool checked) { Q_UNUSED(checked) diff --git a/src/Mod/Material/Gui/ModelSelect.h b/src/Mod/Material/Gui/ModelSelect.h index a80e98fe65..57c3737411 100644 --- a/src/Mod/Material/Gui/ModelSelect.h +++ b/src/Mod/Material/Gui/ModelSelect.h @@ -22,7 +22,7 @@ #ifndef MATGUI_MODELSELECT_H #define MATGUI_MODELSELECT_H -#include +#include #include #include @@ -31,9 +31,7 @@ #include #include -#include - -namespace fs = boost::filesystem; +#include namespace MatGui { @@ -45,15 +43,15 @@ class ModelSelect: public QDialog Q_OBJECT public: - explicit ModelSelect( - QWidget* parent = nullptr, - Materials::ModelManager::ModelFilter filter = Materials::ModelManager::ModelFilter_None); + ModelSelect(QWidget* parent = nullptr, + Materials::ModelFilter filter = Materials::ModelFilter_None); ~ModelSelect() override; void onURL(bool checked); void onDOI(bool checked); void onFavourite(bool checked); void onSelectModel(const QItemSelection& selected, const QItemSelection& deselected); + void onDoubleClick(const QModelIndex& index); const QString& selectedModel() const { return _selected; @@ -77,9 +75,11 @@ private: void addExpanded(QTreeView* tree, QStandardItemModel* parent, QStandardItem* child); void addRecents(QStandardItem* parent); void addFavorites(QStandardItem* parent); - void addModels(QStandardItem& parent, - const std::shared_ptr> modelTree, - const QIcon& icon); + void + addModels(QStandardItem& parent, + const std::shared_ptr>> + modelTree, + const QIcon& icon); void updateMaterialModel(const QString& uuid); void clearMaterialModel(); void createModelTree(); @@ -88,14 +88,14 @@ private: void setHeaders(QStandardItemModel* model); void setColumnWidths(QTableView* table); - void updateModelProperties(const Materials::Model& model); + void updateModelProperties(std::shared_ptr model); void createModelProperties(); Materials::ModelManager& getModelManager() { return _modelManager; } - Materials::ModelManager::ModelFilter _filter; + Materials::ModelFilter _filter; std::unique_ptr ui; Materials::ModelManager _modelManager; QString _selected; diff --git a/src/Mod/Material/Gui/PreCompiled.h b/src/Mod/Material/Gui/PreCompiled.h index 6c9e2163ab..36cb312a6f 100644 --- a/src/Mod/Material/Gui/PreCompiled.h +++ b/src/Mod/Material/Gui/PreCompiled.h @@ -55,10 +55,6 @@ // OpenCasCade // #include -// Boost -#include -#include - // Qt Toolkit #ifndef __QtAll__ #include diff --git a/src/Mod/Material/Gui/Workbench.cpp b/src/Mod/Material/Gui/Workbench.cpp index 21c244052f..65ee6aa6b8 100644 --- a/src/Mod/Material/Gui/Workbench.cpp +++ b/src/Mod/Material/Gui/Workbench.cpp @@ -22,13 +22,53 @@ #include "PreCompiled.h" +#include +#include + #include "Workbench.h" using namespace MatGui; + +#if 0 // needed for Qt's lupdate utility + qApp->translate("Workbench", "&Materials"); + qApp->translate("Workbench", "Materials"); +#endif + /// @namespace MatGui @class Workbench TYPESYSTEM_SOURCE(MatGui::Workbench, Gui::StdWorkbench) Workbench::Workbench() = default; Workbench::~Workbench() = default; + +Gui::MenuItem* Workbench::setupMenuBar() const +{ + Gui::MenuItem* root = StdWorkbench::setupMenuBar(); + Gui::MenuItem* item = root->findItem("&Windows"); + + Gui::MenuItem* part = new Gui::MenuItem; + root->insertItem(item, part); + part->setCommand("&Materials"); + *part << "Materials_Edit"; + + return root; +} + +Gui::ToolBarItem* Workbench::setupToolBars() const +{ + Gui::ToolBarItem* root = StdWorkbench::setupToolBars(); + + Gui::ToolBarItem* solids = new Gui::ToolBarItem(root); + solids->setCommand("Materials"); + *solids << "Materials_Edit"; + + return root; +} + +Gui::ToolBarItem* Workbench::setupCommandBars() const +{ + // Part tools + Gui::ToolBarItem* root = new Gui::ToolBarItem; + return root; +} diff --git a/src/Mod/Material/Gui/Workbench.h b/src/Mod/Material/Gui/Workbench.h index d0de5238c6..fe3800fca7 100644 --- a/src/Mod/Material/Gui/Workbench.h +++ b/src/Mod/Material/Gui/Workbench.h @@ -39,6 +39,11 @@ class MatGuiExport Workbench: public Gui::StdWorkbench public: Workbench(); ~Workbench() override; + +protected: + Gui::MenuItem* setupMenuBar() const override; + Gui::ToolBarItem* setupToolBars() const override; + Gui::ToolBarItem* setupCommandBars() const override; }; } // namespace MatGui diff --git a/src/Mod/Material/Resources/Materials/Appearance/Aluminum.FCMat b/src/Mod/Material/Resources/Materials/Appearance/Aluminum.FCMat index d33f1d0ef4..df4bfa6d55 100644 --- a/src/Mod/Material/Resources/Materials/Appearance/Aluminum.FCMat +++ b/src/Mod/Material/Resources/Materials/Appearance/Aluminum.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "d1f317f0-5ffa-4798-8ab3-af2ff0b5182c" - AuthorAndLicense: "(c) 2023 David Carter" + Author: "David Carter" + License: "GPL-2.0-or-later" Name: "Aluminum" Description: "Defines the Aluminum appearance properties" AppearanceModels: diff --git a/src/Mod/Material/Resources/Materials/Appearance/Brass.FCMat b/src/Mod/Material/Resources/Materials/Appearance/Brass.FCMat index f17c932862..7c84d933f4 100644 --- a/src/Mod/Material/Resources/Materials/Appearance/Brass.FCMat +++ b/src/Mod/Material/Resources/Materials/Appearance/Brass.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "4151e19c-fd6a-4ca4-83d4-d5e17d76cb9c" - AuthorAndLicense: "(c) 2023 David Carter" + Author: "David Carter" + License: "GPL-2.0-or-later" Name: "Brass" Description: "Defines the Brass appearance properties" AppearanceModels: diff --git a/src/Mod/Material/Resources/Materials/Appearance/Bronze.FCMat b/src/Mod/Material/Resources/Materials/Appearance/Bronze.FCMat index bc6c294526..18f0b94a57 100644 --- a/src/Mod/Material/Resources/Materials/Appearance/Bronze.FCMat +++ b/src/Mod/Material/Resources/Materials/Appearance/Bronze.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "ae194589-02d4-4e9b-98a7-f523f660d510" - AuthorAndLicense: "(c) 2023 David Carter" + Author: "David Carter" + License: "GPL-2.0-or-later" Name: "Bronze" Description: "Defines the Bronze appearance properties" AppearanceModels: diff --git a/src/Mod/Material/Resources/Materials/Appearance/Chrome.FCMat b/src/Mod/Material/Resources/Materials/Appearance/Chrome.FCMat index dccbfaec0e..646c2d8891 100644 --- a/src/Mod/Material/Resources/Materials/Appearance/Chrome.FCMat +++ b/src/Mod/Material/Resources/Materials/Appearance/Chrome.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "a9544b88-dde7-4d05-9bdb-c008a4e88dc1" - AuthorAndLicense: "(c) 2023 David Carter" + Author: "David Carter" + License: "GPL-2.0-or-later" Name: "Chrome" Description: "Defines the Chrome appearance properties" AppearanceModels: diff --git a/src/Mod/Material/Resources/Materials/Appearance/Copper.FCMat b/src/Mod/Material/Resources/Materials/Appearance/Copper.FCMat index 643ca6ed06..2e04a10667 100644 --- a/src/Mod/Material/Resources/Materials/Appearance/Copper.FCMat +++ b/src/Mod/Material/Resources/Materials/Appearance/Copper.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "524cad9b-b841-4037-9851-badeca7dcee2" - AuthorAndLicense: "(c) 2023 David Carter" + Author: "David Carter" + License: "GPL-2.0-or-later" Name: "Copper" Description: "Defines the Copper appearance properties" AppearanceModels: diff --git a/src/Mod/Material/Resources/Materials/Appearance/DefaultAppearance.FCMat b/src/Mod/Material/Resources/Materials/Appearance/DefaultAppearance.FCMat index 9795ceae40..9c6eb2f497 100644 --- a/src/Mod/Material/Resources/Materials/Appearance/DefaultAppearance.FCMat +++ b/src/Mod/Material/Resources/Materials/Appearance/DefaultAppearance.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "5dbb7be6-8b63-479b-ab4c-87be02ead973" - AuthorAndLicense: "(c) 2023 David Carter" + Author: "David Carter" + License: "GPL-2.0-or-later" Name: "Default Appearance" Description: "Defines the default appearance properties" AppearanceModels: diff --git a/src/Mod/Material/Resources/Materials/Appearance/Emerald.FCMat b/src/Mod/Material/Resources/Materials/Appearance/Emerald.FCMat index d98a8f1153..519b79bdd6 100644 --- a/src/Mod/Material/Resources/Materials/Appearance/Emerald.FCMat +++ b/src/Mod/Material/Resources/Materials/Appearance/Emerald.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "54def35f-a6bf-472e-8410-dc9fb4b143cf" - AuthorAndLicense: "(c) 2023 David Carter" + Author: "David Carter" + License: "GPL-2.0-or-later" Name: "Emerald" Description: "Defines the Emerald appearance properties" AppearanceModels: diff --git a/src/Mod/Material/Resources/Materials/Appearance/Gold.FCMat b/src/Mod/Material/Resources/Materials/Appearance/Gold.FCMat index 170b7d1302..4805837cf3 100644 --- a/src/Mod/Material/Resources/Materials/Appearance/Gold.FCMat +++ b/src/Mod/Material/Resources/Materials/Appearance/Gold.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "85257e2c-be3f-40a1-b03f-0bd4ba58ca08" - AuthorAndLicense: "(c) 2023 David Carter" + Author: "David Carter" + License: "GPL-2.0-or-later" Name: "Gold" Description: "Defines the Gold appearance properties" AppearanceModels: diff --git a/src/Mod/Material/Resources/Materials/Appearance/Jade.FCMat b/src/Mod/Material/Resources/Materials/Appearance/Jade.FCMat index 3a956ebff2..af9b12ceeb 100644 --- a/src/Mod/Material/Resources/Materials/Appearance/Jade.FCMat +++ b/src/Mod/Material/Resources/Materials/Appearance/Jade.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "cddfa21f-0715-49dd-b35b-951c076fa52c" - AuthorAndLicense: "(c) 2023 David Carter" + Author: "David Carter" + License: "GPL-2.0-or-later" Name: "Jade" Description: "Defines the Jade appearance properties" AppearanceModels: diff --git a/src/Mod/Material/Resources/Materials/Appearance/Metalized.FCMat b/src/Mod/Material/Resources/Materials/Appearance/Metalized.FCMat index 11892dc311..9c9d2feb2d 100644 --- a/src/Mod/Material/Resources/Materials/Appearance/Metalized.FCMat +++ b/src/Mod/Material/Resources/Materials/Appearance/Metalized.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "d149a177-07f1-4e53-9bad-0b5bf0663600" - AuthorAndLicense: "(c) 2023 David Carter" + Author: "David Carter" + License: "GPL-2.0-or-later" Name: "Metalized" Description: "Defines the Metalized appearance properties" AppearanceModels: diff --git a/src/Mod/Material/Resources/Materials/Appearance/NeonGNC.FCMat b/src/Mod/Material/Resources/Materials/Appearance/NeonGNC.FCMat index ddf2092e1c..00a226c0ca 100644 --- a/src/Mod/Material/Resources/Materials/Appearance/NeonGNC.FCMat +++ b/src/Mod/Material/Resources/Materials/Appearance/NeonGNC.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "c0341eef-0897-4fcf-a7f7-eddf1a2600a5" - AuthorAndLicense: "(c) 2023 David Carter" + Author: "David Carter" + License: "GPL-2.0-or-later" Name: "Neon GNC" Description: "Defines the Neon GNC appearance properties" AppearanceModels: diff --git a/src/Mod/Material/Resources/Materials/Appearance/NeonPHC.FCMat b/src/Mod/Material/Resources/Materials/Appearance/NeonPHC.FCMat index ed315a25b6..ea1473d575 100644 --- a/src/Mod/Material/Resources/Materials/Appearance/NeonPHC.FCMat +++ b/src/Mod/Material/Resources/Materials/Appearance/NeonPHC.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "add2d6b2-c8fb-4777-a80a-52bae97300ae" - AuthorAndLicense: "(c) 2023 David Carter" + Author: "David Carter" + License: "GPL-2.0-or-later" Name: "Neon PHC" Description: "Defines the Neon PHC appearance properties" AppearanceModels: diff --git a/src/Mod/Material/Resources/Materials/Appearance/Obsidian.FCMat b/src/Mod/Material/Resources/Materials/Appearance/Obsidian.FCMat index e4f366cff9..3496efb8ea 100644 --- a/src/Mod/Material/Resources/Materials/Appearance/Obsidian.FCMat +++ b/src/Mod/Material/Resources/Materials/Appearance/Obsidian.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "a004c270-7d2c-4898-bec6-b1120edacea9" - AuthorAndLicense: "(c) 2023 David Carter" + Author: "David Carter" + License: "GPL-2.0-or-later" Name: "Obsidian" Description: "Defines the Obsidian appearance properties" AppearanceModels: diff --git a/src/Mod/Material/Resources/Materials/Appearance/Pewter.FCMat b/src/Mod/Material/Resources/Materials/Appearance/Pewter.FCMat index b7592ea3df..b263611987 100644 --- a/src/Mod/Material/Resources/Materials/Appearance/Pewter.FCMat +++ b/src/Mod/Material/Resources/Materials/Appearance/Pewter.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "a61853b9-ec9f-403e-9726-0a938731aecd" - AuthorAndLicense: "(c) 2023 David Carter" + Author: "David Carter" + License: "GPL-2.0-or-later" Name: "Pewter" Description: "Defines the Pewter appearance properties" AppearanceModels: diff --git a/src/Mod/Material/Resources/Materials/Appearance/Plaster.FCMat b/src/Mod/Material/Resources/Materials/Appearance/Plaster.FCMat index 70f6c8932a..d969f84f02 100644 --- a/src/Mod/Material/Resources/Materials/Appearance/Plaster.FCMat +++ b/src/Mod/Material/Resources/Materials/Appearance/Plaster.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "569dccb6-c64b-4dd0-9d3c-1b78f40ad1a5" - AuthorAndLicense: "(c) 2023 David Carter" + Author: "David Carter" + License: "GPL-2.0-or-later" Name: "Plaster" Description: "Defines the Plaster appearance properties" AppearanceModels: diff --git a/src/Mod/Material/Resources/Materials/Appearance/Plastic.FCMat b/src/Mod/Material/Resources/Materials/Appearance/Plastic.FCMat index 2484521dca..efcc9df554 100644 --- a/src/Mod/Material/Resources/Materials/Appearance/Plastic.FCMat +++ b/src/Mod/Material/Resources/Materials/Appearance/Plastic.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "a74622cd-0e2d-4a96-b8c4-fefcc82ac694" - AuthorAndLicense: "(c) 2023 David Carter" + Author: "David Carter" + License: "GPL-2.0-or-later" Name: "Plastic" Description: "Defines the Plastic appearance properties" AppearanceModels: diff --git a/src/Mod/Material/Resources/Materials/Appearance/Ruby.FCMat b/src/Mod/Material/Resources/Materials/Appearance/Ruby.FCMat index 5a8138ba39..eac38bb236 100644 --- a/src/Mod/Material/Resources/Materials/Appearance/Ruby.FCMat +++ b/src/Mod/Material/Resources/Materials/Appearance/Ruby.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "953261a0-cc48-41f8-a3f9-7b20ae3f9b56" - AuthorAndLicense: "(c) 2023 David Carter" + Author: "David Carter" + License: "GPL-2.0-or-later" Name: "Ruby" Description: "Defines the Ruby appearance properties" AppearanceModels: diff --git a/src/Mod/Material/Resources/Materials/Appearance/Satin.FCMat b/src/Mod/Material/Resources/Materials/Appearance/Satin.FCMat index 97a198c206..211f1441df 100644 --- a/src/Mod/Material/Resources/Materials/Appearance/Satin.FCMat +++ b/src/Mod/Material/Resources/Materials/Appearance/Satin.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "951b54ae-86b6-46d2-b452-60bd6a3ba1bb" - AuthorAndLicense: "(c) 2023 David Carter" + Author: "David Carter" + License: "GPL-2.0-or-later" Name: "Satin" Description: "Defines the Satin appearance properties" AppearanceModels: diff --git a/src/Mod/Material/Resources/Materials/Appearance/ShinyPlastic.FCMat b/src/Mod/Material/Resources/Materials/Appearance/ShinyPlastic.FCMat index 75853c01bc..221be76449 100644 --- a/src/Mod/Material/Resources/Materials/Appearance/ShinyPlastic.FCMat +++ b/src/Mod/Material/Resources/Materials/Appearance/ShinyPlastic.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "591c4c4a-22ba-4a9a-869d-e5610107d69a" - AuthorAndLicense: "(c) 2023 David Carter" + Author: "David Carter" + License: "GPL-2.0-or-later" Name: "Shiny Plastic" Description: "Defines the Shiny Plastic appearance properties" AppearanceModels: diff --git a/src/Mod/Material/Resources/Materials/Appearance/Silver.FCMat b/src/Mod/Material/Resources/Materials/Appearance/Silver.FCMat index b3354a150a..dbdedc9a27 100644 --- a/src/Mod/Material/Resources/Materials/Appearance/Silver.FCMat +++ b/src/Mod/Material/Resources/Materials/Appearance/Silver.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "62839fb0-d854-4b44-92df-b7249213de49" - AuthorAndLicense: "(c) 2023 David Carter" + Author: "David Carter" + License: "GPL-2.0-or-later" Name: "Silver" Description: "Defines the Silver appearance properties" AppearanceModels: diff --git a/src/Mod/Material/Resources/Materials/Appearance/Steel.FCMat b/src/Mod/Material/Resources/Materials/Appearance/Steel.FCMat index 7bebcd8a90..bc9e1acc99 100644 --- a/src/Mod/Material/Resources/Materials/Appearance/Steel.FCMat +++ b/src/Mod/Material/Resources/Materials/Appearance/Steel.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "4b849c55-6b3a-4f75-a055-40c0d0324596" - AuthorAndLicense: "(c) 2023 David Carter" + Author: "David Carter" + License: "GPL-2.0-or-later" Name: "Steel" Description: "Defines the Steel appearance properties" AppearanceModels: diff --git a/src/Mod/Material/Resources/Materials/Appearance/Stone.FCMat b/src/Mod/Material/Resources/Materials/Appearance/Stone.FCMat index 8c3910ee5d..74436298ba 100644 --- a/src/Mod/Material/Resources/Materials/Appearance/Stone.FCMat +++ b/src/Mod/Material/Resources/Materials/Appearance/Stone.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "a9f54d61-cc98-46df-8734-b0543ceb4e45" - AuthorAndLicense: "(c) 2023 David Carter" + Author: "David Carter" + License: "GPL-2.0-or-later" Name: "Stone" Description: "Defines the Stone appearance properties" AppearanceModels: diff --git a/src/Mod/Material/Resources/Materials/FluidMaterial/Air.FCMat b/src/Mod/Material/Resources/Materials/FluidMaterial/Air.FCMat index 6a5be9c27c..025c280566 100644 --- a/src/Mod/Material/Resources/Materials/FluidMaterial/Air.FCMat +++ b/src/Mod/Material/Resources/Materials/FluidMaterial/Air.FCMat @@ -1,6 +1,7 @@ # File created by ConvertFCMat.py General: UUID: "94370b96-c97e-4a3f-83b2-11d7461f7da7" + License: "GPL-2.0-or-later" Name: "Air" Description: "Dry air properties at 20 Degrees Celsius and 1 atm" Models: diff --git a/src/Mod/Material/Resources/Materials/FluidMaterial/Argon.FCMat b/src/Mod/Material/Resources/Materials/FluidMaterial/Argon.FCMat index 1607bd59da..235f07091c 100644 --- a/src/Mod/Material/Resources/Materials/FluidMaterial/Argon.FCMat +++ b/src/Mod/Material/Resources/Materials/FluidMaterial/Argon.FCMat @@ -1,6 +1,7 @@ # File created by ConvertFCMat.py General: UUID: "e359c5b5-eae2-42b1-9ef6-edde21d706ee" + License: "GPL-2.0-or-later" Name: "Argon" Description: "Argon properties at 20 Degrees Celsius and 1 atm" Models: diff --git a/src/Mod/Material/Resources/Materials/FluidMaterial/Carbon_dioxide.FCMat b/src/Mod/Material/Resources/Materials/FluidMaterial/Carbon_dioxide.FCMat index 7ffe282fed..fdfc5a94c9 100644 --- a/src/Mod/Material/Resources/Materials/FluidMaterial/Carbon_dioxide.FCMat +++ b/src/Mod/Material/Resources/Materials/FluidMaterial/Carbon_dioxide.FCMat @@ -1,6 +1,7 @@ # File created by ConvertFCMat.py General: UUID: "ef0e4040-a498-48c3-a87b-e996bfd89195" + License: "GPL-2.0-or-later" Name: "Carbon dioxide" Description: "Carbon dioxide properties at 20 Degrees Celsius and 1 atm" Models: diff --git a/src/Mod/Material/Resources/Materials/FluidMaterial/Nitrogen.FCMat b/src/Mod/Material/Resources/Materials/FluidMaterial/Nitrogen.FCMat index bd5fd3ea07..d7c81bea31 100644 --- a/src/Mod/Material/Resources/Materials/FluidMaterial/Nitrogen.FCMat +++ b/src/Mod/Material/Resources/Materials/FluidMaterial/Nitrogen.FCMat @@ -1,6 +1,7 @@ # File created by ConvertFCMat.py General: UUID: "8d02a797-5e0a-4e40-803a-75fc66de8de6" + License: "GPL-2.0-or-later" Name: "Nitrogen" Description: "Nitrogen properties at 20 Degrees Celsius and 1 atm" Models: diff --git a/src/Mod/Material/Resources/Materials/FluidMaterial/None.FCMat b/src/Mod/Material/Resources/Materials/FluidMaterial/None.FCMat index 40094e2d06..8497cd58bb 100644 --- a/src/Mod/Material/Resources/Materials/FluidMaterial/None.FCMat +++ b/src/Mod/Material/Resources/Materials/FluidMaterial/None.FCMat @@ -1,6 +1,7 @@ # File created by ConvertFCMat.py General: UUID: "944a8018-09bf-48f6-a7b3-aa8f6a00a310" + License: "GPL-2.0-or-later" Name: "None" Description: "None" Models: diff --git a/src/Mod/Material/Resources/Materials/FluidMaterial/Water.FCMat b/src/Mod/Material/Resources/Materials/FluidMaterial/Water.FCMat index aa4c8d35cc..6f0fe7c6dc 100644 --- a/src/Mod/Material/Resources/Materials/FluidMaterial/Water.FCMat +++ b/src/Mod/Material/Resources/Materials/FluidMaterial/Water.FCMat @@ -1,6 +1,7 @@ # File created by ConvertFCMat.py General: UUID: "7e5559d5-be15-4571-a72f-20c39edd41cf" + License: "GPL-2.0-or-later" Name: "Water" Description: "Standard distilled water properties at 20 Degrees Celsius and 1 atm" ReferenceSource: "''" diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Aggregate/Concrete-EN-C35_45.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Aggregate/Concrete-EN-C35_45.FCMat index fa6eabb71f..281b959ca6 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Aggregate/Concrete-EN-C35_45.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Aggregate/Concrete-EN-C35_45.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "dba76940-a910-4a3b-ab73-a9f412ac69d9" - AuthorAndLicense: "(c) 2019 Bernd Hahnebach (CC-BY 3.0)" + Author: "Bernd Hahnebach" + License: "CC-BY-3.0" Name: "Concrete-EN-C35/45" Description: "Concrete matrix for reinforcement material examples, 0.6 x 0.75 x 35 MPa = 15.75 MPa (https://forum.freecad.org/viewtopic.php?f=18&t=33106&start=200#p311075)" Inherits: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Aggregate/Concrete-Generic.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Aggregate/Concrete-Generic.FCMat index 994874548d..72e4c9af4a 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Aggregate/Concrete-Generic.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Aggregate/Concrete-Generic.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "26042aa5-56e6-4d99-8b63-dd8b9ea5a37a" - AuthorAndLicense: "(c) 2013 Yorik van Havre (CC-BY 3.0)" + Author: "Yorik van Havre" + License: "CC-BY-3.0" Name: "Concrete" Description: "A standard C-25 construction concrete" Inherits: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Aggregate/Reinforcement-FIB-B500.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Aggregate/Reinforcement-FIB-B500.FCMat index 13ac6afc77..70e70e1916 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Aggregate/Reinforcement-FIB-B500.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Aggregate/Reinforcement-FIB-B500.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "57507cd4-d22f-4d86-9794-fdb1ec8cd098" - AuthorAndLicense: "(c) 2019 Bernd Hahnebach (CC-BY 3.0)" + Author: "Bernd Hahnebach" + License: "CC-BY-3.0" Name: "Reinforcement-Harry" Description: "Reinforcement inside concrete for reinforcement material examples, from fib examples, 0.84 x 0.75 x 500 MPa = 315 MPa (https://forum.freecad.org/viewtopic.php?f=18&t=33106&start=200#p311705)" Inherits: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Carbon/Graphite.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Carbon/Graphite.FCMat index e66b987f2e..5983299e4a 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Carbon/Graphite.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Carbon/Graphite.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "5c67b675-69a2-4782-902a-bb90c3952f07" - AuthorAndLicense: "Uwe Stöhr, LGPL" + Author: "Uwe Stöhr" + License: "LGPL-2.0-or-later" Name: "Graphite" Description: "Typical material properties for pure graphite" ReferenceSource: "Properties and characteristics of graphite" diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Glass/Glass-E-GlassFibre.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Glass/Glass-E-GlassFibre.FCMat index 034f5271f0..862f02108f 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Glass/Glass-E-GlassFibre.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Glass/Glass-E-GlassFibre.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "a02bf9d7-6e3e-4e36-881b-10779ee9f706" - AuthorAndLicense: "(c) 2015 DaviKaur (CC-BY 3.0)" + Author: "DaviKaur" + License: "CC-BY-3.0" Name: "Glass-E" Description: "Glass Fibre" Models: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Glass/Glass-Generic.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Glass/Glass-Generic.FCMat index 1502a1e85b..9074cfe621 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Glass/Glass-Generic.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Glass/Glass-Generic.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "3e3a3e13-04a4-410e-8e36-bbd83ca66847" - AuthorAndLicense: "(c) 2015 Przemo Firszt (CC-BY 3.0)" + Author: "Przemo Firszt" + License: "CC-BY-3.0" Name: "Glass" Description: "Generic soda-lime glass" Models: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Glass/Glass-S2-GlassFibre.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Glass/Glass-S2-GlassFibre.FCMat index 79d993d62d..70daa6df5b 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Glass/Glass-S2-GlassFibre.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Glass/Glass-S2-GlassFibre.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "0c4943e0-248b-4df9-88d9-3b4dd84dfc68" - AuthorAndLicense: "(c) 2015 DaviKaur (CC-BY 3.0)" + Author: "DaviKaur" + License: "CC-BY-3.0" Name: "Glass-S2" Description: "Glass Fibre" Models: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Alloys/Invar-Generic.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Alloys/Invar-Generic.FCMat index 1653bde1ae..80fce39425 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Alloys/Invar-Generic.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Alloys/Invar-Generic.FCMat @@ -1,7 +1,7 @@ # File created by ConvertFCMat.py General: UUID: "27745e16-2a10-4c8e-bd22-59971806909c" - AuthorAndLicense: "Uwe Stöhr" + Author: "Uwe Stöhr" Name: "Invar Generic" Models: Father: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Aluminum/AlMg3F24.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Aluminum/AlMg3F24.FCMat index d3ea2edf4c..b7a7da8f77 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Aluminum/AlMg3F24.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Aluminum/AlMg3F24.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "0051bddf-6f62-4406-b8c9-569322880564" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "AlMg3F24" Inherits: Aluminum: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Aluminum/AlMgSi1F31.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Aluminum/AlMgSi1F31.FCMat index ce7ad3a053..7d27af3936 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Aluminum/AlMgSi1F31.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Aluminum/AlMgSi1F31.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "460e02a3-b6cd-4662-b2f6-8c9d44146c66" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "AlMgSi1F31" Inherits: Aluminum: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Aluminum/AlZn4-5Mg1F35.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Aluminum/AlZn4-5Mg1F35.FCMat index 9ff117b0ed..cae2453d1e 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Aluminum/AlZn4-5Mg1F35.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Aluminum/AlZn4-5Mg1F35.FCMat @@ -1,7 +1,7 @@ # File created by ConvertFCMat.py General: UUID: "05f8f1b2-b92b-4e41-8de9-1e064e78a165" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + License: "LGPL-2.0-or-later" Name: "AlZn4,5Mg1F35" Inherits: Aluminum: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Aluminum/Aluminum-6061-T6.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Aluminum/Aluminum-6061-T6.FCMat index 648350b109..3fe4777c23 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Aluminum/Aluminum-6061-T6.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Aluminum/Aluminum-6061-T6.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "68b152b2-fd5e-4f10-8db0-1a2df3fe0fda" - AuthorAndLicense: "(c) 2016 Mandeep Singh (CC-BY 3.0)" + Author: "Mandeep Singh" + License: "CC-BY-3.0" Name: "Aluminum 6061-T6" Description: "Precipitation-hardened, Nonferrous Aluminum alloy" Inherits: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Aluminum/Aluminum-Generic.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Aluminum/Aluminum-Generic.FCMat index c518eaf674..d96cd80218 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Aluminum/Aluminum-Generic.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Aluminum/Aluminum-Generic.FCMat @@ -1,7 +1,7 @@ # File created by ConvertFCMat.py General: UUID: "9bf060e9-1663-44a2-88e2-2ff6ee858efe" - AuthorAndLicense: "Uwe Stöhr" + Author: "Uwe Stöhr" Name: "Aluminum Generic" Inherits: Aluminum: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Copper/Copper-Generic.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Copper/Copper-Generic.FCMat index 8188c3a553..8379ecba69 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Copper/Copper-Generic.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Copper/Copper-Generic.FCMat @@ -1,7 +1,7 @@ # File created by ConvertFCMat.py General: UUID: "6c03899d-496e-4c60-a41b-3d66f2337fb9" - AuthorAndLicense: "Uwe Stöhr" + Author: "Uwe Stöhr" Name: "Copper Generic" Inherits: Copper: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Iron/Iron-Generic.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Iron/Iron-Generic.FCMat index f99d52a37f..f33cdf155f 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Iron/Iron-Generic.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Iron/Iron-Generic.FCMat @@ -1,7 +1,7 @@ # File created by ConvertFCMat.py General: UUID: "1826c364-d26a-43fb-8f61-288281236836" - AuthorAndLicense: "Uwe Stöhr" + Author: "Uwe Stöhr" Name: "Iron Generic" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/CalculiX-Steel.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/CalculiX-Steel.FCMat index 7763a27728..5105e234d2 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/CalculiX-Steel.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/CalculiX-Steel.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "92589471-a6cb-4bbc-b748-d425a17dea7d" - AuthorAndLicense: "(c) 2013 Juergen Riegel (CC-BY 3.0)" + Author: "Juergen Riegel" + License: "CC-BY-3.0" Name: "CalculiX-Steel" Description: "Standard steel material for CalculiX sample calculations" Inherits: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-15CrNi6.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-15CrNi6.FCMat index c1be13ce98..e719b9b5e6 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-15CrNi6.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-15CrNi6.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "6822df30-db32-4a68-a8d7-aaddcb9649d1" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "15CrNi6" Description: "High-strength carbon steel" Inherits: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-17CrNiMo6.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-17CrNiMo6.FCMat index 462e784536..247c10e733 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-17CrNiMo6.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-17CrNiMo6.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "e4c76f15-00af-4498-ac57-beaf49c150e9" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "17CrNiMo6" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-1C22.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-1C22.FCMat index f36307b08d..4f0271aff2 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-1C22.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-1C22.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "c424fe3d-5f49-4c39-9467-8a2a800076aa" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "1C22" Description: "Case hardened alloy steel" Inherits: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-1C35.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-1C35.FCMat index 8cc577729a..0c5702696b 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-1C35.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-1C35.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "cd932bad-4085-459f-aea6-1da737ae38ae" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "1C35" Description: "Non-alloy quality steel" Inherits: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-1C45.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-1C45.FCMat index 9433799bcb..4fabe2bb90 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-1C45.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-1C45.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "958b7a5c-4764-4a2f-a450-2153a41fb5ec" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "1C45" Description: "Non-alloy quality steel" Inherits: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-1C60.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-1C60.FCMat index dac83e2809..45ae6f0566 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-1C60.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-1C60.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "9717f953-1cfc-41a6-8974-3ad45188ad48" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "1C60" Description: "Non-alloy quality steel" Inherits: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-20NiCrMo2.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-20NiCrMo2.FCMat index f63fc2cd6b..af5e731492 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-20NiCrMo2.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-20NiCrMo2.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "1c759697-7aef-4a14-92c5-5bf84b99a4f0" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "20NiCrMo2" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-28Mn6.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-28Mn6.FCMat index 5166ff1d58..c310e12ec6 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-28Mn6.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-28Mn6.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "6894c597-5771-4b56-825f-ce7d5e4689f4" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "28Mn6" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-2C10.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-2C10.FCMat index bb25674809..55e4894152 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-2C10.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-2C10.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "a7be39a1-1686-4fee-a1d5-81ef73b82d16" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "2C10" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-30CrNiMo8.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-30CrNiMo8.FCMat index b8edc93d8e..276e40f244 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-30CrNiMo8.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-30CrNiMo8.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "a6d96264-affc-4406-9816-75099c1fa0d9" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "30CrNiMo8" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-34CrNiMo6.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-34CrNiMo6.FCMat index 4c02195cf8..67ce48abdb 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-34CrNiMo6.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-34CrNiMo6.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "e69448d5-2517-4c00-9e70-ebeb11ca017f" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "34CrNiMo6" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-36CrNiMo4.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-36CrNiMo4.FCMat index f1635de298..e41bf67f6b 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-36CrNiMo4.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-36CrNiMo4.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "3e78b767-5530-4d69-a541-cf33a5a2ad19" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "36CrNiMo4" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-36NiCrMo16.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-36NiCrMo16.FCMat index 1a9e29753a..be7b82a8fe 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-36NiCrMo16.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-36NiCrMo16.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "3fdf729c-bec4-4bfa-ba94-b0c9e51a2040" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "36NiCrMo16" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-3C15.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-3C15.FCMat index 6ad2a41287..5384f6afb0 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-3C15.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-3C15.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "605fd7b6-caa3-400d-b6d7-ed52c0f5da21" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "3C15" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-3C22.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-3C22.FCMat index 19c035f0a4..bb8f193f81 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-3C22.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-3C22.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "7313f076-faf4-41dd-8dae-1b9a586990dc" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "3C22" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-3C35.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-3C35.FCMat index 583523ea88..91c2f6478f 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-3C35.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-3C35.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "251cc54e-4a5a-4cd3-9c9e-006c416d7ce9" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "3C35" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-3V45.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-3V45.FCMat index 193f19e1b9..189f0f3b04 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-3V45.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-3V45.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "d2e12a80-fd17-42db-99d8-62971f65ee84" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "3V45" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C10.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C10.FCMat index b72f563c88..016b585afa 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C10.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C10.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "9086ae2f-3b2e-4654-9665-0fe31effb8a2" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "C10" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C15.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C15.FCMat index 6a11819478..47d53206b6 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C15.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C15.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "06ae5c92-de7b-46c9-984d-4dd87964bc5c" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "C15" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C22E.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C22E.FCMat index 932930426e..09bbdc3424 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C22E.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C22E.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "befa2489-dba0-41c5-aa83-7cca2ac8947b" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "C22E" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C25E.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C25E.FCMat index 12f65b3acc..fecc163322 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C25E.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C25E.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "b95d3de5-36af-41cd-a6dd-3f647b1d4eee" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "C25E" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C30E.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C30E.FCMat index d6cfe2d8c3..8dc09c6ca6 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C30E.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C30E.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "e88e1e86-fad2-4c70-b185-4b2975e7fba5" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "C30E" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C40E.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C40E.FCMat index c777dc3028..1ccb48ea77 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C40E.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C40E.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "5b33f177-b0da-4ffa-acb5-a3b23ab6e630" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "C40E" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C50E.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C50E.FCMat index 3a73bb97f7..10122e36fa 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C50E.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C50E.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "6821be5f-5471-4939-bb1d-866f83018090" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "C50E" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C55E.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C55E.FCMat index be4341ad95..27da081e4e 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C55E.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C55E.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "d60a21c9-9c4b-4463-b133-bb0e84ce46b2" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "C55E" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C60E.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C60E.FCMat index 7c0c04301b..7ae48bda84 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C60E.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-C60E.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "56027b3e-876e-4c0e-9f39-242feaa67e13" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "C60E" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-E295-GC.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-E295-GC.FCMat index 9b314d4c01..1cae3d8294 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-E295-GC.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-E295-GC.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "fc010ef8-91de-4099-9a73-605c01dd117c" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "E295 GC" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-E295.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-E295.FCMat index e74c218799..d919a2b3f1 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-E295.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-E295.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "f1567a1c-995f-4feb-8baf-09ade3e830c5" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "E295" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-E335-GC.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-E335-GC.FCMat index 9612056c9b..b4a6f21b2b 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-E335-GC.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-E335-GC.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "ab901ecc-d880-4cb4-b400-dbe4fd9b0f0a" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "E335 GC" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-E335.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-E335.FCMat index 7ca7e2a764..44e9e013db 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-E335.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-E335.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "da418876-f80e-4793-8fc8-a6040a694389" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "E335" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-E360-GC.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-E360-GC.FCMat index aa14d78d49..69ee63fa8d 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-E360-GC.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-E360-GC.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "4c311592-659b-4ef0-bac9-5cffe9e70612" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "E360 GC" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-E360.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-E360.FCMat index 6ed1535ce0..086b7b9ddb 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-E360.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-E360.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "dfba065e-2bfb-4fe3-8eec-dfb1cb6274fe" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "E360" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJL-100.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJL-100.FCMat index 282a042e41..8bac4460a4 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJL-100.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJL-100.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "5a1d56e3-8180-4f81-a0d7-887fb08e3752" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "EN-GJL-100" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJL-150.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJL-150.FCMat index f4c9e2ca3c..e68bdbd697 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJL-150.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJL-150.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "7a2aa3c4-10fa-44b0-9420-37ae74207fa3" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "EN-GJL-150" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJL-200.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJL-200.FCMat index aca3e5b83a..ed3218a3ff 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJL-200.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJL-200.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "8ae26e72-65b6-4f93-9fbe-9e3f17a2e1b5" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "EN-GJL-200" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJL-250.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJL-250.FCMat index 13d4da1f70..5272f9b931 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJL-250.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJL-250.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "71f32e31-656e-4f94-a5f0-5b656b9367c6" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "EN-GJL-250" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJL-300.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJL-300.FCMat index 489a2e3c24..2dd95eb99d 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJL-300.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJL-300.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "6db01463-7772-4d0e-ab81-fae6d45ce669" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "EN-GJL-300" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJL-350.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJL-350.FCMat index 9922275365..f463241b6d 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJL-350.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJL-350.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "c4ff4bef-4885-41d5-904f-9c71a8018c98" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "EN-GJL-350" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMB-350-10.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMB-350-10.FCMat index 05dc53a302..e3068a9035 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMB-350-10.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMB-350-10.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "eec1833a-424a-4c4f-bdf2-6f8377845d54" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "EN-GJMB-350-10" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMB-550-4.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMB-550-4.FCMat index 7e8b518d5c..d4e4f44237 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMB-550-4.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMB-550-4.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "095140bb-df01-4bb9-8ff3-062aa91ec48c" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "EN-GJMB-550-4" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMB-650-2.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMB-650-2.FCMat index d22fcd93ad..d11ba1c726 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMB-650-2.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMB-650-2.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "490a348c-f508-4599-a5e0-2f6b211126d5" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "EN-GJMB-650-2" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMW-350-4.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMW-350-4.FCMat index 148e26a9b3..ebb8694572 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMW-350-4.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMW-350-4.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "a97c3eab-a1e8-472b-ba40-519a0d660019" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "EN-GJMW-350-4" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMW-360-12.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMW-360-12.FCMat index 604538d200..e1c40edde3 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMW-360-12.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMW-360-12.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "81a865af-79b6-4e0b-98ad-5cde134ad99e" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "EN-GJMW-360-12" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMW-400-5.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMW-400-5.FCMat index db74ef871c..9220b27f79 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMW-400-5.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMW-400-5.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "9d71fc9c-960a-47e8-afa8-a86a24b3ff89" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "EN-GJMW-400-5" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMW-450-7.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMW-450-7.FCMat index 0e6de5ac4e..1e9d4e28d1 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMW-450-7.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMW-450-7.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "c0eedc49-d63b-429d-be63-ef0ea442f45c" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "EN-GJMW-450-7" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJS-400-15.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJS-400-15.FCMat index ab7c0b2163..051c98f0ec 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJS-400-15.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJS-400-15.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "f6300691-ecf0-4846-acb1-8c2bad3359a8" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "EN-GJS-400-15" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJS-500-7.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJS-500-7.FCMat index 5a28f4356f..1c28126097 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJS-500-7.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJS-500-7.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "51aabe6f-642b-4f47-9006-1c8c3613a422" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "EN-GJS-500-7" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJS-600-3.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJS-600-3.FCMat index 0f3f5d7ed9..1de6ec6cf9 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJS-600-3.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJS-600-3.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "eb573f18-5a7b-493b-bfda-d711f03f7f71" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "EN-GJS-600-3" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJS-700-2.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJS-700-2.FCMat index 28c327f104..3e1f7625de 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJS-700-2.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJS-700-2.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "9a194e62-d2e4-466d-92ba-2707107c4e3c" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "EN-GJS-700-2" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJS-800-1.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJS-800-1.FCMat index 071d813334..9ad715e980 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJS-800-1.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJS-800-1.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "97c444f9-83ae-48d8-98e5-603349d06f7e" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "EN-GJS-800-1" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G16Mn5.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G16Mn5.FCMat index 97d45db1ae..bdede7e22a 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G16Mn5.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G16Mn5.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "fc5c14ba-4885-4c75-aaf6-0ec4f2365f40" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "G16Mn5" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G200.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G200.FCMat index 51965ab4d2..2c61fce091 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G200.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G200.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "8d799def-e941-4cb6-b48d-72b9a292fafe" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "G200" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G20Mn5.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G20Mn5.FCMat index 7e1e9c8e6d..b7bbf43d10 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G20Mn5.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G20Mn5.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "d384d1e5-e2fe-4e09-9a0f-78e5670425ee" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "G20Mn5" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G230.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G230.FCMat index 2c11dcd9f6..114fd54038 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G230.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G230.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "53931707-6fe7-4ac0-ac7a-e9ddfec70fa5" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "G230" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G260.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G260.FCMat index 4c4b62744e..71e5f54ef6 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G260.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G260.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "22971112-d137-4db1-9349-edf5e281e333" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "G260" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G300.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G300.FCMat index 8c0acbd1cd..488a762db6 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G300.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G300.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "33f1c891-7488-4324-9af9-cbdde6726b49" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "G300" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G30Mn5.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G30Mn5.FCMat index bb11cbee52..91675dc395 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G30Mn5.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-G30Mn5.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "e03df70c-ceb8-4317-825d-1195c8c178d0" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "G30Mn5" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-Generic.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-Generic.FCMat index c2fead712a..e291486c4a 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-Generic.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-Generic.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "90bbd8ef-8623-4d78-b3bf-e0bdb9b74dd3" - AuthorAndLicense: "(c) 2013 Juergen Riegel (CC-BY 3.0)" + Author: "Juergen Riegel" + License: "CC-BY-3.0" Name: "Steel-Generic" Description: "This is a blend Steel material card. The values are at the low end of the spectrum. If you need a more precise material definition use the more specialised steel cards." Inherits: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S185.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S185.FCMat index ebba16c9d5..c8f0ada537 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S185.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S185.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "6f32981a-7bbf-49a1-842c-7567a195fa7e" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "S185" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S235JO.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S235JO.FCMat index 3f26e56e56..c484567ffd 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S235JO.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S235JO.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "5b13e02a-b173-4e2d-95fd-a30d9e0f7cf5" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "S235JO" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S235JR.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S235JR.FCMat index 5c4cf2a2ca..657975b9c7 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S235JR.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S235JR.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "4a96627d-6518-458c-8ccf-846f69fd8a50" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "S235JR" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S235JRG1.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S235JRG1.FCMat index a4949171a9..fe1182e815 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S235JRG1.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S235JRG1.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "d8cc450d-7d6d-4377-8a8d-ffe3cf30fcb2" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "S235JRG1" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S260NC.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S260NC.FCMat index 09cf375caa..b9e5794e79 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S260NC.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S260NC.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "4994efd8-fc7b-41b3-ad61-9d98d1bdbe6e" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "S260NC" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S275JO.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S275JO.FCMat index 95a8ec460a..56fb705e76 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S275JO.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S275JO.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "f9deac5f-91a4-41aa-b49c-ef09ec4613e2" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "S275JO" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S275JR.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S275JR.FCMat index 9d57c21c9d..c3da4512c9 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S275JR.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S275JR.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "30e4da7d-1fe3-41de-911a-a42e3405bb7b" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "S275JR" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S275N.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S275N.FCMat index 18c0439561..59a1888016 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S275N.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S275N.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "07592e35-3e1a-470f-8eda-f4bee7d9cb4a" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "S275N" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S335JO.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S335JO.FCMat index c8ae2510e0..c7fbcc90db 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S335JO.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S335JO.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "c50ad549-b4f4-47ab-9bc6-4eb5191da111" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "S335JO" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S335JR.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S335JR.FCMat index 931e9d418f..83ac7fe653 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S335JR.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S335JR.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "dbd04cee-3b92-4b79-a208-58547ebe3807" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "S335JR" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S335N.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S335N.FCMat index 231271d7cd..e7d8fc174b 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S335N.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S335N.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "16d7f1d5-449f-4b9e-b57a-7ea114fda115" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "S335N" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S340MC.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S340MC.FCMat index a3e0a90eb4..baccd4ca36 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S340MC.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S340MC.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "5785ea5e-3376-47dd-8dc2-f1267c47e9bc" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "S340MC" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S355J2G3.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S355J2G3.FCMat index 71b783d323..72e7ca9845 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S355J2G3.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S355J2G3.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "b9e861ee-93fb-4eca-a2de-03579bc503c1" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "S355J2G3" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S380MC.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S380MC.FCMat index aa8d2c2c94..b28262ff49 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S380MC.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S380MC.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "da2a429b-8763-4586-be3d-620e7dd30271" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "S380MC" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S420MC.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S420MC.FCMat index 41b6518bed..407d553894 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S420MC.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S420MC.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "c3452eff-f68e-4cfd-a24e-27e2abcd01ac" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "S420MC" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S420N.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S420N.FCMat index a8a2d0b6cd..74f00df70f 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S420N.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S420N.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "902f2d4a-5bd0-44bf-9c14-54462ba6778b" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "S420N" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S460MC.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S460MC.FCMat index 2b972e87ef..7834dca011 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S460MC.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S460MC.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "c254dac5-3ee3-49b9-b8d4-16d20d21c94f" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "S460MC" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S460N.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S460N.FCMat index d3c96c9639..536b5df413 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S460N.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S460N.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "f0ae245a-1041-4674-ac4f-bf212dda6009" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "S460N" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S500MC.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S500MC.FCMat index 7703c36586..679dfaf447 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S500MC.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S500MC.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "ad8e2007-ee73-4b71-8830-6d40a8407284" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "S500MC" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S550MC.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S550MC.FCMat index 9ac063cd0d..b7c5bc08b2 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S550MC.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S550MC.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "b7308026-9278-4346-b157-2b3da280b61b" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "S550MC" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S690MC.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S690MC.FCMat index 1d979fd02c..223f410073 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S690MC.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-S690MC.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "41360af5-98ed-4125-a89c-ff711e4dd2bf" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "S690MC" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-St-37-2K.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-St-37-2K.FCMat index 0478534039..9f6476151e 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-St-37-2K.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-St-37-2K.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "e97be20f-246a-48b5-9718-3d39486e7af2" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "St 37-2K" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-St-E-255.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-St-E-255.FCMat index 230b39f30a..2b5057f72a 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-St-E-255.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-St-E-255.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "1078eb9f-ac3e-4b24-b40e-b9ead77828e0" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "St E 255" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-St-E-315.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-St-E-315.FCMat index efcc99b6f9..3d15c2d2df 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-St-E-315.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-St-E-315.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "74ca3b08-d561-4440-a4c2-d9b839b66670" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "St E 315" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-St-E-380.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-St-E-380.FCMat index f2d7b9df43..33b2d3c85a 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-St-E-380.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-St-E-380.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "a1b62461-7abc-45da-9a3c-3068367d2990" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "St E 380" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-St-E-460.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-St-E-460.FCMat index 9ec5596e74..5bc873d0d9 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-St-E-460.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-St-E-460.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "b312ad7b-95d4-4ca5-9736-360dbed918ee" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "St E 460" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-St-E-500.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-St-E-500.FCMat index 7c08645652..c5bc2706f3 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-St-E-500.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-St-E-500.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "90fb6bd4-05db-4d44-ba89-280b5a060921" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "St E 500" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X2CrNiMoN17-13-3.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X2CrNiMoN17-13-3.FCMat index 104b026672..083668673d 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X2CrNiMoN17-13-3.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X2CrNiMoN17-13-3.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "a05b5f9b-27b9-4554-8feb-553f9d6027ef" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "X2CrNiMoN17-13-3" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X2CrNiN24-4.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X2CrNiN24-4.FCMat index f59cd81717..d048a4677c 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X2CrNiN24-4.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X2CrNiN24-4.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "be74ada5-2775-41fc-a44b-36df6fb5e0b8" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "X2CrNiN24-4" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X39CrMo17-1.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X39CrMo17-1.FCMat index ec90558bbe..485f5099a7 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X39CrMo17-1.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X39CrMo17-1.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "9e7069ef-296d-401d-9331-d3e11267c2e0" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "X39CrMo17-1" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X3CrNiMo13-14.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X3CrNiMo13-14.FCMat index b4fc5986dd..87ec296574 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X3CrNiMo13-14.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X3CrNiMo13-14.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "88632101-8868-407a-a95f-01773b5f2245" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "X3CrNiMo13-14" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X5CrNi18-10.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X5CrNi18-10.FCMat index e8c5f023bf..0e0a81db1e 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X5CrNi18-10.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X5CrNi18-10.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "e5329208-0c38-47ec-8c59-e7bf6a35801d" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "X5CrNi18-10" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X5CrNiMo17-12-2.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X5CrNiMo17-12-2.FCMat index 5bf2b0b38b..f115a63bff 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X5CrNiMo17-12-2.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X5CrNiMo17-12-2.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "7625a484-96de-438d-b251-2b71044cfa88" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "X5CrNiMo17-12-2" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X6CrNiTi18-10.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X6CrNiTi18-10.FCMat index 8e04da41e5..76366b8f64 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X6CrNiTi18-10.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Steel/Steel-X6CrNiTi18-10.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "2c577c45-ebae-46b2-9e36-e41fbcce9286" - AuthorAndLicense: "(c) 2014 M. Münch - GNU Lesser General Public License (LGPL)" + Author: "M. Münch" + License: "LGPL-2.0-or-later" Name: "X6CrNiTi18-10" Inherits: Steel: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Titanium/Ti-6Al-4V.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Titanium/Ti-6Al-4V.FCMat index b68cc7b6d0..ee1b06c1b0 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Titanium/Ti-6Al-4V.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Metal/Titanium/Ti-6Al-4V.FCMat @@ -1,7 +1,7 @@ # File created by ConvertFCMat.py General: UUID: "f8013463-8008-4063-818c-ab6884cfa015" - AuthorAndLicense: "vlk" + Author: "vlk" Name: "Ti-6Al-4V (Grade 5)" Models: Father: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/ABS-Generic.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/ABS-Generic.FCMat index d85813be24..b5fba41f91 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/ABS-Generic.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/ABS-Generic.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "73371529-2983-47dd-b988-6739a2e20029" - AuthorAndLicense: "(c) 2013 Juergen Riegel (CC-BY 3.0)" + Author: "Juergen Riegel" + License: "CC-BY-3.0" Name: "ABS" Description: "This is a blend AcrylnitrilButadienStyrol (ABS) material card. The values are at the low end of the spectrum. If you need a more precise material definition use the more specialised ABS-blend cards." SourceURL: "http://www.matweb.com/search/DataSheet.aspx?MatGUID=eb7a78f5948d481c9493a67f0d089646" diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/Acrylic-Glass-Generic.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/Acrylic-Glass-Generic.FCMat index 086f0b1ad5..8daa44d95b 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/Acrylic-Glass-Generic.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/Acrylic-Glass-Generic.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "f255cd82-91d5-4e97-9032-1843128a2eaa" - AuthorAndLicense: "(c) 2016 Przemo Firszt (CC-BY 3.0)" + Author: "Przemo Firszt" + License: "CC-BY-3.0" Name: "Acrylic Glass" Description: "Poly(methyl methacrylate) (PMMA, acrylic, acrylic glass, trade names Plexiglas, Acrylite, Lucite, Perspex) a transparent thermoplastic often used in sheet form as a lightweight or shatter-resistant alternative to glass." SourceURL: "http://www.matweb.com/search/DataSheet.aspx?MatGUID=632572aeef2a4224b5ac8fbd4f1b6f77" diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/PA6-Generic.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/PA6-Generic.FCMat index 1a16486a01..2460f65648 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/PA6-Generic.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/PA6-Generic.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "9d59dc3b-ce66-4bec-82c9-b962082e7c9e" - AuthorAndLicense: "(c) 2019 Uwe Stöhr (CC-BY 3.0)" + Author: "Uwe Stöhr" + License: "CC-BY-3.0" Name: "Polyamide 6" SourceURL: "http://www.matweb.com/search/datasheet.aspx?MatGUID=8d78f3cfcb6f49d595896ce6ce6a2ef1" Models: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/PET-Generic.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/PET-Generic.FCMat index 6822285250..c80562e2b1 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/PET-Generic.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/PET-Generic.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "f73004e3-6fb4-4591-8be7-89d1370be312" - AuthorAndLicense: "(c) 2019 Uwe Stöhr (CC-BY 3.0)" + Author: "Uwe Stöhr" + License: "CC-BY-3.0" Name: "PET" SourceURL: "http://www.matweb.com/search/DataSheet.aspx?MatGUID=a696bdcdff6f41dd98f8eec3599eaa20" Models: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/PLA-Generic.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/PLA-Generic.FCMat index f1f23fd796..1eab389a6d 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/PLA-Generic.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/PLA-Generic.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "93861244-fbbe-41a9-a7e0-aeed53abd782" - AuthorAndLicense: "(c) 2019 Uwe Stöhr (CC-BY 3.0)" + Author: "Uwe Stöhr" + License: "CC-BY-3.0" Name: "PLA" Description: "Polylactic acid or polylactide (PLA, Poly) is a biodegradable thermoplastic aliphatic polyester derived from renewable resources, such as corn starch, tapioca roots, chips, starch or sugarcane." SourceURL: "https://www.sd3d.com/wp-content/uploads/2017/06/MaterialTDS-PLA_01.pdf" diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/PP-Generic.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/PP-Generic.FCMat index 19a8d81b6b..39c439f422 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/PP-Generic.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/PP-Generic.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "0e669f57-de27-4915-9a02-124f36047972" - AuthorAndLicense: "(c) 2019 Uwe Stöhr (CC-BY 3.0)" + Author: "Uwe Stöhr" + License: "CC-BY-3.0" Name: "Polypropylene" SourceURL: "http://www.matweb.com/search/DataSheet.aspx?MatGUID=a882a1c603374e278d062f106dfda95b" Models: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/PTFE-Generic.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/PTFE-Generic.FCMat index b7091e9e05..8cdd2fcb2b 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/PTFE-Generic.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/PTFE-Generic.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "8ce226db-43ef-4471-93f1-07e7276aa276" - AuthorAndLicense: "(c) 2019 Uwe Stöhr (CC-BY 3.0)" + Author: "Uwe Stöhr" + License: "CC-BY-3.0" Name: "PTFE" SourceURL: "http://www.matweb.com/search/datasheet.aspx?MatGUID=4d14eac958e5401a8fd152e1261b6843" Models: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/PVC-Generic.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/PVC-Generic.FCMat index dfde218e7f..f94f4e5b11 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/PVC-Generic.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Thermoplast/PVC-Generic.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "758cfc44-f4ad-4605-8645-75e9e6b053ab" - AuthorAndLicense: "(c) 2019 Uwe Stöhr (CC-BY 3.0)" + Author: "Uwe Stöhr" + License: "CC-BY-3.0" Name: "PVC" SourceURL: "http://www.matweb.com/search/DataSheet.aspx?MatGUID=1f650966ec834bb8833dd4c6e3116079" Models: diff --git a/src/Mod/Material/Resources/Materials/StandardMaterial/Wood/Wood-Generic.FCMat b/src/Mod/Material/Resources/Materials/StandardMaterial/Wood/Wood-Generic.FCMat index 9c64883f91..4f87fd1b6d 100644 --- a/src/Mod/Material/Resources/Materials/StandardMaterial/Wood/Wood-Generic.FCMat +++ b/src/Mod/Material/Resources/Materials/StandardMaterial/Wood/Wood-Generic.FCMat @@ -1,7 +1,8 @@ # File created by ConvertFCMat.py General: UUID: "b588224e-e8d6-47ad-ba1f-a058333fd1c6" - AuthorAndLicense: "(c) 2015 Bernd Hahnebach (CC-BY 3.0)" + Author: "Bernd Hahnebach" + License: "CC-BY-3.0" Name: "Wood" Description: "A standard construction wood" Models: diff --git a/src/Mod/Material/TestMaterialsApp.py b/src/Mod/Material/TestMaterialsApp.py index 4679987368..30d562dc6f 100644 --- a/src/Mod/Material/TestMaterialsApp.py +++ b/src/Mod/Material/TestMaterialsApp.py @@ -26,220 +26,5 @@ import unittest import FreeCAD import Material -parseQuantity = FreeCAD.Units.parseQuantity -# import locale -# locale.setpreferredencoding("UTF8") - -class MaterialTestCases(unittest.TestCase): - def setUp(self): - self.ModelManager = Material.ModelManager() - self.MaterialManager = Material.MaterialManager() - - def testModelManager(self): - self.assertIn("ModelLibraries", dir(self.ModelManager)) - self.assertIn("Models", dir(self.ModelManager)) - - def testMaterialManager(self): - self.assertIn("MaterialLibraries", dir(self.MaterialManager)) - self.assertIn("Materials", dir(self.MaterialManager)) - - def testModelLoad(self): - density = self.ModelManager.getModel("454661e5-265b-4320-8e6f-fcf6223ac3af") - self.assertIsNotNone(density) - self.assertEqual(density.Name, "Density") - self.assertEqual(density.UUID, "454661e5-265b-4320-8e6f-fcf6223ac3af") - self.assertIn("Density", density.Properties) - prop = density.Properties["Density"] - self.assertIn("Description", dir(prop)) - self.assertIn("Name", dir(prop)) - self.assertIn("Type", dir(prop)) - self.assertIn("URL", dir(prop)) - self.assertIn("Units", dir(prop)) - self.assertEqual(prop.Name, "Density") - - def testCalculiXSteel(self): - steel = self.MaterialManager.getMaterial("92589471-a6cb-4bbc-b748-d425a17dea7d") - self.assertIsNotNone(steel) - self.assertEqual(steel.Name, "CalculiX-Steel") - self.assertEqual(steel.UUID, "92589471-a6cb-4bbc-b748-d425a17dea7d") - - self.assertTrue(steel.hasPhysicalModel('454661e5-265b-4320-8e6f-fcf6223ac3af')) # Density - self.assertTrue(steel.hasPhysicalModel('f6f9e48c-b116-4e82-ad7f-3659a9219c50')) # IsotropicLinearElastic - self.assertTrue(steel.hasPhysicalModel('9959d007-a970-4ea7-bae4-3eb1b8b883c7')) # Thermal - self.assertFalse(steel.hasPhysicalModel('7b561d1d-fb9b-44f6-9da9-56a4f74d7536')) # Legacy linear elastic - Not in the model - self.assertTrue(steel.hasAppearanceModel('f006c7e4-35b7-43d5-bbf9-c5d572309e6e')) # BasicRendering - inherited from Steel.FCMat - - self.assertTrue(steel.isPhysicalModelComplete('454661e5-265b-4320-8e6f-fcf6223ac3af')) # Density - self.assertFalse(steel.isPhysicalModelComplete('f6f9e48c-b116-4e82-ad7f-3659a9219c50')) # IsotropicLinearElastic - incomplete - self.assertTrue(steel.isPhysicalModelComplete('9959d007-a970-4ea7-bae4-3eb1b8b883c7')) # Thermal - self.assertFalse(steel.isPhysicalModelComplete('7b561d1d-fb9b-44f6-9da9-56a4f74d7536')) # Legacy linear elastic - Not in the model - self.assertTrue(steel.isAppearanceModelComplete('f006c7e4-35b7-43d5-bbf9-c5d572309e6e')) # BasicRendering - inherited from Steel.FCMat - - self.assertTrue(steel.hasPhysicalProperty("Density")) - self.assertTrue(steel.hasPhysicalProperty("BulkModulus")) - self.assertTrue(steel.hasPhysicalProperty("PoissonRatio")) - self.assertTrue(steel.hasPhysicalProperty("YoungsModulus")) - self.assertTrue(steel.hasPhysicalProperty("ShearModulus")) - self.assertTrue(steel.hasPhysicalProperty("SpecificHeat")) - self.assertTrue(steel.hasPhysicalProperty("ThermalConductivity")) - self.assertTrue(steel.hasPhysicalProperty("ThermalExpansionCoefficient")) - self.assertTrue(steel.hasAppearanceProperty("AmbientColor")) - self.assertTrue(steel.hasAppearanceProperty("DiffuseColor")) - self.assertTrue(steel.hasAppearanceProperty("EmissiveColor")) - self.assertTrue(steel.hasAppearanceProperty("Shininess")) - self.assertTrue(steel.hasAppearanceProperty("SpecularColor")) - self.assertTrue(steel.hasAppearanceProperty("Transparency")) - - properties = steel.PhysicalProperties - self.assertIn("Density", properties) - self.assertNotIn("BulkModulus", properties) - self.assertIn("PoissonRatio", properties) - self.assertIn("YoungsModulus", properties) - self.assertNotIn("ShearModulus", properties) - self.assertIn("SpecificHeat", properties) - self.assertIn("ThermalConductivity", properties) - self.assertIn("ThermalExpansionCoefficient", properties) - self.assertNotIn("AmbientColor", properties) - self.assertNotIn("DiffuseColor", properties) - self.assertNotIn("EmissiveColor", properties) - self.assertNotIn("Shininess", properties) - self.assertNotIn("SpecularColor", properties) - self.assertNotIn("Transparency", properties) - - properties = steel.AppearanceProperties - self.assertNotIn("Density", properties) - self.assertNotIn("BulkModulus", properties) - self.assertNotIn("PoissonRatio", properties) - self.assertNotIn("YoungsModulus", properties) - self.assertNotIn("ShearModulus", properties) - self.assertNotIn("SpecificHeat", properties) - self.assertNotIn("ThermalConductivity", properties) - self.assertNotIn("ThermalExpansionCoefficient", properties) - self.assertIn("AmbientColor", properties) - self.assertIn("DiffuseColor", properties) - self.assertIn("EmissiveColor", properties) - self.assertIn("Shininess", properties) - self.assertIn("SpecularColor", properties) - self.assertIn("Transparency", properties) - - properties = steel.Properties - self.assertIn("Density", properties) - self.assertNotIn("BulkModulus", properties) - self.assertIn("PoissonRatio", properties) - self.assertIn("YoungsModulus", properties) - self.assertNotIn("ShearModulus", properties) - self.assertIn("SpecificHeat", properties) - self.assertIn("ThermalConductivity", properties) - self.assertIn("ThermalExpansionCoefficient", properties) - self.assertIn("AmbientColor", properties) - self.assertIn("DiffuseColor", properties) - self.assertIn("EmissiveColor", properties) - self.assertIn("Shininess", properties) - self.assertIn("SpecularColor", properties) - self.assertIn("Transparency", properties) - - # - # The test for ThermalExpansionCoefficient causes problems with some localizations - # due to the Unicode mu character in the units. I don't have a solution to this - # yet so it's commented out for now - print("Density " + properties["Density"]) - # print("BulkModulus " + properties["BulkModulus"]) - print("PoissonRatio " + properties["PoissonRatio"]) - print("YoungsModulus " + properties["YoungsModulus"]) - # print("ShearModulus " + properties["ShearModulus"]) - print("SpecificHeat " + properties["SpecificHeat"]) - print("ThermalConductivity " + properties["ThermalConductivity"]) - # print("ThermalExpansionCoefficient " + properties["ThermalExpansionCoefficient"]) - print("AmbientColor " + properties["AmbientColor"]) - print("DiffuseColor " + properties["DiffuseColor"]) - print("EmissiveColor " + properties["EmissiveColor"]) - print("Shininess " + properties["Shininess"]) - print("SpecularColor " + properties["SpecularColor"]) - print("Transparency " + properties["Transparency"]) - - self.assertTrue(len(properties["Density"]) > 0) - # self.assertTrue(len(properties["BulkModulus"]) == 0) - self.assertTrue(len(properties["PoissonRatio"]) > 0) - self.assertTrue(len(properties["YoungsModulus"]) > 0) - # self.assertTrue(len(properties["ShearModulus"]) == 0) - self.assertTrue(len(properties["SpecificHeat"]) > 0) - self.assertTrue(len(properties["ThermalConductivity"]) > 0) - self.assertTrue(len(properties["ThermalExpansionCoefficient"]) > 0) - self.assertTrue(len(properties["AmbientColor"]) > 0) - self.assertTrue(len(properties["DiffuseColor"]) > 0) - self.assertTrue(len(properties["EmissiveColor"]) > 0) - self.assertTrue(len(properties["Shininess"]) > 0) - self.assertTrue(len(properties["SpecularColor"]) > 0) - self.assertTrue(len(properties["Transparency"]) > 0) - - self.assertEqual(properties["Density"], parseQuantity("7900.00 kg/m^3").UserString) - # self.assertEqual(properties["BulkModulus"], "") - self.assertAlmostEqual(parseQuantity(properties["PoissonRatio"]).Value, parseQuantity("0.30000001192092896").Value) - self.assertEqual(properties["YoungsModulus"], parseQuantity("210.00 GPa").UserString) - # self.assertEqual(properties["ShearModulus"], "") - self.assertEqual(properties["SpecificHeat"], parseQuantity("590.00 J/kg/K").UserString) - self.assertEqual(properties["ThermalConductivity"], parseQuantity("43.00 W/m/K").UserString) - self.assertEqual(properties["ThermalExpansionCoefficient"], parseQuantity("12.00 µm/m/K").UserString) - self.assertEqual(properties["AmbientColor"], "(0.0020, 0.0020, 0.0020, 1.0)") - self.assertEqual(properties["DiffuseColor"], "(0.0000, 0.0000, 0.0000, 1.0)") - self.assertEqual(properties["EmissiveColor"], "(0.0000, 0.0000, 0.0000, 1.0)") - self.assertAlmostEqual(parseQuantity(properties["Shininess"]).Value, parseQuantity("0.05999999865889549").Value) - self.assertEqual(properties["SpecularColor"], "(0.9800, 0.9800, 0.9800, 1.0)") - self.assertAlmostEqual(parseQuantity(properties["Transparency"]).Value, parseQuantity("0").Value) - - print("Density " + steel.getPhysicalValue("Density").UserString) - # print("BulkModulus " + properties["BulkModulus"]) - print("PoissonRatio %f" % steel.getPhysicalValue("PoissonRatio")) - print("YoungsModulus " + steel.getPhysicalValue("YoungsModulus").UserString) - # print("ShearModulus " + properties["ShearModulus"]) - print("SpecificHeat " + steel.getPhysicalValue("SpecificHeat").UserString) - print("ThermalConductivity " + steel.getPhysicalValue("ThermalConductivity").UserString) - # print("ThermalExpansionCoefficient " + steel.getPhysicalValue("ThermalExpansionCoefficient").UserString) - print("AmbientColor " + steel.getAppearanceValue("AmbientColor")) - print("DiffuseColor " + steel.getAppearanceValue("DiffuseColor")) - print("EmissiveColor " + steel.getAppearanceValue("EmissiveColor")) - print("Shininess %f" % steel.getAppearanceValue("Shininess")) - print("SpecularColor " + steel.getAppearanceValue("SpecularColor")) - print("Transparency %f" % steel.getAppearanceValue("Transparency")) - - self.assertAlmostEqual(steel.getPhysicalValue("Density").Value, 7.9e-06) - self.assertAlmostEqual(steel.getPhysicalValue("PoissonRatio"), 0.3) - self.assertAlmostEqual(steel.getPhysicalValue("YoungsModulus").Value, 210000000.0) - self.assertAlmostEqual(steel.getPhysicalValue("SpecificHeat").Value, 590000000.0) - self.assertAlmostEqual(steel.getPhysicalValue("ThermalConductivity").Value, 43000.0) - self.assertAlmostEqual(steel.getPhysicalValue("ThermalExpansionCoefficient").Value, 1.2e-05) - self.assertEqual(steel.getAppearanceValue("AmbientColor"), "(0.0020, 0.0020, 0.0020, 1.0)") - self.assertEqual(steel.getAppearanceValue("DiffuseColor"), "(0.0000, 0.0000, 0.0000, 1.0)") - self.assertEqual(steel.getAppearanceValue("EmissiveColor"), "(0.0000, 0.0000, 0.0000, 1.0)") - self.assertAlmostEqual(steel.getAppearanceValue("Shininess"), 0.06) - self.assertEqual(steel.getAppearanceValue("SpecularColor"), "(0.9800, 0.9800, 0.9800, 1.0)") - self.assertAlmostEqual(steel.getAppearanceValue("Transparency"), 0.0) - - def testMaterialsWithModel(self): - materials = self.MaterialManager.materialsWithModel('f6f9e48c-b116-4e82-ad7f-3659a9219c50') # IsotropicLinearElastic - materialsComplete = self.MaterialManager.materialsWithModelComplete('f6f9e48c-b116-4e82-ad7f-3659a9219c50') # IsotropicLinearElastic - - self.assertTrue(len(materialsComplete) <= len(materials)) # Not all will be complete - - materialsLinearElastic = self.MaterialManager.materialsWithModel('7b561d1d-fb9b-44f6-9da9-56a4f74d7536') # LinearElastic - - # All LinearElastic models should be in IsotropicLinearElastic since it is inherited - self.assertTrue(len(materialsLinearElastic) <= len(materials)) - for mat in materialsLinearElastic: - self.assertIn(mat, materials) - - def testMaterialByPath(self): - steel = self.MaterialManager.getMaterialByPath('StandardMaterial/Metal/Steel/CalculiX-Steel.FCMat', 'System') - self.assertIsNotNone(steel) - self.assertEqual(steel.Name, "CalculiX-Steel") - self.assertEqual(steel.UUID, "92589471-a6cb-4bbc-b748-d425a17dea7d") - - steel2 = self.MaterialManager.getMaterialByPath('/StandardMaterial/Metal/Steel/CalculiX-Steel.FCMat', 'System') - self.assertIsNotNone(steel2) - self.assertEqual(steel2.Name, "CalculiX-Steel") - self.assertEqual(steel2.UUID, "92589471-a6cb-4bbc-b748-d425a17dea7d") - - steel3 = self.MaterialManager.getMaterialByPath('/System/StandardMaterial/Metal/Steel/CalculiX-Steel.FCMat', 'System') - self.assertIsNotNone(steel3) - self.assertEqual(steel3.Name, "CalculiX-Steel") - self.assertEqual(steel3.UUID, "92589471-a6cb-4bbc-b748-d425a17dea7d") +from materialtests.TestModels import ModelTestCases +from materialtests.TestMaterials import MaterialTestCases diff --git a/src/Mod/Material/materialtests/TestMaterials.py b/src/Mod/Material/materialtests/TestMaterials.py new file mode 100644 index 0000000000..7e8cb030df --- /dev/null +++ b/src/Mod/Material/materialtests/TestMaterials.py @@ -0,0 +1,228 @@ +#************************************************************************** +# Copyright (c) 2023 David Carter * +# * +# This file is part of the FreeCAD CAx development system. * +# * +# This program is free software; you can redistribute it and/or modify * +# it under the terms of the GNU Lesser General Public License (LGPL) * +# as published by the Free Software Foundation; either version 2 of * +# the License, or (at your option) any later version. * +# for detail see the LICENCE text file. * +# * +# FreeCAD is distributed in the hope that it will be useful, * +# but WITHOUT ANY WARRANTY; without even the implied warranty of * +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +# GNU Library General Public License for more details. * +# * +# You should have received a copy of the GNU Library General Public * +# License along with FreeCAD; if not, write to the Free Software * +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * +# USA * +#************************************************************************** + +# import FreeCAD +from os import walk +import unittest +import FreeCAD +import Material + +parseQuantity = FreeCAD.Units.parseQuantity + +class MaterialTestCases(unittest.TestCase): + def setUp(self): + self.ModelManager = Material.ModelManager() + self.MaterialManager = Material.MaterialManager() + self.uuids = Material.UUIDs() + + def testMaterialManager(self): + self.assertIn("MaterialLibraries", dir(self.MaterialManager)) + self.assertIn("Materials", dir(self.MaterialManager)) + + def testCalculiXSteel(self): + steel = self.MaterialManager.getMaterial("92589471-a6cb-4bbc-b748-d425a17dea7d") + self.assertIsNotNone(steel) + self.assertEqual(steel.Name, "CalculiX-Steel") + self.assertEqual(steel.UUID, "92589471-a6cb-4bbc-b748-d425a17dea7d") + + self.assertTrue(steel.hasPhysicalModel(self.uuids.Density)) + self.assertTrue(steel.hasPhysicalModel(self.uuids.IsotropicLinearElastic)) + self.assertTrue(steel.hasPhysicalModel(self.uuids.Thermal)) + self.assertFalse(steel.hasPhysicalModel(self.uuids.LinearElastic)) # Not in the model + self.assertTrue(steel.hasAppearanceModel(self.uuids.BasicRendering)) # inherited from Steel.FCMat + + self.assertTrue(steel.isPhysicalModelComplete(self.uuids.Density)) + self.assertFalse(steel.isPhysicalModelComplete(self.uuids.IsotropicLinearElastic)) + self.assertTrue(steel.isPhysicalModelComplete(self.uuids.Thermal)) + self.assertFalse(steel.isPhysicalModelComplete(self.uuids.LinearElastic)) # Not in the model + self.assertTrue(steel.isAppearanceModelComplete(self.uuids.BasicRendering)) # inherited from Steel.FCMat + + self.assertTrue(steel.hasPhysicalProperty("Density")) + self.assertTrue(steel.hasPhysicalProperty("BulkModulus")) + self.assertTrue(steel.hasPhysicalProperty("PoissonRatio")) + self.assertTrue(steel.hasPhysicalProperty("YoungsModulus")) + self.assertTrue(steel.hasPhysicalProperty("ShearModulus")) + self.assertTrue(steel.hasPhysicalProperty("SpecificHeat")) + self.assertTrue(steel.hasPhysicalProperty("ThermalConductivity")) + self.assertTrue(steel.hasPhysicalProperty("ThermalExpansionCoefficient")) + self.assertTrue(steel.hasAppearanceProperty("AmbientColor")) + self.assertTrue(steel.hasAppearanceProperty("DiffuseColor")) + self.assertTrue(steel.hasAppearanceProperty("EmissiveColor")) + self.assertTrue(steel.hasAppearanceProperty("Shininess")) + self.assertTrue(steel.hasAppearanceProperty("SpecularColor")) + self.assertTrue(steel.hasAppearanceProperty("Transparency")) + + properties = steel.PhysicalProperties + self.assertIn("Density", properties) + self.assertNotIn("BulkModulus", properties) + self.assertIn("PoissonRatio", properties) + self.assertIn("YoungsModulus", properties) + self.assertNotIn("ShearModulus", properties) + self.assertIn("SpecificHeat", properties) + self.assertIn("ThermalConductivity", properties) + self.assertIn("ThermalExpansionCoefficient", properties) + self.assertNotIn("AmbientColor", properties) + self.assertNotIn("DiffuseColor", properties) + self.assertNotIn("EmissiveColor", properties) + self.assertNotIn("Shininess", properties) + self.assertNotIn("SpecularColor", properties) + self.assertNotIn("Transparency", properties) + + properties = steel.AppearanceProperties + self.assertNotIn("Density", properties) + self.assertNotIn("BulkModulus", properties) + self.assertNotIn("PoissonRatio", properties) + self.assertNotIn("YoungsModulus", properties) + self.assertNotIn("ShearModulus", properties) + self.assertNotIn("SpecificHeat", properties) + self.assertNotIn("ThermalConductivity", properties) + self.assertNotIn("ThermalExpansionCoefficient", properties) + self.assertIn("AmbientColor", properties) + self.assertIn("DiffuseColor", properties) + self.assertIn("EmissiveColor", properties) + self.assertIn("Shininess", properties) + self.assertIn("SpecularColor", properties) + self.assertIn("Transparency", properties) + + properties = steel.Properties + self.assertIn("Density", properties) + self.assertNotIn("BulkModulus", properties) + self.assertIn("PoissonRatio", properties) + self.assertIn("YoungsModulus", properties) + self.assertNotIn("ShearModulus", properties) + self.assertIn("SpecificHeat", properties) + self.assertIn("ThermalConductivity", properties) + self.assertIn("ThermalExpansionCoefficient", properties) + self.assertIn("AmbientColor", properties) + self.assertIn("DiffuseColor", properties) + self.assertIn("EmissiveColor", properties) + self.assertIn("Shininess", properties) + self.assertIn("SpecularColor", properties) + self.assertIn("Transparency", properties) + + # + # The test for ThermalExpansionCoefficient causes problems with some localizations + # due to the Unicode mu character in the units. This will happen with + # locales that don't support UTF8 such as zh_CN (It does support UTF-8) + # + # When this is a problem simply comment the lines printing ThermalExpansionCoefficient + print("Density " + properties["Density"]) + # print("BulkModulus " + properties["BulkModulus"]) + print("PoissonRatio " + properties["PoissonRatio"]) + print("YoungsModulus " + properties["YoungsModulus"]) + # print("ShearModulus " + properties["ShearModulus"]) + print("SpecificHeat " + properties["SpecificHeat"]) + print("ThermalConductivity " + properties["ThermalConductivity"]) + print("ThermalExpansionCoefficient " + properties["ThermalExpansionCoefficient"]) + print("AmbientColor " + properties["AmbientColor"]) + print("DiffuseColor " + properties["DiffuseColor"]) + print("EmissiveColor " + properties["EmissiveColor"]) + print("Shininess " + properties["Shininess"]) + print("SpecularColor " + properties["SpecularColor"]) + print("Transparency " + properties["Transparency"]) + + self.assertTrue(len(properties["Density"]) > 0) + # self.assertTrue(len(properties["BulkModulus"]) == 0) + self.assertTrue(len(properties["PoissonRatio"]) > 0) + self.assertTrue(len(properties["YoungsModulus"]) > 0) + # self.assertTrue(len(properties["ShearModulus"]) == 0) + self.assertTrue(len(properties["SpecificHeat"]) > 0) + self.assertTrue(len(properties["ThermalConductivity"]) > 0) + self.assertTrue(len(properties["ThermalExpansionCoefficient"]) > 0) + self.assertTrue(len(properties["AmbientColor"]) > 0) + self.assertTrue(len(properties["DiffuseColor"]) > 0) + self.assertTrue(len(properties["EmissiveColor"]) > 0) + self.assertTrue(len(properties["Shininess"]) > 0) + self.assertTrue(len(properties["SpecularColor"]) > 0) + self.assertTrue(len(properties["Transparency"]) > 0) + + self.assertEqual(properties["Density"], parseQuantity("7900.00 kg/m^3").UserString) + # self.assertEqual(properties["BulkModulus"], "") + self.assertAlmostEqual(parseQuantity(properties["PoissonRatio"]).Value, parseQuantity("0.3").Value) + self.assertEqual(properties["YoungsModulus"], parseQuantity("210.00 GPa").UserString) + # self.assertEqual(properties["ShearModulus"], "") + self.assertEqual(properties["SpecificHeat"], parseQuantity("590.00 J/kg/K").UserString) + self.assertEqual(properties["ThermalConductivity"], parseQuantity("43.00 W/m/K").UserString) + self.assertEqual(properties["ThermalExpansionCoefficient"], parseQuantity("12.00 µm/m/K").UserString) + self.assertEqual(properties["AmbientColor"], "(0.0020, 0.0020, 0.0020, 1.0)") + self.assertEqual(properties["DiffuseColor"], "(0.0000, 0.0000, 0.0000, 1.0)") + self.assertEqual(properties["EmissiveColor"], "(0.0000, 0.0000, 0.0000, 1.0)") + self.assertAlmostEqual(parseQuantity(properties["Shininess"]).Value, parseQuantity("0.06").Value) + self.assertEqual(properties["SpecularColor"], "(0.9800, 0.9800, 0.9800, 1.0)") + self.assertAlmostEqual(parseQuantity(properties["Transparency"]).Value, parseQuantity("0").Value) + + print("Density " + steel.getPhysicalValue("Density").UserString) + # print("BulkModulus " + properties["BulkModulus"]) + print("PoissonRatio %f" % steel.getPhysicalValue("PoissonRatio")) + print("YoungsModulus " + steel.getPhysicalValue("YoungsModulus").UserString) + # print("ShearModulus " + properties["ShearModulus"]) + print("SpecificHeat " + steel.getPhysicalValue("SpecificHeat").UserString) + print("ThermalConductivity " + steel.getPhysicalValue("ThermalConductivity").UserString) + print("ThermalExpansionCoefficient " + steel.getPhysicalValue("ThermalExpansionCoefficient").UserString) + print("AmbientColor " + steel.getAppearanceValue("AmbientColor")) + print("DiffuseColor " + steel.getAppearanceValue("DiffuseColor")) + print("EmissiveColor " + steel.getAppearanceValue("EmissiveColor")) + print("Shininess %f" % steel.getAppearanceValue("Shininess")) + print("SpecularColor " + steel.getAppearanceValue("SpecularColor")) + print("Transparency %f" % steel.getAppearanceValue("Transparency")) + + self.assertAlmostEqual(steel.getPhysicalValue("Density").Value, 7.9e-06) + self.assertAlmostEqual(steel.getPhysicalValue("PoissonRatio"), 0.3) + self.assertAlmostEqual(steel.getPhysicalValue("YoungsModulus").Value, 210000000.0) + self.assertAlmostEqual(steel.getPhysicalValue("SpecificHeat").Value, 590000000.0) + self.assertAlmostEqual(steel.getPhysicalValue("ThermalConductivity").Value, 43000.0) + self.assertAlmostEqual(steel.getPhysicalValue("ThermalExpansionCoefficient").Value, 1.2e-05) + self.assertEqual(steel.getAppearanceValue("AmbientColor"), "(0.0020, 0.0020, 0.0020, 1.0)") + self.assertEqual(steel.getAppearanceValue("DiffuseColor"), "(0.0000, 0.0000, 0.0000, 1.0)") + self.assertEqual(steel.getAppearanceValue("EmissiveColor"), "(0.0000, 0.0000, 0.0000, 1.0)") + self.assertAlmostEqual(steel.getAppearanceValue("Shininess"), 0.06) + self.assertEqual(steel.getAppearanceValue("SpecularColor"), "(0.9800, 0.9800, 0.9800, 1.0)") + self.assertAlmostEqual(steel.getAppearanceValue("Transparency"), 0.0) + + def testMaterialsWithModel(self): + materials = self.MaterialManager.materialsWithModel('f6f9e48c-b116-4e82-ad7f-3659a9219c50') # IsotropicLinearElastic + materialsComplete = self.MaterialManager.materialsWithModelComplete('f6f9e48c-b116-4e82-ad7f-3659a9219c50') # IsotropicLinearElastic + + self.assertTrue(len(materialsComplete) <= len(materials)) # Not all will be complete + + materialsLinearElastic = self.MaterialManager.materialsWithModel('7b561d1d-fb9b-44f6-9da9-56a4f74d7536') # LinearElastic + + # All LinearElastic models should be in IsotropicLinearElastic since it is inherited + self.assertTrue(len(materialsLinearElastic) <= len(materials)) + for mat in materialsLinearElastic: + self.assertIn(mat, materials) + + def testMaterialByPath(self): + steel = self.MaterialManager.getMaterialByPath('StandardMaterial/Metal/Steel/CalculiX-Steel.FCMat', 'System') + self.assertIsNotNone(steel) + self.assertEqual(steel.Name, "CalculiX-Steel") + self.assertEqual(steel.UUID, "92589471-a6cb-4bbc-b748-d425a17dea7d") + + steel2 = self.MaterialManager.getMaterialByPath('/StandardMaterial/Metal/Steel/CalculiX-Steel.FCMat', 'System') + self.assertIsNotNone(steel2) + self.assertEqual(steel2.Name, "CalculiX-Steel") + self.assertEqual(steel2.UUID, "92589471-a6cb-4bbc-b748-d425a17dea7d") + + steel3 = self.MaterialManager.getMaterialByPath('/System/StandardMaterial/Metal/Steel/CalculiX-Steel.FCMat', 'System') + self.assertIsNotNone(steel3) + self.assertEqual(steel3.Name, "CalculiX-Steel") + self.assertEqual(steel3.UUID, "92589471-a6cb-4bbc-b748-d425a17dea7d") diff --git a/src/Mod/Material/materialtests/TestModels.py b/src/Mod/Material/materialtests/TestModels.py new file mode 100644 index 0000000000..d4fd143442 --- /dev/null +++ b/src/Mod/Material/materialtests/TestModels.py @@ -0,0 +1,79 @@ +#************************************************************************** +# Copyright (c) 2023 David Carter * +# * +# This file is part of the FreeCAD CAx development system. * +# * +# This program is free software; you can redistribute it and/or modify * +# it under the terms of the GNU Lesser General Public License (LGPL) * +# as published by the Free Software Foundation; either version 2 of * +# the License, or (at your option) any later version. * +# for detail see the LICENCE text file. * +# * +# FreeCAD is distributed in the hope that it will be useful, * +# but WITHOUT ANY WARRANTY; without even the implied warranty of * +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +# GNU Library General Public License for more details. * +# * +# You should have received a copy of the GNU Library General Public * +# License along with FreeCAD; if not, write to the Free Software * +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * +# USA * +#************************************************************************** + +# import FreeCAD +from os import walk +import unittest +import FreeCAD +import Material + +parseQuantity = FreeCAD.Units.parseQuantity +# import locale +# locale.setpreferredencoding("UTF8") + +class ModelTestCases(unittest.TestCase): + def setUp(self): + self.ModelManager = Material.ModelManager() + self.uuids = Material.UUIDs() + + def testModelManager(self): + self.assertIn("ModelLibraries", dir(self.ModelManager)) + self.assertIn("Models", dir(self.ModelManager)) + + def testUUIDs(self): + self.assertTrue(self.uuids.Father, "9cdda8b6-b606-4778-8f13-3934d8668e67") + self.assertTrue(self.uuids.MaterialStandard, "1e2c0088-904a-4537-925f-64064c07d700") + + self.assertTrue(self.uuids.Density, "454661e5-265b-4320-8e6f-fcf6223ac3af") + self.assertTrue(self.uuids.IsotropicLinearElastic, "f6f9e48c-b116-4e82-ad7f-3659a9219c50") + self.assertTrue(self.uuids.LinearElastic,"7b561d1d-fb9b-44f6-9da9-56a4f74d7536") + self.assertTrue(self.uuids.OgdenYld2004p18, "3ef9e427-cc25-43f7-817f-79ff0d49625f") + self.assertTrue(self.uuids.OrthotropicLinearElastic, "b19ccc6b-a431-418e-91c2-0ac8c649d146") + + self.assertTrue(self.uuids.Fluid, "1ae66d8c-1ba1-4211-ad12-b9917573b202") + + self.assertTrue(self.uuids.Thermal, "9959d007-a970-4ea7-bae4-3eb1b8b883c7") + + self.assertTrue(self.uuids.Electromagnetic, "b2eb5f48-74b3-4193-9fbb-948674f427f3") + + self.assertTrue(self.uuids.Architectural, "32439c3b-262f-4b7b-99a8-f7f44e5894c8") + + self.assertTrue(self.uuids.Costs, "881df808-8726-4c2e-be38-688bb6cce466") + + self.assertTrue(self.uuids.BasicRendering, "f006c7e4-35b7-43d5-bbf9-c5d572309e6e") + self.assertTrue(self.uuids.TextureRendering, "bbdcc65b-67ca-489c-bd5c-a36e33d1c160") + self.assertTrue(self.uuids.AdvancedRendering, "c880f092-cdae-43d6-a24b-55e884aacbbf") + self.assertTrue(self.uuids.VectorRendering, "fdf5a80e-de50-4157-b2e5-b6e5f88b680e") + + def testModelLoad(self): + density = self.ModelManager.getModel(self.uuids.Density) + self.assertIsNotNone(density) + self.assertEqual(density.Name, "Density") + self.assertEqual(density.UUID, "454661e5-265b-4320-8e6f-fcf6223ac3af") + self.assertIn("Density", density.Properties) + prop = density.Properties["Density"] + self.assertIn("Description", dir(prop)) + self.assertIn("Name", dir(prop)) + self.assertIn("Type", dir(prop)) + self.assertIn("URL", dir(prop)) + self.assertIn("Units", dir(prop)) + self.assertEqual(prop.Name, "Density") diff --git a/src/Mod/Material/materialtests/__init__.py b/src/Mod/Material/materialtests/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/Tools/updatecrowdin.py b/src/Tools/updatecrowdin.py index 57c17d890f..15f197b48c 100755 --- a/src/Tools/updatecrowdin.py +++ b/src/Tools/updatecrowdin.py @@ -96,7 +96,6 @@ GENERATE_QM = { "Cloud", "Draft", "Inspection", - "Material", "OpenSCAD", "Tux", "Help", @@ -135,6 +134,11 @@ locations = [ "../Mod/Inspection/Gui/Resources/translations", "../Mod/Inspection/Gui/Resources/Inspection.qrc", ], + [ + "Material", + "../Mod/Material/Gui/Resources/translations", + "../Mod/Material/Gui/Resources/Material.qrc", + ], [ "Mesh", "../Mod/Mesh/Gui/Resources/translations", diff --git a/tests/src/Mod/Material/App/CMakeLists.txt b/tests/src/Mod/Material/App/CMakeLists.txt index 879f74ef06..1e1fe038b7 100644 --- a/tests/src/Mod/Material/App/CMakeLists.txt +++ b/tests/src/Mod/Material/App/CMakeLists.txt @@ -2,5 +2,9 @@ target_sources( Material_tests_run PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR}/Model.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/TestMaterialProperties.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/TestMaterials.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/TestMaterialValue.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/TestModel.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/TestModelProperties.cpp ) diff --git a/tests/src/Mod/Material/App/TestMaterialProperties.cpp b/tests/src/Mod/Material/App/TestMaterialProperties.cpp new file mode 100644 index 0000000000..bac0b1adee --- /dev/null +++ b/tests/src/Mod/Material/App/TestMaterialProperties.cpp @@ -0,0 +1,226 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later +/*************************************************************************** + * Copyright (c) 2023 David Carter * + * * + * This file is part of FreeCAD. * + * * + * FreeCAD is free software: you can redistribute it and/or modify it * + * under the terms of the GNU Lesser General Public License as * + * published by the Free Software Foundation, either version 2.1 of the * + * License, or (at your option) any later version. * + * * + * FreeCAD is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with FreeCAD. If not, see * + * . * + * * + **************************************************************************/ + +#include "gtest/gtest.h" + +#include +#ifndef _PreComp_ +#endif + +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include + +class TestMaterialProperties: public ::testing::Test +{ +protected: + static void SetUpTestSuite() + {} + + void SetUp() override + { + // 2D Properties + modelProp = Materials::ModelProperty(QString::fromStdString("Density"), // Name + QString::fromStdString("2DArray"), // Type + QString::fromStdString(""), // Units + QString::fromStdString(""), // URL + QString::fromStdString("desc")); // Description + modelProp1 = Materials::ModelProperty(QString::fromStdString("Temperature"), + QString::fromStdString("Quantity"), + QString::fromStdString("C"), + QString::fromStdString(""), + QString::fromStdString("desc1")); + modelProp2 = Materials::ModelProperty( + QString::fromStdString("Density"), + QString::fromStdString("Quantity"), + QString::fromStdString("kg/m^3"), + QString::fromStdString("https://en.wikipedia.org/wiki/Density"), + QString::fromStdString("desc2")); + + modelProp.addColumn(modelProp1); + modelProp.addColumn(modelProp2); + + // 3D properties + model3DProp = Materials::ModelProperty( + QString::fromStdString("StressStrain"), // Name + QString::fromStdString("3DArray"), // Type + QString::fromStdString(""), // Units + QString::fromStdString(""), // URL + QString::fromStdString("3 Dimensional array showing stress and strain as a function of " + "temperature")); // Description + model3DProp1 = Materials::ModelProperty(QString::fromStdString("Temperature"), + QString::fromStdString("Quantity"), + QString::fromStdString("C"), + QString::fromStdString(""), + QString::fromStdString("desc1")); + model3DProp2 = Materials::ModelProperty(QString::fromStdString("Stress"), + QString::fromStdString("Quantity"), + QString::fromStdString("MPa"), + QString::fromStdString(""), + QString::fromStdString("desc2")); + model3DProp3 = Materials::ModelProperty(QString::fromStdString("Strain"), + QString::fromStdString("Quantity"), + QString::fromStdString("MPa"), + QString::fromStdString(""), + QString::fromStdString("desc3")); + + model3DProp.addColumn(model3DProp1); + model3DProp.addColumn(model3DProp2); + model3DProp.addColumn(model3DProp3); + } + + // void TearDown() override {} + + Materials::ModelProperty modelProp; + Materials::ModelProperty modelProp1; + Materials::ModelProperty modelProp2; + Materials::ModelProperty model3DProp; + Materials::ModelProperty model3DProp1; + Materials::ModelProperty model3DProp2; + Materials::ModelProperty model3DProp3; +}; + +TEST_F(TestMaterialProperties, TestEmpty) +{ + Materials::MaterialProperty prop; + EXPECT_EQ(prop.getType(), Materials::MaterialValue::None); + EXPECT_TRUE(prop.isNull()); + auto variant = prop.getValue(); + EXPECT_TRUE(variant.isNull()); + EXPECT_FALSE(variant.canConvert()); + EXPECT_TRUE(variant.toString().isNull()); + EXPECT_TRUE(variant.toString().isEmpty()); + EXPECT_EQ(variant.toString().size(), 0); +} + +TEST_F(TestMaterialProperties, TestSingle) +{ + Materials::MaterialProperty prop(modelProp1); + EXPECT_EQ(prop.getType(), Materials::MaterialValue::Quantity); + EXPECT_TRUE(prop.isNull()); + auto variant = prop.getValue(); + EXPECT_TRUE(variant.canConvert()); + EXPECT_FALSE(variant.value().isValid()); + EXPECT_FALSE(variant.canConvert()); + EXPECT_TRUE(variant.toString().isNull()); + EXPECT_TRUE(variant.toString().isEmpty()); + EXPECT_EQ(variant.toString().size(), 0); +} + +void check2DArray(Materials::MaterialProperty& prop) +{ + EXPECT_EQ(prop.getType(), Materials::MaterialValue::Array2D); + EXPECT_TRUE(prop.isNull()); + auto array = std::static_pointer_cast(prop.getMaterialValue()); + EXPECT_FALSE(array->defaultSet()); + EXPECT_EQ(array->rows(), 0); + auto variant = prop.getValue(); // Throw an error? + // Getting a default value is not yet defined or implemented + // EXPECT_TRUE(variant.canConvert()); + // EXPECT_TRUE(variant.isNull()); + // EXPECT_FALSE(variant.value().isValid()); -- the variant is null + EXPECT_FALSE(variant.canConvert()); + EXPECT_TRUE(variant.toString().isNull()); + EXPECT_TRUE(variant.toString().isEmpty()); + EXPECT_EQ(variant.toString().size(), 0); + + // Check the columns + EXPECT_EQ(prop.columns(), 2); +} + +TEST_F(TestMaterialProperties, Test2DArray) +{ + Materials::MaterialProperty prop(modelProp); + check2DArray(prop); +} + +TEST_F(TestMaterialProperties, Test2DArrayCopy) +{ + Materials::MaterialProperty propBase(modelProp); + Materials::MaterialProperty prop(propBase); + check2DArray(prop); +} + +TEST_F(TestMaterialProperties, Test2DArrayAssignment) +{ + Materials::MaterialProperty propBase(modelProp); + Materials::MaterialProperty prop; + + prop = propBase; + check2DArray(prop); +} + +void check3DArray(Materials::MaterialProperty& prop) +{ + EXPECT_EQ(prop.getType(), Materials::MaterialValue::Array3D); + EXPECT_TRUE(prop.isNull()); + auto array = std::static_pointer_cast(prop.getMaterialValue()); + EXPECT_FALSE(array->defaultSet()); + EXPECT_EQ(array->depth(), 0); + auto variant = prop.getValue(); // Throw an error? + // Getting a default value is not yet defined or implemented + // EXPECT_TRUE(variant.canConvert()); + // EXPECT_TRUE(variant.isNull()); + // EXPECT_FALSE(variant.value().isValid()); -- the variant is null + EXPECT_FALSE(variant.canConvert()); + EXPECT_TRUE(variant.toString().isNull()); + EXPECT_TRUE(variant.toString().isEmpty()); + EXPECT_EQ(variant.toString().size(), 0); + + // Check the columns + EXPECT_EQ(prop.columns(), 3); +} + +TEST_F(TestMaterialProperties, Test3DArray) +{ + Materials::MaterialProperty prop(model3DProp); + check3DArray(prop); +} + +TEST_F(TestMaterialProperties, Test3DArrayCopy) +{ + Materials::MaterialProperty propBase(model3DProp); + Materials::MaterialProperty prop(propBase); + check3DArray(prop); +} + +TEST_F(TestMaterialProperties, Test3DArrayAssignment) +{ + Materials::MaterialProperty propBase(model3DProp); + Materials::MaterialProperty prop; + + prop = propBase; + check3DArray(prop); +} + +// clang-format off + +// clang-format on diff --git a/tests/src/Mod/Material/App/TestMaterialValue.cpp b/tests/src/Mod/Material/App/TestMaterialValue.cpp new file mode 100644 index 0000000000..d39023f939 --- /dev/null +++ b/tests/src/Mod/Material/App/TestMaterialValue.cpp @@ -0,0 +1,310 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later +/*************************************************************************** + * Copyright (c) 2023 David Carter * + * * + * This file is part of FreeCAD. * + * * + * FreeCAD is free software: you can redistribute it and/or modify it * + * under the terms of the GNU Lesser General Public License as * + * published by the Free Software Foundation, either version 2.1 of the * + * License, or (at your option) any later version. * + * * + * FreeCAD is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with FreeCAD. If not, see * + * . * + * * + **************************************************************************/ + +#include "gtest/gtest.h" + +#include +#ifndef _PreComp_ +#endif + +#include +#include + +#include +#include + +#include +#include +#include +#include + +// clang-format off + +class TestMaterialValue : public ::testing::Test { + protected: + static void SetUpTestSuite() { + // if (App::Application::GetARGC() == 0) { + // constexpr int argc = 1; + // std::array argv {"FreeCAD"}; + // App::Application::Config()["ExeName"] = "FreeCAD"; + // App::Application::init(argc, argv.data()); + // } + } + +// void SetUp() override { +// _modelManager = new Materials::ModelManager(); +// _materialManager = new Materials::MaterialManager(); +// } + + // void TearDown() override {} +// Materials::ModelManager* _modelManager; +// Materials::MaterialManager* _materialManager; +}; + +TEST_F(TestMaterialValue, TestNoneType) +{ + auto mat1 = Materials::MaterialValue(); + EXPECT_EQ(mat1.getType(), Materials::MaterialValue::None); + EXPECT_TRUE(mat1.isNull()); + auto variant = mat1.getValue(); + EXPECT_TRUE(variant.isNull()); + EXPECT_FALSE(variant.canConvert()); + EXPECT_TRUE(variant.toString().isNull()); + EXPECT_TRUE(variant.toString().isEmpty()); + EXPECT_EQ(variant.toString().size(), 0); +} + +TEST_F(TestMaterialValue, TestStringType) +{ + auto mat1 = Materials::MaterialValue(Materials::MaterialValue::String); + EXPECT_EQ(mat1.getType(), Materials::MaterialValue::String); + EXPECT_TRUE(mat1.isNull()); + auto variant = mat1.getValue(); + EXPECT_TRUE(variant.isNull()); + EXPECT_TRUE(variant.canConvert()); + EXPECT_TRUE(variant.toString().isNull()); + EXPECT_TRUE(variant.toString().isEmpty()); + EXPECT_EQ(variant.toString().size(), 0); +} + +TEST_F(TestMaterialValue, TestBooleanType) +{ + auto mat1 = Materials::MaterialValue(Materials::MaterialValue::Boolean); + EXPECT_EQ(mat1.getType(), Materials::MaterialValue::Boolean); + EXPECT_TRUE(mat1.isNull()); + auto variant = mat1.getValue(); + EXPECT_TRUE(variant.isNull()); + EXPECT_TRUE(variant.canConvert()); + EXPECT_FALSE(variant.toString().isNull()); + EXPECT_FALSE(variant.toString().isEmpty()); + EXPECT_EQ(variant.toString().size(), 5); + EXPECT_EQ(variant.toString(), QString::fromStdString("false")); + EXPECT_EQ(variant.toBool(), false); +} + +TEST_F(TestMaterialValue, TestIntegerType) +{ + auto mat1 = Materials::MaterialValue(Materials::MaterialValue::Integer); + EXPECT_EQ(mat1.getType(), Materials::MaterialValue::Integer); + EXPECT_TRUE(mat1.isNull()); + auto variant = mat1.getValue(); + EXPECT_TRUE(variant.isNull()); + EXPECT_TRUE(variant.canConvert()); + EXPECT_FALSE(variant.toString().isNull()); + EXPECT_FALSE(variant.toString().isEmpty()); + EXPECT_EQ(variant.toString().size(), 1); + EXPECT_EQ(variant.toString(), QString::fromStdString("0")); + EXPECT_EQ(variant.toInt(), 0); +} + +TEST_F(TestMaterialValue, TestFloatType) +{ + auto mat1 = Materials::MaterialValue(Materials::MaterialValue::Float); + EXPECT_EQ(mat1.getType(), Materials::MaterialValue::Float); + EXPECT_TRUE(mat1.isNull()); + auto variant = mat1.getValue(); + EXPECT_TRUE(variant.isNull()); + EXPECT_TRUE(variant.canConvert()); + EXPECT_FALSE(variant.toString().isNull()); + EXPECT_FALSE(variant.toString().isEmpty()); + EXPECT_EQ(variant.toString().size(), 1); + EXPECT_EQ(variant.toString(), QString::fromStdString("0")); + EXPECT_EQ(variant.toFloat(), 0); +} + +TEST_F(TestMaterialValue, TestQuantityType) +{ + auto mat1 = Materials::MaterialValue(Materials::MaterialValue::Quantity); + EXPECT_EQ(mat1.getType(), Materials::MaterialValue::Quantity); + EXPECT_TRUE(mat1.isNull()); + + auto variant = mat1.getValue(); + EXPECT_FALSE(variant.isNull()); + EXPECT_TRUE(variant.canConvert()); + EXPECT_TRUE(variant.toString().isNull()); + EXPECT_TRUE(variant.toString().isEmpty()); + EXPECT_EQ(variant.toString().size(), 0); + + auto quantity = variant.value(); + EXPECT_FALSE(quantity.isValid()); + EXPECT_EQ(quantity.getUserString(), QString::fromStdString("nan ")); + EXPECT_TRUE(std::isnan(quantity.getValue())); + + // Test a copy + auto mat2 = Materials::MaterialValue(mat1); + EXPECT_EQ(mat2.getType(), Materials::MaterialValue::Quantity); + EXPECT_TRUE(mat2.isNull()); + + variant = mat2.getValue(); + EXPECT_FALSE(variant.isNull()); + EXPECT_TRUE(variant.canConvert()); + EXPECT_TRUE(variant.toString().isNull()); + EXPECT_TRUE(variant.toString().isEmpty()); + EXPECT_EQ(variant.toString().size(), 0); + + quantity = variant.value(); + EXPECT_FALSE(quantity.isValid()); + EXPECT_EQ(quantity.getUserString(), QString::fromStdString("nan ")); + EXPECT_TRUE(std::isnan(quantity.getValue())); +} + +TEST_F(TestMaterialValue, TestListType) +{ + auto mat1 = Materials::MaterialValue(Materials::MaterialValue::List); + EXPECT_EQ(mat1.getType(), Materials::MaterialValue::List); + EXPECT_TRUE(mat1.isNull()); + auto variant = mat1.getValue(); + EXPECT_TRUE(variant.isNull()); + EXPECT_TRUE(variant.canConvert()); + EXPECT_TRUE(variant.toString().isNull()); + EXPECT_TRUE(variant.toString().isEmpty()); + EXPECT_EQ(variant.toString().size(), 0); +} + +TEST_F(TestMaterialValue, TestArray2DType) +{ + EXPECT_THROW(auto mat1 = Materials::MaterialValue(Materials::MaterialValue::Array2D), Materials::InvalidMaterialType); + + auto mat2 = Materials::Material2DArray(); + EXPECT_EQ(mat2.getType(), Materials::MaterialValue::Array2D); + EXPECT_TRUE(mat2.isNull()); + auto variant = mat2.getDefault(); + EXPECT_TRUE(variant.isNull()); + EXPECT_FALSE(variant.canConvert()); + EXPECT_TRUE(variant.toString().isNull()); + EXPECT_TRUE(variant.toString().isEmpty()); + EXPECT_EQ(variant.toString().size(), 0); + + EXPECT_EQ(mat2.rows(), 0); +} + +TEST_F(TestMaterialValue, TestArray3DType) +{ + EXPECT_THROW(auto mat1 = Materials::MaterialValue(Materials::MaterialValue::Array3D), Materials::InvalidMaterialType); + + auto mat2 = Materials::Material3DArray(); + EXPECT_EQ(mat2.getType(), Materials::MaterialValue::Array3D); + EXPECT_TRUE(mat2.isNull()); + auto variant = mat2.getDefault(); + EXPECT_TRUE(variant.isNull()); + EXPECT_FALSE(variant.canConvert()); + EXPECT_TRUE(variant.toString().isNull()); + EXPECT_TRUE(variant.toString().isEmpty()); + EXPECT_EQ(variant.toString().size(), 0); + + EXPECT_EQ(mat2.depth(), 0); + EXPECT_EQ(mat2.rows(), 0); + EXPECT_EQ(mat2.rows(0), 0); + EXPECT_THROW(mat2.rows(1), Materials::InvalidDepth); + + Base::Quantity quantity; + quantity.setInvalid(); + + EXPECT_EQ(mat2.addDepth(0, quantity), 0); + EXPECT_EQ(mat2.depth(), 1); + EXPECT_EQ(mat2.rows(0), 0); + EXPECT_THROW(mat2.rows(1), Materials::InvalidDepth); + + EXPECT_EQ(mat2.addDepth(quantity), 1); + EXPECT_EQ(mat2.depth(), 2); + EXPECT_EQ(mat2.rows(1), 0); + + EXPECT_THROW(mat2.addDepth(99, quantity), Materials::InvalidDepth); + EXPECT_EQ(mat2.addDepth(2, quantity), 2); + EXPECT_EQ(mat2.depth(), 3); + EXPECT_EQ(mat2.rows(2), 0); + + // Add rows + auto row = std::make_shared>(); + row->push_back(quantity); + row->push_back(quantity); + + EXPECT_EQ(mat2.rows(0), 0); + EXPECT_EQ(mat2.rows(1), 0); + EXPECT_EQ(mat2.rows(2), 0); + + mat2.addRow(0, row); + EXPECT_EQ(mat2.rows(0), 1); + EXPECT_EQ(mat2.rows(1), 0); + EXPECT_EQ(mat2.rows(2), 0); + + mat2.addRow(1, row); + EXPECT_EQ(mat2.rows(0), 1); + EXPECT_EQ(mat2.rows(1), 1); + EXPECT_EQ(mat2.rows(2), 0); + + mat2.addRow(2, row); + EXPECT_EQ(mat2.rows(0), 1); + EXPECT_EQ(mat2.rows(1), 1); + EXPECT_EQ(mat2.rows(2), 1); + + EXPECT_EQ(mat2.currentDepth(), 0); + mat2.addRow(row); + EXPECT_EQ(mat2.rows(0), 2); + EXPECT_EQ(mat2.rows(1), 1); + EXPECT_EQ(mat2.rows(2), 1); + + mat2.setCurrentDepth(2); + EXPECT_EQ(mat2.currentDepth(), 2); + mat2.addRow(row); + EXPECT_EQ(mat2.rows(0), 2); + EXPECT_EQ(mat2.rows(1), 1); + EXPECT_EQ(mat2.rows(2), 2); + + quantity = Base::Quantity::parse(QString::fromStdString("32 C")); + mat2.setDepthValue(quantity); + EXPECT_FALSE(mat2.getDepthValue(0).isValid()); + EXPECT_FALSE(mat2.getDepthValue(1).isValid()); + EXPECT_TRUE(mat2.getDepthValue(2).isValid()); + EXPECT_EQ(mat2.getDepthValue(2), Base::Quantity::parse(QString::fromStdString("32 C"))); + + mat2.setDepthValue(0, Base::Quantity::parse(QString::fromStdString("9.8 m/s/s"))); + EXPECT_TRUE(mat2.getDepthValue(0).isValid()); + EXPECT_FALSE(mat2.getDepthValue(1).isValid()); + EXPECT_TRUE(mat2.getDepthValue(2).isValid()); + EXPECT_EQ(mat2.getDepthValue(0), Base::Quantity::parse(QString::fromStdString("9.8 m/s/s"))); + EXPECT_EQ(mat2.getDepthValue(2), Base::Quantity::parse(QString::fromStdString("32 C"))); + + mat2.setDepthValue(1, Base::Quantity::parse(QString::fromStdString("120 MPa"))); + EXPECT_TRUE(mat2.getDepthValue(0).isValid()); + EXPECT_TRUE(mat2.getDepthValue(1).isValid()); + EXPECT_TRUE(mat2.getDepthValue(2).isValid()); + EXPECT_EQ(mat2.getDepthValue(0), Base::Quantity::parse(QString::fromStdString("9.8 m/s/s"))); + EXPECT_EQ(mat2.getDepthValue(1), Base::Quantity::parse(QString::fromStdString("120 MPa"))); + EXPECT_EQ(mat2.getDepthValue(2), Base::Quantity::parse(QString::fromStdString("32 C"))); + + // Rows are currently empty + EXPECT_THROW(mat2.getValue(2, 0), Materials::InvalidRow); + EXPECT_NO_THROW(mat2.getValue(0, 0)); + EXPECT_FALSE(mat2.getValue(0, 0).isValid()); + EXPECT_FALSE(mat2.getValue(0, 1).isValid()); + + // set to a valid quantity + mat2.setValue(0, 0, Base::Quantity::parse(QString::fromStdString("120 MPa"))); + EXPECT_TRUE(mat2.getValue(0, 0).isValid()); + mat2.setValue(0, 1, Base::Quantity::parse(QString::fromStdString("9.8 m/s/s"))); + EXPECT_TRUE(mat2.getValue(0, 1).isValid()); + EXPECT_THROW(mat2.setValue(0, 2, Base::Quantity::parse(QString::fromStdString("32 C"))), Materials::InvalidColumn); + +} + +// clang-format on diff --git a/tests/src/Mod/Material/App/TestMaterials.cpp b/tests/src/Mod/Material/App/TestMaterials.cpp new file mode 100644 index 0000000000..e06212c3d4 --- /dev/null +++ b/tests/src/Mod/Material/App/TestMaterials.cpp @@ -0,0 +1,339 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later +/*************************************************************************** + * Copyright (c) 2023 David Carter * + * * + * This file is part of FreeCAD. * + * * + * FreeCAD is free software: you can redistribute it and/or modify it * + * under the terms of the GNU Lesser General Public License as * + * published by the Free Software Foundation, either version 2.1 of the * + * License, or (at your option) any later version. * + * * + * FreeCAD is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with FreeCAD. If not, see * + * . * + * * + **************************************************************************/ + +#include "gtest/gtest.h" + +#include +#ifndef _PreComp_ +#endif + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +// clang-format off + +class TestMaterial : public ::testing::Test { + protected: + static void SetUpTestSuite() { + if (App::Application::GetARGC() == 0) { + constexpr int argc = 1; + std::array argv {"FreeCAD"}; + App::Application::Config()["ExeName"] = "FreeCAD"; + App::Application::init(argc, argv.data()); + } + } + + void SetUp() override { + _modelManager = new Materials::ModelManager(); + _materialManager = new Materials::MaterialManager(); + } + + // void TearDown() override {} + Materials::ModelManager* _modelManager; + Materials::MaterialManager* _materialManager; +}; + +TEST_F(TestMaterial, TestInstallation) +{ + EXPECT_NE(_modelManager, nullptr); + + // We should have loaded at least the system library + auto libraries = _materialManager->getMaterialLibraries(); + ASSERT_GT(libraries->size(), 0); + + // We should have at least one material + auto materials = _materialManager->getMaterials(); + ASSERT_GT(materials->size(), 0); +} + +TEST_F(TestMaterial, TestMaterialsWithModel) +{ + auto materials = _materialManager->materialsWithModel( + QString::fromStdString("f6f9e48c-b116-4e82-ad7f-3659a9219c50")); // IsotropicLinearElastic + EXPECT_GT(materials->size(), 0); + + auto materialsComplete = _materialManager->materialsWithModelComplete( + QString::fromStdString("f6f9e48c-b116-4e82-ad7f-3659a9219c50")); // IsotropicLinearElastic + EXPECT_LE(materialsComplete->size(), materials->size()); + + auto materialsLinearElastic = _materialManager->materialsWithModel( + QString::fromStdString("7b561d1d-fb9b-44f6-9da9-56a4f74d7536")); // LinearElastic + + // All LinearElastic models should be in IsotropicLinearElastic since it is inherited + EXPECT_LE(materialsLinearElastic->size(), materials->size()); + for (auto itp = materialsLinearElastic->begin(); itp != materialsLinearElastic->end(); itp++) { + auto mat = itp->first; + EXPECT_NO_THROW(materials->at(mat)); + } +} + +TEST_F(TestMaterial, TestMaterialByPath) +{ + auto steel = _materialManager->getMaterialByPath( + QString::fromStdString("StandardMaterial/Metal/Steel/CalculiX-Steel.FCMat"), + QString::fromStdString("System")); + EXPECT_NE(&steel, nullptr); + EXPECT_EQ(steel->getName(), QString::fromStdString("CalculiX-Steel")); + EXPECT_EQ(steel->getUUID(), QString::fromStdString("92589471-a6cb-4bbc-b748-d425a17dea7d")); + + // The same but with a leading '/' + auto steel2 = _materialManager->getMaterialByPath( + QString::fromStdString("/StandardMaterial/Metal/Steel/CalculiX-Steel.FCMat"), + QString::fromStdString("System")); + EXPECT_NE(&steel2, nullptr); + EXPECT_EQ(steel2->getName(), QString::fromStdString("CalculiX-Steel")); + EXPECT_EQ(steel2->getUUID(), QString::fromStdString("92589471-a6cb-4bbc-b748-d425a17dea7d")); + + // Same with the library name as a prefix + auto steel3 = _materialManager->getMaterialByPath( + QString::fromStdString("/System/StandardMaterial/Metal/Steel/CalculiX-Steel.FCMat"), + QString::fromStdString("System")); + EXPECT_NE(&steel3, nullptr); + EXPECT_EQ(steel3->getName(), QString::fromStdString("CalculiX-Steel")); + EXPECT_EQ(steel3->getUUID(), QString::fromStdString("92589471-a6cb-4bbc-b748-d425a17dea7d")); +} + +TEST_F(TestMaterial, TestAddPhysicalModel) +{ + // Start with an empty material + Materials::Material material; + auto models = material.getPhysicalModels(); + EXPECT_NE(&models, nullptr); + EXPECT_EQ(models->size(), 0); + + // Add a model + material.addPhysical(Materials::ModelUUIDs::ModelUUID_Electromagnetic_Default); + models = material.getPhysicalModels(); + EXPECT_EQ(models->size(), 1); + + // Add a second model + material.addPhysical(Materials::ModelUUIDs::ModelUUID_Mechanical_LinearElastic); + models = material.getPhysicalModels(); + EXPECT_EQ(models->size(), 2); + + // Add an inherited model + material.addPhysical(Materials::ModelUUIDs::ModelUUID_Mechanical_IsotropicLinearElastic); + models = material.getPhysicalModels(); + EXPECT_EQ(models->size(), 2); + + // Add a super model + material.clearModels(); + EXPECT_EQ(models->size(), 0); + + material.addPhysical(Materials::ModelUUIDs::ModelUUID_Mechanical_IsotropicLinearElastic); + models = material.getPhysicalModels(); + EXPECT_EQ(models->size(), 1); + material.addPhysical(Materials::ModelUUIDs::ModelUUID_Mechanical_LinearElastic); + models = material.getPhysicalModels(); + EXPECT_EQ(models->size(), 1); + + // Remove the inherited model + material.removePhysical(Materials::ModelUUIDs::ModelUUID_Mechanical_IsotropicLinearElastic); + models = material.getPhysicalModels(); + EXPECT_EQ(models->size(), 1); + + // Remove the super model + material.removePhysical(Materials::ModelUUIDs::ModelUUID_Mechanical_LinearElastic); + models = material.getPhysicalModels(); + EXPECT_EQ(models->size(), 0); +} + +TEST_F(TestMaterial, TestAddAppearanceModel) +{ + // Start with an empty material + Materials::Material material; + auto models = material.getAppearanceModels(); + EXPECT_NE(models, nullptr); + EXPECT_EQ(models->size(), 0); + + // Add a model + material.addAppearance(Materials::ModelUUIDs::ModelUUID_Rendering_Vector); + models = material.getAppearanceModels(); + EXPECT_EQ(models->size(), 1); + + // Add a second model + material.addAppearance(Materials::ModelUUIDs::ModelUUID_Rendering_Advanced); + models = material.getAppearanceModels(); + EXPECT_EQ(models->size(), 2); + + // Add an inherited model + material.addAppearance(Materials::ModelUUIDs::ModelUUID_Rendering_Basic); + models = material.getAppearanceModels(); + EXPECT_EQ(models->size(), 2); + + // Add a super model + material.clearModels(); + EXPECT_EQ(models->size(), 0); + + material.addAppearance(Materials::ModelUUIDs::ModelUUID_Rendering_Basic); + models = material.getAppearanceModels(); + EXPECT_EQ(models->size(), 1); + material.addAppearance(Materials::ModelUUIDs::ModelUUID_Rendering_Advanced); + models = material.getAppearanceModels(); + EXPECT_EQ(models->size(), 1); + + // Remove the inherited model + material.removeAppearance(Materials::ModelUUIDs::ModelUUID_Rendering_Basic); + models = material.getAppearanceModels(); + EXPECT_EQ(models->size(), 1); + + // Remove the super model + material.removeAppearance(Materials::ModelUUIDs::ModelUUID_Rendering_Advanced); + models = material.getAppearanceModels(); + EXPECT_EQ(models->size(), 0); +} + +QString parseQuantity(const char *string) +{ + QString value = QString::fromStdString(string); + return Base::Quantity::parse(value).getUserString(); +} + +TEST_F(TestMaterial, TestCalculiXSteel) +{ + auto steel = _materialManager->getMaterial(QString::fromStdString("92589471-a6cb-4bbc-b748-d425a17dea7d")); + EXPECT_EQ(steel->getName(), QString::fromStdString("CalculiX-Steel")); + EXPECT_EQ(steel->getUUID(), QString::fromStdString("92589471-a6cb-4bbc-b748-d425a17dea7d")); + + EXPECT_TRUE(steel->hasPhysicalModel(Materials::ModelUUIDs::ModelUUID_Mechanical_Density)); // Density + EXPECT_TRUE(steel->hasPhysicalModel(Materials::ModelUUIDs::ModelUUID_Mechanical_IsotropicLinearElastic)); // IsotropicLinearElastic + EXPECT_TRUE(steel->hasPhysicalModel(Materials::ModelUUIDs::ModelUUID_Thermal_Default)); // Thermal + EXPECT_FALSE(steel->hasPhysicalModel(Materials::ModelUUIDs::ModelUUID_Mechanical_LinearElastic)); // Legacy linear elastic - Not in the model + EXPECT_TRUE(steel->hasAppearanceModel(Materials::ModelUUIDs::ModelUUID_Rendering_Basic)); // BasicRendering - inherited from Steel.FCMat + + EXPECT_TRUE(steel->isPhysicalModelComplete(Materials::ModelUUIDs::ModelUUID_Mechanical_Density)); // Density + EXPECT_FALSE(steel->isPhysicalModelComplete(Materials::ModelUUIDs::ModelUUID_Mechanical_IsotropicLinearElastic)); // IsotropicLinearElastic - incomplete + EXPECT_TRUE(steel->isPhysicalModelComplete(Materials::ModelUUIDs::ModelUUID_Thermal_Default)); // Thermal + EXPECT_FALSE(steel->isPhysicalModelComplete(Materials::ModelUUIDs::ModelUUID_Mechanical_LinearElastic)); // Legacy linear elastic - Not in the model + EXPECT_TRUE(steel->isAppearanceModelComplete(Materials::ModelUUIDs::ModelUUID_Rendering_Basic)); // BasicRendering - inherited from Steel.FCMat + + EXPECT_TRUE(steel->hasPhysicalProperty(QString::fromStdString("Density"))); + EXPECT_TRUE(steel->hasPhysicalProperty(QString::fromStdString("BulkModulus"))); + EXPECT_TRUE(steel->hasPhysicalProperty(QString::fromStdString("PoissonRatio"))); + EXPECT_TRUE(steel->hasPhysicalProperty(QString::fromStdString("YoungsModulus"))); + EXPECT_TRUE(steel->hasPhysicalProperty(QString::fromStdString("ShearModulus"))); + EXPECT_TRUE(steel->hasPhysicalProperty(QString::fromStdString("SpecificHeat"))); + EXPECT_TRUE(steel->hasPhysicalProperty(QString::fromStdString("ThermalConductivity"))); + EXPECT_TRUE(steel->hasPhysicalProperty(QString::fromStdString("ThermalExpansionCoefficient"))); + EXPECT_TRUE(steel->hasAppearanceProperty(QString::fromStdString("AmbientColor"))); + EXPECT_TRUE(steel->hasAppearanceProperty(QString::fromStdString("DiffuseColor"))); + EXPECT_TRUE(steel->hasAppearanceProperty(QString::fromStdString("EmissiveColor"))); + EXPECT_TRUE(steel->hasAppearanceProperty(QString::fromStdString("Shininess"))); + EXPECT_TRUE(steel->hasAppearanceProperty(QString::fromStdString("SpecularColor"))); + EXPECT_TRUE(steel->hasAppearanceProperty(QString::fromStdString("Transparency"))); + + auto& properties = steel->getPhysicalProperties(); + EXPECT_NO_THROW(properties.at(QString::fromStdString("Density"))); + EXPECT_NO_THROW(properties.at(QString::fromStdString("BulkModulus"))); // This is different from the Python behaviour + EXPECT_NO_THROW(properties.at(QString::fromStdString("PoissonRatio"))); + EXPECT_NO_THROW(properties.at(QString::fromStdString("YoungsModulus"))); + EXPECT_NO_THROW(properties.at(QString::fromStdString("ShearModulus"))); + EXPECT_NO_THROW(properties.at(QString::fromStdString("SpecificHeat"))); + EXPECT_NO_THROW(properties.at(QString::fromStdString("ThermalConductivity"))); + EXPECT_NO_THROW(properties.at(QString::fromStdString("ThermalExpansionCoefficient"))); + EXPECT_THROW(properties.at(QString::fromStdString("AmbientColor")), std::out_of_range); + EXPECT_THROW(properties.at(QString::fromStdString("DiffuseColor")), std::out_of_range); + EXPECT_THROW(properties.at(QString::fromStdString("EmissiveColor")), std::out_of_range); + EXPECT_THROW(properties.at(QString::fromStdString("Shininess")), std::out_of_range); + EXPECT_THROW(properties.at(QString::fromStdString("SpecularColor")), std::out_of_range); + EXPECT_THROW(properties.at(QString::fromStdString("Transparency")), std::out_of_range); + + auto& properties1 = steel->getAppearanceProperties(); + EXPECT_THROW(properties1.at(QString::fromStdString("Density")), std::out_of_range); + EXPECT_THROW(properties1.at(QString::fromStdString("BulkModulus")), std::out_of_range); + EXPECT_THROW(properties1.at(QString::fromStdString("PoissonRatio")), std::out_of_range); + EXPECT_THROW(properties1.at(QString::fromStdString("YoungsModulus")), std::out_of_range); + EXPECT_THROW(properties1.at(QString::fromStdString("ShearModulus")), std::out_of_range); + EXPECT_THROW(properties1.at(QString::fromStdString("SpecificHeat")), std::out_of_range); + EXPECT_THROW(properties1.at(QString::fromStdString("ThermalConductivity")), std::out_of_range); + EXPECT_THROW(properties1.at(QString::fromStdString("ThermalExpansionCoefficient")), std::out_of_range); + EXPECT_NO_THROW(properties1.at(QString::fromStdString("AmbientColor"))); + EXPECT_NO_THROW(properties1.at(QString::fromStdString("DiffuseColor"))); + EXPECT_NO_THROW(properties1.at(QString::fromStdString("EmissiveColor"))); + EXPECT_NO_THROW(properties1.at(QString::fromStdString("Shininess"))); + EXPECT_NO_THROW(properties1.at(QString::fromStdString("SpecularColor"))); + EXPECT_NO_THROW(properties1.at(QString::fromStdString("Transparency"))); + + EXPECT_FALSE(properties[QString::fromStdString("Density")]->isNull()); + EXPECT_TRUE(properties[QString::fromStdString("BulkModulus")]->isNull()); + EXPECT_FALSE(properties[QString::fromStdString("PoissonRatio")]->isNull()); + EXPECT_FALSE(properties[QString::fromStdString("YoungsModulus")]->isNull()); + EXPECT_TRUE(properties[QString::fromStdString("ShearModulus")]->isNull()); + EXPECT_FALSE(properties[QString::fromStdString("SpecificHeat")]->isNull()); + EXPECT_FALSE(properties[QString::fromStdString("ThermalConductivity")]->isNull()); + EXPECT_FALSE(properties[QString::fromStdString("ThermalExpansionCoefficient")]->isNull()); + EXPECT_FALSE(properties1[QString::fromStdString("AmbientColor")]->isNull()); + EXPECT_FALSE(properties1[QString::fromStdString("DiffuseColor")]->isNull()); + EXPECT_FALSE(properties1[QString::fromStdString("EmissiveColor")]->isNull()); + EXPECT_FALSE(properties1[QString::fromStdString("Shininess")]->isNull()); + EXPECT_FALSE(properties1[QString::fromStdString("SpecularColor")]->isNull()); + EXPECT_FALSE(properties1[QString::fromStdString("Transparency")]->isNull()); + + EXPECT_EQ(properties[QString::fromStdString("Density")]->getString(), parseQuantity("7900.00 kg/m^3")); + EXPECT_EQ(properties[QString::fromStdString("PoissonRatio")]->getString(), QString::fromStdString("0.3")); + EXPECT_EQ(properties[QString::fromStdString("YoungsModulus")]->getString(), parseQuantity("210.00 GPa")); + EXPECT_EQ(properties[QString::fromStdString("SpecificHeat")]->getString(), parseQuantity("590.00 J/kg/K")); + EXPECT_EQ(properties[QString::fromStdString("ThermalConductivity")]->getString(), parseQuantity("43.00 W/m/K")); + EXPECT_EQ(properties[QString::fromStdString("ThermalExpansionCoefficient")]->getString(), parseQuantity("12.00 µm/m/K")); + EXPECT_EQ(properties1[QString::fromStdString("AmbientColor")]->getString(), QString::fromStdString("(0.0020, 0.0020, 0.0020, 1.0)")); + EXPECT_EQ(properties1[QString::fromStdString("DiffuseColor")]->getString(), QString::fromStdString("(0.0000, 0.0000, 0.0000, 1.0)")); + EXPECT_EQ(properties1[QString::fromStdString("EmissiveColor")]->getString(), QString::fromStdString("(0.0000, 0.0000, 0.0000, 1.0)")); + EXPECT_EQ(properties1[QString::fromStdString("Shininess")]->getString(), QString::fromStdString("0.06")); + EXPECT_EQ(properties1[QString::fromStdString("SpecularColor")]->getString(), QString::fromStdString("(0.9800, 0.9800, 0.9800, 1.0)")); + EXPECT_EQ(properties1[QString::fromStdString("Transparency")]->getString(), QString::fromStdString("0")); + + EXPECT_TRUE(properties[QString::fromStdString("BulkModulus")]->getString().isEmpty()); + EXPECT_TRUE(properties[QString::fromStdString("ShearModulus")]->getString().isEmpty()); + + // These are the preferred method of access + // + EXPECT_FLOAT_EQ(steel->getPhysicalQuantity(QString::fromStdString("Density")).getValue(), 7.9e-06); + EXPECT_FLOAT_EQ(steel->getPhysicalValue(QString::fromStdString("PoissonRatio")).toDouble(), 0.3); + EXPECT_FLOAT_EQ(steel->getPhysicalQuantity(QString::fromStdString("YoungsModulus")).getValue(), 210000000.0); + EXPECT_FLOAT_EQ(steel->getPhysicalQuantity(QString::fromStdString("SpecificHeat")).getValue(), 590000000.0); + EXPECT_FLOAT_EQ(steel->getPhysicalQuantity(QString::fromStdString("ThermalConductivity")).getValue(), 43000.0); + EXPECT_FLOAT_EQ(steel->getPhysicalQuantity(QString::fromStdString("ThermalExpansionCoefficient")).getValue(), 1.2e-05); + EXPECT_EQ(steel->getAppearanceValue(QString::fromStdString("AmbientColor")), QString::fromStdString("(0.0020, 0.0020, 0.0020, 1.0)")); + EXPECT_EQ(steel->getAppearanceValue(QString::fromStdString("DiffuseColor")), QString::fromStdString("(0.0000, 0.0000, 0.0000, 1.0)")); + EXPECT_EQ(steel->getAppearanceValue(QString::fromStdString("EmissiveColor")), QString::fromStdString("(0.0000, 0.0000, 0.0000, 1.0)")); + EXPECT_FLOAT_EQ(steel->getAppearanceValue(QString::fromStdString("Shininess")).toDouble(), 0.06); + EXPECT_EQ(steel->getAppearanceValue(QString::fromStdString("SpecularColor")), QString::fromStdString("(0.9800, 0.9800, 0.9800, 1.0)")); + EXPECT_FLOAT_EQ(steel->getAppearanceValue(QString::fromStdString("Transparency")).toDouble(), 0.0); + + EXPECT_EQ(steel->getPhysicalQuantity(QString::fromStdString("Density")).getUserString(), parseQuantity("7900.00 kg/m^3")); + EXPECT_EQ(steel->getPhysicalQuantity(QString::fromStdString("YoungsModulus")).getUserString(), parseQuantity("210.00 GPa")); + EXPECT_EQ(steel->getPhysicalQuantity(QString::fromStdString("SpecificHeat")).getUserString(), parseQuantity("590.00 J/kg/K")); + EXPECT_EQ(steel->getPhysicalQuantity(QString::fromStdString("ThermalConductivity")).getUserString(), parseQuantity("43.00 W/m/K")); + EXPECT_EQ(steel->getPhysicalQuantity(QString::fromStdString("ThermalExpansionCoefficient")).getUserString(), parseQuantity("12.00 µm/m/K")); + +} + +// clang-format on diff --git a/tests/src/Mod/Material/App/TestModel.cpp b/tests/src/Mod/Material/App/TestModel.cpp new file mode 100644 index 0000000000..c3f6e1b127 --- /dev/null +++ b/tests/src/Mod/Material/App/TestModel.cpp @@ -0,0 +1,140 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later +/*************************************************************************** + * Copyright (c) 2023 David Carter * + * * + * This file is part of FreeCAD. * + * * + * FreeCAD is free software: you can redistribute it and/or modify it * + * under the terms of the GNU Lesser General Public License as * + * published by the Free Software Foundation, either version 2.1 of the * + * License, or (at your option) any later version. * + * * + * FreeCAD is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with FreeCAD. If not, see * + * . * + * * + **************************************************************************/ + +#include "gtest/gtest.h" + +#include +#ifndef _PreComp_ +#endif + +#include + +#include + +#include +#include +#include + +// clang-format off + +class TestModel : public ::testing::Test { + protected: + static void SetUpTestSuite() { + if (App::Application::GetARGC() == 0) { + constexpr int argc = 1; + std::array argv {"FreeCAD"}; + App::Application::Config()["ExeName"] = "FreeCAD"; + App::Application::init(argc, argv.data()); + } + } + + void SetUp() override { + _modelManager = new Materials::ModelManager(); + } + + // void TearDown() override {} + Materials::ModelManager* _modelManager; +}; + +TEST_F(TestModel, TestApplication) +{ + ASSERT_NO_THROW(App::GetApplication()); +} + +TEST_F(TestModel, TestResources) +{ + try { + auto param = App::GetApplication().GetParameterGroupByPath( + "User parameter:BaseApp/Preferences/Mod/Material/Resources"); + EXPECT_NE(param, nullptr); + } + catch (const std::exception &e) + { + FAIL() << "Exception: " << e.what() << "\n"; + } +} + +TEST_F(TestModel, TestInstallation) +{ + EXPECT_NE(_modelManager, nullptr); + + // We should have loaded at least the system library + auto libraries = _modelManager->getModelLibraries(); + ASSERT_GT(libraries->size(), 0); + + // We should have at least one model + auto models = _modelManager->getModels(); + ASSERT_GT(models->size(), 0); +} + +TEST_F(TestModel, TestModelLoad) +{ + EXPECT_NE(_modelManager, nullptr); + + auto density = _modelManager->getModel(QString::fromStdString("454661e5-265b-4320-8e6f-fcf6223ac3af")); + EXPECT_EQ(density->getName(), QString::fromStdString("Density")); + EXPECT_EQ(density->getUUID(), QString::fromStdString("454661e5-265b-4320-8e6f-fcf6223ac3af")); + + auto& prop = (*density)[QString::fromStdString("Density")]; + EXPECT_EQ(prop.getName(), QString::fromStdString("Density")); +} + +TEST_F(TestModel, TestModelByPath) +{ + auto linearElastic = _modelManager->getModelByPath( + QString::fromStdString("Mechanical/LinearElastic.yml"), + QString::fromStdString("System")); + EXPECT_NE(&linearElastic, nullptr); + EXPECT_EQ(linearElastic->getName(), QString::fromStdString("Linear Elastic")); + EXPECT_EQ(linearElastic->getUUID(), QString::fromStdString("7b561d1d-fb9b-44f6-9da9-56a4f74d7536")); + + // The same but with a leading '/' + auto linearElastic2 = _modelManager->getModelByPath( + QString::fromStdString("/Mechanical/LinearElastic.yml"), + QString::fromStdString("System")); + EXPECT_NE(&linearElastic2, nullptr); + EXPECT_EQ(linearElastic2->getName(), QString::fromStdString("Linear Elastic")); + EXPECT_EQ(linearElastic2->getUUID(), QString::fromStdString("7b561d1d-fb9b-44f6-9da9-56a4f74d7536")); + + // Same with the library name as a prefix + auto linearElastic3 = _modelManager->getModelByPath( + QString::fromStdString("/System/Mechanical/LinearElastic.yml"), + QString::fromStdString("System")); + EXPECT_NE(&linearElastic3, nullptr); + EXPECT_EQ(linearElastic3->getName(), QString::fromStdString("Linear Elastic")); + EXPECT_EQ(linearElastic3->getUUID(), QString::fromStdString("7b561d1d-fb9b-44f6-9da9-56a4f74d7536")); + + // Test with the file system path + ASSERT_NO_THROW(linearElastic->getLibrary()); + ASSERT_NO_THROW(linearElastic->getLibrary()->getName()); + ASSERT_NO_THROW(linearElastic->getLibrary()->getDirectoryPath()); + EXPECT_EQ(linearElastic->getLibrary()->getName(), QString::fromStdString("System")); + QString path = linearElastic->getLibrary()->getDirectoryPath() + QString::fromStdString("/Mechanical/LinearElastic.yml"); + + ASSERT_NO_THROW(_modelManager->getModelByPath(path)); + auto linearElastic4 = _modelManager->getModelByPath(path); + EXPECT_NE(&linearElastic4, nullptr); + EXPECT_EQ(linearElastic4->getName(), QString::fromStdString("Linear Elastic")); + EXPECT_EQ(linearElastic4->getUUID(), QString::fromStdString("7b561d1d-fb9b-44f6-9da9-56a4f74d7536")); +} + +// clang-format on diff --git a/tests/src/Mod/Material/App/TestModelProperties.cpp b/tests/src/Mod/Material/App/TestModelProperties.cpp new file mode 100644 index 0000000000..06d21c689e --- /dev/null +++ b/tests/src/Mod/Material/App/TestModelProperties.cpp @@ -0,0 +1,144 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later +/*************************************************************************** + * Copyright (c) 2023 David Carter * + * * + * This file is part of FreeCAD. * + * * + * FreeCAD is free software: you can redistribute it and/or modify it * + * under the terms of the GNU Lesser General Public License as * + * published by the Free Software Foundation, either version 2.1 of the * + * License, or (at your option) any later version. * + * * + * FreeCAD is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with FreeCAD. If not, see * + * . * + * * + **************************************************************************/ + +#include "gtest/gtest.h" + +#include +#ifndef _PreComp_ +#endif + +#include +#include + +#include +#include + +#include +#include +#include +#include + +// clang-format off + +class TestModelProperties : public ::testing::Test { + protected: + static void SetUpTestSuite() { + // if (App::Application::GetARGC() == 0) { + // constexpr int argc = 1; + // std::array argv {"FreeCAD"}; + // App::Application::Config()["ExeName"] = "FreeCAD"; + // App::Application::init(argc, argv.data()); + // } + } + +// void SetUp() override { +// _modelManager = new Materials::ModelManager(); +// _materialManager = new Materials::MaterialManager(); +// } + + // void TearDown() override {} +// Materials::ModelManager* _modelManager; +// Materials::MaterialManager* _materialManager; +}; + +TEST_F(TestModelProperties, TestEmpty) +{ + auto prop = Materials::ModelProperty(); + EXPECT_TRUE(prop.getName().isNull()); + EXPECT_TRUE(prop.getPropertyType().isNull()); + EXPECT_TRUE(prop.getUnits().isNull()); + EXPECT_TRUE(prop.getURL().isNull()); + EXPECT_TRUE(prop.getDescription().isNull()); + EXPECT_TRUE(prop.getInheritance().isNull()); + EXPECT_FALSE(prop.isInherited()); + EXPECT_EQ(prop.columns(), 0); +} + +TEST_F(TestModelProperties, TestBasic) +{ + auto prop = Materials::ModelProperty(QString::fromStdString("1"), + QString::fromStdString("2"), + QString::fromStdString("3"), + QString::fromStdString("4"), + QString::fromStdString("5")); + EXPECT_EQ(prop.getName(), QString::fromStdString("1")); + EXPECT_EQ(prop.getPropertyType(), QString::fromStdString("2")); + EXPECT_EQ(prop.getUnits(), QString::fromStdString("3")); + EXPECT_EQ(prop.getURL(), QString::fromStdString("4")); + EXPECT_EQ(prop.getDescription(), QString::fromStdString("5")); + EXPECT_TRUE(prop.getInheritance().isNull()); + EXPECT_FALSE(prop.isInherited()); + EXPECT_EQ(prop.columns(), 0); + + prop.setInheritance(QString::fromStdString("12345")); + EXPECT_EQ(prop.getInheritance(), QString::fromStdString("12345")); + EXPECT_TRUE(prop.isInherited()); +} + +TEST_F(TestModelProperties, TestAddColumns) +{ + auto prop = Materials::ModelProperty(QString::fromStdString("1"), + QString::fromStdString("2"), + QString::fromStdString("3"), + QString::fromStdString("4"), + QString::fromStdString("5")); + auto prop1 = Materials::ModelProperty(QString::fromStdString("10"), + QString::fromStdString("9"), + QString::fromStdString("8"), + QString::fromStdString("7"), + QString::fromStdString("6")); + auto prop2 = Materials::ModelProperty(QString::fromStdString("a"), + QString::fromStdString("b"), + QString::fromStdString("c"), + QString::fromStdString("d"), + QString::fromStdString("e")); + + EXPECT_EQ(prop.columns(), 0); + prop.addColumn(prop1); + EXPECT_EQ(prop.columns(), 1); + prop.addColumn(prop2); + EXPECT_EQ(prop.columns(), 2); + + auto columns = prop.getColumns(); + auto entry1 = columns.at(0); + EXPECT_EQ(entry1.getName(), QString::fromStdString("10")); + EXPECT_EQ(entry1.getPropertyType(), QString::fromStdString("9")); + EXPECT_EQ(entry1.getUnits(), QString::fromStdString("8")); + EXPECT_EQ(entry1.getURL(), QString::fromStdString("7")); + EXPECT_EQ(entry1.getDescription(), QString::fromStdString("6")); + EXPECT_TRUE(entry1.getInheritance().isNull()); + EXPECT_FALSE(entry1.isInherited()); + EXPECT_EQ(entry1.columns(), 0); + + auto entry2 = columns.at(1); + EXPECT_EQ(entry2.getName(), QString::fromStdString("a")); + EXPECT_EQ(entry2.getPropertyType(), QString::fromStdString("b")); + EXPECT_EQ(entry2.getUnits(), QString::fromStdString("c")); + EXPECT_EQ(entry2.getURL(), QString::fromStdString("d")); + EXPECT_EQ(entry2.getDescription(), QString::fromStdString("e")); + EXPECT_TRUE(entry2.getInheritance().isNull()); + EXPECT_FALSE(entry2.isInherited()); + EXPECT_EQ(entry2.columns(), 0); + +} + +// clang-format on From 17aea3416fea4683a16886b637799d4798c84775 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 23 Oct 2023 19:21:52 +0000 Subject: [PATCH 6/6] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/Mod/Fem/Gui/AppFemGui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Mod/Fem/Gui/AppFemGui.cpp b/src/Mod/Fem/Gui/AppFemGui.cpp index a6e8b665cd..c4f36d46a2 100644 --- a/src/Mod/Fem/Gui/AppFemGui.cpp +++ b/src/Mod/Fem/Gui/AppFemGui.cpp @@ -187,4 +187,4 @@ PyMOD_INIT_FUNC(FemGui) // clang-format on PyMOD_Return(mod); -} \ No newline at end of file +}