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