Material: Material handling enhancements
Rework of the material handling system. This first part concntrates on a rework of the material cards. Rather than use a fixed list of possible properties, properties can be defined separately in their own files and mixed to provide a complete list of possible properties. Properties can be inherited. The cards then provide values for the properties. These can also be inherited allowing for small changes in cards as required. The new property definitions are more extensive than previously. 2 and 3 dimensional arrays of properties can be defined. Values are obtained by calling an API instead of reading from a dictionary. For compatibility, a Python dictionary of values can be obtained similar to how it was done previously, but this is considered a deprecated API and won't support the newer advanced features. The editor is completely reworked. It will be able to edit older format material cards, but can only save them in the new format. For testing during the development phase, a system preference can specifiy wether the old or new material editors are to be used. This option will be removed before release.
This commit is contained in:
@@ -47,6 +47,13 @@ runs:
|
||||
testCommand: ${{ inputs.builddir }}/tests/Tests_run --gtest_output=json:${{ inputs.reportdir }}core_gtest_results.json
|
||||
testLogFile: ${{ inputs.reportdir }}core_gtest_test_log.txt
|
||||
testName: Core
|
||||
- name: C++ Material tests
|
||||
id: material
|
||||
uses: ./.github/workflows/actions/runCPPTests/runSingleTest
|
||||
with:
|
||||
testCommand: ${{ inputs.builddir }}/tests/Material_tests_run --gtest_output=json:${{ inputs.reportdir }}material_gtest_results.json
|
||||
testLogFile: ${{ inputs.reportdir }}material_gtest_test_log.txt
|
||||
testName: Material
|
||||
- name: C++ Mesh tests
|
||||
id: mesh
|
||||
uses: ./.github/workflows/actions/runCPPTests/runSingleTest
|
||||
|
||||
@@ -51,6 +51,7 @@ CheckInterModuleDependencies()
|
||||
FreeCADLibpackChecks()
|
||||
SetupDoxygen()
|
||||
SetupLibFmt()
|
||||
SetupYamlCpp()
|
||||
if(NOT FREECAD_LIBPACK_USE OR FREECAD_LIBPACK_CHECKFILE_CLBUNDLER)
|
||||
SetupPython()
|
||||
SetupPCL()
|
||||
|
||||
11
cMake/FreeCAD_Helpers/SetupLibYaml.cmake
Normal file
11
cMake/FreeCAD_Helpers/SetupLibYaml.cmake
Normal file
@@ -0,0 +1,11 @@
|
||||
macro(SetupYamlCpp)
|
||||
# -------------------------------- YamlCpp --------------------------------
|
||||
|
||||
find_package(yaml-cpp REQUIRED)
|
||||
if(NOT yaml-cpp_FOUND)
|
||||
message(FATAL_ERROR "==================\n"
|
||||
"YamlCpp not found.\n"
|
||||
"==================\n")
|
||||
endif(NOT yaml-cpp_FOUND)
|
||||
|
||||
endmacro(SetupYamlCpp)
|
||||
@@ -34,7 +34,6 @@
|
||||
#include "DlgSettingsFemGeneralImp.h"
|
||||
#include "DlgSettingsFemGmshImp.h"
|
||||
#include "DlgSettingsFemInOutVtkImp.h"
|
||||
#include "DlgSettingsFemMaterialImp.h"
|
||||
#include "DlgSettingsFemMystranImp.h"
|
||||
#include "DlgSettingsFemZ88Imp.h"
|
||||
#include "PropertyFemMeshItem.h"
|
||||
@@ -108,81 +107,85 @@ PyMOD_INIT_FUNC(FemGui)
|
||||
|
||||
// clang-format off
|
||||
// addition objects
|
||||
FemGui::Workbench ::init();
|
||||
FemGui::Workbench ::init();
|
||||
|
||||
FemGui::ViewProviderFemAnalysis ::init();
|
||||
FemGui::ViewProviderFemAnalysisPython ::init();
|
||||
FemGui::ViewProviderFemAnalysis ::init();
|
||||
FemGui::ViewProviderFemAnalysisPython ::init();
|
||||
|
||||
FemGui::ViewProviderFemConstraint ::init();
|
||||
FemGui::ViewProviderFemConstraintPython ::init();
|
||||
FemGui::ViewProviderFemConstraint ::init();
|
||||
FemGui::ViewProviderFemConstraintPython ::init();
|
||||
|
||||
FemGui::ViewProviderFemConstraintOnBoundary ::init();
|
||||
FemGui::ViewProviderFemConstraintBearing ::init();
|
||||
FemGui::ViewProviderFemConstraintContact ::init();
|
||||
FemGui::ViewProviderFemConstraintDisplacement ::init();
|
||||
FemGui::ViewProviderFemConstraintFixed ::init();
|
||||
FemGui::ViewProviderFemConstraintFluidBoundary ::init();
|
||||
FemGui::ViewProviderFemConstraintForce ::init();
|
||||
FemGui::ViewProviderFemConstraintGear ::init();
|
||||
FemGui::ViewProviderFemConstraintHeatflux ::init();
|
||||
FemGui::ViewProviderFemConstraintInitialTemperature ::init();
|
||||
FemGui::ViewProviderFemConstraintPlaneRotation ::init();
|
||||
FemGui::ViewProviderFemConstraintPressure ::init();
|
||||
FemGui::ViewProviderFemConstraintPulley ::init();
|
||||
FemGui::ViewProviderFemConstraintTemperature ::init();
|
||||
FemGui::ViewProviderFemConstraintTransform ::init();
|
||||
FemGui::ViewProviderFemConstraintSpring ::init();
|
||||
FemGui::ViewProviderFemConstraintOnBoundary ::init();
|
||||
FemGui::ViewProviderFemConstraintBearing ::init();
|
||||
FemGui::ViewProviderFemConstraintContact ::init();
|
||||
FemGui::ViewProviderFemConstraintDisplacement ::init();
|
||||
FemGui::ViewProviderFemConstraintFixed ::init();
|
||||
FemGui::ViewProviderFemConstraintFluidBoundary ::init();
|
||||
FemGui::ViewProviderFemConstraintForce ::init();
|
||||
FemGui::ViewProviderFemConstraintGear ::init();
|
||||
FemGui::ViewProviderFemConstraintHeatflux ::init();
|
||||
FemGui::ViewProviderFemConstraintInitialTemperature ::init();
|
||||
FemGui::ViewProviderFemConstraintPlaneRotation ::init();
|
||||
FemGui::ViewProviderFemConstraintPressure ::init();
|
||||
FemGui::ViewProviderFemConstraintPulley ::init();
|
||||
FemGui::ViewProviderFemConstraintTemperature ::init();
|
||||
FemGui::ViewProviderFemConstraintTransform ::init();
|
||||
FemGui::ViewProviderFemConstraintSpring ::init();
|
||||
|
||||
FemGui::ViewProviderFemMesh ::init();
|
||||
FemGui::ViewProviderFemMeshPython ::init();
|
||||
FemGui::ViewProviderFemMeshShape ::init();
|
||||
FemGui::ViewProviderFemMeshShapeNetgen ::init();
|
||||
FemGui::PropertyFemMeshItem ::init();
|
||||
FemGui::ViewProviderFemMesh ::init();
|
||||
FemGui::ViewProviderFemMeshPython ::init();
|
||||
FemGui::ViewProviderFemMeshShape ::init();
|
||||
FemGui::ViewProviderFemMeshShapeNetgen ::init();
|
||||
FemGui::PropertyFemMeshItem ::init();
|
||||
|
||||
FemGui::ViewProviderSetElements ::init();
|
||||
FemGui::ViewProviderSetFaces ::init();
|
||||
FemGui::ViewProviderSetGeometry ::init();
|
||||
FemGui::ViewProviderSetNodes ::init();
|
||||
FemGui::ViewProviderSetElements ::init();
|
||||
FemGui::ViewProviderSetFaces ::init();
|
||||
FemGui::ViewProviderSetGeometry ::init();
|
||||
FemGui::ViewProviderSetNodes ::init();
|
||||
|
||||
FemGui::ViewProviderSolver ::init();
|
||||
FemGui::ViewProviderSolverPython ::init();
|
||||
FemGui::ViewProviderSolver ::init();
|
||||
FemGui::ViewProviderSolverPython ::init();
|
||||
|
||||
FemGui::ViewProviderResult ::init();
|
||||
FemGui::ViewProviderResultPython ::init();
|
||||
FemGui::ViewProviderResult ::init();
|
||||
FemGui::ViewProviderResultPython ::init();
|
||||
|
||||
|
||||
#ifdef FC_USE_VTK
|
||||
FemGui::ViewProviderFemPostObject ::init();
|
||||
FemGui::ViewProviderFemPostPipeline ::init();
|
||||
FemGui::ViewProviderFemPostClip ::init();
|
||||
FemGui::ViewProviderFemPostContours ::init();
|
||||
FemGui::ViewProviderFemPostCut ::init();
|
||||
FemGui::ViewProviderFemPostDataAlongLine ::init();
|
||||
FemGui::ViewProviderFemPostDataAtPoint ::init();
|
||||
FemGui::ViewProviderFemPostScalarClip ::init();
|
||||
FemGui::ViewProviderFemPostWarpVector ::init();
|
||||
FemGui::ViewProviderFemPostObject ::init();
|
||||
FemGui::ViewProviderFemPostPipeline ::init();
|
||||
FemGui::ViewProviderFemPostClip ::init();
|
||||
FemGui::ViewProviderFemPostContours ::init();
|
||||
FemGui::ViewProviderFemPostCut ::init();
|
||||
FemGui::ViewProviderFemPostDataAlongLine ::init();
|
||||
FemGui::ViewProviderFemPostDataAtPoint ::init();
|
||||
FemGui::ViewProviderFemPostScalarClip ::init();
|
||||
FemGui::ViewProviderFemPostWarpVector ::init();
|
||||
|
||||
FemGui::ViewProviderFemPostFunction ::init();
|
||||
FemGui::ViewProviderFemPostFunctionProvider ::init();
|
||||
FemGui::ViewProviderFemPostBoxFunction ::init();
|
||||
FemGui::ViewProviderFemPostCylinderFunction ::init();
|
||||
FemGui::ViewProviderFemPostPlaneFunction ::init();
|
||||
FemGui::ViewProviderFemPostSphereFunction ::init();
|
||||
FemGui::ViewProviderFemPostFunction ::init();
|
||||
FemGui::ViewProviderFemPostFunctionProvider ::init();
|
||||
FemGui::ViewProviderFemPostBoxFunction ::init();
|
||||
FemGui::ViewProviderFemPostCylinderFunction ::init();
|
||||
FemGui::ViewProviderFemPostPlaneFunction ::init();
|
||||
FemGui::ViewProviderFemPostSphereFunction ::init();
|
||||
#endif
|
||||
|
||||
|
||||
// register preferences pages on FEM, the order here will be the order of the tabs in pref widget
|
||||
new Gui::PrefPageProducer<FemGui::DlgSettingsFemGeneralImp>(QT_TRANSLATE_NOOP("QObject", "FEM"));
|
||||
// register preferences pages on FEM, the order here will be the order of the tabs in pref
|
||||
// widget
|
||||
new Gui::PrefPageProducer<FemGui::DlgSettingsFemGeneralImp>(
|
||||
QT_TRANSLATE_NOOP("QObject", "FEM"));
|
||||
new Gui::PrefPageProducer<FemGui::DlgSettingsFemGmshImp>(QT_TRANSLATE_NOOP("QObject", "FEM"));
|
||||
new Gui::PrefPageProducer<FemGui::DlgSettingsFemCcxImp>(QT_TRANSLATE_NOOP("QObject", "FEM"));
|
||||
new Gui::PrefPageProducer<FemGui::DlgSettingsFemElmerImp>(QT_TRANSLATE_NOOP("QObject", "FEM"));
|
||||
new Gui::PrefPageProducer<FemGui::DlgSettingsFemMystranImp>(QT_TRANSLATE_NOOP("QObject", "FEM"));
|
||||
new Gui::PrefPageProducer<FemGui::DlgSettingsFemMystranImp>(
|
||||
QT_TRANSLATE_NOOP("QObject", "FEM"));
|
||||
new Gui::PrefPageProducer<FemGui::DlgSettingsFemZ88Imp>(QT_TRANSLATE_NOOP("QObject", "FEM"));
|
||||
new Gui::PrefPageProducer<FemGui::DlgSettingsFemMaterialImp>(QT_TRANSLATE_NOOP("QObject", "FEM"));
|
||||
|
||||
// register preferences pages on Import-Export
|
||||
new Gui::PrefPageProducer<FemGui::DlgSettingsFemExportAbaqusImp>(QT_TRANSLATE_NOOP("QObject", "Import-Export"));
|
||||
new Gui::PrefPageProducer<FemGui::DlgSettingsFemInOutVtkImp>(QT_TRANSLATE_NOOP("QObject", "Import-Export"));
|
||||
new Gui::PrefPageProducer<FemGui::DlgSettingsFemExportAbaqusImp>(
|
||||
QT_TRANSLATE_NOOP("QObject", "Import-Export"));
|
||||
new Gui::PrefPageProducer<FemGui::DlgSettingsFemInOutVtkImp>(
|
||||
QT_TRANSLATE_NOOP("QObject", "Import-Export"));
|
||||
|
||||
// add resources and reloads the translators
|
||||
loadFemResource();
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
|
||||
# Many warnings caused by vtk
|
||||
if(CMAKE_COMPILER_IS_CLANGXX)
|
||||
add_compile_options(-Wno-pedantic) # needed for vtk headers
|
||||
if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.0)
|
||||
|
||||
if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.0)
|
||||
add_compile_options(-Wno-inconsistent-missing-override)
|
||||
endif()
|
||||
elseif(CMAKE_COMPILER_IS_GNUCXX)
|
||||
@@ -15,12 +15,10 @@ else(MSVC)
|
||||
add_definitions(-DHAVE_LIMITS_H -DHAVE_CONFIG_H)
|
||||
endif(MSVC)
|
||||
|
||||
|
||||
if(BUILD_FEM_NETGEN)
|
||||
add_definitions(-DFCWithNetgen)
|
||||
endif(BUILD_FEM_NETGEN)
|
||||
|
||||
|
||||
include_directories(
|
||||
${CMAKE_BINARY_DIR}
|
||||
${CMAKE_SOURCE_DIR}/src
|
||||
@@ -37,18 +35,15 @@ include_directories(
|
||||
link_directories(${OCC_LIBRARY_DIR})
|
||||
link_directories(${SMESH_LIB_PATH})
|
||||
|
||||
|
||||
set(FemGui_LIBS
|
||||
Fem
|
||||
FreeCADGui
|
||||
PartGui
|
||||
)
|
||||
|
||||
|
||||
generate_from_xml(ViewProviderFemMeshPy)
|
||||
generate_from_xml(ViewProviderFemPostPipelinePy)
|
||||
|
||||
|
||||
SET(Python_SRCS
|
||||
ViewProviderFemMeshPy.xml
|
||||
ViewProviderFemMeshPyImp.cpp
|
||||
@@ -57,7 +52,6 @@ SET(Python_SRCS
|
||||
)
|
||||
SOURCE_GROUP("Python" FILES ${Python_SRCS})
|
||||
|
||||
|
||||
set(FemGui_UIC_SRCS
|
||||
DlgSettingsFemCcx.ui
|
||||
DlgSettingsFemElmer.ui
|
||||
@@ -65,7 +59,6 @@ set(FemGui_UIC_SRCS
|
||||
DlgSettingsFemGeneral.ui
|
||||
DlgSettingsFemGmsh.ui
|
||||
DlgSettingsFemInOutVtk.ui
|
||||
DlgSettingsFemMaterial.ui
|
||||
DlgSettingsFemMystran.ui
|
||||
DlgSettingsFemZ88.ui
|
||||
TaskCreateNodeSet.ui
|
||||
@@ -88,6 +81,7 @@ set(FemGui_UIC_SRCS
|
||||
TaskAnalysisInfo.ui
|
||||
TaskDriver.ui
|
||||
)
|
||||
|
||||
if(BUILD_FEM_VTK)
|
||||
set(FemGui_UIC_SRCS
|
||||
${FemGui_UIC_SRCS}
|
||||
@@ -126,9 +120,6 @@ SET(FemGui_DLG_SRCS
|
||||
DlgSettingsFemInOutVtk.ui
|
||||
DlgSettingsFemInOutVtkImp.cpp
|
||||
DlgSettingsFemInOutVtkImp.h
|
||||
DlgSettingsFemMaterial.ui
|
||||
DlgSettingsFemMaterialImp.cpp
|
||||
DlgSettingsFemMaterialImp.h
|
||||
DlgSettingsFemMystran.ui
|
||||
DlgSettingsFemMystranImp.cpp
|
||||
DlgSettingsFemMystranImp.h
|
||||
@@ -186,14 +177,13 @@ SET(FemGui_DLG_SRCS
|
||||
)
|
||||
SOURCE_GROUP("Constraint-Dialogs" FILES ${FemGui_DLG_SRCS})
|
||||
|
||||
set (Fem_TR_QRC ${CMAKE_CURRENT_BINARY_DIR}/Resources/Fem_translation.qrc)
|
||||
set(Fem_TR_QRC ${CMAKE_CURRENT_BINARY_DIR}/Resources/Fem_translation.qrc)
|
||||
qt_find_and_add_translation(QM_SRCS "Resources/translations/*_*.ts"
|
||||
${CMAKE_CURRENT_BINARY_DIR}/Resources/translations)
|
||||
qt_create_resource_file(${Fem_TR_QRC} ${QM_SRCS})
|
||||
qt_add_resources(FemResource_SRCS Resources/Fem.qrc ${Fem_TR_QRC})
|
||||
SOURCE_GROUP("Resources" FILES ${FemResource_SRCS})
|
||||
|
||||
|
||||
SET(FemGui_SRCS_ViewProvider
|
||||
ViewProviderFemMesh.cpp
|
||||
ViewProviderFemMesh.h
|
||||
@@ -254,7 +244,6 @@ SET(FemGui_SRCS_ViewProvider
|
||||
)
|
||||
SOURCE_GROUP("ViewProvider" FILES ${FemGui_SRCS_ViewProvider})
|
||||
|
||||
|
||||
SET(FemGui_SRCS_TaskBoxes
|
||||
TaskObjectName.ui
|
||||
TaskObjectName.cpp
|
||||
@@ -272,6 +261,7 @@ SET(FemGui_SRCS_TaskBoxes
|
||||
TaskTetParameter.cpp
|
||||
TaskTetParameter.h
|
||||
)
|
||||
|
||||
if(BUILD_FEM_VTK)
|
||||
SET(FemGui_SRCS_TaskBoxes
|
||||
${FemGui_SRCS_TaskBoxes}
|
||||
@@ -291,8 +281,8 @@ if(BUILD_FEM_VTK)
|
||||
TaskPostWarpVector.ui
|
||||
)
|
||||
endif(BUILD_FEM_VTK)
|
||||
SOURCE_GROUP("Task_Boxes" FILES ${FemGui_SRCS_TaskBoxes})
|
||||
|
||||
SOURCE_GROUP("Task_Boxes" FILES ${FemGui_SRCS_TaskBoxes})
|
||||
|
||||
SET(FemGui_SRCS_TaskDlg
|
||||
TaskDlgCreateNodeSet.h
|
||||
@@ -304,7 +294,6 @@ SET(FemGui_SRCS_TaskDlg
|
||||
)
|
||||
SOURCE_GROUP("Task_Dialogs" FILES ${FemGui_SRCS_TaskDlg})
|
||||
|
||||
|
||||
SET(FemGui_SRCS_Module
|
||||
AppFemGui.cpp
|
||||
AppFemGuiPy.cpp
|
||||
@@ -325,7 +314,6 @@ SET(FemGui_SRCS_Module
|
||||
)
|
||||
SOURCE_GROUP("Module" FILES ${FemGui_SRCS_Module})
|
||||
|
||||
|
||||
if(BUILD_FEM_VTK)
|
||||
SET(FemGui_SRCS_Post
|
||||
ViewProviderFemPostObject.h
|
||||
@@ -336,11 +324,10 @@ if(BUILD_FEM_VTK)
|
||||
ViewProviderFemPostFunction.cpp
|
||||
ViewProviderFemPostFilter.h
|
||||
ViewProviderFemPostFilter.cpp
|
||||
)
|
||||
)
|
||||
SOURCE_GROUP("PostObjects" FILES ${FemGui_SRCS_Post})
|
||||
endif(BUILD_FEM_VTK)
|
||||
|
||||
|
||||
SET(FemGui_SRCS
|
||||
${Python_SRCS}
|
||||
${FemGui_DLG_SRCS}
|
||||
@@ -365,13 +352,10 @@ SET(FemGuiIcon_SVG
|
||||
add_library(FemGui SHARED ${FemGui_SRCS} ${FemGuiIcon_SVG})
|
||||
target_link_libraries(FemGui ${FemGui_LIBS} ${VTK_LIBRARIES})
|
||||
|
||||
|
||||
fc_copy_sources(FemGui "${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_DATADIR}/Mod/Fem" ${FemGuiIcon_SVG})
|
||||
|
||||
|
||||
INSTALL(FILES ${FemGuiIcon_SVG} DESTINATION "${CMAKE_INSTALL_DATADIR}/Mod/Fem/Resources/icons")
|
||||
|
||||
|
||||
# Python modules ui files, they are copied as they are, thus the need not to be added to Fem.qrc
|
||||
# see https://forum.freecad.org/viewtopic.php?f=10&t=25833
|
||||
SET(FemGuiPythonUI_SRCS
|
||||
@@ -409,10 +393,7 @@ fc_copy_sources(FemPythonUi "${CMAKE_BINARY_DIR}/Mod/Fem" ${FemGuiPythonUI_SRCS}
|
||||
|
||||
INSTALL(FILES ${FemGuiPythonUI_SRCS} DESTINATION Mod/Fem/Resources/ui)
|
||||
|
||||
|
||||
|
||||
SET_BIN_DIR(FemGui FemGui /Mod/Fem)
|
||||
SET_PYTHON_PREFIX_SUFFIX(FemGui)
|
||||
|
||||
|
||||
INSTALL(TARGETS FemGui DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
|
||||
76
src/Mod/Material/App/AppMaterial.cpp
Normal file
76
src/Mod/Material/App/AppMaterial.cpp
Normal file
@@ -0,0 +1,76 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2023 David Carter <dcarter@david.carter.ca> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License (LGPL) *
|
||||
* as published by the Free Software Foundation; either version 2 of *
|
||||
* the License, or (at your option) any later version. *
|
||||
* for detail see the LICENCE text file. *
|
||||
* *
|
||||
* FreeCAD is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with FreeCAD; if not, write to the Free Software *
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||
* USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#include "PreCompiled.h"
|
||||
#ifndef _PreComp_
|
||||
#endif
|
||||
|
||||
#include <Base/Console.h>
|
||||
#include <Base/Interpreter.h>
|
||||
#include <Base/PyObjectBase.h>
|
||||
|
||||
// #include "Model.h"
|
||||
#include "MaterialManagerPy.h"
|
||||
#include "MaterialPy.h"
|
||||
#include "ModelManagerPy.h"
|
||||
#include "ModelPropertyPy.h"
|
||||
#include "ModelPy.h"
|
||||
|
||||
namespace Materials
|
||||
{
|
||||
class Module: public Py::ExtensionModule<Module>
|
||||
{
|
||||
public:
|
||||
Module()
|
||||
: Py::ExtensionModule<Module>("Material")
|
||||
{
|
||||
initialize("This module is the Material module.");// register with Python
|
||||
}
|
||||
|
||||
~Module() override = default;
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
PyObject* initModule()
|
||||
{
|
||||
return Base::Interpreter().addModule(new Module);
|
||||
}
|
||||
|
||||
}// namespace Materials
|
||||
|
||||
PyMOD_INIT_FUNC(Material)
|
||||
{
|
||||
PyObject* module = Materials::initModule();
|
||||
|
||||
Base::Console().Log("Loading Material module... done\n");
|
||||
|
||||
Base::Interpreter().addType(&Materials::MaterialManagerPy ::Type, module, "MaterialManager");
|
||||
Base::Interpreter().addType(&Materials::MaterialPy ::Type, module, "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");
|
||||
|
||||
PyMOD_Return(module);
|
||||
}
|
||||
99
src/Mod/Material/App/CMakeLists.txt
Normal file
99
src/Mod/Material/App/CMakeLists.txt
Normal file
@@ -0,0 +1,99 @@
|
||||
if(MSVC)
|
||||
add_definitions(-DFCAppMaterial -DHAVE_ACOSH -DHAVE_ASINH -DHAVE_ATANH)
|
||||
else(MSVC)
|
||||
add_definitions(-DHAVE_LIMITS_H -DHAVE_CONFIG_H)
|
||||
endif(MSVC)
|
||||
|
||||
add_definitions(-DYAML_CPP_STATIC_DEFINE)
|
||||
|
||||
include_directories(
|
||||
${CMAKE_BINARY_DIR}
|
||||
${CMAKE_BINARY_DIR}/src
|
||||
${CMAKE_SOURCE_DIR}/src
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${Boost_INCLUDE_DIRS}
|
||||
${PYTHON_INCLUDE_DIRS}
|
||||
${XercesC_INCLUDE_DIRS}
|
||||
${ZLIB_INCLUDE_DIR}
|
||||
${YAML_CPP_INCLUDE_DIR}
|
||||
)
|
||||
link_directories(${YAML_CPP_LIBRARY_DIR})
|
||||
|
||||
set(Material_LIBS
|
||||
${Boost_LIBRARIES}
|
||||
FreeCADApp
|
||||
)
|
||||
|
||||
include_directories(
|
||||
${QtConcurrent_INCLUDE_DIRS}
|
||||
)
|
||||
list(APPEND Material_LIBS
|
||||
${QtConcurrent_LIBRARIES}
|
||||
${YAML_CPP_LIBRARIES}
|
||||
)
|
||||
|
||||
generate_from_xml(MaterialManagerPy)
|
||||
generate_from_xml(MaterialPy)
|
||||
generate_from_xml(ModelManagerPy)
|
||||
generate_from_xml(ModelPropertyPy)
|
||||
generate_from_xml(ModelPy)
|
||||
|
||||
SET(Python_SRCS
|
||||
Exceptions.h
|
||||
MaterialManagerPy.xml
|
||||
MaterialManagerPyImpl.cpp
|
||||
MaterialPy.xml
|
||||
MaterialPyImpl.cpp
|
||||
ModelManagerPy.xml
|
||||
ModelManagerPyImpl.cpp
|
||||
ModelPropertyPy.xml
|
||||
ModelPropertyPyImpl.cpp
|
||||
ModelPy.xml
|
||||
ModelPyImpl.cpp
|
||||
)
|
||||
SOURCE_GROUP("Python" FILES ${Python_SRCS})
|
||||
|
||||
SET(Material_SRCS
|
||||
${Python_SRCS}
|
||||
AppMaterial.cpp
|
||||
FolderTree.h
|
||||
MaterialConfigLoader.cpp
|
||||
MaterialConfigLoader.h
|
||||
MaterialLibrary.cpp
|
||||
MaterialLibrary.h
|
||||
MaterialLoader.cpp
|
||||
MaterialLoader.h
|
||||
MaterialManager.cpp
|
||||
MaterialManager.h
|
||||
Materials.cpp
|
||||
Materials.h
|
||||
MaterialValue.cpp
|
||||
MaterialValue.h
|
||||
Model.cpp
|
||||
Model.h
|
||||
ModelLibrary.cpp
|
||||
ModelLibrary.h
|
||||
ModelLoader.cpp
|
||||
ModelLoader.h
|
||||
ModelManager.cpp
|
||||
ModelManager.h
|
||||
ModelUuids.h
|
||||
PreCompiled.cpp
|
||||
PreCompiled.h
|
||||
trim.h
|
||||
)
|
||||
|
||||
if(FREECAD_USE_PCH)
|
||||
add_definitions(-D_PreComp_)
|
||||
GET_MSVC_PRECOMPILED_SOURCE("PreCompiled.cpp" PCH_SRCS ${Material_SRCS})
|
||||
ADD_MSVC_PRECOMPILED_HEADER(Material PreCompiled.h PreCompiled.cpp PCH_SRCS)
|
||||
endif(FREECAD_USE_PCH)
|
||||
|
||||
add_library(Material SHARED ${Material_SRCS})
|
||||
target_link_libraries(Material ${Material_LIBS})
|
||||
|
||||
SET_BIN_DIR(Material Material /Mod/Material)
|
||||
SET_PYTHON_PREFIX_SUFFIX(Material)
|
||||
|
||||
INSTALL(TARGETS Material DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
154
src/Mod/Material/App/Exceptions.h
Normal file
154
src/Mod/Material/App/Exceptions.h
Normal file
@@ -0,0 +1,154 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2023 David Carter <dcarter@david.carter.ca> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef MATERIAL_EXCEPTIONS_H
|
||||
#define MATERIAL_EXCEPTIONS_H
|
||||
|
||||
#include <Base/BaseClass.h>
|
||||
#include <Base/Exception.h>
|
||||
|
||||
namespace Materials
|
||||
{
|
||||
|
||||
class Uninitialized: public Base::Exception
|
||||
{
|
||||
public:
|
||||
Uninitialized()
|
||||
{}
|
||||
explicit Uninitialized(const char* msg)
|
||||
{
|
||||
this->setMessage(msg);
|
||||
}
|
||||
~Uninitialized() throw() override = default;
|
||||
};
|
||||
|
||||
class ModelNotFound: public Base::Exception
|
||||
{
|
||||
public:
|
||||
ModelNotFound()
|
||||
{}
|
||||
explicit ModelNotFound(const char* msg)
|
||||
{
|
||||
this->setMessage(msg);
|
||||
}
|
||||
~ModelNotFound() throw() override = default;
|
||||
};
|
||||
|
||||
class MaterialNotFound: public Base::Exception
|
||||
{
|
||||
public:
|
||||
MaterialNotFound()
|
||||
{}
|
||||
explicit MaterialNotFound(const char* msg)
|
||||
{
|
||||
this->setMessage(msg);
|
||||
}
|
||||
~MaterialNotFound() throw() override = default;
|
||||
};
|
||||
|
||||
class PropertyNotFound: public Base::Exception
|
||||
{
|
||||
public:
|
||||
PropertyNotFound()
|
||||
{}
|
||||
explicit PropertyNotFound(const char* msg)
|
||||
{
|
||||
this->setMessage(msg);
|
||||
}
|
||||
~PropertyNotFound() throw() override = default;
|
||||
};
|
||||
|
||||
class LibraryNotFound: public Base::Exception
|
||||
{
|
||||
public:
|
||||
LibraryNotFound()
|
||||
{}
|
||||
explicit LibraryNotFound(const char* msg)
|
||||
{
|
||||
this->setMessage(msg);
|
||||
}
|
||||
~LibraryNotFound() throw() override = default;
|
||||
};
|
||||
|
||||
class InvalidModel: public Base::Exception
|
||||
{
|
||||
public:
|
||||
InvalidModel()
|
||||
{}
|
||||
explicit InvalidModel(const char* msg)
|
||||
{
|
||||
this->setMessage(msg);
|
||||
}
|
||||
~InvalidModel() throw() override = default;
|
||||
};
|
||||
|
||||
class InvalidRow: public Base::Exception
|
||||
{
|
||||
public:
|
||||
InvalidRow()
|
||||
{}
|
||||
explicit InvalidRow(char* msg)
|
||||
{
|
||||
this->setMessage(msg);
|
||||
}
|
||||
~InvalidRow() throw() override = default;
|
||||
};
|
||||
|
||||
class InvalidColumn: public Base::Exception
|
||||
{
|
||||
public:
|
||||
InvalidColumn()
|
||||
{}
|
||||
explicit InvalidColumn(char* msg)
|
||||
{
|
||||
this->setMessage(msg);
|
||||
}
|
||||
~InvalidColumn() throw() override = default;
|
||||
};
|
||||
|
||||
class InvalidIndex: public Base::Exception
|
||||
{
|
||||
public:
|
||||
InvalidIndex()
|
||||
{}
|
||||
explicit InvalidIndex(char* msg)
|
||||
{
|
||||
this->setMessage(msg);
|
||||
}
|
||||
~InvalidIndex() throw() override = default;
|
||||
};
|
||||
|
||||
class UnknownValueType: public Base::Exception
|
||||
{
|
||||
public:
|
||||
UnknownValueType()
|
||||
{}
|
||||
explicit UnknownValueType(char* msg)
|
||||
{
|
||||
this->setMessage(msg);
|
||||
}
|
||||
~UnknownValueType() throw() override = default;
|
||||
};
|
||||
|
||||
}// namespace Materials
|
||||
|
||||
#endif// MATERIAL_EXCEPTIONS_H
|
||||
87
src/Mod/Material/App/FolderTree.h
Normal file
87
src/Mod/Material/App/FolderTree.h
Normal file
@@ -0,0 +1,87 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2023 David Carter <dcarter@david.carter.ca> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef MATERIAL_FOLDERTREE_H
|
||||
#define MATERIAL_FOLDERTREE_H
|
||||
|
||||
#include <QString>
|
||||
#include <map>
|
||||
|
||||
namespace Materials
|
||||
{
|
||||
|
||||
template<class T>
|
||||
class FolderTreeNode
|
||||
{
|
||||
public:
|
||||
enum NodeType
|
||||
{
|
||||
DataNode,
|
||||
FolderNode
|
||||
};
|
||||
|
||||
FolderTreeNode()
|
||||
{}
|
||||
virtual ~FolderTreeNode() = default;
|
||||
|
||||
NodeType getType(void) const
|
||||
{
|
||||
return _type;
|
||||
}
|
||||
void setType(NodeType type)
|
||||
{
|
||||
_type = type;
|
||||
}
|
||||
|
||||
const std::map<QString, FolderTreeNode<T>*>* getFolder(void) const
|
||||
{
|
||||
return _folder;
|
||||
}
|
||||
std::map<QString, FolderTreeNode<T>*>* getFolder(void)
|
||||
{
|
||||
return _folder;
|
||||
}
|
||||
const T* getData(void) const
|
||||
{
|
||||
return _data;
|
||||
}
|
||||
|
||||
void setFolder(std::map<QString, FolderTreeNode<T>*>* folder)
|
||||
{
|
||||
setType(FolderNode);
|
||||
_folder = folder;
|
||||
}
|
||||
void setData(const T* data)
|
||||
{
|
||||
setType(DataNode);
|
||||
_data = data;
|
||||
}
|
||||
|
||||
private:
|
||||
NodeType _type;
|
||||
std::map<QString, FolderTreeNode<T>*>* _folder;
|
||||
const T* _data;
|
||||
};
|
||||
|
||||
}// namespace Materials
|
||||
|
||||
#endif// MATERIAL_FOLDERTREE_H
|
||||
396
src/Mod/Material/App/MaterialConfigLoader.cpp
Normal file
396
src/Mod/Material/App/MaterialConfigLoader.cpp
Normal file
@@ -0,0 +1,396 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2023 David Carter <dcarter@david.carter.ca> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "PreCompiled.h"
|
||||
#ifndef _PreComp_
|
||||
#include <QDirIterator>
|
||||
#include <QFileInfo>
|
||||
#include <QString>
|
||||
#endif
|
||||
|
||||
#include <QUuid>
|
||||
|
||||
#include <App/Application.h>
|
||||
#include <Base/Interpreter.h>
|
||||
#include <fstream>
|
||||
|
||||
|
||||
#include "MaterialConfigLoader.h"
|
||||
#include "MaterialLoader.h"
|
||||
#include "Model.h"
|
||||
#include "ModelUuids.h"
|
||||
|
||||
|
||||
using namespace Materials;
|
||||
|
||||
MaterialConfigLoader::MaterialConfigLoader()
|
||||
{}
|
||||
|
||||
bool MaterialConfigLoader::isConfigStyle(const QString& path)
|
||||
{
|
||||
std::ifstream infile(path.toStdString());
|
||||
|
||||
// Check the first 2 lines for a ";"
|
||||
for (int i = 0; i < 2; i++) {
|
||||
std::string line;
|
||||
if (!std::getline(infile, line)) {
|
||||
return false;
|
||||
}
|
||||
if (line.at(0) != ';') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QString MaterialConfigLoader::getAuthorAndLicense(const QString& path)
|
||||
{
|
||||
std::ifstream infile(path.toStdString());
|
||||
QString noAuthor;
|
||||
|
||||
// Skip the first line
|
||||
std::string line;
|
||||
if (!std::getline(infile, line)) {
|
||||
return noAuthor;
|
||||
}
|
||||
|
||||
// The second line has it in a comment
|
||||
if (!std::getline(infile, line)) {
|
||||
return noAuthor;
|
||||
}
|
||||
std::size_t found = line.find(";");
|
||||
if (found != std::string::npos) {
|
||||
return QString::fromStdString(trim_copy(line.substr(found + 1)));
|
||||
}
|
||||
|
||||
return noAuthor;
|
||||
}
|
||||
|
||||
void MaterialConfigLoader::addVectorRendering(const QSettings& fcmat, Material* finalModel)
|
||||
{
|
||||
QString sectionFillPattern = value(fcmat, "VectorRendering/SectionFillPattern", "");
|
||||
QString sectionLinewidth = value(fcmat, "VectorRendering/SectionLinewidth", "");
|
||||
QString sectionColor = value(fcmat, "VectorRendering/SectionColor", "");
|
||||
QString viewColor = value(fcmat, "VectorRendering/ViewColor", "");
|
||||
QString viewFillPattern = value(fcmat, "VectorRendering/ViewFillPattern", "");
|
||||
QString viewLinewidth = value(fcmat, "VectorRendering/ViewLinewidth", "");
|
||||
|
||||
if (sectionFillPattern.length() + sectionLinewidth.length() + sectionColor.length()
|
||||
+ viewColor.length() + viewFillPattern.length() + viewLinewidth.length()
|
||||
> 0) {
|
||||
finalModel->addAppearance(ModelUUID_Rendering_Vector);
|
||||
}
|
||||
|
||||
// Now add the data
|
||||
setAppearanceValue(finalModel, "SectionFillPattern", sectionFillPattern);
|
||||
setAppearanceValue(finalModel, "SectionLinewidth", sectionLinewidth);
|
||||
setAppearanceValue(finalModel, "SectionColor", sectionColor);
|
||||
setAppearanceValue(finalModel, "ViewColor", viewColor);
|
||||
setAppearanceValue(finalModel, "ViewFillPattern", viewFillPattern);
|
||||
setAppearanceValue(finalModel, "ViewLinewidth", viewLinewidth);
|
||||
}
|
||||
|
||||
void MaterialConfigLoader::addRendering(const QSettings& fcmat, Material* finalModel)
|
||||
{
|
||||
QString ambientColor = value(fcmat, "Rendering/AmbientColor", "");
|
||||
QString diffuseColor = value(fcmat, "Rendering/DiffuseColor", "");
|
||||
QString emissiveColor = value(fcmat, "Rendering/EmissiveColor", "");
|
||||
QString shininess = value(fcmat, "Rendering/Shininess", "");
|
||||
QString specularColor = value(fcmat, "Rendering/SpecularColor", "");
|
||||
QString transparency = value(fcmat, "Rendering/Transparency", "");
|
||||
QString texturePath = value(fcmat, "Rendering/TexturePath", "");
|
||||
QString textureScaling = value(fcmat, "Rendering/TextureScaling", "");
|
||||
QString fragmentShader = value(fcmat, "Rendering/FragmentShader", "");
|
||||
QString vertexShader = value(fcmat, "Rendering/VertexShader", "");
|
||||
|
||||
// Check which model we need
|
||||
bool useTexture = false;
|
||||
bool useAdvanced = false;
|
||||
bool useBasic = false;
|
||||
if (texturePath.length() + textureScaling.length() > 0) {
|
||||
useTexture = true;
|
||||
}
|
||||
if (fragmentShader.length() + vertexShader.length() > 0) {
|
||||
useAdvanced = true;
|
||||
}
|
||||
if (ambientColor.length() + diffuseColor.length() + emissiveColor.length() + shininess.length()
|
||||
+ specularColor.length() + transparency.length()
|
||||
> 0) {
|
||||
useBasic = true;
|
||||
}
|
||||
|
||||
if (useAdvanced) {
|
||||
finalModel->addAppearance(ModelUUID_Rendering_Advanced);
|
||||
}
|
||||
else if (useTexture) {
|
||||
finalModel->addAppearance(ModelUUID_Rendering_Texture);
|
||||
}
|
||||
else if (useBasic) {
|
||||
finalModel->addAppearance(ModelUUID_Rendering_Basic);
|
||||
}
|
||||
|
||||
// Now add the data
|
||||
setAppearanceValue(finalModel, "AmbientColor", ambientColor);
|
||||
setAppearanceValue(finalModel, "DiffuseColor", diffuseColor);
|
||||
setAppearanceValue(finalModel, "EmissiveColor", emissiveColor);
|
||||
setAppearanceValue(finalModel, "Shininess", shininess);
|
||||
setAppearanceValue(finalModel, "SpecularColor", specularColor);
|
||||
setAppearanceValue(finalModel, "Transparency", transparency);
|
||||
setAppearanceValue(finalModel, "TexturePath", texturePath);
|
||||
setAppearanceValue(finalModel, "TextureScaling", textureScaling);
|
||||
setAppearanceValue(finalModel, "FragmentShader", fragmentShader);
|
||||
setAppearanceValue(finalModel, "VertexShader", vertexShader);
|
||||
}
|
||||
|
||||
void MaterialConfigLoader::addCosts(const QSettings& fcmat, Material* 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);
|
||||
}
|
||||
|
||||
// Now add the data
|
||||
setPhysicalValue(finalModel, "ProductURL", productURL);
|
||||
setPhysicalValue(finalModel, "SpecificPrice", specificPrice);
|
||||
setPhysicalValue(finalModel, "Vendor", vendor);
|
||||
}
|
||||
|
||||
void MaterialConfigLoader::addArchitectural(const QSettings& fcmat, Material* finalModel)
|
||||
{
|
||||
QString color = value(fcmat, "Architectural/Color", "");
|
||||
QString environmentalEfficiencyClass =
|
||||
value(fcmat, "Architectural/EnvironmentalEfficiencyClass", "");
|
||||
QString executionInstructions = value(fcmat, "Architectural/ExecutionInstructions", "");
|
||||
QString finish = value(fcmat, "Architectural/Finish", "");
|
||||
QString fireResistanceClass = value(fcmat, "Architectural/FireResistanceClass", "");
|
||||
QString model = value(fcmat, "Architectural/Model", "");
|
||||
QString soundTransmissionClass = value(fcmat, "Architectural/SoundTransmissionClass", "");
|
||||
QString unitsPerQuantity = value(fcmat, "Architectural/UnitsPerQuantity", "");
|
||||
|
||||
if (color.length() + environmentalEfficiencyClass.length() + executionInstructions.length()
|
||||
+ finish.length() + fireResistanceClass.length() + model.length()
|
||||
+ soundTransmissionClass.length() + unitsPerQuantity.length()
|
||||
> 0) {
|
||||
finalModel->addPhysical(ModelUUID_Architectural_Default);
|
||||
}
|
||||
|
||||
// Now add the data
|
||||
setPhysicalValue(finalModel, "Color", color);
|
||||
setPhysicalValue(finalModel, "EnvironmentalEfficiencyClass", environmentalEfficiencyClass);
|
||||
setPhysicalValue(finalModel, "ExecutionInstructions", executionInstructions);
|
||||
setPhysicalValue(finalModel, "Finish", finish);
|
||||
setPhysicalValue(finalModel, "FireResistanceClass", fireResistanceClass);
|
||||
setPhysicalValue(finalModel, "Model", model);
|
||||
setPhysicalValue(finalModel, "SoundTransmissionClass", soundTransmissionClass);
|
||||
setPhysicalValue(finalModel, "UnitsPerQuantity", unitsPerQuantity);
|
||||
}
|
||||
|
||||
void MaterialConfigLoader::addElectromagnetic(const QSettings& fcmat, Material* finalModel)
|
||||
{
|
||||
QString relativePermittivity = value(fcmat, "Electromagnetic/RelativePermittivity", "");
|
||||
QString electricalConductivity = value(fcmat, "Electromagnetic/ElectricalConductivity", "");
|
||||
QString relativePermeability = value(fcmat, "Electromagnetic/RelativePermeability", "");
|
||||
|
||||
if (relativePermittivity.length() + electricalConductivity.length()
|
||||
+ relativePermeability.length()
|
||||
> 0) {
|
||||
finalModel->addPhysical(ModelUUID_Electromagnetic_Default);
|
||||
}
|
||||
|
||||
// Now add the data
|
||||
setPhysicalValue(finalModel, "RelativePermittivity", relativePermittivity);
|
||||
setPhysicalValue(finalModel, "ElectricalConductivity", electricalConductivity);
|
||||
setPhysicalValue(finalModel, "RelativePermeability", relativePermeability);
|
||||
}
|
||||
|
||||
void MaterialConfigLoader::addThermal(const QSettings& fcmat, Material* finalModel)
|
||||
{
|
||||
QString specificHeat = value(fcmat, "Thermal/SpecificHeat", "");
|
||||
QString thermalConductivity = value(fcmat, "Thermal/ThermalConductivity", "");
|
||||
QString thermalExpansionCoefficient = value(fcmat, "Thermal/ThermalExpansionCoefficient", "");
|
||||
|
||||
if (specificHeat.length() + thermalConductivity.length() + thermalExpansionCoefficient.length()
|
||||
> 0) {
|
||||
finalModel->addPhysical(ModelUUID_Thermal_Default);
|
||||
}
|
||||
|
||||
// Now add the data
|
||||
setPhysicalValue(finalModel, "SpecificHeat", specificHeat);
|
||||
setPhysicalValue(finalModel, "ThermalConductivity", thermalConductivity);
|
||||
setPhysicalValue(finalModel, "ThermalExpansionCoefficient", thermalExpansionCoefficient);
|
||||
}
|
||||
|
||||
void MaterialConfigLoader::addFluid(const QSettings& fcmat, Material* finalModel)
|
||||
{
|
||||
QString density = value(fcmat, "Fluidic/Density", "");
|
||||
QString dynamicViscosity = value(fcmat, "Fluidic/DynamicViscosity", "");
|
||||
QString kinematicViscosity = value(fcmat, "Fluidic/KinematicViscosity", "");
|
||||
QString prandtlNumber = value(fcmat, "Fluidic/PrandtlNumber", "");
|
||||
|
||||
// Check which model we need
|
||||
bool useDensity = false;
|
||||
bool useFluid = false;
|
||||
if (density.length() > 0) {
|
||||
useDensity = true;
|
||||
}
|
||||
if (dynamicViscosity.length() + kinematicViscosity.length() + prandtlNumber.length() > 0) {
|
||||
useFluid = true;
|
||||
}
|
||||
|
||||
if (useFluid) {
|
||||
finalModel->addPhysical(ModelUUID_Fluid_Default);
|
||||
}
|
||||
else if (useDensity) {
|
||||
finalModel->addPhysical(ModelUUID_Mechanical_Density);
|
||||
}
|
||||
|
||||
// Now add the data
|
||||
setPhysicalValue(finalModel, "Density", density);
|
||||
setPhysicalValue(finalModel, "DynamicViscosity", dynamicViscosity);
|
||||
setPhysicalValue(finalModel, "KinematicViscosity", kinematicViscosity);
|
||||
setPhysicalValue(finalModel, "PrandtlNumber", prandtlNumber);
|
||||
}
|
||||
|
||||
void MaterialConfigLoader::addMechanical(const QSettings& fcmat, Material* finalModel)
|
||||
{
|
||||
QString density = value(fcmat, "Mechanical/Density", "");
|
||||
QString bulkModulus = value(fcmat, "Mechanical/BulkModulus", "");
|
||||
QString poissonRatio = value(fcmat, "Mechanical/PoissonRatio", "");
|
||||
QString shearModulus = value(fcmat, "Mechanical/ShearModulus", "");
|
||||
QString youngsModulus = value(fcmat, "Mechanical/YoungsModulus", "");
|
||||
QString angleOfFriction = value(fcmat, "Mechanical/AngleOfFriction", "");
|
||||
QString compressiveStrength = value(fcmat, "Mechanical/CompressiveStrength", "");
|
||||
QString fractureToughness = value(fcmat, "Mechanical/FractureToughness", "");
|
||||
QString ultimateStrain = value(fcmat, "Mechanical/UltimateStrain", "");
|
||||
QString ultimateTensileStrength = value(fcmat, "Mechanical/UltimateTensileStrength", "");
|
||||
QString yieldStrength = value(fcmat, "Mechanical/YieldStrength", "");
|
||||
QString stiffness = value(fcmat, "Mechanical/Stiffness", "");
|
||||
|
||||
// Check which model we need
|
||||
bool useDensity = false;
|
||||
bool useIso = false;
|
||||
bool useLinearElastic = false;
|
||||
if (density.length() > 0) {
|
||||
useDensity = true;
|
||||
}
|
||||
if (bulkModulus.length() + poissonRatio.length() + shearModulus.length()
|
||||
+ youngsModulus.length()
|
||||
> 0) {
|
||||
useIso = true;
|
||||
}
|
||||
if (angleOfFriction.length() + compressiveStrength.length() + fractureToughness.length()
|
||||
+ ultimateStrain.length() + ultimateTensileStrength.length() + yieldStrength.length()
|
||||
+ stiffness.length()
|
||||
> 0) {
|
||||
useLinearElastic = true;
|
||||
}
|
||||
|
||||
if (useLinearElastic) {
|
||||
finalModel->addPhysical(ModelUUID_Mechanical_LinearElastic);
|
||||
}
|
||||
else {
|
||||
if (useIso) {
|
||||
finalModel->addPhysical(ModelUUID_Mechanical_IsotropicLinearElastic);
|
||||
}
|
||||
if (useDensity) {
|
||||
finalModel->addPhysical(ModelUUID_Mechanical_Density);
|
||||
}
|
||||
}
|
||||
|
||||
// Now add the data
|
||||
setPhysicalValue(finalModel, "Density", density);
|
||||
setPhysicalValue(finalModel, "BulkModulus", bulkModulus);
|
||||
setPhysicalValue(finalModel, "PoissonRatio", poissonRatio);
|
||||
setPhysicalValue(finalModel, "ShearModulus", shearModulus);
|
||||
setPhysicalValue(finalModel, "YoungsModulus", youngsModulus);
|
||||
setPhysicalValue(finalModel, "AngleOfFriction", angleOfFriction);
|
||||
setPhysicalValue(finalModel, "CompressiveStrength", compressiveStrength);
|
||||
setPhysicalValue(finalModel, "FractureToughness", fractureToughness);
|
||||
setPhysicalValue(finalModel, "UltimateStrain", ultimateStrain);
|
||||
setPhysicalValue(finalModel, "UltimateTensileStrength", ultimateTensileStrength);
|
||||
setPhysicalValue(finalModel, "YieldStrength", yieldStrength);
|
||||
setPhysicalValue(finalModel, "Stiffness", stiffness);
|
||||
}
|
||||
|
||||
Material* MaterialConfigLoader::getMaterialFromPath(const MaterialLibrary& library,
|
||||
const QString& path)
|
||||
{
|
||||
QString authorAndLicense = getAuthorAndLicense(path);
|
||||
|
||||
QSettings fcmat(path, QSettings::IniFormat);
|
||||
|
||||
// General section
|
||||
// QString name = value(fcmat, "Name", ""); - always get the name from the filename
|
||||
QFileInfo filepath(path);
|
||||
QString name =
|
||||
filepath.fileName().remove(QString::fromStdString(".FCMat"), Qt::CaseInsensitive);
|
||||
QString uuid = QUuid::createUuid().toString(QUuid::WithoutBraces);
|
||||
|
||||
QString description = value(fcmat, "Description", "");
|
||||
QString sourceReference = value(fcmat, "ReferenceSource", "");
|
||||
QString sourceURL = value(fcmat, "SourceURL", "");
|
||||
|
||||
Material* finalModel = new Material(library, path, uuid, name);
|
||||
finalModel->setAuthorAndLicense(authorAndLicense);
|
||||
finalModel->setDescription(description);
|
||||
finalModel->setReference(sourceReference);
|
||||
finalModel->setURL(sourceURL);
|
||||
|
||||
QString father = value(fcmat, "Father", "");
|
||||
if (father.length() > 0) {
|
||||
finalModel->addPhysical(ModelUUID_Legacy_Father);
|
||||
|
||||
// Now add the data
|
||||
setPhysicalValue(finalModel, "Father", father);
|
||||
}
|
||||
|
||||
QString kindOfMaterial = value(fcmat, "KindOfMaterial", "");
|
||||
QString materialNumber = value(fcmat, "MaterialNumber", "");
|
||||
QString norm = value(fcmat, "Norm", "");
|
||||
QString standardCode = value(fcmat, "StandardCode", "");
|
||||
if (kindOfMaterial.length() + materialNumber.length() + norm.length() + standardCode.length()
|
||||
> 0) {
|
||||
finalModel->addPhysical(ModelUUID_Legacy_MaterialStandard);
|
||||
|
||||
// Now add the data
|
||||
setPhysicalValue(finalModel, "KindOfMaterial", kindOfMaterial);
|
||||
setPhysicalValue(finalModel, "MaterialNumber", materialNumber);
|
||||
setPhysicalValue(finalModel, "StandardCode", norm);// Norm is the same as StandardCode
|
||||
setPhysicalValue(finalModel, "StandardCode", standardCode);
|
||||
}
|
||||
|
||||
// Add the remaining sections
|
||||
addMechanical(fcmat, finalModel);
|
||||
addFluid(fcmat, finalModel);
|
||||
addThermal(fcmat, finalModel);
|
||||
addElectromagnetic(fcmat, finalModel);
|
||||
addArchitectural(fcmat, finalModel);
|
||||
addCosts(fcmat, finalModel);
|
||||
addRendering(fcmat, finalModel);
|
||||
addVectorRendering(fcmat, finalModel);
|
||||
|
||||
return finalModel;
|
||||
}
|
||||
81
src/Mod/Material/App/MaterialConfigLoader.h
Normal file
81
src/Mod/Material/App/MaterialConfigLoader.h
Normal file
@@ -0,0 +1,81 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2023 David Carter <dcarter@david.carter.ca> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef MATERIAL_MATERIALCONFIGLOADER_H
|
||||
#define MATERIAL_MATERIALCONFIGLOADER_H
|
||||
|
||||
#include <QDir>
|
||||
#include <QSettings>
|
||||
#include <QString>
|
||||
|
||||
#include "Materials.h"
|
||||
|
||||
namespace Materials
|
||||
{
|
||||
|
||||
class MaterialConfigLoader
|
||||
{
|
||||
public:
|
||||
MaterialConfigLoader();
|
||||
virtual ~MaterialConfigLoader() = default;
|
||||
|
||||
|
||||
static bool isConfigStyle(const QString& path);
|
||||
static Material* getMaterialFromPath(const MaterialLibrary& library, const QString& path);
|
||||
|
||||
private:
|
||||
static QString
|
||||
value(const QSettings& fcmat, const std::string& name, const std::string& defaultValue)
|
||||
{
|
||||
return fcmat.value(QString::fromStdString(name), QString::fromStdString(defaultValue))
|
||||
.toString();
|
||||
}
|
||||
|
||||
static void
|
||||
setPhysicalValue(Material* 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)
|
||||
{
|
||||
if (value.length() > 0) {
|
||||
finalModel->setAppearanceValue(QString::fromStdString(name), value);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
};
|
||||
|
||||
}// namespace Materials
|
||||
|
||||
#endif// MATERIAL_MATERIALCONFIGLOADER_H
|
||||
168
src/Mod/Material/App/MaterialLibrary.cpp
Normal file
168
src/Mod/Material/App/MaterialLibrary.cpp
Normal file
@@ -0,0 +1,168 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2023 David Carter <dcarter@david.carter.ca> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "PreCompiled.h"
|
||||
#ifndef _PreComp_
|
||||
#endif
|
||||
|
||||
#include <App/Application.h>
|
||||
|
||||
#include "MaterialLibrary.h"
|
||||
#include "Materials.h"
|
||||
#include "ModelManager.h"
|
||||
|
||||
|
||||
using namespace Materials;
|
||||
|
||||
/* TRANSLATOR Material::Materials */
|
||||
|
||||
std::map<QString, Material*>* MaterialLibrary::_materialPathMap = nullptr;
|
||||
|
||||
TYPESYSTEM_SOURCE(Materials::MaterialLibrary, LibraryBase)
|
||||
|
||||
MaterialLibrary::MaterialLibrary()
|
||||
{
|
||||
if (_materialPathMap == nullptr) {
|
||||
_materialPathMap = new std::map<QString, Material*>();
|
||||
}
|
||||
}
|
||||
|
||||
MaterialLibrary::MaterialLibrary(const QString& libraryName,
|
||||
const QString& dir,
|
||||
const QString& icon,
|
||||
bool readOnly)
|
||||
: LibraryBase(libraryName, dir, icon)
|
||||
, _readOnly(readOnly)
|
||||
{
|
||||
if (_materialPathMap == nullptr) {
|
||||
_materialPathMap = new std::map<QString, Material*>();
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialLibrary::createPath(const QString& path)
|
||||
{
|
||||
Q_UNUSED(path)
|
||||
}
|
||||
|
||||
Material* MaterialLibrary::saveMaterial(Material& material, const QString& path, bool saveAsCopy)
|
||||
{
|
||||
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 overwrite false having warned the user
|
||||
// if old format true, but already set
|
||||
|
||||
|
||||
QFileInfo info(file);
|
||||
QDir fileDir(info.path());
|
||||
if (!fileDir.exists()) {
|
||||
if (!fileDir.mkpath(info.path())) {
|
||||
Base::Console().Error("Unable to create directory path '%s'\n",
|
||||
info.path().toStdString().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
|
||||
QTextStream stream(&file);
|
||||
stream.setCodec("UTF-8");
|
||||
stream.setGenerateByteOrderMark(true);
|
||||
|
||||
// Write the contents
|
||||
material.setLibrary(*this);
|
||||
material.setDirectory(getRelativePath(path));
|
||||
material.save(stream, saveAsCopy);
|
||||
}
|
||||
|
||||
return addMaterial(material, path);
|
||||
}
|
||||
|
||||
Material* MaterialLibrary::addMaterial(const Material& material, const QString& path)
|
||||
{
|
||||
QString filePath = getRelativePath(path);
|
||||
Material* newMaterial = new Material(material);
|
||||
newMaterial->setLibrary(*this);
|
||||
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
|
||||
{
|
||||
// Base::Console().Log("MaterialLibrary::getMaterialByPath(%s)\n", path.toStdString().c_str());
|
||||
// for (auto itp = _materialPathMap->begin(); itp != _materialPathMap->end(); itp++) {
|
||||
// Base::Console().Log("\tpath = '%s'\n", itp->first.toStdString().c_str());
|
||||
// }
|
||||
|
||||
QString filePath = getRelativePath(path);
|
||||
try {
|
||||
Material* material = _materialPathMap->at(filePath);
|
||||
return *material;
|
||||
}
|
||||
catch (std::out_of_range& e) {
|
||||
throw MaterialNotFound();
|
||||
}
|
||||
}
|
||||
|
||||
const QString MaterialLibrary::getUUIDFromPath(const QString& path) const
|
||||
{
|
||||
QString filePath = getRelativePath(path);
|
||||
try {
|
||||
Material* material = _materialPathMap->at(filePath);
|
||||
return material->getUUID();
|
||||
}
|
||||
catch (std::out_of_range& e) {
|
||||
throw MaterialNotFound();
|
||||
}
|
||||
}
|
||||
|
||||
TYPESYSTEM_SOURCE(Materials::MaterialExternalLibrary, MaterialLibrary::MaterialLibrary)
|
||||
|
||||
MaterialExternalLibrary::MaterialExternalLibrary()
|
||||
{}
|
||||
|
||||
MaterialExternalLibrary::MaterialExternalLibrary(const QString& libraryName,
|
||||
const QString& dir,
|
||||
const QString& icon,
|
||||
bool readOnly)
|
||||
: MaterialLibrary(libraryName, dir, icon, readOnly)
|
||||
{}
|
||||
|
||||
MaterialExternalLibrary::~MaterialExternalLibrary()
|
||||
{
|
||||
// delete directory;
|
||||
}
|
||||
95
src/Mod/Material/App/MaterialLibrary.h
Normal file
95
src/Mod/Material/App/MaterialLibrary.h
Normal file
@@ -0,0 +1,95 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2023 David Carter <dcarter@david.carter.ca> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef MATERIAL_MATERIALLIBRARY_H
|
||||
#define MATERIAL_MATERIALLIBRARY_H
|
||||
|
||||
#include <Base/BaseClass.h>
|
||||
#include <QDir>
|
||||
#include <QString>
|
||||
#include <QVariant>
|
||||
|
||||
#include "Model.h"
|
||||
#include "ModelLibrary.h"
|
||||
|
||||
namespace Materials
|
||||
{
|
||||
|
||||
class Material;
|
||||
|
||||
class MaterialsExport MaterialLibrary: public LibraryBase
|
||||
{
|
||||
TYPESYSTEM_HEADER();
|
||||
|
||||
public:
|
||||
MaterialLibrary();
|
||||
explicit MaterialLibrary(const QString& libraryName,
|
||||
const QString& dir,
|
||||
const QString& icon,
|
||||
bool readOnly = true);
|
||||
virtual ~MaterialLibrary() = default;
|
||||
|
||||
bool operator==(const MaterialLibrary& library) const
|
||||
{
|
||||
return LibraryBase::operator==(library);
|
||||
}
|
||||
bool operator!=(const MaterialLibrary& library) const
|
||||
{
|
||||
return !operator==(library);
|
||||
}
|
||||
const Material& 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);
|
||||
|
||||
bool isReadOnly() const
|
||||
{
|
||||
return _readOnly;
|
||||
}
|
||||
|
||||
protected:
|
||||
const QString getUUIDFromPath(const QString& path) const;
|
||||
|
||||
bool _readOnly;
|
||||
static std::map<QString, Material*>* _materialPathMap;
|
||||
};
|
||||
|
||||
class MaterialsExport MaterialExternalLibrary: public MaterialLibrary
|
||||
{
|
||||
TYPESYSTEM_HEADER();
|
||||
|
||||
public:
|
||||
MaterialExternalLibrary();
|
||||
explicit MaterialExternalLibrary(const QString& libraryName,
|
||||
const QString& dir,
|
||||
const QString& icon,
|
||||
bool readOnly = true);
|
||||
virtual ~MaterialExternalLibrary();
|
||||
};
|
||||
|
||||
}// namespace Materials
|
||||
|
||||
Q_DECLARE_METATYPE(Materials::MaterialLibrary)
|
||||
Q_DECLARE_METATYPE(Materials::MaterialExternalLibrary)
|
||||
|
||||
#endif// MATERIAL_MATERIALLIBRARY_H
|
||||
445
src/Mod/Material/App/MaterialLoader.cpp
Normal file
445
src/Mod/Material/App/MaterialLoader.cpp
Normal file
@@ -0,0 +1,445 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2023 David Carter <dcarter@david.carter.ca> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "PreCompiled.h"
|
||||
#ifndef _PreComp_
|
||||
#include <QString>
|
||||
#endif
|
||||
|
||||
#include <App/Application.h>
|
||||
#include <Base/Interpreter.h>
|
||||
|
||||
#include <QDirIterator>
|
||||
#include <QFileInfo>
|
||||
|
||||
#include "MaterialConfigLoader.h"
|
||||
#include "MaterialLoader.h"
|
||||
#include "Model.h"
|
||||
#include "ModelManager.h"
|
||||
|
||||
|
||||
using namespace Materials;
|
||||
|
||||
MaterialEntry::MaterialEntry()
|
||||
{}
|
||||
|
||||
MaterialEntry::MaterialEntry(const MaterialLibrary& library,
|
||||
const QString& modelName,
|
||||
const QString& dir,
|
||||
const QString& modelUuid)
|
||||
: _library(library)
|
||||
, _name(modelName)
|
||||
, _directory(dir)
|
||||
, _uuid(modelUuid)
|
||||
{}
|
||||
|
||||
MaterialYamlEntry::MaterialYamlEntry(const MaterialLibrary& library,
|
||||
const QString& modelName,
|
||||
const QString& dir,
|
||||
const QString& modelUuid,
|
||||
const YAML::Node& modelData)
|
||||
: MaterialEntry(library, modelName, dir, modelUuid)
|
||||
, _model(modelData)
|
||||
{}
|
||||
|
||||
// MaterialYamlEntry::~MaterialYamlEntry()
|
||||
// {}
|
||||
|
||||
QString MaterialYamlEntry::yamlValue(const YAML::Node& node,
|
||||
const std::string& key,
|
||||
const std::string& defaultValue)
|
||||
{
|
||||
if (node[key]) {
|
||||
return QString::fromStdString(node[key].as<std::string>());
|
||||
}
|
||||
return QString::fromStdString(defaultValue);
|
||||
}
|
||||
|
||||
void MaterialYamlEntry::addToTree(std::map<QString, Material*>* materialMap)
|
||||
{
|
||||
std::set<QString> exclude;
|
||||
exclude.insert(QString::fromStdString("General"));
|
||||
exclude.insert(QString::fromStdString("Inherits"));
|
||||
|
||||
auto yamlModel = getModel();
|
||||
auto library = getLibrary();
|
||||
auto name = getName();
|
||||
auto directory = getDirectory();
|
||||
QString uuid = getUUID();
|
||||
|
||||
QString authorAndLicense = yamlValue(yamlModel["General"], "AuthorAndLicense", "");
|
||||
QString description = yamlValue(yamlModel["General"], "Description", "");
|
||||
|
||||
Material* finalModel = new Material(library, directory, uuid, name);
|
||||
finalModel->setAuthorAndLicense(authorAndLicense);
|
||||
finalModel->setDescription(description);
|
||||
|
||||
// Add inheritance list
|
||||
if (yamlModel["Inherits"]) {
|
||||
auto inherits = yamlModel["Inherits"];
|
||||
for (auto it = inherits.begin(); it != inherits.end(); it++) {
|
||||
std::string nodeName = it->second["UUID"].as<std::string>();
|
||||
|
||||
finalModel->setParentUUID(
|
||||
QString::fromStdString(nodeName));// Should only be one. Need to check
|
||||
}
|
||||
}
|
||||
|
||||
// Add material models
|
||||
if (yamlModel["Models"]) {
|
||||
auto models = yamlModel["Models"];
|
||||
for (auto it = models.begin(); it != models.end(); it++) {
|
||||
std::string modelName = (it->first).as<std::string>();
|
||||
|
||||
// Add the model uuid
|
||||
auto modelNode = models[modelName];
|
||||
std::string modelUUID = modelNode["UUID"].as<std::string>();
|
||||
finalModel->addPhysical(QString::fromStdString(modelUUID));
|
||||
|
||||
// Add the property values
|
||||
auto properties = yamlModel["Models"][modelName];
|
||||
for (auto itp = properties.begin(); itp != properties.end(); itp++) {
|
||||
std::string propertyName = (itp->first).as<std::string>();
|
||||
std::string propertyValue = (itp->second).as<std::string>();
|
||||
|
||||
if (finalModel->hasPhysicalProperty(QString::fromStdString(propertyName))) {
|
||||
finalModel->setPhysicalValue(QString::fromStdString(propertyName),
|
||||
QString::fromStdString(propertyValue));
|
||||
}
|
||||
else if (propertyName != "UUID") {
|
||||
Base::Console().Log("\tProperty '%s' is not described by any model. Ignored\n",
|
||||
propertyName.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add appearance models
|
||||
if (yamlModel["AppearanceModels"]) {
|
||||
auto models = yamlModel["AppearanceModels"];
|
||||
for (auto it = models.begin(); it != models.end(); it++) {
|
||||
std::string modelName = (it->first).as<std::string>();
|
||||
|
||||
// Add the model uuid
|
||||
auto modelNode = models[modelName];
|
||||
std::string modelUUID = modelNode["UUID"].as<std::string>();
|
||||
finalModel->addAppearance(QString::fromStdString(modelUUID));
|
||||
|
||||
// Add the property values
|
||||
auto properties = yamlModel["AppearanceModels"][modelName];
|
||||
for (auto itp = properties.begin(); itp != properties.end(); itp++) {
|
||||
std::string propertyName = (itp->first).as<std::string>();
|
||||
std::string propertyValue = (itp->second).as<std::string>();
|
||||
|
||||
if (finalModel->hasAppearanceProperty(QString::fromStdString(propertyName))) {
|
||||
finalModel->setAppearanceValue(QString::fromStdString(propertyName),
|
||||
QString::fromStdString(propertyValue));
|
||||
}
|
||||
else if (propertyName != "UUID") {
|
||||
Base::Console().Log("\tProperty '%s' is not described by any model. Ignored\n",
|
||||
propertyName.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QString path = QDir(directory).absolutePath();
|
||||
// Base::Console().Log("\tPath '%s'\n", path.toStdString().c_str());
|
||||
(*materialMap)[uuid] = library.addMaterial(*finalModel, path);
|
||||
}
|
||||
|
||||
std::map<QString, MaterialEntry*>* MaterialLoader::_materialEntryMap = nullptr;
|
||||
|
||||
MaterialLoader::MaterialLoader(std::map<QString, Material*>* materialMap,
|
||||
std::list<MaterialLibrary*>* libraryList)
|
||||
: _materialMap(materialMap)
|
||||
, _libraryList(libraryList)
|
||||
{
|
||||
loadLibraries();
|
||||
}
|
||||
|
||||
/*
|
||||
* Destroys the object and frees any allocated resources
|
||||
*/
|
||||
MaterialLoader::~MaterialLoader()
|
||||
{}
|
||||
|
||||
void MaterialLoader::addLibrary(MaterialLibrary* model)
|
||||
{
|
||||
_libraryList->push_back(model);
|
||||
}
|
||||
|
||||
MaterialEntry* MaterialLoader::getMaterialFromPath(MaterialLibrary& library,
|
||||
const QString& path) const
|
||||
{
|
||||
MaterialEntry* 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);
|
||||
if (material) {
|
||||
(*_materialMap)[material->getUUID()] = library.addMaterial(*material, path);
|
||||
}
|
||||
|
||||
// Return the nullptr as there are no intermediate steps to take, such
|
||||
// as checking inheritance
|
||||
return model;
|
||||
}
|
||||
|
||||
YAML::Node yamlroot;
|
||||
try {
|
||||
yamlroot = YAML::LoadFile(pathName);
|
||||
|
||||
const std::string uuid = yamlroot["General"]["UUID"].as<std::string>();
|
||||
// Always get the name from the filename
|
||||
// QString name = QString::fromStdString(yamlroot["General"]["Name"].as<std::string>());
|
||||
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);
|
||||
}
|
||||
catch (YAML::Exception const& e) {
|
||||
Base::Console().Error("YAML parsing error: '%s'\n", pathName.c_str());
|
||||
Base::Console().Error("\t'%s'\n", e.what());
|
||||
showYaml(yamlroot);
|
||||
}
|
||||
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
void MaterialLoader::showYaml(const YAML::Node& yaml)
|
||||
{
|
||||
std::stringstream out;
|
||||
|
||||
out << yaml;
|
||||
std::string logData = out.str();
|
||||
Base::Console().Log("%s\n", logData.c_str());
|
||||
}
|
||||
|
||||
|
||||
void MaterialLoader::dereference(Material* material)
|
||||
{
|
||||
// Avoid recursion
|
||||
if (material->getDereferenced()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Base::Console().Log("Dereferencing material '%s'.\n",
|
||||
// material->getName().toStdString().c_str());
|
||||
|
||||
auto parentUUID = material->getParentUUID();
|
||||
if (parentUUID.size() > 0) {
|
||||
Material* parent;
|
||||
try {
|
||||
parent = (*_materialMap)[parentUUID];
|
||||
}
|
||||
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());
|
||||
}
|
||||
|
||||
// Ensure the parent has been dereferenced
|
||||
dereference(parent);
|
||||
|
||||
// Add physical models
|
||||
auto modelVector = parent->getPhysicalModels();
|
||||
for (auto model = modelVector->begin(); model != modelVector->end(); model++) {
|
||||
if (!material->hasPhysicalModel(*model)) {
|
||||
material->addPhysical(*model);
|
||||
}
|
||||
}
|
||||
|
||||
// Add appearance models
|
||||
modelVector = parent->getAppearanceModels();
|
||||
for (auto model = modelVector->begin(); model != modelVector->end(); model++) {
|
||||
if (!material->hasAppearanceModel(*model)) {
|
||||
material->addAppearance(*model);
|
||||
}
|
||||
}
|
||||
|
||||
// Add values
|
||||
auto properties = parent->getPhysicalProperties();
|
||||
for (auto itp = properties.begin(); itp != properties.end(); itp++) {
|
||||
auto name = itp->first;
|
||||
auto property = static_cast<const MaterialProperty>(itp->second);
|
||||
|
||||
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<const MaterialProperty>(itp->second);
|
||||
|
||||
if (material->getAppearanceProperty(name).isNull()) {
|
||||
material->getAppearanceProperty(name).setValue(property.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
material->markDereferenced();
|
||||
}
|
||||
|
||||
void MaterialLoader::loadLibrary(MaterialLibrary& library)
|
||||
{
|
||||
if (_materialEntryMap == nullptr) {
|
||||
_materialEntryMap = new std::map<QString, MaterialEntry*>();
|
||||
}
|
||||
|
||||
QDirIterator it(library.getDirectory(), QDirIterator::Subdirectories);
|
||||
while (it.hasNext()) {
|
||||
auto pathname = it.next();
|
||||
QFileInfo file(pathname);
|
||||
if (file.isFile()) {
|
||||
if (file.suffix().toStdString() == "FCMat") {
|
||||
QString libraryName = file.baseName();
|
||||
|
||||
auto model = getMaterialFromPath(library, file.canonicalFilePath());
|
||||
if (model) {
|
||||
(*_materialEntryMap)[model->getUUID()] = model;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (auto it = _materialEntryMap->begin(); it != _materialEntryMap->end(); it++) {
|
||||
it->second->addToTree(_materialMap);
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialLoader::loadLibraries(void)
|
||||
{
|
||||
std::list<MaterialLibrary*>* _libraryList = getMaterialLibraries();
|
||||
if (_libraryList) {
|
||||
for (auto it = _libraryList->begin(); it != _libraryList->end(); it++) {
|
||||
loadLibrary(**it);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto it = _materialMap->begin(); it != _materialMap->end(); it++) {
|
||||
dereference(it->second);
|
||||
}
|
||||
}
|
||||
|
||||
std::list<MaterialLibrary*>* MaterialLoader::getMaterialLibraries()
|
||||
{
|
||||
auto param = App::GetApplication().GetParameterGroupByPath(
|
||||
"User parameter:BaseApp/Preferences/Mod/Material/Resources");
|
||||
bool useBuiltInMaterials = param->GetBool("UseBuiltInMaterials", true);
|
||||
bool useMatFromModules = param->GetBool("UseMaterialsFromWorkbenches", true);
|
||||
bool useMatFromConfigDir = param->GetBool("UseMaterialsFromConfigDir", true);
|
||||
bool useMatFromCustomDir = param->GetBool("UseMaterialsFromCustomDir", true);
|
||||
|
||||
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);
|
||||
_libraryList->push_back(libData);
|
||||
}
|
||||
|
||||
if (useMatFromModules) {
|
||||
auto moduleParam = App::GetApplication().GetParameterGroupByPath(
|
||||
"User parameter:BaseApp/Preferences/Mod/Material/Resources/Modules");
|
||||
for (auto& group : moduleParam->GetGroups()) {
|
||||
// auto module = moduleParam->GetGroup(group->GetGroupName());
|
||||
auto moduleName = QString::fromStdString(group->GetGroupName());
|
||||
auto materialDir = QString::fromStdString(group->GetASCII("ModuleDir", ""));
|
||||
auto materialIcon = QString::fromStdString(group->GetASCII("ModuleIcon", ""));
|
||||
auto materialReadOnly = group->GetBool("ModuleReadOnly", true);
|
||||
|
||||
if (materialDir.length() > 0) {
|
||||
QDir dir(materialDir);
|
||||
if (dir.exists()) {
|
||||
auto libData = new MaterialLibrary(moduleName,
|
||||
materialDir,
|
||||
materialIcon,
|
||||
materialReadOnly);
|
||||
_libraryList->push_back(libData);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (useMatFromConfigDir) {
|
||||
QString resourceDir =
|
||||
QString::fromStdString(App::Application::getUserAppDataDir() + "/Material");
|
||||
if (!resourceDir.isEmpty()) {
|
||||
QDir materialDir(resourceDir);
|
||||
if (materialDir.exists()) {
|
||||
auto libData =
|
||||
new MaterialLibrary(QString::fromStdString("User"),
|
||||
resourceDir,
|
||||
QString::fromStdString(":/icons/preferences-general.svg"),
|
||||
false);
|
||||
_libraryList->push_back(libData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (useMatFromCustomDir) {
|
||||
QString resourceDir = QString::fromStdString(param->GetASCII("CustomMaterialsDir", ""));
|
||||
if (!resourceDir.isEmpty()) {
|
||||
QDir materialDir(resourceDir);
|
||||
if (materialDir.exists()) {
|
||||
auto libData = new MaterialLibrary(QString::fromStdString("Custom"),
|
||||
resourceDir,
|
||||
QString::fromStdString(":/icons/user.svg"),
|
||||
false);
|
||||
_libraryList->push_back(libData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return _libraryList;
|
||||
}
|
||||
|
||||
std::list<QString>* MaterialLoader::getMaterialFolders(const MaterialLibrary& library)
|
||||
{
|
||||
std::list<QString>* pathList = new std::list<QString>();
|
||||
QDirIterator it(library.getDirectory(), QDirIterator::Subdirectories);
|
||||
while (it.hasNext()) {
|
||||
auto pathname = it.next();
|
||||
QFileInfo file(pathname);
|
||||
if (file.isDir()) {
|
||||
QString path = QDir(library.getDirectory()).relativeFilePath(file.absoluteFilePath());
|
||||
if (!path.startsWith(QString::fromStdString("."))) {
|
||||
pathList->push_back(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return pathList;
|
||||
}
|
||||
129
src/Mod/Material/App/MaterialLoader.h
Normal file
129
src/Mod/Material/App/MaterialLoader.h
Normal file
@@ -0,0 +1,129 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2023 David Carter <dcarter@david.carter.ca> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef MATERIAL_MATERIALLOADER_H
|
||||
#define MATERIAL_MATERIALLOADER_H
|
||||
|
||||
#include <QDir>
|
||||
#include <QString>
|
||||
#include <yaml-cpp/yaml.h>
|
||||
|
||||
#include "Materials.h"
|
||||
#include "trim.h"
|
||||
|
||||
namespace Materials
|
||||
{
|
||||
|
||||
class MaterialEntry
|
||||
{
|
||||
public:
|
||||
MaterialEntry();
|
||||
explicit MaterialEntry(const MaterialLibrary& library,
|
||||
const QString& modelName,
|
||||
const QString& dir,
|
||||
const QString& modelUuid);
|
||||
virtual ~MaterialEntry() = default;
|
||||
|
||||
virtual void addToTree(std::map<QString, Material*>* materialMap) = 0;
|
||||
|
||||
const MaterialLibrary& getLibrary() const
|
||||
{
|
||||
return _library;
|
||||
}
|
||||
const QString getName() const
|
||||
{
|
||||
return _name;
|
||||
}
|
||||
const QString getDirectory() const
|
||||
{
|
||||
return _directory;
|
||||
}
|
||||
const QString getUUID() const
|
||||
{
|
||||
return _uuid;
|
||||
}
|
||||
|
||||
protected:
|
||||
MaterialLibrary _library;
|
||||
QString _name;
|
||||
QString _directory;
|
||||
QString _uuid;
|
||||
};
|
||||
|
||||
class MaterialYamlEntry: public MaterialEntry
|
||||
{
|
||||
public:
|
||||
explicit MaterialYamlEntry(const MaterialLibrary& library,
|
||||
const QString& modelName,
|
||||
const QString& dir,
|
||||
const QString& modelUuid,
|
||||
const YAML::Node& modelData);
|
||||
~MaterialYamlEntry() override = default;
|
||||
|
||||
void addToTree(std::map<QString, Material*>* materialMap) override;
|
||||
|
||||
const YAML::Node& getModel() const
|
||||
{
|
||||
return _model;
|
||||
}
|
||||
YAML::Node* getModelPtr()
|
||||
{
|
||||
return &_model;
|
||||
}
|
||||
|
||||
private:
|
||||
MaterialYamlEntry();
|
||||
|
||||
QString
|
||||
yamlValue(const YAML::Node& node, const std::string& key, const std::string& defaultValue);
|
||||
|
||||
YAML::Node _model;
|
||||
};
|
||||
|
||||
class MaterialLoader
|
||||
{
|
||||
public:
|
||||
explicit MaterialLoader(std::map<QString, Material*>* materialMap,
|
||||
std::list<MaterialLibrary*>* libraryList);
|
||||
virtual ~MaterialLoader();
|
||||
|
||||
std::list<MaterialLibrary*>* getMaterialLibraries();
|
||||
static std::list<QString>* getMaterialFolders(const MaterialLibrary& library);
|
||||
static void showYaml(const YAML::Node& yaml);
|
||||
|
||||
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 loadLibraries(void);
|
||||
static std::map<QString, MaterialEntry*>* _materialEntryMap;
|
||||
std::map<QString, Material*>* _materialMap;
|
||||
std::list<MaterialLibrary*>* _libraryList;
|
||||
};
|
||||
|
||||
}// namespace Materials
|
||||
|
||||
#endif// MATERIAL_MATERIALLOADER_H
|
||||
273
src/Mod/Material/App/MaterialManager.cpp
Normal file
273
src/Mod/Material/App/MaterialManager.cpp
Normal file
@@ -0,0 +1,273 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2023 David Carter <dcarter@david.carter.ca> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "PreCompiled.h"
|
||||
#ifndef _PreComp_
|
||||
#endif
|
||||
|
||||
#include <QMutexLocker>
|
||||
|
||||
#include <App/Application.h>
|
||||
|
||||
#include "Exceptions.h"
|
||||
#include "MaterialLoader.h"
|
||||
#include "MaterialManager.h"
|
||||
#include "ModelManager.h"
|
||||
|
||||
|
||||
using namespace Materials;
|
||||
|
||||
/* TRANSLATOR Material::Materials */
|
||||
|
||||
std::list<MaterialLibrary*>* MaterialManager::_libraryList = nullptr;
|
||||
std::map<QString, Material*>* MaterialManager::_materialMap = nullptr;
|
||||
QMutex MaterialManager::_mutex;
|
||||
|
||||
TYPESYSTEM_SOURCE(Materials::MaterialManager, Base::BaseClass)
|
||||
|
||||
MaterialManager::MaterialManager()
|
||||
{
|
||||
// TODO: Add a mutex or similar
|
||||
initLibraries();
|
||||
}
|
||||
|
||||
void MaterialManager::initLibraries()
|
||||
{
|
||||
QMutexLocker locker(&_mutex);
|
||||
|
||||
if (_materialMap == nullptr) {
|
||||
// Load the models first
|
||||
ModelManager* manager = new ModelManager();
|
||||
Q_UNUSED(manager)
|
||||
|
||||
delete manager;
|
||||
|
||||
_materialMap = new std::map<QString, Material*>();
|
||||
|
||||
if (_libraryList == nullptr) {
|
||||
_libraryList = new std::list<MaterialLibrary*>();
|
||||
}
|
||||
|
||||
// Load the libraries
|
||||
MaterialLoader loader(_materialMap, _libraryList);
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialManager::saveMaterial(MaterialLibrary* library,
|
||||
Material& material,
|
||||
const QString& path,
|
||||
bool saveAsCopy)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
bool MaterialManager::isMaterial(const fs::path& p)
|
||||
{
|
||||
if (!fs::is_regular_file(p)) {
|
||||
return false;
|
||||
}
|
||||
// check file extension
|
||||
if (p.extension() == ".FCMat") {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const Material& MaterialManager::getMaterial(const QString& uuid) const
|
||||
{
|
||||
try {
|
||||
return *(_materialMap->at(uuid));
|
||||
}
|
||||
catch (std::out_of_range& e) {
|
||||
throw MaterialNotFound();
|
||||
}
|
||||
}
|
||||
|
||||
const Material& 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());
|
||||
|
||||
|
||||
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());
|
||||
return library->getMaterialByPath(cleanPath);
|
||||
}
|
||||
}
|
||||
Base::Console().Log("MaterialManager::getMaterialByPath() Library not found for path '%s'\n",
|
||||
cleanPath.toStdString().c_str());
|
||||
|
||||
throw MaterialNotFound();
|
||||
}
|
||||
|
||||
const Material& 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
|
||||
{
|
||||
for (auto library : *_libraryList) {
|
||||
if (library->getName() == name) {
|
||||
return library;
|
||||
}
|
||||
}
|
||||
|
||||
throw LibraryNotFound();
|
||||
}
|
||||
|
||||
std::list<MaterialLibrary*>* MaterialManager::getMaterialLibraries()
|
||||
{
|
||||
if (_libraryList == nullptr) {
|
||||
if (_materialMap == nullptr) {
|
||||
_materialMap = new std::map<QString, Material*>();
|
||||
}
|
||||
_libraryList = new std::list<MaterialLibrary*>();
|
||||
|
||||
// Load the libraries
|
||||
MaterialLoader loader(_materialMap, _libraryList);
|
||||
}
|
||||
return _libraryList;
|
||||
}
|
||||
|
||||
std::map<QString, MaterialTreeNode*>*
|
||||
MaterialManager::getMaterialTree(const MaterialLibrary& library)
|
||||
{
|
||||
std::map<QString, MaterialTreeNode*>* materialTree = new std::map<QString, MaterialTreeNode*>();
|
||||
|
||||
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
|
||||
std::map<QString, MaterialTreeNode*>* 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::map<QString, MaterialTreeNode*>* mapPtr;
|
||||
if (node->count(folderName) == 0) {
|
||||
mapPtr = new std::map<QString, MaterialTreeNode*>();
|
||||
MaterialTreeNode* child = new MaterialTreeNode();
|
||||
child->setFolder(mapPtr);
|
||||
(*node)[folderName] = child;
|
||||
node = mapPtr;
|
||||
}
|
||||
else {
|
||||
node = (*node)[folderName]->getFolder();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::list<QString>* folderList = getMaterialFolders(library);
|
||||
for (auto folder : *folderList) {
|
||||
fs::path path = folder.toStdString();
|
||||
|
||||
// Start at the root
|
||||
std::map<QString, MaterialTreeNode*>* 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::map<QString, MaterialTreeNode*>* mapPtr =
|
||||
new std::map<QString, MaterialTreeNode*>();
|
||||
MaterialTreeNode* child = new MaterialTreeNode();
|
||||
child->setFolder(mapPtr);
|
||||
(*node)[folderName] = child;
|
||||
node = mapPtr;
|
||||
}
|
||||
else {
|
||||
node = (*node)[folderName]->getFolder();
|
||||
}
|
||||
}
|
||||
}
|
||||
delete folderList;
|
||||
|
||||
return materialTree;
|
||||
}
|
||||
|
||||
std::list<QString>* MaterialManager::getMaterialFolders(const MaterialLibrary& library)
|
||||
{
|
||||
return MaterialLoader::getMaterialFolders(library);
|
||||
}
|
||||
|
||||
std::map<QString, Material*>* MaterialManager::materialsWithModel(QString uuid)
|
||||
{
|
||||
std::map<QString, Material*>* dict = new std::map<QString, Material*>();
|
||||
|
||||
for (auto it = _materialMap->begin(); it != _materialMap->end(); it++) {
|
||||
QString key = it->first;
|
||||
Material* material = it->second;
|
||||
|
||||
if (material->hasModel(uuid)) {
|
||||
(*dict)[key] = material;
|
||||
}
|
||||
}
|
||||
|
||||
return dict;
|
||||
}
|
||||
|
||||
std::map<QString, Material*>* MaterialManager::materialsWithModelComplete(QString uuid)
|
||||
{
|
||||
std::map<QString, Material*>* dict = new std::map<QString, Material*>();
|
||||
|
||||
for (auto it = _materialMap->begin(); it != _materialMap->end(); it++) {
|
||||
QString key = it->first;
|
||||
Material* material = it->second;
|
||||
|
||||
if (material->isModelComplete(uuid)) {
|
||||
(*dict)[key] = material;
|
||||
}
|
||||
}
|
||||
|
||||
return dict;
|
||||
}
|
||||
85
src/Mod/Material/App/MaterialManager.h
Normal file
85
src/Mod/Material/App/MaterialManager.h
Normal file
@@ -0,0 +1,85 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2023 David Carter <dcarter@david.carter.ca> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef MATERIAL_MATERIALMANAGER_H
|
||||
#define MATERIAL_MATERIALMANAGER_H
|
||||
|
||||
#include <QMutex>
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
#include "FolderTree.h"
|
||||
#include "Materials.h"
|
||||
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
namespace Materials
|
||||
{
|
||||
|
||||
typedef FolderTreeNode<Material> MaterialTreeNode;
|
||||
|
||||
class MaterialsExport MaterialManager: public Base::BaseClass
|
||||
{
|
||||
TYPESYSTEM_HEADER();
|
||||
|
||||
public:
|
||||
MaterialManager();
|
||||
virtual ~MaterialManager() = default;
|
||||
|
||||
std::map<QString, Material*>* 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;
|
||||
|
||||
// Library management
|
||||
static std::list<MaterialLibrary*>* getMaterialLibraries();
|
||||
std::map<QString, MaterialTreeNode*>* getMaterialTree(const MaterialLibrary& library);
|
||||
std::list<QString>* getMaterialFolders(const MaterialLibrary& library);
|
||||
void createPath(MaterialLibrary* library, const QString& path)
|
||||
{
|
||||
library->createPath(path);
|
||||
}
|
||||
void saveMaterial(MaterialLibrary* library,
|
||||
Material& material,
|
||||
const QString& path,
|
||||
bool saveAsCopy = true);
|
||||
|
||||
static bool isMaterial(const fs::path& p);
|
||||
|
||||
std::map<QString, Material*>* materialsWithModel(QString uuid);
|
||||
std::map<QString, Material*>* materialsWithModelComplete(QString uuid);
|
||||
|
||||
private:
|
||||
static std::list<MaterialLibrary*>* _libraryList;
|
||||
static std::map<QString, Material*>* _materialMap;
|
||||
static QMutex _mutex;
|
||||
|
||||
static void initLibraries();
|
||||
};
|
||||
|
||||
}// namespace Materials
|
||||
|
||||
#endif// MATERIAL_MATERIALMANAGER_H
|
||||
51
src/Mod/Material/App/MaterialManagerPy.xml
Normal file
51
src/Mod/Material/App/MaterialManagerPy.xml
Normal file
@@ -0,0 +1,51 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<GenerateMaterial xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="generateMetaMaterial_Module.xsd">
|
||||
<PythonExport
|
||||
Father="BaseClassPy"
|
||||
Name="MaterialManagerPy"
|
||||
Twin="MaterialManager"
|
||||
TwinPointer="MaterialManager"
|
||||
Include="Mod/Material/App/MaterialManager.h"
|
||||
Namespace="Materials"
|
||||
FatherInclude="Base/BaseClassPy.h"
|
||||
FatherNamespace="Base"
|
||||
Constructor="true"
|
||||
Delete="true">
|
||||
<Documentation>
|
||||
<Author Licence="LGPL" Name="DavidCarter" EMail="dcarter@davidcarter.ca" />
|
||||
<UserDocu>Material descriptions.</UserDocu>
|
||||
</Documentation>
|
||||
<Methode Name="getMaterial">
|
||||
<Documentation>
|
||||
<UserDocu>Get a material object by specifying its UUID</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="getMaterialByPath">
|
||||
<Documentation>
|
||||
<UserDocu>Get a material object by specifying its path and library name</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Attribute Name="MaterialLibraries" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>List of Material libraries.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="MaterialLibraries" Type="List"/>
|
||||
</Attribute>
|
||||
<Attribute Name="Materials" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>List of Materials.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="Materials" Type="Dict"/>
|
||||
</Attribute>
|
||||
<Methode Name="materialsWithModel">
|
||||
<Documentation>
|
||||
<UserDocu>Get a list of materials implementing the specified model</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="materialsWithModelComplete">
|
||||
<Documentation>
|
||||
<UserDocu>Get a list of materials implementing the specified model, with values for all properties</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
</PythonExport>
|
||||
</GenerateMaterial>
|
||||
204
src/Mod/Material/App/MaterialManagerPyImpl.cpp
Normal file
204
src/Mod/Material/App/MaterialManagerPyImpl.cpp
Normal file
@@ -0,0 +1,204 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2008 Werner Mayer <wmayer[at]users.sourceforge.net> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "PreCompiled.h"
|
||||
|
||||
#ifndef _PreComp_
|
||||
#include <boost/uuid/uuid_io.hpp>
|
||||
#endif
|
||||
|
||||
#include "Exceptions.h"
|
||||
#include "MaterialManager.h"
|
||||
#include "MaterialManagerPy.h"
|
||||
#include "MaterialPy.h"
|
||||
#include "Materials.h"
|
||||
|
||||
#include "MaterialManagerPy.cpp"
|
||||
|
||||
using namespace Materials;
|
||||
|
||||
// returns a string which represents the object e.g. when printed in python
|
||||
std::string MaterialManagerPy::representation() const
|
||||
{
|
||||
std::stringstream str;
|
||||
str << "<MaterialManager object at " << getMaterialManagerPtr() << ">";
|
||||
|
||||
return str.str();
|
||||
}
|
||||
|
||||
PyObject* MaterialManagerPy::PyMake(struct _typeobject*, PyObject*, PyObject*)// Python wrapper
|
||||
{
|
||||
// never create such objects with the constructor
|
||||
return new MaterialManagerPy(new MaterialManager());
|
||||
}
|
||||
|
||||
// constructor method
|
||||
int MaterialManagerPy::PyInit(PyObject* /*args*/, PyObject* /*kwd*/)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
PyObject* MaterialManagerPy::getMaterial(PyObject* args)
|
||||
{
|
||||
char* uuid;
|
||||
if (!PyArg_ParseTuple(args, "s", &uuid)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
try {
|
||||
const Material& material =
|
||||
getMaterialManagerPtr()->getMaterial(QString::fromStdString(uuid));
|
||||
return new MaterialPy(new Material(material));
|
||||
}
|
||||
catch (const MaterialNotFound&) {
|
||||
PyErr_SetString(PyExc_LookupError, "Material not found");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
PyObject* MaterialManagerPy::getMaterialByPath(PyObject* args)
|
||||
{
|
||||
char* path;
|
||||
char* lib = "";
|
||||
if (!PyArg_ParseTuple(args, "s|s", &path, &lib)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
QString libPath(QString::fromStdString(lib));
|
||||
if (!libPath.isEmpty()) {
|
||||
try {
|
||||
const Material& material =
|
||||
getMaterialManagerPtr()->getMaterialByPath(QString::fromStdString(path), libPath);
|
||||
return new MaterialPy(new Material(material));
|
||||
}
|
||||
catch (const MaterialNotFound&) {
|
||||
PyErr_SetString(PyExc_LookupError, "Material not found");
|
||||
return nullptr;
|
||||
}
|
||||
catch (const LibraryNotFound&) {
|
||||
PyErr_SetString(PyExc_LookupError, "Library not found");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
const Material& material =
|
||||
getMaterialManagerPtr()->getMaterialByPath(QString::fromStdString(path));
|
||||
return new MaterialPy(new Material(material));
|
||||
}
|
||||
catch (const MaterialNotFound&) {
|
||||
PyErr_SetString(PyExc_LookupError, "Material not found");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
Py::List MaterialManagerPy::getMaterialLibraries() const
|
||||
{
|
||||
std::list<MaterialLibrary*>* libraries = getMaterialManagerPtr()->getMaterialLibraries();
|
||||
Py::List list;
|
||||
|
||||
for (auto it = libraries->begin(); it != libraries->end(); it++) {
|
||||
MaterialLibrary* lib = *it;
|
||||
Py::Tuple libTuple(3);
|
||||
libTuple.setItem(0, Py::String(lib->getName().toStdString()));
|
||||
libTuple.setItem(1, Py::String(lib->getDirectoryPath().toStdString()));
|
||||
libTuple.setItem(2, Py::String(lib->getIconPath().toStdString()));
|
||||
|
||||
list.append(libTuple);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
Py::Dict MaterialManagerPy::getMaterials() const
|
||||
{
|
||||
Py::Dict dict;
|
||||
|
||||
std::map<QString, Material*>* materials = getMaterialManagerPtr()->getMaterials();
|
||||
|
||||
for (auto it = materials->begin(); it != materials->end(); it++) {
|
||||
QString key = it->first;
|
||||
Material* material = it->second;
|
||||
|
||||
PyObject* materialPy = new MaterialPy(new Material(*material));
|
||||
dict.setItem(Py::String(key.toStdString()), Py::Object(materialPy, true));
|
||||
}
|
||||
|
||||
// return Py::new_reference_to(dict);
|
||||
return dict;
|
||||
}
|
||||
|
||||
PyObject* MaterialManagerPy::getCustomAttributes(const char* /*attr*/) const
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int MaterialManagerPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
PyObject* MaterialManagerPy::materialsWithModel(PyObject* args)
|
||||
{
|
||||
char* uuid;
|
||||
if (!PyArg_ParseTuple(args, "s", &uuid)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::map<QString, Material*>* materials =
|
||||
getMaterialManagerPtr()->materialsWithModel(QString::fromStdString(uuid));
|
||||
PyObject* dict = PyDict_New();
|
||||
|
||||
for (auto it = materials->begin(); it != materials->end(); it++) {
|
||||
QString key = it->first;
|
||||
Material* material = it->second;
|
||||
|
||||
PyObject* materialPy = new MaterialPy(new Material(*material));
|
||||
PyDict_SetItem(dict, PyUnicode_FromString(key.toStdString().c_str()), materialPy);
|
||||
}
|
||||
delete materials;
|
||||
|
||||
return dict;
|
||||
}
|
||||
|
||||
PyObject* MaterialManagerPy::materialsWithModelComplete(PyObject* args)
|
||||
{
|
||||
char* uuid;
|
||||
if (!PyArg_ParseTuple(args, "s", &uuid)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::map<QString, Material*>* materials =
|
||||
getMaterialManagerPtr()->materialsWithModelComplete(QString::fromStdString(uuid));
|
||||
PyObject* dict = PyDict_New();
|
||||
|
||||
for (auto it = materials->begin(); it != materials->end(); it++) {
|
||||
QString key = it->first;
|
||||
Material* material = it->second;
|
||||
|
||||
PyObject* materialPy = new MaterialPy(new Material(*material));
|
||||
PyDict_SetItem(dict, PyUnicode_FromString(key.toStdString().c_str()), materialPy);
|
||||
}
|
||||
delete materials;
|
||||
|
||||
return dict;
|
||||
}
|
||||
161
src/Mod/Material/App/MaterialPy.xml
Normal file
161
src/Mod/Material/App/MaterialPy.xml
Normal file
@@ -0,0 +1,161 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<GenerateModel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="generateMetaModel_Module.xsd">
|
||||
<PythonExport
|
||||
Father="BaseClassPy"
|
||||
Name="MaterialPy"
|
||||
Twin="Material"
|
||||
TwinPointer="Material"
|
||||
Include="Mod/Material/App/Materials.h"
|
||||
Namespace="Materials"
|
||||
FatherInclude="Base/BaseClassPy.h"
|
||||
FatherNamespace="Base"
|
||||
Constructor="true"
|
||||
Delete="true">
|
||||
<Documentation>
|
||||
<Author Licence="LGPL" Name="DavidCarter" EMail="dcarter@davidcarter.ca" />
|
||||
<UserDocu>Material descriptions.</UserDocu>
|
||||
</Documentation>
|
||||
<Attribute Name="LibraryName" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>Model library name.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="LibraryName" Type="String"/>
|
||||
</Attribute>
|
||||
<Attribute Name="LibraryRoot" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>Model library path.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="LibraryRoot" Type="String"/>
|
||||
</Attribute>
|
||||
<Attribute Name="LibraryIcon" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>Model icon path.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="LibraryIcon" Type="String"/>
|
||||
</Attribute>
|
||||
<Attribute Name="Name" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>Model name.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="Name" Type="String"/>
|
||||
</Attribute>
|
||||
<Attribute Name="Directory" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>Model directory relative to the library root.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="Directory" Type="String"/>
|
||||
</Attribute>
|
||||
<Attribute Name="UUID" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>Unique model identifier.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="UUID" Type="String"/>
|
||||
</Attribute>
|
||||
<Attribute Name="Description" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>Description of the material.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="Description" Type="String"/>
|
||||
</Attribute>
|
||||
<Attribute Name="URL" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>URL to a material reference.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="URL" Type="String"/>
|
||||
</Attribute>
|
||||
<Attribute Name="Reference" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>Reference for material data.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="Reference" Type="String"/>
|
||||
</Attribute>
|
||||
<Attribute Name="Parent" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>Parent material UUID.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="Parent" Type="String"/>
|
||||
</Attribute>
|
||||
<Attribute Name="AuthorAndLicense" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>Author and license information.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="AuthorAndLicense" Type="String"/>
|
||||
</Attribute>
|
||||
<Attribute Name="PhysicalModels" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>List of implemented models.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="PhysicalModels" Type="List"/>
|
||||
</Attribute>
|
||||
<Attribute Name="AppearanceModels" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>List of implemented models.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="AppearanceModels" Type="List"/>
|
||||
</Attribute>
|
||||
<Attribute Name="Tags" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>List of searchable tags.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="Tags" Type="List"/>
|
||||
</Attribute>
|
||||
<Methode Name="hasPhysicalModel" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>Check if the material implements the physical model with the given UUID</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="hasAppearanceModel" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>Check if the material implements the appearance model with the given UUID</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="isPhysicalModelComplete" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>Check if the material implements the physical model with the given UUID, and has values defined for each property</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="isAppearanceModelComplete" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>Check if the material implements the appearance model with the given UUID, and has values defined for each property</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="hasPhysicalProperty" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>Check if the material implements the physical property with the given name</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="hasAppearanceProperty" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>Check if the material implements the appearance property with the given name</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Attribute Name="Properties" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>deprecated -- Dictionary of all material properties.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="Properties" Type="Dict"/>
|
||||
</Attribute>
|
||||
<Attribute Name="PhysicalProperties" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>deprecated -- Dictionary of material physical properties.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="PhysicalProperties" Type="Dict"/>
|
||||
</Attribute>
|
||||
<Attribute Name="AppearanceProperties" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>deprecated -- Dictionary of material appearance properties.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="AppearanceProperties" Type="Dict"/>
|
||||
</Attribute>
|
||||
<Methode Name="getPhysicalValue" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>Get the value associated with the property</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="getAppearanceValue" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>Get the value associated with the property</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
</PythonExport>
|
||||
</GenerateModel>
|
||||
395
src/Mod/Material/App/MaterialPyImpl.cpp
Normal file
395
src/Mod/Material/App/MaterialPyImpl.cpp
Normal file
@@ -0,0 +1,395 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2008 Werner Mayer <wmayer[at]users.sourceforge.net> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "PreCompiled.h"
|
||||
|
||||
#ifndef _PreComp_
|
||||
#include <boost/uuid/uuid_io.hpp>
|
||||
#endif
|
||||
|
||||
#include <QMetaType>
|
||||
|
||||
#include <Base/Quantity.h>
|
||||
#include <Base/QuantityPy.h>
|
||||
#include <Gui/MetaTypes.h>
|
||||
|
||||
#include "Exceptions.h"
|
||||
#include "MaterialPy.h"
|
||||
#include "Materials.h"
|
||||
|
||||
#include "MaterialPy.cpp"
|
||||
|
||||
using namespace Materials;
|
||||
|
||||
// returns a string which represents the object e.g. when printed in python
|
||||
std::string MaterialPy::representation() const
|
||||
{
|
||||
MaterialPy::PointerType ptr = getMaterialPtr();
|
||||
std::stringstream str;
|
||||
str << "Property [Name=(";
|
||||
str << ptr->getName().toStdString();
|
||||
str << "), UUID=(";
|
||||
str << ptr->getUUID().toStdString();
|
||||
str << "), Library Name=(";
|
||||
str << ptr->getLibrary().getName().toStdString();
|
||||
str << "), Library Root=(";
|
||||
str << ptr->getLibrary().getDirectoryPath().toStdString();
|
||||
str << "), Library Icon=(";
|
||||
str << ptr->getLibrary().getIconPath().toStdString();
|
||||
str << "), Directory=(";
|
||||
str << ptr->getDirectory().toStdString();
|
||||
// str << "), URL=(";
|
||||
// str << ptr->getURL();
|
||||
// str << "), DOI=(";
|
||||
// str << ptr->getDOI();
|
||||
// str << "), Description=(";
|
||||
// str << ptr->getDescription();
|
||||
// str << "), Inherits=[";
|
||||
// const std::vector<std::string> &inherited = getMaterialPtr()->getInheritance();
|
||||
// for (auto it = inherited.begin(); it != inherited.end(); it++)
|
||||
// {
|
||||
// std::string uuid = *it;
|
||||
// if (it != inherited.begin())
|
||||
// str << "), UUID=(";
|
||||
// else
|
||||
// str << "UUID=(";
|
||||
// str << uuid << ")";
|
||||
// }
|
||||
// str << "]]";
|
||||
str << ")]";
|
||||
|
||||
return str.str();
|
||||
}
|
||||
|
||||
PyObject* MaterialPy::PyMake(struct _typeobject*, PyObject*, PyObject*)// Python wrapper
|
||||
{
|
||||
// never create such objects with the constructor
|
||||
return new MaterialPy(new Material());
|
||||
}
|
||||
|
||||
// constructor method
|
||||
int MaterialPy::PyInit(PyObject* /*args*/, PyObject* /*kwd*/)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
Py::String MaterialPy::getLibraryName() const
|
||||
{
|
||||
return Py::String(getMaterialPtr()->getLibrary().getName().toStdString());
|
||||
}
|
||||
|
||||
Py::String MaterialPy::getLibraryRoot() const
|
||||
{
|
||||
return Py::String(getMaterialPtr()->getLibrary().getDirectoryPath().toStdString());
|
||||
}
|
||||
|
||||
Py::String MaterialPy::getLibraryIcon() const
|
||||
{
|
||||
return Py::String(getMaterialPtr()->getLibrary().getIconPath().toStdString());
|
||||
}
|
||||
|
||||
Py::String MaterialPy::getName() const
|
||||
{
|
||||
return Py::String(getMaterialPtr()->getName().toStdString());
|
||||
}
|
||||
|
||||
Py::String MaterialPy::getDirectory() const
|
||||
{
|
||||
return Py::String(getMaterialPtr()->getDirectory().toStdString());
|
||||
}
|
||||
|
||||
Py::String MaterialPy::getUUID() const
|
||||
{
|
||||
return Py::String(getMaterialPtr()->getUUID().toStdString());
|
||||
}
|
||||
|
||||
Py::String MaterialPy::getDescription() const
|
||||
{
|
||||
return Py::String(getMaterialPtr()->getDescription().toStdString());
|
||||
}
|
||||
|
||||
Py::String MaterialPy::getURL() const
|
||||
{
|
||||
return Py::String(getMaterialPtr()->getURL().toStdString());
|
||||
}
|
||||
|
||||
Py::String MaterialPy::getReference() const
|
||||
{
|
||||
return Py::String(getMaterialPtr()->getReference().toStdString());
|
||||
}
|
||||
|
||||
Py::String MaterialPy::getParent() const
|
||||
{
|
||||
return Py::String(getMaterialPtr()->getParentUUID().toStdString());
|
||||
}
|
||||
|
||||
Py::String MaterialPy::getAuthorAndLicense() const
|
||||
{
|
||||
return Py::String(getMaterialPtr()->getAuthorAndLicense().toStdString());
|
||||
}
|
||||
|
||||
Py::List MaterialPy::getPhysicalModels() const
|
||||
{
|
||||
const std::vector<QString>* models = getMaterialPtr()->getPhysicalModels();
|
||||
Py::List list;
|
||||
|
||||
for (auto it = models->begin(); it != models->end(); it++) {
|
||||
QString uuid = *it;
|
||||
|
||||
list.append(Py::String(uuid.toStdString()));
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
Py::List MaterialPy::getAppearanceModels() const
|
||||
{
|
||||
const std::vector<QString>* models = getMaterialPtr()->getAppearanceModels();
|
||||
Py::List list;
|
||||
|
||||
for (auto it = models->begin(); it != models->end(); it++) {
|
||||
QString uuid = *it;
|
||||
|
||||
list.append(Py::String(uuid.toStdString()));
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
Py::List MaterialPy::getTags() const
|
||||
{
|
||||
const std::list<QString>& tags = getMaterialPtr()->getTags();
|
||||
Py::List list;
|
||||
|
||||
for (auto it = tags.begin(); it != tags.end(); it++) {
|
||||
QString uuid = *it;
|
||||
|
||||
list.append(Py::String(uuid.toStdString()));
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
PyObject* MaterialPy::getCustomAttributes(const char* /*attr*/) const
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int MaterialPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
PyObject* MaterialPy::hasPhysicalModel(PyObject* args)
|
||||
{
|
||||
char* uuid;
|
||||
if (!PyArg_ParseTuple(args, "s", &uuid)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool hasProperty = getMaterialPtr()->hasPhysicalModel(QString::fromStdString(uuid));
|
||||
return hasProperty ? Py_True : Py_False;
|
||||
}
|
||||
|
||||
PyObject* MaterialPy::hasAppearanceModel(PyObject* args)
|
||||
{
|
||||
char* uuid;
|
||||
if (!PyArg_ParseTuple(args, "s", &uuid)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool hasProperty = getMaterialPtr()->hasAppearanceModel(QString::fromStdString(uuid));
|
||||
return hasProperty ? Py_True : Py_False;
|
||||
}
|
||||
|
||||
PyObject* MaterialPy::isPhysicalModelComplete(PyObject* args)
|
||||
{
|
||||
char* name;
|
||||
if (!PyArg_ParseTuple(args, "s", &name)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool isComplete = getMaterialPtr()->isPhysicalModelComplete(QString::fromStdString(name));
|
||||
return isComplete ? Py_True : Py_False;
|
||||
}
|
||||
|
||||
PyObject* MaterialPy::isAppearanceModelComplete(PyObject* args)
|
||||
{
|
||||
char* name;
|
||||
if (!PyArg_ParseTuple(args, "s", &name)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool isComplete = getMaterialPtr()->isAppearanceModelComplete(QString::fromStdString(name));
|
||||
return isComplete ? Py_True : Py_False;
|
||||
}
|
||||
|
||||
PyObject* MaterialPy::hasPhysicalProperty(PyObject* args)
|
||||
{
|
||||
char* name;
|
||||
if (!PyArg_ParseTuple(args, "s", &name)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool hasProperty = getMaterialPtr()->hasPhysicalProperty(QString::fromStdString(name));
|
||||
return hasProperty ? Py_True : Py_False;
|
||||
}
|
||||
|
||||
PyObject* MaterialPy::hasAppearanceProperty(PyObject* args)
|
||||
{
|
||||
char* name;
|
||||
if (!PyArg_ParseTuple(args, "s", &name)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool hasProperty = getMaterialPtr()->hasAppearanceProperty(QString::fromStdString(name));
|
||||
return hasProperty ? Py_True : Py_False;
|
||||
}
|
||||
|
||||
Py::Dict MaterialPy::getProperties() const
|
||||
{
|
||||
Py::Dict dict;
|
||||
|
||||
// Maintain backwards compatibility
|
||||
dict.setItem(Py::String("CardName"), Py::String(getMaterialPtr()->getName().toStdString()));
|
||||
dict.setItem(Py::String("AuthorAndLicense"),
|
||||
Py::String(getMaterialPtr()->getAuthorAndLicense().toStdString()));
|
||||
dict.setItem(Py::String("Name"), Py::String(getMaterialPtr()->getName().toStdString()));
|
||||
dict.setItem(Py::String("Description"),
|
||||
Py::String(getMaterialPtr()->getDescription().toStdString()));
|
||||
dict.setItem(Py::String("ReferenceSource"),
|
||||
Py::String(getMaterialPtr()->getReference().toStdString()));
|
||||
dict.setItem(Py::String("SourceURL"), Py::String(getMaterialPtr()->getURL().toStdString()));
|
||||
|
||||
auto properties = getMaterialPtr()->getPhysicalProperties();
|
||||
for (auto it = properties.begin(); it != properties.end(); it++) {
|
||||
QString key = it->first;
|
||||
MaterialProperty& materialProperty = it->second;
|
||||
|
||||
if (!materialProperty.isNull()) {
|
||||
auto value = materialProperty.getString();
|
||||
dict.setItem(Py::String(key.toStdString()), Py::String(value.toStdString()));
|
||||
}
|
||||
}
|
||||
|
||||
properties = getMaterialPtr()->getAppearanceProperties();
|
||||
for (auto it = properties.begin(); it != properties.end(); it++) {
|
||||
QString key = it->first;
|
||||
MaterialProperty& materialProperty = it->second;
|
||||
|
||||
if (!materialProperty.isNull()) {
|
||||
auto value = materialProperty.getString();
|
||||
dict.setItem(Py::String(key.toStdString()), Py::String(value.toStdString()));
|
||||
}
|
||||
}
|
||||
|
||||
return dict;
|
||||
}
|
||||
|
||||
Py::Dict MaterialPy::getPhysicalProperties() const
|
||||
{
|
||||
Py::Dict dict;
|
||||
|
||||
auto properties = getMaterialPtr()->getPhysicalProperties();
|
||||
for (auto it = properties.begin(); it != properties.end(); it++) {
|
||||
QString key = it->first;
|
||||
MaterialProperty& materialProperty = it->second;
|
||||
|
||||
if (!materialProperty.isNull()) {
|
||||
auto value = materialProperty.getString();
|
||||
dict.setItem(Py::String(key.toStdString()), Py::String(value.toStdString()));
|
||||
}
|
||||
}
|
||||
|
||||
return dict;
|
||||
}
|
||||
|
||||
Py::Dict MaterialPy::getAppearanceProperties() const
|
||||
{
|
||||
Py::Dict dict;
|
||||
|
||||
auto properties = getMaterialPtr()->getAppearanceProperties();
|
||||
for (auto it = properties.begin(); it != properties.end(); it++) {
|
||||
QString key = it->first;
|
||||
MaterialProperty& materialProperty = it->second;
|
||||
|
||||
if (!materialProperty.isNull()) {
|
||||
auto value = materialProperty.getString();
|
||||
dict.setItem(Py::String(key.toStdString()), Py::String(value.toStdString()));
|
||||
}
|
||||
}
|
||||
|
||||
return dict;
|
||||
}
|
||||
|
||||
static PyObject* _pyObjectFromVariant(const QVariant& value)
|
||||
{
|
||||
if (value.isNull()) {
|
||||
return new PyObject();
|
||||
}
|
||||
|
||||
if (value.userType() == QMetaType::type("Base::Quantity")) {
|
||||
return new Base::QuantityPy(new Base::Quantity(value.value<Base::Quantity>()));
|
||||
}
|
||||
else if (value.userType() == QMetaType::Double) {
|
||||
return PyFloat_FromDouble(value.toDouble());
|
||||
}
|
||||
else if (value.userType() == QMetaType::Float) {
|
||||
return PyFloat_FromDouble(value.toFloat());
|
||||
}
|
||||
else if (value.userType() == QMetaType::Int) {
|
||||
return PyLong_FromLong(value.toInt());
|
||||
}
|
||||
else if (value.userType() == QMetaType::Long) {
|
||||
return PyLong_FromLong(value.toInt());
|
||||
}
|
||||
else if (value.userType() == QMetaType::Bool) {
|
||||
return value.toBool() ? Py_True : Py_False;
|
||||
}
|
||||
else if (value.userType() == QMetaType::QString) {
|
||||
return PyUnicode_FromString(value.toString().toStdString().c_str());
|
||||
}
|
||||
|
||||
throw UnknownValueType();
|
||||
}
|
||||
|
||||
PyObject* MaterialPy::getPhysicalValue(PyObject* args)
|
||||
{
|
||||
char* name;
|
||||
if (!PyArg_ParseTuple(args, "s", &name)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
QVariant value = getMaterialPtr()->getPhysicalValue(QString::fromStdString(name));
|
||||
return _pyObjectFromVariant(value);
|
||||
}
|
||||
|
||||
PyObject* MaterialPy::getAppearanceValue(PyObject* args)
|
||||
{
|
||||
char* name;
|
||||
if (!PyArg_ParseTuple(args, "s", &name)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
QVariant value = getMaterialPtr()->getAppearanceValue(QString::fromStdString(name));
|
||||
return _pyObjectFromVariant(value);
|
||||
}
|
||||
243
src/Mod/Material/App/MaterialValue.cpp
Normal file
243
src/Mod/Material/App/MaterialValue.cpp
Normal file
@@ -0,0 +1,243 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2023 David Carter <dcarter@david.carter.ca> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "PreCompiled.h"
|
||||
#ifndef _PreComp_
|
||||
#endif
|
||||
|
||||
#include <App/Application.h>
|
||||
|
||||
#include "Exceptions.h"
|
||||
#include "MaterialValue.h"
|
||||
|
||||
|
||||
using namespace Materials;
|
||||
|
||||
/* TRANSLATOR Material::MaterialValue */
|
||||
|
||||
MaterialValue::MaterialValue()
|
||||
: _valueType(None)
|
||||
{}
|
||||
|
||||
MaterialValue::MaterialValue(ValueType type)
|
||||
: _valueType(type)
|
||||
{}
|
||||
|
||||
//===
|
||||
|
||||
Material2DArray::Material2DArray()
|
||||
: MaterialValue(Array2D)
|
||||
, _defaultSet(false)
|
||||
{}
|
||||
|
||||
MaterialValue Material2DArray::getDefault() const
|
||||
{
|
||||
MaterialValue ret(_valueType);
|
||||
ret.setValue(_value);
|
||||
return ret;
|
||||
}
|
||||
|
||||
const std::vector<QVariant>* Material2DArray::getRow(int row) const
|
||||
{
|
||||
try {
|
||||
return _rows.at(row);
|
||||
}
|
||||
catch (std::out_of_range const&) {
|
||||
throw InvalidRow();
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<QVariant>* Material2DArray::getRow(int row)
|
||||
{
|
||||
try {
|
||||
return _rows.at(row);
|
||||
}
|
||||
catch (std::out_of_range const&) {
|
||||
throw InvalidRow();
|
||||
}
|
||||
}
|
||||
|
||||
void Material2DArray::addRow(std::vector<QVariant>* row)
|
||||
{
|
||||
_rows.push_back(row);
|
||||
}
|
||||
|
||||
void Material2DArray::insertRow(int index, std::vector<QVariant>* row)
|
||||
{
|
||||
_rows.insert(_rows.begin() + index, row);
|
||||
}
|
||||
|
||||
void Material2DArray::deleteRow(int row)
|
||||
{
|
||||
if (static_cast<std::size_t>(row) >= _rows.size() || row < 0) {
|
||||
throw InvalidRow();
|
||||
}
|
||||
_rows.erase(_rows.begin() + row);
|
||||
}
|
||||
|
||||
void Material2DArray::setValue(int row, int column, const QVariant& value)
|
||||
{
|
||||
if (row >= rows()) {
|
||||
throw InvalidIndex();
|
||||
}
|
||||
|
||||
std::vector<QVariant>* val = getRow(row);
|
||||
try {
|
||||
val->at(column) = value;
|
||||
}
|
||||
catch (const std::out_of_range&) {
|
||||
throw InvalidIndex();
|
||||
}
|
||||
}
|
||||
|
||||
const QVariant Material2DArray::getValue(int row, int column)
|
||||
{
|
||||
try {
|
||||
auto val = getRow(row);
|
||||
try {
|
||||
return val->at(column);
|
||||
}
|
||||
catch (std::out_of_range const&) {
|
||||
throw InvalidIndex();
|
||||
}
|
||||
}
|
||||
catch (const InvalidRow&) {
|
||||
throw InvalidIndex();
|
||||
}
|
||||
}
|
||||
|
||||
void Material2DArray::dumpRow(const std::vector<QVariant>& row) const
|
||||
{
|
||||
Base::Console().Log("row: ");
|
||||
for (auto column : row) {
|
||||
Base::Console().Log("'%s' ", column.toString().toStdString().c_str());
|
||||
}
|
||||
Base::Console().Log("\n");
|
||||
}
|
||||
|
||||
void Material2DArray::dump() const
|
||||
{
|
||||
for (auto row : _rows) {
|
||||
dumpRow(*row);
|
||||
}
|
||||
}
|
||||
|
||||
//===
|
||||
|
||||
Material3DArray::Material3DArray()
|
||||
: MaterialValue(Array3D)
|
||||
, _defaultSet(false)
|
||||
{}
|
||||
|
||||
MaterialValue Material3DArray::getDefault() const
|
||||
{
|
||||
MaterialValue ret(_valueType);
|
||||
ret.setValue(_value);
|
||||
return ret;
|
||||
}
|
||||
|
||||
const std::vector<std::vector<QVariant>*>& Material3DArray::getTable(const QVariant& depth) const
|
||||
{
|
||||
try {
|
||||
return _rowMap.at(depth);
|
||||
}
|
||||
catch (std::out_of_range const&) {
|
||||
throw InvalidRow();
|
||||
}
|
||||
}
|
||||
|
||||
const std::vector<QVariant>& Material3DArray::getRow(const QVariant& depth, int row) const
|
||||
{
|
||||
try {
|
||||
return *(_rowMap.at(depth).at(row));
|
||||
}
|
||||
catch (std::out_of_range const&) {
|
||||
throw InvalidRow();
|
||||
}
|
||||
}
|
||||
|
||||
const std::vector<QVariant>& Material3DArray::getRow(int row) const
|
||||
{
|
||||
return getRow(getDefault().getValue().toString(), row);
|
||||
}
|
||||
|
||||
std::vector<QVariant>& Material3DArray::getRow(const QVariant& depth, int row)
|
||||
{
|
||||
try {
|
||||
return *(_rowMap.at(depth).at(row));
|
||||
}
|
||||
catch (std::out_of_range const&) {
|
||||
throw InvalidRow();
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<QVariant>& Material3DArray::getRow(int row)
|
||||
{
|
||||
return getRow(getDefault().getValue().toString(), row);
|
||||
}
|
||||
|
||||
void Material3DArray::addRow(const QVariant& depth, std::vector<QVariant>* row)
|
||||
{
|
||||
_rowMap[depth].push_back(row);
|
||||
}
|
||||
|
||||
void Material3DArray::deleteRow(const QVariant& depth, int row)
|
||||
{
|
||||
Q_UNUSED(depth)
|
||||
Q_UNUSED(row)
|
||||
}
|
||||
|
||||
void Material3DArray::deleteRows(int depth)
|
||||
{
|
||||
Q_UNUSED(depth)
|
||||
}
|
||||
|
||||
void Material3DArray::setValue(const QVariant& depth, int row, int column, const QVariant& value)
|
||||
{
|
||||
Q_UNUSED(depth)
|
||||
Q_UNUSED(row)
|
||||
Q_UNUSED(column)
|
||||
Q_UNUSED(value)
|
||||
}
|
||||
|
||||
void Material3DArray::setValue(int row, int column, const QVariant& value)
|
||||
{
|
||||
Q_UNUSED(row)
|
||||
Q_UNUSED(column)
|
||||
Q_UNUSED(value)
|
||||
}
|
||||
|
||||
const QVariant Material3DArray::getValue(const QVariant& depth, int row, int column)
|
||||
{
|
||||
auto val = getRow(depth, row);
|
||||
try {
|
||||
return val.at(column);
|
||||
}
|
||||
catch (std::out_of_range const&) {
|
||||
throw InvalidColumn();
|
||||
}
|
||||
}
|
||||
|
||||
const QVariant Material3DArray::getValue(int row, int column)
|
||||
{
|
||||
return getValue(getDefault().getValue().toString(), row, column);
|
||||
}
|
||||
187
src/Mod/Material/App/MaterialValue.h
Normal file
187
src/Mod/Material/App/MaterialValue.h
Normal file
@@ -0,0 +1,187 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2023 David Carter <dcarter@david.carter.ca> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef MATERIAL_MATERIALVALUE_H
|
||||
#define MATERIAL_MATERIALVALUE_H
|
||||
|
||||
#include <QVariant>
|
||||
|
||||
namespace Materials
|
||||
{
|
||||
|
||||
class MaterialsExport MaterialValue
|
||||
{
|
||||
public:
|
||||
enum ValueType
|
||||
{
|
||||
None = 0,
|
||||
String = 1,
|
||||
Boolean = 2,
|
||||
Integer = 3,
|
||||
Float = 4,
|
||||
Quantity = 5,
|
||||
Distribution = 6,
|
||||
List = 7,
|
||||
Array2D = 8,
|
||||
Array3D = 9,
|
||||
Color = 10,
|
||||
Image = 11,
|
||||
File = 12,
|
||||
URL = 13
|
||||
};
|
||||
MaterialValue();
|
||||
explicit MaterialValue(ValueType type);
|
||||
virtual ~MaterialValue() = default;
|
||||
|
||||
ValueType getType()
|
||||
{
|
||||
return _valueType;
|
||||
}
|
||||
|
||||
const QVariant getValue(void) const
|
||||
{
|
||||
return _value;
|
||||
}
|
||||
bool isNull() const
|
||||
{
|
||||
return _value.isNull();
|
||||
}
|
||||
virtual const QVariant getValueAt(const QVariant& value) const
|
||||
{
|
||||
Q_UNUSED(value);
|
||||
return _value;
|
||||
}
|
||||
void setValue(const QVariant& value)
|
||||
{
|
||||
_value = value;
|
||||
}
|
||||
|
||||
protected:
|
||||
ValueType _valueType;
|
||||
QVariant _value;
|
||||
|
||||
void setType(ValueType type)
|
||||
{
|
||||
_valueType = type;
|
||||
}
|
||||
};
|
||||
|
||||
class MaterialsExport Material2DArray: public MaterialValue
|
||||
{
|
||||
public:
|
||||
Material2DArray();
|
||||
~Material2DArray() override = default;
|
||||
|
||||
void setDefault(MaterialValue value)
|
||||
{
|
||||
_value = value.getValue();
|
||||
_defaultSet = true;
|
||||
}
|
||||
void setDefault(const QVariant& value)
|
||||
{
|
||||
_value = value;
|
||||
_defaultSet = true;
|
||||
}
|
||||
MaterialValue getDefault() const;
|
||||
bool defaultSet() const
|
||||
{
|
||||
return _defaultSet;
|
||||
}
|
||||
|
||||
const std::vector<QVariant>* getRow(int row) const;
|
||||
std::vector<QVariant>* getRow(int row);
|
||||
int rows() const
|
||||
{
|
||||
return _rows.size();
|
||||
}
|
||||
void addRow(std::vector<QVariant>* row);
|
||||
void insertRow(int index, std::vector<QVariant>* row);
|
||||
void deleteRow(int row);
|
||||
|
||||
void setValue(int row, int column, const QVariant& value);
|
||||
const QVariant getValue(int row, int column);
|
||||
|
||||
protected:
|
||||
std::vector<std::vector<QVariant>*> _rows;
|
||||
bool _defaultSet;
|
||||
|
||||
private:
|
||||
void dumpRow(const std::vector<QVariant>& row) const;
|
||||
void dump() const;
|
||||
};
|
||||
|
||||
class MaterialsExport Material3DArray: public MaterialValue
|
||||
{
|
||||
public:
|
||||
Material3DArray();
|
||||
~Material3DArray() override = default;
|
||||
|
||||
void setDefault(MaterialValue value)
|
||||
{
|
||||
_value = value.getValue();
|
||||
_defaultSet = true;
|
||||
}
|
||||
void setDefault(const QVariant& value)
|
||||
{
|
||||
_value = value;
|
||||
_defaultSet = true;
|
||||
}
|
||||
MaterialValue getDefault() const;
|
||||
bool defaultSet() const
|
||||
{
|
||||
return _defaultSet;
|
||||
}
|
||||
|
||||
const std::vector<std::vector<QVariant>*>& getTable(const QVariant& depth) const;
|
||||
const std::vector<QVariant>& getRow(const QVariant& depth, int row) const;
|
||||
const std::vector<QVariant>& getRow(int row) const;
|
||||
std::vector<QVariant>& getRow(const QVariant& depth, int row);
|
||||
std::vector<QVariant>& getRow(int row);
|
||||
void addRow(const QVariant& depth, std::vector<QVariant>* row);
|
||||
void deleteRow(const QVariant& depth, int row);
|
||||
void deleteRows(int depth);
|
||||
int depth() const
|
||||
{
|
||||
return _rowMap.size();
|
||||
}
|
||||
int rows(const QVariant& depth) const
|
||||
{
|
||||
return getTable(depth).size();
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
protected:
|
||||
std::map<QVariant, std::vector<std::vector<QVariant>*>> _rowMap;
|
||||
bool _defaultSet;
|
||||
};
|
||||
|
||||
}// namespace Materials
|
||||
|
||||
Q_DECLARE_METATYPE(Materials::MaterialValue)
|
||||
Q_DECLARE_METATYPE(Materials::Material2DArray)
|
||||
Q_DECLARE_METATYPE(Materials::Material3DArray)
|
||||
|
||||
#endif// MATERIAL_MATERIALVALUE_H
|
||||
914
src/Mod/Material/App/Materials.cpp
Normal file
914
src/Mod/Material/App/Materials.cpp
Normal file
@@ -0,0 +1,914 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2023 David Carter <dcarter@david.carter.ca> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "PreCompiled.h"
|
||||
#ifndef _PreComp_
|
||||
#endif
|
||||
|
||||
#include <QMetaType>
|
||||
#include <QUuid>
|
||||
|
||||
#include <App/Application.h>
|
||||
#include <Gui/MetaTypes.h>
|
||||
|
||||
#include "MaterialManager.h"
|
||||
#include "Materials.h"
|
||||
#include "ModelManager.h"
|
||||
|
||||
|
||||
using namespace Materials;
|
||||
|
||||
/* TRANSLATOR Material::Materials */
|
||||
|
||||
TYPESYSTEM_SOURCE(Materials::MaterialProperty, Materials::ModelProperty)
|
||||
|
||||
MaterialProperty::MaterialProperty()
|
||||
{
|
||||
_valuePtr = new MaterialValue(MaterialValue::None);
|
||||
}
|
||||
|
||||
MaterialProperty::MaterialProperty(const ModelProperty& property)
|
||||
: ModelProperty(property)
|
||||
, _valuePtr(nullptr)
|
||||
{
|
||||
setType(getPropertyType());
|
||||
auto columns = property.getColumns();
|
||||
for (std::vector<ModelProperty>::const_iterator it = columns.begin(); it != columns.end();
|
||||
it++) {
|
||||
MaterialProperty prop(*it);
|
||||
addColumn(prop);
|
||||
}
|
||||
|
||||
if (_valuePtr->getType() == MaterialValue::Array2D) {
|
||||
reinterpret_cast<Material2DArray*>(_valuePtr)->setDefault(getColumnNull(0));
|
||||
}
|
||||
else if (_valuePtr->getType() == MaterialValue::Array3D) {
|
||||
reinterpret_cast<Material3DArray*>(_valuePtr)->setDefault(getColumnNull(0));
|
||||
}
|
||||
}
|
||||
|
||||
MaterialProperty::MaterialProperty(const MaterialProperty& other)
|
||||
: ModelProperty(other)
|
||||
{
|
||||
_modelUUID = other._modelUUID;
|
||||
if (other._valuePtr != nullptr) {
|
||||
_valuePtr = new MaterialValue(*(other._valuePtr));
|
||||
}
|
||||
else {
|
||||
_valuePtr = nullptr;
|
||||
}
|
||||
|
||||
for (auto it = other._columns.begin(); it != other._columns.end(); it++) {
|
||||
_columns.push_back(*it);
|
||||
}
|
||||
}
|
||||
|
||||
MaterialProperty::~MaterialProperty()
|
||||
{}
|
||||
|
||||
void MaterialProperty::setModelUUID(const QString& uuid)
|
||||
{
|
||||
_modelUUID = uuid;
|
||||
}
|
||||
|
||||
const QVariant MaterialProperty::getValue(void) const
|
||||
{
|
||||
return _valuePtr->getValue();
|
||||
}
|
||||
|
||||
MaterialValue* MaterialProperty::getMaterialValue(void)
|
||||
{
|
||||
return _valuePtr;
|
||||
}
|
||||
|
||||
const QString MaterialProperty::getString(void) const
|
||||
{
|
||||
if (getType() == MaterialValue::Quantity) {
|
||||
Base::Quantity quantity = getValue().value<Base::Quantity>();
|
||||
return quantity.getUserString();
|
||||
}
|
||||
return getValue().toString();
|
||||
}
|
||||
|
||||
void MaterialProperty::setPropertyType(const QString& type)
|
||||
{
|
||||
ModelProperty::setPropertyType(type);
|
||||
setType(type);
|
||||
}
|
||||
|
||||
void MaterialProperty::setType(const QString& type)
|
||||
{
|
||||
if (_valuePtr) {
|
||||
delete _valuePtr;
|
||||
}
|
||||
|
||||
if (type == QString::fromStdString("String")) {
|
||||
_valuePtr = new MaterialValue(MaterialValue::String);
|
||||
}
|
||||
else if (type == QString::fromStdString("Boolean")) {
|
||||
_valuePtr = new MaterialValue(MaterialValue::Boolean);
|
||||
}
|
||||
else if (type == QString::fromStdString("Integer")) {
|
||||
_valuePtr = new MaterialValue(MaterialValue::Integer);
|
||||
}
|
||||
else if (type == QString::fromStdString("Float")) {
|
||||
_valuePtr = new MaterialValue(MaterialValue::Float);
|
||||
}
|
||||
else if (type == QString::fromStdString("URL")) {
|
||||
_valuePtr = new MaterialValue(MaterialValue::URL);
|
||||
}
|
||||
else if (type == QString::fromStdString("Quantity")) {
|
||||
_valuePtr = new MaterialValue(MaterialValue::Quantity);
|
||||
}
|
||||
else if (type == QString::fromStdString("Color")) {
|
||||
_valuePtr = new MaterialValue(MaterialValue::Color);
|
||||
}
|
||||
else if (type == QString::fromStdString("File")) {
|
||||
_valuePtr = new MaterialValue(MaterialValue::File);
|
||||
}
|
||||
else if (type == QString::fromStdString("Image")) {
|
||||
_valuePtr = new MaterialValue(MaterialValue::Image);
|
||||
}
|
||||
else if (type == QString::fromStdString("List")) {
|
||||
_valuePtr = new MaterialValue(MaterialValue::List);
|
||||
}
|
||||
else if (type == QString::fromStdString("2DArray")) {
|
||||
_valuePtr = new Material2DArray();
|
||||
}
|
||||
else if (type == QString::fromStdString("3DArray")) {
|
||||
_valuePtr = new Material3DArray();
|
||||
}
|
||||
else {
|
||||
// Error. Throw something
|
||||
_valuePtr = new MaterialValue(MaterialValue::None);
|
||||
std::string stringType = type.toStdString();
|
||||
std::string name = getName().toStdString();
|
||||
throw UnknownValueType();
|
||||
}
|
||||
}
|
||||
|
||||
MaterialProperty& MaterialProperty::getColumn(int column)
|
||||
{
|
||||
try {
|
||||
return _columns.at(column);
|
||||
}
|
||||
catch (std::out_of_range const&) {
|
||||
throw InvalidColumn();
|
||||
}
|
||||
}
|
||||
|
||||
MaterialValue::ValueType MaterialProperty::getColumnType(int column) const
|
||||
{
|
||||
try {
|
||||
return _columns.at(column).getType();
|
||||
}
|
||||
catch (std::out_of_range const&) {
|
||||
throw InvalidColumn();
|
||||
}
|
||||
}
|
||||
|
||||
QString MaterialProperty::getColumnUnits(int column) const
|
||||
{
|
||||
try {
|
||||
return _columns.at(column).getUnits();
|
||||
}
|
||||
catch (std::out_of_range const&) {
|
||||
throw InvalidColumn();
|
||||
}
|
||||
}
|
||||
|
||||
QVariant MaterialProperty::getColumnNull(int column) const
|
||||
{
|
||||
MaterialValue::ValueType valueType = getColumnType(column);
|
||||
|
||||
switch (valueType) {
|
||||
case MaterialValue::Quantity: {
|
||||
Base::Quantity q = Base::Quantity(0, getColumnUnits(column));
|
||||
return QVariant::fromValue(q);
|
||||
}
|
||||
|
||||
case MaterialValue::Float:
|
||||
case MaterialValue::Integer:
|
||||
return QVariant(0);
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return QVariant(QString());
|
||||
}
|
||||
|
||||
void MaterialProperty::setValue(const QVariant& value)
|
||||
{
|
||||
// _valueType = MaterialValue::String;
|
||||
_valuePtr->setValue(value);
|
||||
}
|
||||
|
||||
void MaterialProperty::setValue(const QString& value)
|
||||
{
|
||||
if (_valuePtr->getType() == MaterialValue::Boolean) {
|
||||
setBoolean(value);
|
||||
}
|
||||
else if (_valuePtr->getType() == MaterialValue::Integer) {
|
||||
setInt(value);
|
||||
}
|
||||
else if (_valuePtr->getType() == MaterialValue::Float) {
|
||||
setFloat(value);
|
||||
}
|
||||
else if (_valuePtr->getType() == MaterialValue::URL) {
|
||||
setURL(value);
|
||||
}
|
||||
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());
|
||||
// Save as a string
|
||||
setString(value);
|
||||
}
|
||||
}
|
||||
else {
|
||||
setString(value);
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialProperty::setString(const QString& value)
|
||||
{
|
||||
// _valueType = MaterialValue::String;
|
||||
_valuePtr->setValue(QVariant(value));
|
||||
}
|
||||
|
||||
void MaterialProperty::setBoolean(bool value)
|
||||
{
|
||||
// _valueType = MaterialValue::Boolean;
|
||||
_valuePtr->setValue(QVariant(value));
|
||||
}
|
||||
|
||||
void MaterialProperty::setBoolean(int value)
|
||||
{
|
||||
// _valueType = MaterialValue::Boolean;
|
||||
_valuePtr->setValue(QVariant(value != 0));
|
||||
}
|
||||
|
||||
void MaterialProperty::setBoolean(const QString& value)
|
||||
{
|
||||
// _valueType = MaterialValue::Boolean;
|
||||
bool boolean;
|
||||
std::string val = value.toStdString();
|
||||
if ((val == "true") || (val == "True")) {
|
||||
boolean = true;
|
||||
}
|
||||
else if ((val == "false") || (val == "False")) {
|
||||
boolean = false;
|
||||
}
|
||||
else {
|
||||
boolean = (std::stoi(val) != 0);
|
||||
}
|
||||
|
||||
setBoolean(boolean);
|
||||
}
|
||||
|
||||
void MaterialProperty::setInt(int value)
|
||||
{
|
||||
_valuePtr->setValue(QVariant(value));
|
||||
}
|
||||
|
||||
void MaterialProperty::setInt(const QString& value)
|
||||
{
|
||||
_valuePtr->setValue(value.toInt());
|
||||
}
|
||||
|
||||
void MaterialProperty::setFloat(double value)
|
||||
{
|
||||
_valuePtr->setValue(QVariant(value));
|
||||
}
|
||||
|
||||
void MaterialProperty::setFloat(const QString& value)
|
||||
{
|
||||
_valuePtr->setValue(QVariant(value.toFloat()));
|
||||
}
|
||||
|
||||
void MaterialProperty::setQuantity(const Base::Quantity& value)
|
||||
{
|
||||
_valuePtr->setValue(QVariant(QVariant::fromValue(value)));
|
||||
}
|
||||
|
||||
void MaterialProperty::setQuantity(double value, const QString& units)
|
||||
{
|
||||
setQuantity(Base::Quantity(value, units));
|
||||
}
|
||||
|
||||
void MaterialProperty::setQuantity(const QString& value)
|
||||
{
|
||||
setQuantity(Base::Quantity::parse(value));
|
||||
}
|
||||
|
||||
void MaterialProperty::setURL(const QString& value)
|
||||
{
|
||||
_valuePtr->setValue(QVariant(value));
|
||||
}
|
||||
|
||||
MaterialProperty& MaterialProperty::operator=(const MaterialProperty& other)
|
||||
{
|
||||
if (this == &other) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
ModelProperty::operator=(other);
|
||||
_modelUUID = other._modelUUID;
|
||||
delete _valuePtr;
|
||||
if (other._valuePtr != nullptr) {
|
||||
_valuePtr = new MaterialValue(*(other._valuePtr));
|
||||
}
|
||||
else {
|
||||
_valuePtr = nullptr;
|
||||
}
|
||||
|
||||
_columns.clear();
|
||||
for (auto it = other._columns.begin(); it != other._columns.end(); it++) {
|
||||
_columns.push_back(*it);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
TYPESYSTEM_SOURCE(Materials::Material, Base::BaseClass)
|
||||
|
||||
Material::Material()
|
||||
: _dereferenced(false)
|
||||
{}
|
||||
|
||||
Material::Material(const MaterialLibrary& library,
|
||||
const QString& directory,
|
||||
const QString& uuid,
|
||||
const QString& name)
|
||||
: _library(library)
|
||||
, _uuid(uuid)
|
||||
, _name(name)
|
||||
, _dereferenced(false)
|
||||
, _editState(ModelEdit_None)
|
||||
{
|
||||
setDirectory(directory);
|
||||
}
|
||||
|
||||
Material::Material(const Material& other)
|
||||
: _library(other._library)
|
||||
, _directory(other._directory)
|
||||
, _uuid(other._uuid)
|
||||
, _name(other._name)
|
||||
, _authorAndLicense(other._authorAndLicense)
|
||||
, _parentUuid(other._parentUuid)
|
||||
, _description(other._description)
|
||||
, _url(other._url)
|
||||
, _reference(other._reference)
|
||||
, _dereferenced(other._dereferenced)
|
||||
, _editState(other._editState)
|
||||
{
|
||||
for (auto it = other._tags.begin(); it != other._tags.end(); it++) {
|
||||
_tags.push_back(*it);
|
||||
}
|
||||
for (auto it = other._physicalUuids.begin(); it != other._physicalUuids.end(); it++) {
|
||||
_physicalUuids.push_back(*it);
|
||||
}
|
||||
for (auto it = other._appearanceUuids.begin(); it != other._appearanceUuids.end(); it++) {
|
||||
_appearanceUuids.push_back(*it);
|
||||
}
|
||||
for (auto it = other._allUuids.begin(); it != other._allUuids.end(); it++) {
|
||||
_allUuids.push_back(*it);
|
||||
}
|
||||
for (auto it = other._physical.begin(); it != other._physical.end(); it++) {
|
||||
_physical[it->first] = MaterialProperty(it->second);
|
||||
}
|
||||
for (auto it = other._appearance.begin(); it != other._appearance.end(); it++) {
|
||||
_appearance[it->first] = MaterialProperty(it->second);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Destroys the object and frees any allocated resources
|
||||
*/
|
||||
Material::~Material()
|
||||
{
|
||||
// no need to delete child widgets, Qt does it all for us
|
||||
}
|
||||
|
||||
void Material::addModel(const QString& uuid)
|
||||
{
|
||||
for (QString modelUUID : _allUuids) {
|
||||
if (modelUUID == uuid) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
_allUuids.push_back(uuid);
|
||||
|
||||
ModelManager manager;
|
||||
|
||||
try {
|
||||
const Model& model = manager.getModel(uuid);
|
||||
auto inheritance = model.getInheritance();
|
||||
for (auto inherits = inheritance.begin(); inherits != inheritance.end(); inherits++) {
|
||||
addModel(*inherits);
|
||||
}
|
||||
}
|
||||
catch (ModelNotFound const&) {
|
||||
}
|
||||
}
|
||||
|
||||
void Material::setEditState(ModelEdit newState)
|
||||
{
|
||||
if (newState == ModelEdit_Extend) {
|
||||
if (_editState != ModelEdit_Alter) {
|
||||
_editState = newState;
|
||||
}
|
||||
}
|
||||
else if (newState == ModelEdit_Alter) {
|
||||
_editState = newState;
|
||||
}
|
||||
}
|
||||
|
||||
void Material::addPhysical(const QString& uuid)
|
||||
{
|
||||
if (hasPhysicalModel(uuid)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ModelManager manager;
|
||||
|
||||
try {
|
||||
const Model& model = manager.getModel(uuid);
|
||||
|
||||
_physicalUuids.push_back(uuid);
|
||||
addModel(uuid);
|
||||
setEditStateExtend();
|
||||
|
||||
for (auto it = model.begin(); it != model.end(); it++) {
|
||||
QString propertyName = it->first;
|
||||
ModelProperty property = static_cast<ModelProperty>(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());
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (ModelNotFound const&) {
|
||||
}
|
||||
}
|
||||
|
||||
void Material::addAppearance(const QString& uuid)
|
||||
{
|
||||
if (hasAppearanceModel(uuid)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ModelManager manager;
|
||||
|
||||
try {
|
||||
const Model& model = manager.getModel(uuid);
|
||||
|
||||
_appearanceUuids.push_back(uuid);
|
||||
addModel(uuid);
|
||||
setEditStateExtend();
|
||||
|
||||
for (auto it = model.begin(); it != model.end(); it++) {
|
||||
QString propertyName = it->first;
|
||||
ModelProperty property = static_cast<ModelProperty>(it->second);
|
||||
|
||||
_appearance[propertyName] = MaterialProperty(property);
|
||||
}
|
||||
}
|
||||
catch (ModelNotFound const&) {
|
||||
}
|
||||
}
|
||||
|
||||
void Material::setPhysicalEditState(const QString& name)
|
||||
{
|
||||
if (getPhysicalProperty(name).isNull()) {
|
||||
setEditStateExtend();
|
||||
}
|
||||
else {
|
||||
setEditStateAlter();
|
||||
}
|
||||
}
|
||||
|
||||
void Material::setAppearanceEditState(const QString& name)
|
||||
{
|
||||
if (getAppearanceProperty(name).isNull()) {
|
||||
setEditStateExtend();
|
||||
}
|
||||
else {
|
||||
setEditStateAlter();
|
||||
}
|
||||
}
|
||||
|
||||
void Material::setPhysicalValue(const QString& name, const QString& value)
|
||||
{
|
||||
setPhysicalEditState(name);
|
||||
|
||||
_physical[name].setValue(value);// may not be a string type
|
||||
}
|
||||
|
||||
void Material::setPhysicalValue(const QString& name, int value)
|
||||
{
|
||||
setPhysicalEditState(name);
|
||||
|
||||
_physical[name].setInt(value);
|
||||
}
|
||||
|
||||
void Material::setPhysicalValue(const QString& name, double value)
|
||||
{
|
||||
setPhysicalEditState(name);
|
||||
|
||||
_physical[name].setFloat(value);
|
||||
}
|
||||
|
||||
void Material::setPhysicalValue(const QString& name, const Base::Quantity value)
|
||||
{
|
||||
setPhysicalEditState(name);
|
||||
|
||||
_physical[name].setQuantity(value);
|
||||
}
|
||||
|
||||
void Material::setAppearanceValue(const QString& name, const QString& value)
|
||||
{
|
||||
setAppearanceEditState(name);
|
||||
|
||||
_appearance[name].setValue(value);// may not be a string type
|
||||
}
|
||||
|
||||
MaterialProperty& Material::getPhysicalProperty(const QString& name)
|
||||
{
|
||||
try {
|
||||
return _physical.at(name);
|
||||
}
|
||||
catch (std::out_of_range const&) {
|
||||
throw PropertyNotFound();
|
||||
}
|
||||
}
|
||||
|
||||
const MaterialProperty& Material::getPhysicalProperty(const QString& name) const
|
||||
{
|
||||
try {
|
||||
return _physical.at(name);
|
||||
}
|
||||
catch (std::out_of_range const&) {
|
||||
throw PropertyNotFound();
|
||||
}
|
||||
}
|
||||
|
||||
MaterialProperty& Material::getAppearanceProperty(const QString& name)
|
||||
{
|
||||
try {
|
||||
return _appearance.at(name);
|
||||
}
|
||||
catch (std::out_of_range const&) {
|
||||
throw PropertyNotFound();
|
||||
}
|
||||
}
|
||||
|
||||
const MaterialProperty& Material::getAppearanceProperty(const QString& name) const
|
||||
{
|
||||
try {
|
||||
return _appearance.at(name);
|
||||
}
|
||||
catch (std::out_of_range const&) {
|
||||
throw PropertyNotFound();
|
||||
}
|
||||
}
|
||||
|
||||
const QVariant Material::getValue(const std::map<QString, MaterialProperty>& propertyList,
|
||||
const QString& name) const
|
||||
{
|
||||
try {
|
||||
return propertyList.at(name).getValue();
|
||||
}
|
||||
catch (std::out_of_range const&) {
|
||||
throw PropertyNotFound();
|
||||
}
|
||||
}
|
||||
|
||||
const QString Material::getValueString(const std::map<QString, MaterialProperty>& propertyList,
|
||||
const QString& name) const
|
||||
{
|
||||
try {
|
||||
if (propertyList.at(name).getType() == MaterialValue::Quantity) {
|
||||
auto value = propertyList.at(name).getValue();
|
||||
if (value.isNull()) {
|
||||
return QString();
|
||||
}
|
||||
return value.value<Base::Quantity>().getUserString();
|
||||
}
|
||||
return propertyList.at(name).getValue().toString();
|
||||
}
|
||||
catch (std::out_of_range const&) {
|
||||
throw PropertyNotFound();
|
||||
}
|
||||
}
|
||||
|
||||
const QVariant Material::getPhysicalValue(const QString& name) const
|
||||
{
|
||||
return getValue(_physical, name);
|
||||
}
|
||||
|
||||
const QString Material::getPhysicalValueString(const QString& name) const
|
||||
{
|
||||
return getValueString(_physical, name);
|
||||
}
|
||||
|
||||
const QVariant Material::getAppearanceValue(const QString& name) const
|
||||
{
|
||||
return getValue(_appearance, name);
|
||||
}
|
||||
|
||||
const QString Material::getAppearanceValueString(const QString& name) const
|
||||
{
|
||||
return getValueString(_appearance, name);
|
||||
}
|
||||
|
||||
bool Material::hasPhysicalProperty(const QString& name) const
|
||||
{
|
||||
try {
|
||||
static_cast<void>(_physical.at(name));
|
||||
}
|
||||
catch (std::out_of_range const&) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Material::hasAppearanceProperty(const QString& name) const
|
||||
{
|
||||
try {
|
||||
static_cast<void>(_appearance.at(name));
|
||||
}
|
||||
catch (std::out_of_range const&) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Material::hasModel(const QString& uuid) const
|
||||
{
|
||||
for (QString modelUUID : _allUuids) {
|
||||
if (modelUUID == uuid) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Material::hasPhysicalModel(const QString& uuid) const
|
||||
{
|
||||
if (!hasModel(uuid)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ModelManager manager;
|
||||
|
||||
try {
|
||||
const Model& model = manager.getModel(uuid);
|
||||
if (model.getType() == Model::ModelType_Physical) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (ModelNotFound const&) {
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Material::hasAppearanceModel(const QString& uuid) const
|
||||
{
|
||||
if (!hasModel(uuid)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ModelManager manager;
|
||||
|
||||
try {
|
||||
const Model& model = manager.getModel(uuid);
|
||||
if (model.getType() == Model::ModelType_Appearance) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (ModelNotFound const&) {
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Material::isPhysicalModelComplete(const QString& uuid) const
|
||||
{
|
||||
if (!hasPhysicalModel(uuid)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ModelManager manager;
|
||||
|
||||
try {
|
||||
const Model& model = manager.getModel(uuid);
|
||||
for (auto it = model.begin(); it != model.end(); it++) {
|
||||
QString propertyName = it->first;
|
||||
const MaterialProperty& property = getPhysicalProperty(propertyName);
|
||||
|
||||
if (property.isNull()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (ModelNotFound const&) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Material::isAppearanceModelComplete(const QString& uuid) const
|
||||
{
|
||||
if (!hasAppearanceModel(uuid)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ModelManager manager;
|
||||
|
||||
try {
|
||||
const Model& model = manager.getModel(uuid);
|
||||
for (auto it = model.begin(); it != model.end(); it++) {
|
||||
QString propertyName = it->first;
|
||||
const MaterialProperty& property = getAppearanceProperty(propertyName);
|
||||
|
||||
if (property.isNull()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (ModelNotFound const&) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
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 (!_description.isEmpty()) {
|
||||
stream << " Description: \"" << _description << "\"\n";
|
||||
}
|
||||
if (!_url.isEmpty()) {
|
||||
stream << " SourceURL: \"" << _url << "\"\n";
|
||||
}
|
||||
if (!_reference.isEmpty()) {
|
||||
stream << " ReferenceSource: \"" << _reference << "\"\n";
|
||||
}
|
||||
}
|
||||
|
||||
void Material::saveInherits(QTextStream& stream) const
|
||||
{
|
||||
if (!_parentUuid.isEmpty()) {
|
||||
MaterialManager manager;
|
||||
|
||||
stream << "Inherits:\n";
|
||||
stream << " " << manager.getMaterial(_parentUuid).getName() << ":\n";
|
||||
stream << " UUID: \"" << _parentUuid << "\"\n";
|
||||
}
|
||||
}
|
||||
|
||||
void Material::saveModels(QTextStream& stream) const
|
||||
{
|
||||
if (!_physical.empty()) {
|
||||
ModelManager modelManager;
|
||||
|
||||
stream << "Models:\n";
|
||||
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 (!property.isNull()) {
|
||||
stream << " " << propertyName << ": \""
|
||||
<< getPhysicalValueString(propertyName) << "\"\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Material::saveAppearanceModels(QTextStream& stream) const
|
||||
{
|
||||
if (!_appearance.empty()) {
|
||||
ModelManager modelManager;
|
||||
|
||||
stream << "AppearanceModels:\n";
|
||||
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 (!property.isNull()) {
|
||||
stream << " " << propertyName << ": \""
|
||||
<< getAppearanceValueString(propertyName) << "\"\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Material::newUuid()
|
||||
{
|
||||
_uuid = QUuid::createUuid().toString(QUuid::WithoutBraces);
|
||||
}
|
||||
|
||||
void Material::save(QTextStream& stream, bool saveAsCopy)
|
||||
{
|
||||
Q_UNUSED(saveAsCopy)
|
||||
|
||||
stream << "# File created by FreeCAD\n";
|
||||
saveGeneral(stream);
|
||||
saveInherits(stream);
|
||||
saveModels(stream);
|
||||
saveAppearanceModels(stream);
|
||||
}
|
||||
|
||||
Material& Material::operator=(const Material& other)
|
||||
{
|
||||
if (this == &other) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
_library = other._library;
|
||||
_directory = other._directory;
|
||||
_uuid = other._uuid;
|
||||
_name = other._name;
|
||||
_authorAndLicense = other._authorAndLicense;
|
||||
_parentUuid = other._parentUuid;
|
||||
_description = other._description;
|
||||
_url = other._url;
|
||||
_reference = other._reference;
|
||||
_dereferenced = other._dereferenced;
|
||||
|
||||
_tags.clear();
|
||||
for (auto it = other._tags.begin(); it != other._tags.end(); it++) {
|
||||
_tags.push_back(*it);
|
||||
}
|
||||
_physicalUuids.clear();
|
||||
for (auto it = other._physicalUuids.begin(); it != other._physicalUuids.end(); it++) {
|
||||
_physicalUuids.push_back(*it);
|
||||
}
|
||||
_appearanceUuids.clear();
|
||||
for (auto it = other._appearanceUuids.begin(); it != other._appearanceUuids.end(); it++) {
|
||||
_appearanceUuids.push_back(*it);
|
||||
}
|
||||
_allUuids.clear();
|
||||
for (auto it = other._allUuids.begin(); it != other._allUuids.end(); it++) {
|
||||
_allUuids.push_back(*it);
|
||||
}
|
||||
_physical.clear();
|
||||
for (auto it = other._physical.begin(); it != other._physical.end(); it++) {
|
||||
_physical[it->first] = MaterialProperty(it->second);
|
||||
}
|
||||
_appearance.clear();
|
||||
for (auto it = other._appearance.begin(); it != other._appearance.end(); it++) {
|
||||
_appearance[it->first] = MaterialProperty(it->second);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
334
src/Mod/Material/App/Materials.h
Normal file
334
src/Mod/Material/App/Materials.h
Normal file
@@ -0,0 +1,334 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2023 David Carter <dcarter@david.carter.ca> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef MATERIAL_MATERIALS_H
|
||||
#define MATERIAL_MATERIALS_H
|
||||
|
||||
#include <Base/BaseClass.h>
|
||||
#include <QDir>
|
||||
#include <QString>
|
||||
#include <QTextStream>
|
||||
|
||||
#include <App/Application.h>
|
||||
|
||||
#include "MaterialLibrary.h"
|
||||
#include "Model.h"
|
||||
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
namespace Materials
|
||||
{
|
||||
|
||||
class MaterialsExport MaterialProperty: public ModelProperty
|
||||
{
|
||||
TYPESYSTEM_HEADER_WITH_OVERRIDE();
|
||||
|
||||
public:
|
||||
MaterialProperty();
|
||||
explicit MaterialProperty(const ModelProperty& property);
|
||||
explicit MaterialProperty(const MaterialProperty& property);
|
||||
virtual ~MaterialProperty();
|
||||
|
||||
MaterialValue::ValueType getType(void) const
|
||||
{
|
||||
return _valuePtr->getType();
|
||||
}
|
||||
|
||||
const QString getModelUUID(void) const;
|
||||
const QVariant getValue(void) const;
|
||||
bool isNull() const
|
||||
{
|
||||
return _valuePtr->isNull();
|
||||
}
|
||||
MaterialValue* getMaterialValue(void);
|
||||
const QString getString(void) const;
|
||||
bool getBoolean(void) const;
|
||||
int getInt(void) const;
|
||||
double getFloat(void) const;
|
||||
const Base::Quantity& getQuantity(void) const;
|
||||
const QString getURL(void) const;
|
||||
|
||||
MaterialProperty& getColumn(int column);
|
||||
MaterialValue::ValueType getColumnType(int column) const;
|
||||
QString getColumnUnits(int column) const;
|
||||
QVariant getColumnNull(int column) const;
|
||||
|
||||
void setModelUUID(const QString& uuid);
|
||||
void setPropertyType(const QString& type) override;
|
||||
void setValue(const QVariant& value);
|
||||
void setValue(const QString& value);
|
||||
void setString(const QString& value);
|
||||
void setBoolean(bool value);
|
||||
void setBoolean(int value);
|
||||
void setBoolean(const QString& value);
|
||||
void setInt(int value);
|
||||
void setInt(const QString& value);
|
||||
void setFloat(double value);
|
||||
void setFloat(const QString& value);
|
||||
void setQuantity(const Base::Quantity& value);
|
||||
void setQuantity(double value, const QString& units);
|
||||
void setQuantity(const QString& value);
|
||||
void setURL(const QString& value);
|
||||
|
||||
MaterialProperty& operator=(const MaterialProperty& other);
|
||||
|
||||
protected:
|
||||
void setType(const QString& type);
|
||||
// void setType(MaterialValue::ValueType type) { _valueType = type; }
|
||||
|
||||
void addColumn(MaterialProperty& column)
|
||||
{
|
||||
_columns.push_back(column);
|
||||
}
|
||||
|
||||
private:
|
||||
QString _modelUUID;
|
||||
MaterialValue* _valuePtr;
|
||||
std::vector<MaterialProperty> _columns;
|
||||
};
|
||||
|
||||
class MaterialsExport Material: public Base::BaseClass
|
||||
{
|
||||
TYPESYSTEM_HEADER();
|
||||
|
||||
public:
|
||||
enum ModelEdit
|
||||
{
|
||||
ModelEdit_None, // No change
|
||||
ModelEdit_Alter,// Existing values are changed
|
||||
ModelEdit_Extend// New values added
|
||||
};
|
||||
|
||||
Material();
|
||||
explicit Material(const MaterialLibrary& library,
|
||||
const QString& directory,
|
||||
const QString& uuid,
|
||||
const QString& name);
|
||||
explicit Material(const Material& other);
|
||||
virtual ~Material();
|
||||
|
||||
const MaterialLibrary& getLibrary() const
|
||||
{
|
||||
return _library;
|
||||
}
|
||||
const QString getDirectory() const
|
||||
{
|
||||
return _directory;
|
||||
}
|
||||
const QString getUUID() const
|
||||
{
|
||||
return _uuid;
|
||||
}
|
||||
const QString getName() const
|
||||
{
|
||||
return _name;
|
||||
}
|
||||
const QString getAuthorAndLicense() const
|
||||
{
|
||||
return _authorAndLicense;
|
||||
}
|
||||
const QString getParentUUID() const
|
||||
{
|
||||
return _parentUuid;
|
||||
}
|
||||
const QString getDescription() const
|
||||
{
|
||||
return _description;
|
||||
}
|
||||
const QString getURL() const
|
||||
{
|
||||
return _url;
|
||||
}
|
||||
const QString getReference() const
|
||||
{
|
||||
return _reference;
|
||||
}
|
||||
ModelEdit getEditState() const
|
||||
{
|
||||
return _editState;
|
||||
}
|
||||
const std::list<QString>& getTags() const
|
||||
{
|
||||
return _tags;
|
||||
}
|
||||
const std::vector<QString>* getPhysicalModels() const
|
||||
{
|
||||
return &_physicalUuids;
|
||||
}
|
||||
const std::vector<QString>* getAppearanceModels() const
|
||||
{
|
||||
return &_appearanceUuids;
|
||||
}
|
||||
|
||||
void setLibrary(const MaterialLibrary& 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 setEditState(ModelEdit newState);
|
||||
void setEditStateAlter()
|
||||
{
|
||||
setEditState(ModelEdit_Alter);
|
||||
}
|
||||
void setEditStateExtend()
|
||||
{
|
||||
setEditState(ModelEdit_Extend);
|
||||
}
|
||||
void setPhysicalEditState(const QString& name);
|
||||
void setAppearanceEditState(const QString& name);
|
||||
void resetEditState()
|
||||
{
|
||||
_editState = ModelEdit_None;
|
||||
}
|
||||
void addTag(const QString& tag)
|
||||
{
|
||||
Q_UNUSED(tag);
|
||||
}
|
||||
void removeTag(const QString& tag)
|
||||
{
|
||||
Q_UNUSED(tag);
|
||||
}
|
||||
void addPhysical(const QString& uuid);
|
||||
void addAppearance(const QString& uuid);
|
||||
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 setAppearanceValue(const QString& name, const QString& 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;
|
||||
const QVariant getPhysicalValue(const QString& name) const;
|
||||
const QString getPhysicalValueString(const QString& name) const;
|
||||
const QVariant getAppearanceValue(const QString& name) const;
|
||||
const QString getAppearanceValueString(const QString& name) const;
|
||||
bool hasPhysicalProperty(const QString& name) const;
|
||||
bool hasAppearanceProperty(const QString& name) const;
|
||||
|
||||
// Test if the model is defined, and if values are provided for all properties
|
||||
bool hasModel(const QString& uuid) const;
|
||||
bool hasPhysicalModel(const QString& uuid) const;
|
||||
bool hasAppearanceModel(const QString& uuid) const;
|
||||
bool isModelComplete(const QString& uuid) const
|
||||
{
|
||||
return isPhysicalModelComplete(uuid) || isAppearanceModelComplete(uuid);
|
||||
}
|
||||
bool isPhysicalModelComplete(const QString& uuid) const;
|
||||
bool isAppearanceModelComplete(const QString& uuid) const;
|
||||
|
||||
const std::map<QString, MaterialProperty>& getPhysicalProperties() const
|
||||
{
|
||||
return _physical;
|
||||
}
|
||||
const std::map<QString, MaterialProperty>& getAppearanceProperties() const
|
||||
{
|
||||
return _appearance;
|
||||
}
|
||||
|
||||
bool getDereferenced() const
|
||||
{
|
||||
return _dereferenced;
|
||||
}
|
||||
void markDereferenced()
|
||||
{
|
||||
_dereferenced = true;
|
||||
}
|
||||
|
||||
void save(QTextStream& stream, bool saveAsCopy);
|
||||
|
||||
Material& operator=(const Material& other);
|
||||
|
||||
protected:
|
||||
void addModel(const QString& uuid);
|
||||
|
||||
const QVariant getValue(const std::map<QString, MaterialProperty>& propertyList,
|
||||
const QString& name) const;
|
||||
const QString getValueString(const std::map<QString, MaterialProperty>& propertyList,
|
||||
const QString& name) const;
|
||||
|
||||
void saveGeneral(QTextStream& stream) const;
|
||||
void saveInherits(QTextStream& stream) const;
|
||||
void saveModels(QTextStream& stream) const;
|
||||
void saveAppearanceModels(QTextStream& stream) const;
|
||||
|
||||
private:
|
||||
MaterialLibrary _library;
|
||||
QString _directory;
|
||||
QString _uuid;
|
||||
QString _name;
|
||||
QString _authorAndLicense;
|
||||
QString _parentUuid;
|
||||
QString _description;
|
||||
QString _url;
|
||||
QString _reference;
|
||||
std::list<QString> _tags;
|
||||
std::vector<QString> _physicalUuids;
|
||||
std::vector<QString> _appearanceUuids;
|
||||
std::vector<QString> _allUuids;// Includes inherited models
|
||||
std::map<QString, MaterialProperty> _physical;
|
||||
std::map<QString, MaterialProperty> _appearance;
|
||||
bool _dereferenced;
|
||||
ModelEdit _editState;
|
||||
};
|
||||
|
||||
}// namespace Materials
|
||||
|
||||
Q_DECLARE_METATYPE(Materials::Material*)
|
||||
|
||||
#endif// MATERIAL_MATERIALS_H
|
||||
116
src/Mod/Material/App/Model.cpp
Normal file
116
src/Mod/Material/App/Model.cpp
Normal file
@@ -0,0 +1,116 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2023 David Carter <dcarter@david.carter.ca> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "PreCompiled.h"
|
||||
#ifndef _PreComp_
|
||||
#endif
|
||||
|
||||
#include "Exceptions.h"
|
||||
#include "Model.h"
|
||||
#include "ModelLibrary.h"
|
||||
#include <string>
|
||||
|
||||
|
||||
using namespace Materials;
|
||||
|
||||
TYPESYSTEM_SOURCE(Materials::ModelProperty, Base::BaseClass)
|
||||
|
||||
ModelProperty::ModelProperty()
|
||||
{}
|
||||
|
||||
ModelProperty::ModelProperty(const QString& name,
|
||||
const QString& type,
|
||||
const QString& units,
|
||||
const QString& url,
|
||||
const QString& description)
|
||||
: _name(name)
|
||||
, _propertyType(type)
|
||||
, _units(units)
|
||||
, _url(url)
|
||||
, _description(description)
|
||||
{}
|
||||
|
||||
ModelProperty::ModelProperty(const ModelProperty& other)
|
||||
: _name(other._name)
|
||||
, _propertyType(other._propertyType)
|
||||
, _units(other._units)
|
||||
, _url(other._url)
|
||||
, _description(other._description)
|
||||
, _inheritance(other._inheritance)
|
||||
{
|
||||
for (auto it = other._columns.begin(); it != other._columns.end(); it++) {
|
||||
_columns.push_back(*it);
|
||||
}
|
||||
}
|
||||
|
||||
ModelProperty& ModelProperty::operator=(const ModelProperty& other)
|
||||
{
|
||||
if (this == &other) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
_name = other._name;
|
||||
_propertyType = other._propertyType;
|
||||
_units = other._units;
|
||||
_url = other._url;
|
||||
_description = other._description;
|
||||
_inheritance = other._inheritance;
|
||||
_columns.clear();
|
||||
for (auto it = other._columns.begin(); it != other._columns.end(); it++) {
|
||||
_columns.push_back(*it);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
TYPESYSTEM_SOURCE(Materials::Model, Base::BaseClass)
|
||||
|
||||
Model::Model()
|
||||
{}
|
||||
|
||||
Model::Model(const ModelLibrary& library,
|
||||
ModelType type,
|
||||
const QString& name,
|
||||
const QString& directory,
|
||||
const QString& uuid,
|
||||
const QString& description,
|
||||
const QString& url,
|
||||
const QString& doi)
|
||||
: _library(library)
|
||||
, _type(type)
|
||||
, _name(name)
|
||||
, _directory(directory)
|
||||
, _uuid(uuid)
|
||||
, _description(description)
|
||||
, _url(url)
|
||||
, _doi(doi)
|
||||
{}
|
||||
|
||||
ModelProperty& Model::operator[](const QString& key)
|
||||
{
|
||||
try {
|
||||
return _properties.at(key);
|
||||
}
|
||||
catch (std::out_of_range const&) {
|
||||
throw PropertyNotFound();
|
||||
}
|
||||
}
|
||||
297
src/Mod/Material/App/Model.h
Normal file
297
src/Mod/Material/App/Model.h
Normal file
@@ -0,0 +1,297 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2023 David Carter <dcarter@david.carter.ca> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef MATERIAL_MODEL_H
|
||||
#define MATERIAL_MODEL_H
|
||||
|
||||
#include <Base/BaseClass.h>
|
||||
#include <Base/Quantity.h>
|
||||
#include <QDir>
|
||||
#include <QString>
|
||||
|
||||
#include "MaterialValue.h"
|
||||
#include "ModelLibrary.h"
|
||||
|
||||
namespace Materials
|
||||
{
|
||||
|
||||
class MaterialsExport ModelProperty: public Base::BaseClass
|
||||
{
|
||||
TYPESYSTEM_HEADER();
|
||||
|
||||
public:
|
||||
ModelProperty();
|
||||
explicit ModelProperty(const QString& name,
|
||||
const QString& type,
|
||||
const QString& units,
|
||||
const QString& url,
|
||||
const QString& description);
|
||||
explicit ModelProperty(const ModelProperty& other);
|
||||
virtual ~ModelProperty() = default;
|
||||
|
||||
const QString getName() const
|
||||
{
|
||||
return _name;
|
||||
}
|
||||
const QString getPropertyType() const
|
||||
{
|
||||
return _propertyType;
|
||||
}
|
||||
const QString getUnits() const
|
||||
{
|
||||
return _units;
|
||||
}
|
||||
const QString getURL() const
|
||||
{
|
||||
return _url;
|
||||
}
|
||||
const QString getDescription() const
|
||||
{
|
||||
return _description;
|
||||
}
|
||||
const QString getInheritance() const
|
||||
{
|
||||
return _inheritance;
|
||||
}
|
||||
bool isInherited() const
|
||||
{
|
||||
return (_inheritance.length() > 0);
|
||||
}
|
||||
|
||||
void setName(const QString& name)
|
||||
{
|
||||
_name = name;
|
||||
}
|
||||
virtual void setPropertyType(const QString& type)
|
||||
{
|
||||
_propertyType = type;
|
||||
}
|
||||
void setUnits(const QString& units)
|
||||
{
|
||||
_units = units;
|
||||
}
|
||||
void setURL(const QString& url)
|
||||
{
|
||||
_url = url;
|
||||
}
|
||||
void setDescription(const QString& description)
|
||||
{
|
||||
_description = description;
|
||||
}
|
||||
void setInheritance(const QString& uuid)
|
||||
{
|
||||
_inheritance = uuid;
|
||||
}
|
||||
|
||||
void addColumn(ModelProperty& column)
|
||||
{
|
||||
_columns.push_back(column);
|
||||
}
|
||||
const std::vector<ModelProperty>& getColumns() const
|
||||
{
|
||||
return _columns;
|
||||
}
|
||||
int columns() const
|
||||
{
|
||||
return _columns.size();
|
||||
}
|
||||
|
||||
ModelProperty& operator=(const ModelProperty& other);
|
||||
|
||||
private:
|
||||
QString _name;
|
||||
QString _propertyType;
|
||||
QString _units;
|
||||
QString _url;
|
||||
QString _description;
|
||||
QString _inheritance;
|
||||
std::vector<ModelProperty> _columns;
|
||||
};
|
||||
|
||||
class MaterialsExport Model: public Base::BaseClass
|
||||
{
|
||||
TYPESYSTEM_HEADER();
|
||||
|
||||
public:
|
||||
enum ModelType
|
||||
{
|
||||
ModelType_Physical,
|
||||
ModelType_Appearance
|
||||
};
|
||||
|
||||
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);
|
||||
virtual ~Model() = default;
|
||||
|
||||
const ModelLibrary& getLibrary() const
|
||||
{
|
||||
return _library;
|
||||
}
|
||||
const QString getBase() const
|
||||
{
|
||||
return (_type == ModelType_Physical) ? QString::fromStdString("Model")
|
||||
: QString::fromStdString("AppearanceModel");
|
||||
}
|
||||
const QString getName() const
|
||||
{
|
||||
return _name;
|
||||
}
|
||||
ModelType getType() const
|
||||
{
|
||||
return _type;
|
||||
}
|
||||
const QString getDirectory() const
|
||||
{
|
||||
return _directory;
|
||||
}
|
||||
const QString getDirectoryPath() const
|
||||
{
|
||||
return QDir(_directory).absolutePath();
|
||||
}
|
||||
const QString getRelativePath() const
|
||||
{
|
||||
return QDir(_directory).relativeFilePath(QDir(_directory).absolutePath());
|
||||
}
|
||||
const QString getUUID() const
|
||||
{
|
||||
return _uuid;
|
||||
}
|
||||
const QString getDescription() const
|
||||
{
|
||||
return _description;
|
||||
}
|
||||
const QString getURL() const
|
||||
{
|
||||
return _url;
|
||||
}
|
||||
const QString getDOI() const
|
||||
{
|
||||
return _doi;
|
||||
}
|
||||
|
||||
void setLibrary(const ModelLibrary& library)
|
||||
{
|
||||
_library = library;
|
||||
}
|
||||
void setType(ModelType type)
|
||||
{
|
||||
_type = type;
|
||||
}
|
||||
void setName(const QString& name)
|
||||
{
|
||||
_name = name;
|
||||
}
|
||||
void setDirectory(const QString& directory)
|
||||
{
|
||||
_directory = directory;
|
||||
}
|
||||
void setUUID(const QString& uuid)
|
||||
{
|
||||
_uuid = uuid;
|
||||
}
|
||||
void setDescription(const QString& description)
|
||||
{
|
||||
_description = description;
|
||||
}
|
||||
void setURL(const QString& url)
|
||||
{
|
||||
_url = url;
|
||||
}
|
||||
void setDOI(const QString& doi)
|
||||
{
|
||||
_doi = doi;
|
||||
}
|
||||
|
||||
void addInheritance(const QString& uuid)
|
||||
{
|
||||
_inheritedUuids.push_back(uuid);
|
||||
}
|
||||
const std::vector<QString>& getInheritance() const
|
||||
{
|
||||
return _inheritedUuids;
|
||||
}
|
||||
|
||||
bool operator==(const Model& m) const
|
||||
{
|
||||
return _uuid == m._uuid;
|
||||
}
|
||||
bool operator!=(const Model& m) const
|
||||
{
|
||||
return !operator==(m);
|
||||
}
|
||||
|
||||
ModelProperty& operator[](const QString& key);
|
||||
void addProperty(ModelProperty& property)
|
||||
{
|
||||
_properties[property.getName()] = property;
|
||||
}
|
||||
|
||||
using iterator = typename std::map<QString, ModelProperty>::iterator;
|
||||
using const_iterator = typename std::map<QString, ModelProperty>::const_iterator;
|
||||
iterator begin()
|
||||
{
|
||||
return _properties.begin();
|
||||
}
|
||||
const_iterator begin() const noexcept
|
||||
{
|
||||
return _properties.begin();
|
||||
}
|
||||
iterator end() noexcept
|
||||
{
|
||||
return _properties.end();
|
||||
}
|
||||
const_iterator end() const noexcept
|
||||
{
|
||||
return _properties.end();
|
||||
}
|
||||
const_iterator cbegin() const noexcept
|
||||
{
|
||||
return _properties.cbegin();
|
||||
}
|
||||
const_iterator cend() const noexcept
|
||||
{
|
||||
return _properties.cend();
|
||||
}
|
||||
|
||||
private:
|
||||
ModelLibrary _library;
|
||||
ModelType _type;
|
||||
QString _name;
|
||||
QString _directory;
|
||||
QString _uuid;
|
||||
QString _description;
|
||||
QString _url;
|
||||
QString _doi;
|
||||
std::vector<QString> _inheritedUuids;
|
||||
std::map<QString, ModelProperty> _properties;
|
||||
};
|
||||
|
||||
}// namespace Materials
|
||||
|
||||
#endif// MATERIAL_MODEL_H
|
||||
114
src/Mod/Material/App/ModelLibrary.cpp
Normal file
114
src/Mod/Material/App/ModelLibrary.cpp
Normal file
@@ -0,0 +1,114 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2023 David Carter <dcarter@david.carter.ca> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "PreCompiled.h"
|
||||
#ifndef _PreComp_
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <App/Application.h>
|
||||
|
||||
#include "Exceptions.h"
|
||||
#include "Model.h"
|
||||
#include "ModelLibrary.h"
|
||||
|
||||
|
||||
using namespace Materials;
|
||||
|
||||
TYPESYSTEM_SOURCE(Materials::LibraryBase, Base::BaseClass)
|
||||
|
||||
LibraryBase::LibraryBase(const QString& libraryName, const QString& dir, const QString& icon)
|
||||
: _name(libraryName)
|
||||
, _directory(QDir::cleanPath(dir))
|
||||
, _iconPath(icon)
|
||||
{}
|
||||
|
||||
LibraryBase::LibraryBase()
|
||||
{}
|
||||
|
||||
bool LibraryBase::operator==(const LibraryBase& library) const
|
||||
{
|
||||
return (_name == library._name) && (_directory == library._directory);
|
||||
}
|
||||
|
||||
QString LibraryBase::getLocalPath(const QString& path) const
|
||||
{
|
||||
QString filePath = getDirectoryPath();
|
||||
QString cleanPath = QDir::cleanPath(path);
|
||||
QString prefix = QString::fromStdString("/") + getName();
|
||||
if (cleanPath.startsWith(prefix)) {
|
||||
// Remove the library name from the path
|
||||
filePath += cleanPath.right(cleanPath.length() - prefix.length());
|
||||
}
|
||||
else {
|
||||
filePath += cleanPath;
|
||||
}
|
||||
|
||||
return filePath;
|
||||
}
|
||||
|
||||
QString LibraryBase::getRelativePath(const QString& path) const
|
||||
{
|
||||
QString filePath;
|
||||
QString cleanPath = QDir::cleanPath(path);
|
||||
QString prefix = QString::fromStdString("/") + getName();
|
||||
if (cleanPath.startsWith(prefix)) {
|
||||
// Remove the library name from the path
|
||||
filePath = cleanPath.right(cleanPath.length() - prefix.length());
|
||||
}
|
||||
else {
|
||||
filePath = cleanPath;
|
||||
}
|
||||
|
||||
prefix = getDirectoryPath();
|
||||
if (filePath.startsWith(prefix)) {
|
||||
// Remove the library root from the path
|
||||
filePath = filePath.right(filePath.length() - prefix.length());
|
||||
}
|
||||
|
||||
// Remove any leading '/'
|
||||
if (filePath.startsWith(QString::fromStdString("/"))) {
|
||||
filePath.remove(0, 1);
|
||||
}
|
||||
|
||||
return filePath;
|
||||
}
|
||||
|
||||
TYPESYSTEM_SOURCE(Materials::ModelLibrary, LibraryBase)
|
||||
|
||||
ModelLibrary::ModelLibrary(const QString& libraryName, const QString& dir, const QString& icon)
|
||||
: LibraryBase(libraryName, dir, icon)
|
||||
{}
|
||||
|
||||
ModelLibrary::ModelLibrary()
|
||||
{}
|
||||
|
||||
Model* ModelLibrary::addModel(const Model& model, const QString& path)
|
||||
{
|
||||
QString filePath = getRelativePath(path);
|
||||
Model* newModel = new Model(model);
|
||||
newModel->setLibrary(*this);
|
||||
newModel->setDirectory(filePath);
|
||||
|
||||
return newModel;
|
||||
}
|
||||
100
src/Mod/Material/App/ModelLibrary.h
Normal file
100
src/Mod/Material/App/ModelLibrary.h
Normal file
@@ -0,0 +1,100 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2023 David Carter <dcarter@david.carter.ca> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef MATERIAL_MODELLIBRARY_H
|
||||
#define MATERIAL_MODELLIBRARY_H
|
||||
|
||||
#include <Base/BaseClass.h>
|
||||
#include <Base/Quantity.h>
|
||||
#include <QDir>
|
||||
#include <QString>
|
||||
|
||||
#include "MaterialValue.h"
|
||||
|
||||
namespace Materials
|
||||
{
|
||||
|
||||
class Model;
|
||||
|
||||
class MaterialsExport LibraryBase: public Base::BaseClass
|
||||
{
|
||||
TYPESYSTEM_HEADER();
|
||||
|
||||
public:
|
||||
LibraryBase();
|
||||
explicit LibraryBase(const QString& libraryName, const QString& dir, const QString& icon);
|
||||
virtual ~LibraryBase() = default;
|
||||
|
||||
const QString getName() const
|
||||
{
|
||||
return _name;
|
||||
}
|
||||
const QString getDirectory() const
|
||||
{
|
||||
return _directory;
|
||||
}
|
||||
const QString getDirectoryPath() const
|
||||
{
|
||||
return QDir(_directory).absolutePath();
|
||||
}
|
||||
const QString getIconPath() const
|
||||
{
|
||||
return _iconPath;
|
||||
}
|
||||
bool operator==(const LibraryBase& library) const;
|
||||
bool operator!=(const LibraryBase& library) const
|
||||
{
|
||||
return !operator==(library);
|
||||
}
|
||||
QString getLocalPath(const QString& path) const;
|
||||
QString getRelativePath(const QString& path) const;
|
||||
|
||||
private:
|
||||
QString _name;
|
||||
QString _directory;
|
||||
QString _iconPath;
|
||||
};
|
||||
|
||||
class MaterialsExport ModelLibrary: public LibraryBase
|
||||
{
|
||||
TYPESYSTEM_HEADER();
|
||||
|
||||
public:
|
||||
ModelLibrary();
|
||||
explicit ModelLibrary(const QString& libraryName, const QString& dir, const QString& icon);
|
||||
virtual ~ModelLibrary() = default;
|
||||
|
||||
bool operator==(const ModelLibrary& library) const
|
||||
{
|
||||
return LibraryBase::operator==(library);
|
||||
}
|
||||
bool operator!=(const ModelLibrary& library) const
|
||||
{
|
||||
return !operator==(library);
|
||||
}
|
||||
|
||||
Model* addModel(const Model& model, const QString& path);
|
||||
};
|
||||
|
||||
}// namespace Materials
|
||||
|
||||
#endif// MATERIAL_MODELLIBRARY_H
|
||||
417
src/Mod/Material/App/ModelLoader.cpp
Normal file
417
src/Mod/Material/App/ModelLoader.cpp
Normal file
@@ -0,0 +1,417 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2023 David Carter <dcarter@david.carter.ca> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "PreCompiled.h"
|
||||
#ifndef _PreComp_
|
||||
#include <QString>
|
||||
#endif
|
||||
|
||||
#include <App/Application.h>
|
||||
#include <Base/Interpreter.h>
|
||||
|
||||
#include <QDirIterator>
|
||||
#include <QFileInfo>
|
||||
|
||||
#include "Model.h"
|
||||
#include "ModelLoader.h"
|
||||
#include "ModelManager.h"
|
||||
|
||||
|
||||
using namespace Materials;
|
||||
|
||||
ModelEntry::ModelEntry(const ModelLibrary& library,
|
||||
const QString& baseName,
|
||||
const QString& modelName,
|
||||
const QString& dir,
|
||||
const QString& modelUuid,
|
||||
const YAML::Node& modelData)
|
||||
: _library(library)
|
||||
, _base(baseName)
|
||||
, _name(modelName)
|
||||
, _directory(dir)
|
||||
, _uuid(modelUuid)
|
||||
, _model(modelData)
|
||||
, _dereferenced(false)
|
||||
{}
|
||||
|
||||
std::map<QString, ModelEntry*>* ModelLoader::_modelEntryMap = nullptr;
|
||||
|
||||
ModelLoader::ModelLoader(std::map<QString, Model*>* modelMap, std::list<ModelLibrary*>* libraryList)
|
||||
: _modelMap(modelMap)
|
||||
, _libraryList(libraryList)
|
||||
{
|
||||
loadLibraries();
|
||||
}
|
||||
|
||||
void ModelLoader::addLibrary(ModelLibrary* model)
|
||||
{
|
||||
_libraryList->push_back(model);
|
||||
}
|
||||
|
||||
const QString ModelLoader::getUUIDFromPath(const QString& path)
|
||||
{
|
||||
QFile file(path);
|
||||
if (!file.exists()) {
|
||||
throw ModelNotFound();
|
||||
}
|
||||
|
||||
try {
|
||||
YAML::Node yamlroot = YAML::LoadFile(path.toStdString());
|
||||
std::string base = "Model";
|
||||
if (yamlroot["AppearanceModel"]) {
|
||||
base = "AppearanceModel";
|
||||
}
|
||||
|
||||
const QString uuid = QString::fromStdString(yamlroot[base]["UUID"].as<std::string>());
|
||||
return uuid;
|
||||
}
|
||||
catch (YAML::Exception& ex) {
|
||||
throw ModelNotFound();
|
||||
}
|
||||
}
|
||||
|
||||
ModelEntry* ModelLoader::getModelFromPath(const ModelLibrary& library, const QString& path) const
|
||||
{
|
||||
QFile file(path);
|
||||
if (!file.exists()) {
|
||||
throw ModelNotFound();
|
||||
}
|
||||
|
||||
YAML::Node yamlroot;
|
||||
std::string base = "Model";
|
||||
std::string uuid;
|
||||
std::string name;
|
||||
try {
|
||||
yamlroot = YAML::LoadFile(path.toStdString());
|
||||
if (yamlroot["AppearanceModel"]) {
|
||||
base = "AppearanceModel";
|
||||
}
|
||||
|
||||
uuid = yamlroot[base]["UUID"].as<std::string>();
|
||||
name = yamlroot[base]["Name"].as<std::string>();
|
||||
}
|
||||
catch (YAML::Exception const&) {
|
||||
throw InvalidModel();
|
||||
}
|
||||
|
||||
ModelEntry* model = new ModelEntry(library,
|
||||
QString::fromStdString(base),
|
||||
QString::fromStdString(name),
|
||||
path,
|
||||
QString::fromStdString(uuid),
|
||||
yamlroot);
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
void ModelLoader::showYaml(const YAML::Node& yaml) const
|
||||
{
|
||||
std::stringstream out;
|
||||
|
||||
out << yaml;
|
||||
std::string logData = out.str();
|
||||
Base::Console().Log("%s\n", logData.c_str());
|
||||
}
|
||||
|
||||
void ModelLoader::dereference(const QString& uuid,
|
||||
ModelEntry* parent,
|
||||
const ModelEntry* child,
|
||||
std::map<std::pair<QString, QString>, QString>* inheritances)
|
||||
{
|
||||
auto parentPtr = parent->getModelPtr();
|
||||
auto parentBase = parent->getBase().toStdString();
|
||||
auto childYaml = child->getModel();
|
||||
auto childBase = child->getBase().toStdString();
|
||||
|
||||
std::set<QString> exclude;
|
||||
exclude.insert(QString::fromStdString("Name"));
|
||||
exclude.insert(QString::fromStdString("UUID"));
|
||||
exclude.insert(QString::fromStdString("URL"));
|
||||
exclude.insert(QString::fromStdString("Description"));
|
||||
exclude.insert(QString::fromStdString("DOI"));
|
||||
exclude.insert(QString::fromStdString("Inherits"));
|
||||
|
||||
auto parentProperties = (*parentPtr)[parentBase];
|
||||
auto childProperties = childYaml[childBase];
|
||||
for (auto it = childProperties.begin(); it != childProperties.end(); it++) {
|
||||
std::string name = it->first.as<std::string>();
|
||||
if (exclude.count(QString::fromStdString(name)) == 0) {
|
||||
// showYaml(it->second);
|
||||
if (!parentProperties[name]) {
|
||||
parentProperties[name] = it->second;
|
||||
// parentProperties[name]["Inherits"] = childYaml[childBase]["UUID"];
|
||||
(*inheritances)[std::pair<QString, QString>(uuid, QString::fromStdString(name))] =
|
||||
yamlValue(childYaml[childBase], "UUID", "");
|
||||
}
|
||||
}
|
||||
}
|
||||
// showYaml(*parentPtr);
|
||||
}
|
||||
|
||||
|
||||
void ModelLoader::dereference(ModelEntry* model,
|
||||
std::map<std::pair<QString, QString>, QString>* inheritances)
|
||||
{
|
||||
// Avoid recursion
|
||||
if (model->getDereferenced()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto yamlModel = model->getModel();
|
||||
auto base = model->getBase().toStdString();
|
||||
if (yamlModel[base]["Inherits"]) {
|
||||
auto inherits = yamlModel[base]["Inherits"];
|
||||
for (auto it = inherits.begin(); it != inherits.end(); it++) {
|
||||
QString nodeName = QString::fromStdString((*it)["UUID"].as<std::string>());
|
||||
|
||||
// This requires that all models have already been loaded undereferenced
|
||||
try {
|
||||
const ModelEntry* child = (*_modelEntryMap)[nodeName];
|
||||
dereference(model->getUUID(), model, child, inheritances);
|
||||
}
|
||||
catch (const std::out_of_range& oor) {
|
||||
Base::Console().Log("Unable to find '%s' in model map\n",
|
||||
nodeName.toStdString().c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
model->markDereferenced();
|
||||
}
|
||||
|
||||
QString ModelLoader::yamlValue(const YAML::Node& node,
|
||||
const std::string& key,
|
||||
const std::string& defaultValue)
|
||||
{
|
||||
if (node[key]) {
|
||||
return QString::fromStdString(node[key].as<std::string>());
|
||||
}
|
||||
return QString::fromStdString(defaultValue);
|
||||
}
|
||||
|
||||
void ModelLoader::addToTree(ModelEntry* model,
|
||||
std::map<std::pair<QString, QString>, QString>* inheritances)
|
||||
{
|
||||
std::set<QString> exclude;
|
||||
exclude.insert(QString::fromStdString("Name"));
|
||||
exclude.insert(QString::fromStdString("UUID"));
|
||||
exclude.insert(QString::fromStdString("URL"));
|
||||
exclude.insert(QString::fromStdString("Description"));
|
||||
exclude.insert(QString::fromStdString("DOI"));
|
||||
exclude.insert(QString::fromStdString("Inherits"));
|
||||
|
||||
auto yamlModel = model->getModel();
|
||||
auto library = model->getLibrary();
|
||||
auto base = model->getBase().toStdString();
|
||||
auto name = model->getName();
|
||||
auto directory = model->getDirectory();
|
||||
auto uuid = model->getUUID();
|
||||
|
||||
QString version = yamlValue(yamlModel["General"], "Version", "");
|
||||
|
||||
QString description = yamlValue(yamlModel[base], "Description", "");
|
||||
QString url = yamlValue(yamlModel[base], "URL", "");
|
||||
QString doi = yamlValue(yamlModel[base], "DOI", "");
|
||||
|
||||
Model::ModelType type =
|
||||
(base == "Model") ? Model::ModelType_Physical : Model::ModelType_Appearance;
|
||||
|
||||
Model* finalModel = new Model(library, type, name, directory, uuid, description, url, doi);
|
||||
|
||||
// Add inheritance list
|
||||
if (yamlModel[base]["Inherits"]) {
|
||||
auto inherits = yamlModel[base]["Inherits"];
|
||||
for (auto it = inherits.begin(); it != inherits.end(); it++) {
|
||||
QString nodeName = QString::fromStdString((*it)["UUID"].as<std::string>());
|
||||
|
||||
finalModel->addInheritance(nodeName);
|
||||
}
|
||||
}
|
||||
|
||||
// Add property list
|
||||
auto yamlProperties = yamlModel[base];
|
||||
for (auto it = yamlProperties.begin(); it != yamlProperties.end(); it++) {
|
||||
std::string propName = it->first.as<std::string>();
|
||||
if (exclude.count(QString::fromStdString(propName)) == 0) {
|
||||
// showYaml(it->second);
|
||||
auto yamlProp = yamlProperties[propName];
|
||||
auto propType = yamlValue(yamlProp, "Type", "");
|
||||
auto propUnits = yamlValue(yamlProp, "Units", "");
|
||||
auto propURL = yamlValue(yamlProp, "URL", "");
|
||||
auto propDescription = yamlValue(yamlProp, "Description", "");
|
||||
// auto inherits = yamlValue(yamlProp, "Inherits", "");
|
||||
|
||||
ModelProperty property(QString::fromStdString(propName),
|
||||
propType,
|
||||
propUnits,
|
||||
propURL,
|
||||
propDescription);
|
||||
|
||||
if (propType == QString::fromStdString("2DArray")
|
||||
|| propType == QString::fromStdString("3DArray")) {
|
||||
Base::Console().Log("Reading columns\n");
|
||||
// Read the columns
|
||||
auto cols = yamlProp["Columns"];
|
||||
for (auto col : cols) {
|
||||
std::string colName = col.first.as<std::string>();
|
||||
Base::Console().Log("\tColumns '%s'\n", colName.c_str());
|
||||
|
||||
auto colProp = cols[colName];
|
||||
auto colPropType = yamlValue(colProp, "Type", "");
|
||||
auto colPropUnits = yamlValue(colProp, "Units", "");
|
||||
auto colPropURL = yamlValue(colProp, "URL", "");
|
||||
auto colPropDescription = yamlValue(colProp, "Description", "");
|
||||
ModelProperty colProperty(QString::fromStdString(colName),
|
||||
colPropType,
|
||||
colPropUnits,
|
||||
colPropURL,
|
||||
colPropDescription);
|
||||
|
||||
property.addColumn(colProperty);
|
||||
}
|
||||
}
|
||||
|
||||
auto key = std::pair<QString, QString>(uuid, QString::fromStdString(propName));
|
||||
if (inheritances->count(key) > 0) {
|
||||
property.setInheritance((*inheritances)[key]);
|
||||
}
|
||||
|
||||
finalModel->addProperty(property);
|
||||
}
|
||||
}
|
||||
|
||||
(*_modelMap)[uuid] = library.addModel(*finalModel, directory);
|
||||
}
|
||||
|
||||
void ModelLoader::loadLibrary(const ModelLibrary& library)
|
||||
{
|
||||
if (_modelEntryMap == nullptr) {
|
||||
_modelEntryMap = new std::map<QString, ModelEntry*>();
|
||||
}
|
||||
|
||||
QDirIterator it(library.getDirectory(), QDirIterator::Subdirectories);
|
||||
while (it.hasNext()) {
|
||||
auto pathname = it.next();
|
||||
QFileInfo file(pathname);
|
||||
if (file.isFile()) {
|
||||
if (file.suffix().toStdString() == "yml") {
|
||||
QString libraryName = file.baseName();
|
||||
|
||||
try {
|
||||
auto model = getModelFromPath(library, file.canonicalFilePath());
|
||||
(*_modelEntryMap)[model->getUUID()] = model;
|
||||
// showYaml(model->getModel());
|
||||
}
|
||||
catch (InvalidModel const&) {
|
||||
Base::Console().Log("Invalid model '%s'\n", pathname.toStdString().c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::map<std::pair<QString, QString>, QString>* inheritances =
|
||||
new std::map<std::pair<QString, QString>, QString>();
|
||||
for (auto it = _modelEntryMap->begin(); it != _modelEntryMap->end(); it++) {
|
||||
dereference(it->second, inheritances);
|
||||
}
|
||||
|
||||
for (auto it = _modelEntryMap->begin(); it != _modelEntryMap->end(); it++) {
|
||||
addToTree(it->second, inheritances);
|
||||
}
|
||||
// delete inheritances;
|
||||
}
|
||||
|
||||
void ModelLoader::loadLibraries(void)
|
||||
{
|
||||
getModelLibraries();
|
||||
if (_libraryList) {
|
||||
for (auto it = _libraryList->begin(); it != _libraryList->end(); it++) {
|
||||
loadLibrary(**it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ModelLoader::getModelLibraries()
|
||||
{
|
||||
auto param = App::GetApplication().GetParameterGroupByPath(
|
||||
"User parameter:BaseApp/Preferences/Mod/Material/Resources");
|
||||
bool useBuiltInMaterials = param->GetBool("UseBuiltInMaterials", true);
|
||||
bool useMatFromModules = param->GetBool("UseMaterialsFromWorkbenches", true);
|
||||
bool useMatFromConfigDir = param->GetBool("UseMaterialsFromConfigDir", true);
|
||||
bool useMatFromCustomDir = param->GetBool("UseMaterialsFromCustomDir", true);
|
||||
|
||||
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"));
|
||||
_libraryList->push_back(libData);
|
||||
}
|
||||
|
||||
if (useMatFromModules) {
|
||||
auto moduleParam = App::GetApplication().GetParameterGroupByPath(
|
||||
"User parameter:BaseApp/Preferences/Mod/Material/Resources/Modules");
|
||||
for (auto& group : moduleParam->GetGroups()) {
|
||||
// auto module = moduleParam->GetGroup(group->GetGroupName());
|
||||
auto moduleName = QString::fromStdString(group->GetGroupName());
|
||||
auto modelDir = QString::fromStdString(group->GetASCII("ModuleModelDir", ""));
|
||||
auto modelIcon = QString::fromStdString(group->GetASCII("ModuleIcon", ""));
|
||||
|
||||
if (modelDir.length() > 0) {
|
||||
QDir dir(modelDir);
|
||||
if (dir.exists()) {
|
||||
auto libData = new ModelLibrary(moduleName, modelDir, modelIcon);
|
||||
_libraryList->push_back(libData);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (useMatFromConfigDir) {
|
||||
QString resourceDir =
|
||||
QString::fromStdString(App::Application::getUserAppDataDir() + "/Models");
|
||||
if (!resourceDir.isEmpty()) {
|
||||
QDir materialDir(resourceDir);
|
||||
if (materialDir.exists()) {
|
||||
auto libData =
|
||||
new ModelLibrary(QString::fromStdString("User"),
|
||||
resourceDir,
|
||||
QString::fromStdString(":/icons/preferences-general.svg"));
|
||||
_libraryList->push_back(libData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (useMatFromCustomDir) {
|
||||
QString resourceDir = QString::fromStdString(param->GetASCII("CustomMaterialsDir", ""));
|
||||
if (!resourceDir.isEmpty()) {
|
||||
QDir materialDir(resourceDir);
|
||||
if (materialDir.exists()) {
|
||||
auto libData = new ModelLibrary(QString::fromStdString("Custom"),
|
||||
resourceDir,
|
||||
QString::fromStdString(":/icons/user.svg"));
|
||||
_libraryList->push_back(libData);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
130
src/Mod/Material/App/ModelLoader.h
Normal file
130
src/Mod/Material/App/ModelLoader.h
Normal file
@@ -0,0 +1,130 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2023 David Carter <dcarter@david.carter.ca> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef MATERIAL_MODELLOADER_H
|
||||
#define MATERIAL_MODELLOADER_H
|
||||
|
||||
#include <QDir>
|
||||
#include <QString>
|
||||
#include <yaml-cpp/yaml.h>
|
||||
|
||||
#include "Model.h"
|
||||
|
||||
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);
|
||||
virtual ~ModelEntry() = default;
|
||||
|
||||
const ModelLibrary& getLibrary() const
|
||||
{
|
||||
return _library;
|
||||
}
|
||||
const QString getBase() const
|
||||
{
|
||||
return _base;
|
||||
}
|
||||
const QString getName() const
|
||||
{
|
||||
return _name;
|
||||
}
|
||||
const QString getDirectory() const
|
||||
{
|
||||
return _directory;
|
||||
}
|
||||
const QString getUUID() const
|
||||
{
|
||||
return _uuid;
|
||||
}
|
||||
const YAML::Node& getModel() const
|
||||
{
|
||||
return _model;
|
||||
}
|
||||
YAML::Node* getModelPtr()
|
||||
{
|
||||
return &_model;
|
||||
}
|
||||
bool getDereferenced() const
|
||||
{
|
||||
return _dereferenced;
|
||||
}
|
||||
|
||||
void markDereferenced()
|
||||
{
|
||||
_dereferenced = true;
|
||||
}
|
||||
|
||||
private:
|
||||
ModelEntry();
|
||||
|
||||
ModelLibrary _library;
|
||||
QString _base;
|
||||
QString _name;
|
||||
QString _directory;
|
||||
QString _uuid;
|
||||
YAML::Node _model;
|
||||
bool _dereferenced;
|
||||
};
|
||||
|
||||
class ModelLoader
|
||||
{
|
||||
public:
|
||||
explicit ModelLoader(std::map<QString, Model*>* modelMap,
|
||||
std::list<ModelLibrary*>* libraryList);
|
||||
virtual ~ModelLoader() = default;
|
||||
|
||||
static const QString getUUIDFromPath(const QString& path);
|
||||
|
||||
private:
|
||||
ModelLoader();
|
||||
|
||||
void getModelLibraries();
|
||||
QString
|
||||
yamlValue(const YAML::Node& node, const std::string& key, const std::string& defaultValue);
|
||||
void addToTree(ModelEntry* model, std::map<std::pair<QString, QString>, QString>* inheritances);
|
||||
void showYaml(const YAML::Node& yaml) const;
|
||||
void dereference(const QString& uuid,
|
||||
ModelEntry* parent,
|
||||
const ModelEntry* child,
|
||||
std::map<std::pair<QString, QString>, QString>* inheritances);
|
||||
void dereference(ModelEntry* model,
|
||||
std::map<std::pair<QString, QString>, QString>* inheritances);
|
||||
ModelEntry* getModelFromPath(const ModelLibrary& library, const QString& path) const;
|
||||
void addLibrary(ModelLibrary* model);
|
||||
void loadLibrary(const ModelLibrary& library);
|
||||
void loadLibraries(void);
|
||||
static std::map<QString, ModelEntry*>* _modelEntryMap;
|
||||
std::map<QString, Model*>* _modelMap;
|
||||
std::list<ModelLibrary*>* _libraryList;
|
||||
};
|
||||
|
||||
}// namespace Materials
|
||||
|
||||
#endif// MATERIAL_MODELLOADER_H
|
||||
172
src/Mod/Material/App/ModelManager.cpp
Normal file
172
src/Mod/Material/App/ModelManager.cpp
Normal file
@@ -0,0 +1,172 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2023 David Carter <dcarter@david.carter.ca> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "PreCompiled.h"
|
||||
#ifndef _PreComp_
|
||||
#endif
|
||||
|
||||
#include <QMutexLocker>
|
||||
|
||||
#include <Base/Console.h>
|
||||
|
||||
#include "Model.h"
|
||||
#include "ModelLoader.h"
|
||||
#include "ModelManager.h"
|
||||
|
||||
|
||||
using namespace Materials;
|
||||
|
||||
std::list<ModelLibrary*>* ModelManager::_libraryList = nullptr;
|
||||
std::map<QString, Model*>* ModelManager::_modelMap = nullptr;
|
||||
QMutex ModelManager::_mutex;
|
||||
|
||||
TYPESYSTEM_SOURCE(Materials::ModelManager, Base::BaseClass)
|
||||
|
||||
ModelManager::ModelManager()
|
||||
{
|
||||
initLibraries();
|
||||
}
|
||||
|
||||
void ModelManager::initLibraries()
|
||||
{
|
||||
QMutexLocker locker(&_mutex);
|
||||
|
||||
if (_modelMap == nullptr) {
|
||||
_modelMap = new std::map<QString, Model*>();
|
||||
if (_libraryList == nullptr) {
|
||||
_libraryList = new std::list<ModelLibrary*>();
|
||||
}
|
||||
|
||||
// Load the libraries
|
||||
ModelLoader loader(_modelMap, _libraryList);
|
||||
}
|
||||
}
|
||||
|
||||
bool ModelManager::isModel(const fs::path& p)
|
||||
{
|
||||
// if (!fs::is_regular_file(p))
|
||||
// return false;
|
||||
// check file extension
|
||||
if (p.extension() == ".yml") {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ModelManager::refresh()
|
||||
{
|
||||
_modelMap->clear();
|
||||
_libraryList->clear();
|
||||
|
||||
// Load the libraries
|
||||
ModelLoader loader(_modelMap, _libraryList);
|
||||
}
|
||||
|
||||
const Model& ModelManager::getModel(const QString& uuid) const
|
||||
{
|
||||
try {
|
||||
if (_modelMap == nullptr) {
|
||||
throw Uninitialized();
|
||||
}
|
||||
|
||||
return *(_modelMap->at(uuid));
|
||||
}
|
||||
catch (std::out_of_range const&) {
|
||||
throw ModelNotFound();
|
||||
}
|
||||
}
|
||||
|
||||
const Model& ModelManager::getModelByPath(const QString& path) const
|
||||
{
|
||||
const QString& uuid = ModelLoader::getUUIDFromPath(path);
|
||||
const Model& model = getModel(uuid);
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
const Model& ModelManager::getModelByPath(const QString& path, const QString& libraryPath) const
|
||||
{
|
||||
QDir modelDir(QDir::cleanPath(libraryPath + QString::fromStdString("/") + path));
|
||||
QString absPath = modelDir.absolutePath();
|
||||
return getModelByPath(absPath);
|
||||
}
|
||||
|
||||
bool ModelManager::passFilter(ModelFilter filter, Model::ModelType modelType) const
|
||||
{
|
||||
switch (filter) {
|
||||
case ModelFilter_None:
|
||||
return true;
|
||||
|
||||
case ModelFilter_Physical:
|
||||
return (modelType == Model::ModelType_Physical);
|
||||
|
||||
case ModelFilter_Appearance:
|
||||
return (modelType == Model::ModelType_Appearance);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
std::map<QString, ModelTreeNode*>* ModelManager::getModelTree(const ModelLibrary& library,
|
||||
ModelFilter filter)
|
||||
{
|
||||
std::map<QString, ModelTreeNode*>* modelTree = new std::map<QString, ModelTreeNode*>();
|
||||
|
||||
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::map<QString, ModelTreeNode*>* 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::map<QString, ModelTreeNode*>* mapPtr;
|
||||
if (node->count(QString::fromStdString(itp->string())) == 0) {
|
||||
mapPtr = new std::map<QString, ModelTreeNode*>();
|
||||
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;
|
||||
}
|
||||
85
src/Mod/Material/App/ModelManager.h
Normal file
85
src/Mod/Material/App/ModelManager.h
Normal file
@@ -0,0 +1,85 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2023 David Carter <dcarter@david.carter.ca> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef MATERIAL_MODELMANAGER_H
|
||||
#define MATERIAL_MODELMANAGER_H
|
||||
|
||||
#include <QMutex>
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
#include "Exceptions.h"
|
||||
#include "FolderTree.h"
|
||||
#include "Model.h"
|
||||
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
namespace Materials
|
||||
{
|
||||
|
||||
typedef FolderTreeNode<Model> ModelTreeNode;
|
||||
|
||||
class MaterialsExport ModelManager: public Base::BaseClass
|
||||
{
|
||||
TYPESYSTEM_HEADER();
|
||||
|
||||
public:
|
||||
enum ModelFilter
|
||||
{
|
||||
ModelFilter_None,
|
||||
ModelFilter_Physical,
|
||||
ModelFilter_Appearance
|
||||
};
|
||||
|
||||
ModelManager();
|
||||
virtual ~ModelManager() = default;
|
||||
|
||||
void refresh();
|
||||
|
||||
std::list<ModelLibrary*>* getModelLibraries()
|
||||
{
|
||||
return _libraryList;
|
||||
}
|
||||
std::map<QString, Model*>* getModels()
|
||||
{
|
||||
return _modelMap;
|
||||
}
|
||||
std::map<QString, ModelTreeNode*>* getModelTree(const ModelLibrary& library,
|
||||
ModelFilter filter = ModelFilter_None);
|
||||
const Model& getModel(const QString& uuid) const;
|
||||
const Model& getModelByPath(const QString& path) const;
|
||||
const Model& getModelByPath(const QString& path, const QString& libraryPath) const;
|
||||
|
||||
static bool isModel(const fs::path& p);
|
||||
bool passFilter(ModelFilter filter, Model::ModelType modelType) const;
|
||||
|
||||
private:
|
||||
static void initLibraries();
|
||||
|
||||
static std::list<ModelLibrary*>* _libraryList;
|
||||
static std::map<QString, Model*>* _modelMap;
|
||||
static QMutex _mutex;
|
||||
};
|
||||
|
||||
}// namespace Materials
|
||||
|
||||
#endif// MATERIAL_MODELMANAGER_H
|
||||
41
src/Mod/Material/App/ModelManagerPy.xml
Normal file
41
src/Mod/Material/App/ModelManagerPy.xml
Normal file
@@ -0,0 +1,41 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<GenerateModel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="generateMetaModel_Module.xsd">
|
||||
<PythonExport
|
||||
Father="BaseClassPy"
|
||||
Name="ModelManagerPy"
|
||||
Twin="ModelManager"
|
||||
TwinPointer="ModelManager"
|
||||
Include="Mod/Material/App/ModelManager.h"
|
||||
Namespace="Materials"
|
||||
FatherInclude="Base/BaseClassPy.h"
|
||||
FatherNamespace="Base"
|
||||
Constructor="true"
|
||||
Delete="true">
|
||||
<Documentation>
|
||||
<Author Licence="LGPL" Name="DavidCarter" EMail="dcarter@davidcarter.ca" />
|
||||
<UserDocu>Material model descriptions.</UserDocu>
|
||||
</Documentation>
|
||||
<Methode Name="getModel">
|
||||
<Documentation>
|
||||
<UserDocu>Get a model object by specifying its UUID</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="getModelByPath">
|
||||
<Documentation>
|
||||
<UserDocu>Get a model object by specifying its path</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Attribute Name="ModelLibraries" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>List of model libraries.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="ModelLibraries" Type="List"/>
|
||||
</Attribute>
|
||||
<Attribute Name="Models" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>List of model libraries.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="Models" Type="Dict"/>
|
||||
</Attribute>
|
||||
</PythonExport>
|
||||
</GenerateModel>
|
||||
163
src/Mod/Material/App/ModelManagerPyImpl.cpp
Normal file
163
src/Mod/Material/App/ModelManagerPyImpl.cpp
Normal file
@@ -0,0 +1,163 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2008 Werner Mayer <wmayer[at]users.sourceforge.net> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "PreCompiled.h"
|
||||
|
||||
#ifndef _PreComp_
|
||||
#include <boost/uuid/uuid_io.hpp>
|
||||
#endif
|
||||
|
||||
#include "ModelManager.h"
|
||||
#include "ModelManagerPy.h"
|
||||
#include "ModelPy.h"
|
||||
|
||||
#include "ModelManagerPy.cpp"
|
||||
|
||||
using namespace Materials;
|
||||
|
||||
// returns a string which represents the object e.g. when printed in python
|
||||
std::string ModelManagerPy::representation() const
|
||||
{
|
||||
std::stringstream str;
|
||||
str << "<ModelManager object at " << getModelManagerPtr() << ">";
|
||||
|
||||
return str.str();
|
||||
}
|
||||
|
||||
PyObject* ModelManagerPy::PyMake(struct _typeobject*, PyObject*, PyObject*)// Python wrapper
|
||||
{
|
||||
// never create such objects with the constructor
|
||||
return new ModelManagerPy(new ModelManager());
|
||||
}
|
||||
|
||||
// constructor method
|
||||
int ModelManagerPy::PyInit(PyObject* /*args*/, PyObject* /*kwd*/)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
PyObject* ModelManagerPy::getModel(PyObject* args)
|
||||
{
|
||||
char* uuid;
|
||||
if (!PyArg_ParseTuple(args, "s", &uuid)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
try {
|
||||
const Model model = getModelManagerPtr()->getModel(QString::fromStdString(uuid));
|
||||
return new ModelPy(new Model(model));
|
||||
}
|
||||
catch (ModelNotFound const&) {
|
||||
QString error = QString::fromStdString("Model not found:\n");
|
||||
std::map<QString, Model*>* _modelMap = getModelManagerPtr()->getModels();
|
||||
error += QString::fromStdString("ModelMap:\n");
|
||||
for (auto itp = _modelMap->begin(); itp != _modelMap->end(); itp++) {
|
||||
error += QString::fromStdString("\t_modelMap[") + itp->first
|
||||
+ QString::fromStdString("] = '") + itp->second->getName()
|
||||
+ QString::fromStdString("'\n");
|
||||
}
|
||||
error += QString::fromStdString("\tuuid = '") + QString::fromStdString(uuid)
|
||||
+ QString::fromStdString("'\n");
|
||||
PyErr_SetString(PyExc_LookupError, error.toStdString().c_str());
|
||||
return nullptr;
|
||||
}
|
||||
catch (Uninitialized const&) {
|
||||
PyErr_SetString(PyExc_LookupError, "Uninitialized model list");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
PyObject* ModelManagerPy::getModelByPath(PyObject* args)
|
||||
{
|
||||
char* path;
|
||||
char* lib = "";
|
||||
if (!PyArg_ParseTuple(args, "s|s", &path, &lib)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
catch (ModelNotFound const&) {
|
||||
PyErr_SetString(PyExc_LookupError, "Model not found");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
const Model& model = getModelManagerPtr()->getModelByPath(QString::fromStdString(path));
|
||||
return new ModelPy(new Model(model));
|
||||
}
|
||||
catch (ModelNotFound const&) {
|
||||
PyErr_SetString(PyExc_LookupError, "Model not found");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
Py::List ModelManagerPy::getModelLibraries() const
|
||||
{
|
||||
std::list<ModelLibrary*>* libraries = getModelManagerPtr()->getModelLibraries();
|
||||
Py::List list;
|
||||
|
||||
for (auto it = libraries->begin(); it != libraries->end(); it++) {
|
||||
ModelLibrary* lib = *it;
|
||||
Py::Tuple libTuple(3);
|
||||
libTuple.setItem(0, Py::String(lib->getName().toStdString()));
|
||||
libTuple.setItem(1, Py::String(lib->getDirectoryPath().toStdString()));
|
||||
libTuple.setItem(2, Py::String(lib->getIconPath().toStdString()));
|
||||
|
||||
list.append(libTuple);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
Py::Dict ModelManagerPy::getModels() const
|
||||
{
|
||||
std::map<QString, Model*>* models = getModelManagerPtr()->getModels();
|
||||
Py::Dict dict;
|
||||
|
||||
for (auto it = models->begin(); it != models->end(); it++) {
|
||||
QString key = it->first;
|
||||
Model* model = it->second;
|
||||
|
||||
PyObject* modelPy = new ModelPy(new Model(*model));
|
||||
dict.setItem(Py::String(key.toStdString()), Py::Object(modelPy, true));
|
||||
}
|
||||
|
||||
return dict;
|
||||
}
|
||||
|
||||
PyObject* ModelManagerPy::getCustomAttributes(const char* /*attr*/) const
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int ModelManagerPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
54
src/Mod/Material/App/ModelPropertyPy.xml
Normal file
54
src/Mod/Material/App/ModelPropertyPy.xml
Normal file
@@ -0,0 +1,54 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<GenerateModel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="generateMetaModel_Module.xsd">
|
||||
<PythonExport
|
||||
Father="BaseClassPy"
|
||||
Name="ModelPropertyPy"
|
||||
Twin="ModelProperty"
|
||||
TwinPointer="ModelProperty"
|
||||
Include="Mod/Material/App/Model.h"
|
||||
Namespace="Materials"
|
||||
FatherInclude="Base/BaseClassPy.h"
|
||||
FatherNamespace="Base"
|
||||
Constructor="true"
|
||||
Delete="true">
|
||||
<Documentation>
|
||||
<Author Licence="LGPL" Name="DavidCarter" EMail="dcarter@davidcarter.ca" />
|
||||
<UserDocu>Material property descriptions.</UserDocu>
|
||||
</Documentation>
|
||||
<!-- <Methode Name="mirror">
|
||||
<Documentation>
|
||||
<UserDocu>Performs the symmetrical transformation of this geometric object</UserDocu>
|
||||
</Documentation>
|
||||
</Methode> -->
|
||||
<Attribute Name="Name" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>Property name.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="Name" Type="String"/>
|
||||
</Attribute>
|
||||
<Attribute Name="Type" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>Property type.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="Type" Type="String"/>
|
||||
</Attribute>
|
||||
<Attribute Name="Units" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>Property units category.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="Units" Type="String"/>
|
||||
</Attribute>
|
||||
<Attribute Name="URL" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>URL to a detailed description of the property.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="URL" Type="String"/>
|
||||
</Attribute>
|
||||
<Attribute Name="Description" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>Property description.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="Description" Type="String"/>
|
||||
</Attribute>
|
||||
</PythonExport>
|
||||
</GenerateModel>
|
||||
101
src/Mod/Material/App/ModelPropertyPyImpl.cpp
Normal file
101
src/Mod/Material/App/ModelPropertyPyImpl.cpp
Normal file
@@ -0,0 +1,101 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2008 Werner Mayer <wmayer[at]users.sourceforge.net> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "PreCompiled.h"
|
||||
|
||||
#ifndef _PreComp_
|
||||
#include <boost/uuid/uuid_io.hpp>
|
||||
#endif
|
||||
|
||||
#include "Model.h"
|
||||
#include "ModelPropertyPy.h"
|
||||
|
||||
#include "ModelPropertyPy.cpp"
|
||||
|
||||
using namespace Materials;
|
||||
|
||||
// returns a string which represents the object e.g. when printed in python
|
||||
std::string ModelPropertyPy::representation() const
|
||||
{
|
||||
ModelPropertyPy::PointerType ptr = getModelPropertyPtr();
|
||||
std::stringstream str;
|
||||
str << "Property [Name=(";
|
||||
str << ptr->getName().toStdString();
|
||||
str << "), Type=(";
|
||||
str << ptr->getPropertyType().toStdString();
|
||||
str << "), Units=(";
|
||||
str << ptr->getUnits().toStdString();
|
||||
str << "), URL=(";
|
||||
str << ptr->getURL().toStdString();
|
||||
str << "), Description=(";
|
||||
str << ptr->getDescription().toStdString();
|
||||
str << ")]";
|
||||
|
||||
return str.str();
|
||||
}
|
||||
|
||||
PyObject* ModelPropertyPy::PyMake(struct _typeobject*, PyObject*, PyObject*)// Python wrapper
|
||||
{
|
||||
// never create such objects with the constructor
|
||||
return new ModelPropertyPy(new ModelProperty());
|
||||
}
|
||||
|
||||
// constructor method
|
||||
int ModelPropertyPy::PyInit(PyObject* /*args*/, PyObject* /*kwd*/)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
Py::String ModelPropertyPy::getName() const
|
||||
{
|
||||
return Py::String(getModelPropertyPtr()->getName().toStdString());
|
||||
}
|
||||
|
||||
Py::String ModelPropertyPy::getType() const
|
||||
{
|
||||
return Py::String(getModelPropertyPtr()->getPropertyType().toStdString());
|
||||
}
|
||||
|
||||
Py::String ModelPropertyPy::getUnits() const
|
||||
{
|
||||
return Py::String(getModelPropertyPtr()->getUnits().toStdString());
|
||||
}
|
||||
|
||||
Py::String ModelPropertyPy::getURL() const
|
||||
{
|
||||
return Py::String(getModelPropertyPtr()->getURL().toStdString());
|
||||
}
|
||||
|
||||
Py::String ModelPropertyPy::getDescription() const
|
||||
{
|
||||
return Py::String(getModelPropertyPtr()->getDescription().toStdString());
|
||||
}
|
||||
|
||||
PyObject* ModelPropertyPy::getCustomAttributes(const char* /*attr*/) const
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int ModelPropertyPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
85
src/Mod/Material/App/ModelPy.xml
Normal file
85
src/Mod/Material/App/ModelPy.xml
Normal file
@@ -0,0 +1,85 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<GenerateModel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="generateMetaModel_Module.xsd">
|
||||
<PythonExport
|
||||
Father="BaseClassPy"
|
||||
Name="ModelPy"
|
||||
Twin="Model"
|
||||
TwinPointer="Model"
|
||||
Include="Mod/Material/App/Model.h"
|
||||
Namespace="Materials"
|
||||
FatherInclude="Base/BaseClassPy.h"
|
||||
FatherNamespace="Base"
|
||||
Constructor="true"
|
||||
Delete="true">
|
||||
<Documentation>
|
||||
<Author Licence="LGPL" Name="DavidCarter" EMail="dcarter@davidcarter.ca" />
|
||||
<UserDocu>Material model descriptions.</UserDocu>
|
||||
</Documentation>
|
||||
<Attribute Name="LibraryName" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>Model library name.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="LibraryName" Type="String"/>
|
||||
</Attribute>
|
||||
<Attribute Name="LibraryRoot" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>Model library path.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="LibraryRoot" Type="String"/>
|
||||
</Attribute>
|
||||
<Attribute Name="LibraryIcon" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>Model icon path.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="LibraryIcon" Type="String"/>
|
||||
</Attribute>
|
||||
<Attribute Name="Name" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>Model name.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="Name" Type="String"/>
|
||||
</Attribute>
|
||||
<Attribute Name="Directory" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>Model directory.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="Directory" Type="String"/>
|
||||
</Attribute>
|
||||
<Attribute Name="UUID" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>Unique model identifier.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="UUID" Type="String"/>
|
||||
</Attribute>
|
||||
<Attribute Name="Description" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>Description of the model.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="Description" Type="String"/>
|
||||
</Attribute>
|
||||
<Attribute Name="URL" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>URL to a detailed description of the model.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="URL" Type="String"/>
|
||||
</Attribute>
|
||||
<Attribute Name="DOI" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>Digital Object Identifier (see https://doi.org/)</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="DOI" Type="String"/>
|
||||
</Attribute>
|
||||
<Attribute Name="Inherited" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>List of inherited models identified by UUID.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="Inherited" Type="List"/>
|
||||
</Attribute>
|
||||
<Attribute Name="Properties" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>Dictionary of model properties.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="Properties" Type="Dict"/>
|
||||
</Attribute>
|
||||
</PythonExport>
|
||||
</GenerateModel>
|
||||
172
src/Mod/Material/App/ModelPyImpl.cpp
Normal file
172
src/Mod/Material/App/ModelPyImpl.cpp
Normal file
@@ -0,0 +1,172 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2008 Werner Mayer <wmayer[at]users.sourceforge.net> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "PreCompiled.h"
|
||||
|
||||
#ifndef _PreComp_
|
||||
#include <boost/uuid/uuid_io.hpp>
|
||||
#endif
|
||||
|
||||
#include "Model.h"
|
||||
#include "ModelPropertyPy.h"
|
||||
#include "ModelPy.h"
|
||||
|
||||
#include "ModelPy.cpp"
|
||||
|
||||
using namespace Materials;
|
||||
|
||||
// returns a string which represents the object e.g. when printed in python
|
||||
std::string ModelPy::representation() const
|
||||
{
|
||||
ModelPy::PointerType ptr = getModelPtr();
|
||||
std::stringstream str;
|
||||
str << "Property [Name=(";
|
||||
str << ptr->getName().toStdString();
|
||||
str << "), UUID=(";
|
||||
str << ptr->getUUID().toStdString();
|
||||
str << "), Library Name=(";
|
||||
str << ptr->getLibrary().getName().toStdString();
|
||||
str << "), Library Root=(";
|
||||
str << ptr->getLibrary().getDirectoryPath().toStdString();
|
||||
str << "), Library Icon=(";
|
||||
str << ptr->getLibrary().getIconPath().toStdString();
|
||||
str << "), Directory=(";
|
||||
str << ptr->getDirectory().toStdString();
|
||||
str << "), URL=(";
|
||||
str << ptr->getURL().toStdString();
|
||||
str << "), DOI=(";
|
||||
str << ptr->getDOI().toStdString();
|
||||
str << "), Description=(";
|
||||
str << ptr->getDescription().toStdString();
|
||||
str << "), Inherits=[";
|
||||
const std::vector<QString>& inherited = getModelPtr()->getInheritance();
|
||||
for (auto it = inherited.begin(); it != inherited.end(); it++) {
|
||||
QString uuid = *it;
|
||||
if (it != inherited.begin()) {
|
||||
str << "), UUID=(";
|
||||
}
|
||||
else {
|
||||
str << "UUID=(";
|
||||
}
|
||||
str << uuid.toStdString() << ")";
|
||||
}
|
||||
str << "]]";
|
||||
|
||||
return str.str();
|
||||
}
|
||||
|
||||
PyObject* ModelPy::PyMake(struct _typeobject*, PyObject*, PyObject*)// Python wrapper
|
||||
{
|
||||
// never create such objects with the constructor
|
||||
return new ModelPy(new Model());
|
||||
}
|
||||
|
||||
// constructor method
|
||||
int ModelPy::PyInit(PyObject* /*args*/, PyObject* /*kwd*/)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
Py::String ModelPy::getLibraryName() const
|
||||
{
|
||||
return Py::String(getModelPtr()->getLibrary().getName().toStdString());
|
||||
}
|
||||
|
||||
Py::String ModelPy::getLibraryRoot() const
|
||||
{
|
||||
return Py::String(getModelPtr()->getLibrary().getDirectoryPath().toStdString());
|
||||
}
|
||||
|
||||
Py::String ModelPy::getLibraryIcon() const
|
||||
{
|
||||
return Py::String(getModelPtr()->getLibrary().getIconPath().toStdString());
|
||||
}
|
||||
|
||||
Py::String ModelPy::getName() const
|
||||
{
|
||||
return Py::String(getModelPtr()->getName().toStdString());
|
||||
}
|
||||
|
||||
Py::String ModelPy::getDirectory() const
|
||||
{
|
||||
return Py::String(getModelPtr()->getDirectoryPath().toStdString());
|
||||
}
|
||||
|
||||
Py::String ModelPy::getUUID() const
|
||||
{
|
||||
return Py::String(getModelPtr()->getUUID().toStdString());
|
||||
}
|
||||
|
||||
Py::String ModelPy::getDescription() const
|
||||
{
|
||||
return Py::String(getModelPtr()->getDescription().toStdString());
|
||||
}
|
||||
|
||||
Py::String ModelPy::getURL() const
|
||||
{
|
||||
return Py::String(getModelPtr()->getURL().toStdString());
|
||||
}
|
||||
|
||||
Py::String ModelPy::getDOI() const
|
||||
{
|
||||
return Py::String(getModelPtr()->getDOI().toStdString());
|
||||
}
|
||||
|
||||
Py::List ModelPy::getInherited() const
|
||||
{
|
||||
const std::vector<QString>& inherited = getModelPtr()->getInheritance();
|
||||
Py::List list;
|
||||
|
||||
for (auto it = inherited.begin(); it != inherited.end(); it++) {
|
||||
QString uuid = *it;
|
||||
|
||||
list.append(Py::String(uuid.toStdString()));
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
Py::Dict ModelPy::getProperties() const
|
||||
{
|
||||
// std::map<std::string, Model*> *models = getModelPtr()->getModels();
|
||||
Py::Dict dict;
|
||||
|
||||
for (auto it = getModelPtr()->begin(); it != getModelPtr()->end(); it++) {
|
||||
QString key = it->first;
|
||||
ModelProperty& modelProperty = it->second;
|
||||
|
||||
PyObject* modelPropertyPy = new ModelPropertyPy(new ModelProperty(modelProperty));
|
||||
dict.setItem(Py::String(key.toStdString()), Py::Object(modelPropertyPy, true));
|
||||
}
|
||||
|
||||
return dict;
|
||||
}
|
||||
|
||||
PyObject* ModelPy::getCustomAttributes(const char* /*attr*/) const
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int ModelPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
73
src/Mod/Material/App/ModelUuids.h
Normal file
73
src/Mod/Material/App/ModelUuids.h
Normal file
@@ -0,0 +1,73 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2023 David Carter <dcarter@david.carter.ca> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef MATERIAL_MODELUUIDS_H
|
||||
#define MATERIAL_MODELUUIDS_H
|
||||
|
||||
namespace Materials
|
||||
{
|
||||
|
||||
// UUIDs for predefined material models
|
||||
|
||||
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");
|
||||
|
||||
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");
|
||||
|
||||
static const QString ModelUUID_Fluid_Default =
|
||||
QString::fromStdString("1ae66d8c-1ba1-4211-ad12-b9917573b202");
|
||||
|
||||
static const QString ModelUUID_Thermal_Default =
|
||||
QString::fromStdString("9959d007-a970-4ea7-bae4-3eb1b8b883c7");
|
||||
|
||||
static const QString ModelUUID_Electromagnetic_Default =
|
||||
QString::fromStdString("b2eb5f48-74b3-4193-9fbb-948674f427f3");
|
||||
|
||||
static const QString ModelUUID_Architectural_Default =
|
||||
QString::fromStdString("32439c3b-262f-4b7b-99a8-f7f44e5894c8");
|
||||
|
||||
static const QString ModelUUID_Costs_Default =
|
||||
QString::fromStdString("881df808-8726-4c2e-be38-688bb6cce466");
|
||||
|
||||
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");
|
||||
|
||||
}// namespace Materials
|
||||
|
||||
#endif// MATERIAL_MODELUUIDS_H
|
||||
24
src/Mod/Material/App/PreCompiled.cpp
Normal file
24
src/Mod/Material/App/PreCompiled.cpp
Normal file
@@ -0,0 +1,24 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2023 David Carter <dcarter@david.carter.ca> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#include "PreCompiled.h"
|
||||
67
src/Mod/Material/App/PreCompiled.h
Normal file
67
src/Mod/Material/App/PreCompiled.h
Normal file
@@ -0,0 +1,67 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2023 David Carter <dcarter@david.carter.ca> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef MATGUI_PRECOMPILED_H
|
||||
#define MATGUI_PRECOMPILED_H
|
||||
|
||||
#include <FCConfig.h>
|
||||
|
||||
#include <Mod/Material/MaterialGlobal.h>
|
||||
|
||||
// point at which warnings of overly long specifiers disabled (needed for VC6)
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning( disable : 4251 )
|
||||
# pragma warning( disable : 4503 )
|
||||
# pragma warning( disable : 4786 ) // specifier longer then 255 chars
|
||||
# pragma warning( disable : 4273 )
|
||||
#endif
|
||||
|
||||
#ifdef FC_OS_WIN32
|
||||
# ifndef NOMINMAX
|
||||
# define NOMINMAX
|
||||
# endif
|
||||
# include <windows.h>
|
||||
#endif
|
||||
|
||||
#ifdef _PreComp_
|
||||
|
||||
// standard
|
||||
#include <cfloat>
|
||||
#include <cmath>
|
||||
|
||||
// STL
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
// Qt
|
||||
#include <QtGlobal>
|
||||
|
||||
// Boost
|
||||
#include <boost/regex.hpp>
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
|
||||
#endif //_PreComp_
|
||||
|
||||
#endif // MATGUI_PRECOMPILED_H
|
||||
81
src/Mod/Material/App/trim.h
Normal file
81
src/Mod/Material/App/trim.h
Normal file
@@ -0,0 +1,81 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2023 David Carter <dcarter@david.carter.ca> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef MATERIAL_TRIM_H
|
||||
#define MATERIAL_TRIM_H
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace Materials
|
||||
{
|
||||
|
||||
// trim from start (in place)
|
||||
static inline void ltrim(std::string& s)
|
||||
{
|
||||
s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char ch) {
|
||||
return !std::isspace(ch);
|
||||
}));
|
||||
}
|
||||
|
||||
// trim from end (in place)
|
||||
static inline void rtrim(std::string& s)
|
||||
{
|
||||
s.erase(std::find_if(s.rbegin(),
|
||||
s.rend(),
|
||||
[](unsigned char ch) {
|
||||
return !std::isspace(ch);
|
||||
})
|
||||
.base(),
|
||||
s.end());
|
||||
}
|
||||
|
||||
// trim from both ends (in place)
|
||||
static inline void trim(std::string& s)
|
||||
{
|
||||
rtrim(s);
|
||||
ltrim(s);
|
||||
}
|
||||
|
||||
// trim from start (copying)
|
||||
static inline std::string ltrim_copy(std::string s)
|
||||
{
|
||||
ltrim(s);
|
||||
return s;
|
||||
}
|
||||
|
||||
// trim from end (copying)
|
||||
static inline std::string rtrim_copy(std::string s)
|
||||
{
|
||||
rtrim(s);
|
||||
return s;
|
||||
}
|
||||
|
||||
// trim from both ends (copying)
|
||||
static inline std::string trim_copy(std::string s)
|
||||
{
|
||||
trim(s);
|
||||
return s;
|
||||
}
|
||||
|
||||
}// namespace Materials
|
||||
|
||||
#endif// MATERIAL_TRIM_H
|
||||
@@ -1,174 +1,221 @@
|
||||
IF (BUILD_GUI)
|
||||
PYSIDE_WRAP_RC(Material_QRC_SRCS Resources/Material.qrc)
|
||||
ENDIF (BUILD_GUI)
|
||||
add_subdirectory(App)
|
||||
|
||||
SET(Material_SRCS
|
||||
if(BUILD_GUI)
|
||||
add_subdirectory(Gui)
|
||||
endif(BUILD_GUI)
|
||||
|
||||
IF(BUILD_GUI)
|
||||
PYSIDE_WRAP_RC(Material_QRC_SRCS Resources/Material.qrc)
|
||||
ENDIF(BUILD_GUI)
|
||||
|
||||
SET(MaterialScripts_Files
|
||||
Init.py
|
||||
InitGui.py
|
||||
Material.py
|
||||
importFCMat.py
|
||||
MaterialEditor.py
|
||||
materials-editor.ui
|
||||
TestMaterialsApp.py
|
||||
Resources/ui/materials-editor.ui
|
||||
Templatematerial.yml
|
||||
)
|
||||
SOURCE_GROUP("Module" FILES ${Material_SRCS})
|
||||
|
||||
SET (MaterialTools_Files
|
||||
# SOURCE_GROUP("MaterialScripts" FILES ${MaterialScripts_Files})
|
||||
SET(MaterialTools_Files
|
||||
materialtools/__init__.py
|
||||
materialtools/cardutils.py
|
||||
materialtools/MaterialModels.py
|
||||
)
|
||||
SET (Material_Icon_Files
|
||||
SET(Material_Icon_Files
|
||||
Resources/icons/preview-rendered.svg
|
||||
Resources/icons/preview-vector.svg
|
||||
)
|
||||
|
||||
# collect all the material cards:
|
||||
#FILE( GLOB MaterialLib_Files ./StandardMaterial/*.FCMat ./StandardMaterial/*.txt )
|
||||
|
||||
SET (MaterialLib_Files
|
||||
StandardMaterial/None.FCMat
|
||||
StandardMaterial/ABS-Generic.FCMat
|
||||
StandardMaterial/Acrylic-Glass-Generic.FCMat
|
||||
StandardMaterial/AlMg3F24.FCMat
|
||||
StandardMaterial/AlMgSi1F31.FCMat
|
||||
StandardMaterial/Aluminum-6061-T6.FCMat
|
||||
StandardMaterial/Aluminum-Generic.FCMat
|
||||
StandardMaterial/AlZn4-5Mg1F35.FCMat
|
||||
StandardMaterial/CalculiX-Steel.FCMat
|
||||
StandardMaterial/Concrete-Generic.FCMat
|
||||
StandardMaterial/Copper-Generic.FCMat
|
||||
StandardMaterial/Glass-E-GlassFibre.FCMat
|
||||
StandardMaterial/Glass-Generic.FCMat
|
||||
StandardMaterial/Glass-S2-GlassFibre.FCMat
|
||||
StandardMaterial/Graphite.FCMat
|
||||
StandardMaterial/Iron-Generic.FCMat
|
||||
StandardMaterial/Invar-Generic.FCMat
|
||||
StandardMaterial/PA6-Generic.FCMat
|
||||
StandardMaterial/PET-Generic.FCMat
|
||||
StandardMaterial/PLA-Generic.FCMat
|
||||
StandardMaterial/PP-Generic.FCMat
|
||||
StandardMaterial/PTFE-Generic.FCMat
|
||||
StandardMaterial/PVC-Generic.FCMat
|
||||
StandardMaterial/Reinforcement-FIB-B500.FCMat
|
||||
StandardMaterial/Steel-15CrNi6.FCMat
|
||||
StandardMaterial/Steel-17CrNiMo6.FCMat
|
||||
StandardMaterial/Steel-1C22.FCMat
|
||||
StandardMaterial/Steel-1C35.FCMat
|
||||
StandardMaterial/Steel-1C45.FCMat
|
||||
StandardMaterial/Steel-1C60.FCMat
|
||||
StandardMaterial/Steel-20NiCrMo2.FCMat
|
||||
StandardMaterial/Steel-28Mn6.FCMat
|
||||
StandardMaterial/Steel-2C10.FCMat
|
||||
StandardMaterial/Steel-30CrNiMo8.FCMat
|
||||
StandardMaterial/Steel-34CrNiMo6.FCMat
|
||||
StandardMaterial/Steel-36CrNiMo4.FCMat
|
||||
StandardMaterial/Steel-36NiCrMo16.FCMat
|
||||
StandardMaterial/Steel-3C15.FCMat
|
||||
StandardMaterial/Steel-3C22.FCMat
|
||||
StandardMaterial/Steel-3C35.FCMat
|
||||
StandardMaterial/Steel-3V45.FCMat
|
||||
StandardMaterial/Steel-C10.FCMat
|
||||
StandardMaterial/Steel-C15.FCMat
|
||||
StandardMaterial/Steel-C22E.FCMat
|
||||
StandardMaterial/Steel-C25E.FCMat
|
||||
StandardMaterial/Steel-C30E.FCMat
|
||||
StandardMaterial/Steel-C40E.FCMat
|
||||
StandardMaterial/Steel-C50E.FCMat
|
||||
StandardMaterial/Steel-C55E.FCMat
|
||||
StandardMaterial/Steel-C60E.FCMat
|
||||
StandardMaterial/Steel-E295-GC.FCMat
|
||||
StandardMaterial/Steel-E295.FCMat
|
||||
StandardMaterial/Steel-E335-GC.FCMat
|
||||
StandardMaterial/Steel-E335.FCMat
|
||||
StandardMaterial/Steel-E360-GC.FCMat
|
||||
StandardMaterial/Steel-E360.FCMat
|
||||
StandardMaterial/Steel-EN-GJL-100.FCMat
|
||||
StandardMaterial/Steel-EN-GJL-150.FCMat
|
||||
StandardMaterial/Steel-EN-GJL-200.FCMat
|
||||
StandardMaterial/Steel-EN-GJL-250.FCMat
|
||||
StandardMaterial/Steel-EN-GJL-300.FCMat
|
||||
StandardMaterial/Steel-EN-GJL-350.FCMat
|
||||
StandardMaterial/Steel-EN-GJMB-350-10.FCMat
|
||||
StandardMaterial/Steel-EN-GJMB-550-4.FCMat
|
||||
StandardMaterial/Steel-EN-GJMB-650-2.FCMat
|
||||
StandardMaterial/Steel-EN-GJMW-350-4.FCMat
|
||||
StandardMaterial/Steel-EN-GJMW-360-12.FCMat
|
||||
StandardMaterial/Steel-EN-GJMW-400-5.FCMat
|
||||
StandardMaterial/Steel-EN-GJMW-450-7.FCMat
|
||||
StandardMaterial/Steel-EN-GJS-400-15.FCMat
|
||||
StandardMaterial/Steel-EN-GJS-500-7.FCMat
|
||||
StandardMaterial/Steel-EN-GJS-600-3.FCMat
|
||||
StandardMaterial/Steel-EN-GJS-700-2.FCMat
|
||||
StandardMaterial/Steel-EN-GJS-800-1.FCMat
|
||||
StandardMaterial/Steel-G16Mn5.FCMat
|
||||
StandardMaterial/Steel-G200.FCMat
|
||||
StandardMaterial/Steel-G20Mn5.FCMat
|
||||
StandardMaterial/Steel-G230.FCMat
|
||||
StandardMaterial/Steel-G260.FCMat
|
||||
StandardMaterial/Steel-G300.FCMat
|
||||
StandardMaterial/Steel-G30Mn5.FCMat
|
||||
StandardMaterial/Steel-Generic.FCMat
|
||||
StandardMaterial/Steel-S185.FCMat
|
||||
StandardMaterial/Steel-S235JO.FCMat
|
||||
StandardMaterial/Steel-S235JR.FCMat
|
||||
StandardMaterial/Steel-S235JRG1.FCMat
|
||||
StandardMaterial/Steel-S260NC.FCMat
|
||||
StandardMaterial/Steel-S275JO.FCMat
|
||||
StandardMaterial/Steel-S275JR.FCMat
|
||||
StandardMaterial/Steel-S275N.FCMat
|
||||
StandardMaterial/Steel-S335JO.FCMat
|
||||
StandardMaterial/Steel-S335JR.FCMat
|
||||
StandardMaterial/Steel-S335N.FCMat
|
||||
StandardMaterial/Steel-S340MC.FCMat
|
||||
StandardMaterial/Steel-S355J2G3.FCMat
|
||||
StandardMaterial/Steel-S380MC.FCMat
|
||||
StandardMaterial/Steel-S420MC.FCMat
|
||||
StandardMaterial/Steel-S420N.FCMat
|
||||
StandardMaterial/Steel-S460MC.FCMat
|
||||
StandardMaterial/Steel-S460N.FCMat
|
||||
StandardMaterial/Steel-S500MC.FCMat
|
||||
StandardMaterial/Steel-S550MC.FCMat
|
||||
StandardMaterial/Steel-S690MC.FCMat
|
||||
StandardMaterial/Steel-St-37-2K.FCMat
|
||||
StandardMaterial/Steel-St-E-255.FCMat
|
||||
StandardMaterial/Steel-St-E-315.FCMat
|
||||
StandardMaterial/Steel-St-E-380.FCMat
|
||||
StandardMaterial/Steel-St-E-460.FCMat
|
||||
StandardMaterial/Steel-St-E-500.FCMat
|
||||
StandardMaterial/Steel-X2CrNiMoN17-13-3.FCMat
|
||||
StandardMaterial/Steel-X2CrNiN24-4.FCMat
|
||||
StandardMaterial/Steel-X39CrMo17-1.FCMat
|
||||
StandardMaterial/Steel-X3CrNiMo13-14.FCMat
|
||||
StandardMaterial/Steel-X5CrNi18-10.FCMat
|
||||
StandardMaterial/Steel-X5CrNiMo17-12-2.FCMat
|
||||
StandardMaterial/Steel-X6CrNiTi18-10.FCMat
|
||||
StandardMaterial/TEMPLATE.FCMat
|
||||
StandardMaterial/Ti-6Al-4V.FCMat
|
||||
StandardMaterial/Wood-Generic.FCMat
|
||||
StandardMaterial/Readme.txt
|
||||
)
|
||||
SOURCE_GROUP("MatLib" FILES ${MaterialLib_Files})
|
||||
|
||||
SET (FluidMaterial_Files
|
||||
FluidMaterial/None.FCMat
|
||||
FluidMaterial/Air.FCMat
|
||||
FluidMaterial/Argon.FCMat
|
||||
FluidMaterial/Carbon_dioxide.FCMat
|
||||
FluidMaterial/Nitrogen.FCMat
|
||||
FluidMaterial/Water.FCMat
|
||||
FluidMaterial/Readme.md
|
||||
)
|
||||
SOURCE_GROUP("MatLib" FILES ${FluidMaterial_Files})
|
||||
|
||||
ADD_CUSTOM_TARGET(Material ALL
|
||||
SOURCES ${Material_SRCS} ${Material_QRC_SRCS}
|
||||
# FILE( GLOB MaterialLib_Files ./StandardMaterial/*.FCMat ./StandardMaterial/*.txt )
|
||||
SET(MaterialLib_Files
|
||||
Resources/Materials/StandardMaterial/Aggregate/Concrete-EN-C35_45.FCMat
|
||||
Resources/Materials/StandardMaterial/Aggregate/Concrete-Generic.FCMat
|
||||
Resources/Materials/StandardMaterial/Aggregate/Reinforcement-FIB-B500.FCMat
|
||||
Resources/Materials/StandardMaterial/Carbon/Graphite.FCMat
|
||||
Resources/Materials/StandardMaterial/Glass/Glass-E-GlassFibre.FCMat
|
||||
Resources/Materials/StandardMaterial/Glass/Glass-Generic.FCMat
|
||||
Resources/Materials/StandardMaterial/Glass/Glass-S2-GlassFibre.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Alloys/Invar-Generic.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Aluminum/AlMg3F24.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Aluminum/AlMgSi1F31.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Aluminum/Aluminum-6061-T6.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Aluminum/Aluminum-Generic.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Aluminum/AlZn4-5Mg1F35.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Copper/Copper-Generic.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Iron/Iron-Generic.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/CalculiX-Steel.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-15CrNi6.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-17CrNiMo6.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-1C22.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-1C35.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-1C45.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-1C60.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-20NiCrMo2.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-28Mn6.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-2C10.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-30CrNiMo8.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-34CrNiMo6.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-36CrNiMo4.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-36NiCrMo16.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-3C15.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-3C22.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-3C35.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-3V45.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-C10.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-C15.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-C22E.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-C25E.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-C30E.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-C40E.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-C50E.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-C55E.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-C60E.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-E295-GC.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-E295.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-E335-GC.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-E335.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-E360-GC.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-E360.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJL-100.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJL-150.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJL-200.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJL-250.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJL-300.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJL-350.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMB-350-10.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMB-550-4.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMB-650-2.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMW-350-4.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMW-360-12.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMW-400-5.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJMW-450-7.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJS-400-15.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJS-500-7.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJS-600-3.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJS-700-2.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-EN-GJS-800-1.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-G16Mn5.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-G200.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-G20Mn5.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-G230.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-G260.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-G300.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-G30Mn5.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-Generic.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-S185.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-S235JO.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-S235JR.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-S235JRG1.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-S260NC.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-S275JO.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-S275JR.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-S275N.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-S335JO.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-S335JR.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-S335N.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-S340MC.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-S355J2G3.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-S380MC.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-S420MC.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-S420N.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-S460MC.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-S460N.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-S500MC.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-S550MC.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-S690MC.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-St-37-2K.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-St-E-255.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-St-E-315.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-St-E-380.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-St-E-460.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-St-E-500.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-X2CrNiMoN17-13-3.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-X2CrNiN24-4.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-X39CrMo17-1.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-X3CrNiMo13-14.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-X5CrNi18-10.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-X5CrNiMo17-12-2.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Steel/Steel-X6CrNiTi18-10.FCMat
|
||||
Resources/Materials/StandardMaterial/Metal/Titanium/Ti-6Al-4V.FCMat
|
||||
Resources/Materials/StandardMaterial/Thermoplast/ABS-Generic.FCMat
|
||||
Resources/Materials/StandardMaterial/Thermoplast/Acrylic-Glass-Generic.FCMat
|
||||
Resources/Materials/StandardMaterial/Thermoplast/PA6-Generic.FCMat
|
||||
Resources/Materials/StandardMaterial/Thermoplast/PET-Generic.FCMat
|
||||
Resources/Materials/StandardMaterial/Thermoplast/PLA-Generic.FCMat
|
||||
Resources/Materials/StandardMaterial/Thermoplast/PP-Generic.FCMat
|
||||
Resources/Materials/StandardMaterial/Thermoplast/PTFE-Generic.FCMat
|
||||
Resources/Materials/StandardMaterial/Thermoplast/PVC-Generic.FCMat
|
||||
Resources/Materials/StandardMaterial/Wood/Wood-Generic.FCMat
|
||||
)
|
||||
|
||||
fc_target_copy_resource(Material
|
||||
SET(FluidMaterial_Files
|
||||
Resources/Materials/FluidMaterial/None.FCMat
|
||||
Resources/Materials/FluidMaterial/Air.FCMat
|
||||
Resources/Materials/FluidMaterial/Argon.FCMat
|
||||
Resources/Materials/FluidMaterial/Carbon_dioxide.FCMat
|
||||
Resources/Materials/FluidMaterial/Nitrogen.FCMat
|
||||
Resources/Materials/FluidMaterial/Water.FCMat
|
||||
)
|
||||
|
||||
SET(AppearanceLib_Files
|
||||
Resources/Materials/Appearance/Aluminum.FCMat
|
||||
Resources/Materials/Appearance/Brass.FCMat
|
||||
Resources/Materials/Appearance/Bronze.FCMat
|
||||
Resources/Materials/Appearance/Chrome.FCMat
|
||||
Resources/Materials/Appearance/Copper.FCMat
|
||||
Resources/Materials/Appearance/DefaultAppearance.FCMat
|
||||
Resources/Materials/Appearance/Emerald.FCMat
|
||||
Resources/Materials/Appearance/Gold.FCMat
|
||||
Resources/Materials/Appearance/Jade.FCMat
|
||||
Resources/Materials/Appearance/Metalized.FCMat
|
||||
Resources/Materials/Appearance/NeonGNC.FCMat
|
||||
Resources/Materials/Appearance/NeonPHC.FCMat
|
||||
Resources/Materials/Appearance/Obsidian.FCMat
|
||||
Resources/Materials/Appearance/Pewter.FCMat
|
||||
Resources/Materials/Appearance/Plaster.FCMat
|
||||
Resources/Materials/Appearance/Plastic.FCMat
|
||||
Resources/Materials/Appearance/Ruby.FCMat
|
||||
Resources/Materials/Appearance/Satin.FCMat
|
||||
Resources/Materials/Appearance/ShinyPlastic.FCMat
|
||||
Resources/Materials/Appearance/Silver.FCMat
|
||||
Resources/Materials/Appearance/Steel.FCMat
|
||||
Resources/Materials/Appearance/Stone.FCMat
|
||||
)
|
||||
|
||||
SET(MaterialModel_Files
|
||||
Resources/Models/Architectural/Architectural.yml
|
||||
Resources/Models/Costs/Costs.yml
|
||||
Resources/Models/Electromagnetic/Electromagnetic.yml
|
||||
Resources/Models/Fluid/Fluid.yml
|
||||
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
|
||||
Resources/Models/Mechanical/OrthotropicLinearElastic.yml
|
||||
Resources/Models/Rendering/AdvancedRendering.yml
|
||||
Resources/Models/Rendering/BasicRendering.yml
|
||||
Resources/Models/Rendering/TextureRendering.yml
|
||||
Resources/Models/Rendering/VectorRendering.yml
|
||||
Resources/Models/Thermal/Thermal.yml
|
||||
)
|
||||
|
||||
ADD_CUSTOM_TARGET(MaterialScripts ALL
|
||||
SOURCES ${MaterialScripts_Files} ${Material_QRC_SRCS}
|
||||
)
|
||||
|
||||
fc_target_copy_resource(MaterialScripts
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_BINARY_DIR}/Mod/Material
|
||||
${Material_SRCS})
|
||||
${MaterialScripts_Files})
|
||||
|
||||
INSTALL(FILES ${MaterialScripts_Files} DESTINATION Mod/Material)
|
||||
|
||||
ADD_CUSTOM_TARGET(MaterialToolsLib ALL
|
||||
SOURCES ${MaterialTools_Files}
|
||||
@@ -191,42 +238,47 @@ fc_target_copy_resource(MaterialIconsLib
|
||||
INSTALL(FILES ${MaterialTools_Files} DESTINATION Mod/Material/materialtools)
|
||||
INSTALL(FILES ${Material_Icon_Files} DESTINATION Mod/Material/Resources/icons)
|
||||
|
||||
IF (BUILD_GUI)
|
||||
fc_target_copy_resource(Material
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
${CMAKE_BINARY_DIR}/Mod/Material
|
||||
Material_rc.py)
|
||||
ENDIF (BUILD_GUI)
|
||||
|
||||
ADD_CUSTOM_TARGET(MaterialLib ALL
|
||||
SOURCES ${MaterialLib_Files}
|
||||
)
|
||||
ADD_CUSTOM_TARGET(FluidMaterialLib ALL
|
||||
SOURCES ${FluidMaterial_Files}
|
||||
)
|
||||
ADD_CUSTOM_TARGET(AppearanceLib ALL
|
||||
SOURCES ${AppearanceLib_Files}
|
||||
)
|
||||
ADD_CUSTOM_TARGET(MaterialModelLib ALL
|
||||
SOURCES ${MaterialModel_Files}
|
||||
)
|
||||
|
||||
# When a target copies files to different output directories then apparently it always builds the project
|
||||
# which is very annoying. So, the trick is to split this into two targets to avoid this behaviour.
|
||||
fc_target_copy_resource(MaterialLib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_DATADIR}/Mod/Material
|
||||
${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_DATADIR}/Mod/Material/
|
||||
${MaterialLib_Files})
|
||||
fc_target_copy_resource(FluidMaterialLib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_DATADIR}/Mod/Material
|
||||
${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_DATADIR}/Mod/Material/
|
||||
${FluidMaterial_Files})
|
||||
fc_target_copy_resource(AppearanceLib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_DATADIR}/Mod/Material/
|
||||
${AppearanceLib_Files})
|
||||
fc_target_copy_resource(MaterialModelLib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_DATADIR}/Mod/Material/
|
||||
${MaterialModel_Files})
|
||||
|
||||
INSTALL(
|
||||
FILES ${Material_SRCS} ${Material_QRC_SRCS}
|
||||
DESTINATION Mod/Material
|
||||
)
|
||||
|
||||
INSTALL(
|
||||
DIRECTORY
|
||||
StandardMaterial
|
||||
DIRECTORY
|
||||
FluidMaterial
|
||||
DESTINATION
|
||||
${CMAKE_INSTALL_DATADIR}/Mod/Material
|
||||
FILES_MATCHING PATTERN "*.FCMat*"
|
||||
)
|
||||
foreach(file ${MaterialLib_Files} ${FluidMaterial_Files} ${AppearanceLib_Files} ${MaterialModel_Files})
|
||||
cmake_path(REMOVE_FILENAME file OUTPUT_VARIABLE filepath)
|
||||
INSTALL(
|
||||
FILES ${file}
|
||||
DESTINATION ${CMAKE_INSTALL_DATADIR}/Mod/Material/${filepath}
|
||||
)
|
||||
endforeach()
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
[General]
|
||||
Name = Air
|
||||
Description = Dry air properties at 20 Degrees Celsius and 1 atm
|
||||
MolarMass = 28.965
|
||||
Father = Gas
|
||||
|
||||
[Fluidic]
|
||||
Density = 1.204 kg/m^3
|
||||
DynamicViscosity = 1.80e-5 kg/m/s
|
||||
KinematicViscosity = 1.511e-5 m^2/s
|
||||
; PrandtlNumber is a nondimension number for CFD simulation
|
||||
PrandtlNumber = 0.7
|
||||
|
||||
[Thermal]
|
||||
SpecificHeat = 1.01 kJ/kg/K
|
||||
ThermalConductivity = 0.02587 W/m/K
|
||||
; thermal expansion coefficient of ideal gas is 1/temperature
|
||||
ThermalExpansionCoefficient = 3.43e-3 1/K
|
||||
|
||||
[Electromagnetic]
|
||||
RelativePermittivity = 1.00059
|
||||
; at 18°C and 50Hz
|
||||
ElectricalConductivity = 1e-12 S/m
|
||||
RelativePermeability = 1.0
|
||||
@@ -1,24 +0,0 @@
|
||||
[General]
|
||||
Name = Argon
|
||||
Description = Argon properties at 20 Degrees Celsius and 1 atm
|
||||
MolarMass = 39.95
|
||||
Father = Gas
|
||||
|
||||
[Fluidic]
|
||||
Density = 1.641 kg/m^3
|
||||
DynamicViscosity = 22.3e-6 kg/m/s
|
||||
; Kinematic Viscosity = Dynamic Viscosity / Density
|
||||
KinematicViscosity = 13.59-6 m^2/s
|
||||
; PrandtlNumber is a nondimension number for CFD simulation
|
||||
PrandtlNumber = 0.7
|
||||
|
||||
[Thermal]
|
||||
SpecificHeat = 0.520 kJ/kg/K
|
||||
ThermalConductivity = 0.018 W/m/K
|
||||
; thermal expansion coefficient of ideal gas is 1/temperature
|
||||
ThermalExpansionCoefficient = 3.43e-3 1/K
|
||||
|
||||
[Electromagnetic]
|
||||
RelativePermittivity = 1.000513
|
||||
ElectricalConductivity = 1e-15 S/m
|
||||
RelativePermeability = 1.0
|
||||
@@ -1,24 +0,0 @@
|
||||
[General]
|
||||
Name = Carbon dioxide
|
||||
Description = Carbon dioxide properties at 20 Degrees Celsius and 1 atm
|
||||
MolarMass = 44.009
|
||||
Father = Gas
|
||||
|
||||
[Fluidic]
|
||||
Density = 1.8393 kg/m^3
|
||||
DynamicViscosity = 14.7e-6 kg/m/s
|
||||
; Kinematic Viscosity = Dynamic Viscosity / Density
|
||||
KinematicViscosity = 8.09e-6 m^2/s
|
||||
; PrandtlNumber is a nondimension number for CFD simulation
|
||||
PrandtlNumber = 0.7651
|
||||
|
||||
[Thermal]
|
||||
SpecificHeat = 0.8460 kJ/kg/K
|
||||
ThermalConductivity = 0.016242 W/m/K
|
||||
; thermal expansion coefficient of ideal gas is 1/temperature
|
||||
ThermalExpansionCoefficient = 3.43e-3 1/K
|
||||
|
||||
[Electromagnetic]
|
||||
RelativePermittivity = 1.0009217
|
||||
ElectricalConductivity = 1e-12 S/m
|
||||
RelativePermeability = 1.0
|
||||
@@ -1,24 +0,0 @@
|
||||
[General]
|
||||
Name = Nitrogen
|
||||
Description = Nitrogen properties at 20 Degrees Celsius and 1 atm
|
||||
MolarMass = 14.007
|
||||
Father = Gas
|
||||
|
||||
[Fluidic]
|
||||
Density = 1.2506 kg/m^3
|
||||
DynamicViscosity = 17.58e-6 kg/m/s
|
||||
; Kinematic Viscosity = Dynamic Viscosity / Density
|
||||
KinematicViscosity = 14.06e-6 m^2/s
|
||||
; PrandtlNumber is a nondimension number for CFD simulation
|
||||
PrandtlNumber = 0.7
|
||||
|
||||
[Thermal]
|
||||
SpecificHeat = 1.04 kJ/kg/K
|
||||
ThermalConductivity = 25.83e-3 W/m/K
|
||||
; thermal expansion coefficient of ideal gas is 1/temperature
|
||||
ThermalExpansionCoefficient = 3.43e-3 1/K
|
||||
|
||||
[Electromagnetic]
|
||||
RelativePermittivity = 1.00058
|
||||
ElectricalConductivity = 1e-12 S/m
|
||||
RelativePermeability = 1.0
|
||||
@@ -1,15 +0,0 @@
|
||||
; None means nothing, as the starting point of making a new fluid material
|
||||
|
||||
[General]
|
||||
Name = None
|
||||
Description = "None"
|
||||
|
||||
[Fluidic]
|
||||
Density = 0 kg/m^3
|
||||
DynamicViscosity = 0 kg/m/s
|
||||
KinematicViscosity = 0 m^2/s
|
||||
|
||||
[Thermal]
|
||||
SpecificHeat = 0 J/kg/K
|
||||
ThermalConductivity = 0 W/m/K
|
||||
ThermalExpansionCoefficient = 0 1/K
|
||||
@@ -1,31 +0,0 @@
|
||||
# FreeCAD fluid material library
|
||||
|
||||
It's intended to gather the most common fluid properties, water, air, which are useful for other modules and workbenches.
|
||||
|
||||
## User defined material
|
||||
|
||||
To prevent the database from becoming inefficiently large it is only limited to commonly used variables at 20 degrees Celsius at 1 atm.
|
||||
|
||||
Users can defined new material, either in Fem material card editor, or directly generate textual material file, * .FCMat, see example in this folder.
|
||||
|
||||
To enable new material, go to FreeCAD menu "Edit->Preference..." Cfd preference page (select on the left panel) and switch to materiai tab on the right.
|
||||
|
||||
Browse to your material folder, and save/apply this preference, new material will be Material with same name as FreeCAD material has higher priority, so user defined `Water` material will not appear in Fem material task panel's dropbox list, just give it a different name!
|
||||
|
||||
### Edit material value
|
||||
|
||||
Please verify the fluid material properties before use. It aims to serve as a quick reference and does not aim to be an extended look up table.
|
||||
|
||||
|
||||
## Add new material to Material module
|
||||
|
||||
1. follow examples in material folders to create new material file
|
||||
2. stick to the meta data definition in `src/Mod/Material/Templatematerial.yml` for property name
|
||||
3. add the file name into the `src/Mod/Material/CMakeLists.txt` , so the new files can be installed to the properly place during compiling and installation.
|
||||
|
||||
## Changelog
|
||||
|
||||
CfdOF module authored 5 material types, values are taken from FM White (2011) Fluid Mechanics.
|
||||
|
||||
Currently, 3 (Water, Air, None) are merged into Fem module and maintained by Cfd module author, Qingfeng Xia
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
; see meta data definition in the file: src/Mod/Material/Templatematerial.yml
|
||||
[General]
|
||||
Name = Water
|
||||
Description = Standard distilled water properties at 20 Degrees Celsius and 1 atm
|
||||
MolarMass = 18
|
||||
Father = Gas
|
||||
ReferenceSource = ''
|
||||
|
||||
[Fluidic]
|
||||
Density = 998 kg/m^3
|
||||
DynamicViscosity = 1.003e-3 kg/m/s
|
||||
KinematicViscosity = 1.005e-6 m^2/s
|
||||
; PrandtlNumber is a nondimension number for CFD simulation
|
||||
PrandtlNumber = 7.56
|
||||
|
||||
[Thermal]
|
||||
SpecificHeat = 4182 J/kg/K
|
||||
ThermalConductivity = 0.591 W/m/K
|
||||
; https://en.wikipedia.org/wiki/Water
|
||||
ThermalExpansionCoefficient = 2.07e-4 m/m/K
|
||||
|
||||
[Electromagnetic]
|
||||
RelativePermittivity = 80.0
|
||||
; at 20°C and 50Hz
|
||||
ElectricalConductivity = 5.5e-6 S/m
|
||||
RelativePermeability = 0.999992
|
||||
105
src/Mod/Material/Gui/AppMatGui.cpp
Normal file
105
src/Mod/Material/Gui/AppMatGui.cpp
Normal file
@@ -0,0 +1,105 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2023 David Carter <dcarter@david.carter.ca> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License (LGPL) *
|
||||
* as published by the Free Software Foundation; either version 2 of *
|
||||
* the License, or (at your option) any later version. *
|
||||
* for detail see the LICENCE text file. *
|
||||
* *
|
||||
* FreeCAD is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with FreeCAD; if not, write to the Free Software *
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||
* USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#include "PreCompiled.h"
|
||||
#ifndef _PreComp_
|
||||
#endif
|
||||
|
||||
#include <Base/Console.h>
|
||||
#include <Base/Interpreter.h>
|
||||
#include <Base/PyObjectBase.h>
|
||||
#include <Gui/Application.h>
|
||||
#include <Gui/Language/Translator.h>
|
||||
#include <Gui/WidgetFactory.h>
|
||||
|
||||
#include "DlgSettingsMaterial.h"
|
||||
|
||||
// use a different name to CreateCommand()
|
||||
void CreateMaterialCommands();
|
||||
|
||||
void loadMaterialResource()
|
||||
{
|
||||
// add resources and reloads the translators
|
||||
Q_INIT_RESOURCE(Material);
|
||||
Q_INIT_RESOURCE(Material_translation);
|
||||
Gui::Translator::instance()->refresh();
|
||||
}
|
||||
|
||||
namespace MatGui
|
||||
{
|
||||
class Module: public Py::ExtensionModule<Module>
|
||||
{
|
||||
public:
|
||||
Module()
|
||||
: Py::ExtensionModule<Module>("MatGui")
|
||||
{
|
||||
initialize("This module is the MatGui module.");// register with Python
|
||||
}
|
||||
|
||||
~Module() override
|
||||
{}
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
PyObject* initModule()
|
||||
{
|
||||
return Base::Interpreter().addModule(new Module);
|
||||
}
|
||||
|
||||
}// namespace MatGui
|
||||
|
||||
PyMOD_INIT_FUNC(MatGui)
|
||||
{
|
||||
if (!Gui::Application::Instance) {
|
||||
PyErr_SetString(PyExc_ImportError, "Cannot load Gui module in console application.");
|
||||
PyMOD_Return(nullptr);
|
||||
}
|
||||
|
||||
// load needed modules
|
||||
try {
|
||||
Base::Interpreter().runString("import Material");
|
||||
}
|
||||
catch (const Base::Exception& e) {
|
||||
PyErr_SetString(PyExc_ImportError, e.what());
|
||||
PyMOD_Return(nullptr);
|
||||
}
|
||||
|
||||
PyObject* matGuiModule = MatGui::initModule();
|
||||
|
||||
Base::Console().Log("Loading GUI of Material module... done\n");
|
||||
|
||||
// instantiating the commands
|
||||
CreateMaterialCommands();
|
||||
|
||||
// register preferences pages on Material, the order here will be the order of the tabs in pref
|
||||
// widget
|
||||
new Gui::PrefPageProducer<MatGui::DlgSettingsMaterial>(
|
||||
QT_TRANSLATE_NOOP("QObject", "Material"));
|
||||
|
||||
// add resources and reloads the translators
|
||||
loadMaterialResource();
|
||||
|
||||
PyMOD_Return(matGuiModule);
|
||||
}
|
||||
158
src/Mod/Material/Gui/Array2D.cpp
Normal file
158
src/Mod/Material/Gui/Array2D.cpp
Normal file
@@ -0,0 +1,158 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2023 David Carter <dcarter@david.carter.ca> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "PreCompiled.h"
|
||||
#ifndef _PreComp_
|
||||
#include <QMessageBox>
|
||||
#endif
|
||||
|
||||
#include <Gui/MainWindow.h>
|
||||
|
||||
#include <Mod/Material/App/Exceptions.h>
|
||||
#include <Mod/Material/App/Materials.h>
|
||||
|
||||
#include "Array2D.h"
|
||||
#include "ArrayDelegate.h"
|
||||
#include "ArrayModel.h"
|
||||
#include "ui_Array2D.h"
|
||||
|
||||
|
||||
using namespace MatGui;
|
||||
|
||||
/* TRANSLATOR MatGui::Array2D */
|
||||
|
||||
Array2D::Array2D(const QString& propertyName, Materials::Material* material, QWidget* parent)
|
||||
: QDialog(parent)
|
||||
, ui(new Ui_Array2D)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
if (material->hasPhysicalProperty(propertyName)) {
|
||||
_property = &(material->getPhysicalProperty(propertyName));
|
||||
}
|
||||
else if (material->hasAppearanceProperty(propertyName)) {
|
||||
_property = &(material->getAppearanceProperty(propertyName));
|
||||
}
|
||||
else {
|
||||
_property = nullptr;
|
||||
}
|
||||
if (_property) {
|
||||
_value = static_cast<Materials::Material2DArray*>(_property->getMaterialValue());
|
||||
}
|
||||
else {
|
||||
_value = nullptr;
|
||||
}
|
||||
|
||||
setupDefault();
|
||||
setupArray();
|
||||
|
||||
connect(ui->standardButtons, &QDialogButtonBox::accepted, this, &Array2D::accept);
|
||||
connect(ui->standardButtons, &QDialogButtonBox::rejected, this, &Array2D::reject);
|
||||
}
|
||||
|
||||
void Array2D::setupDefault()
|
||||
{
|
||||
if (_property == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
Materials::MaterialProperty& column1 = _property->getColumn(0);
|
||||
QString label = QString::fromStdString("Default ") + column1.getName();
|
||||
ui->labelDefault->setText(label);
|
||||
if (column1.getPropertyType() == QString::fromStdString("Quantity")) {
|
||||
ui->editDefault->setMinimum(std::numeric_limits<double>::min());
|
||||
ui->editDefault->setMaximum(std::numeric_limits<double>::max());
|
||||
ui->editDefault->setUnitText(_property->getColumnUnits(0));
|
||||
ui->editDefault->setValue(_value->getDefault().getValue().value<Base::Quantity>());
|
||||
|
||||
connect(ui->editDefault,
|
||||
qOverload<const Base::Quantity&>(&Gui::QuantitySpinBox::valueChanged),
|
||||
this,
|
||||
&Array2D::defaultValueChanged);
|
||||
}
|
||||
}
|
||||
catch (const Materials::PropertyNotFound&) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void Array2D::setHeaders(QStandardItemModel* model)
|
||||
{
|
||||
QStringList headers;
|
||||
auto columns = _property->getColumns();
|
||||
for (auto column = columns.begin(); column != columns.end(); column++) {
|
||||
headers.append(column->getName());
|
||||
}
|
||||
model->setHorizontalHeaderLabels(headers);
|
||||
}
|
||||
|
||||
void Array2D::setColumnWidths(QTableView* table)
|
||||
{
|
||||
int length = _property->columns();
|
||||
for (int i = 0; i < length; i++) {
|
||||
table->setColumnWidth(i, 100);
|
||||
}
|
||||
}
|
||||
|
||||
void Array2D::setColumnDelegates(QTableView* table)
|
||||
{
|
||||
int length = _property->columns();
|
||||
for (int i = 0; i < length; i++) {
|
||||
Materials::MaterialProperty& column = _property->getColumn(i);
|
||||
table->setItemDelegateForColumn(
|
||||
i,
|
||||
new ArrayDelegate(column.getType(), column.getUnits(), this));
|
||||
}
|
||||
}
|
||||
|
||||
void Array2D::setupArray()
|
||||
{
|
||||
if (_property == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto table = ui->tableView;
|
||||
auto model = new Array2DModel(_property, _value, this);
|
||||
table->setModel(model);
|
||||
table->setEditTriggers(QAbstractItemView::AllEditTriggers);
|
||||
|
||||
setColumnWidths(table);
|
||||
setColumnDelegates(table);
|
||||
}
|
||||
|
||||
void Array2D::defaultValueChanged(const Base::Quantity& value)
|
||||
{
|
||||
_value->setDefault(QVariant::fromValue(value));
|
||||
}
|
||||
|
||||
void Array2D::accept()
|
||||
{
|
||||
QDialog::accept();
|
||||
}
|
||||
|
||||
void Array2D::reject()
|
||||
{
|
||||
QDialog::reject();
|
||||
}
|
||||
|
||||
#include "moc_Array2D.cpp"
|
||||
68
src/Mod/Material/Gui/Array2D.h
Normal file
68
src/Mod/Material/Gui/Array2D.h
Normal file
@@ -0,0 +1,68 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2023 David Carter <dcarter@david.carter.ca> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef MATGUI_ARRAY2D_H
|
||||
#define MATGUI_ARRAY2D_H
|
||||
|
||||
#include <QAbstractTableModel>
|
||||
#include <QDialog>
|
||||
#include <QStandardItem>
|
||||
#include <QTableView>
|
||||
|
||||
#include "ArrayModel.h"
|
||||
#include <Mod/Material/App/Model.h>
|
||||
|
||||
namespace MatGui
|
||||
{
|
||||
|
||||
class Ui_Array2D;
|
||||
|
||||
class Array2D: public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit Array2D(const QString& propertyName,
|
||||
Materials::Material* material,
|
||||
QWidget* parent = nullptr);
|
||||
~Array2D() override = default;
|
||||
|
||||
void defaultValueChanged(const Base::Quantity& value);
|
||||
|
||||
void accept() override;
|
||||
void reject() override;
|
||||
|
||||
private:
|
||||
std::unique_ptr<Ui_Array2D> ui;
|
||||
Materials::MaterialProperty* _property;
|
||||
Materials::Material2DArray* _value;
|
||||
|
||||
void setupDefault();
|
||||
void setHeaders(QStandardItemModel* model);
|
||||
void setColumnWidths(QTableView* table);
|
||||
void setColumnDelegates(QTableView* table);
|
||||
void setupArray();
|
||||
};
|
||||
|
||||
}// namespace MatGui
|
||||
|
||||
#endif// MATGUI_ARRAY2D_H
|
||||
92
src/Mod/Material/Gui/Array2D.ui
Normal file
92
src/Mod/Material/Gui/Array2D.ui
Normal file
@@ -0,0 +1,92 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>MatGui::Array2D</class>
|
||||
<widget class="QDialog" name="MatGui::Array2D">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>578</width>
|
||||
<height>557</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>2D Array</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="labelDefault">
|
||||
<property name="text">
|
||||
<string>Default Value</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Gui::QuantitySpinBox" name="editDefault" native="true">
|
||||
<property name="unit" stdset="0">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTableView" name="tableView"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="standardButtons">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>Gui::QuantitySpinBox</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>Gui/QuantitySpinBox.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>standardButtons</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>MatGui::Array2D</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>standardButtons</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>MatGui::Array2D</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
198
src/Mod/Material/Gui/Array3D.cpp
Normal file
198
src/Mod/Material/Gui/Array3D.cpp
Normal file
@@ -0,0 +1,198 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2023 David Carter <dcarter@david.carter.ca> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "PreCompiled.h"
|
||||
#ifndef _PreComp_
|
||||
#include <QMessageBox>
|
||||
#include <QPushButton>
|
||||
#endif
|
||||
|
||||
#include <Gui/MainWindow.h>
|
||||
|
||||
#include <Mod/Material/App/Exceptions.h>
|
||||
#include <Mod/Material/App/Materials.h>
|
||||
|
||||
#include "Array3D.h"
|
||||
#include "ArrayDelegate.h"
|
||||
#include "ArrayModel.h"
|
||||
#include "ui_Array3D.h"
|
||||
|
||||
|
||||
using namespace MatGui;
|
||||
|
||||
Array3D::Array3D(const QString& propertyName, Materials::Material* material, QWidget* parent)
|
||||
: QDialog(parent)
|
||||
, ui(new Ui_Array3D)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
if (material->hasPhysicalProperty(propertyName)) {
|
||||
_property = &(material->getPhysicalProperty(propertyName));
|
||||
}
|
||||
else if (material->hasAppearanceProperty(propertyName)) {
|
||||
_property = &(material->getAppearanceProperty(propertyName));
|
||||
}
|
||||
else {
|
||||
_property = nullptr;
|
||||
}
|
||||
if (_property) {
|
||||
_value = static_cast<Materials::Material3DArray*>(_property->getMaterialValue());
|
||||
}
|
||||
else {
|
||||
_value = nullptr;
|
||||
}
|
||||
|
||||
setupDefault();
|
||||
setupDepthArray();
|
||||
setupArray();
|
||||
|
||||
Base::Console().Log("Material '%s'\n", material->getName().toStdString().c_str());
|
||||
Base::Console().Log("\tproperty '%s'\n", propertyName.toStdString().c_str());
|
||||
|
||||
// connect(ui->splitter, &QSplitter::event,
|
||||
// this, &Array3D::onSplitter);
|
||||
|
||||
connect(ui->standardButtons->button(QDialogButtonBox::Ok),
|
||||
&QPushButton::clicked,
|
||||
this,
|
||||
&Array3D::onOk);
|
||||
connect(ui->standardButtons->button(QDialogButtonBox::Cancel),
|
||||
&QPushButton::clicked,
|
||||
this,
|
||||
&Array3D::onCancel);
|
||||
}
|
||||
|
||||
bool Array3D::onSplitter(QEvent* e)
|
||||
{
|
||||
Q_UNUSED(e)
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Array3D::setupDefault()
|
||||
{
|
||||
if (_property == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
Materials::MaterialProperty& column1 = _property->getColumn(0);
|
||||
QString label = QString::fromStdString("Default ") + column1.getName();
|
||||
ui->labelDefault->setText(label);
|
||||
if (column1.getPropertyType() == QString::fromStdString("Quantity")) {
|
||||
ui->editDefault->setMinimum(std::numeric_limits<double>::min());
|
||||
ui->editDefault->setMaximum(std::numeric_limits<double>::max());
|
||||
ui->editDefault->setUnitText(_property->getColumnUnits(0));
|
||||
ui->editDefault->setValue(_value->getDefault().getValue().value<Base::Quantity>());
|
||||
|
||||
connect(ui->editDefault,
|
||||
qOverload<const Base::Quantity&>(&Gui::QuantitySpinBox::valueChanged),
|
||||
this,
|
||||
&Array3D::defaultValueChanged);
|
||||
}
|
||||
}
|
||||
catch (const Materials::PropertyNotFound&) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void Array3D::defaultValueChanged(const Base::Quantity& value)
|
||||
{
|
||||
_value->setDefault(QVariant::fromValue(value));
|
||||
}
|
||||
|
||||
void Array3D::setDepthColumnDelegate(QTableView* table)
|
||||
{
|
||||
Materials::MaterialProperty& column = _property->getColumn(0);
|
||||
table->setItemDelegateForColumn(0,
|
||||
new ArrayDelegate(column.getType(), column.getUnits(), this));
|
||||
}
|
||||
|
||||
void Array3D::setDepthColumnWidth(QTableView* table)
|
||||
{
|
||||
table->setColumnWidth(0, 100);
|
||||
}
|
||||
|
||||
void Array3D::setupDepthArray()
|
||||
{
|
||||
if (_property == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto table = ui->table3D;
|
||||
auto model = new Array3DDepthModel(_property, _value, this);
|
||||
table->setModel(model);
|
||||
table->setEditTriggers(QAbstractItemView::AllEditTriggers);
|
||||
|
||||
setDepthColumnWidth(table);
|
||||
setDepthColumnDelegate(table);
|
||||
}
|
||||
|
||||
void Array3D::setColumnWidths(QTableView* table)
|
||||
{
|
||||
int length = _property->columns();
|
||||
for (int i = 0; i < length; i++) {
|
||||
table->setColumnWidth(i, 100);
|
||||
}
|
||||
}
|
||||
|
||||
void Array3D::setColumnDelegates(QTableView* table)
|
||||
{
|
||||
int length = _property->columns();
|
||||
for (int i = 0; i < length; i++) {
|
||||
Materials::MaterialProperty& column = _property->getColumn(i);
|
||||
table->setItemDelegateForColumn(
|
||||
i,
|
||||
new ArrayDelegate(column.getType(), column.getUnits(), this));
|
||||
}
|
||||
}
|
||||
|
||||
void Array3D::setupArray()
|
||||
{
|
||||
if (_property == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto table = ui->table2D;
|
||||
auto model = new Array3DModel(_property, _value, this);
|
||||
table->setModel(model);
|
||||
table->setEditTriggers(QAbstractItemView::AllEditTriggers);
|
||||
|
||||
setColumnWidths(table);
|
||||
setColumnDelegates(table);
|
||||
}
|
||||
|
||||
void Array3D::onOk(bool checked)
|
||||
{
|
||||
Q_UNUSED(checked)
|
||||
|
||||
QDialog::accept();
|
||||
}
|
||||
|
||||
void Array3D::onCancel(bool checked)
|
||||
{
|
||||
Q_UNUSED(checked)
|
||||
|
||||
QDialog::reject();
|
||||
}
|
||||
|
||||
#include "moc_Array3D.cpp"
|
||||
67
src/Mod/Material/Gui/Array3D.h
Normal file
67
src/Mod/Material/Gui/Array3D.h
Normal file
@@ -0,0 +1,67 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2023 David Carter <dcarter@david.carter.ca> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef MATGUI_ARRAY3D_H
|
||||
#define MATGUI_ARRAY3D_H
|
||||
|
||||
#include <QDialog>
|
||||
#include <QStandardItem>
|
||||
#include <QTableView>
|
||||
|
||||
namespace MatGui
|
||||
{
|
||||
|
||||
class Ui_Array3D;
|
||||
|
||||
class Array3D: public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit Array3D(const QString& propertyName,
|
||||
Materials::Material* material,
|
||||
QWidget* parent = nullptr);
|
||||
~Array3D() override = default;
|
||||
|
||||
void defaultValueChanged(const Base::Quantity& value);
|
||||
bool onSplitter(QEvent* e);
|
||||
|
||||
void onOk(bool checked);
|
||||
void onCancel(bool checked);
|
||||
|
||||
private:
|
||||
std::unique_ptr<Ui_Array3D> ui;
|
||||
Materials::MaterialProperty* _property;
|
||||
Materials::Material3DArray* _value;
|
||||
|
||||
void setupDefault();
|
||||
void setDepthColumnWidth(QTableView* table);
|
||||
void setDepthColumnDelegate(QTableView* table);
|
||||
void setupDepthArray();
|
||||
void setColumnWidths(QTableView* table);
|
||||
void setColumnDelegates(QTableView* table);
|
||||
void setupArray();
|
||||
};
|
||||
|
||||
}// namespace MatGui
|
||||
|
||||
#endif// MATGUI_ARRAY3D_H
|
||||
104
src/Mod/Material/Gui/Array3D.ui
Normal file
104
src/Mod/Material/Gui/Array3D.ui
Normal file
@@ -0,0 +1,104 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>MatGui::Array3D</class>
|
||||
<widget class="QDialog" name="MatGui::Array3D">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>915</width>
|
||||
<height>709</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>3D Array</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="labelDefault">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Default Value</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Gui::QuantitySpinBox" name="editDefault" native="true">
|
||||
<property name="unit" stdset="0">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSplitter" name="splitter">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<widget class="QTableView" name="table3D"/>
|
||||
<widget class="QTableView" name="table2D"/>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="standardButtons">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>Gui::QuantitySpinBox</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>Gui/QuantitySpinBox.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>standardButtons</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>MatGui::Array3D</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>standardButtons</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>MatGui::Array3D</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
184
src/Mod/Material/Gui/ArrayDelegate.cpp
Normal file
184
src/Mod/Material/Gui/ArrayDelegate.cpp
Normal file
@@ -0,0 +1,184 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2023 David Carter <dcarter@david.carter.ca> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "PreCompiled.h"
|
||||
#ifndef _PreComp_
|
||||
#include <QColorDialog>
|
||||
#include <QDesktopServices>
|
||||
#include <QIODevice>
|
||||
#include <QItemSelectionModel>
|
||||
#include <QPainter>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include <QTextStream>
|
||||
#include <QVariant>
|
||||
#endif
|
||||
|
||||
#include <limits>
|
||||
|
||||
#include <App/Application.h>
|
||||
#include <Base/Interpreter.h>
|
||||
#include <Base/Quantity.h>
|
||||
#include <Gui/Application.h>
|
||||
#include <Gui/Command.h>
|
||||
#include <Gui/InputField.h>
|
||||
#include <Gui/PrefWidgets.h>
|
||||
#include <Gui/SpinBox.h>
|
||||
#include <Gui/WaitCursor.h>
|
||||
// #include <Gui/FileDialog.h>
|
||||
|
||||
#include <Mod/Material/App/Exceptions.h>
|
||||
#include <Mod/Material/App/ModelManager.h>
|
||||
|
||||
#include "Array2D.h"
|
||||
#include "Array3D.h"
|
||||
#include "ArrayDelegate.h"
|
||||
#include "MaterialSave.h"
|
||||
|
||||
|
||||
using namespace MatGui;
|
||||
|
||||
ArrayDelegate::ArrayDelegate(Materials::MaterialValue::ValueType type,
|
||||
QString units,
|
||||
QObject* parent)
|
||||
: QStyledItemDelegate(parent)
|
||||
, _type(type)
|
||||
, _units(units)
|
||||
{}
|
||||
|
||||
void ArrayDelegate::paint(QPainter* painter,
|
||||
const QStyleOptionViewItem& option,
|
||||
const QModelIndex& index) const
|
||||
{
|
||||
|
||||
if (_type == Materials::MaterialValue::Quantity) {
|
||||
const AbstractArrayModel* tableModel =
|
||||
reinterpret_cast<const AbstractArrayModel*>(index.model());
|
||||
painter->save();
|
||||
|
||||
if (tableModel->newRow(index)) {
|
||||
painter->drawText(option.rect, 0, QString());
|
||||
}
|
||||
else {
|
||||
QVariant item = tableModel->data(index);
|
||||
Base::Quantity quantity = item.value<Base::Quantity>();
|
||||
QString text = quantity.getUserString();
|
||||
painter->drawText(option.rect, 0, text);
|
||||
}
|
||||
|
||||
painter->restore();
|
||||
}
|
||||
else {
|
||||
QStyledItemDelegate::paint(painter, option, index);
|
||||
}
|
||||
}
|
||||
|
||||
void ArrayDelegate::setEditorData(QWidget* editor, const QModelIndex& index) const
|
||||
{
|
||||
Base::Console().Log("ArrayDelegate::setEditorData()\n");
|
||||
|
||||
if (_type == Materials::MaterialValue::Quantity) {
|
||||
QAbstractItemModel* tableModel = const_cast<QAbstractItemModel*>(index.model());
|
||||
auto item = tableModel->data(index);
|
||||
|
||||
// Gui::InputField* input = static_cast<Gui::InputField*>(editor);
|
||||
// input->setText(item.toString());
|
||||
Gui::QuantitySpinBox* input = static_cast<Gui::QuantitySpinBox*>(editor);
|
||||
input->setValue(item.value<Base::Quantity>());
|
||||
}
|
||||
else {
|
||||
QStyledItemDelegate::setEditorData(editor, index);
|
||||
}
|
||||
}
|
||||
|
||||
QWidget* ArrayDelegate::createEditor(QWidget* parent,
|
||||
const QStyleOptionViewItem&,
|
||||
const QModelIndex& index) const
|
||||
{
|
||||
Base::Console().Log("ArrayDelegate::createEditor()\n");
|
||||
|
||||
const QAbstractTableModel* tableModel = static_cast<const QAbstractTableModel*>(index.model());
|
||||
auto item = tableModel->data(index);
|
||||
|
||||
QWidget* editor = createWidget(parent, item);
|
||||
|
||||
return editor;
|
||||
}
|
||||
|
||||
QWidget* ArrayDelegate::createWidget(QWidget* parent, const QVariant& item) const
|
||||
{
|
||||
QWidget* widget = nullptr;
|
||||
|
||||
if (_type == Materials::MaterialValue::String || _type == Materials::MaterialValue::URL
|
||||
|| _type == Materials::MaterialValue::List) {
|
||||
widget = new Gui::PrefLineEdit(parent);
|
||||
}
|
||||
else if (_type == Materials::MaterialValue::Integer) {
|
||||
Gui::UIntSpinBox* spinner = new Gui::UIntSpinBox(parent);
|
||||
spinner->setMinimum(0);
|
||||
spinner->setMaximum(UINT_MAX);
|
||||
spinner->setValue(item.toUInt());
|
||||
widget = spinner;
|
||||
}
|
||||
else if (_type == Materials::MaterialValue::Float) {
|
||||
Gui::DoubleSpinBox* spinner = new Gui::DoubleSpinBox(parent);
|
||||
|
||||
// the magnetic permeability is the parameter for which many decimals matter
|
||||
// the most however, even for this, 6 digits are sufficient
|
||||
spinner->setDecimals(6);
|
||||
|
||||
// for almost all Float parameters of materials a step of 1 would be too large
|
||||
spinner->setSingleStep(0.1);
|
||||
|
||||
spinner->setMinimum(std::numeric_limits<double>::min());
|
||||
spinner->setMaximum(std::numeric_limits<double>::max());
|
||||
spinner->setValue(item.toDouble());
|
||||
widget = spinner;
|
||||
}
|
||||
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->setCurrentText(item.toString());
|
||||
widget = combo;
|
||||
}
|
||||
else if (_type == Materials::MaterialValue::Quantity) {
|
||||
Gui::QuantitySpinBox* input = new Gui::QuantitySpinBox();
|
||||
input->setMinimum(std::numeric_limits<double>::min());
|
||||
input->setMaximum(std::numeric_limits<double>::max());
|
||||
input->setUnitText(_units);
|
||||
input->setValue(item.value<Base::Quantity>());
|
||||
|
||||
widget = input;
|
||||
}
|
||||
else {
|
||||
// Default editor
|
||||
widget = new QLineEdit(parent);
|
||||
}
|
||||
|
||||
widget->setParent(parent);
|
||||
|
||||
return widget;
|
||||
}
|
||||
|
||||
#include "moc_ArrayDelegate.cpp"
|
||||
75
src/Mod/Material/Gui/ArrayDelegate.h
Normal file
75
src/Mod/Material/Gui/ArrayDelegate.h
Normal file
@@ -0,0 +1,75 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2023 David Carter <dcarter@david.carter.ca> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef MATGUI_ArrayDelegate_H
|
||||
#define MATGUI_ArrayDelegate_H
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
#include <QDialog>
|
||||
#include <QDir>
|
||||
#include <QStandardItem>
|
||||
#include <QStyledItemDelegate>
|
||||
#include <QSvgWidget>
|
||||
#include <QTreeView>
|
||||
|
||||
#include <Mod/Material/App/MaterialManager.h>
|
||||
#include <Mod/Material/App/Materials.h>
|
||||
#include <Mod/Material/App/ModelManager.h>
|
||||
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
namespace MatGui
|
||||
{
|
||||
|
||||
class ArrayDelegate: public QStyledItemDelegate
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ArrayDelegate(
|
||||
Materials::MaterialValue::ValueType type = Materials::MaterialValue::None,
|
||||
QString units = QString(),
|
||||
QObject* parent = nullptr);
|
||||
virtual ~ArrayDelegate() = default;
|
||||
|
||||
void paint(QPainter* painter,
|
||||
const QStyleOptionViewItem& option,
|
||||
const QModelIndex& index) const override;
|
||||
QWidget* createEditor(QWidget* parent,
|
||||
const QStyleOptionViewItem&,
|
||||
const QModelIndex& index) const override;
|
||||
void setEditorData(QWidget* editor, const QModelIndex& index) const override;
|
||||
|
||||
// Q_SIGNALS:
|
||||
/** Emits this signal when a property has changed */
|
||||
// void propertyChange(const QString &property, const QString value);
|
||||
|
||||
private:
|
||||
Materials::MaterialValue::ValueType _type;
|
||||
QString _units;
|
||||
|
||||
QWidget* createWidget(QWidget* parent, const QVariant& item) const;
|
||||
};
|
||||
|
||||
}// namespace MatGui
|
||||
|
||||
#endif// MATGUI_ArrayDelegate_H
|
||||
466
src/Mod/Material/Gui/ArrayModel.cpp
Normal file
466
src/Mod/Material/Gui/ArrayModel.cpp
Normal file
@@ -0,0 +1,466 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2023 David Carter <dcarter@david.carter.ca> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "PreCompiled.h"
|
||||
#ifndef _PreComp_
|
||||
#include <QMessageBox>
|
||||
#endif
|
||||
|
||||
#include <QMetaType>
|
||||
|
||||
#include <Gui/MainWindow.h>
|
||||
#include <Gui/MetaTypes.h>
|
||||
|
||||
#include <Mod/Material/App/Exceptions.h>
|
||||
#include <Mod/Material/App/Materials.h>
|
||||
|
||||
#include "ArrayModel.h"
|
||||
|
||||
|
||||
using namespace MatGui;
|
||||
|
||||
/* TRANSLATOR MatGui::ArrayModel */
|
||||
|
||||
AbstractArrayModel::AbstractArrayModel(QObject* parent)
|
||||
: QAbstractTableModel(parent)
|
||||
{}
|
||||
|
||||
//===
|
||||
|
||||
|
||||
Array2DModel::Array2DModel(Materials::MaterialProperty* property,
|
||||
Materials::Material2DArray* value,
|
||||
QObject* parent)
|
||||
: AbstractArrayModel(parent)
|
||||
, _property(property)
|
||||
, _value(value)
|
||||
{}
|
||||
|
||||
int Array2DModel::rowCount(const QModelIndex& parent) const
|
||||
{
|
||||
if (parent.isValid()) {
|
||||
return 0;// No children
|
||||
}
|
||||
|
||||
return _value->rows() + 1;// Will always have 1 empty row
|
||||
}
|
||||
|
||||
bool Array2DModel::newRow(const QModelIndex& index) const
|
||||
{
|
||||
return (index.row() == _value->rows());
|
||||
}
|
||||
|
||||
int Array2DModel::columnCount(const QModelIndex& parent) const
|
||||
{
|
||||
Q_UNUSED(parent);
|
||||
|
||||
return _property->columns();
|
||||
}
|
||||
|
||||
QVariant Array2DModel::data(const QModelIndex& index, int role) const
|
||||
{
|
||||
if (role == Qt::DisplayRole) {
|
||||
try {
|
||||
return _value->getValue(index.row(), index.column());
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
catch (const Materials::InvalidColumn&) {
|
||||
}
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QVariant Array2DModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
if (role == Qt::DisplayRole) {
|
||||
if (orientation == Qt::Horizontal) {
|
||||
Materials::MaterialProperty& column = _property->getColumn(section);
|
||||
return QVariant(column.getName());
|
||||
}
|
||||
else if (orientation == Qt::Vertical) {
|
||||
// Vertical header
|
||||
if (section == (rowCount() - 1)) {
|
||||
return QVariant(QString::fromStdString("*"));
|
||||
}
|
||||
return QVariant(section + 1);
|
||||
}
|
||||
}
|
||||
|
||||
return QAbstractTableModel::headerData(section, orientation, role);
|
||||
}
|
||||
|
||||
bool Array2DModel::setData(const QModelIndex& index, const QVariant& value, int role)
|
||||
{
|
||||
Q_UNUSED(role);
|
||||
|
||||
if (index.row() == _value->rows()) {
|
||||
insertRows(index.row(), 1);
|
||||
}
|
||||
_value->setValue(index.row(), index.column(), value);
|
||||
|
||||
Q_EMIT dataChanged(index, index);
|
||||
return true;
|
||||
}
|
||||
|
||||
Qt::ItemFlags Array2DModel::flags(const QModelIndex& index) const
|
||||
{
|
||||
return (QAbstractTableModel::flags(index) | Qt::ItemIsEditable);
|
||||
}
|
||||
|
||||
|
||||
// Resizing functions
|
||||
bool Array2DModel::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<QVariant>* rowPtr = new std::vector<QVariant>();
|
||||
for (int j = 0; j < columns; j++) {
|
||||
rowPtr->push_back(_property->getColumnNull(j));
|
||||
}
|
||||
|
||||
_value->insertRow(row, rowPtr);
|
||||
}
|
||||
|
||||
endInsertRows();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Array2DModel::removeRows(int row, int count, const QModelIndex& parent)
|
||||
{
|
||||
beginRemoveRows(parent, row, row + count - 1);
|
||||
|
||||
endRemoveRows();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Array2DModel::insertColumns(int column, int count, const QModelIndex& parent)
|
||||
{
|
||||
Q_UNUSED(column);
|
||||
Q_UNUSED(count);
|
||||
Q_UNUSED(parent);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Array2DModel::removeColumns(int column, int count, const QModelIndex& parent)
|
||||
{
|
||||
Q_UNUSED(column);
|
||||
Q_UNUSED(count);
|
||||
Q_UNUSED(parent);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//===
|
||||
|
||||
Array3DDepthModel::Array3DDepthModel(Materials::MaterialProperty* property,
|
||||
Materials::Material3DArray* value,
|
||||
QObject* parent)
|
||||
: AbstractArrayModel(parent)
|
||||
, _property(property)
|
||||
, _value(value)
|
||||
{}
|
||||
|
||||
int Array3DDepthModel::rowCount(const QModelIndex& parent) const
|
||||
{
|
||||
if (parent.isValid()) {
|
||||
return 0;// No children
|
||||
}
|
||||
|
||||
return _value->depth() + 1;// Will always have 1 empty row
|
||||
}
|
||||
|
||||
bool Array3DDepthModel::newRow(const QModelIndex& index) const
|
||||
{
|
||||
return (index.row() == _value->depth());
|
||||
}
|
||||
|
||||
QVariant Array3DDepthModel::data(const QModelIndex& index, int role) const
|
||||
{
|
||||
if (role == Qt::DisplayRole) {
|
||||
try {
|
||||
return _value->getValue(index.row(), index.column());
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
catch (const Materials::InvalidColumn&) {
|
||||
}
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QVariant Array3DDepthModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
if (role == Qt::DisplayRole) {
|
||||
if (orientation == Qt::Horizontal) {
|
||||
Materials::MaterialProperty& column = _property->getColumn(section);
|
||||
return QVariant(column.getName());
|
||||
}
|
||||
else if (orientation == Qt::Vertical) {
|
||||
// Vertical header
|
||||
if (section == (rowCount() - 1)) {
|
||||
return QVariant(QString::fromStdString("*"));
|
||||
}
|
||||
return QVariant(section + 1);
|
||||
}
|
||||
}
|
||||
|
||||
return QAbstractTableModel::headerData(section, orientation, role);
|
||||
}
|
||||
|
||||
bool Array3DDepthModel::setData(const QModelIndex& index, const QVariant& value, int role)
|
||||
{
|
||||
Q_UNUSED(role);
|
||||
|
||||
if (index.row() == _value->depth()) {
|
||||
insertRows(index.row(), 1);
|
||||
}
|
||||
_value->setValue(index.row(), index.column(), value);
|
||||
|
||||
Q_EMIT dataChanged(index, index);
|
||||
return true;
|
||||
}
|
||||
|
||||
Qt::ItemFlags Array3DDepthModel::flags(const QModelIndex& index) const
|
||||
{
|
||||
return (QAbstractTableModel::flags(index) | Qt::ItemIsEditable);
|
||||
}
|
||||
|
||||
|
||||
// Resizing functions
|
||||
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<QVariant>* rowPtr = new std::vector<QVariant>();
|
||||
for (int j = 0; j < columns; j++) {
|
||||
rowPtr->push_back(_property->getColumnNull(j));
|
||||
}
|
||||
|
||||
// _value->insertRow(row, rowPtr);
|
||||
}
|
||||
|
||||
endInsertRows();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Array3DDepthModel::removeRows(int row, int count, const QModelIndex& parent)
|
||||
{
|
||||
beginRemoveRows(parent, row, row + count - 1);
|
||||
|
||||
endRemoveRows();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Array3DDepthModel::insertColumns(int column, int count, const QModelIndex& parent)
|
||||
{
|
||||
Q_UNUSED(column);
|
||||
Q_UNUSED(count);
|
||||
Q_UNUSED(parent);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Array3DDepthModel::removeColumns(int column, int count, const QModelIndex& parent)
|
||||
{
|
||||
Q_UNUSED(column);
|
||||
Q_UNUSED(count);
|
||||
Q_UNUSED(parent);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//===
|
||||
|
||||
Array3DModel::Array3DModel(Materials::MaterialProperty* property,
|
||||
Materials::Material3DArray* value,
|
||||
QObject* parent)
|
||||
: AbstractArrayModel(parent)
|
||||
, _property(property)
|
||||
, _value(value)
|
||||
{}
|
||||
|
||||
int Array3DModel::rowCount(const QModelIndex& parent) const
|
||||
{
|
||||
if (parent.isValid()) {
|
||||
return 0;// No children
|
||||
}
|
||||
|
||||
return _value->depth() + 1;// Will always have 1 empty row
|
||||
}
|
||||
|
||||
int Array3DModel::columnCount(const QModelIndex& parent) const
|
||||
{
|
||||
Q_UNUSED(parent);
|
||||
|
||||
return _property->columns() - 1;
|
||||
}
|
||||
|
||||
bool Array3DModel::newRow(const QModelIndex& index) const
|
||||
{
|
||||
return (index.row() == _value->depth());
|
||||
}
|
||||
|
||||
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());
|
||||
try {
|
||||
return _value->getValue(index.row(), index.column() + 1);
|
||||
}
|
||||
catch (const Materials::InvalidIndex&) {
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
Base::Console().Error("The error message is: %s\n", e.what());
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
catch (const Materials::InvalidColumn&) {
|
||||
}
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QVariant Array3DModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
if (role == Qt::DisplayRole) {
|
||||
if (orientation == Qt::Horizontal) {
|
||||
Materials::MaterialProperty& column = _property->getColumn(section + 1);
|
||||
return QVariant(column.getName());
|
||||
}
|
||||
else if (orientation == Qt::Vertical) {
|
||||
// Vertical header
|
||||
if (section == (rowCount() - 1)) {
|
||||
return QVariant(QString::fromStdString("*"));
|
||||
}
|
||||
return QVariant(section + 1);
|
||||
}
|
||||
}
|
||||
|
||||
return QAbstractTableModel::headerData(section, orientation, role);
|
||||
}
|
||||
|
||||
bool Array3DModel::setData(const QModelIndex& index, const QVariant& value, int role)
|
||||
{
|
||||
Q_UNUSED(role);
|
||||
|
||||
if (index.row() == _value->depth()) {
|
||||
insertRows(index.row(), 1);
|
||||
}
|
||||
_value->setValue(index.row(), index.column(), value);
|
||||
|
||||
Q_EMIT dataChanged(index, index);
|
||||
return true;
|
||||
}
|
||||
|
||||
Qt::ItemFlags Array3DModel::flags(const QModelIndex& index) const
|
||||
{
|
||||
return (QAbstractTableModel::flags(index) | Qt::ItemIsEditable);
|
||||
}
|
||||
|
||||
|
||||
// Resizing functions
|
||||
bool Array3DModel::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<QVariant>* rowPtr = new std::vector<QVariant>();
|
||||
for (int j = 0; j < columns; j++) {
|
||||
rowPtr->push_back(_property->getColumnNull(j));
|
||||
}
|
||||
|
||||
// _value->insertRow(row, rowPtr);
|
||||
}
|
||||
|
||||
endInsertRows();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Array3DModel::removeRows(int row, int count, const QModelIndex& parent)
|
||||
{
|
||||
beginRemoveRows(parent, row, row + count - 1);
|
||||
|
||||
endRemoveRows();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Array3DModel::insertColumns(int column, int count, const QModelIndex& parent)
|
||||
{
|
||||
Q_UNUSED(column);
|
||||
Q_UNUSED(count);
|
||||
Q_UNUSED(parent);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Array3DModel::removeColumns(int column, int count, const QModelIndex& parent)
|
||||
{
|
||||
Q_UNUSED(column);
|
||||
Q_UNUSED(count);
|
||||
Q_UNUSED(parent);
|
||||
|
||||
return false;
|
||||
}
|
||||
139
src/Mod/Material/Gui/ArrayModel.h
Normal file
139
src/Mod/Material/Gui/ArrayModel.h
Normal file
@@ -0,0 +1,139 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2023 David Carter <dcarter@david.carter.ca> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef MATGUI_ARRAYMODEL_H
|
||||
#define MATGUI_ARRAYMODEL_H
|
||||
|
||||
#include <QAbstractTableModel>
|
||||
#include <QDialog>
|
||||
#include <QStandardItem>
|
||||
#include <QTableView>
|
||||
|
||||
#include <Mod/Material/App/Materials.h>
|
||||
#include <Mod/Material/App/Model.h>
|
||||
|
||||
namespace MatGui
|
||||
{
|
||||
|
||||
class AbstractArrayModel: public QAbstractTableModel
|
||||
{
|
||||
public:
|
||||
explicit AbstractArrayModel(QObject* parent = nullptr);
|
||||
~AbstractArrayModel() override = default;
|
||||
|
||||
virtual bool newRow(const QModelIndex& index) const = 0;
|
||||
};
|
||||
|
||||
class Array2DModel: public AbstractArrayModel
|
||||
{
|
||||
public:
|
||||
explicit Array2DModel(Materials::MaterialProperty* property = nullptr,
|
||||
Materials::Material2DArray* 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;
|
||||
int columnCount(const QModelIndex& parent = QModelIndex()) const override;
|
||||
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
|
||||
QVariant
|
||||
headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
|
||||
bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) override;
|
||||
Qt::ItemFlags flags(const QModelIndex& index) const override;
|
||||
|
||||
// Resizing functions
|
||||
bool insertRows(int row, int count, const QModelIndex& parent = QModelIndex()) override;
|
||||
bool removeRows(int row, int count, const QModelIndex& parent = QModelIndex()) override;
|
||||
bool insertColumns(int column, int count, const QModelIndex& parent = QModelIndex()) override;
|
||||
bool removeColumns(int column, int count, const QModelIndex& parent = QModelIndex()) override;
|
||||
|
||||
private:
|
||||
Materials::MaterialProperty* _property;
|
||||
Materials::Material2DArray* _value;
|
||||
};
|
||||
|
||||
class Array3DDepthModel: public AbstractArrayModel
|
||||
{
|
||||
public:
|
||||
explicit Array3DDepthModel(Materials::MaterialProperty* property = nullptr,
|
||||
Materials::Material3DArray* 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;
|
||||
int columnCount(const QModelIndex& parent = QModelIndex()) const override
|
||||
{
|
||||
Q_UNUSED(parent)
|
||||
return 1;
|
||||
}
|
||||
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
|
||||
QVariant
|
||||
headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
|
||||
bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) override;
|
||||
Qt::ItemFlags flags(const QModelIndex& index) const override;
|
||||
|
||||
// Resizing functions
|
||||
bool insertRows(int row, int count, const QModelIndex& parent = QModelIndex()) override;
|
||||
bool removeRows(int row, int count, const QModelIndex& parent = QModelIndex()) override;
|
||||
bool insertColumns(int column, int count, const QModelIndex& parent = QModelIndex()) override;
|
||||
bool removeColumns(int column, int count, const QModelIndex& parent = QModelIndex()) override;
|
||||
|
||||
private:
|
||||
Materials::MaterialProperty* _property;
|
||||
Materials::Material3DArray* _value;
|
||||
};
|
||||
|
||||
class Array3DModel: public AbstractArrayModel
|
||||
{
|
||||
public:
|
||||
explicit Array3DModel(Materials::MaterialProperty* property = nullptr,
|
||||
Materials::Material3DArray* 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;
|
||||
int columnCount(const QModelIndex& parent = QModelIndex()) const override;
|
||||
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
|
||||
QVariant
|
||||
headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
|
||||
bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) override;
|
||||
Qt::ItemFlags flags(const QModelIndex& index) const override;
|
||||
|
||||
// Resizing functions
|
||||
bool insertRows(int row, int count, const QModelIndex& parent = QModelIndex()) override;
|
||||
bool removeRows(int row, int count, const QModelIndex& parent = QModelIndex()) override;
|
||||
bool insertColumns(int column, int count, const QModelIndex& parent = QModelIndex()) override;
|
||||
bool removeColumns(int column, int count, const QModelIndex& parent = QModelIndex()) override;
|
||||
|
||||
private:
|
||||
Materials::MaterialProperty* _property;
|
||||
Materials::Material3DArray* _value;
|
||||
};
|
||||
|
||||
}// namespace MatGui
|
||||
|
||||
#endif// MATGUI_ARRAYMODEL_H
|
||||
106
src/Mod/Material/Gui/CMakeLists.txt
Normal file
106
src/Mod/Material/Gui/CMakeLists.txt
Normal file
@@ -0,0 +1,106 @@
|
||||
if(MSVC)
|
||||
add_definitions(-DHAVE_ACOSH -DHAVE_ATANH -DHAVE_ASINH)
|
||||
else(MSVC)
|
||||
add_definitions(-DHAVE_LIMITS_H -DHAVE_CONFIG_H)
|
||||
endif(MSVC)
|
||||
|
||||
include_directories(
|
||||
${CMAKE_BINARY_DIR}
|
||||
${CMAKE_SOURCE_DIR}/src
|
||||
${CMAKE_BINARY_DIR}/src
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
${Boost_INCLUDE_DIRS}
|
||||
${COIN3D_INCLUDE_DIRS}
|
||||
${OCC_INCLUDE_DIR}
|
||||
${PYTHON_INCLUDE_DIRS}
|
||||
${XercesC_INCLUDE_DIRS}
|
||||
${ZLIB_INCLUDE_DIR}
|
||||
)
|
||||
link_directories(${OCC_LIBRARY_DIR})
|
||||
|
||||
set(MatGui_LIBS
|
||||
Material
|
||||
FreeCADGui
|
||||
)
|
||||
|
||||
include_directories(
|
||||
${QtConcurrent_INCLUDE_DIRS}
|
||||
)
|
||||
list(APPEND MatGui_LIBS
|
||||
${QtConcurrent_LIBRARIES}
|
||||
)
|
||||
|
||||
set (Material_TR_QRC ${CMAKE_CURRENT_BINARY_DIR}/Resources/Material_translation.qrc)
|
||||
qt_find_and_add_translation(QM_SRCS "Resources/translations/*_*.ts"
|
||||
${CMAKE_CURRENT_BINARY_DIR}/Resources/translations)
|
||||
qt_create_resource_file(${Material_TR_QRC} ${QM_SRCS})
|
||||
qt_add_resources(MatGui_QRC_SRCS Resources/Material.qrc ${Material_TR_QRC})
|
||||
|
||||
set(MatGui_UIC_SRCS
|
||||
Array2D.ui
|
||||
Array3D.ui
|
||||
DlgSettingsMaterial.ui
|
||||
MaterialSave.ui
|
||||
MaterialsEditor.ui
|
||||
ModelSelect.ui
|
||||
)
|
||||
|
||||
SET(MatGui_SRCS
|
||||
${MatGui_QRC_SRCS}
|
||||
${MatGui_UIC_HDRS}
|
||||
AppMatGui.cpp
|
||||
Array2D.cpp
|
||||
Array2D.h
|
||||
Array2D.ui
|
||||
Array3D.cpp
|
||||
Array3D.h
|
||||
Array3D.ui
|
||||
ArrayDelegate.cpp
|
||||
ArrayDelegate.h
|
||||
ArrayModel.cpp
|
||||
ArrayModel.h
|
||||
Command.cpp
|
||||
DlgSettingsMaterial.cpp
|
||||
DlgSettingsMaterial.h
|
||||
DlgSettingsMaterial.ui
|
||||
MaterialDelegate.cpp
|
||||
MaterialDelegate.h
|
||||
MaterialSave.cpp
|
||||
MaterialSave.h
|
||||
MaterialSave.ui
|
||||
MaterialsEditor.cpp
|
||||
MaterialsEditor.h
|
||||
MaterialsEditor.ui
|
||||
ModelSelect.cpp
|
||||
ModelSelect.h
|
||||
ModelSelect.ui
|
||||
PreCompiled.cpp
|
||||
PreCompiled.h
|
||||
)
|
||||
|
||||
if(FREECAD_USE_PCH)
|
||||
add_definitions(-D_PreComp_)
|
||||
GET_MSVC_PRECOMPILED_SOURCE("PreCompiled.cpp" PCH_SRCS ${MatGui_SRCS})
|
||||
ADD_MSVC_PRECOMPILED_HEADER(MatGui PreCompiled.h PreCompiled.cpp PCH_SRCS)
|
||||
endif(FREECAD_USE_PCH)
|
||||
|
||||
SET(MatGuiIcon_SVG
|
||||
Resources/icons/Materials_Edit.svg
|
||||
Resources/icons/MaterialWorkbench.svg
|
||||
Resources/icons/preferences-material.svg
|
||||
Resources/icons/preview-rendered.svg
|
||||
Resources/icons/preview-vector.svg
|
||||
Resources/icons/table.svg
|
||||
)
|
||||
|
||||
add_library(MatGui SHARED ${MatGui_SRCS} ${MatGuiIcon_SVG})
|
||||
target_link_libraries(MatGui ${MatGui_LIBS})
|
||||
|
||||
|
||||
SET_BIN_DIR(MatGui MatGui /Mod/Material)
|
||||
SET_PYTHON_PREFIX_SUFFIX(MatGui)
|
||||
|
||||
fc_copy_sources(MatGui "${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_DATADIR}/Mod/Material" ${MatGuiIcon_SVG})
|
||||
|
||||
INSTALL(TARGETS MatGui DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
INSTALL(FILES ${MatGuiIcon_SVG} DESTINATION "${CMAKE_INSTALL_DATADIR}/Mod/Material/Resources/icons")
|
||||
83
src/Mod/Material/Gui/Command.cpp
Normal file
83
src/Mod/Material/Gui/Command.cpp
Normal file
@@ -0,0 +1,83 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2023 David Carter <dcarter@david.carter.ca> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#include "PreCompiled.h"
|
||||
#ifndef _PreComp_
|
||||
#include <QPointer>
|
||||
#endif
|
||||
|
||||
#include <Gui/Command.h>
|
||||
#include <Gui/MainWindow.h>
|
||||
|
||||
#include "MaterialSave.h"
|
||||
#include "MaterialsEditor.h"
|
||||
#include "ModelSelect.h"
|
||||
|
||||
|
||||
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
//===========================================================================
|
||||
// Material_Edit
|
||||
//===========================================================================
|
||||
DEF_STD_CMD_A(CmdMaterialsEdit)
|
||||
|
||||
CmdMaterialsEdit::CmdMaterialsEdit()
|
||||
: Command("Materials_Edit")
|
||||
{
|
||||
sAppModule = "Material";
|
||||
sGroup = QT_TR_NOOP("Material");
|
||||
sMenuText = QT_TR_NOOP("Edit...");
|
||||
sToolTipText = QT_TR_NOOP("Edit material properties");
|
||||
sWhatsThis = "Materials_Edit";
|
||||
sStatusTip = sToolTipText;
|
||||
sPixmap = "Materials_Edit";
|
||||
}
|
||||
|
||||
void CmdMaterialsEdit::activated(int iMsg)
|
||||
{
|
||||
Q_UNUSED(iMsg);
|
||||
|
||||
Base::Console().Log("Materials_Edit\n");
|
||||
|
||||
static QPointer<QDialog> dlg = nullptr;
|
||||
if (!dlg) {
|
||||
dlg = new MatGui::MaterialsEditor(Gui::getMainWindow());
|
||||
}
|
||||
dlg->setAttribute(Qt::WA_DeleteOnClose);
|
||||
dlg->show();
|
||||
}
|
||||
|
||||
bool CmdMaterialsEdit::isActive()
|
||||
{
|
||||
// return (hasActiveDocument() && !Gui::Control().activeDialog());
|
||||
return true;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
|
||||
void CreateMaterialCommands()
|
||||
{
|
||||
Gui::CommandManager& rcCmdMgr = Gui::Application::Instance->commandManager();
|
||||
|
||||
rcCmdMgr.addCommand(new CmdMaterialsEdit());
|
||||
}
|
||||
@@ -24,45 +24,51 @@
|
||||
|
||||
#include "PreCompiled.h"
|
||||
|
||||
#include "DlgSettingsFemMaterialImp.h"
|
||||
#include "ui_DlgSettingsFemMaterial.h"
|
||||
#include "DlgSettingsMaterial.h"
|
||||
#include "ui_DlgSettingsMaterial.h"
|
||||
|
||||
|
||||
using namespace FemGui;
|
||||
using namespace MatGui;
|
||||
|
||||
DlgSettingsFemMaterialImp::DlgSettingsFemMaterialImp(QWidget* parent)
|
||||
DlgSettingsMaterial::DlgSettingsMaterial(QWidget* parent)
|
||||
: PreferencePage(parent)
|
||||
, ui(new Ui_DlgSettingsFemMaterialImp)
|
||||
, ui(new Ui_DlgSettingsMaterial)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
}
|
||||
|
||||
DlgSettingsFemMaterialImp::~DlgSettingsFemMaterialImp() = default;
|
||||
|
||||
void DlgSettingsFemMaterialImp::saveSettings()
|
||||
void DlgSettingsMaterial::saveSettings()
|
||||
{
|
||||
ui->cb_use_built_in_materials->onSave();
|
||||
ui->cb_use_mat_from_workbenches->onSave();
|
||||
ui->cb_use_mat_from_config_dir->onSave();
|
||||
ui->cb_use_mat_from_custom_dir->onSave();
|
||||
ui->fc_custom_mat_dir->onSave();
|
||||
ui->cb_delete_duplicates->onSave();
|
||||
ui->cb_sort_by_resources->onSave();
|
||||
|
||||
// Temporary for testing
|
||||
ui->cb_legacy_editor->onSave();
|
||||
}
|
||||
|
||||
void DlgSettingsFemMaterialImp::loadSettings()
|
||||
void DlgSettingsMaterial::loadSettings()
|
||||
{
|
||||
ui->cb_use_built_in_materials->onRestore();
|
||||
ui->cb_use_mat_from_workbenches->onRestore();
|
||||
ui->cb_use_mat_from_config_dir->onRestore();
|
||||
ui->cb_use_mat_from_custom_dir->onRestore();
|
||||
ui->fc_custom_mat_dir->onRestore();
|
||||
ui->cb_delete_duplicates->onRestore();
|
||||
ui->cb_sort_by_resources->onRestore();
|
||||
|
||||
// Temporary for testing
|
||||
ui->cb_legacy_editor->onRestore();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the strings of the subwidgets using the current language.
|
||||
*/
|
||||
void DlgSettingsFemMaterialImp::changeEvent(QEvent* e)
|
||||
void DlgSettingsMaterial::changeEvent(QEvent* e)
|
||||
{
|
||||
if (e->type() == QEvent::LanguageChange) {
|
||||
ui->retranslateUi(this);
|
||||
@@ -72,4 +78,4 @@ void DlgSettingsFemMaterialImp::changeEvent(QEvent* e)
|
||||
}
|
||||
}
|
||||
|
||||
#include "moc_DlgSettingsFemMaterialImp.cpp"
|
||||
#include "moc_DlgSettingsMaterial.cpp"
|
||||
@@ -22,24 +22,24 @@
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef FEMGUI_DLGSETTINGSFEMMATERIALIMP_H
|
||||
#define FEMGUI_DLGSETTINGSFEMMATERIALIMP_H
|
||||
#ifndef MATGUI_DLGSETTINGSMATERIAL_H
|
||||
#define MATGUI_DLGSETTINGSMATERIAL_H
|
||||
|
||||
#include <Gui/PropertyPage.h>
|
||||
#include <memory>
|
||||
|
||||
|
||||
namespace FemGui
|
||||
namespace MatGui
|
||||
{
|
||||
class Ui_DlgSettingsFemMaterialImp;
|
||||
class Ui_DlgSettingsMaterial;
|
||||
|
||||
class DlgSettingsFemMaterialImp: public Gui::Dialog::PreferencePage
|
||||
class DlgSettingsMaterial: public Gui::Dialog::PreferencePage
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit DlgSettingsFemMaterialImp(QWidget* parent = nullptr);
|
||||
~DlgSettingsFemMaterialImp() override;
|
||||
explicit DlgSettingsMaterial(QWidget* parent = nullptr);
|
||||
~DlgSettingsMaterial() override = default;
|
||||
|
||||
protected:
|
||||
void saveSettings() override;
|
||||
@@ -47,9 +47,9 @@ protected:
|
||||
void changeEvent(QEvent* e) override;
|
||||
|
||||
private:
|
||||
std::unique_ptr<Ui_DlgSettingsFemMaterialImp> ui;
|
||||
std::unique_ptr<Ui_DlgSettingsMaterial> ui;
|
||||
};
|
||||
|
||||
} // namespace FemGui
|
||||
} // namespace MatGui
|
||||
|
||||
#endif // FEMGUI_DLGSETTINGSFEMMATERIALIMP_H
|
||||
#endif // MATGUI_DLGSETTINGSMATERIAL_H
|
||||
@@ -1,17 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>FemGui::DlgSettingsFemMaterialImp</class>
|
||||
<widget class="QWidget" name="FemGui::DlgSettingsFemMaterialImp">
|
||||
<class>MatGui::DlgSettingsMaterial</class>
|
||||
<widget class="QWidget" name="MatGui::DlgSettingsMaterial">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>434</width>
|
||||
<height>229</height>
|
||||
<height>341</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Material</string>
|
||||
<string>General</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="spacing">
|
||||
@@ -44,6 +44,25 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Gui::PrefCheckBox" name="cb_use_mat_from_workbenches">
|
||||
<property name="toolTip">
|
||||
<string>Use materials added by external workbenches.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Use materials from external workbenches</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>UseMaterialsFromWorkbenches</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>Mod/Material/Resources</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Gui::PrefCheckBox" name="cb_use_mat_from_config_dir">
|
||||
<property name="toolTip">
|
||||
@@ -124,9 +143,6 @@ will be listed as available.</string>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="mode">
|
||||
<enum>Gui::FileChooser::Directory</enum>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>CustomMaterialsDir</cstring>
|
||||
</property>
|
||||
@@ -190,6 +206,31 @@ If unchecked, they will be sorted by their name.</string>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="gb_materials_testing">
|
||||
<property name="title">
|
||||
<string>Testing</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<item>
|
||||
<widget class="Gui::PrefCheckBox" name="cb_legacy_editor">
|
||||
<property name="text">
|
||||
<string>Use legacy editor</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>LegacyEditor</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>Mod/Material/Cards</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
@@ -226,9 +267,7 @@ If unchecked, they will be sorted by their name.</string>
|
||||
<header>Gui/PrefWidgets.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
<include location="Resources/Fem.qrc"/>
|
||||
</resources>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>cb_use_mat_from_custom_dir</sender>
|
||||
466
src/Mod/Material/Gui/MaterialDelegate.cpp
Normal file
466
src/Mod/Material/Gui/MaterialDelegate.cpp
Normal file
@@ -0,0 +1,466 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2023 David Carter <dcarter@david.carter.ca> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "PreCompiled.h"
|
||||
#ifndef _PreComp_
|
||||
#include <QColorDialog>
|
||||
#include <QDesktopServices>
|
||||
#include <QIODevice>
|
||||
#include <QItemSelectionModel>
|
||||
#include <QPainter>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include <QTextStream>
|
||||
#include <QVariant>
|
||||
#endif
|
||||
|
||||
#include <limits>
|
||||
|
||||
#include <App/Application.h>
|
||||
#include <Base/Interpreter.h>
|
||||
#include <Base/Quantity.h>
|
||||
#include <Gui/Application.h>
|
||||
#include <Gui/Command.h>
|
||||
#include <Gui/InputField.h>
|
||||
#include <Gui/PrefWidgets.h>
|
||||
#include <Gui/SpinBox.h>
|
||||
#include <Gui/WaitCursor.h>
|
||||
|
||||
#include <Mod/Material/App/Exceptions.h>
|
||||
#include <Mod/Material/App/ModelManager.h>
|
||||
|
||||
#include "Array2D.h"
|
||||
#include "Array3D.h"
|
||||
#include "MaterialDelegate.h"
|
||||
#include "MaterialSave.h"
|
||||
|
||||
|
||||
using namespace MatGui;
|
||||
|
||||
MaterialDelegate::MaterialDelegate(QObject* parent)
|
||||
: QStyledItemDelegate(parent)
|
||||
{}
|
||||
|
||||
bool MaterialDelegate::editorEvent(QEvent* event,
|
||||
QAbstractItemModel* model,
|
||||
const QStyleOptionViewItem& option,
|
||||
const QModelIndex& index)
|
||||
{
|
||||
if (index.column() == 1) {
|
||||
if (event->type() == QEvent::MouseButtonDblClick) {
|
||||
const QStandardItemModel* treeModel =
|
||||
static_cast<const QStandardItemModel*>(index.model());
|
||||
|
||||
// Check we're not the material model root. This is also used to access the entry
|
||||
// columns
|
||||
auto item = treeModel->itemFromIndex(index);
|
||||
auto group = item->parent();
|
||||
if (!group) {
|
||||
return QStyledItemDelegate::editorEvent(event, model, option, index);
|
||||
}
|
||||
|
||||
int row = index.row();
|
||||
|
||||
QString propertyName = group->child(row, 0)->text();
|
||||
QString propertyType = QString::fromStdString("String");
|
||||
if (group->child(row, 2)) {
|
||||
propertyType = group->child(row, 2)->text();
|
||||
}
|
||||
|
||||
std::string type = propertyType.toStdString();
|
||||
if (type == "Color") {
|
||||
Base::Console().Log("Edit color\n");
|
||||
showColorModal(item);
|
||||
// Mark as handled
|
||||
return true;
|
||||
}
|
||||
else if (type == "2DArray") {
|
||||
Base::Console().Log("Edit 2DArray\n");
|
||||
showArray2DModal(propertyName, item);
|
||||
// Mark as handled
|
||||
return true;
|
||||
}
|
||||
else if (type == "3DArray") {
|
||||
Base::Console().Log("Edit 3DArray\n");
|
||||
showArray3DModal(propertyName, item);
|
||||
// Mark as handled
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return QStyledItemDelegate::editorEvent(event, model, option, index);
|
||||
}
|
||||
|
||||
void MaterialDelegate::showColorModal(QStandardItem* item)
|
||||
{
|
||||
QColor currentColor;// = d->col;
|
||||
currentColor.setRgba(parseColor(item->text()));
|
||||
QColorDialog* dlg = new QColorDialog(currentColor);
|
||||
|
||||
dlg->setAttribute(Qt::WA_DeleteOnClose);
|
||||
if (Gui::DialogOptions::dontUseNativeColorDialog()) {
|
||||
dlg->setOptions(QColorDialog::DontUseNativeDialog);
|
||||
}
|
||||
dlg->setOption(QColorDialog::ColorDialogOption::ShowAlphaChannel, false);
|
||||
|
||||
dlg->setCurrentColor(currentColor);
|
||||
dlg->adjustSize();
|
||||
|
||||
connect(dlg, &QColorDialog::finished, this, [&](int result) {
|
||||
if (result == QDialog::Accepted) {
|
||||
QColor color = dlg->selectedColor();
|
||||
if (color.isValid()) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
dlg->exec();
|
||||
}
|
||||
|
||||
void MaterialDelegate::showArray2DModal(const QString& propertyName, QStandardItem* item)
|
||||
{
|
||||
Materials::Material* material = item->data().value<Materials::Material*>();
|
||||
Array2D* dlg = new Array2D(propertyName, material);
|
||||
|
||||
dlg->setAttribute(Qt::WA_DeleteOnClose);
|
||||
|
||||
dlg->adjustSize();
|
||||
|
||||
connect(dlg, &QDialog::finished, this, [&](int result) {
|
||||
if (result == QDialog::Accepted) {
|
||||
Base::Console().Log("Accepted\n");
|
||||
}
|
||||
});
|
||||
|
||||
dlg->exec();
|
||||
}
|
||||
|
||||
void MaterialDelegate::showArray3DModal(const QString& propertyName, QStandardItem* item)
|
||||
{
|
||||
Materials::Material* material = item->data().value<Materials::Material*>();
|
||||
Array3D* dlg = new Array3D(propertyName, material);
|
||||
|
||||
dlg->setAttribute(Qt::WA_DeleteOnClose);
|
||||
|
||||
dlg->adjustSize();
|
||||
|
||||
connect(dlg, &QDialog::finished, this, [&](int result) {
|
||||
if (result == QDialog::Accepted) {
|
||||
Base::Console().Log("Accepted\n");
|
||||
}
|
||||
});
|
||||
|
||||
dlg->exec();
|
||||
}
|
||||
|
||||
void MaterialDelegate::paint(QPainter* painter,
|
||||
const QStyleOptionViewItem& option,
|
||||
const QModelIndex& index) const
|
||||
{
|
||||
// Base::Console().Log("MaterialsEditor::paint()\n");
|
||||
if (index.column() != 1) {
|
||||
QStyledItemDelegate::paint(painter, option, index);
|
||||
return;
|
||||
}
|
||||
|
||||
const QStandardItemModel* treeModel = static_cast<const QStandardItemModel*>(index.model());
|
||||
|
||||
// Check we're not the material model root. This is also used to access the entry columns
|
||||
auto item = treeModel->itemFromIndex(index);
|
||||
auto group = item->parent();
|
||||
if (!group) {
|
||||
QStyledItemDelegate::paint(painter, option, index);
|
||||
return;
|
||||
}
|
||||
|
||||
int row = index.row();
|
||||
|
||||
QString propertyName = group->child(row, 0)->text();
|
||||
QString propertyType = QString::fromStdString("String");
|
||||
if (group->child(row, 2)) {
|
||||
propertyType = group->child(row, 2)->text();
|
||||
}
|
||||
QString propertyValue = QString::fromStdString("");
|
||||
if (group->child(row, 1)) {
|
||||
propertyValue = group->child(row, 1)->text();
|
||||
}
|
||||
|
||||
std::string type = propertyType.toStdString();
|
||||
if (type == "Color") {
|
||||
painter->save();
|
||||
|
||||
QColor color;
|
||||
color.setRgba(parseColor(propertyValue));
|
||||
int left = option.rect.left() + 5;
|
||||
int width = option.rect.width() - 10;
|
||||
if (option.rect.width() > 75) {
|
||||
left += (option.rect.width() - 75) / 2;
|
||||
width = 65;
|
||||
}
|
||||
painter->fillRect(left,
|
||||
option.rect.top() + 5,
|
||||
width,
|
||||
option.rect.height() - 10,
|
||||
QBrush(color));
|
||||
|
||||
painter->restore();
|
||||
return;
|
||||
}
|
||||
else if (type == "2DArray" || type == "3DArray") {
|
||||
// painter->save();
|
||||
|
||||
QImage table(QString::fromStdString(":/icons/table.svg"));
|
||||
QRect target(option.rect);
|
||||
if (target.width() > target.height()) {
|
||||
target.setWidth(target.height());
|
||||
}
|
||||
else {
|
||||
target.setHeight(target.width());
|
||||
}
|
||||
painter->drawImage(target, table, table.rect());
|
||||
|
||||
// painter->restore();
|
||||
return;
|
||||
}
|
||||
|
||||
QStyledItemDelegate::paint(painter, option, index);
|
||||
}
|
||||
|
||||
QSize MaterialDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const
|
||||
{
|
||||
if (index.column() != 1) {
|
||||
return QStyledItemDelegate::sizeHint(option, index);
|
||||
}
|
||||
|
||||
const QStandardItemModel* treeModel = static_cast<const QStandardItemModel*>(index.model());
|
||||
|
||||
// Check we're not the material model root. This is also used to access the entry columns
|
||||
auto item = treeModel->itemFromIndex(index);
|
||||
auto group = item->parent();
|
||||
if (!group) {
|
||||
return QStyledItemDelegate::sizeHint(option, index);
|
||||
}
|
||||
|
||||
int row = index.row();
|
||||
|
||||
QString propertyType = QString::fromStdString("String");
|
||||
if (group->child(row, 2)) {
|
||||
propertyType = group->child(row, 2)->text();
|
||||
}
|
||||
|
||||
std::string type = propertyType.toStdString();
|
||||
if (type == "Color") {
|
||||
return QSize(75, 23);// Standard QPushButton size
|
||||
}
|
||||
else if (type == "2DArray" || type == "3DArray") {
|
||||
return QSize(23, 23);
|
||||
}
|
||||
|
||||
return QStyledItemDelegate::sizeHint(option, index);
|
||||
}
|
||||
|
||||
void MaterialDelegate::setEditorData(QWidget* editor, const QModelIndex& index) const
|
||||
{
|
||||
Base::Console().Log("MaterialsEditor::setEditorData()\n");
|
||||
QVariant propertyType = editor->property("Type");
|
||||
const QStandardItemModel* model = static_cast<const QStandardItemModel*>(index.model());
|
||||
QStandardItem* item = model->itemFromIndex(index);
|
||||
auto group = item->parent();
|
||||
if (!group) {
|
||||
return;
|
||||
}
|
||||
|
||||
int row = index.row();
|
||||
QString propertyName = group->child(row, 0)->text();
|
||||
|
||||
std::string type = propertyType.toString().toStdString();
|
||||
if (type == "File") {
|
||||
Gui::FileChooser* chooser = static_cast<Gui::FileChooser*>(editor);
|
||||
item->setText(chooser->fileName());
|
||||
}
|
||||
else if (type == "Quantity") {
|
||||
Gui::InputField* input = static_cast<Gui::InputField*>(editor);
|
||||
item->setText(input->getQuantityString());
|
||||
}
|
||||
else {
|
||||
QStyledItemDelegate::setEditorData(editor, index);
|
||||
}
|
||||
|
||||
// Q_EMIT const_cast<MaterialDelegate *>(this)->propertyChange(propertyName, item->text());
|
||||
}
|
||||
|
||||
void MaterialDelegate::setModelData(QWidget* editor,
|
||||
QAbstractItemModel* model,
|
||||
const QModelIndex& index) const
|
||||
{
|
||||
QStyledItemDelegate::setModelData(editor, model, index);
|
||||
|
||||
QStandardItem* item = static_cast<const QStandardItemModel*>(model)->itemFromIndex(index);
|
||||
auto group = item->parent();
|
||||
if (!group) {
|
||||
return;
|
||||
}
|
||||
|
||||
int row = index.row();
|
||||
QString propertyName = group->child(row, 0)->text();
|
||||
Q_EMIT const_cast<MaterialDelegate*>(this)->propertyChange(propertyName, item->text());
|
||||
}
|
||||
|
||||
QWidget* MaterialDelegate::createEditor(QWidget* parent,
|
||||
const QStyleOptionViewItem&,
|
||||
const QModelIndex& index) const
|
||||
{
|
||||
Base::Console().Log("MaterialsEditor::createEditor()\n");
|
||||
if (index.column() != 1) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const QStandardItemModel* treeModel = static_cast<const QStandardItemModel*>(index.model());
|
||||
|
||||
// Check we're not the material model root. This is also used to access the entry columns
|
||||
auto item = treeModel->itemFromIndex(index);
|
||||
auto group = item->parent();
|
||||
if (!group) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int row = index.row();
|
||||
|
||||
QString propertyName = group->child(row, 0)->text();
|
||||
QString propertyType = QString::fromStdString("String");
|
||||
if (group->child(row, 2)) {
|
||||
propertyType = group->child(row, 2)->text();
|
||||
}
|
||||
|
||||
QString propertyValue = QString::fromStdString("");
|
||||
if (group->child(row, 1)) {
|
||||
propertyValue = group->child(row, 1)->text();
|
||||
}
|
||||
|
||||
QString propertyUnits = QString::fromStdString("");
|
||||
if (group->child(row, 1)) {
|
||||
propertyUnits = group->child(row, 3)->text();
|
||||
}
|
||||
|
||||
QWidget* editor =
|
||||
createWidget(parent, propertyName, propertyType, propertyValue, propertyUnits);
|
||||
|
||||
return editor;
|
||||
}
|
||||
|
||||
QWidget* MaterialDelegate::createWidget(QWidget* parent,
|
||||
const QString& propertyName,
|
||||
const QString& propertyType,
|
||||
const QString& propertyValue,
|
||||
const QString& propertyUnits) const
|
||||
{
|
||||
Q_UNUSED(propertyName);
|
||||
|
||||
QWidget* widget = nullptr;
|
||||
|
||||
std::string type = propertyType.toStdString();
|
||||
if (type == "String" || type == "URL" || type == "Vector") {
|
||||
widget = new Gui::PrefLineEdit(parent);
|
||||
}
|
||||
else if ((type == "Integer") || (type == "Int")) {
|
||||
Gui::UIntSpinBox* spinner = new Gui::UIntSpinBox(parent);
|
||||
spinner->setMinimum(0);
|
||||
spinner->setMaximum(UINT_MAX);
|
||||
spinner->setValue(propertyValue.toUInt());
|
||||
widget = spinner;
|
||||
}
|
||||
else if (type == "Float") {
|
||||
Gui::DoubleSpinBox* spinner = new Gui::DoubleSpinBox(parent);
|
||||
|
||||
// the magnetic permeability is the parameter for which many decimals matter
|
||||
// the most however, even for this, 6 digits are sufficient
|
||||
spinner->setDecimals(6);
|
||||
|
||||
// for almost all Float parameters of materials a step of 1 would be too large
|
||||
spinner->setSingleStep(0.1);
|
||||
|
||||
spinner->setMinimum(std::numeric_limits<double>::min());
|
||||
spinner->setMaximum(std::numeric_limits<double>::max());
|
||||
spinner->setValue(propertyValue.toDouble());
|
||||
widget = spinner;
|
||||
}
|
||||
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->setCurrentText(propertyValue);
|
||||
widget = combo;
|
||||
}
|
||||
else if (type == "Quantity") {
|
||||
Gui::InputField* input = new Gui::InputField();
|
||||
input->setMinimum(std::numeric_limits<double>::min());
|
||||
input->setMaximum(std::numeric_limits<double>::max());
|
||||
input->setUnitText(propertyUnits);// TODO: Ensure this exists
|
||||
input->setPrecision(6);
|
||||
input->setQuantityString(propertyValue);
|
||||
|
||||
widget = input;
|
||||
}
|
||||
else if (type == "File") {
|
||||
Gui::FileChooser* chooser = new Gui::FileChooser();
|
||||
if (propertyValue.length() > 0) {
|
||||
chooser->setFileName(propertyValue);
|
||||
}
|
||||
|
||||
widget = chooser;
|
||||
}
|
||||
else {
|
||||
// Default editor
|
||||
widget = new QLineEdit(parent);
|
||||
}
|
||||
|
||||
widget->setProperty("Type", propertyType);
|
||||
widget->setParent(parent);
|
||||
|
||||
return widget;
|
||||
}
|
||||
|
||||
QRgb MaterialDelegate::parseColor(const QString& color) const
|
||||
{
|
||||
QString trimmed = color;
|
||||
trimmed.replace(QRegularExpression(QString::fromStdString("\\(([^<]*)\\)")),
|
||||
QString::fromStdString("\\1"));
|
||||
QStringList parts = trimmed.split(QString::fromStdString(","));
|
||||
if (parts.length() < 4) {
|
||||
return qRgba(0, 0, 0, 1);
|
||||
}
|
||||
int red = parts.at(0).toDouble() * 255;
|
||||
int green = parts.at(1).toDouble() * 255;
|
||||
int blue = parts.at(2).toDouble() * 255;
|
||||
int alpha = parts.at(3).toDouble() * 255;
|
||||
|
||||
return qRgba(red, green, blue, alpha);
|
||||
}
|
||||
|
||||
#include "moc_MaterialDelegate.cpp"
|
||||
87
src/Mod/Material/Gui/MaterialDelegate.h
Normal file
87
src/Mod/Material/Gui/MaterialDelegate.h
Normal file
@@ -0,0 +1,87 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2023 David Carter <dcarter@david.carter.ca> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef MATGUI_MATERIALDELEGATE_H
|
||||
#define MATGUI_MATERIALDELEGATE_H
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
#include <QDialog>
|
||||
#include <QDir>
|
||||
#include <QStandardItem>
|
||||
#include <QStyledItemDelegate>
|
||||
#include <QSvgWidget>
|
||||
#include <QTreeView>
|
||||
|
||||
#include <Mod/Material/App/MaterialManager.h>
|
||||
#include <Mod/Material/App/Materials.h>
|
||||
#include <Mod/Material/App/ModelManager.h>
|
||||
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
namespace MatGui
|
||||
{
|
||||
|
||||
class MaterialDelegate: public QStyledItemDelegate
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit MaterialDelegate(QObject* parent = nullptr);
|
||||
virtual ~MaterialDelegate() = default;
|
||||
|
||||
QWidget* createEditor(QWidget* parent,
|
||||
const QStyleOptionViewItem&,
|
||||
const QModelIndex& index) const override;
|
||||
QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const override;
|
||||
void paint(QPainter* painter,
|
||||
const QStyleOptionViewItem& option,
|
||||
const QModelIndex& index) const override;
|
||||
void setEditorData(QWidget* editor, const QModelIndex& index) const override;
|
||||
void setModelData(QWidget* editor,
|
||||
QAbstractItemModel* model,
|
||||
const QModelIndex& index) const override;
|
||||
|
||||
protected:
|
||||
bool editorEvent(QEvent* event,
|
||||
QAbstractItemModel* model,
|
||||
const QStyleOptionViewItem& option,
|
||||
const QModelIndex& index) override;
|
||||
|
||||
Q_SIGNALS:
|
||||
/** Emits this signal when a property has changed */
|
||||
void propertyChange(const QString& property, const QString value);
|
||||
|
||||
private:
|
||||
QWidget* createWidget(QWidget* parent,
|
||||
const QString& propertyName,
|
||||
const QString& propertyType,
|
||||
const QString& propertyValue,
|
||||
const QString& propertyUnits) const;
|
||||
QRgb parseColor(const QString& color) const;
|
||||
void showColorModal(QStandardItem* item);
|
||||
void showArray2DModal(const QString& propertyName, QStandardItem* item);
|
||||
void showArray3DModal(const QString& propertyName, QStandardItem* item);
|
||||
};
|
||||
|
||||
}// namespace MatGui
|
||||
|
||||
#endif// MATGUI_MATERIALDELEGATE_H
|
||||
314
src/Mod/Material/Gui/MaterialSave.cpp
Normal file
314
src/Mod/Material/Gui/MaterialSave.cpp
Normal file
@@ -0,0 +1,314 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2023 David Carter <dcarter@david.carter.ca> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "PreCompiled.h"
|
||||
#ifndef _PreComp_
|
||||
#include <QMessageBox>
|
||||
#include <QTreeView>
|
||||
#endif
|
||||
|
||||
#include <Gui/MainWindow.h>
|
||||
|
||||
#include <Mod/Material/App/MaterialLibrary.h>
|
||||
|
||||
#include "MaterialSave.h"
|
||||
#include "ui_MaterialSave.h"
|
||||
|
||||
using namespace MatGui;
|
||||
|
||||
/* TRANSLATOR MatGui::MaterialsEditor */
|
||||
|
||||
MaterialSave::MaterialSave(Materials::Material* material, QWidget* parent)
|
||||
: QDialog(parent)
|
||||
, ui(new Ui_MaterialSave)
|
||||
, _material(material)
|
||||
, _selectedPath(QString::fromStdString("/"))
|
||||
, _selectedUUID(QString())
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
setLibraries();
|
||||
createModelTree();
|
||||
showSelectedTree();
|
||||
|
||||
if (_material->getName().length() > 0) {
|
||||
ui->editFilename->setText(_material->getName() + QString::fromStdString(".FCMat"));
|
||||
}
|
||||
else {
|
||||
ui->editFilename->setText(QString::fromStdString("NewMaterial.FCMat"));
|
||||
}
|
||||
_filename = QString(ui->editFilename->text());// No filename by default
|
||||
|
||||
connect(ui->standardButtons->button(QDialogButtonBox::Ok),
|
||||
&QPushButton::clicked,
|
||||
this,
|
||||
&MaterialSave::onOk);
|
||||
connect(ui->standardButtons->button(QDialogButtonBox::Cancel),
|
||||
&QPushButton::clicked,
|
||||
this,
|
||||
&MaterialSave::onCancel);
|
||||
|
||||
connect(ui->comboLibrary,
|
||||
&QComboBox::currentTextChanged,
|
||||
this,
|
||||
&MaterialSave::currentTextChanged);
|
||||
connect(ui->buttonNewFolder, &QPushButton::clicked, this, &MaterialSave::onNewFolder);
|
||||
connect(ui->editFilename, &QLineEdit::textEdited, this, &MaterialSave::onFilename);
|
||||
|
||||
QItemSelectionModel* selectionModel = ui->treeMaterials->selectionModel();
|
||||
connect(selectionModel,
|
||||
&QItemSelectionModel::selectionChanged,
|
||||
this,
|
||||
&MaterialSave::onSelectModel);
|
||||
}
|
||||
|
||||
/*
|
||||
* Destroys the object and frees any allocated resources
|
||||
*/
|
||||
MaterialSave::~MaterialSave()
|
||||
{
|
||||
// no need to delete child widgets, Qt does it all for us
|
||||
}
|
||||
|
||||
void MaterialSave::onOk(bool checked)
|
||||
{
|
||||
Q_UNUSED(checked)
|
||||
|
||||
QString name = _filename.remove(QString::fromStdString(".FCMat"), Qt::CaseInsensitive);
|
||||
Base::Console().Log("name '%s'\n", _filename.toStdString().c_str());
|
||||
if (name != _material->getName()) {
|
||||
_material->setName(name);
|
||||
_material->setEditStateAlter();// ? Does a name change count?
|
||||
}
|
||||
|
||||
auto variant = ui->comboLibrary->currentData();
|
||||
auto library = variant.value<Materials::MaterialLibrary>();
|
||||
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(),
|
||||
_material->getName().toStdString().c_str(),
|
||||
filepath.filePath().toStdString().c_str());
|
||||
_manager.saveMaterial(&library, *_material, filepath.filePath());
|
||||
|
||||
accept();
|
||||
}
|
||||
|
||||
void MaterialSave::onCancel(bool checked)
|
||||
{
|
||||
Q_UNUSED(checked)
|
||||
|
||||
reject();
|
||||
}
|
||||
|
||||
void MaterialSave::accept()
|
||||
{
|
||||
QDialog::accept();
|
||||
}
|
||||
|
||||
void MaterialSave::reject()
|
||||
{
|
||||
QDialog::reject();
|
||||
}
|
||||
|
||||
void MaterialSave::setLibraries()
|
||||
{
|
||||
std::list<Materials::MaterialLibrary*>* libraries = _manager.getMaterialLibraries();
|
||||
for (Materials::MaterialLibrary* library : *libraries) {
|
||||
if (!library->isReadOnly()) {
|
||||
QVariant libraryVariant;
|
||||
libraryVariant.setValue(*library);
|
||||
ui->comboLibrary->addItem(library->getName(), libraryVariant);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialSave::createModelTree()
|
||||
{
|
||||
auto tree = ui->treeMaterials;
|
||||
auto model = new QStandardItemModel();
|
||||
tree->setModel(model);
|
||||
tree->setHeaderHidden(true);
|
||||
}
|
||||
|
||||
void MaterialSave::addExpanded(QTreeView* tree, QStandardItem* parent, QStandardItem* child)
|
||||
{
|
||||
parent->appendRow(child);
|
||||
tree->setExpanded(child->index(), true);
|
||||
}
|
||||
|
||||
void MaterialSave::addExpanded(QTreeView* tree, QStandardItemModel* parent, QStandardItem* child)
|
||||
{
|
||||
parent->appendRow(child);
|
||||
tree->setExpanded(child->index(), true);
|
||||
}
|
||||
|
||||
void MaterialSave::addMaterials(QStandardItem& parent,
|
||||
const std::map<QString, Materials::MaterialTreeNode*>* modelTree,
|
||||
const QIcon& folderIcon,
|
||||
const QIcon& icon)
|
||||
{
|
||||
auto tree = ui->treeMaterials;
|
||||
for (auto& mat : *modelTree) {
|
||||
Materials::MaterialTreeNode* nodePtr = mat.second;
|
||||
if (nodePtr->getType() == Materials::MaterialTreeNode::DataNode) {
|
||||
const Materials::Material* 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->setData(QVariant(uuid), Qt::UserRole);
|
||||
|
||||
addExpanded(tree, &parent, card);
|
||||
}
|
||||
else {
|
||||
auto node = new QStandardItem(folderIcon, mat.first);
|
||||
addExpanded(tree, &parent, node);
|
||||
// node->setFlags(Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled);
|
||||
const std::map<QString, Materials::MaterialTreeNode*>* treeMap = nodePtr->getFolder();
|
||||
addMaterials(*node, treeMap, folderIcon, icon);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialSave::showSelectedTree()
|
||||
{
|
||||
auto tree = ui->treeMaterials;
|
||||
auto model = static_cast<QStandardItemModel*>(tree->model());
|
||||
model->clear();
|
||||
|
||||
if (ui->comboLibrary->count() > 0) {
|
||||
auto variant = ui->comboLibrary->currentData();
|
||||
auto library = variant.value<Materials::MaterialLibrary>();
|
||||
QIcon icon(library.getIconPath());
|
||||
QIcon folderIcon(QString::fromStdString(":/icons/folder.svg"));
|
||||
_libraryName = library.getName();
|
||||
_selectedPath = QString::fromStdString("/") + _libraryName;
|
||||
|
||||
auto lib = new QStandardItem(library.getName());
|
||||
lib->setFlags(Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled);
|
||||
addExpanded(tree, model, lib);
|
||||
|
||||
std::map<QString, Materials::MaterialTreeNode*>* modelTree =
|
||||
_manager.getMaterialTree(library);
|
||||
addMaterials(*lib, modelTree, folderIcon, icon);
|
||||
}
|
||||
else {
|
||||
QMessageBox::warning(Gui::getMainWindow(),
|
||||
QObject::tr("No writeable library"),
|
||||
QObject::tr("No writeable library"));
|
||||
}
|
||||
}
|
||||
|
||||
QString MaterialSave::getPath(const QStandardItem* item) const
|
||||
{
|
||||
QString path = QString::fromStdString("/");
|
||||
if (item) {
|
||||
path = path + item->text();
|
||||
if (item->parent()) {
|
||||
return getPath(item->parent()) + path;
|
||||
}
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
void MaterialSave::onSelectModel(const QItemSelection& selected, const QItemSelection& deselected)
|
||||
{
|
||||
// Q_UNUSED(selected);
|
||||
Q_UNUSED(deselected);
|
||||
|
||||
_filename = QString(ui->editFilename->text());// No filename by default
|
||||
QStandardItemModel* model = static_cast<QStandardItemModel*>(ui->treeMaterials->model());
|
||||
QModelIndexList indexes = selected.indexes();
|
||||
if (indexes.count() == 0) {
|
||||
Base::Console().Log("Nothing selected\n");
|
||||
_selectedPath = QString::fromStdString("/") + _libraryName;
|
||||
_selectedUUID = QString();
|
||||
Base::Console().Log("\tSelected path '%s'\n", _selectedPath.toStdString().c_str());
|
||||
return;
|
||||
}
|
||||
for (auto it = indexes.begin(); it != indexes.end(); it++) {
|
||||
QStandardItem* item = model->itemFromIndex(*it);
|
||||
Base::Console().Log("%s\n", item->text().toStdString().c_str());
|
||||
if (item) {
|
||||
auto _selected = item->data(Qt::UserRole);
|
||||
if (_selected.isValid()) {
|
||||
Base::Console().Log("\tuuid %s\n", _selected.toString().toStdString().c_str());
|
||||
_selectedPath = getPath(item->parent());
|
||||
_selectedUUID = _selected.toString();
|
||||
_filename = item->text();
|
||||
}
|
||||
else {
|
||||
_selectedPath = getPath(item);
|
||||
_selectedUUID = QString();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (_filename.length() > 0) {
|
||||
ui->editFilename->setText(_filename);
|
||||
}
|
||||
Base::Console().Log("\tSelected path '%s', filename = '%s'\n",
|
||||
_selectedPath.toStdString().c_str(),
|
||||
_filename.toStdString().c_str());
|
||||
}
|
||||
|
||||
void MaterialSave::currentTextChanged(const QString& value)
|
||||
{
|
||||
Q_UNUSED(value)
|
||||
|
||||
showSelectedTree();
|
||||
}
|
||||
|
||||
void MaterialSave::onNewFolder(bool checked)
|
||||
{
|
||||
Q_UNUSED(checked)
|
||||
|
||||
auto tree = ui->treeMaterials;
|
||||
auto model = static_cast<QStandardItemModel*>(tree->model());
|
||||
auto current = tree->currentIndex();
|
||||
if (!current.isValid()) {
|
||||
current = model->index(0, 0);
|
||||
}
|
||||
auto item = model->itemFromIndex(current);
|
||||
if (item->hasChildren()) {
|
||||
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"));
|
||||
addExpanded(tree, item, node);
|
||||
// node->setFlags(Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled);
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialSave::onFilename(const QString& text)
|
||||
{
|
||||
Base::Console().Log("MaterialSave::onFilename('%s')\n", text.toStdString().c_str());
|
||||
|
||||
_filename = text;
|
||||
}
|
||||
|
||||
#include "moc_MaterialSave.cpp"
|
||||
81
src/Mod/Material/Gui/MaterialSave.h
Normal file
81
src/Mod/Material/Gui/MaterialSave.h
Normal file
@@ -0,0 +1,81 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2023 David Carter <dcarter@david.carter.ca> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef MATGUI_MATERIALSAVE_H
|
||||
#define MATGUI_MATERIALSAVE_H
|
||||
|
||||
// #include <boost/filesystem.hpp>
|
||||
|
||||
#include <QDialog>
|
||||
#include <QItemSelection>
|
||||
#include <QStandardItem>
|
||||
#include <QTreeView>
|
||||
|
||||
#include <Mod/Material/App/MaterialManager.h>
|
||||
|
||||
namespace MatGui
|
||||
{
|
||||
|
||||
class Ui_MaterialSave;
|
||||
|
||||
class MaterialSave: public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit MaterialSave(Materials::Material* 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::map<QString, Materials::MaterialTreeNode*>* 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 onFilename(const QString& text);
|
||||
void onOk(bool checked);
|
||||
void onCancel(bool checked);
|
||||
void accept() override;
|
||||
void reject() override;
|
||||
|
||||
private:
|
||||
std::unique_ptr<Ui_MaterialSave> ui;
|
||||
Materials::MaterialManager _manager;
|
||||
Materials::Material* _material;
|
||||
QString _selectedPath;
|
||||
QString _selectedUUID;
|
||||
QString _libraryName;
|
||||
QString _filename;
|
||||
|
||||
QString getPath(const QStandardItem* item) const;
|
||||
};
|
||||
|
||||
}// namespace MatGui
|
||||
|
||||
#endif// MATGUI_MATERIALSAVE_H
|
||||
133
src/Mod/Material/Gui/MaterialSave.ui
Normal file
133
src/Mod/Material/Gui/MaterialSave.ui
Normal file
@@ -0,0 +1,133 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>MatGui::MaterialSave</class>
|
||||
<widget class="QDialog" name="MatGui::MaterialSave">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>654</width>
|
||||
<height>708</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Save Material</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Library:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="comboLibrary">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTreeView" name="treeMaterials"/>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="buttonNewFolder">
|
||||
<property name="text">
|
||||
<string>New Folder</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Filename:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="editFilename">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="standardButtons">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>standardButtons</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>MatGui::MaterialSave</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>standardButtons</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>MatGui::MaterialSave</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
905
src/Mod/Material/Gui/MaterialsEditor.cpp
Normal file
905
src/Mod/Material/Gui/MaterialsEditor.cpp
Normal file
@@ -0,0 +1,905 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2023 David Carter <dcarter@david.carter.ca> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "PreCompiled.h"
|
||||
#ifndef _PreComp_
|
||||
#include <QColorDialog>
|
||||
#include <QDesktopServices>
|
||||
#include <QIODevice>
|
||||
#include <QItemSelectionModel>
|
||||
#include <QMessageBox>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include <QTextStream>
|
||||
#include <QVariant>
|
||||
#endif
|
||||
|
||||
#include <limits>
|
||||
|
||||
#include <App/Application.h>
|
||||
#include <Base/Interpreter.h>
|
||||
#include <Base/Quantity.h>
|
||||
#include <Gui/Application.h>
|
||||
#include <Gui/Command.h>
|
||||
#include <Gui/InputField.h>
|
||||
#include <Gui/PrefWidgets.h>
|
||||
#include <Gui/SpinBox.h>
|
||||
#include <Gui/WaitCursor.h>
|
||||
|
||||
#include <Mod/Material/App/Exceptions.h>
|
||||
#include <Mod/Material/App/ModelManager.h>
|
||||
|
||||
#include "MaterialDelegate.h"
|
||||
#include "MaterialSave.h"
|
||||
#include "MaterialsEditor.h"
|
||||
#include "ModelSelect.h"
|
||||
#include "ui_MaterialsEditor.h"
|
||||
|
||||
|
||||
using namespace MatGui;
|
||||
|
||||
/* TRANSLATOR MatGui::MaterialsEditor */
|
||||
|
||||
MaterialsEditor::MaterialsEditor(QWidget* parent)
|
||||
: QDialog(parent)
|
||||
, ui(new Ui_MaterialsEditor)
|
||||
, _edited(false)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
getFavorites();
|
||||
getRecents();
|
||||
|
||||
createMaterialTree();
|
||||
createPhysicalTree();
|
||||
createAppearanceTree();
|
||||
createPreviews();
|
||||
|
||||
ui->buttonURL->setIcon(QIcon(QString::fromStdString(":/icons/internet-web-browser.svg")));
|
||||
|
||||
connect(ui->standardButtons->button(QDialogButtonBox::Ok),
|
||||
&QPushButton::clicked,
|
||||
this,
|
||||
&MaterialsEditor::onOk);
|
||||
connect(ui->standardButtons->button(QDialogButtonBox::Cancel),
|
||||
&QPushButton::clicked,
|
||||
this,
|
||||
&MaterialsEditor::onCancel);
|
||||
connect(ui->standardButtons->button(QDialogButtonBox::Save),
|
||||
&QPushButton::clicked,
|
||||
this,
|
||||
&MaterialsEditor::onSave);
|
||||
|
||||
connect(ui->buttonURL, &QPushButton::clicked, this, &MaterialsEditor::onURL);
|
||||
connect(ui->buttonPhysicalAdd, &QPushButton::clicked, this, &MaterialsEditor::onPhysicalAdd);
|
||||
connect(ui->buttonAppearanceAdd,
|
||||
&QPushButton::clicked,
|
||||
this,
|
||||
&MaterialsEditor::onAppearanceAdd);
|
||||
connect(ui->buttonFavorite, &QPushButton::clicked, this, &MaterialsEditor::onFavourite);
|
||||
|
||||
QItemSelectionModel* selectionModel = ui->treeMaterials->selectionModel();
|
||||
connect(selectionModel,
|
||||
&QItemSelectionModel::selectionChanged,
|
||||
this,
|
||||
&MaterialsEditor::onSelectMaterial);
|
||||
}
|
||||
|
||||
void MaterialsEditor::getFavorites()
|
||||
{
|
||||
_favorites.clear();
|
||||
|
||||
auto param = App::GetApplication().GetParameterGroupByPath(
|
||||
"User parameter:BaseApp/Preferences/Mod/Material/Favorites");
|
||||
int count = param->GetInt("Favorites", 0);
|
||||
for (int i = 0; i < count; i++) {
|
||||
QString key = QString::fromLatin1("FAV%1").arg(i);
|
||||
QString uuid = QString::fromStdString(param->GetASCII(key.toStdString().c_str(), ""));
|
||||
_favorites.push_back(uuid);
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialsEditor::saveFavorites()
|
||||
{
|
||||
auto param = App::GetApplication().GetParameterGroupByPath(
|
||||
"User parameter:BaseApp/Preferences/Mod/Material/Favorites");
|
||||
|
||||
// Clear out the existing favorites
|
||||
int count = param->GetInt("Favorites", 0);
|
||||
for (int i = 0; i < count; i++) {
|
||||
QString key = QString::fromLatin1("FAV%1").arg(i);
|
||||
param->RemoveASCII(key.toStdString().c_str());
|
||||
}
|
||||
|
||||
// Add the current values
|
||||
param->SetInt("Favorites", _favorites.size());
|
||||
int j = 0;
|
||||
for (auto favorite : _favorites) {
|
||||
QString key = QString::fromLatin1("FAV%1").arg(j);
|
||||
param->SetASCII(key.toStdString().c_str(), favorite.toStdString());
|
||||
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
Q_UNUSED(material)
|
||||
}
|
||||
catch (const Materials::MaterialNotFound&) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isFavorite(uuid)) {
|
||||
_favorites.push_back(uuid);
|
||||
saveFavorites();
|
||||
refreshMaterialTree();
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialsEditor::removeFavorite(const QString& uuid)
|
||||
{
|
||||
if (isFavorite(uuid)) {
|
||||
_favorites.remove(uuid);
|
||||
saveFavorites();
|
||||
refreshMaterialTree();
|
||||
}
|
||||
}
|
||||
|
||||
bool MaterialsEditor::isFavorite(const QString& uuid) const
|
||||
{
|
||||
for (auto it : _favorites) {
|
||||
if (it == uuid) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void MaterialsEditor::getRecents()
|
||||
{
|
||||
_recents.clear();
|
||||
|
||||
auto param = App::GetApplication().GetParameterGroupByPath(
|
||||
"User parameter:BaseApp/Preferences/Mod/Material/Recent");
|
||||
_recentMax = param->GetInt("RecentMax", 5);
|
||||
int count = param->GetInt("Recent", 0);
|
||||
for (int i = 0; i < count; i++) {
|
||||
QString key = QString::fromLatin1("MRU%1").arg(i);
|
||||
QString uuid = QString::fromStdString(param->GetASCII(key.toStdString().c_str(), ""));
|
||||
_recents.push_back(uuid);
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialsEditor::saveRecents()
|
||||
{
|
||||
auto param = App::GetApplication().GetParameterGroupByPath(
|
||||
"User parameter:BaseApp/Preferences/Mod/Material/Recent");
|
||||
|
||||
// Clear out the existing favorites
|
||||
int count = param->GetInt("Recent", 0);
|
||||
for (int i = 0; i < count; i++) {
|
||||
QString key = QString::fromLatin1("MRU%1").arg(i);
|
||||
param->RemoveASCII(key.toStdString().c_str());
|
||||
}
|
||||
|
||||
// Add the current values
|
||||
int size = _recents.size();
|
||||
if (size > _recentMax) {
|
||||
size = _recentMax;
|
||||
}
|
||||
param->SetInt("Recent", size);
|
||||
int j = 0;
|
||||
for (auto recent : _recents) {
|
||||
QString key = QString::fromLatin1("MRU%1").arg(j);
|
||||
param->SetASCII(key.toStdString().c_str(), recent.toStdString());
|
||||
|
||||
j++;
|
||||
if (j >= size) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
Q_UNUSED(material)
|
||||
}
|
||||
catch (const Materials::MaterialNotFound&) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Ensure no duplicates
|
||||
if (isRecent(uuid)) {
|
||||
_recents.remove(uuid);
|
||||
}
|
||||
|
||||
_recents.push_front(uuid);
|
||||
while (_recents.size() > static_cast<std::size_t>(_recentMax)) {
|
||||
_recents.pop_back();
|
||||
}
|
||||
|
||||
saveRecents();
|
||||
}
|
||||
|
||||
bool MaterialsEditor::isRecent(const QString& uuid) const
|
||||
{
|
||||
for (auto it : _recents) {
|
||||
if (it == uuid) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
else if (_material.hasAppearanceProperty(property)) {
|
||||
_material.setAppearanceValue(property, value);
|
||||
updatePreview();
|
||||
}
|
||||
_edited = true;
|
||||
}
|
||||
|
||||
void MaterialsEditor::onURL(bool checked)
|
||||
{
|
||||
Q_UNUSED(checked)
|
||||
|
||||
Base::Console().Log("URL\n");
|
||||
QString url = ui->editSourceURL->text();
|
||||
if (url.length() > 0) {
|
||||
QDesktopServices::openUrl(QUrl(url, QUrl::TolerantMode));
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialsEditor::onPhysicalAdd(bool checked)
|
||||
{
|
||||
Q_UNUSED(checked)
|
||||
|
||||
ModelSelect dialog(this, Materials::ModelManager::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);
|
||||
updateMaterial();
|
||||
}
|
||||
else {
|
||||
Base::Console().Log("No model selected\n");
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialsEditor::onAppearanceAdd(bool checked)
|
||||
{
|
||||
Q_UNUSED(checked)
|
||||
|
||||
ModelSelect dialog(this, Materials::ModelManager::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);
|
||||
updateMaterial();
|
||||
}
|
||||
else {
|
||||
Base::Console().Log("No model selected\n");
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialsEditor::onFavourite(bool checked)
|
||||
{
|
||||
Q_UNUSED(checked)
|
||||
|
||||
Base::Console().Log("Favorite\n");
|
||||
auto selected = _material.getUUID();
|
||||
if (isFavorite(selected)) {
|
||||
removeFavorite(selected);
|
||||
}
|
||||
else {
|
||||
addFavorite(selected);
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialsEditor::onOk(bool checked)
|
||||
{
|
||||
Q_UNUSED(checked)
|
||||
|
||||
accept();
|
||||
}
|
||||
|
||||
void MaterialsEditor::onCancel(bool checked)
|
||||
{
|
||||
Q_UNUSED(checked)
|
||||
|
||||
reject();
|
||||
}
|
||||
|
||||
void MaterialsEditor::onSave(bool checked)
|
||||
{
|
||||
Q_UNUSED(checked)
|
||||
|
||||
saveMaterial();
|
||||
}
|
||||
|
||||
void MaterialsEditor::saveMaterial()
|
||||
{
|
||||
MaterialSave dialog(&_material, this);
|
||||
dialog.setModal(true);
|
||||
if (dialog.exec() == QDialog::Accepted) {
|
||||
_material.resetEditState();
|
||||
refreshMaterialTree();
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialsEditor::accept()
|
||||
{
|
||||
addRecent(_material.getUUID());
|
||||
QDialog::accept();
|
||||
}
|
||||
|
||||
void MaterialsEditor::reject()
|
||||
{
|
||||
QDialog::reject();
|
||||
}
|
||||
|
||||
// QIcon MaterialsEditor::errorIcon(const QIcon &icon) const {
|
||||
// auto pixmap = icon.pixmap();
|
||||
// }
|
||||
|
||||
void MaterialsEditor::addMaterials(QStandardItem& parent,
|
||||
const std::map<QString, Materials::MaterialTreeNode*>* modelTree,
|
||||
const QIcon& folderIcon,
|
||||
const QIcon& icon)
|
||||
{
|
||||
auto tree = ui->treeMaterials;
|
||||
for (auto& mat : *modelTree) {
|
||||
Materials::MaterialTreeNode* nodePtr = mat.second;
|
||||
if (nodePtr->getType() == Materials::MaterialTreeNode::DataNode) {
|
||||
const Materials::Material* 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->setData(QVariant(uuid), Qt::UserRole);
|
||||
|
||||
addExpanded(tree, &parent, card);
|
||||
}
|
||||
else {
|
||||
auto node = new QStandardItem(folderIcon, mat.first);
|
||||
addExpanded(tree, &parent, node);
|
||||
node->setFlags(Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled);
|
||||
const std::map<QString, Materials::MaterialTreeNode*>* treeMap = nodePtr->getFolder();
|
||||
addMaterials(*node, treeMap, folderIcon, icon);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialsEditor::addExpanded(QTreeView* tree, QStandardItem* parent, QStandardItem* child)
|
||||
{
|
||||
parent->appendRow(child);
|
||||
tree->setExpanded(child->index(), true);
|
||||
}
|
||||
|
||||
void MaterialsEditor::addExpanded(QTreeView* tree, QStandardItemModel* parent, QStandardItem* child)
|
||||
{
|
||||
parent->appendRow(child);
|
||||
tree->setExpanded(child->index(), true);
|
||||
}
|
||||
|
||||
void MaterialsEditor::createPhysicalTree()
|
||||
{
|
||||
auto tree = ui->treePhysicalProperties;
|
||||
auto model = new QStandardItemModel();
|
||||
tree->setModel(model);
|
||||
|
||||
QStringList headers;
|
||||
headers.append(QString::fromStdString("Property"));
|
||||
headers.append(QString::fromStdString("Value"));
|
||||
headers.append(QString::fromStdString("Type"));
|
||||
model->setHorizontalHeaderLabels(headers);
|
||||
|
||||
tree->setColumnWidth(0, 250);
|
||||
tree->setColumnWidth(1, 250);
|
||||
tree->setColumnHidden(2, true);
|
||||
|
||||
tree->setHeaderHidden(false);
|
||||
tree->setUniformRowHeights(true);
|
||||
MaterialDelegate* delegate = new MaterialDelegate(this);
|
||||
tree->setItemDelegateForColumn(1, delegate);
|
||||
|
||||
connect(delegate, &MaterialDelegate::propertyChange, this, &MaterialsEditor::propertyChange);
|
||||
}
|
||||
|
||||
void MaterialsEditor::createPreviews()
|
||||
{
|
||||
_rendered = new QSvgWidget(QString::fromStdString(":/icons/preview-rendered.svg"));
|
||||
_rendered->setMaximumWidth(64);
|
||||
_rendered->setMinimumHeight(64);
|
||||
ui->layoutAppearance->addWidget(_rendered);
|
||||
|
||||
_vectored = new QSvgWidget(QString::fromStdString(":/icons/preview-vector.svg"));
|
||||
_vectored->setMaximumWidth(64);
|
||||
_vectored->setMinimumHeight(64);
|
||||
ui->layoutAppearance->addWidget(_vectored);
|
||||
|
||||
updatePreview();
|
||||
}
|
||||
|
||||
void MaterialsEditor::createAppearanceTree()
|
||||
{
|
||||
auto tree = ui->treeAppearance;
|
||||
auto model = new QStandardItemModel();
|
||||
tree->setModel(model);
|
||||
|
||||
QStringList headers;
|
||||
headers.append(QString::fromStdString("Property"));
|
||||
headers.append(QString::fromStdString("Value"));
|
||||
headers.append(QString::fromStdString("Type"));
|
||||
model->setHorizontalHeaderLabels(headers);
|
||||
|
||||
tree->setColumnWidth(0, 250);
|
||||
tree->setColumnWidth(1, 250);
|
||||
tree->setColumnHidden(2, true);
|
||||
|
||||
tree->setHeaderHidden(false);
|
||||
tree->setUniformRowHeights(false);
|
||||
MaterialDelegate* delegate = new MaterialDelegate(this);
|
||||
tree->setItemDelegateForColumn(1, delegate);
|
||||
|
||||
connect(delegate, &MaterialDelegate::propertyChange, this, &MaterialsEditor::propertyChange);
|
||||
}
|
||||
|
||||
void MaterialsEditor::addRecents(QStandardItem* parent)
|
||||
{
|
||||
auto tree = ui->treeMaterials;
|
||||
for (auto& uuid : _recents) {
|
||||
try {
|
||||
const Materials::Material& material = getMaterialManager().getMaterial(uuid);
|
||||
|
||||
QIcon icon = QIcon(material.getLibrary().getIconPath());
|
||||
auto card = new QStandardItem(icon, material.getName());
|
||||
card->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled
|
||||
| Qt::ItemIsDropEnabled);
|
||||
card->setData(QVariant(uuid), Qt::UserRole);
|
||||
|
||||
addExpanded(tree, parent, card);
|
||||
}
|
||||
catch (const Materials::MaterialNotFound&) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialsEditor::addFavorites(QStandardItem* parent)
|
||||
{
|
||||
auto tree = ui->treeMaterials;
|
||||
for (auto& uuid : _favorites) {
|
||||
try {
|
||||
const Materials::Material& material = getMaterialManager().getMaterial(uuid);
|
||||
|
||||
QIcon icon = QIcon(material.getLibrary().getIconPath());
|
||||
auto card = new QStandardItem(icon, material.getName());
|
||||
card->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled
|
||||
| Qt::ItemIsDropEnabled);
|
||||
card->setData(QVariant(uuid), Qt::UserRole);
|
||||
|
||||
addExpanded(tree, parent, card);
|
||||
}
|
||||
catch (const Materials::MaterialNotFound&) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialsEditor::fillMaterialTree()
|
||||
{
|
||||
auto tree = ui->treeMaterials;
|
||||
auto model = static_cast<QStandardItemModel*>(tree->model());
|
||||
|
||||
auto lib = new QStandardItem(QString::fromStdString("Favorites"));
|
||||
lib->setFlags(Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled);
|
||||
addExpanded(tree, model, lib);
|
||||
addFavorites(lib);
|
||||
|
||||
lib = new QStandardItem(QString::fromStdString("Recent"));
|
||||
lib->setFlags(Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled);
|
||||
addExpanded(tree, model, lib);
|
||||
addRecents(lib);
|
||||
|
||||
auto libraries = Materials::MaterialManager::getMaterialLibraries();
|
||||
for (const auto& library : *libraries) {
|
||||
lib = new QStandardItem(library->getName());
|
||||
lib->setFlags(Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled);
|
||||
addExpanded(tree, model, lib);
|
||||
|
||||
QIcon icon(library->getIconPath());
|
||||
QIcon folderIcon(QString::fromStdString(":/icons/folder.svg"));
|
||||
|
||||
std::map<QString, Materials::MaterialTreeNode*>* modelTree =
|
||||
_materialManager.getMaterialTree(*library);
|
||||
addMaterials(*lib, modelTree, folderIcon, icon);
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialsEditor::createMaterialTree()
|
||||
{
|
||||
// Materials::ModelManager &modelManager = getModelManager();
|
||||
// Q_UNUSED(modelManager)
|
||||
|
||||
auto tree = ui->treeMaterials;
|
||||
auto model = new QStandardItemModel();
|
||||
tree->setModel(model);
|
||||
|
||||
tree->setHeaderHidden(true);
|
||||
fillMaterialTree();
|
||||
}
|
||||
|
||||
void MaterialsEditor::refreshMaterialTree()
|
||||
{
|
||||
auto tree = ui->treeMaterials;
|
||||
auto model = static_cast<QStandardItemModel*>(tree->model());
|
||||
model->clear();
|
||||
|
||||
fillMaterialTree();
|
||||
}
|
||||
|
||||
void MaterialsEditor::updatePreview() const
|
||||
{
|
||||
QString diffuseColor;
|
||||
QString highlightColor;
|
||||
QString sectionColor;
|
||||
|
||||
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("Color"))) {
|
||||
diffuseColor = _material.getAppearanceValueString(QString::fromStdString("Color"));
|
||||
}
|
||||
|
||||
if (_material.hasAppearanceProperty(QString::fromStdString("SpecularColor"))) {
|
||||
highlightColor =
|
||||
_material.getAppearanceValueString(QString::fromStdString("SpecularColor"));
|
||||
}
|
||||
|
||||
if (_material.hasAppearanceProperty(QString::fromStdString("SectionColor"))) {
|
||||
sectionColor = _material.getAppearanceValueString(QString::fromStdString("SectionColor"));
|
||||
}
|
||||
|
||||
if ((diffuseColor.length() + highlightColor.length()) > 0) {
|
||||
auto file = QFile(QString::fromStdString(":/icons/preview-rendered.svg"));
|
||||
if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
QString svg = QTextStream(&file).readAll();
|
||||
file.close();
|
||||
if (diffuseColor.length() > 0) {
|
||||
svg =
|
||||
svg.replace(QString::fromStdString("#d3d7cf"), getColorHash(diffuseColor, 255));
|
||||
svg =
|
||||
svg.replace(QString::fromStdString("#555753"), getColorHash(diffuseColor, 125));
|
||||
}
|
||||
if (highlightColor.length() > 0) {
|
||||
svg = svg.replace(QString::fromStdString("#fffffe"),
|
||||
getColorHash(highlightColor, 255));
|
||||
}
|
||||
_rendered->load(svg.toUtf8());
|
||||
}
|
||||
}
|
||||
|
||||
if ((diffuseColor.length() + sectionColor.length()) > 0) {
|
||||
auto file = QFile(QString::fromStdString(":/icons/preview-vector.svg"));
|
||||
if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
QString svg = QTextStream(&file).readAll();
|
||||
file.close();
|
||||
if (diffuseColor.length() > 0) {
|
||||
svg =
|
||||
svg.replace(QString::fromStdString("#d3d7cf"), getColorHash(diffuseColor, 255));
|
||||
svg =
|
||||
svg.replace(QString::fromStdString("#555753"), getColorHash(diffuseColor, 125));
|
||||
}
|
||||
if (sectionColor.length() > 0) {
|
||||
svg =
|
||||
svg.replace(QString::fromStdString("#ffffff"), getColorHash(sectionColor, 255));
|
||||
}
|
||||
_vectored->load(svg.toUtf8());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QString MaterialsEditor::getColorHash(const QString& colorString, int colorRange) const
|
||||
{
|
||||
/*
|
||||
returns a '#000000' string from a '(0.1,0.2,0.3)' string. Optionally the string
|
||||
has a fourth value for alpha (transparency)
|
||||
*/
|
||||
std::stringstream stream(colorString.toStdString());
|
||||
|
||||
char c;
|
||||
stream >> c;// read "("
|
||||
double red;
|
||||
stream >> red;
|
||||
stream >> c;// ","
|
||||
double green;
|
||||
stream >> green;
|
||||
stream >> c;// ","
|
||||
double blue;
|
||||
stream >> blue;
|
||||
stream >> c;// ","
|
||||
double alpha = 1.0;
|
||||
if (c == ',') {
|
||||
stream >> alpha;
|
||||
}
|
||||
|
||||
QColor color(static_cast<int>(red * colorRange),
|
||||
static_cast<int>(green * colorRange),
|
||||
static_cast<int>(blue * colorRange),
|
||||
static_cast<int>(alpha * colorRange));
|
||||
return color.name();
|
||||
}
|
||||
|
||||
void MaterialsEditor::updateMaterialAppearance()
|
||||
{
|
||||
QTreeView* tree = ui->treeAppearance;
|
||||
QStandardItemModel* treeModel = static_cast<QStandardItemModel*>(tree->model());
|
||||
treeModel->clear();
|
||||
|
||||
QStringList headers;
|
||||
headers.append(QString::fromStdString("Property"));
|
||||
headers.append(QString::fromStdString("Value"));
|
||||
headers.append(QString::fromStdString("Type"));
|
||||
treeModel->setHorizontalHeaderLabels(headers);
|
||||
|
||||
tree->setColumnWidth(0, 250);
|
||||
tree->setColumnWidth(1, 250);
|
||||
tree->setColumnHidden(2, true);
|
||||
|
||||
const std::vector<QString>* 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 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++) {
|
||||
QList<QStandardItem*> items;
|
||||
|
||||
QString key = itp->first;
|
||||
auto propertyItem = new QStandardItem(key);
|
||||
propertyItem->setToolTip(itp->second.getDescription());
|
||||
items.append(propertyItem);
|
||||
|
||||
auto valueItem = new QStandardItem(_material.getAppearanceValueString(key));
|
||||
valueItem->setToolTip(itp->second.getDescription());
|
||||
QVariant variant;
|
||||
variant.setValue(&_material);
|
||||
valueItem->setData(variant);
|
||||
items.append(valueItem);
|
||||
|
||||
auto typeItem = new QStandardItem(itp->second.getPropertyType());
|
||||
items.append(typeItem);
|
||||
|
||||
auto unitsItem = new QStandardItem(itp->second.getUnits());
|
||||
items.append(unitsItem);
|
||||
|
||||
modelRoot->appendRow(items);
|
||||
tree->setExpanded(modelRoot->index(), true);
|
||||
}
|
||||
}
|
||||
catch (Materials::ModelNotFound const&) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialsEditor::updateMaterialProperties()
|
||||
{
|
||||
QTreeView* tree = ui->treePhysicalProperties;
|
||||
QStandardItemModel* treeModel = static_cast<QStandardItemModel*>(tree->model());
|
||||
treeModel->clear();
|
||||
|
||||
QStringList headers;
|
||||
headers.append(QString::fromStdString("Property"));
|
||||
headers.append(QString::fromStdString("Value"));
|
||||
headers.append(QString::fromStdString("Type"));
|
||||
headers.append(QString::fromStdString("Units"));
|
||||
treeModel->setHorizontalHeaderLabels(headers);
|
||||
|
||||
tree->setColumnWidth(0, 250);
|
||||
tree->setColumnWidth(1, 250);
|
||||
tree->setColumnHidden(2, true);
|
||||
tree->setColumnHidden(3, true);
|
||||
|
||||
const std::vector<QString>* 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 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++) {
|
||||
QList<QStandardItem*> items;
|
||||
|
||||
QString key = itp->first;
|
||||
Materials::ModelProperty modelProperty =
|
||||
static_cast<Materials::ModelProperty>(itp->second);
|
||||
auto propertyItem = new QStandardItem(key);
|
||||
propertyItem->setToolTip(modelProperty.getDescription());
|
||||
items.append(propertyItem);
|
||||
|
||||
auto valueItem = new QStandardItem(_material.getPhysicalValueString(key));
|
||||
valueItem->setToolTip(modelProperty.getDescription());
|
||||
QVariant variant;
|
||||
variant.setValue(&_material);
|
||||
valueItem->setData(variant);
|
||||
items.append(valueItem);
|
||||
|
||||
auto typeItem = new QStandardItem(modelProperty.getPropertyType());
|
||||
items.append(typeItem);
|
||||
|
||||
auto unitsItem = new QStandardItem(modelProperty.getUnits());
|
||||
items.append(unitsItem);
|
||||
|
||||
// addExpanded(tree, modelRoot, propertyItem);
|
||||
modelRoot->appendRow(items);
|
||||
tree->setExpanded(modelRoot->index(), true);
|
||||
}
|
||||
}
|
||||
catch (Materials::ModelNotFound const&) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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());
|
||||
|
||||
updateMaterialProperties();
|
||||
updateMaterialAppearance();
|
||||
|
||||
updatePreview();
|
||||
}
|
||||
|
||||
void MaterialsEditor::onSelectMaterial(const QItemSelection& selected,
|
||||
const QItemSelection& deselected)
|
||||
{
|
||||
Q_UNUSED(deselected);
|
||||
|
||||
// Get the UUID before changing the underlying data model
|
||||
QString uuid;
|
||||
QStandardItemModel* model = static_cast<QStandardItemModel*>(ui->treeMaterials->model());
|
||||
QModelIndexList indexes = selected.indexes();
|
||||
for (auto it = indexes.begin(); it != indexes.end(); it++) {
|
||||
QStandardItem* item = model->itemFromIndex(*it);
|
||||
|
||||
Base::Console().Log("%s\n", item->text().toStdString().c_str());
|
||||
if (item) {
|
||||
uuid = item->data(Qt::UserRole).toString();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
// Prompt the user to save or discard changes
|
||||
Base::Console().Log("*** Material edited!!!\n");
|
||||
int res = confirmSave(this);
|
||||
if (res == QMessageBox::Cancel) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Get the selected material
|
||||
try {
|
||||
_material = 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;
|
||||
}
|
||||
|
||||
updateMaterial();
|
||||
_material.resetEditState();
|
||||
}
|
||||
|
||||
int MaterialsEditor::confirmSave(QWidget* parent)
|
||||
{
|
||||
QMessageBox box(parent ? parent : this);
|
||||
box.setIcon(QMessageBox::Question);
|
||||
box.setWindowTitle(QObject::tr("Unsaved Material"));
|
||||
box.setText(QObject::tr("Do you want to save your changes to the material before closing?"));
|
||||
|
||||
box.setInformativeText(QObject::tr("If you don't save, your changes will be lost."));
|
||||
box.setStandardButtons(QMessageBox::Discard | QMessageBox::Cancel | QMessageBox::Save);
|
||||
box.setDefaultButton(QMessageBox::Save);
|
||||
box.setEscapeButton(QMessageBox::Cancel);
|
||||
|
||||
// add shortcuts
|
||||
QAbstractButton* saveBtn = box.button(QMessageBox::Save);
|
||||
if (saveBtn->shortcut().isEmpty()) {
|
||||
QString text = saveBtn->text();
|
||||
text.prepend(QLatin1Char('&'));
|
||||
saveBtn->setShortcut(QKeySequence::mnemonic(text));
|
||||
}
|
||||
|
||||
QAbstractButton* discardBtn = box.button(QMessageBox::Discard);
|
||||
if (discardBtn->shortcut().isEmpty()) {
|
||||
QString text = discardBtn->text();
|
||||
text.prepend(QLatin1Char('&'));
|
||||
discardBtn->setShortcut(QKeySequence::mnemonic(text));
|
||||
}
|
||||
|
||||
int res = QMessageBox::Cancel;
|
||||
box.adjustSize();// Silence warnings from Qt on Windows
|
||||
switch (box.exec()) {
|
||||
case QMessageBox::Save:
|
||||
saveMaterial();
|
||||
res = QMessageBox::Save;
|
||||
break;
|
||||
case QMessageBox::Discard:
|
||||
res = QMessageBox::Discard;
|
||||
break;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
#include "moc_MaterialsEditor.cpp"
|
||||
131
src/Mod/Material/Gui/MaterialsEditor.h
Normal file
131
src/Mod/Material/Gui/MaterialsEditor.h
Normal file
@@ -0,0 +1,131 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2023 David Carter <dcarter@david.carter.ca> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef MATGUI_MATERIALSEDITOR_H
|
||||
#define MATGUI_MATERIALSEDITOR_H
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
#include <QDialog>
|
||||
#include <QDir>
|
||||
#include <QStandardItem>
|
||||
#include <QStyledItemDelegate>
|
||||
#include <QSvgWidget>
|
||||
#include <QTreeView>
|
||||
|
||||
#include <Mod/Material/App/MaterialManager.h>
|
||||
#include <Mod/Material/App/Materials.h>
|
||||
#include <Mod/Material/App/ModelManager.h>
|
||||
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
namespace MatGui
|
||||
{
|
||||
|
||||
class Ui_MaterialsEditor;
|
||||
|
||||
class MaterialsEditor: public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit MaterialsEditor(QWidget* parent = nullptr);
|
||||
~MaterialsEditor() override = default;
|
||||
|
||||
void propertyChange(const QString& property, const QString value);
|
||||
void onFavourite(bool checked);
|
||||
void onURL(bool checked);
|
||||
void onPhysicalAdd(bool checked);
|
||||
void onAppearanceAdd(bool checked);
|
||||
void onOk(bool checked);
|
||||
void onCancel(bool checked);
|
||||
void onSave(bool checked);
|
||||
void accept() override;
|
||||
void reject() override;
|
||||
|
||||
Materials::MaterialManager& getMaterialManager()
|
||||
{
|
||||
return _materialManager;
|
||||
}
|
||||
Materials::ModelManager& getModelManager()
|
||||
{
|
||||
return _modelManager;
|
||||
}
|
||||
|
||||
void updateMaterialAppearance();
|
||||
void updateMaterialProperties();
|
||||
void updateMaterial();
|
||||
void onSelectMaterial(const QItemSelection& selected, const QItemSelection& deselected);
|
||||
|
||||
protected:
|
||||
int confirmSave(QWidget* parent);
|
||||
void saveMaterial();
|
||||
|
||||
private:
|
||||
std::unique_ptr<Ui_MaterialsEditor> ui;
|
||||
Materials::MaterialManager _materialManager;
|
||||
Materials::ModelManager _modelManager;
|
||||
Materials::Material _material;
|
||||
QSvgWidget* _rendered;
|
||||
QSvgWidget* _vectored;
|
||||
bool _edited;
|
||||
std::list<QString> _favorites;
|
||||
std::list<QString> _recents;
|
||||
int _recentMax;
|
||||
|
||||
void getFavorites();
|
||||
void saveFavorites();
|
||||
void addFavorite(const QString& uuid);
|
||||
void removeFavorite(const QString& uuid);
|
||||
bool isFavorite(const QString& uuid) const;
|
||||
|
||||
void getRecents();
|
||||
void saveRecents();
|
||||
void addRecent(const QString& uuid);
|
||||
bool isRecent(const QString& uuid) const;
|
||||
|
||||
void updatePreview() const;
|
||||
QString getColorHash(const QString& colorString, int colorRange = 255) const;
|
||||
|
||||
void addExpanded(QTreeView* tree, QStandardItem* parent, QStandardItem* child);
|
||||
void addExpanded(QTreeView* tree, QStandardItemModel* parent, QStandardItem* child);
|
||||
void addRecents(QStandardItem* parent);
|
||||
void addFavorites(QStandardItem* parent);
|
||||
void createPreviews();
|
||||
void createAppearanceTree();
|
||||
void createPhysicalTree();
|
||||
void createMaterialTree();
|
||||
void fillMaterialTree();
|
||||
void refreshMaterialTree();
|
||||
void addMaterials(QStandardItem& parent,
|
||||
const std::map<QString, Materials::MaterialTreeNode*>* modelTree,
|
||||
const QIcon& folderIcon,
|
||||
const QIcon& icon);
|
||||
bool isMaterial(const fs::path& p) const
|
||||
{
|
||||
return Materials::MaterialManager::isMaterial(p);
|
||||
}
|
||||
};
|
||||
|
||||
}// namespace MatGui
|
||||
|
||||
#endif// MATGUI_MATERIALSEDITOR_H
|
||||
288
src/Mod/Material/Gui/MaterialsEditor.ui
Normal file
288
src/Mod/Material/Gui/MaterialsEditor.ui
Normal file
@@ -0,0 +1,288 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>MatGui::MaterialsEditor</class>
|
||||
<widget class="QDialog" name="MatGui::MaterialsEditor">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>835</width>
|
||||
<height>542</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Materials</string>
|
||||
</property>
|
||||
<property name="sizeGripEnabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QSplitter" name="splitter">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<widget class="QTreeView" name="treeMaterials">
|
||||
<property name="selectionBehavior">
|
||||
<enum>QAbstractItemView::SelectItems</enum>
|
||||
</property>
|
||||
<property name="headerHidden">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QTabWidget" name="tabWidget">
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="tabGeneral">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<attribute name="title">
|
||||
<string>General</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetMinAndMaxSize</enum>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>7</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>7</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>7</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>7</number>
|
||||
</property>
|
||||
<item row="0" column="2">
|
||||
<widget class="QLineEdit" name="editName"/>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<widget class="QLabel" name="labelDescription">
|
||||
<property name="text">
|
||||
<string>Description</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QLineEdit" name="editAuthorLicense"/>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="labelName">
|
||||
<property name="text">
|
||||
<string>Name</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="labelSourceReference">
|
||||
<property name="text">
|
||||
<string>Source Reference</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="labelParent">
|
||||
<property name="text">
|
||||
<string>Parent</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="2">
|
||||
<widget class="QTextEdit" name="editDescription"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="labelAuthorLicense">
|
||||
<property name="text">
|
||||
<string>Author and License</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<widget class="QLineEdit" name="editParent"/>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Tags</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="labelSourceURL">
|
||||
<property name="text">
|
||||
<string>Source URL</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="2">
|
||||
<widget class="QLineEdit" name="editTags"/>
|
||||
</item>
|
||||
<item row="4" column="2">
|
||||
<widget class="QLineEdit" name="editSourceReference"/>
|
||||
</item>
|
||||
<item row="3" column="2">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QLineEdit" name="editSourceURL"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="buttonURL">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>22</width>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="buttonFavorite">
|
||||
<property name="text">
|
||||
<string>*</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tabProperties">
|
||||
<attribute name="title">
|
||||
<string>Properties</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_43">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_23">
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="buttonPhysicalAdd">
|
||||
<property name="text">
|
||||
<string>+</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="buttonPhysicalRemove">
|
||||
<property name="text">
|
||||
<string>-</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTreeView" name="treePhysicalProperties"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tabAppearance">
|
||||
<attribute name="title">
|
||||
<string>Appearance</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_42">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="layoutAppearance"/>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="buttonAppearanceAdd">
|
||||
<property name="text">
|
||||
<string>+</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="buttonAppearanceRemove">
|
||||
<property name="text">
|
||||
<string>-</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTreeView" name="treeAppearance"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="standardButtons">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok|QDialogButtonBox::Save</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
545
src/Mod/Material/Gui/ModelSelect.cpp
Normal file
545
src/Mod/Material/Gui/ModelSelect.cpp
Normal file
@@ -0,0 +1,545 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2023 David Carter <dcarter@david.carter.ca> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "PreCompiled.h"
|
||||
#ifndef _PreComp_
|
||||
#include <QDesktopServices>
|
||||
#include <QItemSelectionModel>
|
||||
#include <QPushButton>
|
||||
#include <QString>
|
||||
#endif
|
||||
|
||||
#include <App/Application.h>
|
||||
#include <Base/Interpreter.h>
|
||||
#include <Gui/Application.h>
|
||||
#include <Gui/Command.h>
|
||||
#include <Gui/WaitCursor.h>
|
||||
|
||||
#include <Mod/Material/App/ModelManager.h>
|
||||
|
||||
#include "ModelSelect.h"
|
||||
#include "ui_ModelSelect.h"
|
||||
|
||||
|
||||
using namespace MatGui;
|
||||
|
||||
/* TRANSLATOR MatGui::ModelSelect */
|
||||
|
||||
ModelSelect::ModelSelect(QWidget* parent, Materials::ModelManager::ModelFilter filter)
|
||||
: QDialog(parent)
|
||||
, _filter(filter)
|
||||
, ui(new Ui_ModelSelect)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
getFavorites();
|
||||
getRecents();
|
||||
|
||||
createModelTree();
|
||||
createModelProperties();
|
||||
|
||||
ui->buttonURL->setIcon(QIcon(QString::fromStdString(":/icons/internet-web-browser.svg")));
|
||||
ui->buttonDOI->setIcon(QIcon(QString::fromStdString(":/icons/internet-web-browser.svg")));
|
||||
|
||||
connect(ui->standardButtons, &QDialogButtonBox::accepted, this, &ModelSelect::accept);
|
||||
connect(ui->standardButtons, &QDialogButtonBox::rejected, this, &ModelSelect::reject);
|
||||
|
||||
QItemSelectionModel* selectionModel = ui->treeModels->selectionModel();
|
||||
connect(selectionModel,
|
||||
&QItemSelectionModel::selectionChanged,
|
||||
this,
|
||||
&ModelSelect::onSelectModel);
|
||||
|
||||
connect(ui->buttonURL, &QPushButton::clicked, this, &ModelSelect::onURL);
|
||||
connect(ui->buttonDOI, &QPushButton::clicked, this, &ModelSelect::onDOI);
|
||||
connect(ui->buttonFavorite, &QPushButton::clicked, this, &ModelSelect::onFavourite);
|
||||
|
||||
ui->standardButtons->button(QDialogButtonBox::Ok)->setEnabled(false);
|
||||
ui->buttonFavorite->setEnabled(false);
|
||||
}
|
||||
|
||||
void ModelSelect::getFavorites()
|
||||
{
|
||||
_favorites.clear();
|
||||
|
||||
auto param = App::GetApplication().GetParameterGroupByPath(
|
||||
"User parameter:BaseApp/Preferences/Mod/Material/Models/Favorites");
|
||||
int count = param->GetInt("Favorites", 0);
|
||||
for (int i = 0; i < count; i++) {
|
||||
QString key = QString::fromLatin1("FAV%1").arg(i);
|
||||
QString uuid = QString::fromStdString(param->GetASCII(key.toStdString().c_str(), ""));
|
||||
_favorites.push_back(uuid);
|
||||
}
|
||||
}
|
||||
|
||||
void ModelSelect::saveFavorites()
|
||||
{
|
||||
auto param = App::GetApplication().GetParameterGroupByPath(
|
||||
"User parameter:BaseApp/Preferences/Mod/Material/Models/Favorites");
|
||||
|
||||
// Clear out the existing favorites
|
||||
int count = param->GetInt("Favorites", 0);
|
||||
for (int i = 0; i < count; i++) {
|
||||
QString key = QString::fromLatin1("FAV%1").arg(i);
|
||||
param->RemoveASCII(key.toStdString().c_str());
|
||||
}
|
||||
|
||||
// Add the current values
|
||||
param->SetInt("Favorites", _favorites.size());
|
||||
int j = 0;
|
||||
for (auto favorite : _favorites) {
|
||||
QString key = QString::fromLatin1("FAV%1").arg(j);
|
||||
param->SetASCII(key.toStdString().c_str(), favorite.toStdString());
|
||||
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
||||
void ModelSelect::addFavorite(const QString& uuid)
|
||||
{
|
||||
if (!isFavorite(uuid)) {
|
||||
_favorites.push_back(uuid);
|
||||
saveFavorites();
|
||||
refreshModelTree();
|
||||
}
|
||||
}
|
||||
|
||||
void ModelSelect::removeFavorite(const QString& uuid)
|
||||
{
|
||||
if (isFavorite(uuid)) {
|
||||
_favorites.remove(uuid);
|
||||
saveFavorites();
|
||||
refreshModelTree();
|
||||
}
|
||||
}
|
||||
|
||||
bool ModelSelect::isFavorite(const QString& uuid) const
|
||||
{
|
||||
for (auto it : _favorites) {
|
||||
if (it == uuid) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void ModelSelect::getRecents()
|
||||
{
|
||||
_recents.clear();
|
||||
|
||||
auto param = App::GetApplication().GetParameterGroupByPath(
|
||||
"User parameter:BaseApp/Preferences/Mod/Material/Models/Recent");
|
||||
_recentMax = param->GetInt("RecentMax", 5);
|
||||
int count = param->GetInt("Recent", 0);
|
||||
for (int i = 0; i < count; i++) {
|
||||
QString key = QString::fromLatin1("MRU%1").arg(i);
|
||||
QString uuid = QString::fromStdString(param->GetASCII(key.toStdString().c_str(), ""));
|
||||
_recents.push_back(uuid);
|
||||
}
|
||||
}
|
||||
|
||||
void ModelSelect::saveRecents()
|
||||
{
|
||||
auto param = App::GetApplication().GetParameterGroupByPath(
|
||||
"User parameter:BaseApp/Preferences/Mod/Material/Models/Recent");
|
||||
|
||||
// Clear out the existing favorites
|
||||
int count = param->GetInt("Recent", 0);
|
||||
for (int i = 0; i < count; i++) {
|
||||
QString key = QString::fromLatin1("MRU%1").arg(i);
|
||||
param->RemoveASCII(key.toStdString().c_str());
|
||||
}
|
||||
|
||||
// Add the current values
|
||||
int size = _recents.size();
|
||||
if (size > _recentMax) {
|
||||
size = _recentMax;
|
||||
}
|
||||
param->SetInt("Recent", size);
|
||||
int j = 0;
|
||||
for (auto recent : _recents) {
|
||||
QString key = QString::fromLatin1("MRU%1").arg(j);
|
||||
param->SetASCII(key.toStdString().c_str(), recent.toStdString());
|
||||
|
||||
j++;
|
||||
if (j >= size) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ModelSelect::addRecent(const QString& uuid)
|
||||
{
|
||||
// Ensure no duplicates
|
||||
if (isRecent(uuid)) {
|
||||
_recents.remove(uuid);
|
||||
}
|
||||
|
||||
_recents.push_front(uuid);
|
||||
while (_recents.size() > static_cast<std::size_t>(_recentMax)) {
|
||||
_recents.pop_back();
|
||||
}
|
||||
|
||||
saveRecents();
|
||||
}
|
||||
|
||||
bool ModelSelect::isRecent(const QString& uuid) const
|
||||
{
|
||||
for (auto it : _recents) {
|
||||
if (it == uuid) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Destroys the object and frees any allocated resources
|
||||
*/
|
||||
ModelSelect::~ModelSelect()
|
||||
{
|
||||
// no need to delete child widgets, Qt does it all for us
|
||||
}
|
||||
|
||||
void ModelSelect::addExpanded(QTreeView* tree, QStandardItem* parent, QStandardItem* child)
|
||||
{
|
||||
parent->appendRow(child);
|
||||
tree->setExpanded(child->index(), true);
|
||||
}
|
||||
|
||||
void ModelSelect::addExpanded(QTreeView* tree, QStandardItemModel* parent, QStandardItem* child)
|
||||
{
|
||||
parent->appendRow(child);
|
||||
tree->setExpanded(child->index(), true);
|
||||
}
|
||||
|
||||
void ModelSelect::addModels(QStandardItem& parent,
|
||||
const std::map<QString, Materials::ModelTreeNode*>* modelTree,
|
||||
const QIcon& icon)
|
||||
{
|
||||
auto tree = ui->treeModels;
|
||||
for (auto& mod : *modelTree) {
|
||||
Materials::ModelTreeNode* nodePtr = mod.second;
|
||||
if (nodePtr->getType() == Materials::ModelTreeNode::DataNode) {
|
||||
const Materials::Model* model = nodePtr->getData();
|
||||
QString uuid = model->getUUID();
|
||||
|
||||
auto card = new QStandardItem(icon, model->getName());
|
||||
card->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled
|
||||
| Qt::ItemIsDropEnabled);
|
||||
card->setData(QVariant(uuid), Qt::UserRole);
|
||||
|
||||
addExpanded(tree, &parent, card);
|
||||
}
|
||||
else {
|
||||
auto node = new QStandardItem(mod.first);
|
||||
addExpanded(tree, &parent, node);
|
||||
node->setFlags(Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled);
|
||||
const std::map<QString, Materials::ModelTreeNode*>* treeMap = nodePtr->getFolder();
|
||||
addModels(*node, treeMap, icon);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ModelSelect::addRecents(QStandardItem* parent)
|
||||
{
|
||||
auto tree = ui->treeModels;
|
||||
for (auto& uuid : _recents) {
|
||||
try {
|
||||
const Materials::Model& model = getModelManager().getModel(uuid);
|
||||
|
||||
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);
|
||||
|
||||
addExpanded(tree, parent, card);
|
||||
}
|
||||
}
|
||||
catch (const Materials::ModelNotFound&) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ModelSelect::addFavorites(QStandardItem* parent)
|
||||
{
|
||||
auto tree = ui->treeModels;
|
||||
for (auto& uuid : _favorites) {
|
||||
try {
|
||||
const Materials::Model& model = getModelManager().getModel(uuid);
|
||||
|
||||
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);
|
||||
|
||||
addExpanded(tree, parent, card);
|
||||
}
|
||||
}
|
||||
catch (const Materials::ModelNotFound&) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ModelSelect::createModelTree()
|
||||
{
|
||||
// Materials::ModelManager modelManager;
|
||||
|
||||
auto tree = ui->treeModels;
|
||||
auto model = new QStandardItemModel();
|
||||
tree->setModel(model);
|
||||
tree->setHeaderHidden(true);
|
||||
|
||||
fillTree();
|
||||
}
|
||||
|
||||
void ModelSelect::refreshModelTree()
|
||||
{
|
||||
auto tree = ui->treeModels;
|
||||
auto model = static_cast<QStandardItemModel*>(tree->model());
|
||||
model->clear();
|
||||
|
||||
fillTree();
|
||||
}
|
||||
|
||||
void ModelSelect::fillTree()
|
||||
{
|
||||
// Materials::ModelManager modelManager;
|
||||
|
||||
auto tree = ui->treeModels;
|
||||
auto model = static_cast<QStandardItemModel*>(tree->model());
|
||||
|
||||
auto lib = new QStandardItem(QString::fromStdString("Favorites"));
|
||||
lib->setFlags(Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled);
|
||||
addExpanded(tree, model, lib);
|
||||
addFavorites(lib);
|
||||
|
||||
lib = new QStandardItem(QString::fromStdString("Recent"));
|
||||
lib->setFlags(Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled);
|
||||
addExpanded(tree, model, lib);
|
||||
addRecents(lib);
|
||||
|
||||
std::list<Materials::ModelLibrary*>* libraries = getModelManager().getModelLibraries();
|
||||
for (Materials::ModelLibrary* library : *libraries) {
|
||||
lib = new QStandardItem(library->getName());
|
||||
lib->setFlags(Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled);
|
||||
addExpanded(tree, model, lib);
|
||||
|
||||
// auto path = library->getDirectoryPath();
|
||||
std::map<QString, Materials::ModelTreeNode*>* modelTree =
|
||||
getModelManager().getModelTree(*library, _filter);
|
||||
// delete modelTree;
|
||||
addModels(*lib, modelTree, QIcon(library->getIconPath()));
|
||||
}
|
||||
}
|
||||
|
||||
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"));
|
||||
|
||||
model->setHorizontalHeaderLabels(headers);
|
||||
}
|
||||
|
||||
void ModelSelect::setColumnWidths(QTableView* table)
|
||||
{
|
||||
table->setColumnWidth(0, 75);
|
||||
table->setColumnWidth(1, 200);
|
||||
table->setColumnWidth(2, 200);
|
||||
table->setColumnWidth(3, 200);
|
||||
table->setColumnWidth(4, 200);
|
||||
}
|
||||
|
||||
void ModelSelect::createModelProperties()
|
||||
{
|
||||
auto table = ui->tableProperties;
|
||||
auto model = new QStandardItemModel();
|
||||
table->setModel(model);
|
||||
table->setEditTriggers(QAbstractItemView::NoEditTriggers);
|
||||
|
||||
setHeaders(model);
|
||||
setColumnWidths(table);
|
||||
|
||||
// table->setHeaderHidden(false);
|
||||
// table->setUniformRowHeights(true);
|
||||
// table->setItemDelegate(new MaterialDelegate(this));
|
||||
}
|
||||
|
||||
void ModelSelect::updateModelProperties(const Materials::Model& model)
|
||||
{
|
||||
QTableView* table = ui->tableProperties;
|
||||
QStandardItemModel* tableModel = static_cast<QStandardItemModel*>(table->model());
|
||||
tableModel->clear();
|
||||
|
||||
setHeaders(tableModel);
|
||||
setColumnWidths(table);
|
||||
|
||||
for (auto itp = model.begin(); itp != model.end(); itp++) {
|
||||
QList<QStandardItem*> items;
|
||||
|
||||
QString key = itp->first;
|
||||
const Materials::ModelProperty modelProperty =
|
||||
static_cast<const Materials::ModelProperty>(itp->second);
|
||||
|
||||
auto inherited =
|
||||
new QStandardItem(QString::fromStdString(modelProperty.isInherited() ? "*" : ""));
|
||||
// inherited->setToolTip(QString::fromStdString(modelProperty.getDescription()));
|
||||
items.append(inherited);
|
||||
|
||||
auto propertyItem = new QStandardItem(key);
|
||||
items.append(propertyItem);
|
||||
|
||||
auto unitsItem = new QStandardItem(modelProperty.getUnits());
|
||||
items.append(unitsItem);
|
||||
|
||||
auto descriptionItem = new QStandardItem(modelProperty.getDescription());
|
||||
items.append(descriptionItem);
|
||||
|
||||
auto urlItem = new QStandardItem(modelProperty.getURL());
|
||||
items.append(urlItem);
|
||||
|
||||
// addExpanded(tree, modelRoot, propertyItem);
|
||||
tableModel->appendRow(items);
|
||||
}
|
||||
}
|
||||
|
||||
void ModelSelect::updateMaterialModel(const QString& uuid)
|
||||
{
|
||||
Materials::Model 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());
|
||||
|
||||
if (model.getType() == Materials::Model::ModelType_Physical) {
|
||||
ui->tabWidget->setTabText(1, QString::fromStdString("Properties"));
|
||||
}
|
||||
else {
|
||||
ui->tabWidget->setTabText(1, QString::fromStdString("Appearance"));
|
||||
}
|
||||
updateModelProperties(model);
|
||||
}
|
||||
|
||||
void ModelSelect::clearMaterialModel(void)
|
||||
{
|
||||
// Update the general information
|
||||
ui->editName->setText(QString::fromStdString(""));
|
||||
ui->editURL->setText(QString::fromStdString(""));
|
||||
ui->editDOI->setText(QString::fromStdString(""));
|
||||
ui->editDescription->setText(QString::fromStdString(""));
|
||||
|
||||
ui->tabWidget->setTabText(1, QString::fromStdString("Properties"));
|
||||
|
||||
QTableView* table = ui->tableProperties;
|
||||
QStandardItemModel* tableModel = static_cast<QStandardItemModel*>(table->model());
|
||||
tableModel->clear();
|
||||
|
||||
setHeaders(tableModel);
|
||||
setColumnWidths(table);
|
||||
}
|
||||
|
||||
void ModelSelect::onSelectModel(const QItemSelection& selected, const QItemSelection& deselected)
|
||||
{
|
||||
Q_UNUSED(deselected);
|
||||
|
||||
QStandardItemModel* model = static_cast<QStandardItemModel*>(ui->treeModels->model());
|
||||
QModelIndexList indexes = selected.indexes();
|
||||
for (auto it = indexes.begin(); it != indexes.end(); it++) {
|
||||
QStandardItem* item = model->itemFromIndex(*it);
|
||||
Base::Console().Log("%s\n", item->text().toStdString().c_str());
|
||||
if (item) {
|
||||
try {
|
||||
_selected = item->data(Qt::UserRole).toString();
|
||||
Base::Console().Log("\t%s\n", _selected.toStdString().c_str());
|
||||
updateMaterialModel(_selected);
|
||||
ui->standardButtons->button(QDialogButtonBox::Ok)->setEnabled(true);
|
||||
ui->buttonFavorite->setEnabled(true);
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
_selected = QString::fromStdString("");
|
||||
Base::Console().Log("Error %s\n", e.what());
|
||||
clearMaterialModel();
|
||||
ui->standardButtons->button(QDialogButtonBox::Ok)->setEnabled(false);
|
||||
ui->buttonFavorite->setEnabled(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ModelSelect::onURL(bool checked)
|
||||
{
|
||||
Q_UNUSED(checked)
|
||||
|
||||
Base::Console().Log("URL\n");
|
||||
QString url = ui->editURL->text();
|
||||
if (url.length() > 0) {
|
||||
QDesktopServices::openUrl(QUrl(url, QUrl::TolerantMode));
|
||||
}
|
||||
}
|
||||
|
||||
void ModelSelect::onDOI(bool checked)
|
||||
{
|
||||
Q_UNUSED(checked)
|
||||
|
||||
Base::Console().Log("DOI\n");
|
||||
QString url = QString::fromStdString("https://doi.org/") + ui->editDOI->text();
|
||||
if (url.length() > 0) {
|
||||
QDesktopServices::openUrl(QUrl(url, QUrl::TolerantMode));
|
||||
}
|
||||
}
|
||||
|
||||
void ModelSelect::onFavourite(bool checked)
|
||||
{
|
||||
Q_UNUSED(checked)
|
||||
|
||||
Base::Console().Log("Favorite\n");
|
||||
if (isFavorite(_selected)) {
|
||||
removeFavorite(_selected);
|
||||
}
|
||||
else {
|
||||
addFavorite(_selected);
|
||||
}
|
||||
}
|
||||
|
||||
void ModelSelect::accept()
|
||||
{
|
||||
addRecent(_selected);
|
||||
QDialog::accept();
|
||||
}
|
||||
|
||||
void ModelSelect::reject()
|
||||
{
|
||||
QDialog::reject();
|
||||
}
|
||||
|
||||
#include "moc_ModelSelect.cpp"
|
||||
109
src/Mod/Material/Gui/ModelSelect.h
Normal file
109
src/Mod/Material/Gui/ModelSelect.h
Normal file
@@ -0,0 +1,109 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2023 David Carter <dcarter@david.carter.ca> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef MATGUI_MODELSELECT_H
|
||||
#define MATGUI_MODELSELECT_H
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
#include <QDialog>
|
||||
#include <QDir>
|
||||
#include <QStandardItem>
|
||||
#include <QTableView>
|
||||
#include <QTreeView>
|
||||
|
||||
#include <Mod/Material/App/Materials.h>
|
||||
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
namespace MatGui
|
||||
{
|
||||
|
||||
class Ui_ModelSelect;
|
||||
|
||||
class ModelSelect: public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ModelSelect(
|
||||
QWidget* parent = nullptr,
|
||||
Materials::ModelManager::ModelFilter filter = Materials::ModelManager::ModelFilter_None);
|
||||
~ModelSelect() override;
|
||||
|
||||
void onURL(bool checked);
|
||||
void onDOI(bool checked);
|
||||
void onFavourite(bool checked);
|
||||
void onSelectModel(const QItemSelection& selected, const QItemSelection& deselected);
|
||||
const QString& selectedModel() const
|
||||
{
|
||||
return _selected;
|
||||
}
|
||||
void accept() override;
|
||||
void reject() override;
|
||||
|
||||
private:
|
||||
void getFavorites();
|
||||
void saveFavorites();
|
||||
void addFavorite(const QString& uuid);
|
||||
void removeFavorite(const QString& uuid);
|
||||
bool isFavorite(const QString& uuid) const;
|
||||
|
||||
void getRecents();
|
||||
void saveRecents();
|
||||
void addRecent(const QString& uuid);
|
||||
bool isRecent(const QString& uuid) const;
|
||||
|
||||
void addExpanded(QTreeView* tree, QStandardItem* parent, QStandardItem* child);
|
||||
void addExpanded(QTreeView* tree, QStandardItemModel* parent, QStandardItem* child);
|
||||
void addRecents(QStandardItem* parent);
|
||||
void addFavorites(QStandardItem* parent);
|
||||
void addModels(QStandardItem& parent,
|
||||
const std::map<QString, Materials::ModelTreeNode*>* modelTree,
|
||||
const QIcon& icon);
|
||||
void updateMaterialModel(const QString& uuid);
|
||||
void clearMaterialModel(void);
|
||||
void createModelTree();
|
||||
void refreshModelTree();
|
||||
void fillTree();
|
||||
|
||||
void setHeaders(QStandardItemModel* model);
|
||||
void setColumnWidths(QTableView* table);
|
||||
void updateModelProperties(const Materials::Model& model);
|
||||
void createModelProperties();
|
||||
Materials::ModelManager& getModelManager()
|
||||
{
|
||||
return _modelManager;
|
||||
}
|
||||
|
||||
Materials::ModelManager::ModelFilter _filter;
|
||||
std::unique_ptr<Ui_ModelSelect> ui;
|
||||
Materials::ModelManager _modelManager;
|
||||
QString _selected;
|
||||
std::list<QString> _favorites;
|
||||
std::list<QString> _recents;
|
||||
int _recentMax;
|
||||
};
|
||||
|
||||
}// namespace MatGui
|
||||
|
||||
#endif// MATGUI_MODELSELECT_H
|
||||
197
src/Mod/Material/Gui/ModelSelect.ui
Normal file
197
src/Mod/Material/Gui/ModelSelect.ui
Normal file
@@ -0,0 +1,197 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>MatGui::ModelSelect</class>
|
||||
<widget class="QDialog" name="MatGui::ModelSelect">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>705</width>
|
||||
<height>489</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Material Models</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QSplitter" name="splitter">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<widget class="QTreeView" name="treeModels"/>
|
||||
<widget class="QTabWidget" name="tabWidget">
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="tabGeneral">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>365</width>
|
||||
<height>409</height>
|
||||
</size>
|
||||
</property>
|
||||
<attribute name="title">
|
||||
<string>General</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="labelURL">
|
||||
<property name="text">
|
||||
<string>URL</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Description</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="labelDOI">
|
||||
<property name="text">
|
||||
<string>DOI</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QTextEdit" name="editDescription">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="editName">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="labelName">
|
||||
<property name="text">
|
||||
<string>Name</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<widget class="QLineEdit" name="editDOI">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="buttonDOI">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>22</width>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QLineEdit" name="editURL">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="buttonURL">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>22</width>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="buttonFavorite">
|
||||
<property name="toolTip">
|
||||
<string>Add to favorites</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>*</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tabProperties">
|
||||
<attribute name="title">
|
||||
<string>Properties</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<widget class="QTableView" name="tableProperties"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="standardButtons">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
24
src/Mod/Material/Gui/PreCompiled.cpp
Normal file
24
src/Mod/Material/Gui/PreCompiled.cpp
Normal file
@@ -0,0 +1,24 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2023 David Carter <dcarter@david.carter.ca> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#include "PreCompiled.h"
|
||||
77
src/Mod/Material/Gui/PreCompiled.h
Normal file
77
src/Mod/Material/Gui/PreCompiled.h
Normal file
@@ -0,0 +1,77 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2023 David Carter <dcarter@david.carter.ca> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef MATGUI_PRECOMPILED_H
|
||||
#define MATGUI_PRECOMPILED_H
|
||||
|
||||
#include <FCConfig.h>
|
||||
|
||||
#include <Mod/Material/MaterialGlobal.h>
|
||||
|
||||
// point at which warnings of overly long specifiers disabled (needed for VC6)
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable : 4251)
|
||||
#pragma warning(disable : 4503)
|
||||
#pragma warning(disable : 4786)// specifier longer then 255 chars
|
||||
#pragma warning(disable : 4273)
|
||||
#endif
|
||||
|
||||
#ifdef FC_OS_WIN32
|
||||
#ifndef NOMINMAX
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#ifdef _PreComp_
|
||||
|
||||
// standard
|
||||
#include <cfloat>
|
||||
#include <cmath>
|
||||
|
||||
// STL
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
// OpenCasCade
|
||||
// #include <Mod/Part/App/OpenCascadeAll.h>
|
||||
|
||||
// Boost
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include <boost/regex.hpp>
|
||||
|
||||
// Qt Toolkit
|
||||
#ifndef __QtAll__
|
||||
#include <Gui/QtAll.h>
|
||||
#endif
|
||||
|
||||
// // Inventor includes OpenGL
|
||||
// #ifndef __InventorAll__
|
||||
// # include <Gui/InventorAll.h>
|
||||
// #endif
|
||||
|
||||
#endif//_PreComp_
|
||||
|
||||
#endif// MATGUI_PRECOMPILED_H
|
||||
10
src/Mod/Material/Gui/Resources/Material.qrc
Normal file
10
src/Mod/Material/Gui/Resources/Material.qrc
Normal file
@@ -0,0 +1,10 @@
|
||||
<RCC>
|
||||
<qresource>
|
||||
<file>icons/MaterialWorkbench.svg</file>
|
||||
<file>icons/Materials_Edit.svg</file>
|
||||
<file>icons/preferences-material.svg</file>
|
||||
<file>icons/preview-rendered.svg</file>
|
||||
<file>icons/preview-vector.svg</file>
|
||||
<file>icons/table.svg</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
128
src/Mod/Material/Gui/Resources/icons/MaterialWorkbench.svg
Normal file
128
src/Mod/Material/Gui/Resources/icons/MaterialWorkbench.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 16 KiB |
128
src/Mod/Material/Gui/Resources/icons/Materials_Edit.svg
Normal file
128
src/Mod/Material/Gui/Resources/icons/Materials_Edit.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 16 KiB |
128
src/Mod/Material/Gui/Resources/icons/preferences-material.svg
Normal file
128
src/Mod/Material/Gui/Resources/icons/preferences-material.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 16 KiB |
65
src/Mod/Material/Gui/Resources/icons/preview-rendered.svg
Normal file
65
src/Mod/Material/Gui/Resources/icons/preview-rendered.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 6.2 KiB |
157
src/Mod/Material/Gui/Resources/icons/preview-vector.svg
Normal file
157
src/Mod/Material/Gui/Resources/icons/preview-vector.svg
Normal file
@@ -0,0 +1,157 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="64"
|
||||
height="64"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.5 r10040"
|
||||
sodipodi:docname="preview-vector.svg">
|
||||
<defs
|
||||
id="defs4">
|
||||
<inkscape:perspective
|
||||
sodipodi:type="inkscape:persp3d"
|
||||
inkscape:vp_x="-206.25075 : 119.68854 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_z="183.50001 : 140.32143 : 1"
|
||||
inkscape:persp3d-origin="48 : 32 : 1"
|
||||
id="perspective3792" />
|
||||
<linearGradient
|
||||
id="linearGradient3755">
|
||||
<stop
|
||||
style="stop-color:#424242;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop3757" />
|
||||
<stop
|
||||
style="stop-color:#9f9f9f;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop3759" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3755"
|
||||
id="linearGradient3761"
|
||||
x1="75.724594"
|
||||
y1="85.023956"
|
||||
x2="41.895164"
|
||||
y2="13.334851"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="8.7571168"
|
||||
inkscape:cx="39.859065"
|
||||
inkscape:cy="30.925664"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="g3794"
|
||||
showgrid="true"
|
||||
showborder="true"
|
||||
inkscape:window-width="800"
|
||||
inkscape:window-height="836"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="27"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:snap-bbox="false"
|
||||
inkscape:snap-nodes="true"
|
||||
inkscape:snap-global="true">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid3002"
|
||||
empspacing="2"
|
||||
visible="true"
|
||||
enabled="true"
|
||||
snapvisiblegridlinesonly="true" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
<dc:creator>
|
||||
<cc:Agent>
|
||||
<dc:title>$committer</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:creator>
|
||||
<dc:title>preview-vector</dc:title>
|
||||
<dc:date>2013-11-19</dc:date>
|
||||
<dc:relation>http://www.freecad.org/wiki/index.php?title=Artwork</dc:relation>
|
||||
<dc:publisher>
|
||||
<cc:Agent>
|
||||
<dc:title>FreeCAD</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:publisher>
|
||||
<dc:identifier>FreeCAD/src/Mod/Material/Resources/icons/preview-vector.svg</dc:identifier>
|
||||
<dc:rights>
|
||||
<cc:Agent>
|
||||
<dc:title>FreeCAD LGPL2+</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:rights>
|
||||
<cc:license>https://www.gnu.org/copyleft/lesser.html</cc:license>
|
||||
<dc:contributor>
|
||||
<cc:Agent>
|
||||
<dc:title>[agryson] Alexander Gryson</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:contributor>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(0,-988.36218)">
|
||||
<g
|
||||
id="g3794"
|
||||
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.29399991;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate">
|
||||
<path
|
||||
style="fill:#d3d7cf;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
d="m 29.814326,991.36218 -8.814326,4 -1,7.00002 26,1 14.994091,-8.6577 z"
|
||||
id="path3816"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccccc" />
|
||||
<path
|
||||
d="M 38.484871,1007.8171 40,1046.3622 l 21,-22.4044 0,-29.25647 z"
|
||||
style="fill:#b7b7b7;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
id="path3818"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<path
|
||||
style="fill:#555753;stroke:#555753;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 59.035745,9.6627807 59.108006,34.818961 40.91531,54.264958 42.698526,19.372964 z"
|
||||
id="path3022"
|
||||
inkscape:connector-curvature="0"
|
||||
transform="translate(0,988.36218)"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<path
|
||||
d="m 21,995.36218 31,5.00002 -12,46 -30,-8 z"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:4;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
id="path3820"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<path
|
||||
d="m 21,995.36218 31,5.00002 -12,46 -30,-8 z"
|
||||
style="color:#000000;fill:none;stroke:#888a85;stroke-width:2;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
id="path3820-3"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.7 KiB |
77
src/Mod/Material/Gui/Resources/icons/table.svg
Normal file
77
src/Mod/Material/Gui/Resources/icons/table.svg
Normal file
@@ -0,0 +1,77 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="64"
|
||||
height="64"
|
||||
viewBox="0 0 16.933333 16.933333"
|
||||
version="1.1"
|
||||
id="svg5"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs2">
|
||||
<linearGradient
|
||||
id="linearGradient992">
|
||||
<stop
|
||||
style="stop-color:#ff0000;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop990" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<g
|
||||
id="layer1">
|
||||
<rect
|
||||
style="fill:none;stroke:#000000;stroke-width:0.52916667;stroke-opacity:1;stroke-dasharray:none"
|
||||
id="rect434"
|
||||
width="14.684375"
|
||||
height="14.122135"
|
||||
x="1.1244792"
|
||||
y="1.3559896" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.529167;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 1.1244792,4.9609349 15.643489,5.0270807"
|
||||
id="path1407" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.529167;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 1.9182291,7.3752603 H 5.523177 v 0"
|
||||
id="path2181" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.529167;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 6.8295573,7.3421875 h 3.6049477 v 0"
|
||||
id="path2181-4" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.529167;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 11.426692,7.4083334 h 3.604948 v 0"
|
||||
id="path2181-5" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.529167;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 1.9099611,12.567709 h 3.604948 v 0"
|
||||
id="path2181-2" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.529167;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 6.8212891,12.534636 h 3.6049479 v 0"
|
||||
id="path2181-4-0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.529167;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 11.418424,12.600782 h 3.604948 v 0"
|
||||
id="path2181-5-5" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.529167;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 1.9264977,10.021094 h 3.6049479 v 0"
|
||||
id="path2181-46" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.529167;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 6.8378259,10.021094 h 3.6049471 v 0"
|
||||
id="path2181-4-3" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.529167;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 11.43496,10.054167 h 3.604948 v 0"
|
||||
id="path2181-5-7" />
|
||||
<path
|
||||
style="fill:#0000ff;stroke:#000000;stroke-width:0.25;stroke-dasharray:none;stroke-opacity:1;fill-opacity:1"
|
||||
d="M 29.5,17.805701 C 20.7,17.760754 11.657813,17.715771 9.40625,17.705739 L 5.3125,17.6875 v -5.75 -5.75 H 32 58.6875 v 5.875 5.875 L 52.09375,17.91246 C 48.467188,17.89869 38.3,17.850648 29.5,17.805701 Z"
|
||||
id="path2364"
|
||||
transform="scale(0.26458333)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.0 KiB |
85
src/Mod/Material/Gui/Resources/translations/Material.ts
Normal file
85
src/Mod/Material/Gui/Resources/translations/Material.ts
Normal file
@@ -0,0 +1,85 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE TS>
|
||||
<TS version="2.1">
|
||||
<context>
|
||||
<name>MaterialEditor</name>
|
||||
<message>
|
||||
<location filename="../../materials-editor.ui" line="14"/>
|
||||
<source>Material Editor</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../materials-editor.ui" line="22"/>
|
||||
<source>Material card</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../materials-editor.ui" line="40"/>
|
||||
<source>Opens the Product URL of this material in an external browser</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../materials-editor.ui" line="56"/>
|
||||
<source>Existing material cards</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../materials-editor.ui" line="67"/>
|
||||
<source>Opens an existing material card</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../materials-editor.ui" line="70"/>
|
||||
<source>Open...</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../materials-editor.ui" line="77"/>
|
||||
<source>Saves this material as a card</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../materials-editor.ui" line="80"/>
|
||||
<source>Save as...</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../materials-editor.ui" line="96"/>
|
||||
<source>Material parameter</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../materials-editor.ui" line="115"/>
|
||||
<source>Add / remove parameter</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../materials-editor.ui" line="126"/>
|
||||
<source>Add property</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../materials-editor.ui" line="133"/>
|
||||
<source>Delete property</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Material</name>
|
||||
<message>
|
||||
<location filename="../../MaterialEditor.py" line="275"/>
|
||||
<source>Product URL</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../MaterialEditor.py" line="337"/>
|
||||
<source>UserDefined</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../MaterialEditor.py" line="583"/>
|
||||
<source>Name</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
</TS>
|
||||
@@ -23,3 +23,5 @@ import FreeCAD
|
||||
|
||||
# import for the FreeCAD Material card
|
||||
FreeCAD.addImportType("FreeCAD Material Card (*.FCMat)", "importFCMat")
|
||||
|
||||
FreeCAD.__unit_test__ += [ "TestMaterialsApp" ]
|
||||
|
||||
@@ -19,3 +19,7 @@
|
||||
#* *
|
||||
#***************************************************************************
|
||||
|
||||
# import FreeCADGui
|
||||
|
||||
# import Material_rc
|
||||
# FreeCADGui.addPreferencePage(":/ui/preferences-material.ui","Material")
|
||||
|
||||
@@ -1,135 +0,0 @@
|
||||
# ***************************************************************************
|
||||
# * Copyright (c) 2013-2015 Juergen Riegel <FreeCAD@juergen-riegel.net> *
|
||||
# * *
|
||||
# * This program is free software; you can redistribute it and/or modify *
|
||||
# * it under the terms of the GNU Lesser General Public License (LGPL) *
|
||||
# * as published by the Free Software Foundation; either version 2 of *
|
||||
# * the License, or (at your option) any later version. *
|
||||
# * for detail see the LICENCE text file. *
|
||||
# * *
|
||||
# * This program is distributed in the hope that it will be useful, *
|
||||
# * but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
# * GNU Library General Public License for more details. *
|
||||
# * *
|
||||
# * You should have received a copy of the GNU Library General Public *
|
||||
# * License along with this program; if not, write to the Free Software *
|
||||
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||
# * USA *
|
||||
# * *
|
||||
# ***************************************************************************
|
||||
|
||||
import sys
|
||||
import FreeCAD
|
||||
|
||||
|
||||
# The usage description if you use this tool from the command line ("__main__")
|
||||
CommandlineUsage = """Material - Tool to work with FreeCAD Material definition cards
|
||||
|
||||
Usage:
|
||||
Material [Options] card-file-name
|
||||
|
||||
Options:
|
||||
-c, --output-csv=filename write a comma separated grid with the material data
|
||||
|
||||
Exit:
|
||||
0 No Error or Warning found
|
||||
1 Argument error, wrong or too few Arguments given
|
||||
|
||||
Tool to work with FreeCAD Material definition cards
|
||||
|
||||
Examples:
|
||||
|
||||
Material "StandardMaterial/Steel.FCMat"
|
||||
|
||||
Author:
|
||||
(c) 2013 Juergen Riegel
|
||||
mail@juergen-riegel.net
|
||||
Licence: LGPL
|
||||
|
||||
Version:
|
||||
0.1
|
||||
"""
|
||||
|
||||
|
||||
# see comments in module importFCMat, there is an independent parser implementation
|
||||
# for reading and writing FCMat files
|
||||
# inside FreeCAD mostly the one from importFCMat.py is used
|
||||
|
||||
|
||||
def importFCMat(fileName):
|
||||
"Read a FCMat file into a dictionary"
|
||||
try:
|
||||
import ConfigParser as configparser
|
||||
except ImportError:
|
||||
import configparser
|
||||
|
||||
FreeCAD.Console.PrintError(
|
||||
'This mat card reader is probably deprecated and not widely used in FreeCAD. '
|
||||
'See comment in Material.py module.\n'
|
||||
)
|
||||
Config = configparser.RawConfigParser()
|
||||
Config.optionxform = str
|
||||
Config.read(fileName, encoding='utf-8') # respect unicode filenames
|
||||
dict1 = {}
|
||||
for section in Config.sections():
|
||||
options = Config.options(section)
|
||||
for option in options:
|
||||
dict1[option] = Config.get(section, option)
|
||||
|
||||
return dict1
|
||||
|
||||
|
||||
def exportFCMat(fileName, matDict):
|
||||
"Write a material dictionary to a FCMat file"
|
||||
try:
|
||||
import ConfigParser as configparser
|
||||
except ImportError:
|
||||
import configparser
|
||||
import string
|
||||
Config = configparser.RawConfigParser()
|
||||
|
||||
FreeCAD.Console.PrintError(
|
||||
'This mat card writer is probably deprecated and not widely used in FreeCAD. '
|
||||
'See comment in Material.py module.\n'
|
||||
)
|
||||
# create groups
|
||||
for x in matDict.keys():
|
||||
grp, key = string.split(x, sep='_')
|
||||
if not Config.has_section(grp):
|
||||
Config.add_section(grp)
|
||||
|
||||
# fill groups
|
||||
for x in matDict.keys():
|
||||
grp, key = string.split(x, sep='_')
|
||||
Config.set(grp, key, matDict[x])
|
||||
|
||||
Preamble = "# This is a FreeCAD material-card file\n\n"
|
||||
# Writing our configuration file to 'example.cfg'
|
||||
with open(fileName, 'wb') as configfile:
|
||||
configfile.write(Preamble)
|
||||
Config.write(configfile)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import getopt
|
||||
try:
|
||||
opts, args = getopt.getopt(sys.argv[1:], "c:", ["output-csv="])
|
||||
except getopt.GetoptError:
|
||||
# print help information and exit:
|
||||
sys.stderr.write(CommandlineUsage)
|
||||
sys.exit(1)
|
||||
|
||||
# checking on the options
|
||||
for o, a in opts:
|
||||
if o in ("-c", "--output-csv"):
|
||||
print("writing file: " + a + "\n")
|
||||
OutPath = a
|
||||
|
||||
# running through the files
|
||||
FileName = args[0]
|
||||
|
||||
kv_map = importFCMat(FileName)
|
||||
for k in kv_map.keys():
|
||||
print(repr(k) + " : " + repr(kv_map[k]))
|
||||
sys.exit(0) # no error
|
||||
@@ -25,12 +25,15 @@ __author__ = "Yorik van Havre, Bernd Hahnebach"
|
||||
__url__ = "http://www.freecad.org"
|
||||
|
||||
import os
|
||||
from pathlib import PurePath
|
||||
import sys
|
||||
from PySide import QtCore, QtGui, QtSvg
|
||||
|
||||
import FreeCAD
|
||||
import FreeCADGui
|
||||
# import Material_rc
|
||||
from materialtools.cardutils import get_material_preferred_directory, get_material_preferred_save_directory
|
||||
|
||||
|
||||
# is this still needed after the move to card utils???
|
||||
unicode = str
|
||||
@@ -52,17 +55,21 @@ class MaterialEditor:
|
||||
self.customprops = []
|
||||
self.internalprops = []
|
||||
self.groups = []
|
||||
self.directory = FreeCAD.getResourceDir() + "Mod/Material"
|
||||
self.directory = get_material_preferred_directory()
|
||||
self.save_directory = get_material_preferred_save_directory()
|
||||
if self.directory is None:
|
||||
self.directory = FreeCAD.getResourceDir() + "Mod/Material"
|
||||
self.materials = {}
|
||||
self.cards = {}
|
||||
self.icons = {}
|
||||
self.initialIndex = -1
|
||||
self.edited = False
|
||||
self.card_path = card_path
|
||||
filePath = os.path.dirname(__file__) + os.sep
|
||||
self.iconPath = (filePath + "Resources" + os.sep + "icons" + os.sep)
|
||||
|
||||
# load the UI file from the same directory as this script
|
||||
self.widget = FreeCADGui.PySideUic.loadUi(filePath + "materials-editor.ui")
|
||||
self.widget = FreeCADGui.PySideUic.loadUi(filePath + "Resources" + os.sep + "ui" + os.sep + "materials-editor.ui")
|
||||
# remove unused Help button
|
||||
self.widget.setWindowFlags(self.widget.windowFlags()
|
||||
& ~QtCore.Qt.WindowContextHelpButtonHint)
|
||||
@@ -104,7 +111,7 @@ class MaterialEditor:
|
||||
# currently closes the dialog
|
||||
|
||||
standardButtons.rejected.connect(self.reject)
|
||||
standardButtons.accepted.connect(self.accept)
|
||||
standardButtons.button(QtGui.QDialogButtonBox.Ok).clicked.connect(self.verify)
|
||||
buttonOpen.clicked.connect(self.openfile)
|
||||
buttonSave.clicked.connect(self.savefile)
|
||||
buttonURL.clicked.connect(self.openProductURL)
|
||||
@@ -117,6 +124,7 @@ class MaterialEditor:
|
||||
treeView.setModel(model)
|
||||
treeView.setUniformRowHeights(True)
|
||||
treeView.setItemDelegate(MaterialsDelegate())
|
||||
model.itemChanged.connect(self.modelChange)
|
||||
|
||||
# init model
|
||||
self.implementModel()
|
||||
@@ -181,6 +189,7 @@ class MaterialEditor:
|
||||
# top.sortChildren(0)
|
||||
|
||||
# treeView.expandAll()
|
||||
self.edited = False
|
||||
|
||||
def updateMatParamsInTree(self, data):
|
||||
|
||||
@@ -220,10 +229,20 @@ class MaterialEditor:
|
||||
it = QtGui.QStandardItem(i)
|
||||
userGroup.appendRow([item, it])
|
||||
self.customprops.append(k)
|
||||
self.edited = False
|
||||
|
||||
def chooseMaterial(self, index):
|
||||
if index < 0:
|
||||
return
|
||||
|
||||
if self.verifyMaterial():
|
||||
"""
|
||||
Save any unchanged data
|
||||
"""
|
||||
self.edited = False
|
||||
else:
|
||||
return
|
||||
|
||||
self.card_path = self.widget.ComboMaterial.itemData(index)
|
||||
FreeCAD.Console.PrintMessage(
|
||||
"choose_material in material editor:\n"
|
||||
@@ -239,6 +258,21 @@ class MaterialEditor:
|
||||
else:
|
||||
FreeCAD.Console.PrintError("Material card not found: {}\n".format(self.card_path))
|
||||
|
||||
def verifyMaterial(self):
|
||||
if self.edited:
|
||||
reply = QtGui.QMessageBox.question(self.widget, #FreeCADGui.getMainWindow(),
|
||||
translate("Material","The document has been modified."),
|
||||
translate("Material","Do you want to save your changes?"),
|
||||
QtGui.QMessageBox.Save | QtGui.QMessageBox.Discard | QtGui.QMessageBox.Cancel,
|
||||
QtGui.QMessageBox.Save)
|
||||
|
||||
if reply == QtGui.QMessageBox.Cancel:
|
||||
return False
|
||||
if reply == QtGui.QMessageBox.Save:
|
||||
self.savefile()
|
||||
|
||||
return True
|
||||
|
||||
def updateCardsInCombo(self):
|
||||
|
||||
"""updates the contents of the materials combo with existing material cards"""
|
||||
@@ -280,6 +314,32 @@ class MaterialEditor:
|
||||
if url:
|
||||
QtGui.QDesktopServices.openUrl(QtCore.QUrl(url, QtCore.QUrl.TolerantMode))
|
||||
|
||||
def modelChange(self, item):
|
||||
"""
|
||||
Called when an item in the tree is modified. This will set edited to True, but this
|
||||
will be reset in the event of mass updates, such as loading a card
|
||||
"""
|
||||
self.edited = True
|
||||
|
||||
def verify(self, button):
|
||||
"""
|
||||
Verify that the user wants to save any changed data before exiting
|
||||
"""
|
||||
|
||||
if self.edited:
|
||||
reply = QtGui.QMessageBox.question(self.widget, #FreeCADGui.getMainWindow(),
|
||||
translate("Material","The document has been modified."),
|
||||
translate("Material","Do you want to save your changes?"),
|
||||
QtGui.QMessageBox.Save | QtGui.QMessageBox.Discard | QtGui.QMessageBox.Cancel,
|
||||
QtGui.QMessageBox.Save)
|
||||
|
||||
if reply == QtGui.QMessageBox.Cancel:
|
||||
return
|
||||
if reply == QtGui.QMessageBox.Save:
|
||||
self.savefile()
|
||||
|
||||
self.accept()
|
||||
|
||||
def accept(self):
|
||||
""
|
||||
|
||||
@@ -340,6 +400,7 @@ class MaterialEditor:
|
||||
it = QtGui.QStandardItem(value)
|
||||
top.appendRow([item, it])
|
||||
self.customprops.append(key)
|
||||
self.edited = True
|
||||
|
||||
def deleteCustomProperty(self, key=None):
|
||||
|
||||
@@ -376,6 +437,8 @@ class MaterialEditor:
|
||||
it.setText("")
|
||||
buttonDeleteProperty.setProperty("text", "Delete value")
|
||||
|
||||
self.edited = True
|
||||
|
||||
buttonDeleteProperty.setEnabled(False)
|
||||
|
||||
def onClickTree(self, index):
|
||||
@@ -505,12 +568,20 @@ class MaterialEditor:
|
||||
return color.name()
|
||||
|
||||
def openfile(self):
|
||||
if self.verifyMaterial():
|
||||
"""
|
||||
Save any unchanged data
|
||||
"""
|
||||
self.edited = False
|
||||
else:
|
||||
return
|
||||
|
||||
"Opens a FCMat file"
|
||||
if self.category == "Solid":
|
||||
directory = self.directory + os.sep + "StandardMaterial"
|
||||
else:
|
||||
directory = self.directory + os.sep + "FluidMaterial"
|
||||
if self.card_path is None:
|
||||
if self.card_path is None or len(self.card_path) == 0:
|
||||
self.card_path = directory
|
||||
filetuple = QtGui.QFileDialog.getOpenFileName(
|
||||
QtGui.QApplication.activeWindow(),
|
||||
@@ -529,8 +600,11 @@ class MaterialEditor:
|
||||
# D:/FreeCAD-build/data/Mod\Material\FluidMaterial\Air.FCMat
|
||||
# To keep it simple, we take a path from the ComboMaterial and change only the
|
||||
# material card filename
|
||||
if self.initialIndex > -1:
|
||||
path = self.widget.ComboMaterial.itemData(self.initialIndex)
|
||||
#
|
||||
# Using the initialIndex variable won't work before a card os selected for the
|
||||
# first time, so use index 1. Index 0 is a blank entry
|
||||
if self.widget.ComboMaterial.count() > 1:
|
||||
path = self.widget.ComboMaterial.itemData(1)
|
||||
# at first check if we have a uniform usage
|
||||
# (if a character is not present, rsplit delivers the initial string)
|
||||
testBackslash = path.rsplit('\\', 1)[0]
|
||||
@@ -590,19 +664,27 @@ class MaterialEditor:
|
||||
filetuple = QtGui.QFileDialog.getSaveFileName(
|
||||
QtGui.QApplication.activeWindow(),
|
||||
"Save FreeCAD Material file",
|
||||
self.directory + "/" + name + ".FCMat",
|
||||
self.save_directory + "/" + name + ".FCMat",
|
||||
"*.FCMat"
|
||||
)
|
||||
# a tuple of two empty strings returns True, so use the filename directly
|
||||
filename = filetuple[0]
|
||||
if filename:
|
||||
self.directory = os.path.dirname(filename)
|
||||
# should not be resource dir but user result dir instead
|
||||
# Update the directories to the current save value
|
||||
self.save_directory = os.path.dirname(filename)
|
||||
self.directory = self.save_directory
|
||||
self.card_path = filename
|
||||
|
||||
d = self.getDict()
|
||||
# self.outputDict(d)
|
||||
if d:
|
||||
# Set the card name to match the filename
|
||||
path = PurePath(filename)
|
||||
d["CardName"] = path.stem
|
||||
|
||||
from importFCMat import write
|
||||
write(filename, d)
|
||||
self.edited = False
|
||||
self.updateCardsInCombo()
|
||||
|
||||
def show(self):
|
||||
@@ -854,8 +936,13 @@ def translate(context, text):
|
||||
def openEditor(obj=None, prop=None):
|
||||
"""openEditor([obj,prop]): opens the editor, optionally with
|
||||
an object name and material property name to edit"""
|
||||
editor = MaterialEditor(obj, prop)
|
||||
editor.exec_()
|
||||
param = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Material/Cards")
|
||||
legacy = param.GetBool("LegacyEditor", True)
|
||||
if legacy:
|
||||
editor = MaterialEditor(obj, prop)
|
||||
editor.exec_()
|
||||
else:
|
||||
FreeCADGui.runCommand('Materials_Edit',0)
|
||||
|
||||
|
||||
def editMaterial(material=None, card_path=None, category="Solid"):
|
||||
|
||||
46
src/Mod/Material/MaterialGlobal.h
Normal file
46
src/Mod/Material/MaterialGlobal.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2023 David Carter <dcarter@david.carter.ca> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include <FCGlobal.h>
|
||||
|
||||
#ifndef MATERIAL_GLOBAL_H
|
||||
#define MATERIAL_GLOBAL_H
|
||||
|
||||
// Material
|
||||
#ifndef MaterialsExport
|
||||
#ifdef Material_EXPORTS
|
||||
# define MaterialsExport FREECAD_DECL_EXPORT
|
||||
#else
|
||||
# define MaterialsExport FREECAD_DECL_IMPORT
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// MatGui
|
||||
#ifndef MatGuiExport
|
||||
#ifdef MatGui_EXPORTS
|
||||
# define MatGuiExport FREECAD_DECL_EXPORT
|
||||
#else
|
||||
# define MatGuiExport FREECAD_DECL_IMPORT
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif //MATERIAL_GLOBAL_H
|
||||
@@ -2,5 +2,6 @@
|
||||
<qresource>
|
||||
<file>icons/preview-rendered.svg</file>
|
||||
<file>icons/preview-vector.svg</file>
|
||||
<file>ui/materials-editor.ui</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
# File created by ConvertFCMat.py
|
||||
General:
|
||||
UUID: "d1f317f0-5ffa-4798-8ab3-af2ff0b5182c"
|
||||
AuthorAndLicense: "(c) 2023 David Carter"
|
||||
Name: "Aluminum"
|
||||
Description: "Defines the Aluminum appearance properties"
|
||||
AppearanceModels:
|
||||
BasicRendering:
|
||||
UUID: 'f006c7e4-35b7-43d5-bbf9-c5d572309e6e'
|
||||
AmbientColor: "(0.3000, 0.3000, 0.3000, 1.0)"
|
||||
DiffuseColor: "(0.3000, 0.3000, 0.3000, 1.0)"
|
||||
EmissiveColor: "(0.0000, 0.0000, 0.0000, 1.0)"
|
||||
Shininess: "0.0900"
|
||||
SpecularColor: "(0.3000, 0.3000, 0.3000, 1.0)"
|
||||
Transparency: "0.0"
|
||||
15
src/Mod/Material/Resources/Materials/Appearance/Brass.FCMat
Normal file
15
src/Mod/Material/Resources/Materials/Appearance/Brass.FCMat
Normal file
@@ -0,0 +1,15 @@
|
||||
# File created by ConvertFCMat.py
|
||||
General:
|
||||
UUID: "4151e19c-fd6a-4ca4-83d4-d5e17d76cb9c"
|
||||
AuthorAndLicense: "(c) 2023 David Carter"
|
||||
Name: "Brass"
|
||||
Description: "Defines the Brass appearance properties"
|
||||
AppearanceModels:
|
||||
BasicRendering:
|
||||
UUID: 'f006c7e4-35b7-43d5-bbf9-c5d572309e6e'
|
||||
AmbientColor: "(0.3294, 0.2235, 0.0275, 1.0)"
|
||||
DiffuseColor: "(0.7804, 0.5686, 0.1137, 1.0)"
|
||||
EmissiveColor: "(0.0000, 0.0000, 0.0000, 1.0)"
|
||||
Shininess: "0.2179"
|
||||
SpecularColor: "(0.9922, 0.9412, 0.8078, 1.0)"
|
||||
Transparency: "0.0"
|
||||
15
src/Mod/Material/Resources/Materials/Appearance/Bronze.FCMat
Normal file
15
src/Mod/Material/Resources/Materials/Appearance/Bronze.FCMat
Normal file
@@ -0,0 +1,15 @@
|
||||
# File created by ConvertFCMat.py
|
||||
General:
|
||||
UUID: "ae194589-02d4-4e9b-98a7-f523f660d510"
|
||||
AuthorAndLicense: "(c) 2023 David Carter"
|
||||
Name: "Bronze"
|
||||
Description: "Defines the Bronze appearance properties"
|
||||
AppearanceModels:
|
||||
BasicRendering:
|
||||
UUID: 'f006c7e4-35b7-43d5-bbf9-c5d572309e6e'
|
||||
AmbientColor: "(0.2125, 0.1275, 0.0540, 1.0)"
|
||||
DiffuseColor: "(0.7140, 0.4284, 0.1814, 1.0)"
|
||||
EmissiveColor: "(0.0000, 0.0000, 0.0000, 1.0)"
|
||||
Shininess: "0.2000"
|
||||
SpecularColor: "(0.3935, 0.2719, 0.1667, 1.0)"
|
||||
Transparency: "0.0"
|
||||
15
src/Mod/Material/Resources/Materials/Appearance/Chrome.FCMat
Normal file
15
src/Mod/Material/Resources/Materials/Appearance/Chrome.FCMat
Normal file
@@ -0,0 +1,15 @@
|
||||
# File created by ConvertFCMat.py
|
||||
General:
|
||||
UUID: "a9544b88-dde7-4d05-9bdb-c008a4e88dc1"
|
||||
AuthorAndLicense: "(c) 2023 David Carter"
|
||||
Name: "Chrome"
|
||||
Description: "Defines the Chrome appearance properties"
|
||||
AppearanceModels:
|
||||
BasicRendering:
|
||||
UUID: 'f006c7e4-35b7-43d5-bbf9-c5d572309e6e'
|
||||
AmbientColor: "(0.3500, 0.3500, 0.3500, 1.0)"
|
||||
DiffuseColor: "(0.9176, 0.9176, 0.9176, 1.0)"
|
||||
EmissiveColor: "(0.0000, 0.0000, 0.0000, 1.0)"
|
||||
Shininess: "0.1000"
|
||||
SpecularColor: "(0.9746, 0.9746, 0.9746, 1.0)"
|
||||
Transparency: "0.0"
|
||||
15
src/Mod/Material/Resources/Materials/Appearance/Copper.FCMat
Normal file
15
src/Mod/Material/Resources/Materials/Appearance/Copper.FCMat
Normal file
@@ -0,0 +1,15 @@
|
||||
# File created by ConvertFCMat.py
|
||||
General:
|
||||
UUID: "524cad9b-b841-4037-9851-badeca7dcee2"
|
||||
AuthorAndLicense: "(c) 2023 David Carter"
|
||||
Name: "Copper"
|
||||
Description: "Defines the Copper appearance properties"
|
||||
AppearanceModels:
|
||||
BasicRendering:
|
||||
UUID: 'f006c7e4-35b7-43d5-bbf9-c5d572309e6e'
|
||||
AmbientColor: "(0.3300, 0.2600, 0.2300, 1.0)"
|
||||
DiffuseColor: "(0.5000, 0.1100, 0.0000, 1.0)"
|
||||
EmissiveColor: "(0.0000, 0.0000, 0.0000, 1.0)"
|
||||
Shininess: "0.9300"
|
||||
SpecularColor: "(0.9500, 0.7300, 0.0000, 1.0)"
|
||||
Transparency: "0.0"
|
||||
@@ -0,0 +1,15 @@
|
||||
# File created by ConvertFCMat.py
|
||||
General:
|
||||
UUID: "5dbb7be6-8b63-479b-ab4c-87be02ead973"
|
||||
AuthorAndLicense: "(c) 2023 David Carter"
|
||||
Name: "Default Appearance"
|
||||
Description: "Defines the default appearance properties"
|
||||
AppearanceModels:
|
||||
BasicRendering:
|
||||
UUID: 'f006c7e4-35b7-43d5-bbf9-c5d572309e6e'
|
||||
AmbientColor: "(0.2000, 0.2000, 0.2000, 1.0)"
|
||||
DiffuseColor: "(0.8000, 0.8000, 0.8000, 1.0)"
|
||||
EmissiveColor: "(0.0000, 0.0000, 0.0000, 1.0)"
|
||||
Shininess: "0.2000"
|
||||
SpecularColor: "(0.0000, 0.0000, 0.0000, 1.0)"
|
||||
Transparency: "0.0"
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user